commit 6a161fa938d2d56703db46c08b6f821b7d3e0207 Author: okuji Date: Fri Dec 27 08:53:07 2002 +0000 Initial revision diff --git a/.cvsignore b/.cvsignore new file mode 100644 index 000000000..91983cf81 --- /dev/null +++ b/.cvsignore @@ -0,0 +1,8 @@ +Makefile +config.cache +config.h +config.log +config.status +stamp-h +stamp-h1 +autom4te.cache diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 000000000..aacc8399e --- /dev/null +++ b/AUTHORS @@ -0,0 +1 @@ +Yoshinori K. Okuji designed and implemented everything. diff --git a/COPYING b/COPYING new file mode 100644 index 000000000..eeb586b39 --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + 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 + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 000000000..be5328821 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,4 @@ +2002-12-27 Yoshinori K. Okuji + + * Changelog: New file. + diff --git a/INSTALL b/INSTALL new file mode 100644 index 000000000..228029e42 --- /dev/null +++ b/INSTALL @@ -0,0 +1,157 @@ +-*- Text -*- + +This is the PUPA. Welcome. + +This file contains instructions for compiling and installing the PUPA. + +The Requirements +================ + +PUPA depends on some software packages installed into your system. If +you don't have any of them, please obtain and install them before +configuring the PUPA. + +* GCC 2.95 or later +* GNU Make +* GNU binutils 2.9.1.0.23 or later +* Other standard GNU/Unix tools + +If you'd like to develop PUPA, these below are also required. + +* Ruby 1.6 or later +* Autoconf 2.53 or later + +Configuring the PUPA +==================== + +The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a +file `config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + +If you need to do unusual things to compile the package, please try to +figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + +The file `configure.ac' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + + +Building the PUPA +================= + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and + type `./configure' to configure the package for your system. If + you're using `csh' on an old version of System V, you might need + to type `sh ./configure' instead to prevent `csh' from trying to + execute `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + + +Compiling For Multiple Architectures +==================================== + +You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. `cd' to the directory where you want the object files +and executables to go and run the `configure' script. `configure' +automatically checks for the source code in the directory that +`configure' is in and in `..'. + + +Installation Names +================== + +By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix by giving `configure' the option `--prefix=PATH'. + +You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If +you give `configure' the option `--exec-prefix=PATH', the package will +use PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + +In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for +particular kinds of files. Run `configure --help' for a list of the +directories you can set and what kinds of files go in them. + +If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' +the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Please note, however, that the PUPA knows where it is located in the +filesystem. If you have installed it in an unusual location, the +system might not work properly, or at all. The chief utility of these +options for the PUPA is to allow you to "install" in some alternate +location, and then copy these to the actual root filesystem later. + + +Sharing Defaults +================ + +If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 000000000..9dfca542c --- /dev/null +++ b/Makefile.in @@ -0,0 +1,259 @@ +# -*- makefile -*- +# +# Copyright (C) 1994,1995,1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc. +# Copyright (C) 2002 Yoshinori K. Okuji +# +# This Makefile.in is free software; the author +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +### The configure script will replace these variables. + +SHELL = /bin/sh + +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +pkgdatadir = $(datadir)/@PACKAGE_TARNAME@/$(host_cpu)-$(host_vendor) +pkglibdir = $(libdir)/@PACKAGE_TARNAME@ + +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ + +host_cpu = @host_cpu@ +host_vendor = @host_vendor@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ + +mkinstalldirs = $(srcdir)/mkinstalldirs + +CC = @CC@ +CFLAGS = @CFLAGS@ +CPPFLAGS = -I. -Iinclude -I$(srcdir)/include -Wall -W +BUILD_CC = @CC@ +BUILD_CFLAGS = -g -O2 +BUILD_CPPFLAGS = -I. -Iinclude -I$(srcdir)/include -Wall -W \ + -DPUPA_DATADIR=\"$(pkgdatadir)\" +OBJCOPY = @OBJCOPY@ +STRIP = @STRIP@ +NM = @NM@ +RUBY = @RUBY@ + +### General variables. + +RMKFILES = $(addprefix conf/,i386-pc.rmk) +MKFILES = $(patsubst %.rmk,%.mk,$(RMKFILES)) + +COMMON_DISTFILES = AUTHORS COPYING ChangeLog INSTALL NEWS README \ + THANKS TODO Makefile.in aclocal.m4 autogen.sh config.guess \ + config.h.in config.sub configure configure.ac genkernsyms.sh \ + genmk.rb genmodsrc.sh gensymlist.sh install-sh mkinstalldirs \ + stamp-h.in + +BOOT_DISTFILES = $(addprefix boot/i386/pc/,boot.S diskboot.S) + +CONF_DISTFILES = $(RMKFILES) $(MKFILES) + +DISK_DISTFILES = $(addprefix disk/i386/pc/,biosdisk.c partition.c) + +FS_DISTFILES = $(addprefix fs/,fat.c) + +INCLUDE_DISTFILES = $(addprefix include/pupa/,boot.h device.h disk.h \ + dl.h elf.h err.h file.h fs.h kernel.h loader.h misc.h mm.h \ + net.h rescue.h symbol.h term.h types.h) \ + $(addprefix include/pupa/util/,misc.h resolve.h) \ + include/pupa/i386/types.h \ + $(addprefix include/pupa/i386/pc/,biosdisk.h boot.h \ + console.h init.h kernel.h loader.h memory.h partition.h) + +KERN_DISTFILES = $(addprefix kern/,device.c disk.c dl.c err.c file.c \ + fs.c loader.c main.c misc.c mm.c rescue.c term.c) \ + kern/i386/dl.c \ + $(addprefix kern/i386/pc/,init.c startup.S) + +LOADER_DISTFILES = $(addprefix loader/i386/pc/,chainloader.c) + +TERM_DISTFILES = $(addprefix term/i386/pc/,console.c) + +UTIL_DISTFILES = $(addprefix util/,genmoddep.c misc.c resolve.c) \ + util/i386/pc/pupa-mkimage.c + +DISTFILES = $(COMMON_DISTFILES) $(BOOT_DISTFILES) $(CONF_DISTFILES) \ + $(DISK_DISTFILES) $(FS_DISTFILES) $(INCLUDE_DISTFILES) \ + $(KERN_DISTFILES) $(LOADER_DISTFILES) $(TERM_DISTFILES) \ + $(UTIL_DISTFILES) + +DATA = $(pkgdata_IMAGES) $(pkgdata_MODULES) +PROGRAMS = $(bin_UTILITIES) $(sbin_UTILITIES) +SCRIPTS = + +CLEANFILES = +MOSTLYCLEANFILES = +DISTCLEANFILES = config.status config.cache config.log config.h \ + Makefile stamp-h include/pupa/cpu include/pupa/machine +MAINTAINER_CLEANFILES = $(srcdir)/configure $(addprefix $(srcdir)/,$(MKFILES)) + +# The default target. +all: all-local + +### Include an arch-specific Makefile. +$(addprefix $(srcdir)/,$(MKFILES)): %.mk: %.rmk genmk.rb + if test "x$(RUBY)" = x; then \ + touch $@; \ + else \ + $(RUBY) $(srcdir)/genmk.rb < $< > $@; \ + fi + +include $(srcdir)/conf/$(host_cpu)-$(host_vendor).mk + +### General targets. + +all-local: $(PROGRAMS) $(DATA) $(SCRIPTS) + +install: install-local + +install-local: all + $(mkinstalldirs) $(DESTDIR)$(pkgdatadir) + @list='$(pkgdata_IMAGES) $(pkgdata_MODULES)'; for file in $$list; do \ + if test -f "$$file"; then dir=; else dir="$(srcdir)"; fi; \ + dest="`echo $$file | sed 's,.*/,,'`"; \ + $(INSTALL_DATA) $$dir$$file $(DESTDIR)$(pkgdatadir)/$$dest; \ + done + $(mkinstalldirs) $(DESTDIR)$(bindir) + @list='$(bin_UTILITIES)'; for file in $$list; do \ + if test -f "$$file"; then dir=; else dir="$(srcdir)"; fi; \ + dest="`echo $$file | sed 's,.*/,,'`"; \ + $(INSTALL_PROGRAM) $$dir$$file $(DESTDIR)$(bindir)/$$dest; \ + done + +install-strip: + $(MAKE) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" install + +uninstall: + @list='$(pkgdata_IMAGES) $(pkgdata_MODULES)'; for file in $$list; do \ + dest="`echo $$file | sed 's,.*/,,'`"; \ + rm -f $(DESTDIR)$(pkgdatadir)/$$dest; \ + done + @list = '$(bin_UTILITIES)'; for file in $$list; do \ + dest="`echo $$file | sed 's,.*/,,'`"; \ + rm -f $(DESTDIR)$(bindir)/$$dest; \ + done + +clean: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +mostlyclean: clean + -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) + +distclean: mostlyclean + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + -rm -rf $(srcdir)/autom4te.cache + +maintainer-clean: distclean + -test -z "$(MAINTAINER_CLEANFILES)" || rm -f $(MAINTAINER_CLEANFILES) + +info: + +dvi: + +distdir=$(PACKAGE_TARNAME)-$(PACKAGE_VERSION) + +distdir: $(DISTFILES) + -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir) + $(mkinstalldirs) $(distdir) + for i in $(DISTFILES); do \ + dir=`echo "$$i" | sed 's:/[^/]*$$::'`; \ + if test -d $(srcdir)/$$dir; then \ + $(mkinstalldirs) $(distdir)/$$dir; \ + fi; \ + cp -p $(srcdir)/$$i $(distdir)/$$i || exit 1; \ + done + chmod -R a+r $(distdir) + +GZIP_ENV = --best + +dist: distdir + tar chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir) + +distcheck: dist + -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir) + GZIP=$(GZIP_ENV) gzip -cd $(distdir).tar.gz | tar xf - + chmod -R a-w $(distdir) + chmod a+w $(distdir) + mkdir $(distdir)/=build + mkdir $(distdir)/=inst + chmod a-w $(distdir) + dc_instdir=`CDPATH=: && cd $(distdir)/=inst && pwd` \ + && cd $(distdir)/=build \ + && ../configure --srcdir=.. --prefix=$$dc_instdir \ + && $(MAKE) all dvi check install uninstall \ + && (test `find $$dc_instdir -type f -print | wc -l` -le 1 \ + || (echo "Error: files left after uninstall" 1>&2; \ + exit 1)) \ + && $(MAKE) dist distclean \ + && rm -f $(distdir).tar.gz \ + && (test `find . -type f -print | wc -l` -eq 0 \ + || (echo "Error: files left after distclean" 1>&2; \ + exit 1)) + -chmod -R a+w $(distdir) > /dev/null 2>&1; rm -rf $(distdir) + @echo "$(distdir).tar.gz is ready for distribution" | \ + sed 'h;s/./=/g;p;x;p;x' + +check: + +.SUFFIX: +.SUFFIX: .c .o .S .d + +# Regenerate configure and Makefile automatically. +$(srcdir)/configure: configure.ac aclocal.m4 + cd $(srcdir) && autoconf + +$(srcdir)/config.h.in: stamp-h.in +$(srcdir)/stamp-h.in: configure.ac aclocal.m4 + cd $(srcdir) && autoheader + echo timestamp > $(srcdir)/stamp-h.in + +config.h: stamp-h +stamp-h: config.h.in config.status + ./config.status + +Makefile: Makefile.in config.status + ./config.status + +config.status: configure + ./config.status --recheck + +.PHONY: all install install-strip uninstall clean mostlyclean distclean +.PHONY: maintainer-clean info dvi dist check + +# Prevent an overflow. +.NOEXPORT: diff --git a/NEWS b/NEWS new file mode 100644 index 000000000..65ce9a0dc --- /dev/null +++ b/NEWS @@ -0,0 +1,12 @@ +New in 0.6 - 2002-12-27, Yoshinori K. Okuji: + +* The chainloader and the FAT filesystem are modularized. + +* The structure of the source tree is a bit changed. + +* Support for building loadable modules is added. + +* Some generic parts of pupa-mkimage are segregated. + +* Some documentation files are added, according to the GNU Coding + Standards. diff --git a/README b/README new file mode 100644 index 000000000..867f47583 --- /dev/null +++ b/README @@ -0,0 +1,26 @@ +This is PUPA, the Preliminary Universal Programming Architecture for +GRUB. PUPA is a research project for the next generation of GNU GRUB. +The most important goal is to make GNU GRUB cleaner, safer, more robust, +more powerful, and more portable. + +See the file NEWS for a description of recent changes to PUPA. + +See the file INSTALL for instructions on how to build and install the +PUPA data and program files. + +Please visit the official web page of PUPA, for more information. +The URL is . + + + +Because PUPA is still in developmental stage, PUPA is not for general +use (yet). For now, you can install PUPA into a floppy by these +instructions: + +$ configure && make +$ ./pupa-mkimage -v -d . -o core.img chain fat +$ dd if=boot.img of=/dev/fd0 bs=512 count=1 +$ dd if=core.img of=/dev/fd0 bs=512 seek=1 + +It would be easier to use Bochs than a real +machine. diff --git a/THANKS b/THANKS new file mode 100644 index 000000000..6c0277094 --- /dev/null +++ b/THANKS @@ -0,0 +1,16 @@ +PUPA would not be what it is today without the invaluable help of +everybody who was kind enough to spend time testing it and reporting +bugs. + +The following people made especially gracious contributions of their +time and energy in helping to track down bugs, add new features, and +generally assist in the PUPA maintainership process: + +NIIBE Yutaka +Tsuneyoshi Yasuo + +Also, we thank the projects GNU GRUB and GNU Automake. Some code were +stolen from them. + +This project is supported by Information-technology Promotion Agency, +Japan. diff --git a/TODO b/TODO new file mode 100644 index 000000000..cd57f7198 --- /dev/null +++ b/TODO @@ -0,0 +1,37 @@ +-*- Mode: Outline -*- + +Before working on anything in this file, it's very important that you +make contact with the core PUPA developers. Things herein might be +slightly out of date or otherwise not easy to understand at first +glance. So write to first. + +Priorities: + Reported bugs generally have top priority. + Non-reported and non-encountered bugs (things we know don't work, + but don't really impede things) have lower priority. + Things in this file are ranked with one to three !; the more, the + higher priority. + + +* Add more filesystems (such as ext2fs, ffs, and reiserfs). ! + +* Add support for internationalization. !!! + +* Add more loaders (such as Multiboot, Linux and FreeBSD). !! + +* Implement an installer. !!! + +* Add more terminals (such as serial). ! + +* Implement a normal mode. !!! + +* Write a manual. + +* Shrink the kernel code. + +* Add support for compressed files. + +* Add support for network devices. + +* Compress the core image and decompress it at loading time, to make it + smaller. ? diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 000000000..9f8e1e715 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,292 @@ +dnl pupa_ASM_USCORE checks if C symbols get an underscore after +dnl compiling to assembler. +dnl Written by Pavel Roskin. Based on grub_ASM_EXT_C written by +dnl Erich Boleyn and modified by Yoshinori K. Okuji. +AC_DEFUN(pupa_ASM_USCORE, +[AC_REQUIRE([AC_PROG_CC]) +AC_MSG_CHECKING([if C symbols get an underscore after compilation]) +AC_CACHE_VAL(pupa_cv_asm_uscore, +[cat > conftest.c <<\EOF +int +func (int *list) +{ + *list = 0; + return *list; +} +EOF + +if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -S conftest.c]) && test -s conftest.s; then + true +else + AC_MSG_ERROR([${CC-cc} failed to produce assembly code]) +fi + +if grep _func conftest.s >/dev/null 2>&1; then + pupa_cv_asm_uscore=yes +else + pupa_cv_asm_uscore=no +fi + +rm -f conftest*]) + +if test "x$pupa_cv_asm_uscore" = xyes; then + AC_DEFINE_UNQUOTED([HAVE_ASM_USCORE], $pupa_cv_asm_uscore, + [Define if C symbols get an underscore after compilation]) +fi + +AC_MSG_RESULT([$pupa_cv_asm_uscore]) +]) + + +dnl Some versions of `objcopy -O binary' vary their output depending +dnl on the link address. +AC_DEFUN(pupa_PROG_OBJCOPY_ABSOLUTE, +[AC_MSG_CHECKING([whether ${OBJCOPY} works for absolute addresses]) +AC_CACHE_VAL(pupa_cv_prog_objcopy_absolute, +[cat > conftest.c <<\EOF +void +cmain (void) +{ + *((int *) 0x1000) = 2; +} +EOF + +if AC_TRY_EVAL(ac_compile) && test -s conftest.o; then : +else + AC_MSG_ERROR([${CC-cc} cannot compile C source code]) +fi +pupa_cv_prog_objcopy_absolute=yes +for link_addr in 2000 8000 7C00; do + if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -nostdlib -Wl,-N -Wl,-Ttext -Wl,$link_addr conftest.o -o conftest.exec]); then : + else + AC_MSG_ERROR([${CC-cc} cannot link at address $link_addr]) + fi + if AC_TRY_COMMAND([${OBJCOPY-objcopy} -O binary conftest.exec conftest]); then : + else + AC_MSG_ERROR([${OBJCOPY-objcopy} cannot create binary files]) + fi + if test ! -f conftest.old || AC_TRY_COMMAND([cmp -s conftest.old conftest]); then + mv -f conftest conftest.old + else + pupa_cv_prog_objcopy_absolute=no + break + fi +done +rm -f conftest*]) +AC_MSG_RESULT([$pupa_cv_prog_objcopy_absolute]) + +if test "x$pupa_cv_prog_objcopy_absolute" = xno; then + AC_MSG_ERROR([PUPA requires a working absolute objcopy; upgrade your binutils]) +fi +]) + + +dnl Mass confusion! +dnl Older versions of GAS interpret `.code16' to mean ``generate 32-bit +dnl instructions, but implicitly insert addr32 and data32 bytes so +dnl that the code works in real mode''. +dnl +dnl Newer versions of GAS interpret `.code16' to mean ``generate 16-bit +dnl instructions,'' which seems right. This requires the programmer +dnl to explicitly insert addr32 and data32 instructions when they want +dnl them. +dnl +dnl We only support the newer versions, because the old versions cause +dnl major pain, by requiring manual assembly to get 16-bit instructions into +dnl asm files. +AC_DEFUN(pupa_I386_ASM_ADDR32, +[AC_REQUIRE([AC_PROG_CC]) +AC_REQUIRE([pupa_I386_ASM_PREFIX_REQUIREMENT]) +AC_MSG_CHECKING([for .code16 addr32 assembler support]) +AC_CACHE_VAL(pupa_cv_i386_asm_addr32, +[cat > conftest.s.in <<\EOF + .code16 +l1: @ADDR32@ movb %al, l1 +EOF + +if test "x$pupa_cv_i386_asm_prefix_requirement" = xyes; then + sed -e s/@ADDR32@/addr32/ < conftest.s.in > conftest.s +else + sed -e s/@ADDR32@/addr32\;/ < conftest.s.in > conftest.s +fi + +if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -c conftest.s]) && test -s conftest.o; then + pupa_cv_i386_asm_addr32=yes +else + pupa_cv_i386_asm_addr32=no +fi + +rm -f conftest*]) + +AC_MSG_RESULT([$pupa_cv_i386_asm_addr32])]) + + +dnl Later versions of GAS requires that addr32 and data32 prefixes +dnl appear in the same lines as the instructions they modify, while +dnl earlier versions requires that they appear in separate lines. +AC_DEFUN(pupa_I386_ASM_PREFIX_REQUIREMENT, +[AC_REQUIRE([AC_PROG_CC]) +AC_MSG_CHECKING(dnl +[whether addr32 must be in the same line as the instruction]) +AC_CACHE_VAL(pupa_cv_i386_asm_prefix_requirement, +[cat > conftest.s <<\EOF + .code16 +l1: addr32 movb %al, l1 +EOF + +if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -c conftest.s]) && test -s conftest.o; then + pupa_cv_i386_asm_prefix_requirement=yes +else + pupa_cv_i386_asm_prefix_requirement=no +fi + +rm -f conftest*]) + +if test "x$pupa_cv_i386_asm_prefix_requirement" = xyes; then + pupa_tmp_addr32="addr32" + pupa_tmp_data32="data32" +else + pupa_tmp_addr32="addr32;" + pupa_tmp_data32="data32;" +fi + +AC_DEFINE_UNQUOTED([ADDR32], $pupa_tmp_addr32, + [Define it to \"addr32\" or \"addr32;\" to make GAS happy]) +AC_DEFINE_UNQUOTED([DATA32], $pupa_tmp_data32, + [Define it to \"data32\" or \"data32;\" to make GAS happy]) + +AC_MSG_RESULT([$pupa_cv_i386_asm_prefix_requirement])]) + + +dnl Older versions of GAS require that absolute indirect calls/jumps are +dnl not prefixed with `*', while later versions warn if not prefixed. +AC_DEFUN(pupa_I386_ASM_ABSOLUTE_WITHOUT_ASTERISK, +[AC_REQUIRE([AC_PROG_CC]) +AC_MSG_CHECKING(dnl +[whether an absolute indirect call/jump must not be prefixed with an asterisk]) +AC_CACHE_VAL(pupa_cv_i386_asm_absolute_without_asterisk, +[cat > conftest.s <<\EOF + lcall *(offset) +offset: + .long 0 + .word 0 +EOF + +if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -c conftest.s]) && test -s conftest.o; then + pupa_cv_i386_asm_absolute_without_asterisk=no +else + pupa_cv_i386_asm_absolute_without_asterisk=yes +fi + +rm -f conftest*]) + +if test "x$pupa_cv_i386_asm_absolute_without_asterisk" = xyes; then + AC_DEFINE([ABSOLUTE_WITHOUT_ASTERISK], 1, + [Define it if GAS requires that absolute indirect calls/jumps are not prefixed with an asterisk]) +fi + +AC_MSG_RESULT([$pupa_cv_i386_asm_absolute_without_asterisk])]) + + +dnl Check what symbol is defined as a start symbol. +dnl Written by Yoshinori K. Okuji. +AC_DEFUN(pupa_CHECK_START_SYMBOL, +[AC_REQUIRE([AC_PROG_CC]) +AC_MSG_CHECKING([if start is defined by the compiler]) +AC_CACHE_VAL(pupa_cv_check_start_symbol, +[AC_TRY_LINK([], [asm ("incl start")], + pupa_cv_check_start_symbol=yes, + pupa_cv_check_start_symbol=no)]) + +AC_MSG_RESULT([$pupa_cv_check_start_symbol]) + +AC_MSG_CHECKING([if _start is defined by the compiler]) +AC_CACHE_VAL(pupa_cv_check_uscore_start_symbol, +[AC_TRY_LINK([], [asm ("incl _start")], + pupa_cv_check_uscore_start_symbol=yes, + pupa_cv_check_uscore_start_symbol=no)]) + +AC_MSG_RESULT([$pupa_cv_check_uscore_start_symbol]) + +AH_TEMPLATE([START_SYMBOL], [Define it to either start or _start]) + +if test "x$pupa_cv_check_start_symbol" = xyes; then + AC_DEFINE([START_SYMBOL], [start]) +elif test "x$pupa_cv_check_uscore_start_symbol" = xyes; then + AC_DEFINE([START_SYMBOL], [_start]) +else + AC_MSG_ERROR([neither start nor _start is defined]) +fi +]) + +dnl Check what symbol is defined as a bss start symbol. +dnl Written by Michael Hohmoth and Yoshinori K. Okuji. +AC_DEFUN(pupa_CHECK_BSS_START_SYMBOL, +[AC_REQUIRE([AC_PROG_CC]) +AC_MSG_CHECKING([if __bss_start is defined by the compiler]) +AC_CACHE_VAL(pupa_cv_check_uscore_uscore_bss_start_symbol, +[AC_TRY_LINK([], [asm ("incl __bss_start")], + pupa_cv_check_uscore_uscore_bss_start_symbol=yes, + pupa_cv_check_uscore_uscore_bss_start_symbol=no)]) + +AC_MSG_RESULT([$pupa_cv_check_uscore_uscore_bss_start_symbol]) + +AC_MSG_CHECKING([if edata is defined by the compiler]) +AC_CACHE_VAL(pupa_cv_check_edata_symbol, +[AC_TRY_LINK([], [asm ("incl edata")], + pupa_cv_check_edata_symbol=yes, + pupa_cv_check_edata_symbol=no)]) + +AC_MSG_RESULT([$pupa_cv_check_edata_symbol]) + +AC_MSG_CHECKING([if _edata is defined by the compiler]) +AC_CACHE_VAL(pupa_cv_check_uscore_edata_symbol, +[AC_TRY_LINK([], [asm ("incl _edata")], + pupa_cv_check_uscore_edata_symbol=yes, + pupa_cv_check_uscore_edata_symbol=no)]) + +AC_MSG_RESULT([$pupa_cv_check_uscore_edata_symbol]) + +AH_TEMPLATE([BSS_START_SYMBOL], [Define it to one of __bss_start, edata and _edata]) + +if test "x$pupa_cv_check_uscore_uscore_bss_start_symbol" = xyes; then + AC_DEFINE([BSS_START_SYMBOL], [__bss_start]) +elif test "x$pupa_cv_check_edata_symbol" = xyes; then + AC_DEFINE([BSS_START_SYMBOL], [edata]) +elif test "x$pupa_cv_check_uscore_edata_symbol" = xyes; then + AC_DEFINE([BSS_START_SYMBOL], [_edata]) +else + AC_MSG_ERROR([none of __bss_start, edata or _edata is defined]) +fi +]) + +dnl Check what symbol is defined as an end symbol. +dnl Written by Yoshinori K. Okuji. +AC_DEFUN(pupa_CHECK_END_SYMBOL, +[AC_REQUIRE([AC_PROG_CC]) +AC_MSG_CHECKING([if end is defined by the compiler]) +AC_CACHE_VAL(pupa_cv_check_end_symbol, +[AC_TRY_LINK([], [asm ("incl end")], + pupa_cv_check_end_symbol=yes, + pupa_cv_check_end_symbol=no)]) + +AC_MSG_RESULT([$pupa_cv_check_end_symbol]) + +AC_MSG_CHECKING([if _end is defined by the compiler]) +AC_CACHE_VAL(pupa_cv_check_uscore_end_symbol, +[AC_TRY_LINK([], [asm ("incl _end")], + pupa_cv_check_uscore_end_symbol=yes, + pupa_cv_check_uscore_end_symbol=no)]) + +AC_MSG_RESULT([$pupa_cv_check_uscore_end_symbol]) + +AH_TEMPLATE([END_SYMBOL], [Define it to either end or _end]) + +if test "x$pupa_cv_check_end_symbol" = xyes; then + AC_DEFINE([END_SYMBOL], [end]) +elif test "x$pupa_cv_check_uscore_end_symbol" = xyes; then + AC_DEFINE([END_SYMBOL], [_end]) +else + AC_MSG_ERROR([neither end nor _end is defined]) +fi +]) diff --git a/autogen.sh b/autogen.sh new file mode 100644 index 000000000..387bea731 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,11 @@ +#! /bin/sh + +set -e + +autoconf +autoheader +for rmk in conf/*.rmk; do + ruby genmk.rb < $rmk > `echo $rmk | sed 's/\.rmk$/.mk/'` +done + +exit 0 diff --git a/boot/i386/pc/boot.S b/boot/i386/pc/boot.S new file mode 100644 index 000000000..dd3c66796 --- /dev/null +++ b/boot/i386/pc/boot.S @@ -0,0 +1,487 @@ +/* -*-Asm-*- */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 1999,2000,2001 Free Software Foundation, Inc. + * Copyright (C) 2002 Yoshinori K. Okuji + * + * 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. + */ + +#include +#include + +/* + * defines for the code go here + */ + + /* Absolute addresses + This makes the assembler generate the address without support + from the linker. (ELF can't relocate 16-bit addresses!) */ +#define ABS(x) (x-_start+0x7c00) + + /* Print message string */ +#define MSG(x) movw $ABS(x), %si; call message + + /* XXX: binutils-2.9.1.0.x doesn't produce a short opcode for this. */ +#define MOV_MEM_TO_AL(x) .byte 0xa0; .word x + + .file "boot.S" + + .text + + /* Tell GAS to generate 16-bit instructions so that this code works + in real mode. */ + .code16 + +.globl _start; _start: + /* + * _start is loaded at 0x7c00 and is jumped to with CS:IP 0:0x7c00 + */ + + /* + * Beginning of the sector is compatible with the FAT/HPFS BIOS + * parameter block. + */ + + jmp after_BPB + nop /* do I care about this ??? */ + + /* + * This space is for the BIOS parameter block!!!! Don't change + * the first jump, nor start the code anywhere but right after + * this area. + */ + + . = _start + 4 + + /* scratch space */ +mode: + .byte 0 +disk_address_packet: +sectors: + .long 0 +heads: + .long 0 +cylinders: + .word 0 +sector_start: + .byte 0 +head_start: + .byte 0 +cylinder_start: + .word 0 + /* more space... */ + + . = _start + PUPA_BOOT_MACHINE_BPBEND + + /* + * End of BIOS parameter block. + */ + +boot_version: + .byte PUPA_BOOT_VERSION_MAJOR, PUPA_BOOT_VERSION_MINOR +boot_drive: + .byte 0xff /* the disk to load kernel from */ + /* 0xff means use the boot drive */ +force_lba: + .byte 0 +kernel_address: + .word PUPA_BOOT_MACHINE_KERNEL_ADDR +kernel_sector: + .long 1 +kernel_segment: + .word PUPA_BOOT_MACHINE_KERNEL_SEG + +after_BPB: + +/* general setup */ + cli /* we're not safe here! */ + + /* + * ljmp to the next instruction because some bogus BIOSes + * jump to 07C0:0000 instead of 0000:7C00. + */ + ljmp $0, $ABS(real_start) + +real_start: + + /* set up %ds and %ss as offset from 0 */ + xorw %ax, %ax + movw %ax, %ds + movw %ax, %ss + + /* set up the REAL stack */ + movw $PUPA_BOOT_MACHINE_STACK_SEG, %sp + + sti /* we're safe again */ + + /* + * Check if we have a forced disk reference here + */ + MOV_MEM_TO_AL(ABS(boot_drive)) /* movb ABS(boot_drive), %al */ + cmpb $0xff, %al + je 1f + movb %al, %dl +1: + /* save drive reference first thing! */ + pushw %dx + + /* print a notification message on the screen */ + MSG(notification_string) + + /* do not probe LBA if the drive is a floppy */ + testb $PUPA_BOOT_MACHINE_BIOS_HD_FLAG, %dl + jz chs_mode + + /* check if LBA is supported */ + movb $0x41, %ah + movw $0x55aa, %bx + int $0x13 + + /* + * %dl may have been clobbered by INT 13, AH=41H. + * This happens, for example, with AST BIOS 1.04. + */ + popw %dx + pushw %dx + + /* use CHS if fails */ + jc chs_mode + cmpw $0xaa55, %bx + jne chs_mode + + /* check if AH=0x42 is supported if FORCE_LBA is zero */ + MOV_MEM_TO_AL(ABS(force_lba)) /* movb ABS(force_lba), %al */ + testb %al, %al + jnz lba_mode + andw $1, %cx + jz chs_mode + +lba_mode: + /* save the total number of sectors */ + movl 0x10(%si), %ecx + + /* set %si to the disk address packet */ + movw $ABS(disk_address_packet), %si + + /* set the mode to non-zero */ + movb $1, -1(%si) + + movl ABS(kernel_sector), %ebx + + /* the size and the reserved byte */ + movw $0x0010, (%si) + + /* the blocks */ + movw $1, 2(%si) + + /* the absolute address (low 32 bits) */ + movl %ebx, 8(%si) + + /* the segment of buffer address */ + movw $PUPA_BOOT_MACHINE_BUFFER_SEG, 6(%si) + + xorl %eax, %eax + movw %ax, 4(%si) + movl %eax, 12(%si) + +/* + * BIOS call "INT 0x13 Function 0x42" to read sectors from disk into memory + * Call with %ah = 0x42 + * %dl = drive number + * %ds:%si = segment:offset of disk address packet + * Return: + * %al = 0x0 on success; err code on failure + */ + + movb $0x42, %ah + int $0x13 + + /* LBA read is not supported, so fallback to CHS. */ + jc chs_mode + + movw $PUPA_BOOT_MACHINE_BUFFER_SEG, %bx + jmp copy_buffer + +chs_mode: + /* + * Determine the hard disk geometry from the BIOS! + * We do this first, so that LS-120 IDE floppies work correctly. + */ + movb $8, %ah + int $0x13 + jnc final_init + + /* + * The call failed, so maybe use the floppy probe instead. + */ + testb $PUPA_BOOT_MACHINE_BIOS_HD_FLAG, %dl + jz floppy_probe + + /* Nope, we definitely have a hard disk, and we're screwed. */ + jmp hd_probe_error + +final_init: + + movw $ABS(sectors), %si + + /* set the mode to zero */ + movb $0, -1(%si) + + /* save number of heads */ + xorl %eax, %eax + movb %dh, %al + incw %ax + movl %eax, 4(%si) + + xorw %dx, %dx + movb %cl, %dl + shlw $2, %dx + movb %ch, %al + movb %dh, %ah + + /* save number of cylinders */ + incw %ax + movw %ax, 8(%si) + + xorw %ax, %ax + movb %dl, %al + shrb $2, %al + + /* save number of sectors */ + movl %eax, (%si) + +setup_sectors: + /* load logical sector start (bottom half) */ + movl ABS(kernel_sector), %eax + + /* zero %edx */ + xorl %edx, %edx + + /* divide by number of sectors */ + divl (%si) + + /* save sector start */ + movb %dl, 10(%si) + + xorl %edx, %edx /* zero %edx */ + divl 4(%si) /* divide by number of heads */ + + /* save head start */ + movb %dl, 11(%si) + + /* save cylinder start */ + movw %ax, 12(%si) + + /* do we need too many cylinders? */ + cmpw 8(%si), %ax + jge geometry_error + +/* + * This is the loop for taking care of BIOS geometry translation (ugh!) + */ + + /* get high bits of cylinder */ + movb 13(%si), %dl + + shlb $6, %dl /* shift left by 6 bits */ + movb 10(%si), %cl /* get sector */ + + incb %cl /* normalize sector (sectors go + from 1-N, not 0-(N-1) ) */ + orb %dl, %cl /* composite together */ + movb 12(%si), %ch /* sector+hcyl in cl, cylinder in ch */ + + /* restore %dx */ + popw %dx + + /* head number */ + movb 11(%si), %dh + +/* + * BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory + * Call with %ah = 0x2 + * %al = number of sectors + * %ch = cylinder + * %cl = sector (bits 6-7 are high bits of "cylinder") + * %dh = head + * %dl = drive (0x80 for hard disk, 0x0 for floppy disk) + * %es:%bx = segment:offset of buffer + * Return: + * %al = 0x0 on success; err code on failure + */ + + movw $PUPA_BOOT_MACHINE_BUFFER_SEG, %bx + movw %bx, %es /* load %es segment with disk buffer */ + + xorw %bx, %bx /* %bx = 0, put it at 0 in the segment */ + movw $0x0201, %ax /* function 2 */ + int $0x13 + + jc read_error + + movw %es, %bx + +copy_buffer: + movw ABS(kernel_segment), %es + + /* + * We need to save %cx and %si because the startup code in + * kernel uses them without initializing them. + */ + pusha + pushw %ds + + movw $0x100, %cx + movw %bx, %ds + xorw %si, %si + xorw %di, %di + + cld + + rep + movsw + + popw %ds + popa + + /* boot kernel */ + jmp *(kernel_address) + +/* END OF MAIN LOOP */ + +/* + * BIOS Geometry translation error (past the end of the disk geometry!). + */ +geometry_error: + MSG(geometry_error_string) + jmp general_error + +/* + * Disk probe failure. + */ +hd_probe_error: + MSG(hd_probe_error_string) + jmp general_error + +/* + * Read error on the disk. + */ +read_error: + MSG(read_error_string) + +general_error: + MSG(general_error_string) + +/* go here when you need to stop the machine hard after an error condition */ +stop: jmp stop + +notification_string: .string "PUPA " +geometry_error_string: .string "Geom" +hd_probe_error_string: .string "Hard Disk" +read_error_string: .string "Read" +general_error_string: .string " Error" + +/* + * message: write the string pointed to by %si + * + * WARNING: trashes %si, %ax, and %bx + */ + + /* + * Use BIOS "int 10H Function 0Eh" to write character in teletype mode + * %ah = 0xe %al = character + * %bh = page %bl = foreground color (graphics modes) + */ +1: + movw $0x0001, %bx + movb $0xe, %ah + int $0x10 /* display a byte */ +message: + lodsb + cmpb $0, %al + jne 1b /* if not end of string, jmp to display */ + ret + + /* + * Windows NT breaks compatibility by embedding a magic + * number here. + */ + + . = _start + PUPA_BOOT_MACHINE_WINDOWS_NT_MAGIC +nt_magic: + .long 0 + .word 0 + + /* + * This is where an MBR would go if on a hard disk. The code + * here isn't even referenced unless we're on a floppy. Kinda + * sneaky, huh? + */ + +part_start: + . = _start + PUPA_BOOT_MACHINE_PART_START + +probe_values: + .byte 36, 18, 15, 9, 0 + +floppy_probe: +/* + * Perform floppy probe. + */ + + movw $ABS(probe_values-1), %si + +probe_loop: + /* reset floppy controller INT 13h AH=0 */ + xorw %ax, %ax + int $0x13 + + incw %si + movb (%si), %cl + + /* if number of sectors is 0, display error and die */ + cmpb $0, %cl + jne 1f + +/* + * Floppy disk probe failure. + */ + MSG(fd_probe_error_string) + jmp general_error + +fd_probe_error_string: .string "Floppy" + +1: + /* perform read */ + movw $PUPA_BOOT_MACHINE_BUFFER_SEG, %bx + movw $0x201, %ax + movb $0, %ch + movb $0, %dh + int $0x13 + + /* if error, jump to "probe_loop" */ + jc probe_loop + + /* %cl is already the correct value! */ + movb $1, %dh + movb $79, %ch + + jmp final_init + + . = _start + PUPA_BOOT_MACHINE_PART_END + +/* the last 2 bytes in the sector 0 contain the signature */ + .word PUPA_BOOT_MACHINE_SIGNATURE diff --git a/boot/i386/pc/diskboot.S b/boot/i386/pc/diskboot.S new file mode 100644 index 000000000..da1e02a17 --- /dev/null +++ b/boot/i386/pc/diskboot.S @@ -0,0 +1,387 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 1999,2000,2001 Free Software Foundation, Inc. + * Copyright (C) 2002 Yoshinori K. Okuji + * + * 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. + */ + +#include + +/* + * defines for the code go here + */ + + /* Absolute addresses + This makes the assembler generate the address without support + from the linker. (ELF can't relocate 16-bit addresses!) */ +#define ABS(x) (x-_start+PUPA_BOOT_MACHINE_KERNEL_ADDR) + + /* Print message string */ +#define MSG(x) movw $ABS(x), %si; call message + + .file "diskboot.S" + + .text + + /* Tell GAS to generate 16-bit instructions so that this code works + in real mode. */ + .code16 + + .globl start, _start +start: +_start: + /* + * _start is loaded at 0x2000 and is jumped to with + * CS:IP 0:0x2000 in kernel. + */ + + /* + * we continue to use the stack for boot.img and assume that + * some registers are set to correct values. See boot.S + * for more information. + */ + + /* save drive reference first thing! */ + pushw %dx + + /* print a notification message on the screen */ + pushw %si + MSG(notification_string) + popw %si + + /* this sets up for the first run through "bootloop" */ + movw $ABS(firstlist - PUPA_BOOT_MACHINE_LIST_SIZE), %di + + /* save the sector number of the second sector in %ebp */ + movl (%di), %ebp + + /* this is the loop for reading the rest of the kernel in */ +bootloop: + + /* check the number of sectors to read */ + cmpw $0, 4(%di) + + /* if zero, go to the start function */ + je bootit + +setup_sectors: + /* check if we use LBA or CHS */ + cmpb $0, -1(%si) + + /* jump to chs_mode if zero */ + je chs_mode + +lba_mode: + /* load logical sector start */ + movl (%di), %ebx + + /* the maximum is limited to 0x7f because of Phoenix EDD */ + xorl %eax, %eax + movb $0x7f, %al + + /* how many do we really want to read? */ + cmpw %ax, 4(%di) /* compare against total number of sectors */ + + /* which is greater? */ + jg 1f + + /* if less than, set to total */ + movw 4(%di), %ax + +1: + /* subtract from total */ + subw %ax, 4(%di) + + /* add into logical sector start */ + addl %eax, (%di) + + /* set up disk address packet */ + + /* the size and the reserved byte */ + movw $0x0010, (%si) + + /* the number of sectors */ + movw %ax, 2(%si) + + /* the absolute address (low 32 bits) */ + movl %ebx, 8(%si) + + /* the segment of buffer address */ + movw $PUPA_BOOT_MACHINE_BUFFER_SEG, 6(%si) + + /* save %ax from destruction! */ + pushw %ax + + /* zero %eax */ + xorl %eax, %eax + + /* the offset of buffer address */ + movw %ax, 4(%si) + + /* the absolute address (high 32 bits) */ + movl %eax, 12(%si) + + +/* + * BIOS call "INT 0x13 Function 0x42" to read sectors from disk into memory + * Call with %ah = 0x42 + * %dl = drive number + * %ds:%si = segment:offset of disk address packet + * Return: + * %al = 0x0 on success; err code on failure + */ + + movb $0x42, %ah + int $0x13 + + jc read_error + + movw $PUPA_BOOT_MACHINE_BUFFER_SEG, %bx + jmp copy_buffer + +chs_mode: + /* load logical sector start (bottom half) */ + movl (%di), %eax + + /* zero %edx */ + xorl %edx, %edx + + /* divide by number of sectors */ + divl (%si) + + /* save sector start */ + movb %dl, 10(%si) + + xorl %edx, %edx /* zero %edx */ + divl 4(%si) /* divide by number of heads */ + + /* save head start */ + movb %dl, 11(%si) + + /* save cylinder start */ + movw %ax, 12(%si) + + /* do we need too many cylinders? */ + cmpw 8(%si), %ax + jge geometry_error + + /* determine the maximum sector length of this read */ + movw (%si), %ax /* get number of sectors per track/head */ + + /* subtract sector start */ + subb 10(%si), %al + + /* how many do we really want to read? */ + cmpw %ax, 4(%di) /* compare against total number of sectors */ + + + /* which is greater? */ + jg 2f + + /* if less than, set to total */ + movw 4(%di), %ax + +2: + /* subtract from total */ + subw %ax, 4(%di) + + /* add into logical sector start */ + addl %eax, (%di) + +/* + * This is the loop for taking care of BIOS geometry translation (ugh!) + */ + + /* get high bits of cylinder */ + movb 13(%si), %dl + + shlb $6, %dl /* shift left by 6 bits */ + movb 10(%si), %cl /* get sector */ + + incb %cl /* normalize sector (sectors go + from 1-N, not 0-(N-1) ) */ + orb %dl, %cl /* composite together */ + movb 12(%si), %ch /* sector+hcyl in cl, cylinder in ch */ + + /* restore %dx */ + popw %dx + pushw %dx + + /* head number */ + movb 11(%si), %dh + + pushw %ax /* save %ax from destruction! */ + +/* + * BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory + * Call with %ah = 0x2 + * %al = number of sectors + * %ch = cylinder + * %cl = sector (bits 6-7 are high bits of "cylinder") + * %dh = head + * %dl = drive (0x80 for hard disk, 0x0 for floppy disk) + * %es:%bx = segment:offset of buffer + * Return: + * %al = 0x0 on success; err code on failure + */ + + movw $PUPA_BOOT_MACHINE_BUFFER_SEG, %bx + movw %bx, %es /* load %es segment with disk buffer */ + + xorw %bx, %bx /* %bx = 0, put it at 0 in the segment */ + movb $0x2, %ah /* function 2 */ + int $0x13 + + jc read_error + + /* save source segment */ + movw %es, %bx + +copy_buffer: + + /* load addresses for copy from disk buffer to destination */ + movw 6(%di), %es /* load destination segment */ + + /* restore %ax */ + popw %ax + + /* determine the next possible destination address (presuming + 512 byte sectors!) */ + shlw $5, %ax /* shift %ax five bits to the left */ + addw %ax, 6(%di) /* add the corrected value to the destination + address for next time */ + + /* save addressing regs */ + pusha + pushw %ds + + /* get the copy length */ + shlw $3, %ax + movw %ax, %cx + + xorw %di, %di /* zero offset of destination addresses */ + xorw %si, %si /* zero offset of source addresses */ + movw %bx, %ds /* restore the source segment */ + + cld /* sets the copy direction to forward */ + + /* perform copy */ + rep /* sets a repeat */ + movsw /* this runs the actual copy */ + + /* restore addressing regs and print a dot with correct DS + (MSG modifies SI, which is saved, and unused AX and BX) */ + popw %ds + MSG(notification_step) + popa + + /* check if finished with this dataset */ + cmpw $0, 4(%di) + jne setup_sectors + + /* update position to load from */ + subw $PUPA_BOOT_MACHINE_LIST_SIZE, %di + + /* jump to bootloop */ + jmp bootloop + +/* END OF MAIN LOOP */ + +bootit: + /* print a newline */ + MSG(notification_done) + popw %dx /* this makes sure %dl is our "boot" drive */ + ljmp $0, $(PUPA_BOOT_MACHINE_KERNEL_ADDR + 0x200) + + +/* + * BIOS Geometry translation error (past the end of the disk geometry!). + */ +geometry_error: + MSG(geometry_error_string) + jmp general_error + +/* + * Read error on the disk. + */ +read_error: + MSG(read_error_string) + +general_error: + MSG(general_error_string) + +/* go here when you need to stop the machine hard after an error condition */ +stop: jmp stop + +notification_string: .string "Loading kernel" + +notification_step: .string "." +notification_done: .string "\r\n" + +geometry_error_string: .string "Geom" +read_error_string: .string "Read" +general_error_string: .string " Error" + +/* + * message: write the string pointed to by %si + * + * WARNING: trashes %si, %ax, and %bx + */ + + /* + * Use BIOS "int 10H Function 0Eh" to write character in teletype mode + * %ah = 0xe %al = character + * %bh = page %bl = foreground color (graphics modes) + */ +1: + movw $0x0001, %bx + movb $0xe, %ah + int $0x10 /* display a byte */ + + incw %si +message: + movb (%si), %al + cmpb $0, %al + jne 1b /* if not end of string, jmp to display */ + ret +lastlist: + +/* + * This area is an empty space between the main body of code below which + * grows up (fixed after compilation, but between releases it may change + * in size easily), and the lists of sectors to read, which grows down + * from a fixed top location. + */ + + .word 0 + .word 0 + + . = _start + 0x200 - PUPA_BOOT_MACHINE_LIST_SIZE + + /* fill the first data listing with the default */ +blocklist_default_start: + /* this is the sector start parameter, in logical sectors from + the start of the disk, sector 0 */ + .long 2 +blocklist_default_len: + /* this is the number of sectors to read the command "install" + will fill this up */ + .word 0 +blocklist_default_seg: + /* this is the segment of the starting address to load the data into */ + .word (PUPA_BOOT_MACHINE_KERNEL_SEG + 0x20) + +firstlist: /* this label has to be after the list data!!! */ diff --git a/conf/i386-pc.mk b/conf/i386-pc.mk new file mode 100644 index 000000000..ee4880b77 --- /dev/null +++ b/conf/i386-pc.mk @@ -0,0 +1,379 @@ +# -*- makefile -*- + +COMMON_ASFLAGS = -nostdinc -fno-builtin +COMMON_CFLAGS = -fno-builtin + +# Images. +pkgdata_IMAGES = boot.img diskboot.img kernel.img + +# For boot.img. +boot_img_SOURCES = boot/i386/pc/boot.S +CLEANFILES += boot.img boot.exec boot_img-boot_i386_pc_boot.o +MOSTLYCLEANFILES += boot_img-boot_i386_pc_boot.d + +boot.img: boot.exec + $(OBJCOPY) -O binary -R .note -R .comment $< $@ + +boot.exec: boot_img-boot_i386_pc_boot.o + $(CC) $(LDFLAGS) $(boot_img_LDFLAGS) -o $@ $^ + +boot_img-boot_i386_pc_boot.o: boot/i386/pc/boot.S + $(CC) -Iboot/i386/pc -I$(srcdir)/boot/i386/pc $(CPPFLAGS) -DASM_FILE=1 $(ASFLAGS) $(boot_img_ASFLAGS) -c -o $@ $< + +boot_img-boot_i386_pc_boot.d: boot/i386/pc/boot.S + set -e; $(CC) -Iboot/i386/pc -I$(srcdir)/boot/i386/pc $(CPPFLAGS) -DASM_FILE=1 $(ASFLAGS) $(boot_img_ASFLAGS) -M $< | sed 's,boot\.o[ :]*,boot_img-boot_i386_pc_boot.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include boot_img-boot_i386_pc_boot.d + +boot_img_ASFLAGS = $(COMMON_ASFLAGS) +boot_img_LDFLAGS = -nostdlib -Wl,-N,-Ttext,7C00 + +# For diskboot.img. +diskboot_img_SOURCES = boot/i386/pc/diskboot.S +CLEANFILES += diskboot.img diskboot.exec diskboot_img-boot_i386_pc_diskboot.o +MOSTLYCLEANFILES += diskboot_img-boot_i386_pc_diskboot.d + +diskboot.img: diskboot.exec + $(OBJCOPY) -O binary -R .note -R .comment $< $@ + +diskboot.exec: diskboot_img-boot_i386_pc_diskboot.o + $(CC) $(LDFLAGS) $(diskboot_img_LDFLAGS) -o $@ $^ + +diskboot_img-boot_i386_pc_diskboot.o: boot/i386/pc/diskboot.S + $(CC) -Iboot/i386/pc -I$(srcdir)/boot/i386/pc $(CPPFLAGS) -DASM_FILE=1 $(ASFLAGS) $(diskboot_img_ASFLAGS) -c -o $@ $< + +diskboot_img-boot_i386_pc_diskboot.d: boot/i386/pc/diskboot.S + set -e; $(CC) -Iboot/i386/pc -I$(srcdir)/boot/i386/pc $(CPPFLAGS) -DASM_FILE=1 $(ASFLAGS) $(diskboot_img_ASFLAGS) -M $< | sed 's,diskboot\.o[ :]*,diskboot_img-boot_i386_pc_diskboot.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include diskboot_img-boot_i386_pc_diskboot.d + +diskboot_img_ASFLAGS = $(COMMON_ASFLAGS) +diskboot_img_LDFLAGS = -nostdlib -Wl,-N,-Ttext,8000 + +# For kernel.img. +kernel_img_SOURCES = kern/i386/pc/startup.S kern/main.c kern/device.c \ + kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ + kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \ + kern/i386/dl.c kern/i386/pc/init.c disk/i386/pc/partition.c \ + disk/i386/pc/biosdisk.c \ + term/i386/pc/console.c \ + symlist.c +CLEANFILES += kernel.img kernel.exec kernel_img-kern_i386_pc_startup.o kernel_img-kern_main.o kernel_img-kern_device.o kernel_img-kern_disk.o kernel_img-kern_dl.o kernel_img-kern_file.o kernel_img-kern_fs.o kernel_img-kern_err.o kernel_img-kern_misc.o kernel_img-kern_mm.o kernel_img-kern_loader.o kernel_img-kern_rescue.o kernel_img-kern_term.o kernel_img-kern_i386_dl.o kernel_img-kern_i386_pc_init.o kernel_img-disk_i386_pc_partition.o kernel_img-disk_i386_pc_biosdisk.o kernel_img-term_i386_pc_console.o kernel_img-symlist.o +MOSTLYCLEANFILES += kernel_img-kern_i386_pc_startup.d kernel_img-kern_main.d kernel_img-kern_device.d kernel_img-kern_disk.d kernel_img-kern_dl.d kernel_img-kern_file.d kernel_img-kern_fs.d kernel_img-kern_err.d kernel_img-kern_misc.d kernel_img-kern_mm.d kernel_img-kern_loader.d kernel_img-kern_rescue.d kernel_img-kern_term.d kernel_img-kern_i386_dl.d kernel_img-kern_i386_pc_init.d kernel_img-disk_i386_pc_partition.d kernel_img-disk_i386_pc_biosdisk.d kernel_img-term_i386_pc_console.d kernel_img-symlist.d + +kernel.img: kernel.exec + $(OBJCOPY) -O binary -R .note -R .comment $< $@ + +kernel.exec: kernel_img-kern_i386_pc_startup.o kernel_img-kern_main.o kernel_img-kern_device.o kernel_img-kern_disk.o kernel_img-kern_dl.o kernel_img-kern_file.o kernel_img-kern_fs.o kernel_img-kern_err.o kernel_img-kern_misc.o kernel_img-kern_mm.o kernel_img-kern_loader.o kernel_img-kern_rescue.o kernel_img-kern_term.o kernel_img-kern_i386_dl.o kernel_img-kern_i386_pc_init.o kernel_img-disk_i386_pc_partition.o kernel_img-disk_i386_pc_biosdisk.o kernel_img-term_i386_pc_console.o kernel_img-symlist.o + $(CC) $(LDFLAGS) $(kernel_img_LDFLAGS) -o $@ $^ + +kernel_img-kern_i386_pc_startup.o: kern/i386/pc/startup.S + $(CC) -Ikern/i386/pc -I$(srcdir)/kern/i386/pc $(CPPFLAGS) -DASM_FILE=1 $(ASFLAGS) $(kernel_img_ASFLAGS) -c -o $@ $< + +kernel_img-kern_i386_pc_startup.d: kern/i386/pc/startup.S + set -e; $(CC) -Ikern/i386/pc -I$(srcdir)/kern/i386/pc $(CPPFLAGS) -DASM_FILE=1 $(ASFLAGS) $(kernel_img_ASFLAGS) -M $< | sed 's,startup\.o[ :]*,kernel_img-kern_i386_pc_startup.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include kernel_img-kern_i386_pc_startup.d + +kernel_img-kern_main.o: kern/main.c + $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $< + +kernel_img-kern_main.d: kern/main.c + set -e; $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -M $< | sed 's,main\.o[ :]*,kernel_img-kern_main.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include kernel_img-kern_main.d + +kernel_img-kern_device.o: kern/device.c + $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $< + +kernel_img-kern_device.d: kern/device.c + set -e; $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -M $< | sed 's,device\.o[ :]*,kernel_img-kern_device.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include kernel_img-kern_device.d + +kernel_img-kern_disk.o: kern/disk.c + $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $< + +kernel_img-kern_disk.d: kern/disk.c + set -e; $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -M $< | sed 's,disk\.o[ :]*,kernel_img-kern_disk.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include kernel_img-kern_disk.d + +kernel_img-kern_dl.o: kern/dl.c + $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $< + +kernel_img-kern_dl.d: kern/dl.c + set -e; $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -M $< | sed 's,dl\.o[ :]*,kernel_img-kern_dl.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include kernel_img-kern_dl.d + +kernel_img-kern_file.o: kern/file.c + $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $< + +kernel_img-kern_file.d: kern/file.c + set -e; $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -M $< | sed 's,file\.o[ :]*,kernel_img-kern_file.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include kernel_img-kern_file.d + +kernel_img-kern_fs.o: kern/fs.c + $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $< + +kernel_img-kern_fs.d: kern/fs.c + set -e; $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -M $< | sed 's,fs\.o[ :]*,kernel_img-kern_fs.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include kernel_img-kern_fs.d + +kernel_img-kern_err.o: kern/err.c + $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $< + +kernel_img-kern_err.d: kern/err.c + set -e; $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -M $< | sed 's,err\.o[ :]*,kernel_img-kern_err.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include kernel_img-kern_err.d + +kernel_img-kern_misc.o: kern/misc.c + $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $< + +kernel_img-kern_misc.d: kern/misc.c + set -e; $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -M $< | sed 's,misc\.o[ :]*,kernel_img-kern_misc.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include kernel_img-kern_misc.d + +kernel_img-kern_mm.o: kern/mm.c + $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $< + +kernel_img-kern_mm.d: kern/mm.c + set -e; $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -M $< | sed 's,mm\.o[ :]*,kernel_img-kern_mm.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include kernel_img-kern_mm.d + +kernel_img-kern_loader.o: kern/loader.c + $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $< + +kernel_img-kern_loader.d: kern/loader.c + set -e; $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -M $< | sed 's,loader\.o[ :]*,kernel_img-kern_loader.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include kernel_img-kern_loader.d + +kernel_img-kern_rescue.o: kern/rescue.c + $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $< + +kernel_img-kern_rescue.d: kern/rescue.c + set -e; $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -M $< | sed 's,rescue\.o[ :]*,kernel_img-kern_rescue.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include kernel_img-kern_rescue.d + +kernel_img-kern_term.o: kern/term.c + $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $< + +kernel_img-kern_term.d: kern/term.c + set -e; $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -M $< | sed 's,term\.o[ :]*,kernel_img-kern_term.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include kernel_img-kern_term.d + +kernel_img-kern_i386_dl.o: kern/i386/dl.c + $(CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $< + +kernel_img-kern_i386_dl.d: kern/i386/dl.c + set -e; $(CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -M $< | sed 's,dl\.o[ :]*,kernel_img-kern_i386_dl.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include kernel_img-kern_i386_dl.d + +kernel_img-kern_i386_pc_init.o: kern/i386/pc/init.c + $(CC) -Ikern/i386/pc -I$(srcdir)/kern/i386/pc $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $< + +kernel_img-kern_i386_pc_init.d: kern/i386/pc/init.c + set -e; $(CC) -Ikern/i386/pc -I$(srcdir)/kern/i386/pc $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -M $< | sed 's,init\.o[ :]*,kernel_img-kern_i386_pc_init.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include kernel_img-kern_i386_pc_init.d + +kernel_img-disk_i386_pc_partition.o: disk/i386/pc/partition.c + $(CC) -Idisk/i386/pc -I$(srcdir)/disk/i386/pc $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $< + +kernel_img-disk_i386_pc_partition.d: disk/i386/pc/partition.c + set -e; $(CC) -Idisk/i386/pc -I$(srcdir)/disk/i386/pc $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -M $< | sed 's,partition\.o[ :]*,kernel_img-disk_i386_pc_partition.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include kernel_img-disk_i386_pc_partition.d + +kernel_img-disk_i386_pc_biosdisk.o: disk/i386/pc/biosdisk.c + $(CC) -Idisk/i386/pc -I$(srcdir)/disk/i386/pc $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $< + +kernel_img-disk_i386_pc_biosdisk.d: disk/i386/pc/biosdisk.c + set -e; $(CC) -Idisk/i386/pc -I$(srcdir)/disk/i386/pc $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -M $< | sed 's,biosdisk\.o[ :]*,kernel_img-disk_i386_pc_biosdisk.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include kernel_img-disk_i386_pc_biosdisk.d + +kernel_img-term_i386_pc_console.o: term/i386/pc/console.c + $(CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $< + +kernel_img-term_i386_pc_console.d: term/i386/pc/console.c + set -e; $(CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -M $< | sed 's,console\.o[ :]*,kernel_img-term_i386_pc_console.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include kernel_img-term_i386_pc_console.d + +kernel_img-symlist.o: symlist.c + $(CC) -I. -I$(srcdir)/. $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $< + +kernel_img-symlist.d: symlist.c + set -e; $(CC) -I. -I$(srcdir)/. $(CPPFLAGS) $(CFLAGS) $(kernel_img_CFLAGS) -M $< | sed 's,symlist\.o[ :]*,kernel_img-symlist.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include kernel_img-symlist.d + +kernel_img_HEADERS = boot.h device.h disk.h dl.h elf.h err.h \ + file.h fs.h kernel.h loader.h misc.h mm.h net.h rescue.h symbol.h \ + term.h types.h machine/biosdisk.h machine/boot.h \ + machine/console.h machine/init.h machine/memory.h \ + machine/loader.h machine/partition.h +kernel_img_CFLAGS = $(COMMON_CFLAGS) +kernel_img_ASFLAGS = $(COMMON_ASFLAGS) +kernel_img_LDFLAGS = -nostdlib -Wl,-N,-Ttext,8200 + +MOSTLYCLEANFILES += symlist.c kernel_syms.lst +DEFSYMFILES += kernel_syms.lst + +symlist.c: $(addprefix include/pupa/,$(kernel_img_HEADERS)) gensymlist.sh + sh $(srcdir)/gensymlist.sh $(filter %.h,$^) > $@ + +kernel_syms.lst: $(addprefix include/pupa/,$(kernel_img_HEADERS)) genkernsyms.sh + sh $(srcdir)/genkernsyms.sh $(filter %h,$^) > $@ + +# Utilities. +bin_UTILITIES = pupa-mkimage +noinst_UTILITIES = genmoddep + +# For pupa-mkimage. +pupa_mkimage_SOURCES = util/i386/pc/pupa-mkimage.c util/misc.c \ + util/resolve.c +CLEANFILES += pupa-mkimage pupa_mkimage-util_i386_pc_pupa_mkimage.o pupa_mkimage-util_misc.o pupa_mkimage-util_resolve.o +MOSTLYCLEANFILES += pupa_mkimage-util_i386_pc_pupa_mkimage.d pupa_mkimage-util_misc.d pupa_mkimage-util_resolve.d + +pupa-mkimage: pupa_mkimage-util_i386_pc_pupa_mkimage.o pupa_mkimage-util_misc.o pupa_mkimage-util_resolve.o + $(BUILD_CC) $(BUILD_LDFLAGS) $(pupa_mkimage_LDFLAGS) -o $@ $^ + +pupa_mkimage-util_i386_pc_pupa_mkimage.o: util/i386/pc/pupa-mkimage.c + $(BUILD_CC) -Iutil/i386/pc -I$(srcdir)/util/i386/pc $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(pupa_mkimage_CFLAGS) -c -o $@ $< + +pupa_mkimage-util_i386_pc_pupa_mkimage.d: util/i386/pc/pupa-mkimage.c + set -e; $(BUILD_CC) -Iutil/i386/pc -I$(srcdir)/util/i386/pc $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(pupa_mkimage_CFLAGS) -M $< | sed 's,pupa\-mkimage\.o[ :]*,pupa_mkimage-util_i386_pc_pupa_mkimage.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include pupa_mkimage-util_i386_pc_pupa_mkimage.d + +pupa_mkimage-util_misc.o: util/misc.c + $(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(pupa_mkimage_CFLAGS) -c -o $@ $< + +pupa_mkimage-util_misc.d: util/misc.c + set -e; $(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(pupa_mkimage_CFLAGS) -M $< | sed 's,misc\.o[ :]*,pupa_mkimage-util_misc.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include pupa_mkimage-util_misc.d + +pupa_mkimage-util_resolve.o: util/resolve.c + $(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(pupa_mkimage_CFLAGS) -c -o $@ $< + +pupa_mkimage-util_resolve.d: util/resolve.c + set -e; $(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(pupa_mkimage_CFLAGS) -M $< | sed 's,resolve\.o[ :]*,pupa_mkimage-util_resolve.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include pupa_mkimage-util_resolve.d + + +# For genmoddep. +genmoddep_SOURCES = util/genmoddep.c +CLEANFILES += genmoddep genmoddep-util_genmoddep.o +MOSTLYCLEANFILES += genmoddep-util_genmoddep.d + +genmoddep: genmoddep-util_genmoddep.o + $(BUILD_CC) $(BUILD_LDFLAGS) $(genmoddep_LDFLAGS) -o $@ $^ + +genmoddep-util_genmoddep.o: util/genmoddep.c + $(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(genmoddep_CFLAGS) -c -o $@ $< + +genmoddep-util_genmoddep.d: util/genmoddep.c + set -e; $(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(genmoddep_CFLAGS) -M $< | sed 's,genmoddep\.o[ :]*,genmoddep-util_genmoddep.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include genmoddep-util_genmoddep.d + + +# Modules. +pkgdata_MODULES = chain.mod fat.mod + +# For chain.mod. +chain_mod_SOURCES = loader/i386/pc/chainloader.c +CLEANFILES += chain.mod mod-chain.o mod-chain.c pre-chain.o chain_mod-loader_i386_pc_chainloader.o def-chain.lst und-chain.lst +MOSTLYCLEANFILES += chain_mod-loader_i386_pc_chainloader.d +DEFSYMFILES += def-chain.lst +UNDSYMFILES += und-chain.lst + +chain.mod: pre-chain.o mod-chain.o + -rm -f $@ + $(LD) -r -o $@ $^ + $(STRIP) --strip-unneeded -K pupa_mod_init -K pupa_mod_fini -R .note -R .comment $@ + +pre-chain.o: chain_mod-loader_i386_pc_chainloader.o + -rm -f $@ + $(LD) -r -o $@ $^ + +mod-chain.o: mod-chain.c + $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< + +mod-chain.c: moddep.lst genmodsrc.sh + sh $(srcdir)/genmodsrc.sh 'chain' $< > $@ || (rm -f $@; exit 1) + +def-chain.lst: pre-chain.o + $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 chain/' > $@ + +und-chain.lst: pre-chain.o + echo 'chain' > $@ + $(NM) -u -P -p $< >> $@ + +chain_mod-loader_i386_pc_chainloader.o: loader/i386/pc/chainloader.c + $(CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(CPPFLAGS) $(CFLAGS) $(chain_mod_CFLAGS) -c -o $@ $< + +chain_mod-loader_i386_pc_chainloader.d: loader/i386/pc/chainloader.c + set -e; $(CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(CPPFLAGS) $(CFLAGS) $(chain_mod_CFLAGS) -M $< | sed 's,chainloader\.o[ :]*,chain_mod-loader_i386_pc_chainloader.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include chain_mod-loader_i386_pc_chainloader.d + +chain_mod_CFLAGS = $(COMMON_CFLAGS) + +# For fat.mod. +fat_mod_SOURCES = fs/fat.c +CLEANFILES += fat.mod mod-fat.o mod-fat.c pre-fat.o fat_mod-fs_fat.o def-fat.lst und-fat.lst +MOSTLYCLEANFILES += fat_mod-fs_fat.d +DEFSYMFILES += def-fat.lst +UNDSYMFILES += und-fat.lst + +fat.mod: pre-fat.o mod-fat.o + -rm -f $@ + $(LD) -r -o $@ $^ + $(STRIP) --strip-unneeded -K pupa_mod_init -K pupa_mod_fini -R .note -R .comment $@ + +pre-fat.o: fat_mod-fs_fat.o + -rm -f $@ + $(LD) -r -o $@ $^ + +mod-fat.o: mod-fat.c + $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< + +mod-fat.c: moddep.lst genmodsrc.sh + sh $(srcdir)/genmodsrc.sh 'fat' $< > $@ || (rm -f $@; exit 1) + +def-fat.lst: pre-fat.o + $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 fat/' > $@ + +und-fat.lst: pre-fat.o + echo 'fat' > $@ + $(NM) -u -P -p $< >> $@ + +fat_mod-fs_fat.o: fs/fat.c + $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) $(fat_mod_CFLAGS) -c -o $@ $< + +fat_mod-fs_fat.d: fs/fat.c + set -e; $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) $(fat_mod_CFLAGS) -M $< | sed 's,fat\.o[ :]*,fat_mod-fs_fat.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include fat_mod-fs_fat.d + +fat_mod_CFLAGS = $(COMMON_CFLAGS) +CLEANFILES += moddep.lst +pkgdata_DATA += moddep.lst +moddep.lst: $(DEFSYMFILES) $(UNDSYMFILES) genmoddep + cat $(DEFSYMFILES) /dev/null | ./genmoddep $(UNDSYMFILES) > $@ \ + || (rm -f $@; exit 1) diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk new file mode 100644 index 000000000..9f72c7e46 --- /dev/null +++ b/conf/i386-pc.rmk @@ -0,0 +1,65 @@ +# -*- makefile -*- + +COMMON_ASFLAGS = -nostdinc -fno-builtin +COMMON_CFLAGS = -fno-builtin + +# Images. +pkgdata_IMAGES = boot.img diskboot.img kernel.img + +# For boot.img. +boot_img_SOURCES = boot/i386/pc/boot.S +boot_img_ASFLAGS = $(COMMON_ASFLAGS) +boot_img_LDFLAGS = -nostdlib -Wl,-N,-Ttext,7C00 + +# For diskboot.img. +diskboot_img_SOURCES = boot/i386/pc/diskboot.S +diskboot_img_ASFLAGS = $(COMMON_ASFLAGS) +diskboot_img_LDFLAGS = -nostdlib -Wl,-N,-Ttext,8000 + +# For kernel.img. +kernel_img_SOURCES = kern/i386/pc/startup.S kern/main.c kern/device.c \ + kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ + kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \ + kern/i386/dl.c kern/i386/pc/init.c disk/i386/pc/partition.c \ + disk/i386/pc/biosdisk.c \ + term/i386/pc/console.c \ + symlist.c +kernel_img_HEADERS = boot.h device.h disk.h dl.h elf.h err.h \ + file.h fs.h kernel.h loader.h misc.h mm.h net.h rescue.h symbol.h \ + term.h types.h machine/biosdisk.h machine/boot.h \ + machine/console.h machine/init.h machine/memory.h \ + machine/loader.h machine/partition.h +kernel_img_CFLAGS = $(COMMON_CFLAGS) +kernel_img_ASFLAGS = $(COMMON_ASFLAGS) +kernel_img_LDFLAGS = -nostdlib -Wl,-N,-Ttext,8200 + +MOSTLYCLEANFILES += symlist.c kernel_syms.lst +DEFSYMFILES += kernel_syms.lst + +symlist.c: $(addprefix include/pupa/,$(kernel_img_HEADERS)) gensymlist.sh + sh $(srcdir)/gensymlist.sh $(filter %.h,$^) > $@ + +kernel_syms.lst: $(addprefix include/pupa/,$(kernel_img_HEADERS)) genkernsyms.sh + sh $(srcdir)/genkernsyms.sh $(filter %h,$^) > $@ + +# Utilities. +bin_UTILITIES = pupa-mkimage +noinst_UTILITIES = genmoddep + +# For pupa-mkimage. +pupa_mkimage_SOURCES = util/i386/pc/pupa-mkimage.c util/misc.c \ + util/resolve.c + +# For genmoddep. +genmoddep_SOURCES = util/genmoddep.c + +# Modules. +pkgdata_MODULES = chain.mod fat.mod + +# For chain.mod. +chain_mod_SOURCES = loader/i386/pc/chainloader.c +chain_mod_CFLAGS = $(COMMON_CFLAGS) + +# For fat.mod. +fat_mod_SOURCES = fs/fat.c +fat_mod_CFLAGS = $(COMMON_CFLAGS) diff --git a/config.guess b/config.guess new file mode 100644 index 000000000..ed2e03b7f --- /dev/null +++ b/config.guess @@ -0,0 +1,1321 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002 Free Software Foundation, Inc. + +timestamp='2002-03-20' + +# This file 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. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + + +dummy=dummy-$$ +trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int dummy(){}" > $dummy.c ; + for c in cc gcc c89 c99 ; do + ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ; + if test $? = 0 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + rm -f $dummy.c $dummy.o $dummy.rel ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit 0 ;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + macppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvmeppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mipseb-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sun3:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + alpha:OSF1:*:*) + if test $UNAME_RELEASE = "V4.0"; then + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + fi + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + cat <$dummy.s + .data +\$Lformat: + .byte 37,100,45,37,120,10,0 # "%d-%x\n" + + .text + .globl main + .align 4 + .ent main +main: + .frame \$30,16,\$26,0 + ldgp \$29,0(\$27) + .prologue 1 + .long 0x47e03d80 # implver \$0 + lda \$2,-1 + .long 0x47e20c21 # amask \$2,\$1 + lda \$16,\$Lformat + mov \$0,\$17 + not \$1,\$18 + jsr \$26,printf + ldgp \$29,0(\$26) + mov 0,\$16 + jsr \$26,exit + .end main +EOF + eval $set_cc_for_build + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + case `./$dummy` in + 0-0) + UNAME_MACHINE="alpha" + ;; + 1-0) + UNAME_MACHINE="alphaev5" + ;; + 1-1) + UNAME_MACHINE="alphaev56" + ;; + 1-101) + UNAME_MACHINE="alphapca56" + ;; + 2-303) + UNAME_MACHINE="alphaev6" + ;; + 2-307) + UNAME_MACHINE="alphaev67" + ;; + 2-1307) + UNAME_MACHINE="alphaev68" + ;; + esac + fi + rm -f $dummy.s $dummy + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit 0 ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit 0;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit 0 ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit 0 ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit 0 ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit 0 ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit 0 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit 0 ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit 0 ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit 0 ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit 0 ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit 0 ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy \ + && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo rs6000-ibm-aix3.2.5 + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit 0 ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null) && HP_ARCH=`./$dummy` + if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi + rm -f $dummy.c $dummy + fi ;; + esac + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3D:*:*:*) + echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit 0 ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit 0 ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit 0 ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit 0 ;; + x86:Interix*:3*) + echo i386-pc-interix3 + exit 0 ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i386-pc-interix + exit 0 ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + *:GNU:*:*) + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit 0 ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + rm -f $dummy.c + test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0 + ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit 0 ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit 0 ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit 0 ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit 0 ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit 0 ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit 0 ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit 0 ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit 0 ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit 0 ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit 0 ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #ifdef __INTEL_COMPILER + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + rm -f $dummy.c + test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 + test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit 0 ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit 0 ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit 0 ;; + i*86:*:5:[78]*) + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit 0 ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` + (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit 0 ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit 0 ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit 0 ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + M68*:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit 0 ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit 0 ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit 0 ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit 0 ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit 0 ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit 0 ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit 0 ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit 0 ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit 0 ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Darwin:*:*) + echo `uname -p`-apple-darwin${UNAME_RELEASE} + exit 0 ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit 0 ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit 0 ;; + NSR-[GKLNPTVW]:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit 0 ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit 0 ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit 0 ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit 0 ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit 0 ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit 0 ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit 0 ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit 0 ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit 0 ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit 0 ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit 0 ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit 0 ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit 0 ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit 0 ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0 +rm -f $dummy.c $dummy + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config.h.in b/config.h.in new file mode 100644 index 000000000..44ab1f719 --- /dev/null +++ b/config.h.in @@ -0,0 +1,78 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define it if GAS requires that absolute indirect calls/jumps are not + prefixed with an asterisk */ +#undef ABSOLUTE_WITHOUT_ASTERISK + +/* Define it to "addr32" or "addr32;" to make GAS happy */ +#undef ADDR32 + +/* Define it to one of __bss_start, edata and _edata */ +#undef BSS_START_SYMBOL + +/* Define it to "data32" or "data32;" to make GAS happy */ +#undef DATA32 + +/* Define it to either end or _end */ +#undef END_SYMBOL + +/* Define if C symbols get an underscore after compilation */ +#undef HAVE_ASM_USCORE + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* The size of a `long', as computed by sizeof. */ +#undef SIZEOF_LONG + +/* The size of a `void *', as computed by sizeof. */ +#undef SIZEOF_VOID_P + +/* Define it to either start or _start */ +#undef START_SYMBOL + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +#undef WORDS_BIGENDIAN diff --git a/config.sub b/config.sub new file mode 100644 index 000000000..299f3f4c5 --- /dev/null +++ b/config.sub @@ -0,0 +1,1443 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002 Free Software Foundation, Inc. + +timestamp='2002-04-26' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file 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. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit 0;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | c4x | clipper \ + | d10v | d30v | dsp16xx \ + | fr30 \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | m32r | m68000 | m68k | m88k | mcore \ + | mips | mips16 | mips64 | mips64el | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el | mips64vr4300 \ + | mips64vr4300el | mips64vr5000 | mips64vr5000el \ + | mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \ + | mipsisa32 | mipsisa64 \ + | mn10200 | mn10300 \ + | ns16k | ns32k \ + | openrisc | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | sh | sh[34] | sh[34]eb | shbe | shle | sh64 \ + | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ + | strongarm \ + | tahoe | thumb | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xscale | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armv*-* \ + | avr-* \ + | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c54x-* \ + | clipper-* | cydra-* \ + | d10v-* | d30v-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | m32r-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | mcore-* \ + | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \ + | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \ + | mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* | sh64-* \ + | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ + | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ + | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + crds | unos) + basic_machine=m68k-crds + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + mmix*) + basic_machine=mmix-knuth + os=-mmixware + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + or32 | or32-*) + basic_machine=or32-unknown + os=-coff + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon) + basic_machine=i686-pc + ;; + pentiumii | pentium2) + basic_machine=i686-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3d) + basic_machine=alpha-cray + os=-unicos + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + windows32) + basic_machine=i386-pc + os=-windows32-msvcrt + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh3 | sh4 | sh3eb | sh4eb) + basic_machine=sh-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparc | sparcv9 | sparcv9b) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + c4x*) + basic_machine=c4x-none + os=-coff + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* ) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto*) + os=-nto-qnx + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-ibm) + os=-aix + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/configure b/configure new file mode 100644 index 000000000..45a328b60 --- /dev/null +++ b/configure @@ -0,0 +1,5745 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.53 for PUPA 0.6. +# +# Report bugs to . +# +# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + + +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi + +# NLS nuisances. +# Support unset when possible. +if (FOO=FOO; unset FOO) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + +(set +x; test -n "`(LANG=C; export LANG) 2>&1`") && + { $as_unset LANG || test "${LANG+set}" != set; } || + { LANG=C; export LANG; } +(set +x; test -n "`(LC_ALL=C; export LC_ALL) 2>&1`") && + { $as_unset LC_ALL || test "${LC_ALL+set}" != set; } || + { LC_ALL=C; export LC_ALL; } +(set +x; test -n "`(LC_TIME=C; export LC_TIME) 2>&1`") && + { $as_unset LC_TIME || test "${LC_TIME+set}" != set; } || + { LC_TIME=C; export LC_TIME; } +(set +x; test -n "`(LC_CTYPE=C; export LC_CTYPE) 2>&1`") && + { $as_unset LC_CTYPE || test "${LC_CTYPE+set}" != set; } || + { LC_CTYPE=C; export LC_CTYPE; } +(set +x; test -n "`(LANGUAGE=C; export LANGUAGE) 2>&1`") && + { $as_unset LANGUAGE || test "${LANGUAGE+set}" != set; } || + { LANGUAGE=C; export LANGUAGE; } +(set +x; test -n "`(LC_COLLATE=C; export LC_COLLATE) 2>&1`") && + { $as_unset LC_COLLATE || test "${LC_COLLATE+set}" != set; } || + { LC_COLLATE=C; export LC_COLLATE; } +(set +x; test -n "`(LC_NUMERIC=C; export LC_NUMERIC) 2>&1`") && + { $as_unset LC_NUMERIC || test "${LC_NUMERIC+set}" != set; } || + { LC_NUMERIC=C; export LC_NUMERIC; } +(set +x; test -n "`(LC_MESSAGES=C; export LC_MESSAGES) 2>&1`") && + { $as_unset LC_MESSAGES || test "${LC_MESSAGES+set}" != set; } || + { LC_MESSAGES=C; export LC_MESSAGES; } + + +# Name of the executable. +as_me=`(basename "$0") 2>/dev/null || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conftest.sh + echo "exit 0" >>conftest.sh + chmod +x conftest.sh + if (PATH=".;."; conftest.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conftest.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=$PATH_SEPARATOR; export CDPATH; } + + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# +ac_default_prefix=/usr/local +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +# Identity of this package. +PACKAGE_NAME='PUPA' +PACKAGE_TARNAME='pupa' +PACKAGE_VERSION='0.6' +PACKAGE_STRING='PUPA 0.6' +PACKAGE_BUGREPORT='okuji@enbug.org' + +ac_unique_file="include/pupa/dl.h" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_STAT_H +# include +#endif +#if STDC_HEADERS +# include +# include +#else +# if HAVE_STDLIB_H +# include +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include +# endif +# include +#endif +#if HAVE_STRINGS_H +# include +#endif +#if HAVE_INTTYPES_H +# include +#else +# if HAVE_STDINT_H +# include +# endif +#endif +#if HAVE_UNISTD_H +# include +#endif" + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +ac_prev= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_option in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "enable_$ac_feature='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "with_$ac_package='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval "with_$ac_package=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_confdir=`(dirname "$0") 2>/dev/null || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } + else + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } + fi +fi +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CC_set=${CC+set} +ac_env_CC_value=$CC +ac_cv_env_CC_set=${CC+set} +ac_cv_env_CC_value=$CC +ac_env_CFLAGS_set=${CFLAGS+set} +ac_env_CFLAGS_value=$CFLAGS +ac_cv_env_CFLAGS_set=${CFLAGS+set} +ac_cv_env_CFLAGS_value=$CFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS +ac_env_CPP_set=${CPP+set} +ac_env_CPP_value=$CPP +ac_cv_env_CPP_set=${CPP+set} +ac_cv_env_CPP_value=$CPP + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures PUPA 0.6 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +_ACEOF + + cat <<_ACEOF +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data [PREFIX/share] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --infodir=DIR info documentation [PREFIX/info] + --mandir=DIR man documentation [PREFIX/man] +_ACEOF + + cat <<\_ACEOF + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of PUPA 0.6:";; + esac + cat <<\_ACEOF + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have + headers in a nonstandard directory + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +_ACEOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d $ac_dir || continue + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac +# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be +# absolute. +ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` +ac_abs_top_builddir=`cd "$ac_dir" && cd $ac_top_builddir && pwd` +ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` +ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + + cd $ac_dir + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_srcdir/configure.gnu; then + echo + $SHELL $ac_srcdir/configure.gnu --help=recursive + elif test -f $ac_srcdir/configure; then + echo + $SHELL $ac_srcdir/configure --help=recursive + elif test -f $ac_srcdir/configure.ac || + test -f $ac_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi + cd $ac_popdir + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\_ACEOF +PUPA configure 0.6 +generated by GNU Autoconf 2.53 + +Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 +Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit 0 +fi +exec 5>config.log +cat >&5 <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by PUPA $as_me 0.6, which was +generated by GNU Autoconf 2.53. Invocation command line was + + $ $0 $@ + +_ACEOF +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell meta-characters. +ac_configure_args= +ac_sep= +for ac_arg +do + case $ac_arg in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n ) continue ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + continue ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + ac_sep=" " ;; + esac + # Get rid of the leading space. +done + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Be sure not to use single quotes in there, as some shells, +# such as our DU 5.0 friend, will then `close' the trap. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} + echo + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + sed "/^$/d" confdefs.h + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core core.* *.core && + rm -rf conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo >confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val="\$ac_cv_env_${ac_var}_value" + eval ac_new_val="\$ac_env_${ac_var}_value" + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + + + + + + + + + + + + + + + +ac_config_headers="$ac_config_headers config.h" + + +# Checks for build and host systems. +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f $ac_dir/shtool; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 +echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} + { (exit 1); exit 1; }; } +fi +ac_config_guess="$SHELL $ac_aux_dir/config.guess" +ac_config_sub="$SHELL $ac_aux_dir/config.sub" +ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. + +# Make sure we can run config.sub. +$ac_config_sub sun4 >/dev/null 2>&1 || + { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5 +echo "$as_me: error: cannot run $ac_config_sub" >&2;} + { (exit 1); exit 1; }; } + +echo "$as_me:$LINENO: checking build system type" >&5 +echo $ECHO_N "checking build system type... $ECHO_C" >&6 +if test "${ac_cv_build+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_build_alias=$build_alias +test -z "$ac_cv_build_alias" && + ac_cv_build_alias=`$ac_config_guess` +test -z "$ac_cv_build_alias" && + { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 +echo "$as_me: error: cannot guess build type; you must specify one" >&2;} + { (exit 1); exit 1; }; } +ac_cv_build=`$ac_config_sub $ac_cv_build_alias` || + { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5 +echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +echo "$as_me:$LINENO: result: $ac_cv_build" >&5 +echo "${ECHO_T}$ac_cv_build" >&6 +build=$ac_cv_build +build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + + +echo "$as_me:$LINENO: checking host system type" >&5 +echo $ECHO_N "checking host system type... $ECHO_C" >&6 +if test "${ac_cv_host+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_host_alias=$host_alias +test -z "$ac_cv_host_alias" && + ac_cv_host_alias=$ac_cv_build_alias +ac_cv_host=`$ac_config_sub $ac_cv_host_alias` || + { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5 +echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +echo "$as_me:$LINENO: result: $ac_cv_host" >&5 +echo "${ECHO_T}$ac_cv_host" >&6 +host=$ac_cv_host +host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + + + +case "$host_cpu" in + i[3456]86) host_cpu=i386 ;; + *) { { echo "$as_me:$LINENO: error: unsupported CPU type" >&5 +echo "$as_me: error: unsupported CPU type" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +case "$host_cpu"-"$host_vendor" in + i386-*) host_vendor=pc ;; + *) { { echo "$as_me:$LINENO: error: unsupported machine type" >&5 +echo "$as_me: error: unsupported machine type" >&2;} + { (exit 1); exit 1; }; } ;; +esac + + + + +# Checks for programs. +if test "x$CFLAGS" = x; then + default_CFLAGS=yes +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$as_dir/$ac_word" ${1+"$@"} + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CC" && break +done + + CC=$ac_ct_CC +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH" >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH" >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +echo "$as_me:$LINENO: checking for C compiler default output" >&5 +echo $ECHO_N "checking for C compiler default output... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. + +# Be careful to initialize this variable, since it used to be cached. +# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. +ac_cv_exeext= +for ac_file in `ls a_out.exe a.exe conftest.exe 2>/dev/null; + ls a.out conftest 2>/dev/null; + ls a.* conftest.* 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.o | *.obj | *.xcoff | *.tds | *.d | *.pdb | *.xSYM ) ;; + a.out ) # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool --akim. + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables" >&5 +echo "$as_me: error: C compiler cannot create executables" >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +rm -f a.out a.exe conftest$ac_cv_exeext +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 + +echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in `(ls conftest.exe; ls conftest; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.o | *.obj | *.xcoff | *.tds | *.d | *.pdb ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link" >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link" >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile" >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile" >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_compiler_gnu=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +CFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_prog_cc_g=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +# Some people use a C++ compiler to compile C. Since we use `exit', +# in C++ we need to declare it. In case someone uses the same compiler +# for both compiling C and C++ we need to have the C++ compiler decide +# the declaration of exit, since it's the most demanding environment. +cat >conftest.$ac_ext <<_ACEOF +#ifndef __cplusplus + choke me +#endif +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + for ac_declaration in \ + ''\ + '#include ' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include +$ac_declaration +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +continue +fi +rm -f conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_declaration +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +fi +rm -f conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Must be GCC. +test "x$GCC" = xyes || { { echo "$as_me:$LINENO: error: GCC is required" >&5 +echo "$as_me: error: GCC is required" >&2;} + { (exit 1); exit 1; }; } + +if test "x$default_CFLAGS" = xyes; then + # debug flags. + tmp_CFLAGS="-Wall -W -g" + + # optimization flags. + echo "$as_me:$LINENO: checking whether optimization for size works" >&5 +echo $ECHO_N "checking whether optimization for size works... $ECHO_C" >&6 +if test "${size_flag+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + CFLAGS=-Os + +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + size_flag=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +size_flag=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext + +fi +echo "$as_me:$LINENO: result: $size_flag" >&5 +echo "${ECHO_T}$size_flag" >&6 + if test "x$size_flag" = xyes; then + tmp_CFLAGS="$tmp_CFLAGS -Os" + else + tmp_CFLAGS="$tmp_CFLAGS -O2 -fno-strength-reduce -fno-unroll-loops" + fi + + # Force no alignment to save space on i386. + if test "x$host_cpu" = xi386; then + echo "$as_me:$LINENO: checking whether -falign-loops works" >&5 +echo $ECHO_N "checking whether -falign-loops works... $ECHO_C" >&6 +if test "${falign_loop_flag+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + CFLAGS="-falign-loops=1" + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + falign_loop_flag=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +falign_loop_flag=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext + +fi +echo "$as_me:$LINENO: result: $falign_loop_flag" >&5 +echo "${ECHO_T}$falign_loop_flag" >&6 + + if test "x$falign_loop_flag" = xyes; then + tmp_CFLAGS="$tmp_CFLAGS -falign-jumps=1 -falign-loops=1 -falign-functions=1" + else + tmp_CFLAGS="$tmp_CFLAGS -malign-jumps=1 -malign-loops=1 -malign-functions=1" + fi + fi + + CFLAGS="$tmp_CFLAGS" +fi + + +# Defined in aclocal.m4. + +echo "$as_me:$LINENO: checking if C symbols get an underscore after compilation" >&5 +echo $ECHO_N "checking if C symbols get an underscore after compilation... $ECHO_C" >&6 +if test "${pupa_cv_asm_uscore+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat > conftest.c <<\EOF +int +func (int *list) +{ + *list = 0; + return *list; +} +EOF + +if { ac_try='${CC-cc} ${CFLAGS} -S conftest.c' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && test -s conftest.s; then + true +else + { { echo "$as_me:$LINENO: error: ${CC-cc} failed to produce assembly code" >&5 +echo "$as_me: error: ${CC-cc} failed to produce assembly code" >&2;} + { (exit 1); exit 1; }; } +fi + +if grep _func conftest.s >/dev/null 2>&1; then + pupa_cv_asm_uscore=yes +else + pupa_cv_asm_uscore=no +fi + +rm -f conftest* +fi + + +if test "x$pupa_cv_asm_uscore" = xyes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_ASM_USCORE $pupa_cv_asm_uscore +_ACEOF + +fi + +echo "$as_me:$LINENO: result: $pupa_cv_asm_uscore" >&5 +echo "${ECHO_T}$pupa_cv_asm_uscore" >&6 + + +echo "$as_me:$LINENO: checking if start is defined by the compiler" >&5 +echo $ECHO_N "checking if start is defined by the compiler... $ECHO_C" >&6 +if test "${pupa_cv_check_start_symbol+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +asm ("incl start") + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + pupa_cv_check_start_symbol=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +pupa_cv_check_start_symbol=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi + + +echo "$as_me:$LINENO: result: $pupa_cv_check_start_symbol" >&5 +echo "${ECHO_T}$pupa_cv_check_start_symbol" >&6 + +echo "$as_me:$LINENO: checking if _start is defined by the compiler" >&5 +echo $ECHO_N "checking if _start is defined by the compiler... $ECHO_C" >&6 +if test "${pupa_cv_check_uscore_start_symbol+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +asm ("incl _start") + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + pupa_cv_check_uscore_start_symbol=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +pupa_cv_check_uscore_start_symbol=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi + + +echo "$as_me:$LINENO: result: $pupa_cv_check_uscore_start_symbol" >&5 +echo "${ECHO_T}$pupa_cv_check_uscore_start_symbol" >&6 + + + + +if test "x$pupa_cv_check_start_symbol" = xyes; then + cat >>confdefs.h <<\_ACEOF +#define START_SYMBOL start +_ACEOF + +elif test "x$pupa_cv_check_uscore_start_symbol" = xyes; then + cat >>confdefs.h <<\_ACEOF +#define START_SYMBOL _start +_ACEOF + +else + { { echo "$as_me:$LINENO: error: neither start nor _start is defined" >&5 +echo "$as_me: error: neither start nor _start is defined" >&2;} + { (exit 1); exit 1; }; } +fi + + +echo "$as_me:$LINENO: checking if __bss_start is defined by the compiler" >&5 +echo $ECHO_N "checking if __bss_start is defined by the compiler... $ECHO_C" >&6 +if test "${pupa_cv_check_uscore_uscore_bss_start_symbol+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +asm ("incl __bss_start") + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + pupa_cv_check_uscore_uscore_bss_start_symbol=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +pupa_cv_check_uscore_uscore_bss_start_symbol=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi + + +echo "$as_me:$LINENO: result: $pupa_cv_check_uscore_uscore_bss_start_symbol" >&5 +echo "${ECHO_T}$pupa_cv_check_uscore_uscore_bss_start_symbol" >&6 + +echo "$as_me:$LINENO: checking if edata is defined by the compiler" >&5 +echo $ECHO_N "checking if edata is defined by the compiler... $ECHO_C" >&6 +if test "${pupa_cv_check_edata_symbol+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +asm ("incl edata") + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + pupa_cv_check_edata_symbol=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +pupa_cv_check_edata_symbol=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi + + +echo "$as_me:$LINENO: result: $pupa_cv_check_edata_symbol" >&5 +echo "${ECHO_T}$pupa_cv_check_edata_symbol" >&6 + +echo "$as_me:$LINENO: checking if _edata is defined by the compiler" >&5 +echo $ECHO_N "checking if _edata is defined by the compiler... $ECHO_C" >&6 +if test "${pupa_cv_check_uscore_edata_symbol+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +asm ("incl _edata") + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + pupa_cv_check_uscore_edata_symbol=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +pupa_cv_check_uscore_edata_symbol=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi + + +echo "$as_me:$LINENO: result: $pupa_cv_check_uscore_edata_symbol" >&5 +echo "${ECHO_T}$pupa_cv_check_uscore_edata_symbol" >&6 + + + + +if test "x$pupa_cv_check_uscore_uscore_bss_start_symbol" = xyes; then + cat >>confdefs.h <<\_ACEOF +#define BSS_START_SYMBOL __bss_start +_ACEOF + +elif test "x$pupa_cv_check_edata_symbol" = xyes; then + cat >>confdefs.h <<\_ACEOF +#define BSS_START_SYMBOL edata +_ACEOF + +elif test "x$pupa_cv_check_uscore_edata_symbol" = xyes; then + cat >>confdefs.h <<\_ACEOF +#define BSS_START_SYMBOL _edata +_ACEOF + +else + { { echo "$as_me:$LINENO: error: none of __bss_start, edata or _edata is defined" >&5 +echo "$as_me: error: none of __bss_start, edata or _edata is defined" >&2;} + { (exit 1); exit 1; }; } +fi + + +echo "$as_me:$LINENO: checking if end is defined by the compiler" >&5 +echo $ECHO_N "checking if end is defined by the compiler... $ECHO_C" >&6 +if test "${pupa_cv_check_end_symbol+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +asm ("incl end") + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + pupa_cv_check_end_symbol=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +pupa_cv_check_end_symbol=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi + + +echo "$as_me:$LINENO: result: $pupa_cv_check_end_symbol" >&5 +echo "${ECHO_T}$pupa_cv_check_end_symbol" >&6 + +echo "$as_me:$LINENO: checking if _end is defined by the compiler" >&5 +echo $ECHO_N "checking if _end is defined by the compiler... $ECHO_C" >&6 +if test "${pupa_cv_check_uscore_end_symbol+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +asm ("incl _end") + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + pupa_cv_check_uscore_end_symbol=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +pupa_cv_check_uscore_end_symbol=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi + + +echo "$as_me:$LINENO: result: $pupa_cv_check_uscore_end_symbol" >&5 +echo "${ECHO_T}$pupa_cv_check_uscore_end_symbol" >&6 + + + + +if test "x$pupa_cv_check_end_symbol" = xyes; then + cat >>confdefs.h <<\_ACEOF +#define END_SYMBOL end +_ACEOF + +elif test "x$pupa_cv_check_uscore_end_symbol" = xyes; then + cat >>confdefs.h <<\_ACEOF +#define END_SYMBOL _end +_ACEOF + +else + { { echo "$as_me:$LINENO: error: neither end nor _end is defined" >&5 +echo "$as_me: error: neither end nor _end is defined" >&2;} + { (exit 1); exit 1; }; } +fi + + +if test "x$host_cpu" = xi386; then + +echo "$as_me:$LINENO: checking whether addr32 must be in the same line as the instruction" >&5 +echo $ECHO_N "checking whether addr32 must be in the same line as the instruction... $ECHO_C" >&6 +if test "${pupa_cv_i386_asm_prefix_requirement+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat > conftest.s <<\EOF + .code16 +l1: addr32 movb %al, l1 +EOF + +if { ac_try='${CC-cc} ${CFLAGS} -c conftest.s' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && test -s conftest.o; then + pupa_cv_i386_asm_prefix_requirement=yes +else + pupa_cv_i386_asm_prefix_requirement=no +fi + +rm -f conftest* +fi + + +if test "x$pupa_cv_i386_asm_prefix_requirement" = xyes; then + pupa_tmp_addr32="addr32" + pupa_tmp_data32="data32" +else + pupa_tmp_addr32="addr32;" + pupa_tmp_data32="data32;" +fi + + +cat >>confdefs.h <<_ACEOF +#define ADDR32 $pupa_tmp_addr32 +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define DATA32 $pupa_tmp_data32 +_ACEOF + + +echo "$as_me:$LINENO: result: $pupa_cv_i386_asm_prefix_requirement" >&5 +echo "${ECHO_T}$pupa_cv_i386_asm_prefix_requirement" >&6 + + +echo "$as_me:$LINENO: checking for .code16 addr32 assembler support" >&5 +echo $ECHO_N "checking for .code16 addr32 assembler support... $ECHO_C" >&6 +if test "${pupa_cv_i386_asm_addr32+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat > conftest.s.in <<\EOF + .code16 +l1: @ADDR32@ movb %al, l1 +EOF + +if test "x$pupa_cv_i386_asm_prefix_requirement" = xyes; then + sed -e s/@ADDR32@/addr32/ < conftest.s.in > conftest.s +else + sed -e s/@ADDR32@/addr32\;/ < conftest.s.in > conftest.s +fi + +if { ac_try='${CC-cc} ${CFLAGS} -c conftest.s' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && test -s conftest.o; then + pupa_cv_i386_asm_addr32=yes +else + pupa_cv_i386_asm_addr32=no +fi + +rm -f conftest* +fi + + +echo "$as_me:$LINENO: result: $pupa_cv_i386_asm_addr32" >&5 +echo "${ECHO_T}$pupa_cv_i386_asm_addr32" >&6 + +echo "$as_me:$LINENO: checking whether an absolute indirect call/jump must not be prefixed with an asterisk" >&5 +echo $ECHO_N "checking whether an absolute indirect call/jump must not be prefixed with an asterisk... $ECHO_C" >&6 +if test "${pupa_cv_i386_asm_absolute_without_asterisk+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat > conftest.s <<\EOF + lcall *(offset) +offset: + .long 0 + .word 0 +EOF + +if { ac_try='${CC-cc} ${CFLAGS} -c conftest.s' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && test -s conftest.o; then + pupa_cv_i386_asm_absolute_without_asterisk=no +else + pupa_cv_i386_asm_absolute_without_asterisk=yes +fi + +rm -f conftest* +fi + + +if test "x$pupa_cv_i386_asm_absolute_without_asterisk" = xyes; then + +cat >>confdefs.h <<\_ACEOF +#define ABSOLUTE_WITHOUT_ASTERISK 1 +_ACEOF + +fi + +echo "$as_me:$LINENO: result: $pupa_cv_i386_asm_absolute_without_asterisk" >&5 +echo "${ECHO_T}$pupa_cv_i386_asm_absolute_without_asterisk" >&6 +fi + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL=$ac_install_sh + fi +fi +echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \${MAKE}" >&5 +echo $ECHO_N "checking whether ${MAKE-make} sets \${MAKE}... $ECHO_C" >&6 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'` +if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.make <<\_ACEOF +all: + @echo 'ac_maketemp="${MAKE}"' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftest.make +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + SET_MAKE= +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objcopy", so it can be a program name with args. +set dummy ${ac_tool_prefix}objcopy; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_OBJCOPY+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$OBJCOPY"; then + ac_cv_prog_OBJCOPY="$OBJCOPY" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJCOPY="${ac_tool_prefix}objcopy" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +OBJCOPY=$ac_cv_prog_OBJCOPY +if test -n "$OBJCOPY"; then + echo "$as_me:$LINENO: result: $OBJCOPY" >&5 +echo "${ECHO_T}$OBJCOPY" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_OBJCOPY"; then + ac_ct_OBJCOPY=$OBJCOPY + # Extract the first word of "objcopy", so it can be a program name with args. +set dummy objcopy; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_OBJCOPY+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_OBJCOPY"; then + ac_cv_prog_ac_ct_OBJCOPY="$ac_ct_OBJCOPY" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJCOPY="objcopy" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_OBJCOPY=$ac_cv_prog_ac_ct_OBJCOPY +if test -n "$ac_ct_OBJCOPY"; then + echo "$as_me:$LINENO: result: $ac_ct_OBJCOPY" >&5 +echo "${ECHO_T}$ac_ct_OBJCOPY" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + OBJCOPY=$ac_ct_OBJCOPY +else + OBJCOPY="$ac_cv_prog_OBJCOPY" +fi + +echo "$as_me:$LINENO: checking whether ${OBJCOPY} works for absolute addresses" >&5 +echo $ECHO_N "checking whether ${OBJCOPY} works for absolute addresses... $ECHO_C" >&6 +if test "${pupa_cv_prog_objcopy_absolute+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat > conftest.c <<\EOF +void +cmain (void) +{ + *((int *) 0x1000) = 2; +} +EOF + +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest.o; then : +else + { { echo "$as_me:$LINENO: error: ${CC-cc} cannot compile C source code" >&5 +echo "$as_me: error: ${CC-cc} cannot compile C source code" >&2;} + { (exit 1); exit 1; }; } +fi +pupa_cv_prog_objcopy_absolute=yes +for link_addr in 2000 8000 7C00; do + if { ac_try='${CC-cc} ${CFLAGS} -nostdlib -Wl,-N -Wl,-Ttext -Wl,$link_addr conftest.o -o conftest.exec' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then : + else + { { echo "$as_me:$LINENO: error: ${CC-cc} cannot link at address $link_addr" >&5 +echo "$as_me: error: ${CC-cc} cannot link at address $link_addr" >&2;} + { (exit 1); exit 1; }; } + fi + if { ac_try='${OBJCOPY-objcopy} -O binary conftest.exec conftest' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then : + else + { { echo "$as_me:$LINENO: error: ${OBJCOPY-objcopy} cannot create binary files" >&5 +echo "$as_me: error: ${OBJCOPY-objcopy} cannot create binary files" >&2;} + { (exit 1); exit 1; }; } + fi + if test ! -f conftest.old || { ac_try='cmp -s conftest.old conftest' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + mv -f conftest conftest.old + else + pupa_cv_prog_objcopy_absolute=no + break + fi +done +rm -f conftest* +fi + +echo "$as_me:$LINENO: result: $pupa_cv_prog_objcopy_absolute" >&5 +echo "${ECHO_T}$pupa_cv_prog_objcopy_absolute" >&6 + +if test "x$pupa_cv_prog_objcopy_absolute" = xno; then + { { echo "$as_me:$LINENO: error: PUPA requires a working absolute objcopy; upgrade your binutils" >&5 +echo "$as_me: error: PUPA requires a working absolute objcopy; upgrade your binutils" >&2;} + { (exit 1); exit 1; }; } +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + echo "$as_me:$LINENO: result: $STRIP" >&5 +echo "${ECHO_T}$STRIP" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 +echo "${ECHO_T}$ac_ct_STRIP" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + STRIP=$ac_ct_STRIP +else + STRIP="$ac_cv_prog_STRIP" +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nm", so it can be a program name with args. +set dummy ${ac_tool_prefix}nm; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_NM+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$NM"; then + ac_cv_prog_NM="$NM" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_NM="${ac_tool_prefix}nm" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +NM=$ac_cv_prog_NM +if test -n "$NM"; then + echo "$as_me:$LINENO: result: $NM" >&5 +echo "${ECHO_T}$NM" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_NM"; then + ac_ct_NM=$NM + # Extract the first word of "nm", so it can be a program name with args. +set dummy nm; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_NM+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_NM"; then + ac_cv_prog_ac_ct_NM="$ac_ct_NM" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_NM="nm" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_NM=$ac_cv_prog_ac_ct_NM +if test -n "$ac_ct_NM"; then + echo "$as_me:$LINENO: result: $ac_ct_NM" >&5 +echo "${ECHO_T}$ac_ct_NM" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + NM=$ac_ct_NM +else + NM="$ac_cv_prog_NM" +fi + + +# This is not a "must". +# Extract the first word of "ruby", so it can be a program name with args. +set dummy ruby; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_RUBY+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $RUBY in + [\\/]* | ?:[\\/]*) + ac_cv_path_RUBY="$RUBY" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_RUBY="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + ;; +esac +fi +RUBY=$ac_cv_path_RUBY + +if test -n "$RUBY"; then + echo "$as_me:$LINENO: result: $RUBY" >&5 +echo "${ECHO_T}$RUBY" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + +# For cross-compiling. +if test "x$build" = "x$host"; then + BUILD_CC="$CC" + +else + for ac_prog in gcc egcs cc +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_BUILD_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$BUILD_CC"; then + ac_cv_prog_BUILD_CC="$BUILD_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_BUILD_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +BUILD_CC=$ac_cv_prog_BUILD_CC +if test -n "$BUILD_CC"; then + echo "$as_me:$LINENO: result: $BUILD_CC" >&5 +echo "${ECHO_T}$BUILD_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$BUILD_CC" && break +done +test -n "$BUILD_CC" || BUILD_CC="{ { echo "$as_me:$LINENO: error: none of gcc, egcs and cc is found. set BUILD_CC manually." >&5 +echo "$as_me: error: none of gcc, egcs and cc is found. set BUILD_CC manually." >&2;} + { (exit 1); exit 1; }; }" + +fi + +# Test the C compiler for the build environment. +pupa_tmp_CC="$CC" +CC="$BUILD_CC" +echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 +echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6 +if test "${ac_cv_c_bigendian+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # See if sys/param.h defines the BYTE_ORDER macro. +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include +#include + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN + bogus endian macros +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + # It does; now see whether it defined to BIG_ENDIAN or not. +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include +#include + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_bigendian=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_c_bigendian=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +# It does not; compile a test program. +if test "$cross_compiling" = yes; then + # try to guess the endianess by grep'ing values into an object file + ac_cv_c_bigendian=unknown + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; +short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; +void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; } +short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; +short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; +void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; } +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ + _ascii (); _ebcdic (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + if fgrep BIGenDianSyS conftest.$ac_objext >/dev/null ; then + ac_cv_c_bigendian=yes +fi +if fgrep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi +fi +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +fi +rm -f conftest.$ac_objext conftest.$ac_ext +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +int +main () +{ + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long l; + char c[sizeof (long)]; + } u; + u.l = 1; + exit (u.c[sizeof (long) - 1] == 1); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_bigendian=no +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +( exit $ac_status ) +ac_cv_c_bigendian=yes +fi +rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 +echo "${ECHO_T}$ac_cv_c_bigendian" >&6 +case $ac_cv_c_bigendian in + yes) + +cat >>confdefs.h <<\_ACEOF +#define WORDS_BIGENDIAN 1 +_ACEOF + ;; + no) + ;; + *) + { { echo "$as_me:$LINENO: error: unknown endianess +presetting ac_cv_c_bigendian=no (or yes) will help" >&5 +echo "$as_me: error: unknown endianess +presetting ac_cv_c_bigendian=no (or yes) will help" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6 +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check" >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include +#include +#include +#include + +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_header_stdc=no +fi +rm -f conftest.err conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + exit(2); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6 +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +eval "$as_ac_Header=no" +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +echo "$as_me:$LINENO: checking for void *" >&5 +echo $ECHO_N "checking for void *... $ECHO_C" >&6 +if test "${ac_cv_type_void_p+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_includes_default +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +if ((void * *) 0) + return 0; +if (sizeof (void *)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_void_p=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_type_void_p=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_void_p" >&5 +echo "${ECHO_T}$ac_cv_type_void_p" >&6 + +echo "$as_me:$LINENO: checking size of void *" >&5 +echo $ECHO_N "checking size of void *... $ECHO_C" >&6 +if test "${ac_cv_sizeof_void_p+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$ac_cv_type_void_p" = yes; then + # The cast to unsigned long works around a bug in the HP C Compiler + # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects + # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. + # This bug is HP SR number 8606223364. + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_includes_default +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (void *))) >= 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=0 ac_mid=0 + while :; do + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_includes_default +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (void *))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_lo=`expr $ac_mid + 1` + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid + 1` +fi +rm -f conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_includes_default +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (void *))) < 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=-1 ac_mid=-1 + while :; do + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_includes_default +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (void *))) >= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_hi=`expr '(' $ac_mid ')' - 1` + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid` +fi +rm -f conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_lo= ac_hi= +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_includes_default +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (void *))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_lo=`expr '(' $ac_mid ')' + 1` +fi +rm -f conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in +?*) ac_cv_sizeof_void_p=$ac_lo;; +'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (void *), 77" >&5 +echo "$as_me: error: cannot compute sizeof (void *), 77" >&2;} + { (exit 1); exit 1; }; } ;; +esac +else + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling" >&5 +echo "$as_me: error: cannot run test program while cross compiling" >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_includes_default +long longval () { return (long) (sizeof (void *)); } +unsigned long ulongval () { return (long) (sizeof (void *)); } +#include +#include +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + exit (1); + if (((long) (sizeof (void *))) < 0) + { + long i = longval (); + if (i != ((long) (sizeof (void *)))) + exit (1); + fprintf (f, "%ld\n", i); + } + else + { + unsigned long i = ulongval (); + if (i != ((long) (sizeof (void *)))) + exit (1); + fprintf (f, "%lu\n", i); + } + exit (ferror (f) || fclose (f) != 0); + + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sizeof_void_p=`cat conftest.val` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +( exit $ac_status ) +{ { echo "$as_me:$LINENO: error: cannot compute sizeof (void *), 77" >&5 +echo "$as_me: error: cannot compute sizeof (void *), 77" >&2;} + { (exit 1); exit 1; }; } +fi +rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +rm -f conftest.val +else + ac_cv_sizeof_void_p=0 +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_sizeof_void_p" >&5 +echo "${ECHO_T}$ac_cv_sizeof_void_p" >&6 +cat >>confdefs.h <<_ACEOF +#define SIZEOF_VOID_P $ac_cv_sizeof_void_p +_ACEOF + + +echo "$as_me:$LINENO: checking for long" >&5 +echo $ECHO_N "checking for long... $ECHO_C" >&6 +if test "${ac_cv_type_long+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_includes_default +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +if ((long *) 0) + return 0; +if (sizeof (long)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_long=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_type_long=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_long" >&5 +echo "${ECHO_T}$ac_cv_type_long" >&6 + +echo "$as_me:$LINENO: checking size of long" >&5 +echo $ECHO_N "checking size of long... $ECHO_C" >&6 +if test "${ac_cv_sizeof_long+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$ac_cv_type_long" = yes; then + # The cast to unsigned long works around a bug in the HP C Compiler + # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects + # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. + # This bug is HP SR number 8606223364. + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_includes_default +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (long))) >= 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=0 ac_mid=0 + while :; do + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_includes_default +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (long))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_lo=`expr $ac_mid + 1` + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid + 1` +fi +rm -f conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_includes_default +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (long))) < 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=-1 ac_mid=-1 + while :; do + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_includes_default +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (long))) >= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_hi=`expr '(' $ac_mid ')' - 1` + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid` +fi +rm -f conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_lo= ac_hi= +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_includes_default +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (long))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_lo=`expr '(' $ac_mid ')' + 1` +fi +rm -f conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in +?*) ac_cv_sizeof_long=$ac_lo;; +'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (long), 77" >&5 +echo "$as_me: error: cannot compute sizeof (long), 77" >&2;} + { (exit 1); exit 1; }; } ;; +esac +else + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling" >&5 +echo "$as_me: error: cannot run test program while cross compiling" >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_includes_default +long longval () { return (long) (sizeof (long)); } +unsigned long ulongval () { return (long) (sizeof (long)); } +#include +#include +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + exit (1); + if (((long) (sizeof (long))) < 0) + { + long i = longval (); + if (i != ((long) (sizeof (long)))) + exit (1); + fprintf (f, "%ld\n", i); + } + else + { + unsigned long i = ulongval (); + if (i != ((long) (sizeof (long)))) + exit (1); + fprintf (f, "%lu\n", i); + } + exit (ferror (f) || fclose (f) != 0); + + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sizeof_long=`cat conftest.val` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +( exit $ac_status ) +{ { echo "$as_me:$LINENO: error: cannot compute sizeof (long), 77" >&5 +echo "$as_me: error: cannot compute sizeof (long), 77" >&2;} + { (exit 1); exit 1; }; } +fi +rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +rm -f conftest.val +else + ac_cv_sizeof_long=0 +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_sizeof_long" >&5 +echo "${ECHO_T}$ac_cv_sizeof_long" >&6 +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG $ac_cv_sizeof_long +_ACEOF + + +CC="$pupa_tmp_CC" + +# Output files. +ac_config_links="$ac_config_links include/pupa/cpu:include/pupa/$host_cpu include/pupa/machine:include/pupa/$host_cpu/$host_vendor" + +ac_config_files="$ac_config_files Makefile" + +ac_config_files="$ac_config_files stamp-h" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overriden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +{ + (set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +if cmp -s $cache_file confcache; then :; else + if test -w $cache_file; then + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' +fi + +DEFS=-DHAVE_CONFIG_H + + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi + +# NLS nuisances. +# Support unset when possible. +if (FOO=FOO; unset FOO) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + +(set +x; test -n "`(LANG=C; export LANG) 2>&1`") && + { $as_unset LANG || test "${LANG+set}" != set; } || + { LANG=C; export LANG; } +(set +x; test -n "`(LC_ALL=C; export LC_ALL) 2>&1`") && + { $as_unset LC_ALL || test "${LC_ALL+set}" != set; } || + { LC_ALL=C; export LC_ALL; } +(set +x; test -n "`(LC_TIME=C; export LC_TIME) 2>&1`") && + { $as_unset LC_TIME || test "${LC_TIME+set}" != set; } || + { LC_TIME=C; export LC_TIME; } +(set +x; test -n "`(LC_CTYPE=C; export LC_CTYPE) 2>&1`") && + { $as_unset LC_CTYPE || test "${LC_CTYPE+set}" != set; } || + { LC_CTYPE=C; export LC_CTYPE; } +(set +x; test -n "`(LANGUAGE=C; export LANGUAGE) 2>&1`") && + { $as_unset LANGUAGE || test "${LANGUAGE+set}" != set; } || + { LANGUAGE=C; export LANGUAGE; } +(set +x; test -n "`(LC_COLLATE=C; export LC_COLLATE) 2>&1`") && + { $as_unset LC_COLLATE || test "${LC_COLLATE+set}" != set; } || + { LC_COLLATE=C; export LC_COLLATE; } +(set +x; test -n "`(LC_NUMERIC=C; export LC_NUMERIC) 2>&1`") && + { $as_unset LC_NUMERIC || test "${LC_NUMERIC+set}" != set; } || + { LC_NUMERIC=C; export LC_NUMERIC; } +(set +x; test -n "`(LC_MESSAGES=C; export LC_MESSAGES) 2>&1`") && + { $as_unset LC_MESSAGES || test "${LC_MESSAGES+set}" != set; } || + { LC_MESSAGES=C; export LC_MESSAGES; } + + +# Name of the executable. +as_me=`(basename "$0") 2>/dev/null || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conftest.sh + echo "exit 0" >>conftest.sh + chmod +x conftest.sh + if (PATH=".;."; conftest.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conftest.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=$PATH_SEPARATOR; export CDPATH; } + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by PUPA $as_me 0.6, which was +generated by GNU Autoconf 2.53. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\_ACEOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration links: +$config_links + +Report bugs to ." +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +PUPA config.status 0.6 +configured by $0, generated by GNU Autoconf 2.53, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + +Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=$srcdir +INSTALL="$INSTALL" +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "x$1" : 'x\([^=]*\)='` + ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + shift + set dummy "$ac_option" "$ac_optarg" ${1+"$@"} + shift + ;; + -*);; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_need_defaults=false;; + esac + + case $1 in + # Handling of the options. +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running $SHELL $0 " $ac_configure_args " --no-create --no-recursion" + exec $SHELL $0 $ac_configure_args --no-create --no-recursion ;; +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + shift + CONFIG_FILES="$CONFIG_FILES $1" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + shift + CONFIG_HEADERS="$CONFIG_HEADERS $1" + ac_need_defaults=false;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +_ACEOF + + + + + +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "stamp-h" ) CONFIG_FILES="$CONFIG_FILES stamp-h" ;; + "include/pupa/cpu" ) CONFIG_LINKS="$CONFIG_LINKS include/pupa/cpu:include/pupa/$host_cpu" ;; + "include/pupa/machine" ) CONFIG_LINKS="$CONFIG_LINKS include/pupa/machine:include/pupa/$host_cpu/$host_vendor" ;; + "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_LINKS+set}" = set || CONFIG_LINKS=$config_links +fi + +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. +: ${TMPDIR=/tmp} +{ + tmp=`(umask 077 && mktemp -d -q "$TMPDIR/csXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=$TMPDIR/cs$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in $TMPDIR" >&2 + { (exit 1); exit 1; } +} + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "\$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF +s,@SHELL@,$SHELL,;t t +s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t +s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t +s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s,@exec_prefix@,$exec_prefix,;t t +s,@prefix@,$prefix,;t t +s,@program_transform_name@,$program_transform_name,;t t +s,@bindir@,$bindir,;t t +s,@sbindir@,$sbindir,;t t +s,@libexecdir@,$libexecdir,;t t +s,@datadir@,$datadir,;t t +s,@sysconfdir@,$sysconfdir,;t t +s,@sharedstatedir@,$sharedstatedir,;t t +s,@localstatedir@,$localstatedir,;t t +s,@libdir@,$libdir,;t t +s,@includedir@,$includedir,;t t +s,@oldincludedir@,$oldincludedir,;t t +s,@infodir@,$infodir,;t t +s,@mandir@,$mandir,;t t +s,@build_alias@,$build_alias,;t t +s,@host_alias@,$host_alias,;t t +s,@target_alias@,$target_alias,;t t +s,@DEFS@,$DEFS,;t t +s,@ECHO_C@,$ECHO_C,;t t +s,@ECHO_N@,$ECHO_N,;t t +s,@ECHO_T@,$ECHO_T,;t t +s,@LIBS@,$LIBS,;t t +s,@build@,$build,;t t +s,@build_cpu@,$build_cpu,;t t +s,@build_vendor@,$build_vendor,;t t +s,@build_os@,$build_os,;t t +s,@host@,$host,;t t +s,@host_cpu@,$host_cpu,;t t +s,@host_vendor@,$host_vendor,;t t +s,@host_os@,$host_os,;t t +s,@CC@,$CC,;t t +s,@CFLAGS@,$CFLAGS,;t t +s,@LDFLAGS@,$LDFLAGS,;t t +s,@CPPFLAGS@,$CPPFLAGS,;t t +s,@ac_ct_CC@,$ac_ct_CC,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t +s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t +s,@INSTALL_DATA@,$INSTALL_DATA,;t t +s,@SET_MAKE@,$SET_MAKE,;t t +s,@OBJCOPY@,$OBJCOPY,;t t +s,@ac_ct_OBJCOPY@,$ac_ct_OBJCOPY,;t t +s,@STRIP@,$STRIP,;t t +s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t +s,@NM@,$NM,;t t +s,@ac_ct_NM@,$ac_ct_NM,;t t +s,@RUBY@,$RUBY,;t t +s,@BUILD_CC@,$BUILD_CC,;t t +s,@CPP@,$CPP,;t t +CEOF + +_ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { case "$ac_dir" in + [\\/]* | ?:[\\/]* ) as_incr_dir=;; + *) as_incr_dir=.;; +esac +as_dummy="$ac_dir" +for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$@"`; do + case $as_mkdir_dir in + # Skip DOS drivespec + ?:) as_incr_dir=$as_mkdir_dir ;; + *) + as_incr_dir=$as_incr_dir/$as_mkdir_dir + test -d "$as_incr_dir" || + mkdir "$as_incr_dir" || + { { echo "$as_me:$LINENO: error: cannot create \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; } + ;; + esac +done; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac +# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be +# absolute. +ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` +ac_abs_top_builddir=`cd "$ac_dir" && cd $ac_top_builddir && pwd` +ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` +ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_builddir$INSTALL ;; + esac + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo $f;; + *) # Relative + if test -f "$f"; then + # Build tree + echo $f + elif test -f "$srcdir/$f"; then + # Source tree + echo $srcdir/$f + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;t t +s,@srcdir@,$ac_srcdir,;t t +s,@abs_srcdir@,$ac_abs_srcdir,;t t +s,@top_srcdir@,$ac_top_srcdir,;t t +s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t +s,@builddir@,$ac_builddir,;t t +s,@abs_builddir@,$ac_abs_builddir,;t t +s,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +s,@INSTALL@,$ac_INSTALL,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + + # Run the commands associated with the file. + case $ac_file in + stamp-h ) echo timestamp > stamp-h ;; + esac +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_HEADER section. +# + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='[ ].*$,\1#\2' +ac_dC=' ' +ac_dD=',;t' +# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='$,\1#\2define\3' +ac_uC=' ' +ac_uD=',;t' + +for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo $f;; + *) # Relative + if test -f "$f"; then + # Build tree + echo $f + elif test -f "$srcdir/$f"; then + # Source tree + echo $srcdir/$f + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } + # Remove the trailing spaces. + sed 's/[ ]*$//' $ac_file_inputs >$tmp/in + +_ACEOF + +# Transform confdefs.h into two sed scripts, `conftest.defines' and +# `conftest.undefs', that substitutes the proper values into +# config.h.in to produce config.h. The first handles `#define' +# templates, and the second `#undef' templates. +# And first: Protect against being on the right side of a sed subst in +# config.status. Protect against being in an unquoted here document +# in config.status. +rm -f conftest.defines conftest.undefs +# Using a here document instead of a string reduces the quoting nightmare. +# Putting comments in sed scripts is not portable. +# +# `end' is used to avoid that the second main sed command (meant for +# 0-ary CPP macros) applies to n-ary macro definitions. +# See the Autoconf documentation for `clear'. +cat >confdef2sed.sed <<\_ACEOF +s/[\\&,]/\\&/g +s,[\\$`],\\&,g +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp +t end +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp +: end +_ACEOF +# If some macros were called several times there might be several times +# the same #defines, which is useless. Nevertheless, we may not want to +# sort them, since we want the *last* AC-DEFINE to be honored. +uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines +sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs +rm -f confdef2sed.sed + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >>conftest.undefs <<\_ACEOF +s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, +_ACEOF + +# Break up conftest.defines because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS +echo ' if egrep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS +echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS +echo ' :' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.defines >/dev/null +do + # Write a limited-size here document to $tmp/defines.sed. + echo ' cat >$tmp/defines.sed <>$CONFIG_STATUS + # Speed up: don't consider the non `#define' lines. + echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/defines.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail + rm -f conftest.defines + mv conftest.tail conftest.defines +done +rm -f conftest.defines +echo ' fi # egrep' >>$CONFIG_STATUS +echo >>$CONFIG_STATUS + +# Break up conftest.undefs because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #undef templates' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.undefs >/dev/null +do + # Write a limited-size here document to $tmp/undefs.sed. + echo ' cat >$tmp/undefs.sed <>$CONFIG_STATUS + # Speed up: don't consider the non `#undef' + echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/undefs.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail + rm -f conftest.undefs + mv conftest.tail conftest.undefs +done +rm -f conftest.undefs + +cat >>$CONFIG_STATUS <<\_ACEOF + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + echo "/* Generated by configure. */" >$tmp/config.h + else + echo "/* $ac_file. Generated by configure. */" >$tmp/config.h + fi + cat $tmp/in >>$tmp/config.h + rm -f $tmp/in + if test x"$ac_file" != x-; then + if cmp -s $ac_file $tmp/config.h 2>/dev/null; then + { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} + else + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { case "$ac_dir" in + [\\/]* | ?:[\\/]* ) as_incr_dir=;; + *) as_incr_dir=.;; +esac +as_dummy="$ac_dir" +for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$@"`; do + case $as_mkdir_dir in + # Skip DOS drivespec + ?:) as_incr_dir=$as_mkdir_dir ;; + *) + as_incr_dir=$as_incr_dir/$as_mkdir_dir + test -d "$as_incr_dir" || + mkdir "$as_incr_dir" || + { { echo "$as_me:$LINENO: error: cannot create \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; } + ;; + esac +done; } + + rm -f $ac_file + mv $tmp/config.h $ac_file + fi + else + cat $tmp/config.h + rm -f $tmp/config.h + fi +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_LINKS section. +# + +for ac_file in : $CONFIG_LINKS; do test "x$ac_file" = x: && continue + ac_dest=`echo "$ac_file" | sed 's,:.*,,'` + ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` + + { echo "$as_me:$LINENO: linking $srcdir/$ac_source to $ac_dest" >&5 +echo "$as_me: linking $srcdir/$ac_source to $ac_dest" >&6;} + + if test ! -r $srcdir/$ac_source; then + { { echo "$as_me:$LINENO: error: $srcdir/$ac_source: file not found" >&5 +echo "$as_me: error: $srcdir/$ac_source: file not found" >&2;} + { (exit 1); exit 1; }; } + fi + rm -f $ac_dest + + # Make relative symlinks. + ac_dest_dir=`(dirname "$ac_dest") 2>/dev/null || +$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_dest" : 'X\(//\)[^/]' \| \ + X"$ac_dest" : 'X\(//\)$' \| \ + X"$ac_dest" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_dest" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { case "$ac_dest_dir" in + [\\/]* | ?:[\\/]* ) as_incr_dir=;; + *) as_incr_dir=.;; +esac +as_dummy="$ac_dest_dir" +for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$@"`; do + case $as_mkdir_dir in + # Skip DOS drivespec + ?:) as_incr_dir=$as_mkdir_dir ;; + *) + as_incr_dir=$as_incr_dir/$as_mkdir_dir + test -d "$as_incr_dir" || + mkdir "$as_incr_dir" || + { { echo "$as_me:$LINENO: error: cannot create \"$ac_dest_dir\"" >&5 +echo "$as_me: error: cannot create \"$ac_dest_dir\"" >&2;} + { (exit 1); exit 1; }; } + ;; + esac +done; } + + ac_builddir=. + +if test "$ac_dest_dir" != .; then + ac_dir_suffix=/`echo "$ac_dest_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac +# Don't blindly perform a `cd "$ac_dest_dir"/$ac_foo && pwd` since $ac_foo can be +# absolute. +ac_abs_builddir=`cd "$ac_dest_dir" && cd $ac_builddir && pwd` +ac_abs_top_builddir=`cd "$ac_dest_dir" && cd $ac_top_builddir && pwd` +ac_abs_srcdir=`cd "$ac_dest_dir" && cd $ac_srcdir && pwd` +ac_abs_top_srcdir=`cd "$ac_dest_dir" && cd $ac_top_srcdir && pwd` + + + case $srcdir in + [\\/$]* | ?:[\\/]* ) ac_rel_source=$srcdir/$ac_source ;; + *) ac_rel_source=$ac_top_builddir$srcdir/$ac_source ;; + esac + + # Make a symlink if possible; otherwise try a hard link. + ln -s $ac_rel_source $ac_dest 2>/dev/null || + ln $srcdir/$ac_source $ac_dest || + { { echo "$as_me:$LINENO: error: cannot link $ac_dest to $srcdir/$ac_source" >&5 +echo "$as_me: error: cannot link $ac_dest to $srcdir/$ac_source" >&2;} + { (exit 1); exit 1; }; } +done +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + exec 5>/dev/null + $SHELL $CONFIG_STATUS || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + diff --git a/configure.ac b/configure.ac new file mode 100644 index 000000000..524fc1420 --- /dev/null +++ b/configure.ac @@ -0,0 +1,124 @@ +# Process this file with autoconf to produce a configure script. + +# Copyright (C) 2002 Yoshinori K. Okuji +# +# This configure.ac is free software; the author +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +AC_INIT(PUPA, 0.6, [okuji@enbug.org]) +AC_PREREQ(2.53) +AC_CONFIG_SRCDIR([include/pupa/dl.h]) +AC_CONFIG_HEADER([config.h]) + +# Checks for build and host systems. +AC_CANONICAL_BUILD +AC_CANONICAL_HOST + +case "$host_cpu" in + i[[3456]]86) host_cpu=i386 ;; + *) AC_MSG_ERROR([unsupported CPU type]) ;; +esac + +case "$host_cpu"-"$host_vendor" in + i386-*) host_vendor=pc ;; + *) AC_MSG_ERROR([unsupported machine type]) ;; +esac + +AC_SUBST(host_cpu) +AC_SUBST(host_vendor) + +# Checks for programs. +if test "x$CFLAGS" = x; then + default_CFLAGS=yes +fi + +AC_PROG_CC + +# Must be GCC. +test "x$GCC" = xyes || AC_MSG_ERROR([GCC is required]) + +if test "x$default_CFLAGS" = xyes; then + # debug flags. + tmp_CFLAGS="-Wall -W -g" + + # optimization flags. + AC_CACHE_CHECK([whether optimization for size works], size_flag, [ + CFLAGS=-Os + AC_TRY_COMPILE(, , size_flag=yes, size_flag=no) + ]) + if test "x$size_flag" = xyes; then + tmp_CFLAGS="$tmp_CFLAGS -Os" + else + tmp_CFLAGS="$tmp_CFLAGS -O2 -fno-strength-reduce -fno-unroll-loops" + fi + + # Force no alignment to save space on i386. + if test "x$host_cpu" = xi386; then + AC_CACHE_CHECK([whether -falign-loops works], [falign_loop_flag], [ + CFLAGS="-falign-loops=1" + AC_TRY_COMPILE(, , [falign_loop_flag=yes], [falign_loop_flag=no]) + ]) + + if test "x$falign_loop_flag" = xyes; then + tmp_CFLAGS="$tmp_CFLAGS -falign-jumps=1 -falign-loops=1 -falign-functions=1" + else + tmp_CFLAGS="$tmp_CFLAGS -malign-jumps=1 -malign-loops=1 -malign-functions=1" + fi + fi + + CFLAGS="$tmp_CFLAGS" +fi +AC_SUBST(CFLAGS) + +# Defined in aclocal.m4. +pupa_ASM_USCORE +pupa_CHECK_START_SYMBOL +pupa_CHECK_BSS_START_SYMBOL +pupa_CHECK_END_SYMBOL + +if test "x$host_cpu" = xi386; then + pupa_I386_ASM_PREFIX_REQUIREMENT + pupa_I386_ASM_ADDR32 + pupa_I386_ASM_ABSOLUTE_WITHOUT_ASTERISK +fi + + +AC_PROG_INSTALL +AC_PROG_MAKE_SET +AC_CHECK_TOOL(OBJCOPY, objcopy) +pupa_PROG_OBJCOPY_ABSOLUTE +AC_CHECK_TOOL(STRIP, strip) +AC_CHECK_TOOL(NM, nm) + +# This is not a "must". +AC_PATH_PROG(RUBY, ruby) + +# For cross-compiling. +if test "x$build" = "x$host"; then + BUILD_CC="$CC" + AC_SUBST(BUILD_CC) +else + AC_CHECK_PROGS(BUILD_CC, [gcc egcs cc], + [AC_MSG_ERROR([none of gcc, egcs and cc is found. set BUILD_CC manually.])]) +fi + +# Test the C compiler for the build environment. +pupa_tmp_CC="$CC" +CC="$BUILD_CC" +AC_C_BIGENDIAN +AC_CHECK_SIZEOF(void *) +AC_CHECK_SIZEOF(long) +CC="$pupa_tmp_CC" + +# Output files. +AC_CONFIG_LINKS([include/pupa/cpu:include/pupa/$host_cpu + include/pupa/machine:include/pupa/$host_cpu/$host_vendor]) +AC_CONFIG_FILES([Makefile]) +AC_CONFIG_FILES([stamp-h], [echo timestamp > stamp-h]) +AC_OUTPUT diff --git a/disk/i386/pc/biosdisk.c b/disk/i386/pc/biosdisk.c new file mode 100644 index 000000000..af14c10fa --- /dev/null +++ b/disk/i386/pc/biosdisk.c @@ -0,0 +1,335 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc. + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Drive Parameters. */ +struct pupa_biosdisk_drp +{ + pupa_uint16_t size; + pupa_uint16_t flags; + pupa_uint32_t cylinders; + pupa_uint32_t heads; + pupa_uint32_t sectors; + pupa_uint64_t total_sectors; + pupa_uint16_t bytes_per_sector; + /* ver 2.0 or higher */ + pupa_uint32_t EDD_configuration_parameters; + /* ver 3.0 or higher */ + pupa_uint16_t signature_dpi; + pupa_uint8_t length_dpi; + pupa_uint8_t reserved[3]; + pupa_uint8_t name_of_host_bus[4]; + pupa_uint8_t name_of_interface_type[8]; + pupa_uint8_t interface_path[8]; + pupa_uint8_t device_path[8]; + pupa_uint8_t reserved2; + pupa_uint8_t checksum; + + /* XXX: This is necessary, because the BIOS of Thinkpad X20 + writes a garbage to the tail of drive parameters, + regardless of a size specified in a caller. */ + pupa_uint8_t dummy[16]; +} __attribute__ ((packed)); + +/* Disk Address Packet. */ +struct pupa_biosdisk_dap +{ + pupa_uint8_t length; + pupa_uint8_t reserved; + pupa_uint16_t blocks; + pupa_uint32_t buffer; + pupa_uint64_t block; +} __attribute__ ((packed)); + + +static int +pupa_biosdisk_get_drive (const char *name) +{ + unsigned long drive; + + if ((name[0] != 'f' && name[0] != 'h') || name[1] != 'd') + goto fail; + + drive = pupa_strtoul (name + 2, 0, 10); + if (pupa_errno != PUPA_ERR_NONE) + goto fail; + + if (name[0] == 'h') + drive += 0x80; + + return (int) drive ; + + fail: + pupa_error (PUPA_ERR_UNKNOWN_DEVICE, "not a biosdisk"); + return -1; +} + +static int +pupa_biosdisk_call_hook (int (*hook) (const char *name), int drive) +{ + char name[4]; + + pupa_sprintf (name, (drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80)); + return hook (name); +} + +static int +pupa_biosdisk_iterate (int (*hook) (const char *name)) +{ + int drive; + int num_floppies; + + /* For floppy disks, we can get the number safely. */ + num_floppies = pupa_biosdisk_get_num_floppies (); + for (drive = 0; drive < num_floppies; drive++) + if (pupa_biosdisk_call_hook (hook, drive)) + return 1; + + /* For hard disks, attempt to read the MBR. */ + for (drive = 0x80; drive < 0x88; drive++) + { + if (pupa_biosdisk_rw_standard (0x02, drive, 0, 0, 1, 1, + PUPA_MEMORY_MACHINE_SCRATCH_SEG) != 0) + break; + + if (pupa_biosdisk_call_hook (hook, drive)) + return 1; + } + + return 0; +} + +static pupa_err_t +pupa_biosdisk_open (const char *name, pupa_disk_t disk) +{ + unsigned long total_sectors = 0; + int drive; + struct pupa_biosdisk_data *data; + + drive = pupa_biosdisk_get_drive (name); + if (drive < 0) + return pupa_errno; + + disk->has_partitions = (drive & 0x80); + disk->id = drive; + + data = (struct pupa_biosdisk_data *) pupa_malloc (sizeof (*data)); + if (! data) + return pupa_errno; + + data->drive = drive; + data->flags = 0; + + if (drive & 0x80) + { + /* HDD */ + int version; + + version = pupa_biosdisk_check_int13_extensions (drive); + if (version) + { + struct pupa_biosdisk_drp *drp + = (struct pupa_biosdisk_drp *) PUPA_MEMORY_MACHINE_SCRATCH_ADDR; + + /* Clear out the DRP. */ + pupa_memset (drp, 0, sizeof (*drp)); + drp->size = sizeof (*drp); + if (pupa_biosdisk_get_diskinfo_int13_extensions (drive, drp)) + { + data->flags = PUPA_BIOSDISK_FLAG_LBA; + + /* FIXME: 2TB limit. */ + if (drp->total_sectors) + total_sectors = drp->total_sectors & ~0L; + else + /* Some buggy BIOSes doesn't return the total sectors + correctly but returns zero. So if it is zero, compute + it by C/H/S returned by the LBA BIOS call. */ + total_sectors = drp->cylinders * drp->heads * drp->sectors; + } + } + } + + if (pupa_biosdisk_get_diskinfo_standard (drive, + &data->cylinders, + &data->heads, + &data->sectors) != 0) + { + pupa_free (data); + return pupa_error (PUPA_ERR_BAD_DEVICE, "cannot get C/H/S values"); + } + + if (! total_sectors) + total_sectors = data->cylinders * data->heads * data->sectors; + + disk->total_sectors = total_sectors; + disk->data = data; + + return PUPA_ERR_NONE; +} + +static void +pupa_biosdisk_close (pupa_disk_t disk) +{ + pupa_free (disk->data); +} + +/* For readability. */ +#define PUPA_BIOSDISK_READ 0 +#define PUPA_BIOSDISK_WRITE 1 + +static pupa_err_t +pupa_biosdisk_rw (int cmd, pupa_disk_t disk, + unsigned long sector, unsigned long size, + unsigned segment) +{ + struct pupa_biosdisk_data *data = disk->data; + + if (data->flags & PUPA_BIOSDISK_FLAG_LBA) + { + struct pupa_biosdisk_dap *dap; + + dap = (struct pupa_biosdisk_dap *) (PUPA_MEMORY_MACHINE_SCRATCH_ADDR + + (data->sectors + << PUPA_DISK_SECTOR_BITS)); + dap->length = sizeof (*dap); + dap->reserved = 0; + dap->blocks = size; + dap->buffer = segment << 16; /* The format SEGMENT:ADDRESS. */ + dap->block = sector; + + if (pupa_biosdisk_rw_int13_extensions (cmd + 0x42, data->drive, dap)) + { + /* Fall back to the CHS mode. */ + data->flags &= ~PUPA_BIOSDISK_FLAG_LBA; + disk->total_sectors = data->cylinders * data->heads * data->sectors; + return pupa_biosdisk_rw (cmd, disk, sector, size, segment); + } + } + else + { + unsigned coff, hoff, soff; + unsigned head; + + soff = sector % data->sectors + 1; + head = sector / data->sectors; + hoff = head % data->heads; + coff = head / data->heads; + + if (coff >= data->cylinders) + return pupa_error (PUPA_ERR_OUT_OF_RANGE, "out of disk"); + + if (pupa_biosdisk_rw_standard (cmd + 0x02, data->drive, + coff, hoff, soff, size, segment)) + { + switch (cmd) + { + case PUPA_BIOSDISK_READ: + return pupa_error (PUPA_ERR_READ_ERROR, "biosdisk read error"); + case PUPA_BIOSDISK_WRITE: + return pupa_error (PUPA_ERR_WRITE_ERROR, "biosdisk write error"); + } + } + } + + return PUPA_ERR_NONE; +} + +static pupa_err_t +pupa_biosdisk_read (pupa_disk_t disk, unsigned long sector, + unsigned long size, char *buf) +{ + struct pupa_biosdisk_data *data = disk->data; + + while (size) + { + unsigned long len; + + len = data->sectors - (sector % data->sectors); + if (len > size) + len = size; + + if (pupa_biosdisk_rw (PUPA_BIOSDISK_READ, disk, sector, len, + PUPA_MEMORY_MACHINE_SCRATCH_SEG)) + return pupa_errno; + + pupa_memcpy (buf, (void *) PUPA_MEMORY_MACHINE_SCRATCH_ADDR, + len << PUPA_DISK_SECTOR_BITS); + buf += len << PUPA_DISK_SECTOR_BITS; + sector += len; + size -= len; + } + + return pupa_errno; +} + +static pupa_err_t +pupa_biosdisk_write (pupa_disk_t disk, unsigned long sector, + unsigned long size, const char *buf) +{ + struct pupa_biosdisk_data *data = disk->data; + + while (size) + { + unsigned long len; + + len = data->sectors - (sector % data->sectors); + if (len > size) + len = size; + + pupa_memcpy ((void *) PUPA_MEMORY_MACHINE_SCRATCH_ADDR, buf, + len << PUPA_DISK_SECTOR_BITS); + + if (pupa_biosdisk_rw (PUPA_BIOSDISK_WRITE, disk, sector, len, + PUPA_MEMORY_MACHINE_SCRATCH_SEG)) + return pupa_errno; + + buf += len << PUPA_DISK_SECTOR_BITS; + sector += len; + size -= len; + } + + return pupa_errno; +} + +static struct pupa_disk_dev pupa_biosdisk_dev = + { + .name = "biosdisk", + .iterate = pupa_biosdisk_iterate, + .open = pupa_biosdisk_open, + .close = pupa_biosdisk_close, + .read = pupa_biosdisk_read, + .write = pupa_biosdisk_write, + .next = 0 + }; + +void +pupa_biosdisk_init (void) +{ + pupa_disk_dev_register (&pupa_biosdisk_dev); +} diff --git a/disk/i386/pc/partition.c b/disk/i386/pc/partition.c new file mode 100644 index 000000000..ba0771b4c --- /dev/null +++ b/disk/i386/pc/partition.c @@ -0,0 +1,248 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +/* Parse the partition representation in STR and return a partition. */ +static pupa_partition_t +pupa_partition_parse (const char *str) +{ + pupa_partition_t p; + char *s = (char *) str; + + p = (pupa_partition_t) pupa_malloc (sizeof (*p)); + if (! p) + return 0; + + /* Initialize some of the fields with invalid values. */ + p->bsd_part = p->dos_type = p->bsd_type = p->index = -1; + + /* Get the DOS partition number. */ + p->dos_part = pupa_strtoul (s, &s, 0); + + if (pupa_errno) + { + /* Not found. Maybe only a BSD label is specified. */ + p->dos_part = -1; + pupa_errno = PUPA_ERR_NONE; + } + else if (*s == ',') + s++; + + if (*s) + { + if (*s >= 'a' && *s <= 'h') + { + p->bsd_part = *s - 'a'; + s++; + } + + if (*s) + goto fail; + } + + if (p->dos_part == -1 && p->bsd_part == -1) + goto fail; + + return p; + + fail: + pupa_free (p); + pupa_error (PUPA_ERR_BAD_FILENAME, "invalid partition"); + return 0; +} + +pupa_err_t +pupa_partition_iterate (pupa_disk_t disk, + int (*hook) (const pupa_partition_t partition)) +{ + struct pupa_partition p; + struct pupa_partition_mbr mbr; + struct pupa_partition_disk_label label; + struct pupa_disk raw; + + /* Enforce raw disk access. */ + raw = *disk; + raw.partition = 0; + + p.offset = 0; + p.ext_offset = 0; + p.dos_part = -1; + + while (1) + { + int i; + struct pupa_partition_entry *e; + + /* Read the MBR. */ + if (pupa_disk_read (&raw, p.offset, 0, sizeof (mbr), (char *) &mbr)) + goto finish; + + /* Check if it is valid. */ + if (mbr.signature != pupa_cpu_to_le16 (PUPA_PARTITION_SIGNATURE)) + return pupa_error (PUPA_ERR_BAD_PART_TABLE, "no signature"); + + /* Analyze DOS partitions. */ + for (p.index = 0; p.index < 4; p.index++) + { + e = mbr.entries + p.index; + + p.start = p.offset + pupa_le_to_cpu32 (e->start); + p.len = pupa_le_to_cpu32 (e->length); + p.bsd_part = -1; + p.dos_type = e->type; + p.bsd_type = -1; + + /* If this partition is a normal one, call the hook. */ + if (! pupa_partition_is_empty (e->type) + && ! pupa_partition_is_extended (e->type)) + { + p.dos_part++; + + if (hook (&p)) + goto finish; + + /* Check if this is a BSD partition. */ + if (pupa_partition_is_bsd (e->type)) + { + /* Check if the BSD label is within the DOS partition. */ + if (p.len <= PUPA_PARTITION_BSD_LABEL_SECTOR) + return pupa_error (PUPA_ERR_BAD_PART_TABLE, + "no space for disk label"); + + /* Read the BSD label. */ + if (pupa_disk_read (&raw, + (p.start + + PUPA_PARTITION_BSD_LABEL_SECTOR), + 0, + sizeof (label), + (char *) &label)) + goto finish; + + /* Check if it is valid. */ + if (label.magic + != pupa_cpu_to_le32 (PUPA_PARTITION_BSD_LABEL_MAGIC)) + return pupa_error (PUPA_ERR_BAD_PART_TABLE, + "invalid disk label magic"); + + for (p.bsd_part = 0; + p.bsd_part < pupa_cpu_to_le16 (label.num_partitions); + p.bsd_part++) + { + struct pupa_partition_bsd_entry *be + = label.entries + p.bsd_part; + + p.start = pupa_le_to_cpu32 (be->offset); + p.len = pupa_le_to_cpu32 (be->size); + p.bsd_type = be->fs_type; + + if (be->fs_type != PUPA_PARTITION_BSD_TYPE_UNUSED) + if (hook (&p)) + goto finish; + } + } + } + else if (p.dos_part < 4) + /* If this partition is a logical one, shouldn't increase the + partition number. */ + p.dos_part++; + } + + /* Find an extended partition. */ + for (i = 0; i < 4; i++) + { + e = mbr.entries + i; + + if (pupa_partition_is_extended (e->type)) + { + p.offset = p.ext_offset + pupa_le_to_cpu32 (e->start); + if (! p.ext_offset) + p.ext_offset = p.offset; + + break; + } + } + + /* If no extended partition, the end. */ + if (i == 4) + break; + } + + finish: + return pupa_errno; +} + +pupa_partition_t +pupa_partition_probe (pupa_disk_t disk, const char *str) +{ + pupa_partition_t p; + auto int find_func (const pupa_partition_t partition); + + int find_func (const pupa_partition_t partition) + { + if ((p->dos_part == partition->dos_part || p->dos_part == -1) + && p->bsd_part == partition->bsd_part) + { + pupa_memcpy (p, partition, sizeof (*p)); + return 1; + } + + return 0; + } + + p = pupa_partition_parse (str); + if (! p) + return 0; + + + if (pupa_partition_iterate (disk, find_func)) + goto fail; + + if (p->index < 0) + { + pupa_error (PUPA_ERR_BAD_DEVICE, "no such partition"); + goto fail; + } + + return p; + + fail: + pupa_free (p); + return 0; +} + +char * +pupa_partition_get_name (const pupa_partition_t p) +{ + char *name; + + name = pupa_malloc (13); + if (! name) + return 0; + + if (p->bsd_part < 0) + pupa_sprintf (name, "%d", p->dos_part); + else + pupa_sprintf (name, "%d,%c", p->dos_part, p->bsd_part + 'a'); + + return name; +} diff --git a/fs/fat.c b/fs/fat.c new file mode 100644 index 000000000..70abadcdb --- /dev/null +++ b/fs/fat.c @@ -0,0 +1,756 @@ +/* fat.c - FAT filesystem */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2000,2001 Free Software Foundation, Inc. + * Copyright (C) 2002 Yoshinori K. Okuji + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define PUPA_FAT_DIR_ENTRY_SIZE 32 + +#define PUPA_FAT_ATTR_READ_ONLY 0x01 +#define PUPA_FAT_ATTR_HIDDEN 0x02 +#define PUPA_FAT_ATTR_SYSTEM 0x04 +#define PUPA_FAT_ATTR_VOLUME_ID 0x08 +#define PUPA_FAT_ATTR_DIRECTORY 0x10 +#define PUPA_FAT_ATTR_ARCHIVE 0x20 + +#define PUPA_FAT_ATTR_LONG_NAME (PUPA_FAT_ATTR_READ_ONLY \ + | PUPA_FAT_ATTR_HIDDEN \ + | PUPA_FAT_ATTR_SYSTEM \ + | PUPA_FAT_ATTR_VOLUME_ID) +#define PUPA_FAT_ATTR_VALID (PUPA_FAT_ATTR_READ_ONLY \ + | PUPA_FAT_ATTR_HIDDEN \ + | PUPA_FAT_ATTR_SYSTEM \ + | PUPA_FAT_ATTR_DIRECTORY \ + | PUPA_FAT_ATTR_ARCHIVE) + +struct pupa_fat_bpb +{ + pupa_uint8_t jmp_boot[3]; + pupa_uint8_t oem_name[8]; + pupa_uint16_t bytes_per_sector; + pupa_uint8_t sectors_per_cluster; + pupa_uint16_t num_reserved_sectors; + pupa_uint8_t num_fats; + pupa_uint16_t num_root_entries; + pupa_uint16_t num_total_sectors_16; + pupa_uint8_t media; + pupa_uint16_t sectors_per_fat_16; + pupa_uint16_t sectors_per_track; + pupa_uint16_t num_heads; + pupa_uint32_t num_hidden_sectors; + pupa_uint32_t num_total_sectors_32; + + /* The following fields are only used by FAT32. */ + pupa_uint32_t sectors_per_fat_32; + pupa_uint16_t extended_flags; + pupa_uint16_t fs_version; + pupa_uint32_t root_cluster; + pupa_uint16_t fs_info; + pupa_uint16_t backup_boot_sector; +} __attribute__ ((packed)); + +struct pupa_fat_dir_entry +{ + pupa_uint8_t name[11]; + pupa_uint8_t attr; + pupa_uint8_t nt_reserved; + pupa_uint8_t c_time_tenth; + pupa_uint16_t c_time; + pupa_uint16_t c_date; + pupa_uint16_t a_date; + pupa_uint16_t first_cluster_high; + pupa_uint16_t w_time; + pupa_uint16_t w_date; + pupa_uint16_t first_cluster_low; + pupa_uint32_t file_size; +} __attribute__ ((packed)); + +struct pupa_fat_long_name_entry +{ + pupa_uint8_t id; + pupa_uint16_t name1[5]; + pupa_uint8_t attr; + pupa_uint8_t reserved; + pupa_uint8_t checksum; + pupa_uint16_t name2[6]; + pupa_uint16_t first_cluster; + pupa_uint16_t name3[2]; +} __attribute__ ((packed)); + +struct pupa_fat_data +{ + int logical_sector_bits; + pupa_uint32_t num_sectors; + + pupa_uint16_t fat_sector; + pupa_uint32_t sectors_per_fat; + int fat_size; + + pupa_uint32_t root_cluster; + pupa_uint32_t root_sector; + pupa_uint32_t num_root_sectors; + + int cluster_bits; + pupa_uint32_t cluster_eof_mark; + pupa_uint32_t cluster_sector; + pupa_uint32_t num_clusters; + + pupa_uint8_t attr; + pupa_ssize_t file_size; + pupa_uint32_t file_cluster; + pupa_uint32_t cur_cluster_num; + pupa_uint32_t cur_cluster; +}; + +static int +log2 (unsigned x) +{ + int i; + + if (x == 0) + return -1; + + for (i = 0; (x & 1) == 0; i++) + x >>= 1; + + if (x != 1) + return -1; + + return i; +} + +static struct pupa_fat_data * +pupa_fat_mount (pupa_disk_t disk) +{ + struct pupa_fat_bpb bpb; + struct pupa_fat_data *data = 0; + pupa_uint32_t first_fat, magic; + + if (! disk) + goto fail; + + data = (struct pupa_fat_data *) pupa_malloc (sizeof (*data)); + if (! data) + goto fail; + + /* Read the BPB. */ + if (pupa_disk_read (disk, 0, 0, sizeof (bpb), (char *) &bpb)) + goto fail; + + /* Get the sizes of logical sectors and clusters. */ + data->logical_sector_bits = log2 (pupa_le_to_cpu16 (bpb.bytes_per_sector)); + if (data->logical_sector_bits < PUPA_DISK_SECTOR_BITS) + goto fail; + data->logical_sector_bits -= PUPA_DISK_SECTOR_BITS; + + data->cluster_bits = log2 (bpb.sectors_per_cluster); + if (data->cluster_bits < 0) + goto fail; + data->cluster_bits += data->logical_sector_bits; + + /* Get information about FATs. */ + data->fat_sector = (pupa_le_to_cpu16 (bpb.num_reserved_sectors) + << data->logical_sector_bits); + if (data->fat_sector == 0) + goto fail; + + data->sectors_per_fat = ((bpb.sectors_per_fat_16 + ? pupa_le_to_cpu16 (bpb.sectors_per_fat_16) + : pupa_le_to_cpu32 (bpb.sectors_per_fat_32)) + << data->logical_sector_bits); + if (data->sectors_per_fat == 0) + goto fail; + + /* Get the number of sectors in this volume. */ + data->num_sectors = ((bpb.num_total_sectors_16 + ? pupa_le_to_cpu16 (bpb.num_total_sectors_16) + : pupa_le_to_cpu32 (bpb.num_total_sectors_32)) + << data->logical_sector_bits); + if (data->num_sectors == 0) + goto fail; + + /* Get information about the root directory. */ + if (bpb.num_fats == 0) + goto fail; + + data->root_sector = data->fat_sector + bpb.num_fats * data->sectors_per_fat; + data->num_root_sectors + = ((((pupa_uint32_t) pupa_le_to_cpu16 (bpb.num_root_entries) + * PUPA_FAT_DIR_ENTRY_SIZE + + pupa_le_to_cpu16 (bpb.bytes_per_sector) - 1) + >> (data->logical_sector_bits + PUPA_DISK_SECTOR_BITS)) + << (data->logical_sector_bits)); + + data->cluster_sector = data->root_sector + data->num_root_sectors; + data->num_clusters = (((data->num_sectors - data->cluster_sector) + >> (data->cluster_bits + data->logical_sector_bits)) + + 2); + + if (data->num_clusters <= 2) + goto fail; + + if (! bpb.sectors_per_fat_16) + { + /* FAT32. */ + pupa_uint16_t flags = pupa_le_to_cpu16 (bpb.extended_flags); + + data->root_cluster = pupa_le_to_cpu32 (bpb.root_cluster); + data->fat_size = 32; + data->cluster_eof_mark = 0x0ffffff8; + + if (flags & 0x80) + { + /* Get an active FAT. */ + unsigned active_fat = flags & 0xf; + + if (active_fat > bpb.num_fats) + goto fail; + + data->fat_sector += active_fat * data->sectors_per_fat; + } + + if (bpb.num_root_entries != 0 || bpb.fs_version != 0) + goto fail; + } + else + { + /* FAT12 or FAT16. */ + data->root_cluster = ~0UL; + + if (data->num_clusters <= 4085 + 2) + { + /* FAT12. */ + data->fat_size = 12; + data->cluster_eof_mark = 0x0ff8; + } + else + { + /* FAT16. */ + data->fat_size = 16; + data->cluster_eof_mark = 0xfff8; + } + } + + /* More sanity checks. */ + if (data->num_sectors <= data->fat_sector) + goto fail; + + if (pupa_disk_read (disk, + data->fat_sector, + 0, + sizeof (first_fat), + (char *) &first_fat)) + goto fail; + + first_fat = pupa_le_to_cpu32 (first_fat); + + if (data->fat_size == 32) + { + first_fat &= 0x0fffffff; + magic = 0x0fffff00; + } + else if (data->fat_size == 16) + { + first_fat &= 0x0000ffff; + magic = 0xff00; + } + else + { + first_fat &= 0x00000fff; + magic = 0x0f00; + } + + if (first_fat != (magic | bpb.media)) + goto fail; + + /* Start from the root directory. */ + data->file_cluster = data->root_cluster; + data->cur_cluster_num = ~0UL; + data->attr = PUPA_FAT_ATTR_DIRECTORY; + return data; + + fail: + + pupa_free (data); + pupa_error (PUPA_ERR_BAD_FS, "not a fat filesystem"); + return 0; +} + +/* Convert UTF-16 (little endian) to UTF8. */ +static pupa_uint8_t * +pupa_fat_utf16_to_utf8 (pupa_uint8_t *dest, pupa_uint16_t *src, + pupa_size_t size) +{ + pupa_uint32_t code_high = 0; + + while (size--) + { + pupa_uint32_t code = pupa_le_to_cpu16 (*src++); + + if (code_high) + { + if (code >= 0xDC00 && code <= 0xDFFF) + { + /* Surrogate pair. */ + code = ((code_high - 0xD800) << 12) + (code - 0xDC00) + 0x10000; + + *dest++ = (code >> 18) | 0xF0; + *dest++ = ((code >> 12) & 0x3F) | 0x80; + *dest++ = ((code >> 6) & 0x3F) | 0x80; + *dest++ = (code & 0x3F) | 0x80; + } + else + { + /* Error... */ + *dest++ = '?'; + } + + code_high = 0; + } + else + { + if (code <= 0x007F) + *dest++ = code; + else if (code <= 0x07FF) + { + *dest++ = (code >> 6) | 0xC0; + *dest++ = (code & 0x3F) | 0x80; + } + else if (code >= 0xD800 && code <= 0xDBFF) + { + code_high = code; + continue; + } + else if (code >= 0xDC00 && code <= 0xDFFF) + { + /* Error... */ + *dest++ = '?'; + } + else + { + *dest++ = (code >> 16) | 0xE0; + *dest++ = ((code >> 12) & 0x3F) | 0x80; + *dest++ = (code & 0x3F) | 0x80; + } + } + } + + return dest; +} + +static pupa_ssize_t +pupa_fat_read_data (pupa_disk_t disk, struct pupa_fat_data *data, + void (*read_hook) (unsigned long sector, + unsigned offset, unsigned length), + pupa_ssize_t offset, pupa_ssize_t len, char *buf) +{ + pupa_ssize_t size; + pupa_uint32_t logical_cluster; + unsigned logical_cluster_bits; + pupa_ssize_t ret = 0; + unsigned long sector; + + /* This is a special case. FAT12 and FAT16 doesn't have the root directory + in clusters. */ + if (data->file_cluster == ~0UL) + { + size = (data->num_root_sectors << PUPA_DISK_SECTOR_BITS) - offset; + if (size > len) + size = len; + + if (pupa_disk_read (disk, data->root_sector, offset, size, buf)) + return -1; + + return size; + } + + /* Calculate the logical cluster number and offset. */ + logical_cluster_bits = (data->cluster_bits + + data->logical_sector_bits + + PUPA_DISK_SECTOR_BITS); + logical_cluster = offset >> logical_cluster_bits; + offset &= (1 << logical_cluster_bits) - 1; + + if (logical_cluster < data->cur_cluster_num) + { + data->cur_cluster_num = 0; + data->cur_cluster = data->file_cluster; + } + + while (len) + { + while (logical_cluster > data->cur_cluster_num) + { + /* Find next cluster. */ + pupa_uint32_t next_cluster; + unsigned long fat_offset; + + switch (data->fat_size) + { + case 32: + fat_offset = data->cur_cluster << 2; + break; + case 16: + fat_offset = data->cur_cluster << 1; + break; + default: + /* case 12: */ + fat_offset = data->cur_cluster + (data->cur_cluster >> 1); + break; + } + + /* Read the FAT. */ + if (pupa_disk_read (disk, data->fat_sector, fat_offset, + (data->fat_size + 7) >> 3, + (char *) &next_cluster)) + return -1; + + next_cluster = pupa_le_to_cpu32 (next_cluster); + switch (data->fat_size) + { + case 16: + next_cluster &= 0xFFFF; + break; + case 12: + if (data->cur_cluster & 1) + next_cluster >>= 12; + + next_cluster &= 0x0FFF; + break; + } + + /* Check the end. */ + if (next_cluster >= data->cluster_eof_mark) + return ret; + + if (next_cluster < 2 || next_cluster >= data->num_clusters) + { + pupa_error (PUPA_ERR_BAD_FS, "invalid cluster"); + return -1; + } + + data->cur_cluster = next_cluster; + data->cur_cluster_num++; + } + + /* Read the data here. */ + sector = (data->cluster_sector + + ((data->cur_cluster - 2) + << (data->cluster_bits + data->logical_sector_bits))); + size = (1 << logical_cluster_bits) - offset; + if (size > len) + size = len; + + disk->read_hook = read_hook; + pupa_disk_read (disk, sector, offset, size, buf); + disk->read_hook = 0; + if (pupa_errno) + return -1; + + len -= size; + buf += size; + ret += size; + logical_cluster++; + offset = 0; + } + + return ret; +} + +/* Find the underlying directory or file in PATH and return the + next path. If there is no next path or an error occurs, return NULL. + If HOOK is specified, call it with each file name. */ +static char * +pupa_fat_find_dir (pupa_disk_t disk, struct pupa_fat_data *data, + const char *path, + int (*hook) (const char *filename, int dir)) +{ + struct pupa_fat_dir_entry dir; + char *dirname, *dirp; + char *filename, *filep = 0; + pupa_uint16_t *unibuf; + int slot = -1, slots = -1; + int checksum = -1; + pupa_ssize_t offset = -sizeof(dir); + int call_hook; + + if (! (data->attr & PUPA_FAT_ATTR_DIRECTORY)) + { + pupa_error (PUPA_ERR_BAD_FILE_TYPE, "not a directory"); + return 0; + } + + /* Extract a directory name. */ + while (*path == '/') + path++; + + dirp = pupa_strchr (path, '/'); + if (dirp) + { + unsigned len = dirp - path; + + dirname = pupa_malloc (len + 1); + if (! dirname) + return 0; + + pupa_memcpy (dirname, path, len); + dirname[len] = '\0'; + } + else + /* This is actually a file. */ + dirname = pupa_strdup (path); + + call_hook = (! dirp && hook); + + /* Allocate space enough to hold a long name. */ + filename = pupa_malloc (0x40 * 13 * 4 + 1); + unibuf = (pupa_uint16_t *) pupa_malloc (0x40 * 13 * 2); + if (! filename || ! unibuf) + { + pupa_free (filename); + pupa_free (unibuf); + pupa_free (dirname); + return 0; + } + + while (1) + { + unsigned i; + + /* Adjust the offset. */ + offset += sizeof (dir); + + /* Read a directory entry. */ + if ((pupa_fat_read_data (disk, data, 0, + offset, sizeof (dir), (char *) &dir) + != sizeof (dir)) + || dir.name[0] == 0) + { + if (pupa_errno == PUPA_ERR_NONE && ! call_hook) + pupa_error (PUPA_ERR_FILE_NOT_FOUND, "file not found"); + + break; + } + + /* Handle long name entries. */ + if (dir.attr == PUPA_FAT_ATTR_LONG_NAME) + { + struct pupa_fat_long_name_entry *long_name + = (struct pupa_fat_long_name_entry *) &dir; + pupa_uint8_t id = long_name->id; + + if (id & 0x40) + { + id &= 0x3f; + slots = slot = id; + checksum = long_name->checksum; + } + + if (id != slot || slot == 0 || checksum != long_name->checksum) + { + checksum = -1; + continue; + } + + slot--; + pupa_memcpy (unibuf + slot * 13, long_name->name1, 5 * 2); + pupa_memcpy (unibuf + slot * 13 + 5, long_name->name2, 6 * 2); + pupa_memcpy (unibuf + slot * 13 + 11, long_name->name3, 2 * 2); + continue; + } + + /* Check if this entry is valid. */ + if (dir.name[0] == 0xe5 || (dir.attr & ~PUPA_FAT_ATTR_VALID)) + continue; + + /* This is a workaround for Japanese. */ + if (dir.name[0] == 0x05) + dir.name[0] = 0xe5; + + if (checksum != -1 && slot == 0) + { + pupa_uint8_t sum; + + for (sum = 0, i = 0; i < sizeof (dir.name); i++) + sum = ((sum >> 1) | (sum << 7)) + dir.name[i]; + + if (sum == checksum) + { + *pupa_fat_utf16_to_utf8 (filename, unibuf, slots * 13) = '\0'; + + if (*dirname == '\0' && call_hook) + { + if (hook (filename, dir.attr & PUPA_FAT_ATTR_DIRECTORY)) + break; + + checksum = -1; + continue; + } + + if (pupa_strcmp (dirname, filename) == 0) + { + if (call_hook) + hook (filename, dir.attr & PUPA_FAT_ATTR_DIRECTORY); + + break; + } + } + + checksum = -1; + } + + /* Convert the 8.3 file name. */ + filep = filename; + + for (i = 0; i < 8 && dir.name[i] && ! pupa_isspace (dir.name[i]); i++) + *filep++ = pupa_tolower (dir.name[i]); + + *filep = '.'; + + for (i = 8; i < 11 && dir.name[i] && ! pupa_isspace (dir.name[i]); i++) + *++filep = pupa_tolower (dir.name[i]); + + if (*filep != '.') + filep++; + + *filep = '\0'; + + if (*dirname == '\0' && call_hook) + { + if (hook (filename, dir.attr & PUPA_FAT_ATTR_DIRECTORY)) + break; + } + else if (pupa_strcmp (dirname, filename) == 0) + { + if (call_hook) + hook (filename, dir.attr & PUPA_FAT_ATTR_DIRECTORY); + + break; + } + } + + pupa_free (filename); + pupa_free (dirname); + + data->attr = dir.attr; + data->file_size = pupa_le_to_cpu32 (dir.file_size); + data->file_cluster = ((pupa_le_to_cpu16 (dir.first_cluster_high) << 16) + | pupa_le_to_cpu16 (dir.first_cluster_low)); + data->cur_cluster_num = ~0UL; + + return dirp; +} + +static pupa_err_t +pupa_fat_dir (pupa_device_t device, const char *path, + int (*hook) (const char *filename, int dir)) +{ + struct pupa_fat_data *data; + pupa_disk_t disk = device->disk; + char *p = (char *) path; + + data = pupa_fat_mount (disk); + if (! data) + return pupa_errno; + + do + { + p = pupa_fat_find_dir (disk, data, p, hook); + } + while (p && pupa_errno == PUPA_ERR_NONE); + + pupa_free (data); + return pupa_errno; +} + +static pupa_err_t +pupa_fat_open (pupa_file_t file, const char *name) +{ + struct pupa_fat_data *data; + char *p = (char *) name; + + data = pupa_fat_mount (file->device->disk); + if (! data) + return pupa_errno; + + do + { + p = pupa_fat_find_dir (file->device->disk, data, p, 0); + if (pupa_errno != PUPA_ERR_NONE) + goto fail; + } + while (p); + + if (data->attr & PUPA_FAT_ATTR_DIRECTORY) + { + pupa_error (PUPA_ERR_BAD_FILE_TYPE, "not a file"); + goto fail; + } + + file->data = data; + file->size = data->file_size; + + return PUPA_ERR_NONE; + + fail: + pupa_free (data); + return pupa_errno; +} + +static pupa_ssize_t +pupa_fat_read (pupa_file_t file, char *buf, pupa_ssize_t len) +{ + return pupa_fat_read_data (file->device->disk, file->data, file->read_hook, + file->offset, len, buf); +} + +static pupa_err_t +pupa_fat_close (pupa_file_t file) +{ + pupa_free (file->data); + return pupa_errno; +} + +static struct pupa_fs pupa_fat_fs = + { + .name = "fat", + .dir = pupa_fat_dir, + .open = pupa_fat_open, + .read = pupa_fat_read, + .close = pupa_fat_close, + .next = 0 + }; + +PUPA_MOD_INIT +{ + pupa_fs_register (&pupa_fat_fs); +} + +PUPA_MOD_FINI +{ + pupa_fs_unregister (&pupa_fat_fs); +} diff --git a/genkernsyms.sh b/genkernsyms.sh new file mode 100644 index 000000000..0177ab3cf --- /dev/null +++ b/genkernsyms.sh @@ -0,0 +1,15 @@ +#! /bin/sh +# +# Copyright (C) 2002 Yoshinori K. Okuji +# +# This gensymlist.sh is free software; the author +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +cat $* | grep -v '^#' | sed -n '/EXPORT_FUNC *([a-zA-Z0-9_]*)/{s/.*EXPORT_FUNC *(\([a-zA-Z0-9_]*\)).*/\1 kernel/;p;}' +cat $* | grep -v '^#' | sed -n '/EXPORT_VAR *([a-zA-Z0-9_]*)/{s/.*EXPORT_VAR *(\([a-zA-Z0-9_]*\)).*/\1 kernel/;p;}' diff --git a/genmk.rb b/genmk.rb new file mode 100644 index 000000000..7c621b970 --- /dev/null +++ b/genmk.rb @@ -0,0 +1,269 @@ +#! /usr/bin/ruby -w +# +# Copyright (C) 2002 Yoshinori K. Okuji +# +# This genmk.rb is free software; the author +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +module Enumerable + def collect_with_index + ret = [] + self.each_with_index do |item, index| + ret.push(yield(item, index)) + end + ret + end +end + +class String + def to_var + self.gsub(/[^a-zA-Z0-9_@]/, '_') + end + + def suffix(str) + self.sub(/\.[^\.]*$/, '') + '.' + str + end + + def to_obj + self.sub(/\.[^\.]*$/, '').to_var + '.o' + end +end + +class Image + def initialize(dir, name) + @dir = dir + @name = name + end + attr_reader :dir, :name + + def rule(sources) + prefix = @name.to_var + exe = @name.suffix('exec') + objs = sources.collect do |src| + raise "unknown source file `#{src}'" if /\.[cS]$/ !~ src + prefix + '-' + src.to_obj + end + objs_str = objs.join(' ') + deps = objs.collect {|obj| obj.suffix('d')} + deps_str = deps.join(' ') + + "CLEANFILES += #{@name} #{exe} #{objs_str} +MOSTLYCLEANFILES += #{deps_str} + +#{@name}: #{exe} + $(OBJCOPY) -O binary -R .note -R .comment $< $@ + +#{exe}: #{objs_str} + $(CC) $(LDFLAGS) $(#{prefix}_LDFLAGS) -o $@ $^ + +" + objs.collect_with_index do |obj, i| + src = sources[i] + fake_obj = File.basename(src).suffix('o') + dep = deps[i] + flag = if /\.c$/ =~ src then 'CFLAGS' else 'ASFLAGS' end + extra_flags = if /\.S$/ =~ src then '-DASM_FILE=1' else '' end + dir = File.dirname(src) + + "#{obj}: #{src} + $(CC) -I#{dir} -I$(srcdir)/#{dir} $(CPPFLAGS) #{extra_flags} $(#{flag}) $(#{prefix}_#{flag}) -c -o $@ $< + +#{dep}: #{src} + set -e; \ + $(CC) -I#{dir} -I$(srcdir)/#{dir} $(CPPFLAGS) #{extra_flags} $(#{flag}) $(#{prefix}_#{flag}) -M $< \ + | sed 's,#{Regexp.quote(fake_obj)}[ :]*,#{obj} $@ : ,g' > $@; \ + [ -s $@ ] || rm -f $@ + +-include #{dep} + +" + end.join('') + end +end + +# Use PModule instead Module, to avoid name conflicting. +class PModule + def initialize(dir, name) + @dir = dir + @name = name + end + attr_reader :dir, :name + + def rule(sources) + prefix = @name.to_var + objs = sources.collect do |src| + raise "unknown source file `#{src}'" if /\.[cS]$/ !~ src + prefix + '-' + src.to_obj + end + objs_str = objs.join(' ') + deps = objs.collect {|obj| obj.suffix('d')} + deps_str = deps.join(' ') + pre_obj = 'pre-' + @name.suffix('o') + mod_src = 'mod-' + @name.suffix('c') + mod_obj = mod_src.suffix('o') + defsym = 'def-' + @name.suffix('lst') + undsym = 'und-' + @name.suffix('lst') + mod_name = File.basename(@name, '.mod') + + "CLEANFILES += #{@name} #{mod_obj} #{mod_src} #{pre_obj} #{objs_str} #{defsym} #{undsym} +MOSTLYCLEANFILES += #{deps_str} +DEFSYMFILES += #{defsym} +UNDSYMFILES += #{undsym} + +#{@name}: #{pre_obj} #{mod_obj} + -rm -f $@ + $(LD) -r -o $@ $^ + $(STRIP) --strip-unneeded -K pupa_mod_init -K pupa_mod_fini -R .note -R .comment $@ + +#{pre_obj}: #{objs_str} + -rm -f $@ + $(LD) -r -o $@ $^ + +#{mod_obj}: #{mod_src} + $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< + +#{mod_src}: moddep.lst genmodsrc.sh + sh $(srcdir)/genmodsrc.sh '#{mod_name}' $< > $@ || (rm -f $@; exit 1) + +#{defsym}: #{pre_obj} + $(NM) -g --defined-only -P -p $< | sed 's/^\\([^ ]*\\).*/\\1 #{mod_name}/' > $@ + +#{undsym}: #{pre_obj} + echo '#{mod_name}' > $@ + $(NM) -u -P -p $< >> $@ + +" + objs.collect_with_index do |obj, i| + src = sources[i] + fake_obj = File.basename(src).suffix('o') + dep = deps[i] + flag = if /\.c$/ =~ src then 'CFLAGS' else 'ASFLAGS' end + dir = File.dirname(src) + + "#{obj}: #{src} + $(CC) -I#{dir} -I$(srcdir)/#{dir} $(CPPFLAGS) $(#{flag}) $(#{prefix}_#{flag}) -c -o $@ $< + +#{dep}: #{src} + set -e; \ + $(CC) -I#{dir} -I$(srcdir)/#{dir} $(CPPFLAGS) $(#{flag}) $(#{prefix}_#{flag}) -M $< \ + | sed 's,#{Regexp.quote(fake_obj)}[ :]*,#{obj} $@ : ,g' > $@; \ + [ -s $@ ] || rm -f $@ + +-include #{dep} + +" + end.join('') + end +end + +class Utility + def initialize(dir, name) + @dir = dir + @name = name + end + attr_reader :dir, :name + + def rule(sources) + prefix = @name.to_var + objs = sources.collect do |src| + raise "unknown source file `#{src}'" if /\.c$/ !~ src + prefix + '-' + src.to_obj + end + objs_str = objs.join(' '); + deps = objs.collect {|obj| obj.suffix('d')} + deps_str = deps.join(' '); + + "CLEANFILES += #{@name} #{objs_str} +MOSTLYCLEANFILES += #{deps_str} + +#{@name}: #{objs_str} + $(BUILD_CC) $(BUILD_LDFLAGS) $(#{prefix}_LDFLAGS) -o $@ $^ + +" + objs.collect_with_index do |obj, i| + src = sources[i] + fake_obj = File.basename(src).suffix('o') + dep = deps[i] + dir = File.dirname(src) + + "#{obj}: #{src} + $(BUILD_CC) -I#{dir} -I$(srcdir)/#{dir} $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(#{prefix}_CFLAGS) -c -o $@ $< + +#{dep}: #{src} + set -e; \ + $(BUILD_CC) -I#{dir} -I$(srcdir)/#{dir} $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(#{prefix}_CFLAGS) -M $< \ + | sed 's,#{Regexp.quote(fake_obj)}[ :]*,#{obj} $@ : ,g' > $@; \ + [ -s $@ ] || rm -f $@ + +-include #{dep} + +" + end.join('') + end +end + +images = [] +utils = [] +pmodules = [] + +cont = false +s = nil +while l = gets + if cont + s += l + else + s = l + end + + print l + cont = (/\\$/ =~ l) + unless cont + s.gsub!(/\\\n/, ' ') + + if /^([a-zA-Z0-9_]+)\s*=\s*(.*?)\s*$/ =~ s + var, args = $1, $2 + + if var =~ /^([a-zA-Z0-9_]+)_([A-Z]+)$/ + prefix, type = $1, $2 + + case type + when 'IMAGES' + images += args.split(/\s+/).collect do |img| + Image.new(prefix, img) + end + + when 'MODULES' + pmodules += args.split(/\s+/).collect do |pmod| + PModule.new(prefix, pmod) + end + + when 'UTILITIES' + utils += args.split(/\s+/).collect do |util| + Utility.new(prefix, util) + end + + when 'SOURCES' + if img = images.detect() {|i| i.name.to_var == prefix} + print img.rule(args.split(/\s+/)) + elsif pmod = pmodules.detect() {|m| m.name.to_var == prefix} + print pmod.rule(args.split(/\s+/)) + elsif util = utils.detect() {|u| u.name.to_var == prefix} + print util.rule(args.split(/\s+/)) + end + end + end + + end + + end + +end + +puts "CLEANFILES += moddep.lst" +puts "pkgdata_DATA += moddep.lst" +puts "moddep.lst: $(DEFSYMFILES) $(UNDSYMFILES) genmoddep" +puts " cat $(DEFSYMFILES) /dev/null | ./genmoddep $(UNDSYMFILES) > $@ \\" +puts " || (rm -f $@; exit 1)" diff --git a/genmodsrc.sh b/genmodsrc.sh new file mode 100644 index 000000000..f02eb139d --- /dev/null +++ b/genmodsrc.sh @@ -0,0 +1,48 @@ +#! /bin/sh +# +# Copyright (C) 2002 Yoshinori K. Okuji +# +# This genmodsrc.sh is free software; the author +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +set -e + +mod_name="$1" +deps="$2" + +cat < + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +EOF + +echo "PUPA_MOD_NAME(${mod_name});" + +for mod in `grep "^${mod_name}:" ${deps} | sed 's/^[^:]*://'`; do + echo "PUPA_MOD_DEP(${mod});" +done diff --git a/gensymlist.sh b/gensymlist.sh new file mode 100644 index 000000000..531ce1c21 --- /dev/null +++ b/gensymlist.sh @@ -0,0 +1,65 @@ +#! /bin/sh +# +# Copyright (C) 2002 Yoshinori K. Okuji +# +# This gensymlist.sh is free software; the author +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +cat < + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +EOF + +for i in $*; do + echo "#include <$i>" +done + +cat <name; p++) + pupa_dl_register_symbol (p->name, p->addr, 0); +} +EOF diff --git a/include/grub/boot.h b/include/grub/boot.h new file mode 100644 index 000000000..bf897dbf2 --- /dev/null +++ b/include/grub/boot.h @@ -0,0 +1,28 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * 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 PUPA_BOOT_HEADER +#define PUPA_BOOT_HEADER 1 + +#define PUPA_BOOT_VERSION_MAJOR 4 +#define PUPA_BOOT_VERSION_MINOR 0 +#define PUPA_BOOT_VERSION ((PUPA_BOOT_VERSION_MINOR << 8) \ + | PUPA_BOOT_VERSION_MAJOR) + +#endif /* ! PUPA_BOOT_HEADER */ diff --git a/include/grub/device.h b/include/grub/device.h new file mode 100644 index 000000000..e8df53c5c --- /dev/null +++ b/include/grub/device.h @@ -0,0 +1,44 @@ +/* device.h - device manager */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PUPA_DEVICE_HEADER +#define PUPA_DEVICE_HEADER 1 + +#include +#include + +struct pupa_disk; +struct pupa_net; +struct pupa_fs; + +struct pupa_device +{ + struct pupa_disk *disk; + struct pupa_net *net; +}; +typedef struct pupa_device *pupa_device_t; + +pupa_device_t EXPORT_FUNC(pupa_device_open) (const char *name); +pupa_err_t EXPORT_FUNC(pupa_device_close) (pupa_device_t device); + +pupa_err_t EXPORT_FUNC(pupa_device_set_root) (const char *name); +const char *EXPORT_FUNC(pupa_device_get_root) (void); + +#endif /* ! PUPA_DEVICE_HEADER */ diff --git a/include/grub/disk.h b/include/grub/disk.h new file mode 100644 index 000000000..51bd5a64c --- /dev/null +++ b/include/grub/disk.h @@ -0,0 +1,119 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PUPA_DISK_HEADER +#define PUPA_DISK_HEADER 1 + +#include +#include +#include + +struct pupa_disk; + +/* Disk device. */ +struct pupa_disk_dev +{ + /* The device name. */ + const char *name; + + /* Call HOOK with each device name, until HOOK returns non-zero. */ + int (*iterate) (int (*hook) (const char *name)); + + /* Open the device named NAME, and set up DISK. */ + pupa_err_t (*open) (const char *name, struct pupa_disk *disk); + + /* Close the disk DISK. */ + void (*close) (struct pupa_disk *disk); + + /* Read SIZE sectors from the sector SECTOR of the disk DISK into BUF. */ + pupa_err_t (*read) (struct pupa_disk *disk, unsigned long sector, + unsigned long size, char *buf); + + /* Write SIZE sectors from BUF into the sector SECTOR of the disk DISK. */ + pupa_err_t (*write) (struct pupa_disk *disk, unsigned long sector, + unsigned long size, const char *buf); + + /* The next disk device. */ + struct pupa_disk_dev *next; +}; +typedef struct pupa_disk_dev *pupa_disk_dev_t; + +struct pupa_partition; + +/* Disk. */ +struct pupa_disk +{ + /* The disk name. */ + const char *name; + + /* The underlying disk device. */ + pupa_disk_dev_t dev; + + /* The total number of sectors. */ + unsigned long total_sectors; + + /* If partitions can be stored. */ + int has_partitions; + + /* The id used by the disk cache manager. */ + unsigned long id; + + /* The partition information. This is machine-specific. */ + struct pupa_partition *partition; + + /* Called when a sector was read. */ + void (*read_hook) (unsigned long sector, unsigned offset, unsigned length); + + /* Device-specific data. */ + void *data; +}; +typedef struct pupa_disk *pupa_disk_t; + +/* The sector size. */ +#define PUPA_DISK_SECTOR_SIZE 0x200 +#define PUPA_DISK_SECTOR_BITS 9 + +/* The maximum number of disk caches. */ +#define PUPA_DISK_CACHE_NUM 1021 + +/* The size of a disk cache in sector units. */ +#define PUPA_DISK_CACHE_SIZE 8 +#define PUPA_DISK_CACHE_BITS 3 + +/* This is called from the memory manager. */ +void pupa_disk_cache_invalidate_all (void); + +void EXPORT_FUNC(pupa_disk_dev_register) (pupa_disk_dev_t dev); +void EXPORT_FUNC(pupa_disk_dev_unregister) (pupa_disk_dev_t dev); +void EXPORT_FUNC(pupa_disk_dev_iterate) (int (*hook) (const char *name)); + +pupa_disk_t EXPORT_FUNC(pupa_disk_open) (const char *name); +void EXPORT_FUNC(pupa_disk_close) (pupa_disk_t disk); +pupa_err_t EXPORT_FUNC(pupa_disk_read) (pupa_disk_t disk, + unsigned long sector, + unsigned long offset, + unsigned long size, + char *buf); +pupa_err_t EXPORT_FUNC(pupa_disk_write) (pupa_disk_t disk, + unsigned long sector, + unsigned long offset, + unsigned long size, + const char *buf); + +#endif /* ! PUPA_DISK_HEADER */ diff --git a/include/grub/dl.h b/include/grub/dl.h new file mode 100644 index 000000000..2763497ed --- /dev/null +++ b/include/grub/dl.h @@ -0,0 +1,86 @@ +/* dl.h - types and prototypes for loadable module support */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PUPA_DL_H +#define PUPA_DL_H 1 + +#include +#include +#include + +#define PUPA_MOD_INIT \ +static void pupa_mod_init (void) __attribute__ ((unused)); \ +static void \ +pupa_mod_init (void) + +#define PUPA_MOD_FINI \ +static void pupa_mod_fini (void) __attribute__ ((unused)); \ +static void \ +pupa_mod_fini (void) + +#define PUPA_MOD_NAME(name) \ +__asm__ (".section .modname,\"S\"\n.string \"" #name "\"\n.previous") + +#define PUPA_MOD_DEP(name) \ +__asm__ (".section .moddeps,\"S\"\n.string \"" #name "\"\n.previous") + +struct pupa_dl_segment +{ + struct pupa_dl_segment *next; + void *addr; + pupa_size_t size; + unsigned section; +}; +typedef struct pupa_dl_segment *pupa_dl_segment_t; + +struct pupa_dl; + +struct pupa_dl_dep +{ + struct pupa_dl_dep *next; + struct pupa_dl *mod; +}; +typedef struct pupa_dl_dep *pupa_dl_dep_t; + +struct pupa_dl +{ + char *name; + int ref_count; + pupa_dl_dep_t dep; + pupa_dl_segment_t segment; + void (*init) (void); + void (*fini) (void); +}; +typedef struct pupa_dl *pupa_dl_t; + +pupa_dl_t EXPORT_FUNC(pupa_dl_load_file) (const char *filename); +pupa_dl_t EXPORT_FUNC(pupa_dl_load) (const char *name); +pupa_dl_t pupa_dl_load_core (void *addr, pupa_size_t size); +void EXPORT_FUNC(pupa_dl_unload) (pupa_dl_t mod); +pupa_dl_t EXPORT_FUNC(pupa_dl_get) (const char *name); +pupa_err_t EXPORT_FUNC(pupa_dl_register_symbol) (const char *name, void *addr, + pupa_dl_t mod); +void *EXPORT_FUNC(pupa_dl_resolve_symbol) (const char *name); +void pupa_dl_init (const char *dir); + +int pupa_arch_dl_check_header (void *ehdr, pupa_size_t size); +pupa_err_t pupa_arch_dl_relocate_symbols (pupa_dl_t mod, void *ehdr); + +#endif /* ! PUPA_DL_H */ diff --git a/include/grub/elf.h b/include/grub/elf.h new file mode 100644 index 000000000..832e95042 --- /dev/null +++ b/include/grub/elf.h @@ -0,0 +1,2314 @@ +/* This file defines standard ELF types, structures, and macros. + Copyright (C) 1995-1999, 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright (C) 2002 Yoshinori K. Okuji + This file was part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef PUPA_ELF_H +#define PUPA_ELF_H 1 + +/* Standard ELF types. */ + +#include + +/* Type for a 16-bit quantity. */ +typedef pupa_uint16_t Elf32_Half; +typedef pupa_uint16_t Elf64_Half; + +/* Types for signed and unsigned 32-bit quantities. */ +typedef pupa_uint32_t Elf32_Word; +typedef pupa_int32_t Elf32_Sword; +typedef pupa_uint32_t Elf64_Word; +typedef pupa_int32_t Elf64_Sword; + +/* Types for signed and unsigned 64-bit quantities. */ +typedef pupa_uint64_t Elf32_Xword; +typedef pupa_int64_t Elf32_Sxword; +typedef pupa_uint64_t Elf64_Xword; +typedef pupa_int64_t Elf64_Sxword; + +/* Type of addresses. */ +typedef pupa_uint32_t Elf32_Addr; +typedef pupa_uint64_t Elf64_Addr; + +/* Type of file offsets. */ +typedef pupa_uint32_t Elf32_Off; +typedef pupa_uint64_t Elf64_Off; + +/* Type for section indices, which are 16-bit quantities. */ +typedef pupa_uint16_t Elf32_Section; +typedef pupa_uint16_t Elf64_Section; + +/* Type for version symbol information. */ +typedef Elf32_Half Elf32_Versym; +typedef Elf64_Half Elf64_Versym; + + +/* The ELF file header. This appears at the start of every ELF file. */ + +#define EI_NIDENT (16) + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf32_Half e_type; /* Object file type */ + Elf32_Half e_machine; /* Architecture */ + Elf32_Word e_version; /* Object file version */ + Elf32_Addr e_entry; /* Entry point virtual address */ + Elf32_Off e_phoff; /* Program header table file offset */ + Elf32_Off e_shoff; /* Section header table file offset */ + Elf32_Word e_flags; /* Processor-specific flags */ + Elf32_Half e_ehsize; /* ELF header size in bytes */ + Elf32_Half e_phentsize; /* Program header table entry size */ + Elf32_Half e_phnum; /* Program header table entry count */ + Elf32_Half e_shentsize; /* Section header table entry size */ + Elf32_Half e_shnum; /* Section header table entry count */ + Elf32_Half e_shstrndx; /* Section header string table index */ +} Elf32_Ehdr; + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf64_Half e_type; /* Object file type */ + Elf64_Half e_machine; /* Architecture */ + Elf64_Word e_version; /* Object file version */ + Elf64_Addr e_entry; /* Entry point virtual address */ + Elf64_Off e_phoff; /* Program header table file offset */ + Elf64_Off e_shoff; /* Section header table file offset */ + Elf64_Word e_flags; /* Processor-specific flags */ + Elf64_Half e_ehsize; /* ELF header size in bytes */ + Elf64_Half e_phentsize; /* Program header table entry size */ + Elf64_Half e_phnum; /* Program header table entry count */ + Elf64_Half e_shentsize; /* Section header table entry size */ + Elf64_Half e_shnum; /* Section header table entry count */ + Elf64_Half e_shstrndx; /* Section header string table index */ +} Elf64_Ehdr; + +/* Fields in the e_ident array. The EI_* macros are indices into the + array. The macros under each EI_* macro are the values the byte + may have. */ + +#define EI_MAG0 0 /* File identification byte 0 index */ +#define ELFMAG0 0x7f /* Magic number byte 0 */ + +#define EI_MAG1 1 /* File identification byte 1 index */ +#define ELFMAG1 'E' /* Magic number byte 1 */ + +#define EI_MAG2 2 /* File identification byte 2 index */ +#define ELFMAG2 'L' /* Magic number byte 2 */ + +#define EI_MAG3 3 /* File identification byte 3 index */ +#define ELFMAG3 'F' /* Magic number byte 3 */ + +/* Conglomeration of the identification bytes, for easy testing as a word. */ +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define EI_CLASS 4 /* File class byte index */ +#define ELFCLASSNONE 0 /* Invalid class */ +#define ELFCLASS32 1 /* 32-bit objects */ +#define ELFCLASS64 2 /* 64-bit objects */ +#define ELFCLASSNUM 3 + +#define EI_DATA 5 /* Data encoding byte index */ +#define ELFDATANONE 0 /* Invalid data encoding */ +#define ELFDATA2LSB 1 /* 2's complement, little endian */ +#define ELFDATA2MSB 2 /* 2's complement, big endian */ +#define ELFDATANUM 3 + +#define EI_VERSION 6 /* File version byte index */ + /* Value must be EV_CURRENT */ + +#define EI_OSABI 7 /* OS ABI identification */ +#define ELFOSABI_NONE 0 /* UNIX System V ABI */ +#define ELFOSABI_SYSV 0 /* Alias. */ +#define ELFOSABI_HPUX 1 /* HP-UX */ +#define ELFOSABI_NETBSD 2 /* NetBSD. */ +#define ELFOSABI_LINUX 3 /* Linux. */ +#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */ +#define ELFOSABI_AIX 7 /* IBM AIX. */ +#define ELFOSABI_IRIX 8 /* SGI Irix. */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD. */ +#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto. */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD. */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +#define EI_ABIVERSION 8 /* ABI version */ + +#define EI_PAD 9 /* Byte index of padding bytes */ + +/* Legal values for e_type (object file type). */ + +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* Relocatable file */ +#define ET_EXEC 2 /* Executable file */ +#define ET_DYN 3 /* Shared object file */ +#define ET_CORE 4 /* Core file */ +#define ET_NUM 5 /* Number of defined types */ +#define ET_LOOS 0xfe00 /* OS-specific range start */ +#define ET_HIOS 0xfeff /* OS-specific range end */ +#define ET_LOPROC 0xff00 /* Processor-specific range start */ +#define ET_HIPROC 0xffff /* Processor-specific range end */ + +/* Legal values for e_machine (architecture). */ + +#define EM_NONE 0 /* No machine */ +#define EM_M32 1 /* AT&T WE 32100 */ +#define EM_SPARC 2 /* SUN SPARC */ +#define EM_386 3 /* Intel 80386 */ +#define EM_68K 4 /* Motorola m68k family */ +#define EM_88K 5 /* Motorola m88k family */ +#define EM_860 7 /* Intel 80860 */ +#define EM_MIPS 8 /* MIPS R3000 big-endian */ +#define EM_S370 9 /* IBM System/370 */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ + +#define EM_PARISC 15 /* HPPA */ +#define EM_VPP500 17 /* Fujitsu VPP500 */ +#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ +#define EM_960 19 /* Intel 80960 */ +#define EM_PPC 20 /* PowerPC */ +#define EM_PPC64 21 /* PowerPC 64-bit */ +#define EM_S390 22 /* IBM S390 */ + +#define EM_V800 36 /* NEC V800 series */ +#define EM_FR20 37 /* Fujitsu FR20 */ +#define EM_RH32 38 /* TRW RH-32 */ +#define EM_RCE 39 /* Motorola RCE */ +#define EM_ARM 40 /* ARM */ +#define EM_FAKE_ALPHA 41 /* Digital Alpha */ +#define EM_SH 42 /* Hitachi SH */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit */ +#define EM_TRICORE 44 /* Siemens Tricore */ +#define EM_ARC 45 /* Argonaut RISC Core */ +#define EM_H8_300 46 /* Hitachi H8/300 */ +#define EM_H8_300H 47 /* Hitachi H8/300H */ +#define EM_H8S 48 /* Hitachi H8S */ +#define EM_H8_500 49 /* Hitachi H8/500 */ +#define EM_IA_64 50 /* Intel Merced */ +#define EM_MIPS_X 51 /* Stanford MIPS-X */ +#define EM_COLDFIRE 52 /* Motorola Coldfire */ +#define EM_68HC12 53 /* Motorola M68HC12 */ +#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/ +#define EM_PCP 55 /* Siemens PCP */ +#define EM_NCPU 56 /* Sony nCPU embeeded RISC */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor */ +#define EM_STARCORE 58 /* Motorola Start*Core processor */ +#define EM_ME16 59 /* Toyota ME16 processor */ +#define EM_ST100 60 /* STMicroelectronic ST100 processor */ +#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/ +#define EM_X86_64 62 /* AMD x86-64 architecture */ +#define EM_PDSP 63 /* Sony DSP Processor */ + +#define EM_FX66 66 /* Siemens FX66 microcontroller */ +#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */ +#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */ +#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */ +#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */ +#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */ +#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */ +#define EM_SVX 73 /* Silicon Graphics SVx */ +#define EM_AT19 74 /* STMicroelectronics ST19 8 bit mc */ +#define EM_VAX 75 /* Digital VAX */ +#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ +#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */ +#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ +#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ +#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */ +#define EM_HUANY 81 /* Harvard University machine-independent object files */ +#define EM_PRISM 82 /* SiTera Prism */ +#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ +#define EM_FR30 84 /* Fujitsu FR30 */ +#define EM_D10V 85 /* Mitsubishi D10V */ +#define EM_D30V 86 /* Mitsubishi D30V */ +#define EM_V850 87 /* NEC v850 */ +#define EM_M32R 88 /* Mitsubishi M32R */ +#define EM_MN10300 89 /* Matsushita MN10300 */ +#define EM_MN10200 90 /* Matsushita MN10200 */ +#define EM_PJ 91 /* picoJava */ +#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ +#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ +#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ +#define EM_NUM 95 + +/* If it is necessary to assign new unofficial EM_* values, please + pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the + chances of collision with official or non-GNU unofficial values. */ + +#define EM_ALPHA 0x9026 + +/* Legal values for e_version (version). */ + +#define EV_NONE 0 /* Invalid ELF version */ +#define EV_CURRENT 1 /* Current version */ +#define EV_NUM 2 + +/* Section header. */ + +typedef struct +{ + Elf32_Word sh_name; /* Section name (string tbl index) */ + Elf32_Word sh_type; /* Section type */ + Elf32_Word sh_flags; /* Section flags */ + Elf32_Addr sh_addr; /* Section virtual addr at execution */ + Elf32_Off sh_offset; /* Section file offset */ + Elf32_Word sh_size; /* Section size in bytes */ + Elf32_Word sh_link; /* Link to another section */ + Elf32_Word sh_info; /* Additional section information */ + Elf32_Word sh_addralign; /* Section alignment */ + Elf32_Word sh_entsize; /* Entry size if section holds table */ +} Elf32_Shdr; + +typedef struct +{ + Elf64_Word sh_name; /* Section name (string tbl index) */ + Elf64_Word sh_type; /* Section type */ + Elf64_Xword sh_flags; /* Section flags */ + Elf64_Addr sh_addr; /* Section virtual addr at execution */ + Elf64_Off sh_offset; /* Section file offset */ + Elf64_Xword sh_size; /* Section size in bytes */ + Elf64_Word sh_link; /* Link to another section */ + Elf64_Word sh_info; /* Additional section information */ + Elf64_Xword sh_addralign; /* Section alignment */ + Elf64_Xword sh_entsize; /* Entry size if section holds table */ +} Elf64_Shdr; + +/* Special section indices. */ + +#define SHN_UNDEF 0 /* Undefined section */ +#define SHN_LORESERVE 0xff00 /* Start of reserved indices */ +#define SHN_LOPROC 0xff00 /* Start of processor-specific */ +#define SHN_HIPROC 0xff1f /* End of processor-specific */ +#define SHN_LOOS 0xff20 /* Start of OS-specific */ +#define SHN_HIOS 0xff3f /* End of OS-specific */ +#define SHN_ABS 0xfff1 /* Associated symbol is absolute */ +#define SHN_COMMON 0xfff2 /* Associated symbol is common */ +#define SHN_XINDEX 0xffff /* Index is in extra table. */ +#define SHN_HIRESERVE 0xffff /* End of reserved indices */ + +/* Legal values for sh_type (section type). */ + +#define SHT_NULL 0 /* Section header table entry unused */ +#define SHT_PROGBITS 1 /* Program data */ +#define SHT_SYMTAB 2 /* Symbol table */ +#define SHT_STRTAB 3 /* String table */ +#define SHT_RELA 4 /* Relocation entries with addends */ +#define SHT_HASH 5 /* Symbol hash table */ +#define SHT_DYNAMIC 6 /* Dynamic linking information */ +#define SHT_NOTE 7 /* Notes */ +#define SHT_NOBITS 8 /* Program space with no data (bss) */ +#define SHT_REL 9 /* Relocation entries, no addends */ +#define SHT_SHLIB 10 /* Reserved */ +#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ +#define SHT_INIT_ARRAY 14 /* Array of constructors */ +#define SHT_FINI_ARRAY 15 /* Array of destructors */ +#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ +#define SHT_GROUP 17 /* Section group */ +#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ +#define SHT_NUM 19 /* Number of defined types. */ +#define SHT_LOOS 0x60000000 /* Start OS-specific */ +#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ +#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */ +#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */ +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ +#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ +#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ +#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */ +#define SHT_HIOS 0x6fffffff /* End OS-specific type */ +#define SHT_LOPROC 0x70000000 /* Start of processor-specific */ +#define SHT_HIPROC 0x7fffffff /* End of processor-specific */ +#define SHT_LOUSER 0x80000000 /* Start of application-specific */ +#define SHT_HIUSER 0x8fffffff /* End of application-specific */ + +/* Legal values for sh_flags (section flags). */ + +#define SHF_WRITE (1 << 0) /* Writable */ +#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ +#define SHF_EXECINSTR (1 << 2) /* Executable */ +#define SHF_MERGE (1 << 4) /* Might be merged */ +#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ +#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */ +#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */ +#define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling + required */ +#define SHF_GROUP (1 << 9) /* Section is member of a group. */ +#define SHF_TLS (1 << 10) /* Section hold thread-local data. */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific. */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific */ + +/* Section group handling. */ +#define GRP_COMDAT 0x1 /* Mark group as COMDAT. */ + +/* Symbol table entry. */ + +typedef struct +{ + Elf32_Word st_name; /* Symbol name (string tbl index) */ + Elf32_Addr st_value; /* Symbol value */ + Elf32_Word st_size; /* Symbol size */ + unsigned char st_info; /* Symbol type and binding */ + unsigned char st_other; /* Symbol visibility */ + Elf32_Section st_shndx; /* Section index */ +} Elf32_Sym; + +typedef struct +{ + Elf64_Word st_name; /* Symbol name (string tbl index) */ + unsigned char st_info; /* Symbol type and binding */ + unsigned char st_other; /* Symbol visibility */ + Elf64_Section st_shndx; /* Section index */ + Elf64_Addr st_value; /* Symbol value */ + Elf64_Xword st_size; /* Symbol size */ +} Elf64_Sym; + +/* The syminfo section if available contains additional information about + every dynamic symbol. */ + +typedef struct +{ + Elf32_Half si_boundto; /* Direct bindings, symbol bound to */ + Elf32_Half si_flags; /* Per symbol flags */ +} Elf32_Syminfo; + +typedef struct +{ + Elf64_Half si_boundto; /* Direct bindings, symbol bound to */ + Elf64_Half si_flags; /* Per symbol flags */ +} Elf64_Syminfo; + +/* Possible values for si_boundto. */ +#define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */ +#define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */ +#define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */ + +/* Possible bitmasks for si_flags. */ +#define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */ +#define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */ +#define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */ +#define SYMINFO_FLG_LAZYLOAD 0x0008 /* Symbol bound to object to be lazy + loaded */ +/* Syminfo version values. */ +#define SYMINFO_NONE 0 +#define SYMINFO_CURRENT 1 +#define SYMINFO_NUM 2 + + +/* How to extract and insert information held in the st_info field. */ + +#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4) +#define ELF32_ST_TYPE(val) ((val) & 0xf) +#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */ +#define ELF64_ST_BIND(val) ELF32_ST_BIND (val) +#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val) +#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type)) + +/* Legal values for ST_BIND subfield of st_info (symbol binding). */ + +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* Weak symbol */ +#define STB_NUM 3 /* Number of defined types. */ +#define STB_LOOS 10 /* Start of OS-specific */ +#define STB_HIOS 12 /* End of OS-specific */ +#define STB_LOPROC 13 /* Start of processor-specific */ +#define STB_HIPROC 15 /* End of processor-specific */ + +/* Legal values for ST_TYPE subfield of st_info (symbol type). */ + +#define STT_NOTYPE 0 /* Symbol type is unspecified */ +#define STT_OBJECT 1 /* Symbol is a data object */ +#define STT_FUNC 2 /* Symbol is a code object */ +#define STT_SECTION 3 /* Symbol associated with a section */ +#define STT_FILE 4 /* Symbol's name is file name */ +#define STT_COMMON 5 /* Symbol is a common data object */ +#define STT_TLS 6 /* Symbol is thread-local data object*/ +#define STT_NUM 7 /* Number of defined types. */ +#define STT_LOOS 10 /* Start of OS-specific */ +#define STT_HIOS 12 /* End of OS-specific */ +#define STT_LOPROC 13 /* Start of processor-specific */ +#define STT_HIPROC 15 /* End of processor-specific */ + + +/* Symbol table indices are found in the hash buckets and chain table + of a symbol hash table section. This special index value indicates + the end of a chain, meaning no further symbols are found in that bucket. */ + +#define STN_UNDEF 0 /* End of a chain. */ + + +/* How to extract and insert information held in the st_other field. */ + +#define ELF32_ST_VISIBILITY(o) ((o) & 0x03) + +/* For ELF64 the definitions are the same. */ +#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o) + +/* Symbol visibility specification encoded in the st_other field. */ +#define STV_DEFAULT 0 /* Default symbol visibility rules */ +#define STV_INTERNAL 1 /* Processor specific hidden class */ +#define STV_HIDDEN 2 /* Sym unavailable in other modules */ +#define STV_PROTECTED 3 /* Not preemptible, not exported */ + + +/* Relocation table entry without addend (in section of type SHT_REL). */ + +typedef struct +{ + Elf32_Addr r_offset; /* Address */ + Elf32_Word r_info; /* Relocation type and symbol index */ +} Elf32_Rel; + +/* I have seen two different definitions of the Elf64_Rel and + Elf64_Rela structures, so we'll leave them out until Novell (or + whoever) gets their act together. */ +/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */ + +typedef struct +{ + Elf64_Addr r_offset; /* Address */ + Elf64_Xword r_info; /* Relocation type and symbol index */ +} Elf64_Rel; + +/* Relocation table entry with addend (in section of type SHT_RELA). */ + +typedef struct +{ + Elf32_Addr r_offset; /* Address */ + Elf32_Word r_info; /* Relocation type and symbol index */ + Elf32_Sword r_addend; /* Addend */ +} Elf32_Rela; + +typedef struct +{ + Elf64_Addr r_offset; /* Address */ + Elf64_Xword r_info; /* Relocation type and symbol index */ + Elf64_Sxword r_addend; /* Addend */ +} Elf64_Rela; + +/* How to extract and insert information held in the r_info field. */ + +#define ELF32_R_SYM(val) ((val) >> 8) +#define ELF32_R_TYPE(val) ((val) & 0xff) +#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff)) + +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i) & 0xffffffff) +#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type)) + +/* Program segment header. */ + +typedef struct +{ + Elf32_Word p_type; /* Segment type */ + Elf32_Off p_offset; /* Segment file offset */ + Elf32_Addr p_vaddr; /* Segment virtual address */ + Elf32_Addr p_paddr; /* Segment physical address */ + Elf32_Word p_filesz; /* Segment size in file */ + Elf32_Word p_memsz; /* Segment size in memory */ + Elf32_Word p_flags; /* Segment flags */ + Elf32_Word p_align; /* Segment alignment */ +} Elf32_Phdr; + +typedef struct +{ + Elf64_Word p_type; /* Segment type */ + Elf64_Word p_flags; /* Segment flags */ + Elf64_Off p_offset; /* Segment file offset */ + Elf64_Addr p_vaddr; /* Segment virtual address */ + Elf64_Addr p_paddr; /* Segment physical address */ + Elf64_Xword p_filesz; /* Segment size in file */ + Elf64_Xword p_memsz; /* Segment size in memory */ + Elf64_Xword p_align; /* Segment alignment */ +} Elf64_Phdr; + +/* Legal values for p_type (segment type). */ + +#define PT_NULL 0 /* Program header table entry unused */ +#define PT_LOAD 1 /* Loadable program segment */ +#define PT_DYNAMIC 2 /* Dynamic linking information */ +#define PT_INTERP 3 /* Program interpreter */ +#define PT_NOTE 4 /* Auxiliary information */ +#define PT_SHLIB 5 /* Reserved */ +#define PT_PHDR 6 /* Entry for header table itself */ +#define PT_TLS 7 /* Thread-local storage segment */ +#define PT_NUM 8 /* Number of defined types */ +#define PT_LOOS 0x60000000 /* Start of OS-specific */ +#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */ +#define PT_LOSUNW 0x6ffffffa +#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ +#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */ +#define PT_HISUNW 0x6fffffff +#define PT_HIOS 0x6fffffff /* End of OS-specific */ +#define PT_LOPROC 0x70000000 /* Start of processor-specific */ +#define PT_HIPROC 0x7fffffff /* End of processor-specific */ + +/* Legal values for p_flags (segment flags). */ + +#define PF_X (1 << 0) /* Segment is executable */ +#define PF_W (1 << 1) /* Segment is writable */ +#define PF_R (1 << 2) /* Segment is readable */ +#define PF_MASKOS 0x0ff00000 /* OS-specific */ +#define PF_MASKPROC 0xf0000000 /* Processor-specific */ + +/* Legal values for note segment descriptor types for core files. */ + +#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */ +#define NT_FPREGSET 2 /* Contains copy of fpregset struct */ +#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */ +#define NT_PRXREG 4 /* Contains copy of prxregset struct */ +#define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */ +#define NT_AUXV 6 /* Contains copy of auxv array */ +#define NT_GWINDOWS 7 /* Contains copy of gwindows struct */ +#define NT_ASRS 8 /* Contains copy of asrset struct */ +#define NT_PSTATUS 10 /* Contains copy of pstatus struct */ +#define NT_PSINFO 13 /* Contains copy of psinfo struct */ +#define NT_PRCRED 14 /* Contains copy of prcred struct */ +#define NT_UTSNAME 15 /* Contains copy of utsname struct */ +#define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */ +#define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */ +#define NT_PRFPXREG 20 /* Contains copy of fprxregset struct*/ + +/* Legal values for the note segment descriptor types for object files. */ + +#define NT_VERSION 1 /* Contains a version string. */ + + +/* Dynamic section entry. */ + +typedef struct +{ + Elf32_Sword d_tag; /* Dynamic entry type */ + union + { + Elf32_Word d_val; /* Integer value */ + Elf32_Addr d_ptr; /* Address value */ + } d_un; +} Elf32_Dyn; + +typedef struct +{ + Elf64_Sxword d_tag; /* Dynamic entry type */ + union + { + Elf64_Xword d_val; /* Integer value */ + Elf64_Addr d_ptr; /* Address value */ + } d_un; +} Elf64_Dyn; + +/* Legal values for d_tag (dynamic entry type). */ + +#define DT_NULL 0 /* Marks end of dynamic section */ +#define DT_NEEDED 1 /* Name of needed library */ +#define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */ +#define DT_PLTGOT 3 /* Processor defined value */ +#define DT_HASH 4 /* Address of symbol hash table */ +#define DT_STRTAB 5 /* Address of string table */ +#define DT_SYMTAB 6 /* Address of symbol table */ +#define DT_RELA 7 /* Address of Rela relocs */ +#define DT_RELASZ 8 /* Total size of Rela relocs */ +#define DT_RELAENT 9 /* Size of one Rela reloc */ +#define DT_STRSZ 10 /* Size of string table */ +#define DT_SYMENT 11 /* Size of one symbol table entry */ +#define DT_INIT 12 /* Address of init function */ +#define DT_FINI 13 /* Address of termination function */ +#define DT_SONAME 14 /* Name of shared object */ +#define DT_RPATH 15 /* Library search path (deprecated) */ +#define DT_SYMBOLIC 16 /* Start symbol search here */ +#define DT_REL 17 /* Address of Rel relocs */ +#define DT_RELSZ 18 /* Total size of Rel relocs */ +#define DT_RELENT 19 /* Size of one Rel reloc */ +#define DT_PLTREL 20 /* Type of reloc in PLT */ +#define DT_DEBUG 21 /* For debugging; unspecified */ +#define DT_TEXTREL 22 /* Reloc might modify .text */ +#define DT_JMPREL 23 /* Address of PLT relocs */ +#define DT_BIND_NOW 24 /* Process relocations of object */ +#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */ +#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */ +#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */ +#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */ +#define DT_RUNPATH 29 /* Library search path */ +#define DT_FLAGS 30 /* Flags for the object being loaded */ +#define DT_ENCODING 32 /* Start of encoded range */ +#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/ +#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */ +#define DT_NUM 34 /* Number used */ +#define DT_LOOS 0x6000000d /* Start of OS-specific */ +#define DT_HIOS 0x6ffff000 /* End of OS-specific */ +#define DT_LOPROC 0x70000000 /* Start of processor-specific */ +#define DT_HIPROC 0x7fffffff /* End of processor-specific */ +#define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */ + +/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the + Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's + approach. */ +#define DT_VALRNGLO 0x6ffffd00 +#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */ +#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */ +#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */ +#define DT_CHECKSUM 0x6ffffdf8 +#define DT_PLTPADSZ 0x6ffffdf9 +#define DT_MOVEENT 0x6ffffdfa +#define DT_MOVESZ 0x6ffffdfb +#define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */ +#define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting + the following DT_* entry. */ +#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */ +#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */ +#define DT_VALRNGHI 0x6ffffdff +#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */ +#define DT_VALNUM 12 + +/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the + Dyn.d_un.d_ptr field of the Elf*_Dyn structure. + + If any adjustment is made to the ELF object after it has been + built these entries will need to be adjusted. */ +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */ +#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */ +#define DT_CONFIG 0x6ffffefa /* Configuration information. */ +#define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */ +#define DT_AUDIT 0x6ffffefc /* Object auditing. */ +#define DT_PLTPAD 0x6ffffefd /* PLT padding. */ +#define DT_MOVETAB 0x6ffffefe /* Move table. */ +#define DT_SYMINFO 0x6ffffeff /* Syminfo table. */ +#define DT_ADDRRNGHI 0x6ffffeff +#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */ +#define DT_ADDRNUM 10 + +/* The versioning entry types. The next are defined as part of the + GNU extension. */ +#define DT_VERSYM 0x6ffffff0 + +#define DT_RELACOUNT 0x6ffffff9 +#define DT_RELCOUNT 0x6ffffffa + +/* These were chosen by Sun. */ +#define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */ +#define DT_VERDEF 0x6ffffffc /* Address of version definition + table */ +#define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */ +#define DT_VERNEED 0x6ffffffe /* Address of table with needed + versions */ +#define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */ +#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ +#define DT_VERSIONTAGNUM 16 + +/* Sun added these machine-independent extensions in the "processor-specific" + range. Be compatible. */ +#define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */ +#define DT_FILTER 0x7fffffff /* Shared object to get values from */ +#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1) +#define DT_EXTRANUM 3 + +/* Values of `d_un.d_val' in the DT_FLAGS entry. */ +#define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */ +#define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */ +#define DF_TEXTREL 0x00000004 /* Object contains text relocations */ +#define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */ +#define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */ + +/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 + entry in the dynamic section. */ +#define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */ +#define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */ +#define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */ +#define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/ +#define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/ +#define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/ +#define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */ +#define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */ +#define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */ +#define DF_1_TRANS 0x00000200 +#define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */ +#define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */ +#define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */ +#define DF_1_CONFALT 0x00002000 /* Configuration alternative created.*/ +#define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */ +#define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */ +#define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */ + +/* Flags for the feature selection in DT_FEATURE_1. */ +#define DTF_1_PARINIT 0x00000001 +#define DTF_1_CONFEXP 0x00000002 + +/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */ +#define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */ +#define DF_P1_GROUPPERM 0x00000002 /* Symbols from next object are not + generally available. */ + +/* Version definition sections. */ + +typedef struct +{ + Elf32_Half vd_version; /* Version revision */ + Elf32_Half vd_flags; /* Version information */ + Elf32_Half vd_ndx; /* Version Index */ + Elf32_Half vd_cnt; /* Number of associated aux entries */ + Elf32_Word vd_hash; /* Version name hash value */ + Elf32_Word vd_aux; /* Offset in bytes to verdaux array */ + Elf32_Word vd_next; /* Offset in bytes to next verdef + entry */ +} Elf32_Verdef; + +typedef struct +{ + Elf64_Half vd_version; /* Version revision */ + Elf64_Half vd_flags; /* Version information */ + Elf64_Half vd_ndx; /* Version Index */ + Elf64_Half vd_cnt; /* Number of associated aux entries */ + Elf64_Word vd_hash; /* Version name hash value */ + Elf64_Word vd_aux; /* Offset in bytes to verdaux array */ + Elf64_Word vd_next; /* Offset in bytes to next verdef + entry */ +} Elf64_Verdef; + + +/* Legal values for vd_version (version revision). */ +#define VER_DEF_NONE 0 /* No version */ +#define VER_DEF_CURRENT 1 /* Current version */ +#define VER_DEF_NUM 2 /* Given version number */ + +/* Legal values for vd_flags (version information flags). */ +#define VER_FLG_BASE 0x1 /* Version definition of file itself */ +#define VER_FLG_WEAK 0x2 /* Weak version identifier */ + +/* Versym symbol index values. */ +#define VER_NDX_LOCAL 0 /* Symbol is local. */ +#define VER_NDX_GLOBAL 1 /* Symbol is global. */ +#define VER_NDX_LORESERVE 0xff00 /* Beginning of reserved entries. */ +#define VER_NDX_ELIMINATE 0xff01 /* Symbol is to be eliminated. */ + +/* Auxialiary version information. */ + +typedef struct +{ + Elf32_Word vda_name; /* Version or dependency names */ + Elf32_Word vda_next; /* Offset in bytes to next verdaux + entry */ +} Elf32_Verdaux; + +typedef struct +{ + Elf64_Word vda_name; /* Version or dependency names */ + Elf64_Word vda_next; /* Offset in bytes to next verdaux + entry */ +} Elf64_Verdaux; + + +/* Version dependency section. */ + +typedef struct +{ + Elf32_Half vn_version; /* Version of structure */ + Elf32_Half vn_cnt; /* Number of associated aux entries */ + Elf32_Word vn_file; /* Offset of filename for this + dependency */ + Elf32_Word vn_aux; /* Offset in bytes to vernaux array */ + Elf32_Word vn_next; /* Offset in bytes to next verneed + entry */ +} Elf32_Verneed; + +typedef struct +{ + Elf64_Half vn_version; /* Version of structure */ + Elf64_Half vn_cnt; /* Number of associated aux entries */ + Elf64_Word vn_file; /* Offset of filename for this + dependency */ + Elf64_Word vn_aux; /* Offset in bytes to vernaux array */ + Elf64_Word vn_next; /* Offset in bytes to next verneed + entry */ +} Elf64_Verneed; + + +/* Legal values for vn_version (version revision). */ +#define VER_NEED_NONE 0 /* No version */ +#define VER_NEED_CURRENT 1 /* Current version */ +#define VER_NEED_NUM 2 /* Given version number */ + +/* Auxiliary needed version information. */ + +typedef struct +{ + Elf32_Word vna_hash; /* Hash value of dependency name */ + Elf32_Half vna_flags; /* Dependency specific information */ + Elf32_Half vna_other; /* Unused */ + Elf32_Word vna_name; /* Dependency name string offset */ + Elf32_Word vna_next; /* Offset in bytes to next vernaux + entry */ +} Elf32_Vernaux; + +typedef struct +{ + Elf64_Word vna_hash; /* Hash value of dependency name */ + Elf64_Half vna_flags; /* Dependency specific information */ + Elf64_Half vna_other; /* Unused */ + Elf64_Word vna_name; /* Dependency name string offset */ + Elf64_Word vna_next; /* Offset in bytes to next vernaux + entry */ +} Elf64_Vernaux; + + +/* Legal values for vna_flags. */ +#define VER_FLG_WEAK 0x2 /* Weak version identifier */ + + +/* Auxiliary vector. */ + +/* This vector is normally only used by the program interpreter. The + usual definition in an ABI supplement uses the name auxv_t. The + vector is not usually defined in a standard file, but it + can't hurt. We rename it to avoid conflicts. The sizes of these + types are an arrangement between the exec server and the program + interpreter, so we don't fully specify them here. */ + +typedef struct +{ + int a_type; /* Entry type */ + union + { + long int a_val; /* Integer value */ + void *a_ptr; /* Pointer value */ + void (*a_fcn) (void); /* Function pointer value */ + } a_un; +} Elf32_auxv_t; + +typedef struct +{ + long int a_type; /* Entry type */ + union + { + long int a_val; /* Integer value */ + void *a_ptr; /* Pointer value */ + void (*a_fcn) (void); /* Function pointer value */ + } a_un; +} Elf64_auxv_t; + +/* Legal values for a_type (entry type). */ + +#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_CLKTCK 17 /* Frequency of times() */ + +/* Some more special a_type values describing the hardware. */ +#define AT_PLATFORM 15 /* String identifying platform. */ +#define AT_HWCAP 16 /* Machine dependent hints about + processor capabilities. */ + +/* This entry gives some information about the FPU initialization + performed by the kernel. */ +#define AT_FPUCW 18 /* Used FPU control word. */ + +/* Cache block sizes. */ +#define AT_DCACHEBSIZE 19 /* Data cache block size. */ +#define AT_ICACHEBSIZE 20 /* Instruction cache block size. */ +#define AT_UCACHEBSIZE 21 /* Unified cache block size. */ + +/* A special ignored value for PPC, used by the kernel to control the + interpretation of the AUXV. Must be > 16. */ +#define AT_IGNOREPPC 22 /* Entry should be ignored */ + + +/* Note section contents. Each entry in the note section begins with + a header of a fixed form. */ + +typedef struct +{ + Elf32_Word n_namesz; /* Length of the note's name. */ + Elf32_Word n_descsz; /* Length of the note's descriptor. */ + Elf32_Word n_type; /* Type of the note. */ +} Elf32_Nhdr; + +typedef struct +{ + Elf64_Word n_namesz; /* Length of the note's name. */ + Elf64_Word n_descsz; /* Length of the note's descriptor. */ + Elf64_Word n_type; /* Type of the note. */ +} Elf64_Nhdr; + +/* Known names of notes. */ + +/* Solaris entries in the note section have this name. */ +#define ELF_NOTE_SOLARIS "SUNW Solaris" + +/* Note entries for GNU systems have this name. */ +#define ELF_NOTE_GNU "GNU" + + +/* Defined types of notes for Solaris. */ + +/* Value of descriptor (one word) is desired pagesize for the binary. */ +#define ELF_NOTE_PAGESIZE_HINT 1 + + +/* Defined note types for GNU systems. */ + +/* ABI information. The descriptor consists of words: + word 0: OS descriptor + word 1: major version of the ABI + word 2: minor version of the ABI + word 3: subminor version of the ABI +*/ +#define ELF_NOTE_ABI 1 + +/* Known OSes. These value can appear in word 0 of an ELF_NOTE_ABI + note section entry. */ +#define ELF_NOTE_OS_LINUX 0 +#define ELF_NOTE_OS_GNU 1 +#define ELF_NOTE_OS_SOLARIS2 2 + + +/* Move records. */ +typedef struct +{ + Elf32_Xword m_value; /* Symbol value. */ + Elf32_Word m_info; /* Size and index. */ + Elf32_Word m_poffset; /* Symbol offset. */ + Elf32_Half m_repeat; /* Repeat count. */ + Elf32_Half m_stride; /* Stride info. */ +} Elf32_Move; + +typedef struct +{ + Elf64_Xword m_value; /* Symbol value. */ + Elf64_Xword m_info; /* Size and index. */ + Elf64_Xword m_poffset; /* Symbol offset. */ + Elf64_Half m_repeat; /* Repeat count. */ + Elf64_Half m_stride; /* Stride info. */ +} Elf64_Move; + +/* Macro to construct move records. */ +#define ELF32_M_SYM(info) ((info) >> 8) +#define ELF32_M_SIZE(info) ((unsigned char) (info)) +#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char) (size)) + +#define ELF64_M_SYM(info) ELF32_M_SYM (info) +#define ELF64_M_SIZE(info) ELF32_M_SIZE (info) +#define ELF64_M_INFO(sym, size) ELF32_M_INFO (sym, size) + + +/* Motorola 68k specific definitions. */ + +/* Values for Elf32_Ehdr.e_flags. */ +#define EF_CPU32 0x00810000 + +/* m68k relocs. */ + +#define R_68K_NONE 0 /* No reloc */ +#define R_68K_32 1 /* Direct 32 bit */ +#define R_68K_16 2 /* Direct 16 bit */ +#define R_68K_8 3 /* Direct 8 bit */ +#define R_68K_PC32 4 /* PC relative 32 bit */ +#define R_68K_PC16 5 /* PC relative 16 bit */ +#define R_68K_PC8 6 /* PC relative 8 bit */ +#define R_68K_GOT32 7 /* 32 bit PC relative GOT entry */ +#define R_68K_GOT16 8 /* 16 bit PC relative GOT entry */ +#define R_68K_GOT8 9 /* 8 bit PC relative GOT entry */ +#define R_68K_GOT32O 10 /* 32 bit GOT offset */ +#define R_68K_GOT16O 11 /* 16 bit GOT offset */ +#define R_68K_GOT8O 12 /* 8 bit GOT offset */ +#define R_68K_PLT32 13 /* 32 bit PC relative PLT address */ +#define R_68K_PLT16 14 /* 16 bit PC relative PLT address */ +#define R_68K_PLT8 15 /* 8 bit PC relative PLT address */ +#define R_68K_PLT32O 16 /* 32 bit PLT offset */ +#define R_68K_PLT16O 17 /* 16 bit PLT offset */ +#define R_68K_PLT8O 18 /* 8 bit PLT offset */ +#define R_68K_COPY 19 /* Copy symbol at runtime */ +#define R_68K_GLOB_DAT 20 /* Create GOT entry */ +#define R_68K_JMP_SLOT 21 /* Create PLT entry */ +#define R_68K_RELATIVE 22 /* Adjust by program base */ +/* Keep this the last entry. */ +#define R_68K_NUM 23 + +/* Intel 80386 specific definitions. */ + +/* i386 relocs. */ + +#define R_386_NONE 0 /* No reloc */ +#define R_386_32 1 /* Direct 32 bit */ +#define R_386_PC32 2 /* PC relative 32 bit */ +#define R_386_GOT32 3 /* 32 bit GOT entry */ +#define R_386_PLT32 4 /* 32 bit PLT address */ +#define R_386_COPY 5 /* Copy symbol at runtime */ +#define R_386_GLOB_DAT 6 /* Create GOT entry */ +#define R_386_JMP_SLOT 7 /* Create PLT entry */ +#define R_386_RELATIVE 8 /* Adjust by program base */ +#define R_386_GOTOFF 9 /* 32 bit offset to GOT */ +#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */ +#define R_386_32PLT 11 +#define R_386_TLS_TPOFF 14 /* Offset in static TLS block */ +#define R_386_TLS_IE 15 /* Address of GOT entry for static TLS + block offset */ +#define R_386_TLS_GOTIE 16 /* GOT entry for static TLS block + offset */ +#define R_386_TLS_LE 17 /* Offset relative to static TLS + block */ +#define R_386_TLS_GD 18 /* Direct 32 bit for GNU version of + general dynamic thread local data */ +#define R_386_TLS_LDM 19 /* Direct 32 bit for GNU version of + local dynamic thread local data + in LE code */ +#define R_386_16 20 +#define R_386_PC16 21 +#define R_386_8 22 +#define R_386_PC8 23 +#define R_386_TLS_GD_32 24 /* Direct 32 bit for general dynamic + thread local data */ +#define R_386_TLS_GD_PUSH 25 /* Tag for pushl in GD TLS code */ +#define R_386_TLS_GD_CALL 26 /* Relocation for call to + __tls_get_addr() */ +#define R_386_TLS_GD_POP 27 /* Tag for popl in GD TLS code */ +#define R_386_TLS_LDM_32 28 /* Direct 32 bit for local dynamic + thread local data in LE code */ +#define R_386_TLS_LDM_PUSH 29 /* Tag for pushl in LDM TLS code */ +#define R_386_TLS_LDM_CALL 30 /* Relocation for call to + __tls_get_addr() in LDM code */ +#define R_386_TLS_LDM_POP 31 /* Tag for popl in LDM TLS code */ +#define R_386_TLS_LDO_32 32 /* Offset relative to TLS block */ +#define R_386_TLS_IE_32 33 /* GOT entry for negated static TLS + block offset */ +#define R_386_TLS_LE_32 34 /* Negated offset relative to static + TLS block */ +#define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */ +#define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */ +#define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */ +/* Keep this the last entry. */ +#define R_386_NUM 38 + +/* SUN SPARC specific definitions. */ + +/* Legal values for ST_TYPE subfield of st_info (symbol type). */ + +#define STT_REGISTER 13 /* Global register reserved to app. */ + +/* Values for Elf64_Ehdr.e_flags. */ + +#define EF_SPARCV9_MM 3 +#define EF_SPARCV9_TSO 0 +#define EF_SPARCV9_PSO 1 +#define EF_SPARCV9_RMO 2 +#define EF_SPARC_LEDATA 0x800000 /* little endian data */ +#define EF_SPARC_EXT_MASK 0xFFFF00 +#define EF_SPARC_32PLUS 0x000100 /* generic V8+ features */ +#define EF_SPARC_SUN_US1 0x000200 /* Sun UltraSPARC1 extensions */ +#define EF_SPARC_HAL_R1 0x000400 /* HAL R1 extensions */ +#define EF_SPARC_SUN_US3 0x000800 /* Sun UltraSPARCIII extensions */ + +/* SPARC relocs. */ + +#define R_SPARC_NONE 0 /* No reloc */ +#define R_SPARC_8 1 /* Direct 8 bit */ +#define R_SPARC_16 2 /* Direct 16 bit */ +#define R_SPARC_32 3 /* Direct 32 bit */ +#define R_SPARC_DISP8 4 /* PC relative 8 bit */ +#define R_SPARC_DISP16 5 /* PC relative 16 bit */ +#define R_SPARC_DISP32 6 /* PC relative 32 bit */ +#define R_SPARC_WDISP30 7 /* PC relative 30 bit shifted */ +#define R_SPARC_WDISP22 8 /* PC relative 22 bit shifted */ +#define R_SPARC_HI22 9 /* High 22 bit */ +#define R_SPARC_22 10 /* Direct 22 bit */ +#define R_SPARC_13 11 /* Direct 13 bit */ +#define R_SPARC_LO10 12 /* Truncated 10 bit */ +#define R_SPARC_GOT10 13 /* Truncated 10 bit GOT entry */ +#define R_SPARC_GOT13 14 /* 13 bit GOT entry */ +#define R_SPARC_GOT22 15 /* 22 bit GOT entry shifted */ +#define R_SPARC_PC10 16 /* PC relative 10 bit truncated */ +#define R_SPARC_PC22 17 /* PC relative 22 bit shifted */ +#define R_SPARC_WPLT30 18 /* 30 bit PC relative PLT address */ +#define R_SPARC_COPY 19 /* Copy symbol at runtime */ +#define R_SPARC_GLOB_DAT 20 /* Create GOT entry */ +#define R_SPARC_JMP_SLOT 21 /* Create PLT entry */ +#define R_SPARC_RELATIVE 22 /* Adjust by program base */ +#define R_SPARC_UA32 23 /* Direct 32 bit unaligned */ + +/* Additional Sparc64 relocs. */ + +#define R_SPARC_PLT32 24 /* Direct 32 bit ref to PLT entry */ +#define R_SPARC_HIPLT22 25 /* High 22 bit PLT entry */ +#define R_SPARC_LOPLT10 26 /* Truncated 10 bit PLT entry */ +#define R_SPARC_PCPLT32 27 /* PC rel 32 bit ref to PLT entry */ +#define R_SPARC_PCPLT22 28 /* PC rel high 22 bit PLT entry */ +#define R_SPARC_PCPLT10 29 /* PC rel trunc 10 bit PLT entry */ +#define R_SPARC_10 30 /* Direct 10 bit */ +#define R_SPARC_11 31 /* Direct 11 bit */ +#define R_SPARC_64 32 /* Direct 64 bit */ +#define R_SPARC_OLO10 33 /* 10bit with secondary 13bit addend */ +#define R_SPARC_HH22 34 /* Top 22 bits of direct 64 bit */ +#define R_SPARC_HM10 35 /* High middle 10 bits of ... */ +#define R_SPARC_LM22 36 /* Low middle 22 bits of ... */ +#define R_SPARC_PC_HH22 37 /* Top 22 bits of pc rel 64 bit */ +#define R_SPARC_PC_HM10 38 /* High middle 10 bit of ... */ +#define R_SPARC_PC_LM22 39 /* Low miggle 22 bits of ... */ +#define R_SPARC_WDISP16 40 /* PC relative 16 bit shifted */ +#define R_SPARC_WDISP19 41 /* PC relative 19 bit shifted */ +#define R_SPARC_7 43 /* Direct 7 bit */ +#define R_SPARC_5 44 /* Direct 5 bit */ +#define R_SPARC_6 45 /* Direct 6 bit */ +#define R_SPARC_DISP64 46 /* PC relative 64 bit */ +#define R_SPARC_PLT64 47 /* Direct 64 bit ref to PLT entry */ +#define R_SPARC_HIX22 48 /* High 22 bit complemented */ +#define R_SPARC_LOX10 49 /* Truncated 11 bit complemented */ +#define R_SPARC_H44 50 /* Direct high 12 of 44 bit */ +#define R_SPARC_M44 51 /* Direct mid 22 of 44 bit */ +#define R_SPARC_L44 52 /* Direct low 10 of 44 bit */ +#define R_SPARC_REGISTER 53 /* Global register usage */ +#define R_SPARC_UA64 54 /* Direct 64 bit unaligned */ +#define R_SPARC_UA16 55 /* Direct 16 bit unaligned */ +#define R_SPARC_TLS_GD_HI22 56 +#define R_SPARC_TLS_GD_LO10 57 +#define R_SPARC_TLS_GD_ADD 58 +#define R_SPARC_TLS_GD_CALL 59 +#define R_SPARC_TLS_LDM_HI22 60 +#define R_SPARC_TLS_LDM_LO10 61 +#define R_SPARC_TLS_LDM_ADD 62 +#define R_SPARC_TLS_LDM_CALL 63 +#define R_SPARC_TLS_LDO_HIX22 64 +#define R_SPARC_TLS_LDO_LOX10 65 +#define R_SPARC_TLS_LDO_ADD 66 +#define R_SPARC_TLS_IE_HI22 67 +#define R_SPARC_TLS_IE_LO10 68 +#define R_SPARC_TLS_IE_LD 69 +#define R_SPARC_TLS_IE_LDX 70 +#define R_SPARC_TLS_IE_ADD 71 +#define R_SPARC_TLS_LE_HIX22 72 +#define R_SPARC_TLS_LE_LOX10 73 +#define R_SPARC_TLS_DTPMOD32 74 +#define R_SPARC_TLS_DTPMOD64 75 +#define R_SPARC_TLS_DTPOFF32 76 +#define R_SPARC_TLS_DTPOFF64 77 +#define R_SPARC_TLS_TPOFF32 78 +#define R_SPARC_TLS_TPOFF64 79 +/* Keep this the last entry. */ +#define R_SPARC_NUM 80 + +/* For Sparc64, legal values for d_tag of Elf64_Dyn. */ + +#define DT_SPARC_REGISTER 0x70000001 +#define DT_SPARC_NUM 2 + +/* Bits present in AT_HWCAP, primarily for Sparc32. */ + +#define HWCAP_SPARC_FLUSH 1 /* The cpu supports flush insn. */ +#define HWCAP_SPARC_STBAR 2 +#define HWCAP_SPARC_SWAP 4 +#define HWCAP_SPARC_MULDIV 8 +#define HWCAP_SPARC_V9 16 /* The cpu is v9, so v8plus is ok. */ +#define HWCAP_SPARC_ULTRA3 32 + +/* MIPS R3000 specific definitions. */ + +/* Legal values for e_flags field of Elf32_Ehdr. */ + +#define EF_MIPS_NOREORDER 1 /* A .noreorder directive was used */ +#define EF_MIPS_PIC 2 /* Contains PIC code */ +#define EF_MIPS_CPIC 4 /* Uses PIC calling sequence */ +#define EF_MIPS_XGOT 8 +#define EF_MIPS_64BIT_WHIRL 16 +#define EF_MIPS_ABI2 32 +#define EF_MIPS_ABI_ON32 64 +#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level */ + +/* Legal values for MIPS architecture level. */ + +#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ +#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ +#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ +#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ +#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ +#define EF_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */ +#define EF_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */ + +/* The following are non-official names and should not be used. */ + +#define E_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ +#define E_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ +#define E_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ +#define E_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ +#define E_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ +#define E_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */ +#define E_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */ + +/* Special section indices. */ + +#define SHN_MIPS_ACOMMON 0xff00 /* Allocated common symbols */ +#define SHN_MIPS_TEXT 0xff01 /* Allocated test symbols. */ +#define SHN_MIPS_DATA 0xff02 /* Allocated data symbols. */ +#define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols */ +#define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols */ + +/* Legal values for sh_type field of Elf32_Shdr. */ + +#define SHT_MIPS_LIBLIST 0x70000000 /* Shared objects used in link */ +#define SHT_MIPS_MSYM 0x70000001 +#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicting symbols */ +#define SHT_MIPS_GPTAB 0x70000003 /* Global data area sizes */ +#define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */ +#define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging information*/ +#define SHT_MIPS_REGINFO 0x70000006 /* Register usage information */ +#define SHT_MIPS_PACKAGE 0x70000007 +#define SHT_MIPS_PACKSYM 0x70000008 +#define SHT_MIPS_RELD 0x70000009 +#define SHT_MIPS_IFACE 0x7000000b +#define SHT_MIPS_CONTENT 0x7000000c +#define SHT_MIPS_OPTIONS 0x7000000d /* Miscellaneous options. */ +#define SHT_MIPS_SHDR 0x70000010 +#define SHT_MIPS_FDESC 0x70000011 +#define SHT_MIPS_EXTSYM 0x70000012 +#define SHT_MIPS_DENSE 0x70000013 +#define SHT_MIPS_PDESC 0x70000014 +#define SHT_MIPS_LOCSYM 0x70000015 +#define SHT_MIPS_AUXSYM 0x70000016 +#define SHT_MIPS_OPTSYM 0x70000017 +#define SHT_MIPS_LOCSTR 0x70000018 +#define SHT_MIPS_LINE 0x70000019 +#define SHT_MIPS_RFDESC 0x7000001a +#define SHT_MIPS_DELTASYM 0x7000001b +#define SHT_MIPS_DELTAINST 0x7000001c +#define SHT_MIPS_DELTACLASS 0x7000001d +#define SHT_MIPS_DWARF 0x7000001e /* DWARF debugging information. */ +#define SHT_MIPS_DELTADECL 0x7000001f +#define SHT_MIPS_SYMBOL_LIB 0x70000020 +#define SHT_MIPS_EVENTS 0x70000021 /* Event section. */ +#define SHT_MIPS_TRANSLATE 0x70000022 +#define SHT_MIPS_PIXIE 0x70000023 +#define SHT_MIPS_XLATE 0x70000024 +#define SHT_MIPS_XLATE_DEBUG 0x70000025 +#define SHT_MIPS_WHIRL 0x70000026 +#define SHT_MIPS_EH_REGION 0x70000027 +#define SHT_MIPS_XLATE_OLD 0x70000028 +#define SHT_MIPS_PDR_EXCEPTION 0x70000029 + +/* Legal values for sh_flags field of Elf32_Shdr. */ + +#define SHF_MIPS_GPREL 0x10000000 /* Must be part of global data area */ +#define SHF_MIPS_MERGE 0x20000000 +#define SHF_MIPS_ADDR 0x40000000 +#define SHF_MIPS_STRINGS 0x80000000 +#define SHF_MIPS_NOSTRIP 0x08000000 +#define SHF_MIPS_LOCAL 0x04000000 +#define SHF_MIPS_NAMES 0x02000000 +#define SHF_MIPS_NODUPE 0x01000000 + + +/* Symbol tables. */ + +/* MIPS specific values for `st_other'. */ +#define STO_MIPS_DEFAULT 0x0 +#define STO_MIPS_INTERNAL 0x1 +#define STO_MIPS_HIDDEN 0x2 +#define STO_MIPS_PROTECTED 0x3 +#define STO_MIPS_SC_ALIGN_UNUSED 0xff + +/* MIPS specific values for `st_info'. */ +#define STB_MIPS_SPLIT_COMMON 13 + +/* Entries found in sections of type SHT_MIPS_GPTAB. */ + +typedef union +{ + struct + { + Elf32_Word gt_current_g_value; /* -G value used for compilation */ + Elf32_Word gt_unused; /* Not used */ + } gt_header; /* First entry in section */ + struct + { + Elf32_Word gt_g_value; /* If this value were used for -G */ + Elf32_Word gt_bytes; /* This many bytes would be used */ + } gt_entry; /* Subsequent entries in section */ +} Elf32_gptab; + +/* Entry found in sections of type SHT_MIPS_REGINFO. */ + +typedef struct +{ + Elf32_Word ri_gprmask; /* General registers used */ + Elf32_Word ri_cprmask[4]; /* Coprocessor registers used */ + Elf32_Sword ri_gp_value; /* $gp register value */ +} Elf32_RegInfo; + +/* Entries found in sections of type SHT_MIPS_OPTIONS. */ + +typedef struct +{ + unsigned char kind; /* Determines interpretation of the + variable part of descriptor. */ + unsigned char size; /* Size of descriptor, including header. */ + Elf32_Section section; /* Section header index of section affected, + 0 for global options. */ + Elf32_Word info; /* Kind-specific information. */ +} Elf_Options; + +/* Values for `kind' field in Elf_Options. */ + +#define ODK_NULL 0 /* Undefined. */ +#define ODK_REGINFO 1 /* Register usage information. */ +#define ODK_EXCEPTIONS 2 /* Exception processing options. */ +#define ODK_PAD 3 /* Section padding options. */ +#define ODK_HWPATCH 4 /* Hardware workarounds performed */ +#define ODK_FILL 5 /* record the fill value used by the linker. */ +#define ODK_TAGS 6 /* reserve space for desktop tools to write. */ +#define ODK_HWAND 7 /* HW workarounds. 'AND' bits when merging. */ +#define ODK_HWOR 8 /* HW workarounds. 'OR' bits when merging. */ + +/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries. */ + +#define OEX_FPU_MIN 0x1f /* FPE's which MUST be enabled. */ +#define OEX_FPU_MAX 0x1f00 /* FPE's which MAY be enabled. */ +#define OEX_PAGE0 0x10000 /* page zero must be mapped. */ +#define OEX_SMM 0x20000 /* Force sequential memory mode? */ +#define OEX_FPDBUG 0x40000 /* Force floating point debug mode? */ +#define OEX_PRECISEFP OEX_FPDBUG +#define OEX_DISMISS 0x80000 /* Dismiss invalid address faults? */ + +#define OEX_FPU_INVAL 0x10 +#define OEX_FPU_DIV0 0x08 +#define OEX_FPU_OFLO 0x04 +#define OEX_FPU_UFLO 0x02 +#define OEX_FPU_INEX 0x01 + +/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry. */ + +#define OHW_R4KEOP 0x1 /* R4000 end-of-page patch. */ +#define OHW_R8KPFETCH 0x2 /* may need R8000 prefetch patch. */ +#define OHW_R5KEOP 0x4 /* R5000 end-of-page patch. */ +#define OHW_R5KCVTL 0x8 /* R5000 cvt.[ds].l bug. clean=1. */ + +#define OPAD_PREFIX 0x1 +#define OPAD_POSTFIX 0x2 +#define OPAD_SYMBOL 0x4 + +/* Entry found in `.options' section. */ + +typedef struct +{ + Elf32_Word hwp_flags1; /* Extra flags. */ + Elf32_Word hwp_flags2; /* Extra flags. */ +} Elf_Options_Hw; + +/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries. */ + +#define OHWA0_R4KEOP_CHECKED 0x00000001 +#define OHWA1_R4KEOP_CLEAN 0x00000002 + +/* MIPS relocs. */ + +#define R_MIPS_NONE 0 /* No reloc */ +#define R_MIPS_16 1 /* Direct 16 bit */ +#define R_MIPS_32 2 /* Direct 32 bit */ +#define R_MIPS_REL32 3 /* PC relative 32 bit */ +#define R_MIPS_26 4 /* Direct 26 bit shifted */ +#define R_MIPS_HI16 5 /* High 16 bit */ +#define R_MIPS_LO16 6 /* Low 16 bit */ +#define R_MIPS_GPREL16 7 /* GP relative 16 bit */ +#define R_MIPS_LITERAL 8 /* 16 bit literal entry */ +#define R_MIPS_GOT16 9 /* 16 bit GOT entry */ +#define R_MIPS_PC16 10 /* PC relative 16 bit */ +#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */ +#define R_MIPS_GPREL32 12 /* GP relative 32 bit */ + +#define R_MIPS_SHIFT5 16 +#define R_MIPS_SHIFT6 17 +#define R_MIPS_64 18 +#define R_MIPS_GOT_DISP 19 +#define R_MIPS_GOT_PAGE 20 +#define R_MIPS_GOT_OFST 21 +#define R_MIPS_GOT_HI16 22 +#define R_MIPS_GOT_LO16 23 +#define R_MIPS_SUB 24 +#define R_MIPS_INSERT_A 25 +#define R_MIPS_INSERT_B 26 +#define R_MIPS_DELETE 27 +#define R_MIPS_HIGHER 28 +#define R_MIPS_HIGHEST 29 +#define R_MIPS_CALL_HI16 30 +#define R_MIPS_CALL_LO16 31 +#define R_MIPS_SCN_DISP 32 +#define R_MIPS_REL16 33 +#define R_MIPS_ADD_IMMEDIATE 34 +#define R_MIPS_PJUMP 35 +#define R_MIPS_RELGOT 36 +#define R_MIPS_JALR 37 +/* Keep this the last entry. */ +#define R_MIPS_NUM 38 + +/* Legal values for p_type field of Elf32_Phdr. */ + +#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */ +#define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */ +#define PT_MIPS_OPTIONS 0x70000002 + +/* Special program header types. */ + +#define PF_MIPS_LOCAL 0x10000000 + +/* Legal values for d_tag field of Elf32_Dyn. */ + +#define DT_MIPS_RLD_VERSION 0x70000001 /* Runtime linker interface version */ +#define DT_MIPS_TIME_STAMP 0x70000002 /* Timestamp */ +#define DT_MIPS_ICHECKSUM 0x70000003 /* Checksum */ +#define DT_MIPS_IVERSION 0x70000004 /* Version string (string tbl index) */ +#define DT_MIPS_FLAGS 0x70000005 /* Flags */ +#define DT_MIPS_BASE_ADDRESS 0x70000006 /* Base address */ +#define DT_MIPS_MSYM 0x70000007 +#define DT_MIPS_CONFLICT 0x70000008 /* Address of CONFLICT section */ +#define DT_MIPS_LIBLIST 0x70000009 /* Address of LIBLIST section */ +#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local GOT entries */ +#define DT_MIPS_CONFLICTNO 0x7000000b /* Number of CONFLICT entries */ +#define DT_MIPS_LIBLISTNO 0x70000010 /* Number of LIBLIST entries */ +#define DT_MIPS_SYMTABNO 0x70000011 /* Number of DYNSYM entries */ +#define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */ +#define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in DYNSYM */ +#define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */ +#define DT_MIPS_RLD_MAP 0x70000016 /* Address of run time loader map. */ +#define DT_MIPS_DELTA_CLASS 0x70000017 /* Delta C++ class definition. */ +#define DT_MIPS_DELTA_CLASS_NO 0x70000018 /* Number of entries in + DT_MIPS_DELTA_CLASS. */ +#define DT_MIPS_DELTA_INSTANCE 0x70000019 /* Delta C++ class instances. */ +#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in + DT_MIPS_DELTA_INSTANCE. */ +#define DT_MIPS_DELTA_RELOC 0x7000001b /* Delta relocations. */ +#define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in + DT_MIPS_DELTA_RELOC. */ +#define DT_MIPS_DELTA_SYM 0x7000001d /* Delta symbols that Delta + relocations refer to. */ +#define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in + DT_MIPS_DELTA_SYM. */ +#define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the + class declaration. */ +#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in + DT_MIPS_DELTA_CLASSSYM. */ +#define DT_MIPS_CXX_FLAGS 0x70000022 /* Flags indicating for C++ flavor. */ +#define DT_MIPS_PIXIE_INIT 0x70000023 +#define DT_MIPS_SYMBOL_LIB 0x70000024 +#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025 +#define DT_MIPS_LOCAL_GOTIDX 0x70000026 +#define DT_MIPS_HIDDEN_GOTIDX 0x70000027 +#define DT_MIPS_PROTECTED_GOTIDX 0x70000028 +#define DT_MIPS_OPTIONS 0x70000029 /* Address of .options. */ +#define DT_MIPS_INTERFACE 0x7000002a /* Address of .interface. */ +#define DT_MIPS_DYNSTR_ALIGN 0x7000002b +#define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */ +#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve + function stored in GOT. */ +#define DT_MIPS_PERF_SUFFIX 0x7000002e /* Default suffix of dso to be added + by rld on dlopen() calls. */ +#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */ +#define DT_MIPS_GP_VALUE 0x70000030 /* GP value for aux GOTs. */ +#define DT_MIPS_AUX_DYNAMIC 0x70000031 /* Address of aux .dynamic. */ +#define DT_MIPS_NUM 0x32 + +/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */ + +#define RHF_NONE 0 /* No flags */ +#define RHF_QUICKSTART (1 << 0) /* Use quickstart */ +#define RHF_NOTPOT (1 << 1) /* Hash size not power of 2 */ +#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2) /* Ignore LD_LIBRARY_PATH */ +#define RHF_NO_MOVE (1 << 3) +#define RHF_SGI_ONLY (1 << 4) +#define RHF_GUARANTEE_INIT (1 << 5) +#define RHF_DELTA_C_PLUS_PLUS (1 << 6) +#define RHF_GUARANTEE_START_INIT (1 << 7) +#define RHF_PIXIE (1 << 8) +#define RHF_DEFAULT_DELAY_LOAD (1 << 9) +#define RHF_REQUICKSTART (1 << 10) +#define RHF_REQUICKSTARTED (1 << 11) +#define RHF_CORD (1 << 12) +#define RHF_NO_UNRES_UNDEF (1 << 13) +#define RHF_RLD_ORDER_SAFE (1 << 14) + +/* Entries found in sections of type SHT_MIPS_LIBLIST. */ + +typedef struct +{ + Elf32_Word l_name; /* Name (string table index) */ + Elf32_Word l_time_stamp; /* Timestamp */ + Elf32_Word l_checksum; /* Checksum */ + Elf32_Word l_version; /* Interface version */ + Elf32_Word l_flags; /* Flags */ +} Elf32_Lib; + +typedef struct +{ + Elf64_Word l_name; /* Name (string table index) */ + Elf64_Word l_time_stamp; /* Timestamp */ + Elf64_Word l_checksum; /* Checksum */ + Elf64_Word l_version; /* Interface version */ + Elf64_Word l_flags; /* Flags */ +} Elf64_Lib; + + +/* Legal values for l_flags. */ + +#define LL_NONE 0 +#define LL_EXACT_MATCH (1 << 0) /* Require exact match */ +#define LL_IGNORE_INT_VER (1 << 1) /* Ignore interface version */ +#define LL_REQUIRE_MINOR (1 << 2) +#define LL_EXPORTS (1 << 3) +#define LL_DELAY_LOAD (1 << 4) +#define LL_DELTA (1 << 5) + +/* Entries found in sections of type SHT_MIPS_CONFLICT. */ + +typedef Elf32_Addr Elf32_Conflict; + + +/* HPPA specific definitions. */ + +/* Legal values for e_flags field of Elf32_Ehdr. */ + +#define EF_PARISC_TRAPNIL 0x00010000 /* Trap nil pointer dereference. */ +#define EF_PARISC_EXT 0x00020000 /* Program uses arch. extensions. */ +#define EF_PARISC_LSB 0x00040000 /* Program expects little endian. */ +#define EF_PARISC_WIDE 0x00080000 /* Program expects wide mode. */ +#define EF_PARISC_NO_KABP 0x00100000 /* No kernel assisted branch + prediction. */ +#define EF_PARISC_LAZYSWAP 0x00400000 /* Allow lazy swapping. */ +#define EF_PARISC_ARCH 0x0000ffff /* Architecture version. */ + +/* Defined values for `e_flags & EF_PARISC_ARCH' are: */ + +#define EFA_PARISC_1_0 0x020b /* PA-RISC 1.0 big-endian. */ +#define EFA_PARISC_1_1 0x0210 /* PA-RISC 1.1 big-endian. */ +#define EFA_PARISC_2_0 0x0214 /* PA-RISC 2.0 big-endian. */ + +/* Additional section indeces. */ + +#define SHN_PARISC_ANSI_COMMON 0xff00 /* Section for tenatively declared + symbols in ANSI C. */ +#define SHN_PARISC_HUGE_COMMON 0xff01 /* Common blocks in huge model. */ + +/* Legal values for sh_type field of Elf32_Shdr. */ + +#define SHT_PARISC_EXT 0x70000000 /* Contains product specific ext. */ +#define SHT_PARISC_UNWIND 0x70000001 /* Unwind information. */ +#define SHT_PARISC_DOC 0x70000002 /* Debug info for optimized code. */ + +/* Legal values for sh_flags field of Elf32_Shdr. */ + +#define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */ +#define SHF_PARISC_HUGE 0x40000000 /* Section far from gp. */ +#define SHF_PARISC_SBP 0x80000000 /* Static branch prediction code. */ + +/* Legal values for ST_TYPE subfield of st_info (symbol type). */ + +#define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */ + +#define STT_HP_OPAQUE (STT_LOOS + 0x1) +#define STT_HP_STUB (STT_LOOS + 0x2) + +/* HPPA relocs. */ + +#define R_PARISC_NONE 0 /* No reloc. */ +#define R_PARISC_DIR32 1 /* Direct 32-bit reference. */ +#define R_PARISC_DIR21L 2 /* Left 21 bits of eff. address. */ +#define R_PARISC_DIR17R 3 /* Right 17 bits of eff. address. */ +#define R_PARISC_DIR17F 4 /* 17 bits of eff. address. */ +#define R_PARISC_DIR14R 6 /* Right 14 bits of eff. address. */ +#define R_PARISC_PCREL32 9 /* 32-bit rel. address. */ +#define R_PARISC_PCREL21L 10 /* Left 21 bits of rel. address. */ +#define R_PARISC_PCREL17R 11 /* Right 17 bits of rel. address. */ +#define R_PARISC_PCREL17F 12 /* 17 bits of rel. address. */ +#define R_PARISC_PCREL14R 14 /* Right 14 bits of rel. address. */ +#define R_PARISC_DPREL21L 18 /* Left 21 bits of rel. address. */ +#define R_PARISC_DPREL14R 22 /* Right 14 bits of rel. address. */ +#define R_PARISC_GPREL21L 26 /* GP-relative, left 21 bits. */ +#define R_PARISC_GPREL14R 30 /* GP-relative, right 14 bits. */ +#define R_PARISC_LTOFF21L 34 /* LT-relative, left 21 bits. */ +#define R_PARISC_LTOFF14R 38 /* LT-relative, right 14 bits. */ +#define R_PARISC_SECREL32 41 /* 32 bits section rel. address. */ +#define R_PARISC_SEGBASE 48 /* No relocation, set segment base. */ +#define R_PARISC_SEGREL32 49 /* 32 bits segment rel. address. */ +#define R_PARISC_PLTOFF21L 50 /* PLT rel. address, left 21 bits. */ +#define R_PARISC_PLTOFF14R 54 /* PLT rel. address, right 14 bits. */ +#define R_PARISC_LTOFF_FPTR32 57 /* 32 bits LT-rel. function pointer. */ +#define R_PARISC_LTOFF_FPTR21L 58 /* LT-rel. fct ptr, left 21 bits. */ +#define R_PARISC_LTOFF_FPTR14R 62 /* LT-rel. fct ptr, right 14 bits. */ +#define R_PARISC_FPTR64 64 /* 64 bits function address. */ +#define R_PARISC_PLABEL32 65 /* 32 bits function address. */ +#define R_PARISC_PCREL64 72 /* 64 bits PC-rel. address. */ +#define R_PARISC_PCREL22F 74 /* 22 bits PC-rel. address. */ +#define R_PARISC_PCREL14WR 75 /* PC-rel. address, right 14 bits. */ +#define R_PARISC_PCREL14DR 76 /* PC rel. address, right 14 bits. */ +#define R_PARISC_PCREL16F 77 /* 16 bits PC-rel. address. */ +#define R_PARISC_PCREL16WF 78 /* 16 bits PC-rel. address. */ +#define R_PARISC_PCREL16DF 79 /* 16 bits PC-rel. address. */ +#define R_PARISC_DIR64 80 /* 64 bits of eff. address. */ +#define R_PARISC_DIR14WR 83 /* 14 bits of eff. address. */ +#define R_PARISC_DIR14DR 84 /* 14 bits of eff. address. */ +#define R_PARISC_DIR16F 85 /* 16 bits of eff. address. */ +#define R_PARISC_DIR16WF 86 /* 16 bits of eff. address. */ +#define R_PARISC_DIR16DF 87 /* 16 bits of eff. address. */ +#define R_PARISC_GPREL64 88 /* 64 bits of GP-rel. address. */ +#define R_PARISC_GPREL14WR 91 /* GP-rel. address, right 14 bits. */ +#define R_PARISC_GPREL14DR 92 /* GP-rel. address, right 14 bits. */ +#define R_PARISC_GPREL16F 93 /* 16 bits GP-rel. address. */ +#define R_PARISC_GPREL16WF 94 /* 16 bits GP-rel. address. */ +#define R_PARISC_GPREL16DF 95 /* 16 bits GP-rel. address. */ +#define R_PARISC_LTOFF64 96 /* 64 bits LT-rel. address. */ +#define R_PARISC_LTOFF14WR 99 /* LT-rel. address, right 14 bits. */ +#define R_PARISC_LTOFF14DR 100 /* LT-rel. address, right 14 bits. */ +#define R_PARISC_LTOFF16F 101 /* 16 bits LT-rel. address. */ +#define R_PARISC_LTOFF16WF 102 /* 16 bits LT-rel. address. */ +#define R_PARISC_LTOFF16DF 103 /* 16 bits LT-rel. address. */ +#define R_PARISC_SECREL64 104 /* 64 bits section rel. address. */ +#define R_PARISC_SEGREL64 112 /* 64 bits segment rel. address. */ +#define R_PARISC_PLTOFF14WR 115 /* PLT-rel. address, right 14 bits. */ +#define R_PARISC_PLTOFF14DR 116 /* PLT-rel. address, right 14 bits. */ +#define R_PARISC_PLTOFF16F 117 /* 16 bits LT-rel. address. */ +#define R_PARISC_PLTOFF16WF 118 /* 16 bits PLT-rel. address. */ +#define R_PARISC_PLTOFF16DF 119 /* 16 bits PLT-rel. address. */ +#define R_PARISC_LTOFF_FPTR64 120 /* 64 bits LT-rel. function ptr. */ +#define R_PARISC_LTOFF_FPTR14WR 123 /* LT-rel. fct. ptr., right 14 bits. */ +#define R_PARISC_LTOFF_FPTR14DR 124 /* LT-rel. fct. ptr., right 14 bits. */ +#define R_PARISC_LTOFF_FPTR16F 125 /* 16 bits LT-rel. function ptr. */ +#define R_PARISC_LTOFF_FPTR16WF 126 /* 16 bits LT-rel. function ptr. */ +#define R_PARISC_LTOFF_FPTR16DF 127 /* 16 bits LT-rel. function ptr. */ +#define R_PARISC_LORESERVE 128 +#define R_PARISC_COPY 128 /* Copy relocation. */ +#define R_PARISC_IPLT 129 /* Dynamic reloc, imported PLT */ +#define R_PARISC_EPLT 130 /* Dynamic reloc, exported PLT */ +#define R_PARISC_TPREL32 153 /* 32 bits TP-rel. address. */ +#define R_PARISC_TPREL21L 154 /* TP-rel. address, left 21 bits. */ +#define R_PARISC_TPREL14R 158 /* TP-rel. address, right 14 bits. */ +#define R_PARISC_LTOFF_TP21L 162 /* LT-TP-rel. address, left 21 bits. */ +#define R_PARISC_LTOFF_TP14R 166 /* LT-TP-rel. address, right 14 bits.*/ +#define R_PARISC_LTOFF_TP14F 167 /* 14 bits LT-TP-rel. address. */ +#define R_PARISC_TPREL64 216 /* 64 bits TP-rel. address. */ +#define R_PARISC_TPREL14WR 219 /* TP-rel. address, right 14 bits. */ +#define R_PARISC_TPREL14DR 220 /* TP-rel. address, right 14 bits. */ +#define R_PARISC_TPREL16F 221 /* 16 bits TP-rel. address. */ +#define R_PARISC_TPREL16WF 222 /* 16 bits TP-rel. address. */ +#define R_PARISC_TPREL16DF 223 /* 16 bits TP-rel. address. */ +#define R_PARISC_LTOFF_TP64 224 /* 64 bits LT-TP-rel. address. */ +#define R_PARISC_LTOFF_TP14WR 227 /* LT-TP-rel. address, right 14 bits.*/ +#define R_PARISC_LTOFF_TP14DR 228 /* LT-TP-rel. address, right 14 bits.*/ +#define R_PARISC_LTOFF_TP16F 229 /* 16 bits LT-TP-rel. address. */ +#define R_PARISC_LTOFF_TP16WF 230 /* 16 bits LT-TP-rel. address. */ +#define R_PARISC_LTOFF_TP16DF 231 /* 16 bits LT-TP-rel. address. */ +#define R_PARISC_HIRESERVE 255 + +/* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr. */ + +#define PT_HP_TLS (PT_LOOS + 0x0) +#define PT_HP_CORE_NONE (PT_LOOS + 0x1) +#define PT_HP_CORE_VERSION (PT_LOOS + 0x2) +#define PT_HP_CORE_KERNEL (PT_LOOS + 0x3) +#define PT_HP_CORE_COMM (PT_LOOS + 0x4) +#define PT_HP_CORE_PROC (PT_LOOS + 0x5) +#define PT_HP_CORE_LOADABLE (PT_LOOS + 0x6) +#define PT_HP_CORE_STACK (PT_LOOS + 0x7) +#define PT_HP_CORE_SHM (PT_LOOS + 0x8) +#define PT_HP_CORE_MMF (PT_LOOS + 0x9) +#define PT_HP_PARALLEL (PT_LOOS + 0x10) +#define PT_HP_FASTBIND (PT_LOOS + 0x11) +#define PT_HP_OPT_ANNOT (PT_LOOS + 0x12) +#define PT_HP_HSL_ANNOT (PT_LOOS + 0x13) +#define PT_HP_STACK (PT_LOOS + 0x14) + +#define PT_PARISC_ARCHEXT 0x70000000 +#define PT_PARISC_UNWIND 0x70000001 + +/* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr. */ + +#define PF_PARISC_SBP 0x08000000 + +#define PF_HP_PAGE_SIZE 0x00100000 +#define PF_HP_FAR_SHARED 0x00200000 +#define PF_HP_NEAR_SHARED 0x00400000 +#define PF_HP_CODE 0x01000000 +#define PF_HP_MODIFY 0x02000000 +#define PF_HP_LAZYSWAP 0x04000000 +#define PF_HP_SBP 0x08000000 + + +/* Alpha specific definitions. */ + +/* Legal values for e_flags field of Elf64_Ehdr. */ + +#define EF_ALPHA_32BIT 1 /* All addresses must be < 2GB. */ +#define EF_ALPHA_CANRELAX 2 /* Relocations for relaxing exist. */ + +/* Legal values for sh_type field of Elf64_Shdr. */ + +/* These two are primerily concerned with ECOFF debugging info. */ +#define SHT_ALPHA_DEBUG 0x70000001 +#define SHT_ALPHA_REGINFO 0x70000002 + +/* Legal values for sh_flags field of Elf64_Shdr. */ + +#define SHF_ALPHA_GPREL 0x10000000 + +/* Legal values for st_other field of Elf64_Sym. */ +#define STO_ALPHA_NOPV 0x80 /* No PV required. */ +#define STO_ALPHA_STD_GPLOAD 0x88 /* PV only used for initial ldgp. */ + +/* Alpha relocs. */ + +#define R_ALPHA_NONE 0 /* No reloc */ +#define R_ALPHA_REFLONG 1 /* Direct 32 bit */ +#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */ +#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */ +#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */ +#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */ +#define R_ALPHA_GPDISP 6 /* Add displacement to GP */ +#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */ +#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */ +#define R_ALPHA_SREL16 9 /* PC relative 16 bit */ +#define R_ALPHA_SREL32 10 /* PC relative 32 bit */ +#define R_ALPHA_SREL64 11 /* PC relative 64 bit */ +#define R_ALPHA_GPRELHIGH 17 /* GP relative 32 bit, high 16 bits */ +#define R_ALPHA_GPRELLOW 18 /* GP relative 32 bit, low 16 bits */ +#define R_ALPHA_GPREL16 19 /* GP relative 16 bit */ +#define R_ALPHA_COPY 24 /* Copy symbol at runtime */ +#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */ +#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */ +#define R_ALPHA_RELATIVE 27 /* Adjust by program base */ +#define R_ALPHA_TLS_GD_HI 28 +#define R_ALPHA_TLSGD 29 +#define R_ALPHA_TLS_LDM 30 +#define R_ALPHA_DTPMOD64 31 +#define R_ALPHA_GOTDTPREL 32 +#define R_ALPHA_DTPREL64 33 +#define R_ALPHA_DTPRELHI 34 +#define R_ALPHA_DTPRELLO 35 +#define R_ALPHA_DTPREL16 36 +#define R_ALPHA_GOTTPREL 37 +#define R_ALPHA_TPREL64 38 +#define R_ALPHA_TPRELHI 39 +#define R_ALPHA_TPRELLO 40 +#define R_ALPHA_TPREL16 41 +/* Keep this the last entry. */ +#define R_ALPHA_NUM 46 + +/* Magic values of the LITUSE relocation addend. */ +#define LITUSE_ALPHA_ADDR 0 +#define LITUSE_ALPHA_BASE 1 +#define LITUSE_ALPHA_BYTOFF 2 +#define LITUSE_ALPHA_JSR 3 +#define LITUSE_ALPHA_TLS_GD 4 +#define LITUSE_ALPHA_TLS_LDM 5 + + +/* PowerPC specific declarations */ + +/* Values for Elf32/64_Ehdr.e_flags. */ +#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */ + +/* Cygnus local bits below */ +#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag*/ +#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib + flag */ + +/* PowerPC relocations defined by the ABIs */ +#define R_PPC_NONE 0 +#define R_PPC_ADDR32 1 /* 32bit absolute address */ +#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */ +#define R_PPC_ADDR16 3 /* 16bit absolute address */ +#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */ +#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */ +#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */ +#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */ +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 /* PC relative 26 bit */ +#define R_PPC_REL14 11 /* PC relative 16 bit */ +#define R_PPC_REL14_BRTAKEN 12 +#define R_PPC_REL14_BRNTAKEN 13 +#define R_PPC_GOT16 14 +#define R_PPC_GOT16_LO 15 +#define R_PPC_GOT16_HI 16 +#define R_PPC_GOT16_HA 17 +#define R_PPC_PLTREL24 18 +#define R_PPC_COPY 19 +#define R_PPC_GLOB_DAT 20 +#define R_PPC_JMP_SLOT 21 +#define R_PPC_RELATIVE 22 +#define R_PPC_LOCAL24PC 23 +#define R_PPC_UADDR32 24 +#define R_PPC_UADDR16 25 +#define R_PPC_REL32 26 +#define R_PPC_PLT32 27 +#define R_PPC_PLTREL32 28 +#define R_PPC_PLT16_LO 29 +#define R_PPC_PLT16_HI 30 +#define R_PPC_PLT16_HA 31 +#define R_PPC_SDAREL16 32 +#define R_PPC_SECTOFF 33 +#define R_PPC_SECTOFF_LO 34 +#define R_PPC_SECTOFF_HI 35 +#define R_PPC_SECTOFF_HA 36 +/* Keep this the last entry. */ +#define R_PPC_NUM 37 + +/* PowerPC64 relocations defined by the ABIs */ +#define R_PPC64_NONE R_PPC_NONE +#define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address. */ +#define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned. */ +#define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address. */ +#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of abs. address. */ +#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of abs. address. */ +#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */ +#define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned. */ +#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN +#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN +#define R_PPC64_REL24 R_PPC_REL24 /* PC relative 26 bit, word aligned. */ +#define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit. */ +#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN +#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN +#define R_PPC64_GOT16 R_PPC_GOT16 +#define R_PPC64_GOT16_LO R_PPC_GOT16_LO +#define R_PPC64_GOT16_HI R_PPC_GOT16_HI +#define R_PPC64_GOT16_HA R_PPC_GOT16_HA + +#define R_PPC64_COPY R_PPC_COPY +#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT +#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT +#define R_PPC64_RELATIVE R_PPC_RELATIVE + +#define R_PPC64_UADDR32 R_PPC_UADDR32 +#define R_PPC64_UADDR16 R_PPC_UADDR16 +#define R_PPC64_REL32 R_PPC_REL32 +#define R_PPC64_PLT32 R_PPC_PLT32 +#define R_PPC64_PLTREL32 R_PPC_PLTREL32 +#define R_PPC64_PLT16_LO R_PPC_PLT16_LO +#define R_PPC64_PLT16_HI R_PPC_PLT16_HI +#define R_PPC64_PLT16_HA R_PPC_PLT16_HA + +#define R_PPC64_SECTOFF R_PPC_SECTOFF +#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO +#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI +#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA +#define R_PPC64_ADDR30 37 /* word30 (S + A - P) >> 2. */ +#define R_PPC64_ADDR64 38 /* doubleword64 S + A. */ +#define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A). */ +#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A). */ +#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A). */ +#define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A). */ +#define R_PPC64_UADDR64 43 /* doubleword64 S + A. */ +#define R_PPC64_REL64 44 /* doubleword64 S + A - P. */ +#define R_PPC64_PLT64 45 /* doubleword64 L + A. */ +#define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P. */ +#define R_PPC64_TOC16 47 /* half16* S + A - .TOC. */ +#define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.). */ +#define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.). */ +#define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.). */ +#define R_PPC64_TOC 51 /* doubleword64 .TOC. */ +#define R_PPC64_PLTGOT16 52 /* half16* M + A. */ +#define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A). */ +#define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A). */ +#define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A). */ + +#define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2. */ +#define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2. */ +#define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2. */ +#define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2. */ +#define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2. */ +#define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2. */ +#define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2. */ +#define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2. */ +#define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2. */ +#define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2. */ +#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2. */ +/* Keep this the last entry. */ +#define R_PPC64_NUM 67 + +/* The remaining relocs are from the Embedded ELF ABI, and are not + in the SVR4 ELF ABI. */ +#define R_PPC_EMB_NADDR32 101 +#define R_PPC_EMB_NADDR16 102 +#define R_PPC_EMB_NADDR16_LO 103 +#define R_PPC_EMB_NADDR16_HI 104 +#define R_PPC_EMB_NADDR16_HA 105 +#define R_PPC_EMB_SDAI16 106 +#define R_PPC_EMB_SDA2I16 107 +#define R_PPC_EMB_SDA2REL 108 +#define R_PPC_EMB_SDA21 109 /* 16 bit offset in SDA */ +#define R_PPC_EMB_MRKREF 110 +#define R_PPC_EMB_RELSEC16 111 +#define R_PPC_EMB_RELST_LO 112 +#define R_PPC_EMB_RELST_HI 113 +#define R_PPC_EMB_RELST_HA 114 +#define R_PPC_EMB_BIT_FLD 115 +#define R_PPC_EMB_RELSDA 116 /* 16 bit relative offset in SDA */ + +/* Diab tool relocations. */ +#define R_PPC_DIAB_SDA21_LO 180 /* like EMB_SDA21, but lower 16 bit */ +#define R_PPC_DIAB_SDA21_HI 181 /* like EMB_SDA21, but high 16 bit */ +#define R_PPC_DIAB_SDA21_HA 182 /* like EMB_SDA21, adjusted high 16 */ +#define R_PPC_DIAB_RELSDA_LO 183 /* like EMB_RELSDA, but lower 16 bit */ +#define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */ +#define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */ + +/* This is a phony reloc to handle any old fashioned TOC16 references + that may still be in object files. */ +#define R_PPC_TOC16 255 + +/* PowerPC64 specific values for the Dyn d_tag field. */ +#define DT_PPC64_GLINK (DT_LOPROC + 0) +#define DT_PPC64_NUM 1 + +/* ARM specific declarations */ + +/* Processor specific flags for the ELF header e_flags field. */ +#define EF_ARM_RELEXEC 0x01 +#define EF_ARM_HASENTRY 0x02 +#define EF_ARM_INTERWORK 0x04 +#define EF_ARM_APCS_26 0x08 +#define EF_ARM_APCS_FLOAT 0x10 +#define EF_ARM_PIC 0x20 +#define EF_ARM_ALIGN8 0x40 /* 8-bit structure alignment is in use */ +#define EF_ARM_NEW_ABI 0x80 +#define EF_ARM_OLD_ABI 0x100 + +/* Other constants defined in the ARM ELF spec. version B-01. */ +/* NB. These conflict with values defined above. */ +#define EF_ARM_SYMSARESORTED 0x04 +#define EF_ARM_DYNSYMSUSESEGIDX 0x08 +#define EF_ARM_MAPSYMSFIRST 0x10 +#define EF_ARM_EABIMASK 0XFF000000 + +#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK) +#define EF_ARM_EABI_UNKNOWN 0x00000000 +#define EF_ARM_EABI_VER1 0x01000000 +#define EF_ARM_EABI_VER2 0x02000000 + +/* Additional symbol types for Thumb */ +#define STT_ARM_TFUNC 0xd + +/* ARM-specific values for sh_flags */ +#define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */ +#define SHF_ARM_COMDEF 0x80000000 /* Section may be multiply defined + in the input to a link step */ + +/* ARM-specific program header flags */ +#define PF_ARM_SB 0x10000000 /* Segment contains the location + addressed by the static base */ + +/* ARM relocs. */ +#define R_ARM_NONE 0 /* No reloc */ +#define R_ARM_PC24 1 /* PC relative 26 bit branch */ +#define R_ARM_ABS32 2 /* Direct 32 bit */ +#define R_ARM_REL32 3 /* PC relative 32 bit */ +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 /* Direct 16 bit */ +#define R_ARM_ABS12 6 /* Direct 12 bit */ +#define R_ARM_THM_ABS5 7 +#define R_ARM_ABS8 8 /* Direct 8 bit */ +#define R_ARM_SBREL32 9 +#define R_ARM_THM_PC22 10 +#define R_ARM_THM_PC8 11 +#define R_ARM_AMP_VCALL9 12 +#define R_ARM_SWI24 13 +#define R_ARM_THM_SWI8 14 +#define R_ARM_XPC25 15 +#define R_ARM_THM_XPC22 16 +#define R_ARM_COPY 20 /* Copy symbol at runtime */ +#define R_ARM_GLOB_DAT 21 /* Create GOT entry */ +#define R_ARM_JUMP_SLOT 22 /* Create PLT entry */ +#define R_ARM_RELATIVE 23 /* Adjust by program base */ +#define R_ARM_GOTOFF 24 /* 32 bit offset to GOT */ +#define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */ +#define R_ARM_GOT32 26 /* 32 bit GOT entry */ +#define R_ARM_PLT32 27 /* 32 bit PLT address */ +#define R_ARM_ALU_PCREL_7_0 32 +#define R_ARM_ALU_PCREL_15_8 33 +#define R_ARM_ALU_PCREL_23_15 34 +#define R_ARM_LDR_SBREL_11_0 35 +#define R_ARM_ALU_SBREL_19_12 36 +#define R_ARM_ALU_SBREL_27_20 37 +#define R_ARM_GNU_VTENTRY 100 +#define R_ARM_GNU_VTINHERIT 101 +#define R_ARM_THM_PC11 102 /* thumb unconditional branch */ +#define R_ARM_THM_PC9 103 /* thumb conditional branch */ +#define R_ARM_RXPC25 249 +#define R_ARM_RSBREL32 250 +#define R_ARM_THM_RPC22 251 +#define R_ARM_RREL32 252 +#define R_ARM_RABS22 253 +#define R_ARM_RPC24 254 +#define R_ARM_RBASE 255 +/* Keep this the last entry. */ +#define R_ARM_NUM 256 + +/* IA-64 specific declarations. */ + +/* Processor specific flags for the Ehdr e_flags field. */ +#define EF_IA_64_MASKOS 0x0000000f /* os-specific flags */ +#define EF_IA_64_ABI64 0x00000010 /* 64-bit ABI */ +#define EF_IA_64_ARCH 0xff000000 /* arch. version mask */ + +/* Processor specific values for the Phdr p_type field. */ +#define PT_IA_64_ARCHEXT (PT_LOPROC + 0) /* arch extension bits */ +#define PT_IA_64_UNWIND (PT_LOPROC + 1) /* ia64 unwind bits */ + +/* Processor specific flags for the Phdr p_flags field. */ +#define PF_IA_64_NORECOV 0x80000000 /* spec insns w/o recovery */ + +/* Processor specific values for the Shdr sh_type field. */ +#define SHT_IA_64_EXT (SHT_LOPROC + 0) /* extension bits */ +#define SHT_IA_64_UNWIND (SHT_LOPROC + 1) /* unwind bits */ + +/* Processor specific flags for the Shdr sh_flags field. */ +#define SHF_IA_64_SHORT 0x10000000 /* section near gp */ +#define SHF_IA_64_NORECOV 0x20000000 /* spec insns w/o recovery */ + +/* Processor specific values for the Dyn d_tag field. */ +#define DT_IA_64_PLT_RESERVE (DT_LOPROC + 0) +#define DT_IA_64_NUM 1 + +/* IA-64 relocations. */ +#define R_IA64_NONE 0x00 /* none */ +#define R_IA64_IMM14 0x21 /* symbol + addend, add imm14 */ +#define R_IA64_IMM22 0x22 /* symbol + addend, add imm22 */ +#define R_IA64_IMM64 0x23 /* symbol + addend, mov imm64 */ +#define R_IA64_DIR32MSB 0x24 /* symbol + addend, data4 MSB */ +#define R_IA64_DIR32LSB 0x25 /* symbol + addend, data4 LSB */ +#define R_IA64_DIR64MSB 0x26 /* symbol + addend, data8 MSB */ +#define R_IA64_DIR64LSB 0x27 /* symbol + addend, data8 LSB */ +#define R_IA64_GPREL22 0x2a /* @gprel(sym + add), add imm22 */ +#define R_IA64_GPREL64I 0x2b /* @gprel(sym + add), mov imm64 */ +#define R_IA64_GPREL32MSB 0x2c /* @gprel(sym + add), data4 MSB */ +#define R_IA64_GPREL32LSB 0x2d /* @gprel(sym + add), data4 LSB */ +#define R_IA64_GPREL64MSB 0x2e /* @gprel(sym + add), data8 MSB */ +#define R_IA64_GPREL64LSB 0x2f /* @gprel(sym + add), data8 LSB */ +#define R_IA64_LTOFF22 0x32 /* @ltoff(sym + add), add imm22 */ +#define R_IA64_LTOFF64I 0x33 /* @ltoff(sym + add), mov imm64 */ +#define R_IA64_PLTOFF22 0x3a /* @pltoff(sym + add), add imm22 */ +#define R_IA64_PLTOFF64I 0x3b /* @pltoff(sym + add), mov imm64 */ +#define R_IA64_PLTOFF64MSB 0x3e /* @pltoff(sym + add), data8 MSB */ +#define R_IA64_PLTOFF64LSB 0x3f /* @pltoff(sym + add), data8 LSB */ +#define R_IA64_FPTR64I 0x43 /* @fptr(sym + add), mov imm64 */ +#define R_IA64_FPTR32MSB 0x44 /* @fptr(sym + add), data4 MSB */ +#define R_IA64_FPTR32LSB 0x45 /* @fptr(sym + add), data4 LSB */ +#define R_IA64_FPTR64MSB 0x46 /* @fptr(sym + add), data8 MSB */ +#define R_IA64_FPTR64LSB 0x47 /* @fptr(sym + add), data8 LSB */ +#define R_IA64_PCREL60B 0x48 /* @pcrel(sym + add), brl */ +#define R_IA64_PCREL21B 0x49 /* @pcrel(sym + add), ptb, call */ +#define R_IA64_PCREL21M 0x4a /* @pcrel(sym + add), chk.s */ +#define R_IA64_PCREL21F 0x4b /* @pcrel(sym + add), fchkf */ +#define R_IA64_PCREL32MSB 0x4c /* @pcrel(sym + add), data4 MSB */ +#define R_IA64_PCREL32LSB 0x4d /* @pcrel(sym + add), data4 LSB */ +#define R_IA64_PCREL64MSB 0x4e /* @pcrel(sym + add), data8 MSB */ +#define R_IA64_PCREL64LSB 0x4f /* @pcrel(sym + add), data8 LSB */ +#define R_IA64_LTOFF_FPTR22 0x52 /* @ltoff(@fptr(s+a)), imm22 */ +#define R_IA64_LTOFF_FPTR64I 0x53 /* @ltoff(@fptr(s+a)), imm64 */ +#define R_IA64_LTOFF_FPTR32MSB 0x54 /* @ltoff(@fptr(s+a)), data4 MSB */ +#define R_IA64_LTOFF_FPTR32LSB 0x55 /* @ltoff(@fptr(s+a)), data4 LSB */ +#define R_IA64_LTOFF_FPTR64MSB 0x56 /* @ltoff(@fptr(s+a)), data8 MSB */ +#define R_IA64_LTOFF_FPTR64LSB 0x57 /* @ltoff(@fptr(s+a)), data8 LSB */ +#define R_IA64_SEGREL32MSB 0x5c /* @segrel(sym + add), data4 MSB */ +#define R_IA64_SEGREL32LSB 0x5d /* @segrel(sym + add), data4 LSB */ +#define R_IA64_SEGREL64MSB 0x5e /* @segrel(sym + add), data8 MSB */ +#define R_IA64_SEGREL64LSB 0x5f /* @segrel(sym + add), data8 LSB */ +#define R_IA64_SECREL32MSB 0x64 /* @secrel(sym + add), data4 MSB */ +#define R_IA64_SECREL32LSB 0x65 /* @secrel(sym + add), data4 LSB */ +#define R_IA64_SECREL64MSB 0x66 /* @secrel(sym + add), data8 MSB */ +#define R_IA64_SECREL64LSB 0x67 /* @secrel(sym + add), data8 LSB */ +#define R_IA64_REL32MSB 0x6c /* data 4 + REL */ +#define R_IA64_REL32LSB 0x6d /* data 4 + REL */ +#define R_IA64_REL64MSB 0x6e /* data 8 + REL */ +#define R_IA64_REL64LSB 0x6f /* data 8 + REL */ +#define R_IA64_LTV32MSB 0x74 /* symbol + addend, data4 MSB */ +#define R_IA64_LTV32LSB 0x75 /* symbol + addend, data4 LSB */ +#define R_IA64_LTV64MSB 0x76 /* symbol + addend, data8 MSB */ +#define R_IA64_LTV64LSB 0x77 /* symbol + addend, data8 LSB */ +#define R_IA64_PCREL21BI 0x79 /* @pcrel(sym + add), 21bit inst */ +#define R_IA64_PCREL22 0x7a /* @pcrel(sym + add), 22bit inst */ +#define R_IA64_PCREL64I 0x7b /* @pcrel(sym + add), 64bit inst */ +#define R_IA64_IPLTMSB 0x80 /* dynamic reloc, imported PLT, MSB */ +#define R_IA64_IPLTLSB 0x81 /* dynamic reloc, imported PLT, LSB */ +#define R_IA64_COPY 0x84 /* copy relocation */ +#define R_IA64_SUB 0x85 /* Addend and symbol difference */ +#define R_IA64_LTOFF22X 0x86 /* LTOFF22, relaxable. */ +#define R_IA64_LDXMOV 0x87 /* Use of LTOFF22X. */ +#define R_IA64_TPREL14 0x91 /* @tprel(sym + add), imm14 */ +#define R_IA64_TPREL22 0x92 /* @tprel(sym + add), imm22 */ +#define R_IA64_TPREL64I 0x93 /* @tprel(sym + add), imm64 */ +#define R_IA64_TPREL64MSB 0x96 /* @tprel(sym + add), data8 MSB */ +#define R_IA64_TPREL64LSB 0x97 /* @tprel(sym + add), data8 LSB */ +#define R_IA64_LTOFF_TPREL22 0x9a /* @ltoff(@tprel(s+a)), imm2 */ +#define R_IA64_DTPMOD64MSB 0xa6 /* @dtpmod(sym + add), data8 MSB */ +#define R_IA64_DTPMOD64LSB 0xa7 /* @dtpmod(sym + add), data8 LSB */ +#define R_IA64_LTOFF_DTPMOD22 0xaa /* @ltoff(@dtpmod(sym + add)), imm22 */ +#define R_IA64_DTPREL14 0xb1 /* @dtprel(sym + add), imm14 */ +#define R_IA64_DTPREL22 0xb2 /* @dtprel(sym + add), imm22 */ +#define R_IA64_DTPREL64I 0xb3 /* @dtprel(sym + add), imm64 */ +#define R_IA64_DTPREL32MSB 0xb4 /* @dtprel(sym + add), data4 MSB */ +#define R_IA64_DTPREL32LSB 0xb5 /* @dtprel(sym + add), data4 LSB */ +#define R_IA64_DTPREL64MSB 0xb6 /* @dtprel(sym + add), data8 MSB */ +#define R_IA64_DTPREL64LSB 0xb7 /* @dtprel(sym + add), data8 LSB */ +#define R_IA64_LTOFF_DTPREL22 0xba /* @ltoff(@dtprel(s+a)), imm22 */ + +/* SH specific declarations */ + +/* SH relocs. */ +#define R_SH_NONE 0 +#define R_SH_DIR32 1 +#define R_SH_REL32 2 +#define R_SH_DIR8WPN 3 +#define R_SH_IND12W 4 +#define R_SH_DIR8WPL 5 +#define R_SH_DIR8WPZ 6 +#define R_SH_DIR8BP 7 +#define R_SH_DIR8W 8 +#define R_SH_DIR8L 9 +#define R_SH_SWITCH16 25 +#define R_SH_SWITCH32 26 +#define R_SH_USES 27 +#define R_SH_COUNT 28 +#define R_SH_ALIGN 29 +#define R_SH_CODE 30 +#define R_SH_DATA 31 +#define R_SH_LABEL 32 +#define R_SH_SWITCH8 33 +#define R_SH_GNU_VTINHERIT 34 +#define R_SH_GNU_VTENTRY 35 +#define R_SH_TLS_GD_32 144 +#define R_SH_TLS_LD_32 145 +#define R_SH_TLS_LDO_32 146 +#define R_SH_TLS_IE_32 147 +#define R_SH_TLS_LE_32 148 +#define R_SH_TLS_DTPMOD32 149 +#define R_SH_TLS_DTPOFF32 150 +#define R_SH_TLS_TPOFF32 151 +#define R_SH_TLS_GD_MOV 152 +#define R_SH_TLS_LDM_MOV 153 +#define R_SH_TLS_LDO_MOV 154 +#define R_SH_TLS_IE_MOV 155 +#define R_SH_TLS_LE_MOV 156 +#define R_SH_GOT32 160 +#define R_SH_PLT32 161 +#define R_SH_COPY 162 +#define R_SH_GLOB_DAT 163 +#define R_SH_JMP_SLOT 164 +#define R_SH_RELATIVE 165 +#define R_SH_GOTOFF 166 +#define R_SH_GOTPC 167 +/* Keep this the last entry. */ +#define R_SH_NUM 256 + +/* Additional s390 relocs */ + +#define R_390_NONE 0 /* No reloc. */ +#define R_390_8 1 /* Direct 8 bit. */ +#define R_390_12 2 /* Direct 12 bit. */ +#define R_390_16 3 /* Direct 16 bit. */ +#define R_390_32 4 /* Direct 32 bit. */ +#define R_390_PC32 5 /* PC relative 32 bit. */ +#define R_390_GOT12 6 /* 12 bit GOT offset. */ +#define R_390_GOT32 7 /* 32 bit GOT offset. */ +#define R_390_PLT32 8 /* 32 bit PC relative PLT address. */ +#define R_390_COPY 9 /* Copy symbol at runtime. */ +#define R_390_GLOB_DAT 10 /* Create GOT entry. */ +#define R_390_JMP_SLOT 11 /* Create PLT entry. */ +#define R_390_RELATIVE 12 /* Adjust by program base. */ +#define R_390_GOTOFF 13 /* 32 bit offset to GOT. */ +#define R_390_GOTPC 14 /* 32 bit PC relative offset to GOT. */ +#define R_390_GOT16 15 /* 16 bit GOT offset. */ +#define R_390_PC16 16 /* PC relative 16 bit. */ +#define R_390_PC16DBL 17 /* PC relative 16 bit shifted by 1. */ +#define R_390_PLT16DBL 18 /* 16 bit PC rel. PLT shifted by 1. */ +#define R_390_PC32DBL 19 /* PC relative 32 bit shifted by 1. */ +#define R_390_PLT32DBL 20 /* 32 bit PC rel. PLT shifted by 1. */ +#define R_390_GOTPCDBL 21 /* 32 bit PC rel. GOT shifted by 1. */ +#define R_390_64 22 /* Direct 64 bit. */ +#define R_390_PC64 23 /* PC relative 64 bit. */ +#define R_390_GOT64 24 /* 64 bit GOT offset. */ +#define R_390_PLT64 25 /* 64 bit PC relative PLT address. */ +#define R_390_GOTENT 26 /* 32 bit PC rel. to GOT entry >> 1. */ + +/* Keep this the last entry. */ +#define R_390_NUM 27 + +/* CRIS relocations. */ +#define R_CRIS_NONE 0 +#define R_CRIS_8 1 +#define R_CRIS_16 2 +#define R_CRIS_32 3 +#define R_CRIS_8_PCREL 4 +#define R_CRIS_16_PCREL 5 +#define R_CRIS_32_PCREL 6 +#define R_CRIS_GNU_VTINHERIT 7 +#define R_CRIS_GNU_VTENTRY 8 +#define R_CRIS_COPY 9 +#define R_CRIS_GLOB_DAT 10 +#define R_CRIS_JUMP_SLOT 11 +#define R_CRIS_RELATIVE 12 +#define R_CRIS_16_GOT 13 +#define R_CRIS_32_GOT 14 +#define R_CRIS_16_GOTPLT 15 +#define R_CRIS_32_GOTPLT 16 +#define R_CRIS_32_GOTREL 17 +#define R_CRIS_32_PLT_GOTREL 18 +#define R_CRIS_32_PLT_PCREL 19 + +#define R_CRIS_NUM 20 + +/* AMD x86-64 relocations. */ +#define R_X86_64_NONE 0 /* No reloc */ +#define R_X86_64_64 1 /* Direct 64 bit */ +#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ +#define R_X86_64_GOT32 3 /* 32 bit GOT entry */ +#define R_X86_64_PLT32 4 /* 32 bit PLT address */ +#define R_X86_64_COPY 5 /* Copy symbol at runtime */ +#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ +#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ +#define R_X86_64_RELATIVE 8 /* Adjust by program base */ +#define R_X86_64_GOTPCREL 9 /* 32 bit signed PC relative + offset to GOT */ +#define R_X86_64_32 10 /* Direct 32 bit zero extended */ +#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ +#define R_X86_64_16 12 /* Direct 16 bit zero extended */ +#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */ +#define R_X86_64_8 14 /* Direct 8 bit sign extended */ +#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ +#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ +#define R_X86_64_DTPOFF64 17 /* Offset in module's TLS block */ +#define R_X86_64_TPOFF64 18 /* Offset in initial TLS block */ +#define R_X86_64_TLSGD 19 /* 32 bit signed PC relative offset + to two GOT entries for GD symbol */ +#define R_X86_64_TLSLD 20 /* 32 bit signed PC relative offset + to two GOT entries for LD symbol */ +#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ +#define r_x86_64_GOTTPOFF 22 /* 32 bit signed PC relative offset + to GOT entry for IE symbol */ +#define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */ + +#define R_X86_64_NUM 24 + +#endif /* ! PUPA_ELF_H */ diff --git a/include/grub/err.h b/include/grub/err.h new file mode 100644 index 000000000..4524fc13e --- /dev/null +++ b/include/grub/err.h @@ -0,0 +1,59 @@ +/* err.h - error numbers and prototypes */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PUPA_ERR_HEADER +#define PUPA_ERR_HEADER 1 + +#include + +typedef enum + { + PUPA_ERR_NONE = 0, + PUPA_ERR_BAD_MODULE, + PUPA_ERR_OUT_OF_MEMORY, + PUPA_ERR_BAD_FILE_TYPE, + PUPA_ERR_FILE_NOT_FOUND, + PUPA_ERR_FILE_READ_ERROR, + PUPA_ERR_BAD_FILENAME, + PUPA_ERR_UNKNOWN_FS, + PUPA_ERR_BAD_FS, + PUPA_ERR_BAD_NUMBER, + PUPA_ERR_OUT_OF_RANGE, + PUPA_ERR_UNKNOWN_DEVICE, + PUPA_ERR_BAD_DEVICE, + PUPA_ERR_READ_ERROR, + PUPA_ERR_WRITE_ERROR, + PUPA_ERR_BAD_ARGUMENT, + PUPA_ERR_BAD_PART_TABLE, + PUPA_ERR_UNKNOWN_OS, + PUPA_ERR_BAD_OS, + PUPA_ERR_NO_KERNEL, + PUPA_ERR_NOT_IMPLEMENTED_YET, + } +pupa_err_t; + +extern pupa_err_t EXPORT_VAR(pupa_errno); +extern char EXPORT_VAR(pupa_errmsg)[]; + +pupa_err_t EXPORT_FUNC(pupa_error) (pupa_err_t n, const char *fmt, ...); +void EXPORT_FUNC(pupa_fatal) (const char *fmt, ...) __attribute__ ((noreturn)); +void EXPORT_FUNC(pupa_print_error) (void); + +#endif /* ! PUPA_ERR_HEADER */ diff --git a/include/grub/file.h b/include/grub/file.h new file mode 100644 index 000000000..5e3a5e64f --- /dev/null +++ b/include/grub/file.h @@ -0,0 +1,73 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PUPA_FILE_HEADER +#define PUPA_FILE_HEADER 1 + +#include +#include +#include +#include + +/* File description. */ +struct pupa_file +{ + /* The underlying device. */ + pupa_device_t device; + + /* The underlying filesystem. */ + pupa_fs_t fs; + + /* The current offset. */ + pupa_ssize_t offset; + + /* The file size. */ + pupa_ssize_t size; + + /* Filesystem-specific data. */ + void *data; + + /* This is called when a sector is read. Used only for a disk device. */ + void (*read_hook) (unsigned long sector, unsigned offset, unsigned length); +}; +typedef struct pupa_file *pupa_file_t; + +/* Get a device name from NAME. */ +char *EXPORT_FUNC(pupa_file_get_device_name) (const char *name); + +pupa_file_t EXPORT_FUNC(pupa_file_open) (const char *name); +pupa_ssize_t EXPORT_FUNC(pupa_file_read) (pupa_file_t file, char *buf, + pupa_ssize_t len); +pupa_ssize_t EXPORT_FUNC(pupa_file_seek) (pupa_file_t file, + pupa_ssize_t offset); +pupa_err_t EXPORT_FUNC(pupa_file_close) (pupa_file_t file); + +static inline pupa_ssize_t +pupa_file_size (const pupa_file_t file) +{ + return file->size; +} + +static inline pupa_ssize_t +pupa_file_tell (const pupa_file_t file) +{ + return file->offset; +} + +#endif /* ! PUPA_FILE_HEADER */ diff --git a/include/grub/fs.h b/include/grub/fs.h new file mode 100644 index 000000000..079bb68a9 --- /dev/null +++ b/include/grub/fs.h @@ -0,0 +1,63 @@ +/* fs.h - filesystem manager */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PUPA_FS_HEADER +#define PUPA_FS_HEADER 1 + +#include +#include +#include + +/* Forward declaration is required, because of mutual reference. */ +struct pupa_file; + +/* Filesystem descriptor. */ +struct pupa_fs +{ + /* My name. */ + const char *name; + + /* Call HOOK with each file under DIR. */ + pupa_err_t (*dir) (pupa_device_t device, const char *path, + int (*hook) (const char *filename, int dir)); + + /* Open a file named NAME and initialize FILE. */ + pupa_err_t (*open) (struct pupa_file *file, const char *name); + + /* Read LEN bytes data from FILE into BUF. */ + pupa_ssize_t (*read) (struct pupa_file *file, char *buf, pupa_ssize_t len); + + /* Close the file FILE. */ + pupa_err_t (*close) (struct pupa_file *file); + + /* The next filesystem. */ + struct pupa_fs *next; +}; +typedef struct pupa_fs *pupa_fs_t; + +/* This is special, because block lists are not files in usual sense. */ +extern struct pupa_fs pupa_fs_blocklist; + +void EXPORT_FUNC(pupa_fs_register) (pupa_fs_t fs); +void EXPORT_FUNC(pupa_fs_unregister) (pupa_fs_t fs); +void EXPORT_FUNC(pupa_fs_iterate) (int (*hook) (const pupa_fs_t fs)); +pupa_fs_t EXPORT_FUNC(pupa_fs_probe) (pupa_device_t device); + +#endif /* ! PUPA_FS_HEADER */ diff --git a/include/grub/i386/pc/biosdisk.h b/include/grub/i386/pc/biosdisk.h new file mode 100644 index 000000000..0260b9654 --- /dev/null +++ b/include/grub/i386/pc/biosdisk.h @@ -0,0 +1,47 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PUPA_BIOSDISK_MACHINE_HEADER +#define PUPA_BIOSDISK_MACHINE_HEADER 1 + +#define PUPA_BIOSDISK_FLAG_LBA 1 + +struct pupa_biosdisk_data +{ + int drive; + unsigned long cylinders; + unsigned long heads; + unsigned long sectors; + unsigned long flags; +}; + +int pupa_biosdisk_rw_int13_extensions (int ah, int drive, void *dap); +int pupa_biosdisk_rw_standard (int ah, int drive, int coff, int hoff, + int soff, int nsec, int segment); +int pupa_biosdisk_check_int13_extensions (int drive); +int pupa_biosdisk_get_diskinfo_int13_extensions (int drive, void *drp); +int pupa_biosdisk_get_diskinfo_standard (int drive, + unsigned long *cylinders, + unsigned long *heads, + unsigned long *sectors); +int pupa_biosdisk_get_num_floppies (void); + +void pupa_biosdisk_init (void); + +#endif /* ! PUPA_BIOSDISK_MACHINE_HEADER */ diff --git a/include/grub/i386/pc/boot.h b/include/grub/i386/pc/boot.h new file mode 100644 index 000000000..b269e72a0 --- /dev/null +++ b/include/grub/i386/pc/boot.h @@ -0,0 +1,83 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 1999, 2000 Free Software Foundation, Inc. + * Copyright (C) 2002 Yoshinori K. Okuji + * + * 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 PUPA_BOOT_MACHINE_HEADER +#define PUPA_BOOT_MACHINE_HEADER 1 + +/* The signature for bootloader. */ +#define PUPA_BOOT_MACHINE_SIGNATURE 0xaa55 + +/* The offset of the end of BPB (BIOS Parameter Block). */ +#define PUPA_BOOT_MACHINE_BPBEND 0x3e + +/* The offset of the major version. */ +#define PUPA_BOOT_MACHINE_VER_MAJ 0x3e + +/* The offset of BOOT_DRIVE. */ +#define PUPA_BOOT_MACHINE_BOOT_DRIVE 0x40 + +/* The offset of FORCE_LBA. */ +#define PUPA_BOOT_MACHINE_FORCE_LBA 0x41 + +/* The offset of KERNEL_ADDRESS. */ +#define PUPA_BOOT_MACHINE_KERNEL_ADDRESS 0x42 + +/* The offset of KERNEL_SECTOR. */ +#define PUPA_BOOT_MACHINE_KERNEL_SECTOR 0x44 + +/* The offset of KERNEL_SEGMENT. */ +#define PUPA_BOOT_MACHINE_KERNEL_SEGMENT 0x48 + +/* The offset of a magic number used by Windows NT. */ +#define PUPA_BOOT_MACHINE_WINDOWS_NT_MAGIC 0x1b8 + +/* The offset of the start of the partition table. */ +#define PUPA_BOOT_MACHINE_PART_START 0x1be + +/* The offset of the end of the partition table. */ +#define PUPA_BOOT_MACHINE_PART_END 0x1fe + +/* The stack segment. */ +#define PUPA_BOOT_MACHINE_STACK_SEG 0x2000 + +/* The segment of disk buffer. The disk buffer MUST be 32K long and + cannot straddle a 64K boundary. */ +#define PUPA_BOOT_MACHINE_BUFFER_SEG 0x7000 + +/* The address of drive parameters. */ +#define PUPA_BOOT_MACHINE_DRP_ADDR 0x7f00 + +/* The size of drive parameters. */ +#define PUPA_BOOT_MACHINE_DRP_SIZE 0x42 + +/* The flag for BIOS drive number to designate a hard disk vs. a + floppy. */ +#define PUPA_BOOT_MACHINE_BIOS_HD_FLAG 0x80 + +/* The segment where the kernel is loaded. */ +#define PUPA_BOOT_MACHINE_KERNEL_SEG 0x800 + +/* The address where the kernel is loaded. */ +#define PUPA_BOOT_MACHINE_KERNEL_ADDR (PUPA_BOOT_MACHINE_KERNEL_SEG << 4) + +/* The size of a block list used in the kernel startup code. */ +#define PUPA_BOOT_MACHINE_LIST_SIZE 8 + +#endif /* ! BOOT_MACHINE_HEADER */ diff --git a/include/grub/i386/pc/console.h b/include/grub/i386/pc/console.h new file mode 100644 index 000000000..69601e5d5 --- /dev/null +++ b/include/grub/i386/pc/console.h @@ -0,0 +1,55 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * 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 PUPA_CONSOLE_MACHINE_HEADER +#define PUPA_CONSOLE_MACHINE_HEADER 1 + +/* Define scan codes. */ +#define PUPA_CONSOLE_KEY_LEFT 0x4B00 +#define PUPA_CONSOLE_KEY_RIGHT 0x4D00 +#define PUPA_CONSOLE_KEY_UP 0x4800 +#define PUPA_CONSOLE_KEY_DOWN 0x5000 +#define PUPA_CONSOLE_KEY_IC 0x5200 +#define PUPA_CONSOLE_KEY_DC 0x5300 +#define PUPA_CONSOLE_KEY_BACKSPACE 0x0008 +#define PUPA_CONSOLE_KEY_HOME 0x4700 +#define PUPA_CONSOLE_KEY_END 0x4F00 +#define PUPA_CONSOLE_KEY_NPAGE 0x4900 +#define PUPA_CONSOLE_KEY_PPAGE 0x5100 + +#ifndef ASM_FILE + +#include + +/* These are global to share code between C and asm. */ +extern pupa_uint8_t pupa_console_cur_color; +void pupa_console_putchar (int c); +int pupa_console_checkkey (void); +int pupa_console_getkey (void); +pupa_uint16_t pupa_console_getxy (void); +void pupa_console_gotoxy (pupa_uint8_t x, pupa_uint8_t y); +void pupa_console_cls (void); +void pupa_console_setcursor (int on); + +/* Initialize the console system. */ +void pupa_console_init (void); + +#endif + +#endif /* ! PUPA_CONSOLE_MACHINE_HEADER */ diff --git a/include/grub/i386/pc/init.h b/include/grub/i386/pc/init.h new file mode 100644 index 000000000..cb9128607 --- /dev/null +++ b/include/grub/i386/pc/init.h @@ -0,0 +1,50 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * 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 PUPA_INIT_MACHINE_HEADER +#define PUPA_INIT_MACHINE_HEADER 1 + +#include +#include + +/* Get the memory size in KB. If EXTENDED is zero, return conventional + memory, otherwise return extended memory. */ +pupa_uint16_t pupa_get_memsize (int extended); + +/* Get a packed EISA memory map. Lower 16 bits are between 1MB and 16MB + in 1KB parts, and upper 16 bits are above 16MB in 64KB parts. */ +pupa_uint32_t pupa_get_eisa_mmap (void); + +struct pupa_machine_mmap_entry +{ + pupa_uint32_t size; + pupa_uint64_t addr; + pupa_uint64_t len; + pupa_uint32_t type; +}; + +/* Get a memory map entry. Return next continuation value. Zero means + the end. */ +pupa_uint32_t pupa_get_mmap_entry (struct pupa_machine_mmap_entry *entry, + pupa_uint32_t cont); + +/* Turn on/off Gate A20. */ +void EXPORT_FUNC(pupa_gate_a20) (int on); + +#endif /* ! PUPA_INIT_MACHINE_HEADER */ diff --git a/include/grub/i386/pc/kernel.h b/include/grub/i386/pc/kernel.h new file mode 100644 index 000000000..d6928d3c7 --- /dev/null +++ b/include/grub/i386/pc/kernel.h @@ -0,0 +1,29 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * 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 KERNEL_MACHINE_HEADER +#define KERNEL_MACHINE_HEADER 1 + +/* The offset of PUPA_TOTAL_MODULE_SIZE. */ +#define PUPA_KERNEL_MACHINE_TOTAL_MODULE_SIZE 0x8 + +/* The offset of PUPA_KERNEL_IMAGE_SIZE. */ +#define PUPA_KERNEL_MACHINE_KERNEL_IMAGE_SIZE 0xc + +#endif /* ! KERNEL_MACHINE_HEADER */ diff --git a/include/grub/i386/pc/loader.h b/include/grub/i386/pc/loader.h new file mode 100644 index 000000000..d2dcc9136 --- /dev/null +++ b/include/grub/i386/pc/loader.h @@ -0,0 +1,29 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * 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 PUPA_LOADER_MACHINE_HEADER +#define PUPA_LOADER_MACHINE_HEADER 1 + +#include +#include + +/* This is an asm part of the chainloader. */ +void EXPORT_FUNC(pupa_chainloader_real_boot) (int drive, void *part_addr) __attribute__ ((noreturn)); + +#endif /* ! PUPA_LOADER_MACHINE_HEADER */ diff --git a/include/grub/i386/pc/memory.h b/include/grub/i386/pc/memory.h new file mode 100644 index 000000000..d22f8b6cb --- /dev/null +++ b/include/grub/i386/pc/memory.h @@ -0,0 +1,67 @@ +/* memory.h - describe the memory map */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * 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 PUPA_MEMORY_MACHINE_HEADER +#define PUPA_MEMORY_MACHINE_HEADER 1 + +/* The scratch buffer used in real mode code. */ +#define PUPA_MEMORY_MACHINE_SCRATCH_ADDR 0x68000 +#define PUPA_MEMORY_MACHINE_SCRATCH_SEG (PUPA_MEMORY_MACHINE_SCRATCH_ADDR >> 4) +#define PUPA_MEMORY_MACHINE_SCRATCH_SIZE 0x10000 + +/* The real mode stack. */ +#define PUPA_MEMORY_MACHINE_REAL_STACK (0x2000 - 0x10) + +/* The size of the protect mode stack. */ +#define PUPA_MEMORY_MACHINE_PROT_STACK_SIZE 0x8000 + +/* The protected mode stack. */ +#define PUPA_MEMORY_MACHINE_PROT_STACK \ + (PUPA_MEMORY_MACHINE_SCRATCH_ADDR + PUPA_MEMORY_MACHINE_SCRATCH_SIZE \ + + PUPA_MEMORY_MACHINE_PROT_STACK_SIZE - 0x10) + +/* The memory area where PUPA uses its own purpose. */ +#define PUPA_MEMORY_MACHINE_RESERVED_START \ + PUPA_MEMORY_MACHINE_SCRATCH_ADDR +#define PUPA_MEMORY_MACHINE_RESERVED_END \ + (PUPA_MEMORY_MACHINE_PROT_STACK + 0x10) + +/* The address of a partition table passed to another boot loader. */ +#define PUPA_MEMORY_MACHINE_PART_TABLE_ADDR 0x7be + +/* The address where another boot loader is loaded. */ +#define PUPA_MEMORY_MACHINE_BOOT_LOADER_ADDR 0x7c00 + +/* The flag for protected mode. */ +#define PUPA_MEMORY_MACHINE_CR0_PE_ON 0x1 + +/* The code segment of the protected mode. */ +#define PUPA_MEMORY_MACHINE_PROT_MODE_CSEG 0x8 + +/* The data segment of the protected mode. */ +#define PUPA_MEMORY_MACHINE_PROT_MODE_DSEG 0x10 + +/* The code segment of the pseudo real mode. */ +#define PUPA_MEMORY_MACHINE_PSEUDO_REAL_CSEG 0x18 + +/* The data segment of the pseudo real mode. */ +#define PUPA_MEMORY_MACHINE_PSEUDO_REAL_DSEG 0x20 + +#endif /* ! PUPA_MEMORY_MACHINE_HEADER */ diff --git a/include/grub/i386/pc/partition.h b/include/grub/i386/pc/partition.h new file mode 100644 index 000000000..10113a438 --- /dev/null +++ b/include/grub/i386/pc/partition.h @@ -0,0 +1,243 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 1999,2000,2001 Free Software Foundation, Inc. + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PUPA_PARTITION_HEADER +#define PUPA_PARTITION_HEADER 1 + +#include +#include +#include + +/* The signature. */ +#define PUPA_PARTITION_SIGNATURE 0xaa55 + +/* This is not a flag actually, but used as if it were a flag. */ +#define PUPA_PARTITION_TYPE_HIDDEN_FLAG 0x10 + +/* DOS partition types. */ +#define PUPA_PARTITION_TYPE_NONE 0 +#define PUPA_PARTITION_TYPE_FAT12 1 +#define PUPA_PARTITION_TYPE_FAT16_LT32M 4 +#define PUPA_PARTITION_TYPE_EXTENDED 5 +#define PUPA_PARTITION_TYPE_FAT16_GT32M 6 +#define PUPA_PARTITION_TYPE_FAT32 0xb +#define PUPA_PARTITION_TYPE_FAT32_LBA 0xc +#define PUPA_PARTITION_TYPE_FAT16_LBA 0xe +#define PUPA_PARTITION_TYPE_WIN95_EXTENDED 0xf +#define PUPA_PARTITION_TYPE_EZD 0x55 +#define PUPA_PARTITION_TYPE_MINIX 0x80 +#define PUPA_PARTITION_TYPE_LINUX_MINIX 0x81 +#define PUPA_PARTITION_TYPE_EXT2FS 0x83 +#define PUPA_PARTITION_TYPE_LINUX_EXTENDED 0x85 +#define PUPA_PARTITION_TYPE_VSTAFS 0x9e +#define PUPA_PARTITION_TYPE_FREEBSD 0xa5 +#define PUPA_PARTITION_TYPE_OPENBSD 0xa6 +#define PUPA_PARTITION_TYPE_NETBSD 0xa9 +#define PUPA_PARTITION_TYPE_LINUX_RAID 0xfd + +/* Constants for BSD disk label. */ +#define PUPA_PARTITION_BSD_LABEL_SECTOR 1 +#define PUPA_PARTITION_BSD_LABEL_MAGIC 0x82564557 +#define PUPA_PARTITION_BSD_MAX_ENTRIES 8 + +/* BSD partition types. */ +#define PUPA_PARTITION_BSD_TYPE_UNUSED 0 +#define PUPA_PARTITION_BSD_TYPE_SWAP 1 +#define PUPA_PARTITION_BSD_TYPE_V6 2 +#define PUPA_PARTITION_BSD_TYPE_V7 3 +#define PUPA_PARTITION_BSD_TYPE_SYSV 4 +#define PUPA_PARTITION_BSD_TYPE_V71K 5 +#define PUPA_PARTITION_BSD_TYPE_V8 6 +#define PUPA_PARTITION_BSD_TYPE_BSDFFS 7 +#define PUPA_PARTITION_BSD_TYPE_MSDOS 8 +#define PUPA_PARTITION_BSD_TYPE_BSDLFS 9 +#define PUPA_PARTITION_BSD_TYPE_OTHER 10 +#define PUPA_PARTITION_BSD_TYPE_HPFS 11 +#define PUPA_PARTITION_BSD_TYPE_ISO9660 12 +#define PUPA_PARTITION_BSD_TYPE_BOOT 13 + +/* FreeBSD-specific types. */ +#define PUPA_PARTITION_FREEBSD_TYPE_VINUM 14 +#define PUPA_PARTITION_FREEBSD_TYPE_RAID 15 +#define PUPA_PARTITION_FREEBSD_TYPE_JFS2 21 + +/* NetBSD-specific types. */ +#define PUPA_PARTITION_NETBSD_TYPE_ADOS 14 +#define PUPA_PARTITION_NETBSD_TYPE_HFS 15 +#define PUPA_PARTITION_NETBSD_TYPE_FILECORE 16 +#define PUPA_PARTITION_NETBSD_TYPE_EXT2FS 17 +#define PUPA_PARTITION_NETBSD_TYPE_NTFS 18 +#define PUPA_PARTITION_NETBSD_TYPE_RAID 19 +#define PUPA_PARTITION_NETBSD_TYPE_CCD 20 +#define PUPA_PARTITION_NETBSD_TYPE_JFS2 21 +#define PUPA_PARTITION_NETBSD_TYPE_APPLEUFS 22 + +/* OpenBSD-specific types. */ +#define PUPA_PARTITION_OPENBSD_TYPE_ADOS 14 +#define PUPA_PARTITION_OPENBSD_TYPE_HFS 15 +#define PUPA_PARTITION_OPENBSD_TYPE_FILECORE 16 +#define PUPA_PARTITION_OPENBSD_TYPE_EXT2FS 17 +#define PUPA_PARTITION_OPENBSD_TYPE_NTFS 18 +#define PUPA_PARTITION_OPENBSD_TYPE_RAID 19 + +/* The BSD partition entry. */ +struct pupa_partition_bsd_entry +{ + pupa_uint32_t size; + pupa_uint32_t offset; + pupa_uint32_t fragment_size; + pupa_uint8_t fs_type; + pupa_uint8_t fs_fragments; + pupa_uint16_t fs_cylinders; +} __attribute__ ((packed)); + +/* The BSD disk label. Only define members useful for PUPA. */ +struct pupa_partition_disk_label +{ + pupa_uint32_t magic; + pupa_uint8_t padding[128]; + pupa_uint32_t magic2; + pupa_uint16_t checksum; + pupa_uint16_t num_partitions; + pupa_uint32_t boot_size; + pupa_uint32_t superblock_size; + struct pupa_partition_bsd_entry entries[PUPA_PARTITION_BSD_MAX_ENTRIES]; +} __attribute__ ((packed)); + +/* The partition entry. */ +struct pupa_partition_entry +{ + /* If active, 0x80, otherwise, 0x00. */ + pupa_uint8_t flag; + + /* The head of the start. */ + pupa_uint8_t start_head; + + /* (S | ((C >> 2) & 0xC0)) where S is the sector of the start and C + is the cylinder of the start. Note that S is counted from one. */ + pupa_uint8_t start_sector; + + /* (C & 0xFF) where C is the cylinder of the start. */ + pupa_uint8_t start_cylinder; + + /* The partition type. */ + pupa_uint8_t type; + + /* The end versions of start_head, start_sector and start_cylinder, + respectively. */ + pupa_uint8_t end_head; + pupa_uint8_t end_sector; + pupa_uint8_t end_cylinder; + + /* The start sector. Note that this is counted from zero. */ + pupa_uint32_t start; + + /* The length in sector units. */ + pupa_uint32_t length; +} __attribute__ ((packed)); + +/* The structure of MBR. */ +struct pupa_partition_mbr +{ + /* The code area (actually, including BPB). */ + pupa_uint8_t code[446]; + + /* Four partition entries. */ + struct pupa_partition_entry entries[4]; + + /* The signature 0xaa55. */ + pupa_uint16_t signature; +} __attribute__ ((packed)); + +/* Partition description. */ +struct pupa_partition +{ + /* The start sector. */ + unsigned long start; + + /* The length in sector units. */ + unsigned long len; + + /* The offset of the partition table. */ + unsigned long offset; + + /* The offset of the extended partition. */ + unsigned long ext_offset; + + /* The index of this partition in the partition table. */ + int index; + + /* The DOS partition number. */ + int dos_part; + + /* The BSD partition number (a == 0). */ + int bsd_part; + + /* The DOS partition type. */ + int dos_type; + + /* The BSD partition type. */ + int bsd_type; +}; +typedef struct pupa_partition *pupa_partition_t; + +struct pupa_disk; + +pupa_partition_t EXPORT_FUNC(pupa_partition_probe) (struct pupa_disk *disk, + const char *str); +pupa_err_t EXPORT_FUNC(pupa_partition_iterate) (struct pupa_disk *disk, + int (*hook) (const pupa_partition_t partition)); +char *EXPORT_FUNC(pupa_partition_get_name) (const pupa_partition_t partition); + +static inline unsigned long +pupa_partition_get_start (const pupa_partition_t p) +{ + return p->start; +} + +static inline unsigned long +pupa_partition_get_len (const pupa_partition_t p) +{ + return p->len; +} + +static inline int +pupa_partition_is_empty (int type) +{ + return (type == PUPA_PARTITION_TYPE_NONE); +} + +static inline int +pupa_partition_is_extended (int type) +{ + return (type == PUPA_PARTITION_TYPE_EXTENDED + || type == PUPA_PARTITION_TYPE_WIN95_EXTENDED + || type == PUPA_PARTITION_TYPE_LINUX_EXTENDED); +} + +static inline int +pupa_partition_is_bsd (int type) +{ + return (type == PUPA_PARTITION_TYPE_FREEBSD + || type == PUPA_PARTITION_TYPE_OPENBSD + || type == PUPA_PARTITION_TYPE_NETBSD); +} + +#endif /* ! PUPA_PARTITION_HEADER */ diff --git a/include/grub/i386/types.h b/include/grub/i386/types.h new file mode 100644 index 000000000..bc49cd6de --- /dev/null +++ b/include/grub/i386/types.h @@ -0,0 +1,32 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PUPA_TYPES_CPU_HEADER +#define PUPA_TYPES_CPU_HEADER 1 + +/* The size of void *. */ +#define PUPA_HOST_SIZEOF_VOID_P 4 + +/* The size of long. */ +#define PUPA_HOST_SIZEOF_LONG 4 + +/* i386 is little-endian. */ +#undef PUPA_HOST_WORDS_BIGENDIAN + +#endif /* ! PUPA_TYPES_CPU_HEADER */ diff --git a/include/grub/kernel.h b/include/grub/kernel.h new file mode 100644 index 000000000..4d5a06c90 --- /dev/null +++ b/include/grub/kernel.h @@ -0,0 +1,61 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * 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 PUPA_KERNEL_HEADER +#define PUPA_KERNEL_HEADER 1 + +#include + +/* The module header. */ +struct pupa_module_header +{ + /* The offset of object code. */ + pupa_off_t offset; + /* The size of object code plus this header. */ + pupa_size_t size; +}; + +/* The start address of the kernel. */ +extern pupa_addr_t pupa_start_addr; + +/* The end address of the kernel. */ +extern pupa_addr_t pupa_end_addr; + +/* The total size of modules including their headers. */ +extern pupa_size_t pupa_total_module_size; + +/* The size of the kernel image. */ +extern pupa_size_t pupa_kernel_image_size; + +/* The start point of the C code. */ +void pupa_main (void); + +/* The machine-specific initialization. This must initialize memory. */ +void pupa_machine_init (void); + +/* Return the end address of the core image. */ +pupa_addr_t pupa_get_end_addr (void); + +/* Register all the exported symbols. This is automatically generated. */ +void pupa_register_exported_symbols (void); + +/* Enter normal mode. */ +void pupa_enter_normal_mode (void); + +#endif /* ! PUPA_KERNEL_HEADER */ diff --git a/include/grub/loader.h b/include/grub/loader.h new file mode 100644 index 000000000..ea2d049cd --- /dev/null +++ b/include/grub/loader.h @@ -0,0 +1,37 @@ +/* loader.h - OS loaders */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * 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 PUPA_LOADER_HEADER +#define PUPA_LOADER_HEADER 1 + +#include +#include +#include +#include + +void EXPORT_FUNC(pupa_loader_set) (pupa_err_t (*load_module) (int argc, + char *argv[]), + pupa_err_t (*boot) (void), + pupa_err_t (*unload) (void)); + +pupa_err_t EXPORT_FUNC(pupa_loader_load_module) (int argc, char *argv[]); +pupa_err_t EXPORT_FUNC(pupa_loader_boot) (void); + +#endif /* ! PUPA_LOADER_HEADER */ diff --git a/include/grub/misc.h b/include/grub/misc.h new file mode 100644 index 000000000..fa2832245 --- /dev/null +++ b/include/grub/misc.h @@ -0,0 +1,47 @@ +/* misc.h - prototypes for misc functions */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PUPA_MISC_HEADER +#define PUPA_MISC_HEADER 1 + +#include +#include +#include + +void *EXPORT_FUNC(pupa_memcpy) (void *dest, const void *src, pupa_size_t n); +int EXPORT_FUNC(pupa_memcmp) (const void *s1, const void *s2, pupa_size_t n); +int EXPORT_FUNC(pupa_strcmp) (const char *s1, const char *s2); +char *EXPORT_FUNC(pupa_strchr) (const char *s, int c); +char *EXPORT_FUNC(pupa_strrchr) (const char *s, int c); +int EXPORT_FUNC(pupa_isspace) (int c); +int EXPORT_FUNC(pupa_isprint) (int c); +int EXPORT_FUNC(pupa_isalpha) (int c); +int EXPORT_FUNC(pupa_tolower) (int c); +unsigned long EXPORT_FUNC(pupa_strtoul) (const char *str, char **end, int base); +char *EXPORT_FUNC(pupa_strdup) (const char *s); +void *EXPORT_FUNC(pupa_memset) (void *s, int c, pupa_size_t n); +pupa_size_t EXPORT_FUNC(pupa_strlen) (const char *s); +int EXPORT_FUNC(pupa_printf) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); +int EXPORT_FUNC(pupa_vprintf) (const char *fmt, va_list args); +int EXPORT_FUNC(pupa_sprintf) (char *str, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); +int EXPORT_FUNC(pupa_vsprintf) (char *str, const char *fmt, va_list args); +void EXPORT_FUNC(pupa_stop) (void) __attribute__ ((noreturn)); + +#endif /* ! PUPA_MISC_HEADER */ diff --git a/include/grub/mm.h b/include/grub/mm.h new file mode 100644 index 000000000..2033574dc --- /dev/null +++ b/include/grub/mm.h @@ -0,0 +1,39 @@ +/* mm.h - prototypes and declarations for memory manager */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PUPA_MM_H +#define PUPA_MM_H 1 + +#include +#include + +void pupa_mm_init_region (void *addr, unsigned size); +void *EXPORT_FUNC(pupa_malloc) (unsigned size); +void EXPORT_FUNC(pupa_free) (void *ptr); +void *EXPORT_FUNC(pupa_realloc) (void *ptr, unsigned size); +void *EXPORT_FUNC(pupa_memalign) (unsigned align, unsigned size); + +/* For debugging. */ +#define MM_DEBUG 1 +#if MM_DEBUG +void pupa_mm_dump (unsigned lineno); +#endif + +#endif /* ! PUPA_MM_H */ diff --git a/include/grub/net.h b/include/grub/net.h new file mode 100644 index 000000000..e7cbcb6d2 --- /dev/null +++ b/include/grub/net.h @@ -0,0 +1,73 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PUPA_NET_HEADER +#define PUPA_NET_HEADER 1 + +#include +#include +#include + +struct pupa_net; + +struct pupa_net_dev +{ + /* The device name. */ + const char *name; + + /* FIXME: Just a template. */ + int (*probe) (struct pupa_net *net, const void *addr); + void (*reset) (struct pupa_net *net); + int (*poll) (struct pupa_net *net); + void (*transmit) (struct pupa_net *net, const void *destip, + unsigned srcsock, unsigned destsock, const void *packet); + void (*disable) (struct pupa_net *net); + + /* The next net device. */ + struct pupa_net_dev *next; +}; +typedef struct pupa_net_dev *pupa_net_dev_t; + +struct pupa_fs; + +struct pupa_net +{ + /* The net name. */ + const char *name; + + /* The underlying disk device. */ + pupa_net_dev_t dev; + + /* The binding filesystem. */ + struct pupa_fs *fs; + + /* FIXME: More data would be required, such as an IP address, a mask, + a gateway, etc. */ + + /* Device-specific data. */ + void *data; +}; +typedef struct pupa_net *pupa_net_t; + +/* FIXME: How to abstract networks? More consideration is necessary. */ + +/* Note: Networks are very different from disks, because networks must + be initialized before used, and the status is persistent. */ + +#endif /* ! PUPA_NET_HEADER */ diff --git a/include/grub/rescue.h b/include/grub/rescue.h new file mode 100644 index 000000000..bf102678f --- /dev/null +++ b/include/grub/rescue.h @@ -0,0 +1,37 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * 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 PUPA_RESCUE_HEADER +#define PUPA_RESCUE_HEADER 1 + +#include + +/* Enter rescue mode. */ +void pupa_enter_rescue_mode (void); + +/* Register a rescue mode command. */ +void EXPORT_FUNC(pupa_rescue_register_command) (const char *name, + void (*func) (int argc, + char *argv[]), + const char *message); + +/* Unregister a rescue mode command. */ +void EXPORT_FUNC(pupa_rescue_unregister_command) (const char *name); + +#endif /* ! PUPA_RESCUE_HEADER */ diff --git a/include/grub/symbol.h b/include/grub/symbol.h new file mode 100644 index 000000000..c51df2600 --- /dev/null +++ b/include/grub/symbol.h @@ -0,0 +1,40 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc. + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PUPA_SYMBOL_HEADER +#define PUPA_SYMBOL_HEADER 1 + +#include + +/* Add an underscore to a C symbol in assembler code if needed. */ +#ifdef HAVE_ASM_USCORE +# define EXT_C(sym) _ ## sym +#else +# define EXT_C(sym) sym +#endif + +#define FUNCTION(x) .globl EXT_C(x) ; EXT_C(x): +#define VARIABLE(x) FUNCTION(x) + +/* Mark an exported symbol. */ +#define EXPORT_FUNC(x) x +#define EXPORT_VAR(x) x + +#endif /* ! PUPA_SYMBOL_HEADER */ diff --git a/include/grub/term.h b/include/grub/term.h new file mode 100644 index 000000000..87b285dec --- /dev/null +++ b/include/grub/term.h @@ -0,0 +1,120 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Free Software Foundation, Inc. + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PUPA_TERM_HEADER +#define PUPA_TERM_HEADER 1 + +#include +#include + +/* These are used to represent the various color states we use. */ +typedef enum + { + /* The color used to display all text that does not use the + user defined colors below. */ + PUPA_TERM_COLOR_STANDARD, + /* The user defined colors for normal text. */ + PUPA_TERM_COLOR_NORMAL, + /* The user defined colors for highlighted text. */ + PUPA_TERM_COLOR_HIGHLIGHT + } +pupa_term_color_state; + +/* Flags for representing the capabilities of a terminal. */ +/* Some notes about the flags: + - These flags are used by higher-level functions but not terminals + themselves. + - If a terminal is dumb, you may assume that only putchar, getkey and + checkkey are called. + - Some fancy features (setcolorstate, setcolor and setcursor) can be set + to NULL. */ + +/* Set when input characters shouldn't be echoed back. */ +#define PUPA_TERM_NO_ECHO (1 << 0) +/* Set when the editing feature should be disabled. */ +#define PUPA_TERM_NO_EDIT (1 << 1) +/* Set when the terminal cannot do fancy things. */ +#define PUPA_TERM_DUMB (1 << 2) +/* Set when the terminal needs to be initialized. */ +#define PUPA_TERM_NEED_INIT (1 << 16) + +struct pupa_term +{ + /* The terminal name. */ + const char *name; + + /* Put a character. */ + void (*putchar) (int c); + + /* Check if any input character is available. */ + int (*checkkey) (void); + + /* Get a character. */ + int (*getkey) (void); + + /* Get the cursor position. The return value is ((X << 8) | Y). */ + pupa_uint16_t (*getxy) (void); + + /* Go to the position (X, Y). */ + void (*gotoxy) (pupa_uint8_t x, pupa_uint8_t y); + + /* Clear the screen. */ + void (*cls) (void); + + /* Set the current color to be used */ + void (*setcolorstate) (pupa_term_color_state state); + + /* Set the normal color and the highlight color. The format of each + color is VGA's. */ + void (*setcolor) (pupa_uint8_t normal_color, pupa_uint8_t highlight_color); + + /* Turn on/off the cursor. */ + void (*setcursor) (int on); + + /* The feature flags defined above. */ + pupa_uint32_t flags; + + /* The next terminal. */ + struct pupa_term *next; +}; +typedef struct pupa_term *pupa_term_t; + +void EXPORT_FUNC(pupa_term_register) (pupa_term_t term); +void EXPORT_FUNC(pupa_term_unregister) (pupa_term_t term); +void EXPORT_FUNC(pupa_term_iterate) (int (*hook) (pupa_term_t term)); + +void EXPORT_FUNC(pupa_term_set_current) (pupa_term_t term); +pupa_term_t EXPORT_FUNC(pupa_term_get_current) (void); + +void EXPORT_FUNC(pupa_putchar) (int c); +int EXPORT_FUNC(pupa_getkey) (void); +int EXPORT_FUNC(pupa_checkkey) (void); +pupa_uint16_t EXPORT_FUNC(pupa_getxy) (void); +void EXPORT_FUNC(pupa_gotoxy) (pupa_uint8_t x, pupa_uint8_t y); +void EXPORT_FUNC(pupa_cls) (void); +void EXPORT_FUNC(pupa_setcolorstate) (pupa_term_color_state state); +void EXPORT_FUNC(pupa_setcolor) (pupa_uint8_t normal_color, + pupa_uint8_t highlight_color); +int EXPORT_FUNC(pupa_setcursor) (int on); + +/* For convenience. */ +#define PUPA_TERM_ASCII_CHAR(c) ((c) & 0xff) + +#endif /* ! PUPA_TERM_HEADER */ diff --git a/include/grub/types.h b/include/grub/types.h new file mode 100644 index 000000000..0dda38486 --- /dev/null +++ b/include/grub/types.h @@ -0,0 +1,141 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * 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 PUPA_TYPES_HEADER +#define PUPA_TYPES_HEADER 1 + +#include +#include + +#ifdef PUPA_UTIL +# define PUPA_CPU_SIZEOF_VOID_P SIZEOF_VOID_P +# define PUPA_CPU_SIZEOF_LONG SIZEOF_LONG +# ifdef WORDS_BIGENDIAN +# define PUPA_CPU_WORDS_BIGENDIAN 1 +# else +# undef PUPA_CPU_WORDS_BIGENDIAN +# endif +#else /* ! PUPA_UTIL */ +# define PUPA_CPU_SIZEOF_VOID_P PUPA_HOST_SIZEOF_VOID_P +# define PUPA_CPU_SIZEOF_LONG PUPA_HOST_SIZEOF_LONG +# ifdef PUPA_HOST_WORDS_BIGENDIAN +# define PUPA_CPU_WORDS_BIGENDIAN 1 +# else +# undef PUPA_CPU_WORDS_BIGENDIAN +# endif +#endif /* ! PUPA_UTIL */ + +#if PUPA_CPU_SIZEOF_VOID_P != PUPA_CPU_SIZEOF_LONG +# error "This architecture is not supported because sizeof(void *) != sizeof(long)" +#endif + +#if PUPA_CPU_SIZEOF_VOID_P != 4 && PUPA_CPU_SIZEOF_VOID_P != 8 +# error "This architecture is not supported because sizeof(void *) != 4 and sizeof(void *) != 8" +#endif + +/* Define various wide integers. */ +typedef signed char pupa_int8_t; +typedef short pupa_int16_t; +typedef int pupa_int32_t; +#if PUPA_CPU_SIZEOF_VOID_P == 8 +typedef long pupa_int64_t; +#else +typedef long long pupa_int64_t; +#endif + +typedef unsigned char pupa_uint8_t; +typedef unsigned short pupa_uint16_t; +typedef unsigned pupa_uint32_t; +#if PUPA_CPU_SIZEOF_VOID_P == 8 +typedef unsigned long pupa_uint64_t; +#else +typedef unsigned long long pupa_uint64_t; +#endif + +/* Misc types. */ +#if PUPA_HOST_SIZE_OF_VOID_P == 8 +typedef pupa_uint64_t pupa_addr_t; +typedef pupa_uint64_t pupa_off_t; +typedef pupa_uint64_t pupa_size_t; +typedef pupa_int64_t pupa_ssize_t; +#else +typedef pupa_uint32_t pupa_addr_t; +typedef pupa_uint32_t pupa_off_t; +typedef pupa_uint32_t pupa_size_t; +typedef pupa_int32_t pupa_ssize_t; +#endif + +/* Byte-orders. */ +#define pupa_swap_bytes16(x) \ +({ \ + pupa_uint16_t _x = (x); \ + (_x << 8) | (_x >> 8); \ +}) + +#define pupa_swap_bytes32(x) \ +({ \ + pupa_uint32_t _x = (x); \ + (pupa_uint32_t) ((_x << 24) \ + | ((_x & (pupa_uint32_t) 0xFF00UL) << 8) \ + | ((_x & (pupa_uint32_t) 0xFF0000UL) >> 8) \ + | (_x >> 24)); \ +}) + +#define pupa_swap_bytes64(x) \ +({ \ + pupa_uint64_t _x = (x); \ + (pupa_uint64_t) ((_x << 56) \ + | ((_x & (pupa_uint64_t) 0xFF00ULL) << 40) \ + | ((_x & (pupa_uint64_t) 0xFF0000ULL) << 24) \ + | ((_x & (pupa_uint64_t) 0xFF000000ULL) << 8) \ + | ((_x & (pupa_uint64_t) 0xFF00000000ULL) >> 8) \ + | ((_x & (pupa_uint64_t) 0xFF0000000000ULL) >> 24) \ + | ((_x & (pupa_uint64_t) 0xFF000000000000ULL) >> 40) \ + | (_x >> 56)); \ +}) + +#ifdef PUPA_CPU_WORDS_BIGENDIAN +# define pupa_cpu_to_le16(x) pupa_swap_bytes16(x) +# define pupa_cpu_to_le32(x) pupa_swap_bytes32(x) +# define pupa_cpu_to_le64(x) pupa_swap_bytes64(x) +# define pupa_le_to_cpu16(x) pupa_swap_bytes16(x) +# define pupa_le_to_cpu32(x) pupa_swap_bytes32(x) +# define pupa_le_to_cpu64(x) pupa_swap_bytes64(x) +# define pupa_cpu_to_be16(x) ((pupa_uint16_t) (x)) +# define pupa_cpu_to_be32(x) ((pupa_uint32_t) (x)) +# define pupa_cpu_to_be64(x) ((pupa_uint64_t) (x)) +# define pupa_be_to_cpu16(x) ((pupa_uint16_t) (x)) +# define pupa_be_to_cpu32(x) ((pupa_uint32_t) (x)) +# define pupa_be_to_cpu64(x) ((pupa_uint64_t) (x)) +#else /* ! WORDS_BIGENDIAN */ +# define pupa_cpu_to_le16(x) ((pupa_uint16_t) (x)) +# define pupa_cpu_to_le32(x) ((pupa_uint32_t) (x)) +# define pupa_cpu_to_le64(x) ((pupa_uint64_t) (x)) +# define pupa_le_to_cpu16(x) ((pupa_uint16_t) (x)) +# define pupa_le_to_cpu32(x) ((pupa_uint32_t) (x)) +# define pupa_le_to_cpu64(x) ((pupa_uint64_t) (x)) +# define pupa_cpu_to_be16(x) pupa_swap_bytes16(x) +# define pupa_cpu_to_be32(x) pupa_swap_bytes32(x) +# define pupa_cpu_to_be64(x) pupa_swap_bytes64(x) +# define pupa_be_to_cpu16(x) pupa_swap_bytes16(x) +# define pupa_be_to_cpu32(x) pupa_swap_bytes32(x) +# define pupa_be_to_cpu64(x) pupa_swap_bytes64(x) +#endif /* ! WORDS_BIGENDIAN */ + +#endif /* ! PUPA_TYPES_HEADER */ diff --git a/include/grub/util/misc.h b/include/grub/util/misc.h new file mode 100644 index 000000000..48bf0e961 --- /dev/null +++ b/include/grub/util/misc.h @@ -0,0 +1,40 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PUPA_UTIL_MISC_HEADER +#define PUPA_UTIL_MISC_HEADER 1 + +#include +#include + +extern char *progname; +extern int verbosity; + +void pupa_util_info (const char *fmt, ...); +void pupa_util_error (const char *fmt, ...) __attribute__ ((noreturn)); + +void *xmalloc (size_t size); +char *xstrdup (const char *str); + +char *pupa_util_get_path (const char *dir, const char *file); +size_t pupa_util_get_image_size (const char *path); +char *pupa_util_read_image (const char *path); +void pupa_util_write_image (const char *img, size_t size, FILE *out); + +#endif /* ! PUPA_UTIL_MISC_HEADER */ diff --git a/include/grub/util/resolve.h b/include/grub/util/resolve.h new file mode 100644 index 000000000..35d2507d9 --- /dev/null +++ b/include/grub/util/resolve.h @@ -0,0 +1,36 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PUPA_UTIL_RESOLVE_HEADER +#define PUPA_UTIL_RESOLVE_HEADER 1 + +struct pupa_util_path_list +{ + const char *name; + struct pupa_util_path_list *next; +}; + +/* Resolve the dependencies of the modules MODULES using the information + in the file DEP_LIST_FILE. The directory PREFIX is used to find files. */ +struct pupa_util_path_list * +pupa_util_resolve_dependencies (const char *prefix, + const char *dep_list_file, + char *modules[]); + +#endif /* ! PUPA_UTIL_RESOLVE_HEADER */ diff --git a/install-sh b/install-sh new file mode 100644 index 000000000..e9de23842 --- /dev/null +++ b/install-sh @@ -0,0 +1,251 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + chmodcmd="" + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/kern/device.c b/kern/device.c new file mode 100644 index 000000000..2c37d936b --- /dev/null +++ b/kern/device.c @@ -0,0 +1,99 @@ +/* device.c - device manager */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +static char *pupa_device_root; + +pupa_err_t +pupa_device_set_root (const char *name) +{ + pupa_free (pupa_device_root); + pupa_device_root = pupa_strdup (name); + return pupa_errno; +} + +const char * +pupa_device_get_root (void) +{ + if (! pupa_device_root) + pupa_error (PUPA_ERR_BAD_DEVICE, "no root device"); + + return pupa_device_root; +} + +pupa_device_t +pupa_device_open (const char *name) +{ + pupa_disk_t disk = 0; + pupa_device_t dev = 0; + + if (! name) + { + if (! pupa_device_root) + { + pupa_error (PUPA_ERR_BAD_DEVICE, "no device is set"); + goto fail; + } + + name = pupa_device_root; + } + + dev = pupa_malloc (sizeof (*dev)); + if (! dev) + goto fail; + + /* Try to open a disk. */ + disk = pupa_disk_open (name); + if (! disk) + { + pupa_error (PUPA_ERR_BAD_DEVICE, "unknown device"); + goto fail; + } + + dev->disk = disk; + dev->net = 0; /* FIXME */ + + return dev; + + fail: + if (disk) + pupa_disk_close (disk); + + pupa_free (dev); + + return 0; +} + +pupa_err_t +pupa_device_close (pupa_device_t device) +{ + if (device->disk) + pupa_disk_close (device->disk); + + pupa_free (device); + + return pupa_errno; +} diff --git a/kern/disk.c b/kern/disk.c new file mode 100644 index 000000000..04e15432a --- /dev/null +++ b/kern/disk.c @@ -0,0 +1,474 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +/* Disk cache. */ +struct pupa_disk_cache +{ + unsigned long id; + unsigned long sector; + char *data; + int lock; +}; + +static struct pupa_disk_cache pupa_disk_cache_table[PUPA_DISK_CACHE_NUM]; + +#if 0 +static unsigned long pupa_disk_cache_hits; +static unsigned long pupa_disk_cache_misses; + +void +pupa_disk_cache_get_performance (unsigned long *hits, unsigned long *misses) +{ + *hits = pupa_disk_cache_hits; + *misses = pupa_disk_cache_misses; +} +#endif + +static unsigned +pupa_disk_cache_get_index (unsigned long id, unsigned long sector) +{ + return ((id * 2606459 + (sector >> PUPA_DISK_CACHE_BITS)) + % PUPA_DISK_CACHE_NUM); +} + +static void +pupa_disk_cache_invalidate (unsigned long id, unsigned long sector) +{ + unsigned index; + struct pupa_disk_cache *cache; + + sector &= ~(PUPA_DISK_CACHE_SIZE - 1); + index = pupa_disk_cache_get_index (id, sector); + cache = pupa_disk_cache_table + index; + + if (cache->id == id && cache->sector == sector && cache->data) + { + cache->lock = 1; + pupa_free (cache->data); + cache->data = 0; + cache->lock = 0; + } +} + +void +pupa_disk_cache_invalidate_all (void) +{ + unsigned i; + + for (i = 0; i < PUPA_DISK_CACHE_NUM; i++) + { + struct pupa_disk_cache *cache = pupa_disk_cache_table + i; + + if (cache->data && ! cache->lock) + { + pupa_free (cache->data); + cache->data = 0; + } + } +} + +static char * +pupa_disk_cache_fetch (unsigned long id, unsigned long sector) +{ + struct pupa_disk_cache *cache; + unsigned index; + + index = pupa_disk_cache_get_index (id, sector); + cache = pupa_disk_cache_table + index; + + if (cache->id == id && cache->sector == sector) + { + cache->lock = 1; +#if 0 + pupa_disk_cache_hits++; +#endif + return cache->data; + } + +#if 0 + pupa_disk_cache_misses++; +#endif + + return 0; +} + +static void +pupa_disk_cache_unlock (unsigned long id, unsigned long sector) +{ + struct pupa_disk_cache *cache; + unsigned index; + + index = pupa_disk_cache_get_index (id, sector); + cache = pupa_disk_cache_table + index; + + if (cache->id == id && cache->sector == sector) + cache->lock = 0; +} + +static pupa_err_t +pupa_disk_cache_store (unsigned long id, unsigned long sector, + const char *data) +{ + unsigned index; + struct pupa_disk_cache *cache; + + pupa_disk_cache_invalidate (id, sector); + + index = pupa_disk_cache_get_index (id, sector); + cache = pupa_disk_cache_table + index; + + cache->data = pupa_malloc (PUPA_DISK_SECTOR_SIZE << PUPA_DISK_CACHE_BITS); + if (! cache->data) + return pupa_errno; + + pupa_memcpy (cache->data, data, + PUPA_DISK_SECTOR_SIZE << PUPA_DISK_CACHE_BITS); + cache->id = id; + cache->sector = sector; + + return PUPA_ERR_NONE; +} + + + +static pupa_disk_dev_t pupa_disk_dev_list; + +void +pupa_disk_dev_register (pupa_disk_dev_t dev) +{ + dev->next = pupa_disk_dev_list; + pupa_disk_dev_list = dev; +} + +void +pupa_disk_dev_unregister (pupa_disk_dev_t dev) +{ + pupa_disk_dev_t *p, q; + + for (p = &pupa_disk_dev_list, q = *p; q; p = &(q->next), q = q->next) + if (q == dev) + { + *p = q->next; + break; + } +} + +void +pupa_disk_dev_iterate (int (*hook) (const char *name)) +{ + pupa_disk_dev_t p; + + for (p = pupa_disk_dev_list; p; p = p->next) + if ((p->iterate) (hook)) + break; +} + +pupa_disk_t +pupa_disk_open (const char *name) +{ + char *p; + pupa_disk_t disk; + pupa_disk_dev_t dev; + char *raw = (char *) name; + + disk = (pupa_disk_t) pupa_malloc (sizeof (*disk)); + if (! disk) + return 0; + + disk->dev = 0; + disk->read_hook = 0; + disk->partition = 0; + disk->data = 0; + disk->name = pupa_strdup (name); + if (! disk->name) + goto fail; + + p = pupa_strchr (name, ','); + if (p) + { + pupa_size_t len = p - name; + + raw = pupa_malloc (len + 1); + if (! raw) + goto fail; + + pupa_memcpy (raw, name, len); + raw[len] = '\0'; + } + + for (dev = pupa_disk_dev_list; dev; dev = dev->next) + { + if ((dev->open) (raw, disk) == PUPA_ERR_NONE) + break; + else if (pupa_errno == PUPA_ERR_UNKNOWN_DEVICE) + pupa_errno = PUPA_ERR_NONE; + else + goto fail; + } + + if (! dev) + { + pupa_error (PUPA_ERR_UNKNOWN_DEVICE, "no such disk"); + goto fail; + } + + if (p && ! disk->has_partitions) + { + pupa_error (PUPA_ERR_BAD_DEVICE, "no partition on this disk"); + goto fail; + } + + disk->dev = dev; + + if (p) + disk->partition = pupa_partition_probe (disk, p + 1); + + fail: + + if (raw && raw != name) + pupa_free (raw); + + if (pupa_errno != PUPA_ERR_NONE) + { + pupa_disk_close (disk); + return 0; + } + + return disk; +} + +void +pupa_disk_close (pupa_disk_t disk) +{ + if (disk->dev && disk->dev->close) + (disk->dev->close) (disk); + + pupa_free (disk->partition); + pupa_free ((void *) disk->name); + pupa_free (disk); +} + +static pupa_err_t +pupa_disk_check_range (pupa_disk_t disk, unsigned long *sector, + unsigned long *offset, pupa_ssize_t size) +{ + *sector += *offset >> PUPA_DISK_SECTOR_BITS; + *offset &= PUPA_DISK_SECTOR_SIZE - 1; + + if (disk->partition) + { + unsigned long start, len; + + start = pupa_partition_get_start (disk->partition); + len = pupa_partition_get_len (disk->partition); + + if (*sector >= len + || len - *sector < ((*offset + size + PUPA_DISK_SECTOR_SIZE - 1) + >> PUPA_DISK_SECTOR_BITS)) + return pupa_error (PUPA_ERR_OUT_OF_RANGE, "out of partition"); + + *sector += start; + } + + if (disk->total_sectors <= *sector + || ((*offset + size + PUPA_DISK_SECTOR_SIZE - 1) + >> PUPA_DISK_SECTOR_BITS) > disk->total_sectors - *sector) + return pupa_error (PUPA_ERR_OUT_OF_RANGE, "out of disk"); + + return PUPA_ERR_NONE; +} + +/* Read data from the disk. */ +pupa_err_t +pupa_disk_read (pupa_disk_t disk, unsigned long sector, + unsigned long offset, unsigned long size, char *buf) +{ + char *tmp_buf; + + /* First of all, check if the region is within the disk. */ + if (pupa_disk_check_range (disk, §or, &offset, size) != PUPA_ERR_NONE) + return pupa_errno; + + /* Allocate a temporary buffer. */ + tmp_buf = pupa_malloc (PUPA_DISK_SECTOR_SIZE << PUPA_DISK_CACHE_BITS); + if (! tmp_buf) + return pupa_errno; + + /* Until SIZE is zero... */ + while (size) + { + char *data; + unsigned long start_sector; + unsigned long len; + unsigned long pos; + + /* For reading bulk data. */ + start_sector = sector & ~(PUPA_DISK_CACHE_SIZE - 1); + pos = (sector - start_sector) << PUPA_DISK_SECTOR_BITS; + len = (PUPA_DISK_SECTOR_SIZE << PUPA_DISK_CACHE_BITS) - pos - offset; + if (len > size) + len = size; + + /* Fetch the cache. */ + data = pupa_disk_cache_fetch (disk->id, start_sector); + if (data) + { + /* Just copy it! */ + pupa_memcpy (buf, data + pos + offset, len); + pupa_disk_cache_unlock (disk->id, start_sector); + } + else + { + /* Otherwise read data from the disk actually. */ + if ((disk->dev->read) (disk, start_sector, + PUPA_DISK_CACHE_SIZE, tmp_buf) + != PUPA_ERR_NONE) + { + /* Uggh... Failed. Instead, just read necessary data. */ + unsigned num; + + /* If more data is required, no way. */ + if (pos + size + >= (PUPA_DISK_SECTOR_SIZE << PUPA_DISK_CACHE_BITS)) + goto finish; + + num = ((size + PUPA_DISK_SECTOR_SIZE - 1) + >> PUPA_DISK_SECTOR_BITS); + if ((disk->dev->read) (disk, sector, num, tmp_buf)) + goto finish; + + pupa_memcpy (buf, tmp_buf + offset, size); + + /* Call the read hook, if any. */ + if (disk->read_hook) + while (size) + { + (disk->read_hook) (sector, offset, + ((size > PUPA_DISK_SECTOR_SIZE) + ? PUPA_DISK_SECTOR_SIZE + : size)); + sector++; + size -= PUPA_DISK_SECTOR_SIZE - offset; + offset = 0; + } + + /* This must be the end. */ + goto finish; + } + + /* Copy it and store it in the disk cache. */ + pupa_memcpy (buf, tmp_buf + pos + offset, len); + pupa_disk_cache_store (disk->id, start_sector, tmp_buf); + } + + /* Call the read hook, if any. */ + if (disk->read_hook) + { + unsigned long s = sector; + unsigned long l = len; + + while (l) + { + (disk->read_hook) (s, offset, + ((l > PUPA_DISK_SECTOR_SIZE) + ? PUPA_DISK_SECTOR_SIZE + : l)); + s++; + l -= PUPA_DISK_SECTOR_SIZE - offset; + offset = 0; + } + } + + sector = start_sector + PUPA_DISK_CACHE_SIZE; + buf += len; + size -= len; + offset = 0; + } + + finish: + + pupa_free (tmp_buf); + + return pupa_errno; +} + +pupa_err_t +pupa_disk_write (pupa_disk_t disk, unsigned long sector, + unsigned long offset, unsigned long size, const char *buf) +{ + if (pupa_disk_check_range (disk, §or, &offset, size) != PUPA_ERR_NONE) + return -1; + + while (size) + { + if (offset != 0 || (size < PUPA_DISK_SECTOR_SIZE && size != 0)) + { + char tmp_buf[PUPA_DISK_SECTOR_SIZE]; + unsigned long len; + + if (pupa_disk_read (disk, sector, 0, PUPA_DISK_SECTOR_SIZE, tmp_buf) + != PUPA_ERR_NONE) + goto finish; + + len = PUPA_DISK_SECTOR_SIZE - offset; + if (len > size) + len = size; + + pupa_memcpy (tmp_buf + offset, buf, len); + + pupa_disk_cache_invalidate (disk->id, sector); + + if ((disk->dev->write) (disk, sector, 1, tmp_buf) != PUPA_ERR_NONE) + goto finish; + + sector++; + buf += len; + size -= len; + offset = 0; + } + else + { + unsigned long len; + unsigned long n; + + len = size & ~(PUPA_DISK_SECTOR_SIZE - 1); + n = size >> PUPA_DISK_SECTOR_BITS; + + if ((disk->dev->write) (disk, sector, n, buf) != PUPA_ERR_NONE) + goto finish; + + while (n--) + pupa_disk_cache_invalidate (disk->id, sector++); + + buf += len; + size -= len; + } + } + + finish: + + return pupa_errno; +} diff --git a/kern/dl.c b/kern/dl.c new file mode 100644 index 000000000..c22c98403 --- /dev/null +++ b/kern/dl.c @@ -0,0 +1,599 @@ +/* dl.c - loadable module support */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if PUPA_HOST_SIZEOF_VOID_P == 4 + +typedef Elf32_Word Elf_Word; +typedef Elf32_Addr Elf_Addr; +typedef Elf32_Ehdr Elf_Ehdr; +typedef Elf32_Shdr Elf_Shdr; +typedef Elf32_Sym Elf_Sym; + +# define ELF_ST_BIND(val) ELF32_ST_BIND (val) +# define ELF_ST_TYPE(val) ELF32_ST_TYPE (val) + +#elif PUPA_HOST_SIZEOF_VOID_P == 8 + +typedef Elf64_Word Elf_Word; +typedef Elf64_Addr Elf_Addr; +typedef Elf64_Ehdr Elf_Ehdr; +typedef Elf64_Shdr Elf_Shdr; +typedef Elf64_Sym Elf_Sym; + +# define ELF_ST_BIND(val) ELF64_ST_BIND (val) +# define ELF_ST_TYPE(val) ELF64_ST_TYPE (val) + +#endif + + + +struct pupa_dl_list +{ + struct pupa_dl_list *next; + pupa_dl_t mod; +}; +typedef struct pupa_dl_list *pupa_dl_list_t; + +static pupa_dl_list_t pupa_dl_head; + +static pupa_err_t +pupa_dl_add (pupa_dl_t mod) +{ + pupa_dl_list_t l; + + if (pupa_dl_get (mod->name)) + return pupa_error (PUPA_ERR_BAD_MODULE, + "`%s' is already loaded", mod->name); + + l = (pupa_dl_list_t) pupa_malloc (sizeof (*l)); + if (! l) + return pupa_errno; + + l->mod = mod; + l->next = pupa_dl_head; + pupa_dl_head = l; + + return PUPA_ERR_NONE; +} + +static void +pupa_dl_remove (pupa_dl_t mod) +{ + pupa_dl_list_t *p, q; + + for (p = &pupa_dl_head, q = *p; q; p = &q->next, q = *p) + if (q->mod == mod) + { + *p = q->next; + pupa_free (q); + return; + } +} + +pupa_dl_t +pupa_dl_get (const char *name) +{ + pupa_dl_list_t l; + + for (l = pupa_dl_head; l; l = l->next) + if (pupa_strcmp (name, l->mod->name) == 0) + return l->mod; + + return 0; +} + + + +struct pupa_symbol +{ + struct pupa_symbol *next; + const char *name; + void *addr; + pupa_dl_t mod; /* The module to which this symbol belongs. */ +}; +typedef struct pupa_symbol *pupa_symbol_t; + +/* The size of the symbol table. */ +#define PUPA_SYMTAB_SIZE 509 + +/* The symbol table (using an open-hash). */ +static struct pupa_symbol *pupa_symtab[PUPA_SYMTAB_SIZE]; + +/* Simple hash function. */ +static unsigned +pupa_symbol_hash (const char *s) +{ + unsigned key = 0; + + while (*s) + key = key * 65599 + *s++; + + return (key + (key >> 5)) % PUPA_SYMTAB_SIZE; +} + +/* Resolve the symbol name NAME and return the address. + Return NULL, if not found. */ +void * +pupa_dl_resolve_symbol (const char *name) +{ + pupa_symbol_t sym; + + for (sym = pupa_symtab[pupa_symbol_hash (name)]; sym; sym = sym->next) + if (pupa_strcmp (sym->name, name) == 0) + return sym->addr; + + return 0; +} + +/* Register a symbol with the name NAME and the address ADDR. */ +pupa_err_t +pupa_dl_register_symbol (const char *name, void *addr, pupa_dl_t mod) +{ + pupa_symbol_t sym; + unsigned k; + + sym = (pupa_symbol_t) pupa_malloc (sizeof (*sym)); + if (! sym) + return pupa_errno; + + if (mod) + { + sym->name = pupa_strdup (name); + if (! sym->name) + { + pupa_free (sym); + return pupa_errno; + } + } + else + sym->name = name; + + sym->addr = addr; + sym->mod = mod; + + k = pupa_symbol_hash (name); + sym->next = pupa_symtab[k]; + pupa_symtab[k] = sym; + + return PUPA_ERR_NONE; +} + +/* Unregister all the symbols defined in the module MOD. */ +static void +pupa_dl_unregister_symbols (pupa_dl_t mod) +{ + unsigned i; + + if (! mod) + pupa_fatal ("core symbols cannot be unregistered"); + + for (i = 0; i < PUPA_SYMTAB_SIZE; i++) + { + pupa_symbol_t sym, *p, q; + + for (p = &pupa_symtab[i], sym = *p; sym; sym = q) + { + q = sym->next; + if (sym->mod == mod) + { + *p = q; + pupa_free ((void *) sym->name); + pupa_free (sym); + } + else + p = &sym->next; + } + } +} + +/* Return the address of a section whose index is N. */ +static void * +pupa_dl_get_section_addr (pupa_dl_t mod, unsigned n) +{ + pupa_dl_segment_t seg; + + for (seg = mod->segment; seg; seg = seg->next) + if (seg->section == n) + return seg->addr; + + return 0; +} + +/* Load all segments from memory specified by E. */ +static pupa_err_t +pupa_dl_load_segments (pupa_dl_t mod, const Elf_Ehdr *e) +{ + unsigned i; + Elf_Shdr *s; + + for (i = 0, s = (Elf_Shdr *)((char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf_Shdr *)((char *) s + e->e_shentsize)) + { + if (s->sh_flags & SHF_ALLOC) + { + pupa_dl_segment_t seg; + + seg = (pupa_dl_segment_t) pupa_malloc (sizeof (*seg)); + if (! seg) + return pupa_errno; + + if (s->sh_size) + { + void *addr; + + addr = pupa_memalign (s->sh_addralign, s->sh_size); + if (! addr) + { + pupa_free (seg); + return pupa_errno; + } + + switch (s->sh_type) + { + case SHT_PROGBITS: + pupa_memcpy (addr, (char *) e + s->sh_offset, s->sh_size); + break; + case SHT_NOBITS: + pupa_memset (addr, 0, s->sh_size); + break; + } + + seg->addr = addr; + } + else + seg->addr = 0; + + seg->size = s->sh_size; + seg->section = i; + seg->next = mod->segment; + mod->segment = seg; + } + } + + return PUPA_ERR_NONE; +} + +static pupa_err_t +pupa_dl_resolve_symbols (pupa_dl_t mod, Elf_Ehdr *e) +{ + unsigned i; + Elf_Shdr *s; + Elf_Sym *sym; + const char *str; + Elf_Word size, entsize; + + for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) + if (s->sh_type == SHT_SYMTAB) + break; + + if (i == e->e_shnum) + return pupa_error (PUPA_ERR_BAD_MODULE, "no symbol table"); + + sym = (Elf_Sym *) ((char *) e + s->sh_offset); + size = s->sh_size; + entsize = s->sh_entsize; + + s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shentsize * s->sh_link); + str = (char *) e + s->sh_offset; + + for (i = 0; + i < size / entsize; + i++, sym = (Elf_Sym *) ((char *) sym + entsize)) + { + unsigned char type = ELF_ST_TYPE (sym->st_info); + unsigned char bind = ELF_ST_BIND (sym->st_info); + const char *name = str + sym->st_name; + + switch (type) + { + case STT_NOTYPE: + /* Resolve a global symbol. */ + if (sym->st_name != 0 && sym->st_shndx == 0) + { + sym->st_value = (Elf_Addr) pupa_dl_resolve_symbol (name); + if (! sym->st_value) + return pupa_error (PUPA_ERR_BAD_MODULE, + "the symbol `%s' not found", name); + } + else + sym->st_value = 0; + break; + + case STT_OBJECT: + sym->st_value += (Elf_Addr) pupa_dl_get_section_addr (mod, + sym->st_shndx); + if (bind != STB_LOCAL) + if (pupa_dl_register_symbol (name, (void *) sym->st_value, mod)) + return pupa_errno; + break; + + case STT_FUNC: + sym->st_value += (Elf_Addr) pupa_dl_get_section_addr (mod, + sym->st_shndx); + if (bind != STB_LOCAL) + if (pupa_dl_register_symbol (name, (void *) sym->st_value, mod)) + return pupa_errno; + + if (pupa_strcmp (name, "pupa_mod_init") == 0) + mod->init = (void (*) ()) sym->st_value; + else if (pupa_strcmp (name, "pupa_mod_fini") == 0) + mod->fini = (void (*) ()) sym->st_value; + break; + + case STT_SECTION: + sym->st_value = (Elf_Addr) pupa_dl_get_section_addr (mod, + sym->st_shndx); + break; + + case STT_FILE: + sym->st_value = 0; + break; + + default: + return pupa_error (PUPA_ERR_BAD_MODULE, + "unknown symbol type `%d'", (int) type); + } + } + + return PUPA_ERR_NONE; +} + +static void +pupa_dl_call_init (pupa_dl_t mod) +{ + if (mod->init) + (mod->init) (); +} + +static pupa_err_t +pupa_dl_resolve_name (pupa_dl_t mod, Elf_Ehdr *e) +{ + Elf_Shdr *s; + const char *str; + unsigned i; + + s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); + str = (char *) e + s->sh_offset; + + for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) + if (pupa_strcmp (str + s->sh_name, ".modname") == 0) + { + mod->name = pupa_strdup ((char *) e + s->sh_offset); + if (! mod->name) + return pupa_errno; + break; + } + + if (i == e->e_shnum) + return pupa_error (PUPA_ERR_BAD_MODULE, "no module name found"); + + return PUPA_ERR_NONE; +} + +static pupa_err_t +pupa_dl_resolve_dependencies (pupa_dl_t mod, Elf_Ehdr *e) +{ + Elf_Shdr *s; + const char *str; + unsigned i; + + s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); + str = (char *) e + s->sh_offset; + + for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) + if (pupa_strcmp (str + s->sh_name, ".moddeps") == 0) + { + const char *name = (char *) e + s->sh_offset; + const char *max = name + s->sh_size; + + while (name < max) + { + pupa_dl_t m; + pupa_dl_dep_t dep; + + m = pupa_dl_load (name); + if (! m) + return pupa_errno; + + dep = (pupa_dl_dep_t) pupa_malloc (sizeof (*dep)); + if (! dep) + return pupa_errno; + + dep->mod = m; + dep->next = mod->dep; + mod->dep = dep; + + name += pupa_strlen (name) + 1; + } + } + + return PUPA_ERR_NONE; +} + +/* Load a module from core memory. */ +pupa_dl_t +pupa_dl_load_core (void *addr, pupa_size_t size) +{ + Elf_Ehdr *e; + pupa_dl_t mod; + + e = addr; + if (! pupa_arch_dl_check_header (e, size)) + { + pupa_error (PUPA_ERR_BAD_MODULE, "invalid ELF header"); + return 0; + } + + mod = (pupa_dl_t) pupa_malloc (sizeof (*mod)); + if (! mod) + return 0; + + mod->name = 0; + mod->ref_count = 1; + mod->dep = 0; + mod->segment = 0; + mod->init = 0; + mod->fini = 0; + + if (pupa_dl_resolve_name (mod, e) + || pupa_dl_resolve_dependencies (mod, e) + || pupa_dl_load_segments (mod, e) + || pupa_dl_resolve_symbols (mod, e) + || pupa_arch_dl_relocate_symbols (mod, e)) + { + mod->fini = 0; + pupa_dl_unload (mod); + return 0; + } + + pupa_dl_call_init (mod); + + if (pupa_dl_add (mod)) + { + pupa_dl_unload (mod); + return 0; + } + + return mod; +} + +/* Load a module from the file FILENAME. */ +pupa_dl_t +pupa_dl_load_file (const char *filename) +{ + pupa_file_t file; + pupa_ssize_t size; + void *core = 0; + pupa_dl_t mod = 0; + + file = pupa_file_open (filename); + if (! file) + return 0; + + size = pupa_file_size (file); + core = pupa_malloc (size); + if (! core) + goto failed; + + if (pupa_file_read (file, core, size) != (int) size) + goto failed; + + mod = pupa_dl_load_core (core, size); + + failed: + pupa_file_close (file); + pupa_free (core); + + return mod; +} + +static char *pupa_dl_dir; + +/* Load a module using a symbolic name. */ +pupa_dl_t +pupa_dl_load (const char *name) +{ + char *filename; + pupa_dl_t mod; + + mod = pupa_dl_get (name); + if (mod) + { + mod->ref_count++; + return mod; + } + + if (! pupa_dl_dir) + pupa_fatal ("module dir is not initialized yet"); + + filename = (char *) pupa_malloc (pupa_strlen (pupa_dl_dir) + 1 + + pupa_strlen (name) + 3); + if (! filename) + return 0; + + pupa_sprintf (filename, "%s/%s.o", pupa_dl_dir, name); + mod = pupa_dl_load_file (filename); + pupa_free (filename); + + if (! mod) + return 0; + + if (pupa_strcmp (mod->name, name) != 0) + pupa_error (PUPA_ERR_BAD_MODULE, "mismatched names"); + + return mod; +} + +/* Unload the module MOD. */ +void +pupa_dl_unload (pupa_dl_t mod) +{ + pupa_dl_dep_t dep, depn; + pupa_dl_segment_t seg, segn; + + if (--mod->ref_count > 0) + return; + + if (mod->fini) + (mod->fini) (); + + pupa_dl_remove (mod); + pupa_dl_unregister_symbols (mod); + + for (dep = mod->dep; dep; dep = depn) + { + depn = dep->next; + pupa_dl_unload (dep->mod); + pupa_free (dep); + } + + for (seg = mod->segment; seg; seg = segn) + { + segn = seg->next; + pupa_free (seg->addr); + pupa_free (seg); + } + + pupa_free (mod->name); + pupa_free (mod); +} + +void +pupa_dl_init (const char *dir) +{ + pupa_dl_dir = (char *) dir; +} diff --git a/kern/err.c b/kern/err.c new file mode 100644 index 000000000..7e2d103e4 --- /dev/null +++ b/kern/err.c @@ -0,0 +1,61 @@ +/* err.c - error handling routines */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include + +#define PUPA_MAX_ERRMSG 256 + +pupa_err_t pupa_errno; +char pupa_errmsg[PUPA_MAX_ERRMSG]; + +pupa_err_t +pupa_error (pupa_err_t n, const char *fmt, ...) +{ + va_list ap; + + pupa_errno = n; + + va_start (ap, fmt); + pupa_vsprintf (pupa_errmsg, fmt, ap); + va_end (ap); + + return n; +} + +void +pupa_fatal (const char *fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + pupa_vprintf (fmt, ap); + va_end (ap); + + pupa_stop (); +} + +void +pupa_print_error (void) +{ + if (pupa_errno != PUPA_ERR_NONE) + pupa_printf ("error: %s\n", pupa_errmsg); +} diff --git a/kern/file.c b/kern/file.c new file mode 100644 index 000000000..7d95ba595 --- /dev/null +++ b/kern/file.c @@ -0,0 +1,158 @@ +/* file.c - file I/O functions */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +/* Get the device part of the filename NAME. It is enclosed by parentheses. */ +char * +pupa_file_get_device_name (const char *name) +{ + if (name[0] == '(') + { + char *p = pupa_strchr (name, ')'); + char *ret; + + if (! p) + { + pupa_error (PUPA_ERR_BAD_FILENAME, "missing `)'"); + return 0; + } + + ret = (char *) pupa_malloc (p - name); + if (! ret) + return 0; + + pupa_memcpy (ret, name + 1, p - name - 1); + ret[p - name - 1] = '\0'; + return ret; + } + + return 0; +} + +pupa_file_t +pupa_file_open (const char *name) +{ + pupa_device_t device; + pupa_file_t file = 0; + char *device_name; + char *file_name; + + device_name = pupa_file_get_device_name (name); + if (pupa_errno) + return 0; + + /* Get the file part of NAME. */ + file_name = pupa_strchr (name, ')'); + if (file_name) + file_name++; + else + file_name = (char *) name; + + device = pupa_device_open (device_name); + pupa_free (device_name); + if (! device) + goto fail; + + file = (pupa_file_t) pupa_malloc (sizeof (*file)); + if (! file) + goto fail; + + file->device = device; + file->offset = 0; + file->data = 0; + file->read_hook = 0; + + if (device->disk && file_name[0] != '/') + /* This is a block list. */ + file->fs = &pupa_fs_blocklist; + else + { + file->fs = pupa_fs_probe (device); + if (! file->fs) + goto fail; + } + + if ((file->fs->open) (file, file_name) != PUPA_ERR_NONE) + goto fail; + + return file; + + fail: + if (device) + pupa_device_close (device); + + /* if (net) pupa_net_close (net); */ + + pupa_free (file); + + return 0; +} + +pupa_ssize_t +pupa_file_read (pupa_file_t file, char *buf, pupa_ssize_t len) +{ + pupa_ssize_t res; + + if (len == 0 || len > file->size - file->offset) + len = file->size - file->offset; + + if (len == 0) + return 0; + + res = (file->fs->read) (file, buf, len); + if (res > 0) + file->offset += res; + + return res; +} + +pupa_err_t +pupa_file_close (pupa_file_t file) +{ + if (file->fs->close) + (file->fs->close) (file); + + pupa_device_close (file->device); + pupa_free (file); + return pupa_errno; +} + +pupa_ssize_t +pupa_file_seek (pupa_file_t file, pupa_ssize_t offset) +{ + pupa_ssize_t old; + + if (offset < 0 || offset >= file->size) + { + pupa_error (PUPA_ERR_OUT_OF_RANGE, + "attempt to seek outside of the file"); + return -1; + } + + old = file->offset; + file->offset = offset; + return old; +} diff --git a/kern/fs.c b/kern/fs.c new file mode 100644 index 000000000..652fc55b9 --- /dev/null +++ b/kern/fs.c @@ -0,0 +1,224 @@ +/* fs.c - filesystem manager */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static pupa_fs_t pupa_fs_list; + +void +pupa_fs_register (pupa_fs_t fs) +{ + fs->next = pupa_fs_list; + pupa_fs_list = fs; +} + +void +pupa_fs_unregister (pupa_fs_t fs) +{ + pupa_fs_t *p, q; + + for (p = &pupa_fs_list, q = *p; q; p = &(q->next), q = q->next) + if (q == fs) + { + *p = q->next; + break; + } +} + +void +pupa_fs_iterate (int (*hook) (const pupa_fs_t fs)) +{ + pupa_fs_t p; + + for (p = pupa_fs_list; p; p = p->next) + if (hook (p)) + break; +} + +pupa_fs_t +pupa_fs_probe (pupa_device_t device) +{ + pupa_fs_t p; + auto int dummy_func (const char *filename, int dir); + + int dummy_func (const char *filename __attribute__ ((unused)), + int dir __attribute__ ((unused))) + { + return 1; + } + + if (device->disk) + { + for (p = pupa_fs_list; p; p = p->next) + { + (p->dir) (device, "/", dummy_func); + if (pupa_errno == PUPA_ERR_NONE) + return p; + + if (pupa_errno != PUPA_ERR_BAD_FS) + return 0; + + pupa_errno = PUPA_ERR_NONE; + } + } + else if (device->net->fs) + return device->net->fs; + + pupa_error (PUPA_ERR_UNKNOWN_FS, "unknown filesystem"); + return 0; +} + + + +/* Block list support routines. */ + +struct pupa_fs_block +{ + unsigned long offset; + unsigned long length; +}; + +static pupa_err_t +pupa_fs_blocklist_open (pupa_file_t file, const char *name) +{ + char *p = (char *) name; + unsigned num = 0; + unsigned i; + pupa_disk_t disk = file->device->disk; + struct pupa_fs_block *blocks; + + /* First, count the number of blocks. */ + do + { + num++; + p = pupa_strchr (p, ','); + } + while (p); + + /* Allocate a block list. */ + blocks = pupa_malloc (sizeof (struct pupa_fs_block) * (num + 1)); + if (! blocks) + return 0; + + file->size = 0; + p = (char *) name; + for (i = 0; i < num; i++) + { + if (*p != '+') + { + blocks[i].offset = pupa_strtoul (p, &p, 0); + if (pupa_errno != PUPA_ERR_NONE || *p != '+') + { + pupa_error (PUPA_ERR_BAD_FILENAME, + "invalid file name `%s'", name); + goto fail; + } + } + else + blocks[i].offset = 0; + + p++; + blocks[i].length = pupa_strtoul (p, &p, 0); + if (pupa_errno != PUPA_ERR_NONE + || blocks[i].length == 0 + || (*p && *p != ',' && ! pupa_isspace (*p))) + { + pupa_error (PUPA_ERR_BAD_FILENAME, + "invalid file name `%s'", name); + goto fail; + } + + if (disk->total_sectors < blocks[i].offset + blocks[i].length) + { + pupa_error (PUPA_ERR_BAD_FILENAME, "beyond the total sectors"); + goto fail; + } + + file->size += (blocks[i].length << PUPA_DISK_SECTOR_BITS); + p++; + } + + blocks[i].length = 0; + file->data = blocks; + + return PUPA_ERR_NONE; + + fail: + pupa_free (blocks); + return pupa_errno; +} + +static pupa_ssize_t +pupa_fs_blocklist_read (pupa_file_t file, char *buf, pupa_ssize_t len) +{ + struct pupa_fs_block *p; + unsigned long sector; + unsigned long offset; + pupa_ssize_t ret = 0; + + if (len > file->size - file->offset) + len = file->size - file->offset; + + sector = (file->offset >> PUPA_DISK_SECTOR_BITS); + offset = (file->offset & (PUPA_DISK_SECTOR_SIZE - 1)); + for (p = file->data; p->length && len > 0; p++) + { + if (sector < p->length) + { + pupa_ssize_t size; + + size = len; + if (((size + offset + PUPA_DISK_SECTOR_SIZE - 1) + >> PUPA_DISK_SECTOR_BITS) > p->length - sector) + size = ((p->length - sector) << PUPA_DISK_SECTOR_BITS) - offset; + + if (pupa_disk_read (file->device->disk, p->offset + sector, offset, + size, buf) != PUPA_ERR_NONE) + return -1; + + ret += size; + len -= size; + sector -= ((size + offset) >> PUPA_DISK_SECTOR_BITS); + offset = ((size + offset) & (PUPA_DISK_SECTOR_SIZE - 1)); + } + else + sector -= p->length; + } + + return ret; +} + +struct pupa_fs pupa_fs_blocklist = + { + .name = "blocklist", + .dir = 0, + .open = pupa_fs_blocklist_open, + .read = pupa_fs_blocklist_read, + .close = 0, + .next = 0 + }; diff --git a/kern/i386/dl.c b/kern/i386/dl.c new file mode 100644 index 000000000..bdd6dd962 --- /dev/null +++ b/kern/i386/dl.c @@ -0,0 +1,126 @@ +/* dl-386.c - arch-dependent part of loadable module support */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +/* Check if EHDR is a valid ELF header. */ +int +pupa_arch_dl_check_header (void *ehdr, unsigned size) +{ + Elf32_Ehdr *e = ehdr; + + /* Check the header size. */ + if (size < sizeof (Elf32_Ehdr)) + return 0; + + /* Check the magic numbers. */ + if (e->e_ident[EI_MAG0] != ELFMAG0 + || e->e_ident[EI_MAG1] != ELFMAG1 + || e->e_ident[EI_MAG2] != ELFMAG2 + || e->e_ident[EI_MAG3] != ELFMAG3 + || e->e_version != EV_CURRENT + || e->e_ident[EI_CLASS] != ELFCLASS32 + || e->e_ident[EI_DATA] != ELFDATA2LSB + || e->e_machine != EM_386 + || e->e_type != ET_REL) + return 0; + + /* Make sure that every section is within the core. */ + if (size < e->e_shoff + e->e_shentsize * e->e_shnum) + return 0; + + return 1; +} + +/* Relocate symbols. */ +pupa_err_t +pupa_arch_dl_relocate_symbols (pupa_dl_t mod, void *ehdr) +{ + Elf32_Ehdr *e = ehdr; + Elf32_Shdr *s; + Elf32_Sym *symtab; + Elf32_Word entsize; + unsigned i; + + /* Find a symbol table. */ + for (i = 0, s = (Elf32_Shdr *) ((char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf32_Shdr *) ((char *) s + e->e_shentsize)) + if (s->sh_type == SHT_SYMTAB) + break; + + if (i == e->e_shnum) + return pupa_error (PUPA_ERR_BAD_MODULE, "no symtab found"); + + symtab = (Elf32_Sym *) ((char *) e + s->sh_offset); + entsize = s->sh_entsize; + + for (i = 0, s = (Elf32_Shdr *) ((char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf32_Shdr *) ((char *) s + e->e_shentsize)) + if (s->sh_type == SHT_REL) + { + pupa_dl_segment_t seg; + + /* Find the target segment. */ + for (seg = mod->segment; seg; seg = seg->next) + if (seg->section == s->sh_info) + break; + + if (seg) + { + Elf32_Rel *rel, *max; + + for (rel = (Elf32_Rel *) ((char *) e + s->sh_offset), + max = rel + s->sh_size / s->sh_entsize; + rel < max; + rel++) + { + Elf32_Word *addr; + Elf32_Sym *sym; + + if (seg->size < rel->r_offset) + return pupa_error (PUPA_ERR_BAD_MODULE, + "reloc offset is out of the segment"); + + addr = (Elf32_Word *) ((char *) seg->addr + rel->r_offset); + sym = (Elf32_Sym *) ((char *) symtab + + entsize * ELF32_R_SYM (rel->r_info)); + + switch (ELF32_R_TYPE (rel->r_info)) + { + case R_386_32: + *addr += sym->st_value; + break; + + case R_386_PC32: + *addr += (sym->st_value - (Elf32_Word) seg->addr + - rel->r_offset); + break; + } + } + } + } + + return PUPA_ERR_NONE; +} diff --git a/kern/i386/pc/init.c b/kern/i386/pc/init.c new file mode 100644 index 000000000..589696e69 --- /dev/null +++ b/kern/i386/pc/init.c @@ -0,0 +1,114 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +void +pupa_machine_init (void) +{ + pupa_uint32_t cont; + struct pupa_machine_mmap_entry entry; + pupa_size_t lower_mem = (pupa_get_memsize (0) << 10); + pupa_addr_t end_addr = pupa_get_end_addr (); + + /* Initialize the console as early as possible. */ + pupa_console_init (); + + /* Sanity check. */ + if (lower_mem < PUPA_MEMORY_MACHINE_RESERVED_END) + pupa_fatal ("too small memory"); + + /* Turn on Gate A20 to access >1MB. */ + pupa_gate_a20 (1); + + /* Add the lower memory into free memory. */ + if (lower_mem >= PUPA_MEMORY_MACHINE_RESERVED_END) + pupa_mm_init_region ((void *) PUPA_MEMORY_MACHINE_RESERVED_END, + lower_mem - PUPA_MEMORY_MACHINE_RESERVED_END); + + pupa_mm_init_region ((void *) end_addr, + PUPA_MEMORY_MACHINE_RESERVED_START - end_addr); + + /* Check if pupa_get_mmap_entry works. */ + cont = pupa_get_mmap_entry (&entry, 0); + + if (entry.size) + do + { + /* Avoid the lower memory. */ + if (entry.addr < 0x100000) + { + if (entry.len <= 0x100000 - entry.addr) + goto next; + + entry.len -= 0x100000 - entry.addr; + entry.addr = 0x100000; + } + + /* Ignore >4GB. */ + if (entry.addr <= 0xFFFFFFFF && entry.type == 1) + { + pupa_addr_t addr; + pupa_size_t len; + + addr = (pupa_addr_t) entry.addr; + len = ((addr + entry.len > 0xFFFFFFFF) + ? 0xFFFFFFFF - addr + : (pupa_size_t) entry.len); + pupa_mm_init_region ((void *) addr, len); + } + + next: + if (! cont) + break; + + cont = pupa_get_mmap_entry (&entry, cont); + } + while (entry.size); + else + { + pupa_uint32_t eisa_mmap = pupa_get_eisa_mmap (); + + if (eisa_mmap) + { + if ((eisa_mmap & 0xFFFF) == 0x3C00) + pupa_mm_init_region ((void *) 0x100000, + (eisa_mmap << 16) + 0x100000 * 15); + else + { + pupa_mm_init_region ((void *) 0x100000, + (eisa_mmap & 0xFFFF) << 10); + pupa_mm_init_region ((void *) 0x1000000, eisa_mmap << 16); + } + } + else + pupa_mm_init_region ((void *) 0x100000, + (pupa_size_t) pupa_get_memsize (1) << 10); + } + + /* The memory system was initialized, thus register built-in devices. */ + pupa_biosdisk_init (); +} diff --git a/kern/i386/pc/startup.S b/kern/i386/pc/startup.S new file mode 100644 index 000000000..ecc97f3f7 --- /dev/null +++ b/kern/i386/pc/startup.S @@ -0,0 +1,1377 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc. + * Copyright (C) 2002 Yoshinori K. Okuji + * + * 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. + */ + + +/* + * Note: These functions defined in this file may be called from C. + * Be careful of that you must not modify some registers. Quote + * from gcc-2.95.2/gcc/config/i386/i386.h: + + 1 for registers not available across function calls. + These must include the FIXED_REGISTERS and also any + registers that can be used without being saved. + The latter must include the registers where values are returned + and the register where structure-value addresses are passed. + Aside from that, you can include as many other registers as you like. + + ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg +{ 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } + */ + +#include +#include +#include +#include +#include +#include + +#define ABS(x) ((x) - EXT_C(start) + PUPA_BOOT_MACHINE_KERNEL_ADDR + 0x200) + + .file "startup.S" + + .text + + /* Tell GAS to generate 16-bit instructions so that this code works + in real mode. */ + .code16 + + .globl start, _start +start: +_start: + /* + * Guarantee that "main" is loaded at 0x0:0x8200. + */ + ljmp $0, $ABS(codestart) + + /* + * Compatibility version number + * + * These MUST be at byte offset 6 and 7 of the executable + * DO NOT MOVE !!! + */ + . = EXT_C(start) + 0x6 + .byte PUPA_BOOT_VERSION_MAJOR, PUPA_BOOT_VERSION_MINOR + + /* + * This is a special data area 8 bytes from the beginning. + */ + + . = EXT_C(start) + 0x8 + +VARIABLE(pupa_total_module_size) + .long 0 +VARIABLE(pupa_kernel_image_size) + .long 0 +VARIABLE(install_partition) + .long 0xFFFFFF +VARIABLE(version_string) + .string PACKAGE_VERSION +VARIABLE(config_file) + .string "/boot/pupa/puparc" + + /* + * Leave some breathing room for the config file name. + */ + + . = EXT_C(start) + 0x70 + +/* the real mode code continues... */ +codestart: + cli /* we're not safe here! */ + + /* set up %ds, %ss, and %es */ + xorw %ax, %ax + movw %ax, %ds + movw %ax, %ss + movw %ax, %es + + /* set up the real mode/BIOS stack */ + movl $PUPA_MEMORY_MACHINE_REAL_STACK, %ebp + movl %ebp, %esp + + sti /* we're safe again */ + + /* save boot drive reference */ + ADDR32 movb %dl, EXT_C(pupa_boot_drive) + + /* reset disk system (%ah = 0) */ + int $0x13 + + /* transition to protected mode */ + DATA32 call real_to_prot + + /* The ".code32" directive takes GAS out of 16-bit mode. */ + .code32 + + /* copy modules before cleaning out the bss */ + movl EXT_C(pupa_total_module_size), %ecx + movl EXT_C(pupa_kernel_image_size), %esi + addl %ecx, %esi + addl $START_SYMBOL, %esi + decl %esi + movl $END_SYMBOL, %edi + addl %ecx, %edi + decl %edi + std + rep + movsb + + /* clean out the bss */ + movl $BSS_START_SYMBOL, %edi + + /* compute the bss length */ + movl $END_SYMBOL, %ecx + subl %edi, %ecx + + /* clean out */ + cld + rep + stosb + + /* + * Call the start of main body of C code. + */ + call EXT_C(pupa_main) + + +/* + * This call is special... it never returns... in fact it should simply + * hang at this point! + */ + +FUNCTION(pupa_stop) + call prot_to_real + + /* + * This next part is sort of evil. It takes advantage of the + * byte ordering on the x86 to work in either 16-bit or 32-bit + * mode, so think about it before changing it. + */ + +FUNCTION(pupa_hard_stop) + hlt + jmp EXT_C(pupa_hard_stop) + + +/* + * pupa_stop_floppy() + * + * Stop the floppy drive from spinning, so that other software is + * jumped to with a known state. + */ +FUNCTION(pupa_stop_floppy) + movw $0x3F2, %dx + xorb %al, %al + outb %al, %dx + ret + +/* + * pupa_reboot() + * + * Reboot the system. At the moment, rely on BIOS. + */ +FUNCTION(pupa_reboot) + call prot_to_real + .code16 + /* cold boot */ + movw $0x0472, %di + movw %ax, (%di) + ljmp $0xFFFF, $0x0000 + .code32 + +/* + * pupa_halt(int no_apm) + * + * Halt the system, using APM if possible. If NO_APM is true, don't use + * APM even if it is available. + */ +FUNCTION(pupa_halt) + /* get the argument */ + movl 4(%esp), %eax + + /* see if zero */ + testl %eax, %eax + jnz EXT_C(pupa_stop) + + call prot_to_real + .code16 + + /* detect APM */ + movw $0x5300, %ax + xorw %bx, %bx + int $0x15 + jc EXT_C(pupa_hard_stop) + /* don't check %bx for buggy BIOSes... */ + + /* disconnect APM first */ + movw $0x5304, %ax + xorw %bx, %bx + int $0x15 + + /* connect APM */ + movw $0x5301, %ax + xorw %bx, %bx + int $0x15 + jc EXT_C(pupa_hard_stop) + + /* set APM protocol level - 1.1 or bust. (this covers APM 1.2 also) */ + movw $0x530E, %ax + xorw %bx, %bx + movw $0x0101, %cx + int $0x15 + jc EXT_C(pupa_hard_stop) + + /* set the power state to off */ + movw $0x5307, %ax + movw $1, %bx + movw $3, %cx + int $0x15 + + /* shouldn't reach here */ + jmp EXT_C(pupa_hard_stop) + .code32 + + +/* + * void pupa_chainloader_real_boot (int drive, void *part_addr) + * + * This starts another boot loader. + */ + +FUNCTION(pupa_chainloader_real_boot) + /* no need to save anything, just use %esp */ + + /* ESI must point to a partition table entry */ + movl 8(%esp), %esi + + /* set up to pass boot drive */ + movl 4(%esp), %edx + + /* Turn off Gate A20 */ + pushl $0 + call EXT_C(pupa_gate_a20) + + call prot_to_real + .code16 + ljmp $0, $PUPA_MEMORY_MACHINE_BOOT_LOADER_ADDR + .code32 + + +/* + * These next two routines, "real_to_prot" and "prot_to_real" are structured + * in a very specific way. Be very careful when changing them. + * + * NOTE: Use of either one messes up %eax and %ebp. + */ + +real_to_prot: + .code16 + cli + + /* load the GDT register */ + DATA32 ADDR32 lgdt gdtdesc + + /* turn on protected mode */ + movl %cr0, %eax + orl $PUPA_MEMORY_MACHINE_CR0_PE_ON, %eax + movl %eax, %cr0 + + /* jump to relocation, flush prefetch queue, and reload %cs */ + DATA32 ljmp $PUPA_MEMORY_MACHINE_PROT_MODE_CSEG, $protcseg + + .code32 +protcseg: + /* reload other segment registers */ + movw $PUPA_MEMORY_MACHINE_PROT_MODE_DSEG, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + movw %ax, %ss + + /* put the return address in a known safe location */ + movl (%esp), %eax + movl %eax, PUPA_MEMORY_MACHINE_REAL_STACK + + /* get protected mode stack */ + movl protstack, %eax + movl %eax, %esp + movl %eax, %ebp + + /* get return address onto the right stack */ + movl PUPA_MEMORY_MACHINE_REAL_STACK, %eax + movl %eax, (%esp) + + /* zero %eax */ + xorl %eax, %eax + + /* return on the old (or initialized) stack! */ + ret + + +prot_to_real: + /* just in case, set GDT */ + lgdt gdtdesc + + /* save the protected mode stack */ + movl %esp, %eax + movl %eax, protstack + + /* get the return address */ + movl (%esp), %eax + movl %eax, PUPA_MEMORY_MACHINE_REAL_STACK + + /* set up new stack */ + movl $PUPA_MEMORY_MACHINE_REAL_STACK, %eax + movl %eax, %esp + movl %eax, %ebp + + /* set up segment limits */ + movw $PUPA_MEMORY_MACHINE_PSEUDO_REAL_DSEG, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + movw %ax, %ss + + /* this might be an extra step */ + /* jump to a 16 bit segment */ + ljmp $PUPA_MEMORY_MACHINE_PSEUDO_REAL_CSEG, $tmpcseg + +tmpcseg: + .code16 + + /* clear the PE bit of CR0 */ + movl %cr0, %eax + andl $(~PUPA_MEMORY_MACHINE_CR0_PE_ON), %eax + movl %eax, %cr0 + + /* flush prefetch queue, reload %cs */ + DATA32 ljmp $0, $realcseg + +realcseg: + /* we are in real mode now + * set up the real mode segment registers : DS, SS, ES + */ + /* zero %eax */ + xorl %eax, %eax + + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + movw %ax, %ss + + /* restore interrupts */ + sti + + /* return on new stack! */ + DATA32 ret + + .code32 + + +/* + * int pupa_biosdisk_rw_int13_extensions (int ah, int drive, void *dap) + * + * Call IBM/MS INT13 Extensions (int 13 %ah=AH) for DRIVE. DAP + * is passed for disk address packet. If an error occurs, return + * non-zero, otherwise zero. + */ + +FUNCTION(pupa_biosdisk_rw_int13_extensions) + pushl %ebp + movl %esp, %ebp + + pushl %esi + + /* compute the address of disk_address_packet */ + movl 0x10(%ebp), %eax + movw %ax, %si + xorw %ax, %ax + shrl $4, %eax + movw %ax, %cx /* save the segment to cx */ + + /* drive */ + movb 0xc(%ebp), %dl + /* ah */ + movb 0x8(%ebp), %dh + /* enter real mode */ + call prot_to_real + + .code16 + movb %dh, %ah + movw %cx, %ds + int $0x13 /* do the operation */ + movb %ah, %dl /* save return value */ + /* clear the data segment */ + xorw %ax, %ax + movw %ax, %ds + /* back to protected mode */ + DATA32 call real_to_prot + .code32 + + movb %dl, %al /* return value in %eax */ + + popl %esi + popl %ebp + + ret + +/* + * int pupa_biosdisk_rw_standard (int ah, int drive, int coff, int hoff, + * int soff, int nsec, int segment) + * + * Call standard and old INT13 (int 13 %ah=AH) for DRIVE. Read/write + * NSEC sectors from COFF/HOFF/SOFF into SEGMENT. If an error occurs, + * return non-zero, otherwise zero. + */ + +FUNCTION(pupa_biosdisk_rw_standard) + pushl %ebp + movl %esp, %ebp + + pushl %ebx + pushl %edi + pushl %esi + + /* set up CHS information */ + movl 0x10(%ebp), %eax + movb %al, %ch + movb 0x18(%ebp), %al + shlb $2, %al + shrw $2, %ax + movb %al, %cl + movb 0x14(%ebp), %dh + /* drive */ + movb 0xc(%ebp), %dl + /* segment */ + movw 0x20(%ebp), %bx + /* save nsec and ah to %di */ + movb 0x8(%ebp), %ah + movb 0x1c(%ebp), %al + movw %ax, %di + /* enter real mode */ + call prot_to_real + + .code16 + movw %bx, %es + xorw %bx, %bx + movw $3, %si /* attempt at least three times */ + +1: + movw %di, %ax + int $0x13 /* do the operation */ + jnc 2f /* check if successful */ + + movb %ah, %bl /* save return value */ + /* if fail, reset the disk system */ + xorw %ax, %ax + int $0x13 + + decw %si + cmpw $0, %si + je 2f + xorb %bl, %bl + jmp 1b /* retry */ +2: + /* back to protected mode */ + DATA32 call real_to_prot + .code32 + + movb %bl, %al /* return value in %eax */ + + popl %esi + popl %edi + popl %ebx + popl %ebp + + ret + + +/* + * int pupa_biosdisk_check_int13_extensions (int drive) + * + * Check if LBA is supported for DRIVE. If it is supported, then return + * the major version of extensions, otherwise zero. + */ + +FUNCTION(pupa_biosdisk_check_int13_extensions) + pushl %ebp + movl %esp, %ebp + + pushl %ebx + + /* drive */ + movb 0x8(%ebp), %dl + /* enter real mode */ + call prot_to_real + + .code16 + movb $0x41, %ah + movw $0x55aa, %bx + int $0x13 /* do the operation */ + + /* check the result */ + jc 1f + cmpw $0xaa55, %bx + jne 1f + + movb %ah, %bl /* save the major version into %bl */ + + /* check if AH=0x42 is supported */ + andw $1, %cx + jnz 2f + +1: + xorb %bl, %bl +2: + /* back to protected mode */ + DATA32 call real_to_prot + .code32 + + movb %bl, %al /* return value in %eax */ + + popl %ebx + popl %ebp + + ret + + +/* + * int pupa_biosdisk_get_diskinfo_int13_extensions (int drive, void *drp) + * + * Return the geometry of DRIVE in a drive parameters, DRP. If an error + * occurs, then return non-zero, otherwise zero. + */ + +FUNCTION(pupa_biosdisk_get_diskinfo_int13_extensions) + pushl %ebp + movl %esp, %ebp + + pushl %ebx + pushl %esi + + /* compute the address of drive parameters */ + movl 0xc(%ebp), %eax + movw %ax, %si + xorw %ax, %ax + shrl $4, %eax + movw %ax, %bx /* save the segment into %bx */ + /* drive */ + movb 0x8(%ebp), %dl + /* enter real mode */ + call prot_to_real + + .code16 + movb $0x48, %ah + movw %bx, %ds + int $0x13 /* do the operation */ + movb %ah, %bl /* save return value in %bl */ + /* clear the data segment */ + xorw %ax, %ax + movw %ax, %ds + /* back to protected mode */ + DATA32 call real_to_prot + .code32 + + movb %bl, %al /* return value in %eax */ + + popl %esi + popl %ebx + popl %ebp + + ret + + +/* + * int pupa_biosdisk_get_diskinfo_standard (int drive, + * unsigned long *cylinders, + * unsigned long *heads, + * unsigned long *sectors) + * + * Return the geometry of DRIVE in CYLINDERS, HEADS and SECTORS. If an + * error occurs, then return non-zero, otherwise zero. + */ + +FUNCTION(pupa_biosdisk_get_diskinfo_standard) + pushl %ebp + movl %esp, %ebp + + pushl %ebx + pushl %edi + + /* drive */ + movb 0x8(%ebp), %dl + /* enter real mode */ + call prot_to_real + + .code16 + movb $0x8, %ah + int $0x13 /* do the operation */ + /* check if successful */ + testb %ah, %ah + jnz 1f + /* bogus BIOSes may not return an error number */ + testb $0x3f, %cl /* 0 sectors means no disk */ + jnz 1f /* if non-zero, then succeed */ + /* XXX 0x60 is one of the unused error numbers */ + movb $0x60, %ah +1: + movb %ah, %bl /* save return value in %bl */ + /* back to protected mode */ + DATA32 call real_to_prot + .code32 + + /* restore %ebp */ + leal 0x8(%esp), %ebp + + /* heads */ + movb %dh, %al + incl %eax /* the number of heads is counted from zero */ + movl 0x10(%ebp), %edi + movl %eax, (%edi) + + /* sectors */ + xorl %eax, %eax + movb %cl, %al + andb $0x3f, %al + movl 0x14(%ebp), %edi + movl %eax, (%edi) + + /* cylinders */ + shrb $6, %cl + movb %cl, %ah + movb %ch, %al + incl %eax /* the number of cylinders is + counted from zero */ + movl 0xc(%ebp), %edi + movl %eax, (%edi) + + xorl %eax, %eax + movb %bl, %al /* return value in %eax */ + + popl %edi + popl %ebx + popl %ebp + + ret + + +/* + * int pupa_biosdisk_get_num_floppies (void) + */ +FUNCTION(pupa_biosdisk_get_num_floppies) + pushl %ebp + + xorl %edx, %edx + call prot_to_real + + .code16 + /* reset the disk system first */ + int $0x13 +1: + stc + + /* call GET DISK TYPE */ + movb $0x15, %ah + int $0x13 + + jc 2f + + /* check if this drive exists */ + testb $0x3, %ah + jz 2f + + incb %dl + cmpb $2, %dl + jne 1b +2: + DATA32 call real_to_prot + .code32 + + movl %edx, %eax + popl %ebp + ret + + +/* + * + * pupa_get_memsize(i) : return the memory size in KB. i == 0 for conventional + * memory, i == 1 for extended memory + * BIOS call "INT 12H" to get conventional memory size + * BIOS call "INT 15H, AH=88H" to get extended memory size + * Both have the return value in AX. + * + */ + +FUNCTION(pupa_get_memsize) + pushl %ebp + pushl %ebx + + movl 0xc(%esp), %ebx + + call prot_to_real /* enter real mode */ + .code16 + + testl %ebx, %ebx + jnz xext + + int $0x12 + jmp xdone + +xext: + movb $0x88, %ah + int $0x15 + +xdone: + movw %ax, %bx + + DATA32 call real_to_prot + .code32 + + movw %bx, %ax + popl %ebx + popl %ebp + ret + + +/* + * + * pupa_get_eisa_mmap() : return packed EISA memory map, lower 16 bits is + * memory between 1M and 16M in 1K parts, upper 16 bits is + * memory above 16M in 64K parts. If error, return zero. + * BIOS call "INT 15H, AH=E801H" to get EISA memory map, + * AX = memory between 1M and 16M in 1K parts. + * BX = memory above 16M in 64K parts. + * + */ + +FUNCTION(pupa_get_eisa_mmap) + pushl %ebp + pushl %ebx + + call prot_to_real /* enter real mode */ + .code16 + + movw $0xe801, %ax + int $0x15 + + shll $16, %ebx + movw %ax, %bx + + DATA32 call real_to_prot + .code32 + + cmpb $0x86, %bh + je xnoteisa + + movl %ebx, %eax + +xnoteisa: + popl %ebx + popl %ebp + ret + +/* + * + * pupa_get_mmap_entry(addr, cont) : address and old continuation value (zero to + * start), for the Query System Address Map BIOS call. + * + * Sets the first 4-byte int value of "addr" to the size returned by + * the call. If the call fails, sets it to zero. + * + * Returns: new (non-zero) continuation value, 0 if done. + */ + +FUNCTION(pupa_get_mmap_entry) + push %ebp + push %ebx + push %edi + push %esi + + /* place address (+4) in ES:DI */ + movl 0x14(%esp), %eax + addl $4, %eax + movl %eax, %edi + andl $0xf, %edi + shrl $4, %eax + movl %eax, %esi + + /* set continuation value */ + movl 0x18(%esp), %ebx + + /* set default maximum buffer size */ + movl $0x14, %ecx + + /* set EDX to 'SMAP' */ + movl $0x534d4150, %edx + + call prot_to_real /* enter real mode */ + .code16 + + movw %si, %es + movl $0xe820, %eax + int $0x15 + + DATA32 jc xnosmap + + cmpl $0x534d4150, %eax + jne xnosmap + + cmpl $0x14, %ecx + jl xnosmap + + cmpl $0x400, %ecx + jg xnosmap + + jmp xsmap + +xnosmap: + xorl %ecx, %ecx + +xsmap: + DATA32 call real_to_prot + .code32 + + /* write length of buffer (zero if error) into "addr" */ + movl 0x14(%esp), %eax + movl %ecx, (%eax) + + /* set return value to continuation */ + movl %ebx, %eax + + pop %esi + pop %edi + pop %ebx + pop %ebp + ret + + +/* + * pupa_gate_a20(int on) + * + * Gate address-line 20 for high memory. + * + * This routine is probably overconservative in what it does, but so what? + * + * It also eats any keystrokes in the keyboard buffer. :-( + */ + +FUNCTION(pupa_gate_a20) + pushl %eax + + call gloop1 + + movb $0xd1, %al + outb $0x64 + +gloopint1: + inb $0x64 + andb $0x02, %al + jnz gloopint1 + + movb $0xdd, %al + cmpb $0, 0x8(%esp) + jz gdoit + + orb $0x02, %al +gdoit: + outb $0x60 + + call gloop1 + + /* output a dummy command (USB keyboard hack) */ + movb $0xff, %al + outb $0x64 + call gloop1 + + popl %eax + ret + +gloop1: + inb $0x64 + andb $0x02, %al + jnz gloop1 + +gloop2: + inb $0x64 + andb $0x01, %al + jz gloop2ret + inb $0x60 + jmp gloop2 + +gloop2ret: + ret + + +/* + * void pupa_console_putchar (int c) + * + * Put the character C on the console. Because GRUB wants to write a + * character with an attribute, this implementation is a bit tricky. + * If C is a control character (CR, LF, BEL, BS), use INT 10, AH = 0Eh + * (TELETYPE OUTPUT). Otherwise, save the original position, put a space, + * save the current position, restore the original position, write the + * character and the attribute, and restore the current position. + * + * The reason why this is so complicated is that there is no easy way to + * get the height of the screen, and the TELETYPE OUPUT BIOS call doesn't + * support setting a background attribute. + */ +FUNCTION(pupa_console_putchar) + movl 0x4(%esp), %edx + pusha + movb EXT_C(pupa_console_cur_color), %bl + + call prot_to_real + .code16 + movb %dl, %al + xorb %bh, %bh + + /* use teletype output if control character */ + cmpb $0x7, %al + je 1f + cmpb $0x8, %al + je 1f + cmpb $0xa, %al + je 1f + cmpb $0xd, %al + je 1f + + /* save the character and the attribute on the stack */ + pushw %ax + pushw %bx + + /* get the current position */ + movb $0x3, %ah + int $0x10 + + /* check the column with the width */ + cmpb $79, %dl + jl 2f + + /* print CR and LF, if next write will exceed the width */ + movw $0x0e0d, %ax + int $0x10 + movb $0x0a, %al + int $0x10 + + /* get the current position */ + movb $0x3, %ah + int $0x10 + +2: + /* restore the character and the attribute */ + popw %bx + popw %ax + + /* write the character with the attribute */ + movb $0x9, %ah + movw $1, %cx + int $0x10 + + /* move the cursor forward */ + incb %dl + movb $0x2, %ah + int $0x10 + + jmp 3f + +1: movb $0x7, %bl + movb $0xe, %ah + int $0x10 + +3: DATA32 call real_to_prot + .code32 + + popa + ret + + +/* + * int pupa_console_getkey (void) + * BIOS call "INT 16H Function 00H" to read character from keyboard + * Call with %ah = 0x0 + * Return: %ah = keyboard scan code + * %al = ASCII character + */ + +FUNCTION(pupa_console_getkey) + pushl %ebp + + call prot_to_real + .code16 + + int $0x16 + + movw %ax, %dx /* real_to_prot uses %eax */ + + DATA32 call real_to_prot + .code32 + + movw %dx, %ax + + popl %ebp + ret + + +/* + * int pupa_console_checkkey (void) + * if there is a character pending, return it; otherwise return -1 + * BIOS call "INT 16H Function 01H" to check whether a character is pending + * Call with %ah = 0x1 + * Return: + * If key waiting to be input: + * %ah = keyboard scan code + * %al = ASCII character + * Zero flag = clear + * else + * Zero flag = set + */ +FUNCTION(pupa_console_checkkey) + pushl %ebp + xorl %edx, %edx + + call prot_to_real /* enter real mode */ + .code16 + + movb $0x1, %ah + int $0x16 + + jz notpending + + movw %ax, %dx + DATA32 jmp pending + +notpending: + decl %edx + +pending: + DATA32 call real_to_prot + .code32 + + movl %edx, %eax + + popl %ebp + ret + + +/* + * pupa_uint16_t pupa_console_getxy (void) + * BIOS call "INT 10H Function 03h" to get cursor position + * Call with %ah = 0x03 + * %bh = page + * Returns %ch = starting scan line + * %cl = ending scan line + * %dh = row (0 is top) + * %dl = column (0 is left) + */ + + +FUNCTION(pupa_console_getxy) + pushl %ebp + pushl %ebx /* save EBX */ + + call prot_to_real + .code16 + + xorb %bh, %bh /* set page to 0 */ + movb $0x3, %ah + int $0x10 /* get cursor position */ + + DATA32 call real_to_prot + .code32 + + movb %dl, %ah + movb %dh, %al + + popl %ebx + popl %ebp + ret + + +/* + * void pupa_console_gotoxy(pupa_uint8_t x, pupa_uint8_t y) + * BIOS call "INT 10H Function 02h" to set cursor position + * Call with %ah = 0x02 + * %bh = page + * %dh = row (0 is top) + * %dl = column (0 is left) + */ + + +FUNCTION(pupa_console_gotoxy) + pushl %ebp + pushl %ebx /* save EBX */ + + movb 0xc(%esp), %dl /* %dl = x */ + movb 0x10(%esp), %dh /* %dh = y */ + + call prot_to_real + .code16 + + xorb %bh, %bh /* set page to 0 */ + movb $0x2, %ah + int $0x10 /* set cursor position */ + + DATA32 call real_to_prot + .code32 + + popl %ebx + popl %ebp + ret + + +/* + * void pupa_console_cls (void) + * BIOS call "INT 10H Function 09h" to write character and attribute + * Call with %ah = 0x09 + * %al = (character) + * %bh = (page number) + * %bl = (attribute) + * %cx = (number of times) + */ + +FUNCTION(pupa_console_cls) + pushl %ebp + pushl %ebx /* save EBX */ + + call prot_to_real + .code16 + + /* move the cursor to the beginning */ + movb $0x02, %ah + xorb %bh, %bh + xorw %dx, %dx + int $0x10 + + /* write spaces to the entire screen */ + movw $0x0920, %ax + movw $0x07, %bx + movw $(80 * 25), %cx + int $0x10 + + /* move back the cursor */ + movb $0x02, %ah + int $0x10 + + DATA32 call real_to_prot + .code32 + + popl %ebx + popl %ebp + ret + + +/* + * void pupa_console_setcursor (int on) + * BIOS call "INT 10H Function 01h" to set cursor type + * Call with %ah = 0x01 + * %ch = cursor starting scanline + * %cl = cursor ending scanline + */ + +console_cursor_state: + .byte 1 +console_cursor_shape: + .word 0 + +FUNCTION(pupa_console_setcursor) + push %ebp + push %ebx + + /* check if the standard cursor shape has already been saved */ + movw console_cursor_shape, %ax + testw %ax, %ax + jne 1f + + call prot_to_real + .code16 + + movb $0x03, %ah + xorb %bh, %bh + int $0x10 + + DATA32 call real_to_prot + .code32 + + movw %cx, console_cursor_shape +1: + /* set %cx to the designated cursor shape */ + movw $0x2000, %cx + movl 0xc(%esp), %ebx + testl %ebx, %ebx + jz 2f + movw console_cursor_shape, %cx +2: + call prot_to_real + .code16 + + movb $0x1, %ah + int $0x10 + + DATA32 call real_to_prot + .code32 + + popl %ebx + popl %ebp + ret + +/* + * pupa_getrtsecs() + * if a seconds value can be read, read it and return it (BCD), + * otherwise return 0xFF + * BIOS call "INT 1AH Function 02H" to check whether a character is pending + * Call with %ah = 0x2 + * Return: + * If RT Clock can give correct values + * %ch = hour (BCD) + * %cl = minutes (BCD) + * %dh = seconds (BCD) + * %dl = daylight savings time (00h std, 01h daylight) + * Carry flag = clear + * else + * Carry flag = set + * (this indicates that the clock is updating, or + * that it isn't running) + */ +FUNCTION(pupa_getrtsecs) + push %ebp + + call prot_to_real /* enter real mode */ + .code16 + + clc + movb $0x2, %ah + int $0x1a + + DATA32 jnc gottime + movb $0xff, %dh + +gottime: + DATA32 call real_to_prot + .code32 + + movb %dh, %al + + pop %ebp + ret + + +/* + * pupa_currticks() + * return the real time in ticks, of which there are about + * 18-20 per second + */ +FUNCTION(pupa_currticks) + pushl %ebp + + call prot_to_real /* enter real mode */ + .code16 + + /* %ax is already zero */ + int $0x1a + + DATA32 call real_to_prot + .code32 + + movl %ecx, %eax + shll $16, %eax + movw %dx, %ax + + popl %ebp + ret + + +/* + * This is the area for all of the special variables. + */ + + .p2align 2 /* force 4-byte alignment */ + +protstack: + .long PUPA_MEMORY_MACHINE_PROT_STACK + +VARIABLE(pupa_boot_drive) + .long 0 + +VARIABLE(pupa_start_addr) + .long START_SYMBOL + +VARIABLE(pupa_end_addr) + .long END_SYMBOL + +VARIABLE(pupa_apm_bios_info) + .word 0 /* version */ + .word 0 /* cseg */ + .long 0 /* offset */ + .word 0 /* cseg_16 */ + .word 0 /* dseg_16 */ + .word 0 /* cseg_len */ + .word 0 /* cseg_16_len */ + .word 0 /* dseg_16_len */ + +/* + * This is the Global Descriptor Table + * + * An entry, a "Segment Descriptor", looks like this: + * + * 31 24 19 16 7 0 + * ------------------------------------------------------------ + * | | |B| |A| | | |1|0|E|W|A| | + * | BASE 31..24 |G|/|0|V| LIMIT |P|DPL| TYPE | BASE 23:16 | + * | | |D| |L| 19..16| | |1|1|C|R|A| | + * ------------------------------------------------------------ + * | | | + * | BASE 15..0 | LIMIT 15..0 | + * | | | + * ------------------------------------------------------------ + * + * Note the ordering of the data items is reversed from the above + * description. + */ + + .p2align 2 /* force 4-byte alignment */ +gdt: + .word 0, 0 + .byte 0, 0, 0, 0 + + /* code segment */ + .word 0xFFFF, 0 + .byte 0, 0x9A, 0xCF, 0 + + /* data segment */ + .word 0xFFFF, 0 + .byte 0, 0x92, 0xCF, 0 + + /* 16 bit real mode CS */ + .word 0xFFFF, 0 + .byte 0, 0x9E, 0, 0 + + /* 16 bit real mode DS */ + .word 0xFFFF, 0 + .byte 0, 0x92, 0, 0 + + +/* this is the GDT descriptor */ +gdtdesc: + .word 0x27 /* limit */ + .long gdt /* addr */ diff --git a/kern/loader.c b/kern/loader.c new file mode 100644 index 000000000..f7d8ebc89 --- /dev/null +++ b/kern/loader.c @@ -0,0 +1,67 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +static pupa_err_t (*pupa_loader_load_module_func) (int argc, char *argv[]); +static pupa_err_t (*pupa_loader_boot_func) (void); +static pupa_err_t (*pupa_loader_unload_func) (void); + +static int pupa_loader_loaded; + +void +pupa_loader_set (pupa_err_t (*load_module) (int argc, char *argv[]), + pupa_err_t (*boot) (void), + pupa_err_t (*unload) (void)) +{ + if (pupa_loader_loaded && pupa_loader_unload_func) + if (pupa_loader_unload_func () != PUPA_ERR_NONE) + return; + + pupa_loader_load_module_func = load_module; + pupa_loader_boot_func = boot; + pupa_loader_unload_func = unload; + + pupa_loader_loaded = 1; +} + +pupa_err_t +pupa_loader_load_module (int argc, char *argv[]) +{ + if (! pupa_loader_loaded) + return pupa_error (PUPA_ERR_NO_KERNEL, "no loaded kernel"); + + if (! pupa_loader_load_module_func) + return pupa_error (PUPA_ERR_BAD_OS, "module not supported"); + + return pupa_loader_load_module_func (argc, argv); +} + +pupa_err_t +pupa_loader_boot (void) +{ + if (! pupa_loader_loaded) + return pupa_error (PUPA_ERR_NO_KERNEL, "no loaded kernel"); + + return (pupa_loader_boot_func) (); +} + diff --git a/kern/main.c b/kern/main.c new file mode 100644 index 000000000..2862e52cb --- /dev/null +++ b/kern/main.c @@ -0,0 +1,86 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Return the end of the core image. */ +pupa_addr_t +pupa_get_end_addr (void) +{ + return pupa_total_module_size + pupa_end_addr; +} + +/* Load all modules in core. */ +static void +pupa_load_modules (void) +{ + struct pupa_module_header *header; + + for (header = (struct pupa_module_header *) pupa_end_addr; + header < (struct pupa_module_header *) pupa_get_end_addr (); + header = (struct pupa_module_header *) ((char *) header + header->size)) + { + if (! pupa_dl_load_core ((char *) header + header->offset, + (header->size - header->offset))) + pupa_fatal ("%s", pupa_errmsg); + } +} + +/* Add the region where modules reside into dynamic memory. */ +static void +pupa_add_unused_region (void) +{ + if (pupa_total_module_size) + pupa_mm_init_region ((void *) pupa_end_addr, pupa_total_module_size); +} + +/* The main routine. */ +void +pupa_main (void) +{ + void (*normal_func) (void); + + /* First of all, initialize the machine. */ + pupa_machine_init (); + + /* Hello. */ + pupa_setcolorstate (PUPA_TERM_COLOR_HIGHLIGHT); + pupa_printf ("Welcome to PUPA!"); + pupa_setcolorstate (PUPA_TERM_COLOR_STANDARD); + pupa_printf ("\n\n"); + + pupa_register_exported_symbols (); + pupa_load_modules (); + pupa_add_unused_region (); + + /* If the function pupa_enter_normal_mode is present, call it. */ + normal_func = pupa_dl_resolve_symbol ("pupa_enter_normal_mode"); + if (normal_func) + (*normal_func) (); + + /* If pupa_enter_normal_mode fails or doesn't exist, enter rescue mode. */ + pupa_printf ("Entering into rescue mode...\n"); + pupa_enter_rescue_mode (); +} diff --git a/kern/misc.c b/kern/misc.c new file mode 100644 index 000000000..3ddd3aada --- /dev/null +++ b/kern/misc.c @@ -0,0 +1,377 @@ +/* misc.c - definitions of misc functions */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc. + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +void * +pupa_memcpy (void *dest, const void *src, pupa_size_t n) +{ + char *d = (char *) dest; + char *s = (char *) src; + + while (n--) + *d++ = *s++; + + return dest; +} + +int +pupa_printf (const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start (ap, fmt); + ret = pupa_vprintf (fmt, ap); + va_end (ap); + + return ret; +} + +int +pupa_vprintf (const char *fmt, va_list args) +{ + return pupa_vsprintf (0, fmt, args); +} + +int +pupa_memcmp (const void *s1, const void *s2, pupa_size_t n) +{ + const char *t1 = s1; + const char *t2 = s2; + + while (n--) + { + if (*t1 != *t2) + return (int) *t1 - (int) *t2; + + t1++; + t2++; + } + + return 0; +} + +int +pupa_strcmp (const char *s1, const char *s2) +{ + while (*s1 && *s2) + { + if (*s1 != *s2) + return (int) *s1 - (int) *s2; + + s1++; + s2++; + } + + return (int) *s1 - (int) *s2; +} + +char * +pupa_strchr (const char *s, int c) +{ + while (*s) + { + if (*s == c) + return (char *) s; + s++; + } + + return 0; +} + +char * +pupa_strrchr (const char *s, int c) +{ + char *p = 0; + + while (*s) + { + if (*s == c) + p = (char *) s; + s++; + } + + return p; +} + +int +pupa_isspace (int c) +{ + return (c == '\n' || c == '\r' || c == ' ' || c == '\t'); +} + +int +pupa_isprint (int c) +{ + return (c >= ' ' && c <= '~'); +} + +int +pupa_isalpha (int c) +{ + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); +} + +int +pupa_tolower (int c) +{ + if (c >= 'A' && c <= 'Z') + return c - 'A' + 'a'; + + return c; +} + +unsigned long +pupa_strtoul (const char *str, char **end, int base) +{ + unsigned long num = 0; + int found = 0; + + /* Skip white spaces. */ + while (*str && pupa_isspace (*str)) + str++; + + /* Guess the base, if not specified. The prefix `0x' means 16, and + the prefix `0' means 8. */ + if (str[0] == '0') + { + if (str[1] == 'x') + { + if (base == 0 || base == 16) + { + base = 16; + str += 2; + } + } + else if (str[1] >= '0' && str[1] <= '7') + base = 8; + } + + if (base == 0) + base = 10; + + while (*str) + { + unsigned long digit; + + digit = pupa_tolower (*str) - '0'; + if (digit > 9) + { + digit += '0' - 'a' + 10; + if (digit >= (unsigned long) base) + break; + } + + found = 1; + + if (num > (~0UL - digit) / base) + { + pupa_error (PUPA_ERR_OUT_OF_RANGE, "overflow is detected"); + return 0; + } + + num += num * base + digit; + str++; + } + + if (! found) + { + pupa_error (PUPA_ERR_BAD_NUMBER, "unrecognized number"); + return 0; + } + + if (end) + *end = (char *) str; + + return num; +} + +char * +pupa_strdup (const char *s) +{ + pupa_size_t len; + char *p; + + len = pupa_strlen (s) + 1; + p = (char *) pupa_malloc (len); + if (! p) + return 0; + + return pupa_memcpy (p, s, len); +} + +void * +pupa_memset (void *s, int c, pupa_size_t n) +{ + unsigned char *p = (unsigned char *) s; + + while (n--) + *p++ = (unsigned char) c; + + return s; +} + +pupa_size_t +pupa_strlen (const char *s) +{ + char *p = (char *) s; + + while (*p) + p++; + + return p - s; +} + +static inline void +pupa_reverse (char *str) +{ + char *p = str + pupa_strlen (str) - 1; + + while (str < p) + { + char tmp; + + tmp = *str; + *str = *p; + *p = tmp; + str++; + p--; + } +} + +char * +pupa_itoa (char *str, int c, unsigned n) +{ + unsigned base = (c == 'x') ? 16 : 10; + char *p; + + if ((int) n < 0 && c == 'd') + { + n = (unsigned) (-((int) n)); + *str++ = '-'; + } + + p = str; + do + { + unsigned d = n % base; + *p++ = (d > 9) ? d + 'a' - 10 : d + '0'; + } + while (n /= base); + *p = 0; + + pupa_reverse (str); + return p; +} + +int +pupa_vsprintf (char *str, const char *fmt, va_list args) +{ + char c; + int count = 0; + auto void write_char (char c); + auto void write_str (const char *s); + + void write_char (char c) + { + if (str) + *str++ = c; + else + pupa_putchar (c); + + count++; + } + + void write_str (const char *s) + { + while (*s) + write_char (*s++); + } + + while ((c = *fmt++) != 0) + { + if (c != '%') + write_char (c); + else + { + char tmp[16]; + char *p; + int n; + + c = *fmt++; + + switch (c) + { + case 'p': + write_str ("0x"); + c = 'x'; + /* fall through */ + case 'x': + case 'u': + case 'd': + n = va_arg (args, int); + pupa_itoa (tmp, c, n); + write_str (tmp); + break; + + case 'c': + n = va_arg (args, int); + write_char (n); + break; + + case 's': + p = va_arg (args, char *); + if (p) + write_str (p); + else + write_str ("(null)"); + break; + + default: + write_char (c); + break; + } + } + } + + if (str) + *str = '\0'; + + return count; +} + +int +pupa_sprintf (char *str, const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start (ap, fmt); + ret = pupa_vsprintf (str, fmt, ap); + va_end (ap); + + return ret; +} diff --git a/kern/mm.c b/kern/mm.c new file mode 100644 index 000000000..9b888b62b --- /dev/null +++ b/kern/mm.c @@ -0,0 +1,352 @@ +/* mm.c - functions for memory manager */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +/* Magic words. */ +#define PUPA_MM_FREE_MAGIC 0x2d3c2808 +#define PUPA_MM_ALLOC_MAGIC 0x6db08fa4 + +typedef struct pupa_mm_header +{ + struct pupa_mm_header *next; + pupa_size_t size; + pupa_size_t magic; +#if PUPA_CPU_SIZEOF_VOID_P == 4 + char padding[4]; +#elif PUPA_CPU_SIZEOF_VOID_P == 8 + char padding[8]; +#else +# error "unknown word size" +#endif +} +*pupa_mm_header_t; + +#if PUPA_CPU_SIZEOF_VOID_P == 4 +# define PUPA_MM_ALIGN_LOG2 4 +#elif PUPA_CPU_SIZEOF_VOID_P == 8 +# define PUPA_MM_ALIGN_LOG2 8 +#endif + +#define PUPA_MM_ALIGN (1 << PUPA_MM_ALIGN_LOG2) + +typedef struct pupa_mm_region +{ + struct pupa_mm_header *first; + struct pupa_mm_region *next; + pupa_addr_t addr; + pupa_size_t size; +} +*pupa_mm_region_t; + + + +static pupa_mm_region_t base; + +/* Get a header from the pointer PTR, and set *P and *R to a pointer + to the header and a pointer to its region, respectively. PTR must + be allocated. */ +static void +get_header_from_pointer (void *ptr, pupa_mm_header_t *p, pupa_mm_region_t *r) +{ + if ((unsigned) ptr & (PUPA_MM_ALIGN - 1)) + pupa_fatal ("unaligned pointer %p", ptr); + + for (*r = base; *r; *r = (*r)->next) + if ((unsigned) ptr > (*r)->addr + && (unsigned) ptr <= (*r)->addr + (*r)->size) + break; + + if (! *r) + pupa_fatal ("out of range pointer %p", ptr); + + *p = (pupa_mm_header_t) ptr - 1; + if ((*p)->magic != PUPA_MM_ALLOC_MAGIC) + pupa_fatal ("alloc magic is broken at %p", *p); +} + +/* Initialize a region starting from ADDR and whose size is SIZE, + to use it as free space. */ +void +pupa_mm_init_region (void *addr, pupa_size_t size) +{ + pupa_mm_header_t h; + pupa_mm_region_t r, *p, q; + + /* If this region is too small, ignore it. */ + if (size < PUPA_MM_ALIGN * 2) + return; + + /* Allocate a region from the head. */ + r = (pupa_mm_region_t) (((pupa_addr_t) addr + PUPA_MM_ALIGN - 1) + & (~(PUPA_MM_ALIGN - 1))); + size -= (char *) r - (char *) addr + sizeof (*r); + + h = (pupa_mm_header_t) ((char *) r + PUPA_MM_ALIGN); + h->next = h; + h->magic = PUPA_MM_FREE_MAGIC; + h->size = (size >> PUPA_MM_ALIGN_LOG2); + + r->first = h; + r->addr = (pupa_addr_t) h; + r->size = (h->size << PUPA_MM_ALIGN_LOG2); + + /* Find where to insert this region. Put a smaller one before bigger ones, + to prevent fragmentations. */ + for (p = &base, q = *p; q; p = &(q->next), q = *p) + if (q->size > r->size) + break; + + *p = r; + r->next = q; +} + +/* Allocate the number of units N with the alignment ALIGN from the ring + buffer starting from *FIRST. ALIGN must be a power of two. Return a + non-NULL if successful, otherwise return NULL. */ +static void * +pupa_real_malloc (pupa_mm_header_t *first, pupa_size_t n, pupa_size_t align) +{ + pupa_mm_header_t p, q; + + if ((*first)->magic == PUPA_MM_ALLOC_MAGIC) + return 0; + + for (q = *first, p = q->next; ; q = p, p = p->next) + { + pupa_off_t extra; + + extra = ((pupa_addr_t) (p + 1) >> PUPA_MM_ALIGN_LOG2) % align; + if (extra) + extra = align - extra; + + if (! p) + pupa_fatal ("null in the ring"); + + if (p->magic != PUPA_MM_FREE_MAGIC) + pupa_fatal ("free magic is broken at %p", p); + + if (p->size >= n + extra) + { + if (extra == 0 && p->size == n) + { + q->next = p->next; + p->magic = PUPA_MM_ALLOC_MAGIC; + } + else if (extra == 0 || p->size == n + extra) + { + p->size -= n; + p += p->size; + p->size = n; + p->magic = PUPA_MM_ALLOC_MAGIC; + } + else + { + pupa_mm_header_t r; + + r = p + extra + n; + r->magic = PUPA_MM_FREE_MAGIC; + r->size = p->size - extra - n; + r->next = p->next; + + p->size = extra; + p->next = r; + p += extra; + p->size = n; + p->magic = PUPA_MM_ALLOC_MAGIC; + } + + *first = q; + return p + 1; + } + + if (p == *first) + break; + } + + return 0; +} + +/* Allocate SIZE bytes with the alignment ALIGN and return the pointer. */ +void * +pupa_memalign (pupa_size_t align, pupa_size_t size) +{ + pupa_mm_region_t r; + pupa_size_t n = ((size + PUPA_MM_ALIGN - 1) >> PUPA_MM_ALIGN_LOG2) + 1; + int first = 1; + + align = (align >> PUPA_MM_ALIGN_LOG2); + if (align == 0) + align = 1; + + again: + + for (r = base; r; r = r->next) + { + void *p; + + p = pupa_real_malloc (&(r->first), n, align); + if (p) + return p; + } + + /* If failed, invalidate disk caches to increase free memory. */ + if (first) + { + pupa_disk_cache_invalidate_all (); + first = 0; + goto again; + } + + pupa_error (PUPA_ERR_OUT_OF_MEMORY, "out of memory"); + return 0; +} + +/* Allocate SIZE bytes and return the pointer. */ +void * +pupa_malloc (pupa_size_t size) +{ + return pupa_memalign (0, size); +} + +/* Deallocate the pointer PTR. */ +void +pupa_free (void *ptr) +{ + pupa_mm_header_t p; + pupa_mm_region_t r; + + if (! ptr) + return; + + get_header_from_pointer (ptr, &p, &r); + + if (p == r->first) + { + p->magic = PUPA_MM_FREE_MAGIC; + p->next = p; + } + else + { + pupa_mm_header_t q; + + for (q = r->first; q >= p || q->next <= p; q = q->next) + { + if (q->magic != PUPA_MM_FREE_MAGIC) + pupa_fatal ("free magic is broken at %p", q); + + if (q >= q->next && (q < p || q->next > p)) + break; + } + + p->magic = PUPA_MM_FREE_MAGIC; + p->next = q->next; + q->next = p; + + if (p + p->size == p->next) + { + p->next->magic = 0; + p->size += p->next->size; + p->next = p->next->next; + } + + if (q + q->size == p) + { + p->magic = 0; + q->size += p->size; + q->next = p->next; + } + + r->first = q; + } +} + +/* Reallocate SIZE bytes and return the pointer. The contents will be + the same as that of PTR. */ +void * +pupa_realloc (void *ptr, pupa_size_t size) +{ + pupa_mm_header_t p; + pupa_mm_region_t r; + void *q; + pupa_size_t n; + + if (! ptr) + return pupa_malloc (size); + + if (! size) + { + pupa_free (ptr); + return 0; + } + + /* FIXME: Not optimal. */ + n = ((size + PUPA_MM_ALIGN - 1) >> PUPA_MM_ALIGN_LOG2) + 1; + get_header_from_pointer (ptr, &p, &r); + + if (p->size >= n) + return p; + + q = pupa_malloc (size); + if (! q) + return q; + + pupa_memcpy (q, ptr, size); + pupa_free (ptr); + return q; +} + +#if MM_DEBUG +void +pupa_mm_dump (unsigned lineno) +{ + pupa_mm_region_t r; + + pupa_printf ("called at line %u\n", lineno); + for (r = base; r; r = r->next) + { + pupa_mm_header_t p; + + for (p = (pupa_mm_header_t) ((r->addr + PUPA_MM_ALIGN - 1) + & (~(PUPA_MM_ALIGN - 1))); + (pupa_addr_t) p < r->addr + r->size; + p++) + { + switch (p->magic) + { + case PUPA_MM_FREE_MAGIC: + pupa_printf ("F:%p:%u:%p\n", + p, p->size << PUPA_MM_ALIGN_LOG2, p->next); + break; + case PUPA_MM_ALLOC_MAGIC: + pupa_printf ("A:%p:%u\n", p, p->size << PUPA_MM_ALIGN_LOG2); + break; + } + } + } + + pupa_printf ("\n"); +} +#endif /* MM_DEBUG */ diff --git a/kern/rescue.c b/kern/rescue.c new file mode 100644 index 000000000..29aecb8a7 --- /dev/null +++ b/kern/rescue.c @@ -0,0 +1,576 @@ +/* rescue.c - rescue mode */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PUPA_RESCUE_BUF_SIZE 256 +#define PUPA_RESCUE_MAX_ARGS 20 + +struct pupa_rescue_command +{ + const char *name; + void (*func) (int argc, char *argv[]); + const char *message; + struct pupa_rescue_command *next; +}; +typedef struct pupa_rescue_command *pupa_rescue_command_t; + +static char buf[PUPA_RESCUE_BUF_SIZE]; + +static pupa_rescue_command_t pupa_rescue_command_list; + +void +pupa_rescue_register_command (const char *name, + void (*func) (int argc, char *argv[]), + const char *message) +{ + pupa_rescue_command_t cmd; + + cmd = (pupa_rescue_command_t) pupa_malloc (sizeof (*cmd)); + if (! cmd) + return; + + cmd->name = name; + cmd->func = func; + cmd->message = message; + + cmd->next = pupa_rescue_command_list; + pupa_rescue_command_list = cmd; +} + +void +pupa_rescue_unregister_command (const char *name) +{ + pupa_rescue_command_t *p, q; + + for (p = &pupa_rescue_command_list, q = *p; q; p = &(q->next), q = q->next) + if (pupa_strcmp (name, q->name) == 0) + { + *p = q->next; + pupa_free (q); + break; + } +} + +/* Prompt to input a command and read the line. */ +static void +pupa_rescue_get_command_line (const char *prompt) +{ + int c; + int pos = 0; + + pupa_printf (prompt); + pupa_memset (buf, 0, PUPA_RESCUE_BUF_SIZE); + + while ((c = PUPA_TERM_ASCII_CHAR (pupa_getkey ())) != '\n' && c != '\r') + { + if (pupa_isprint (c)) + { + if (pos < PUPA_RESCUE_BUF_SIZE - 1) + { + buf[pos++] = c; + pupa_putchar (c); + } + } + else if (c == '\b') + { + if (pos > 0) + { + buf[--pos] = 0; + pupa_putchar (c); + pupa_putchar (' '); + pupa_putchar (c); + } + } + } + + pupa_putchar ('\n'); +} + +/* Get the next word in STR and return a next pointer. */ +static char * +next_word (char **str) +{ + char *word; + char *p = *str; + + /* Skip spaces. */ + while (*p && pupa_isspace (*p)) + p++; + + word = p; + + /* Find a space. */ + while (*p && ! pupa_isspace (*p)) + p++; + + *p = '\0'; + *str = p + 1; + + return word; +} + +/* boot */ +static void +pupa_rescue_cmd_boot (int argc __attribute__ ((unused)), + char *argv[] __attribute__ ((unused))) +{ + pupa_loader_boot (); +} + +/* cat FILE */ +static void +pupa_rescue_cmd_cat (int argc, char *argv[]) +{ + pupa_file_t file; + char buf[PUPA_DISK_SECTOR_SIZE]; + pupa_ssize_t size; + + if (argc < 1) + { + pupa_error (PUPA_ERR_BAD_ARGUMENT, "no file specified"); + return; + } + + file = pupa_file_open (argv[0]); + if (! file) + return; + + while ((size = pupa_file_read (file, buf, sizeof (buf))) > 0) + { + int i; + + for (i = 0; i < size; i++) + { + unsigned char c = buf[i]; + + if (pupa_isprint (c) || pupa_isspace (c)) + pupa_putchar (c); + else + { + pupa_setcolorstate (PUPA_TERM_COLOR_HIGHLIGHT); + pupa_printf ("<%x>", (int) c); + pupa_setcolorstate (PUPA_TERM_COLOR_STANDARD); + } + } + } + + pupa_putchar ('\n'); + pupa_file_close (file); +} + +static int +pupa_rescue_print_disks (const char *name) +{ + pupa_device_t dev; + auto int print_partition (const pupa_partition_t p); + + int print_partition (const pupa_partition_t p) + { + char *pname = pupa_partition_get_name (p); + + if (pname) + { + pupa_printf ("(%s,%s) ", name, pname); + pupa_free (pname); + } + + return 0; + } + + dev = pupa_device_open (name); + pupa_errno = PUPA_ERR_NONE; + + if (dev) + { + pupa_printf ("(%s) ", name); + + if (dev->disk && dev->disk->has_partitions) + { + pupa_partition_iterate (dev->disk, print_partition); + pupa_errno = PUPA_ERR_NONE; + } + + pupa_device_close (dev); + } + + return 0; +} + +static int +pupa_rescue_print_files (const char *filename, int dir) +{ + pupa_printf ("%s%s ", filename, dir ? "/" : ""); + + return 0; +} + +/* ls [ARG] */ +static void +pupa_rescue_cmd_ls (int argc, char *argv[]) +{ + if (argc < 1) + { + pupa_disk_dev_iterate (pupa_rescue_print_disks); + pupa_putchar ('\n'); + } + else + { + char *device_name; + pupa_device_t dev; + pupa_fs_t fs; + char *path; + + device_name = pupa_file_get_device_name (argv[0]); + dev = pupa_device_open (device_name); + if (! dev) + goto fail; + + fs = pupa_fs_probe (dev); + path = pupa_strchr (argv[0], '/'); + + if (! path && ! device_name) + { + pupa_error (PUPA_ERR_BAD_ARGUMENT, "invalid argument"); + goto fail; + } + + if (! path) + { + if (pupa_errno == PUPA_ERR_UNKNOWN_FS) + pupa_errno = PUPA_ERR_NONE; + + pupa_printf ("(%s): Filesystem is %s.\n", + device_name, fs ? fs->name : "unknown"); + } + else if (fs) + { + (fs->dir) (dev, path, pupa_rescue_print_files); + pupa_putchar ('\n'); + } + + fail: + if (dev) + pupa_device_close (dev); + + pupa_free (device_name); + } +} + +/* help */ +static void +pupa_rescue_cmd_help (int argc __attribute__ ((unused)), + char *argv[] __attribute__ ((unused))) +{ + pupa_rescue_command_t p, q; + + /* Sort the commands. This is not a good algorithm, but this is enough, + because rescue mode has a small number of commands. */ + for (p = pupa_rescue_command_list; p; p = p->next) + for (q = p->next; q; q = q->next) + if (pupa_strcmp (p->name, q->name) > 0) + { + struct pupa_rescue_command tmp; + + tmp.name = p->name; + tmp.func = p->func; + tmp.message = p->message; + + p->name = q->name; + p->func = q->func; + p->message = q->message; + + q->name = tmp.name; + q->func = tmp.func; + q->message = tmp.message; + } + + /* Print them. */ + for (p = pupa_rescue_command_list; p; p = p->next) + pupa_printf ("%s\t%s\n", p->name, p->message); +} + +#if 0 +static void +pupa_rescue_cmd_info (void) +{ + extern void pupa_disk_cache_get_performance (unsigned long *, + unsigned long *); + unsigned long hits, misses; + + pupa_disk_cache_get_performance (&hits, &misses); + pupa_printf ("Disk cache: hits = %u, misses = %u ", hits, misses); + if (hits + misses) + { + unsigned long ratio = hits * 10000 / (hits + misses); + pupa_printf ("(%u.%u%%)\n", ratio / 100, ratio % 100); + } + else + pupa_printf ("(N/A)\n"); +} +#endif + +/* (module|initrd) FILE [ARGS] */ +static void +pupa_rescue_cmd_module (int argc, char *argv[]) +{ + pupa_loader_load_module (argc, argv); +} + +/* root [DEVICE] */ +static void +pupa_rescue_cmd_root (int argc, char *argv[]) +{ + pupa_device_t dev; + pupa_fs_t fs; + + if (argc > 0) + { + char *device_name = pupa_file_get_device_name (argv[0]); + if (! device_name) + return; + + pupa_device_set_root (device_name); + pupa_free (device_name); + } + + dev = pupa_device_open (0); + if (! dev) + return; + + fs = pupa_fs_probe (dev); + if (pupa_errno == PUPA_ERR_UNKNOWN_FS) + pupa_errno = PUPA_ERR_NONE; + + pupa_printf ("(%s): Filesystem is %s.\n", + pupa_device_get_root (), fs ? fs->name : "unknown"); + + pupa_device_close (dev); +} + +#if 0 +static void +pupa_rescue_cmd_testload (int argc, char *argv[]) +{ + pupa_file_t file; + char *buf; + pupa_ssize_t size; + pupa_ssize_t pos; + auto void read_func (unsigned long sector, unsigned offset, unsigned len); + + void read_func (unsigned long sector __attribute__ ((unused)), + unsigned offset __attribute__ ((unused)), + unsigned len __attribute__ ((unused))) + { + pupa_putchar ('.'); + } + + if (argc < 1) + { + pupa_error (PUPA_ERR_BAD_ARGUMENT, "no file specified"); + return; + } + + file = pupa_file_open (argv[0]); + if (! file) + return; + + size = pupa_file_size (file) & ~(PUPA_DISK_SECTOR_SIZE - 1); + if (size == 0) + { + pupa_file_close (file); + return; + } + + buf = pupa_malloc (size); + if (! buf) + goto fail; + + pupa_printf ("Reading %s sequentially", argv[0]); + file->read_hook = read_func; + if (pupa_file_read (file, buf, size) != size) + goto fail; + pupa_printf (" Done.\n"); + + /* Read sequentially again. */ + pupa_printf ("Reading %s sequentially again", argv[0]); + if (pupa_file_seek (file, 0) < 0) + goto fail; + + for (pos = 0; pos < size; pos += PUPA_DISK_SECTOR_SIZE) + { + char sector[PUPA_DISK_SECTOR_SIZE]; + + if (pupa_file_read (file, sector, PUPA_DISK_SECTOR_SIZE) + != PUPA_DISK_SECTOR_SIZE) + goto fail; + + if (pupa_memcmp (sector, buf + pos, PUPA_DISK_SECTOR_SIZE) != 0) + { + pupa_printf ("\nDiffers in %d\n", pos); + goto fail; + } + } + pupa_printf (" Done.\n"); + + /* Read backwards and compare. */ + pupa_printf ("Reading %s backwards", argv[0]); + pos = size; + while (pos > 0) + { + char sector[PUPA_DISK_SECTOR_SIZE]; + + pos -= PUPA_DISK_SECTOR_SIZE; + + if (pupa_file_seek (file, pos) < 0) + goto fail; + + if (pupa_file_read (file, sector, PUPA_DISK_SECTOR_SIZE) + != PUPA_DISK_SECTOR_SIZE) + goto fail; + + if (pupa_memcmp (sector, buf + pos, PUPA_DISK_SECTOR_SIZE) != 0) + { + int i; + + pupa_printf ("\nDiffers in %d\n", pos); + + for (i = 0; i < PUPA_DISK_SECTOR_SIZE; i++) + pupa_putchar (buf[pos + i]); + + goto fail; + } + } + pupa_printf (" Done.\n"); + + fail: + + pupa_file_close (file); + pupa_free (buf); +} +#endif + +static void +pupa_rescue_cmd_dump (int argc, char *argv[]) +{ + pupa_uint8_t *addr; + pupa_size_t size = 4; + + if (argc == 0) + { + pupa_error (PUPA_ERR_BAD_ARGUMENT, "no address specified"); + return; + } + + addr = (pupa_uint8_t *) pupa_strtoul (argv[0], 0, 0); + if (pupa_errno) + return; + + if (argc > 1) + size = (pupa_size_t) pupa_strtoul (argv[1], 0, 0); + + while (size--) + { + pupa_printf ("%x%x ", *addr >> 4, *addr & 0xf); + addr++; + } +} + +/* Enter the rescue mode. */ +void +pupa_enter_rescue_mode (void) +{ + pupa_rescue_register_command ("boot", pupa_rescue_cmd_boot, + "boot an operating system"); + pupa_rescue_register_command ("cat", pupa_rescue_cmd_cat, + "show the contents of a file"); + pupa_rescue_register_command ("help", pupa_rescue_cmd_help, + "show this message"); + pupa_rescue_register_command ("initrd", pupa_rescue_cmd_module, + "load an initrd"); + pupa_rescue_register_command ("ls", pupa_rescue_cmd_ls, + "list devices or files"); + pupa_rescue_register_command ("module", pupa_rescue_cmd_module, + "load an OS module"); + pupa_rescue_register_command ("root", pupa_rescue_cmd_root, + "set a root device"); + pupa_rescue_register_command ("dump", pupa_rescue_cmd_dump, + "dump memory"); + + while (1) + { + char *line = buf; + char *name; + int n; + pupa_rescue_command_t cmd; + char *args[PUPA_RESCUE_MAX_ARGS + 1]; + + /* Get a command line. */ + pupa_rescue_get_command_line ("pupa rescue> "); + + /* Get the command name. */ + name = next_word (&line); + + /* If nothing is specified, restart. */ + if (*name == '\0') + continue; + + /* Get arguments. */ + for (n = 0; n <= PUPA_RESCUE_MAX_ARGS; n++) + { + char *arg = next_word (&line); + + if (*arg) + args[n] = arg; + else + break; + } + args[n] = 0; + + /* Find the command and execute it. */ + for (cmd = pupa_rescue_command_list; cmd; cmd = cmd->next) + { + if (pupa_strcmp (name, cmd->name) == 0) + { + (cmd->func) (n, args); + break; + } + } + + /* If not found, print an error message. */ + if (! cmd) + { + pupa_printf ("Unknown command `%s'\n", name); + pupa_printf ("Try `help' for usage\n"); + } + + /* Print an error, if any. */ + pupa_print_error (); + pupa_errno = PUPA_ERR_NONE; + } +} diff --git a/kern/term.c b/kern/term.c new file mode 100644 index 000000000..509e5c8e1 --- /dev/null +++ b/kern/term.c @@ -0,0 +1,153 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Free Software Foundation, Inc. + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include + +/* The list of terminals. */ +static pupa_term_t pupa_term_list; + +/* The current terminal. */ +static pupa_term_t pupa_cur_term; + +void +pupa_term_register (pupa_term_t term) +{ + term->next = pupa_term_list; + pupa_term_list = term; +} + +void +pupa_term_unregister (pupa_term_t term) +{ + pupa_term_t *p, q; + + for (p = &pupa_term_list, q = *p; q; p = &(q->next), q = q->next) + if (q == term) + { + *p = q->next; + break; + } +} + +void +pupa_term_iterate (int (*hook) (pupa_term_t term)) +{ + pupa_term_t p; + + for (p = pupa_term_list; p; p = p->next) + if (hook (p)) + break; +} + +void +pupa_term_set_current (pupa_term_t term) +{ + pupa_cur_term = term; +} + +pupa_term_t +pupa_term_get_current (void) +{ + return pupa_cur_term; +} + +void +pupa_putchar (int c) +{ + if (c == '\n') + pupa_putchar ('\r'); + else if (c == '\t' && pupa_cur_term->getxy) + { + int n; + + n = 8 - ((pupa_getxy () >> 8) & 7); + while (n--) + pupa_putchar (' '); + + return; + } + + (pupa_cur_term->putchar) (c); +} + +int +pupa_getkey (void) +{ + return (pupa_cur_term->getkey) (); +} + +int +pupa_checkkey (void) +{ + return (pupa_cur_term->checkkey) (); +} + +pupa_uint16_t +pupa_getxy (void) +{ + return (pupa_cur_term->getxy) (); +} + +void +pupa_gotoxy (pupa_uint8_t x, pupa_uint8_t y) +{ + (pupa_cur_term->gotoxy) (x, y); +} + +void +pupa_cls (void) +{ + if (pupa_cur_term->flags & PUPA_TERM_DUMB) + pupa_putchar ('\n'); + else + (pupa_cur_term->cls) (); +} + +void +pupa_setcolorstate (pupa_term_color_state state) +{ + if (pupa_cur_term->setcolorstate) + (pupa_cur_term->setcolorstate) (state); +} + +void +pupa_setcolor (pupa_uint8_t normal_color, pupa_uint8_t highlight_color) +{ + if (pupa_cur_term->setcolor) + (pupa_cur_term->setcolor) (normal_color, highlight_color); +} + +int +pupa_setcursor (int on) +{ + static int prev = 1; + int ret = prev; + + if (pupa_cur_term->setcursor) + { + (pupa_cur_term->setcursor) (on); + prev = on; + } + + return ret; +} + diff --git a/loader/i386/pc/chainloader.c b/loader/i386/pc/chainloader.c new file mode 100644 index 000000000..911f795d9 --- /dev/null +++ b/loader/i386/pc/chainloader.c @@ -0,0 +1,137 @@ +/* chainloader.c - boot another boot loader */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Allocate space statically, because this is very small anyway. */ +static char pupa_chainloader_boot_sector[PUPA_DISK_SECTOR_SIZE]; + +static pupa_err_t +pupa_chainloader_boot (void) +{ + pupa_device_t dev; + int drive = -1; + void *part_addr = 0; + + /* Open the root device. */ + dev = pupa_device_open (0); + if (dev) + { + pupa_disk_t disk = dev->disk; + + if (disk) + { + pupa_partition_t p = disk->partition; + + /* In i386-pc, the id is equal to the BIOS drive number. */ + drive = (int) disk->id; + + if (p) + { + pupa_disk_read (disk, p->offset, 446, 64, + (char *) PUPA_MEMORY_MACHINE_PART_TABLE_ADDR); + + /* Ignore errors. Perhaps it's not fatal. */ + part_addr = (void *) (PUPA_MEMORY_MACHINE_PART_TABLE_ADDR + + (p->index << 4)); + } + } + + pupa_device_close (dev); + } + + pupa_chainloader_real_boot (drive, part_addr); + + /* Never reach here. */ + return PUPA_ERR_NONE; +} + +static void +pupa_rescue_cmd_chainloader (int argc, char *argv[]) +{ + pupa_file_t file; + pupa_uint16_t signature; + int force = 0; + + if (argc > 0 && pupa_strcmp (argv[0], "--force") == 0) + { + force = 1; + argc--; + argv++; + } + + if (argc == 0) + { + pupa_error (PUPA_ERR_BAD_ARGUMENT, "no file specified"); + return; + } + + file = pupa_file_open (argv[0]); + if (! file) + return; + + /* Read the first block. */ + if (pupa_file_read (file, pupa_chainloader_boot_sector, + PUPA_DISK_SECTOR_SIZE) != PUPA_DISK_SECTOR_SIZE) + { + if (pupa_errno == PUPA_ERR_NONE) + pupa_error (PUPA_ERR_BAD_OS, "too small"); + + pupa_file_close (file); + return; + } + + /* Check the signature. */ + signature = *((pupa_uint16_t *) (pupa_chainloader_boot_sector + + PUPA_DISK_SECTOR_SIZE - 2)); + if (signature != pupa_le_to_cpu16 (0xaa55) && ! force) + pupa_error (PUPA_ERR_BAD_OS, "invalid signature"); + + pupa_file_close (file); + + if (pupa_errno == PUPA_ERR_NONE) + pupa_loader_set (0, pupa_chainloader_boot, 0); +} + +static const char loader_name[] = "chainloader"; + +PUPA_MOD_INIT +{ + pupa_rescue_register_command (loader_name, + pupa_rescue_cmd_chainloader, + "load another boot loader"); +} + +PUPA_MOD_FINI +{ + pupa_rescue_unregister_command (loader_name); +} diff --git a/mkinstalldirs b/mkinstalldirs new file mode 100644 index 000000000..6b3b5fc5d --- /dev/null +++ b/mkinstalldirs @@ -0,0 +1,40 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Public domain + +# $Id$ + +errstatus=0 + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here diff --git a/stamp-h.in b/stamp-h.in new file mode 100644 index 000000000..9788f7023 --- /dev/null +++ b/stamp-h.in @@ -0,0 +1 @@ +timestamp diff --git a/term/i386/pc/console.c b/term/i386/pc/console.c new file mode 100644 index 000000000..b0a3b8868 --- /dev/null +++ b/term/i386/pc/console.c @@ -0,0 +1,76 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Free Software Foundation, Inc. + * Copyright (C) 2002 Yoshinori K. Okuji + * + * 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. + */ + +#include +#include +#include + +pupa_uint8_t pupa_console_cur_color = 0x7; +static pupa_uint8_t pupa_console_standard_color = 0x7; +static pupa_uint8_t pupa_console_normal_color = 0x7; +static pupa_uint8_t pupa_console_highlight_color = 0x70; + +static void +pupa_console_setcolorstate (pupa_term_color_state state) +{ + switch (state) { + case PUPA_TERM_COLOR_STANDARD: + pupa_console_cur_color = pupa_console_standard_color; + break; + case PUPA_TERM_COLOR_NORMAL: + pupa_console_cur_color = pupa_console_normal_color; + break; + case PUPA_TERM_COLOR_HIGHLIGHT: + pupa_console_cur_color = pupa_console_highlight_color; + break; + default: + break; + } +} + +static void +pupa_console_setcolor (pupa_uint8_t normal_color, pupa_uint8_t highlight_color) +{ + pupa_console_normal_color = normal_color; + pupa_console_highlight_color = highlight_color; +} + +static struct pupa_term pupa_console_term = + { + .name = "console", + .putchar = pupa_console_putchar, + .checkkey = pupa_console_checkkey, + .getkey = pupa_console_getkey, + .getxy = pupa_console_getxy, + .gotoxy = pupa_console_gotoxy, + .cls = pupa_console_cls, + .setcolorstate = pupa_console_setcolorstate, + .setcolor = pupa_console_setcolor, + .setcursor = pupa_console_setcursor, + .flags = 0, + .next = 0 + }; + +void +pupa_console_init (void) +{ + pupa_term_register (&pupa_console_term); + pupa_term_set_current (&pupa_console_term); +} diff --git a/util/genmoddep.c b/util/genmoddep.c new file mode 100644 index 000000000..20da7a532 --- /dev/null +++ b/util/genmoddep.c @@ -0,0 +1,279 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * 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. + */ + +#include +#include +#include +#include + +#define BUF_SIZE 1024 +#define SYMTAB_SIZE 509 + +struct symbol +{ + const char *name; + const char *mod; + struct symbol *next; +}; + +struct module +{ + const char *name; + struct module *next; +}; + +static char buf[BUF_SIZE]; +static struct symbol *symtab[SYMTAB_SIZE]; + +static void +err (const char *fmt, ...) +{ + va_list ap; + + fprintf (stderr, "genmoddep: error: "); + + va_start (ap, fmt); + vfprintf (stderr, fmt, ap); + va_end (ap); + + fputc ('\n', stderr); + exit (1); +} + +static void * +xmalloc (size_t size) +{ + void *p; + + p = malloc (size); + if (! p) + err ("out of memory"); + + return p; +} + +static char * +xstrdup (const char *str) +{ + char *s; + size_t len; + + len = strlen (str); + s = (char *) xmalloc (len + 1); + memcpy (s, str, len + 1); + + return s; +} + +static void +chomp (char *str) +{ + int end; + + end = strlen (str) - 1; + if (end < 0) + err ("empty string"); + + if (str[end] == '\n') + str[end] = '\0'; +} + +static unsigned +symbol_hash (const char *s) +{ + unsigned key = 0; + + while (*s) + key = key * 65599 + *s++; + + return (key + (key >> 5)) % SYMTAB_SIZE; +} + +static struct symbol * +get_symbol (const char *name) +{ + unsigned k; + struct symbol *sym; + + k = symbol_hash (name); + for (sym = symtab[k]; sym; sym = sym->next) + if (strcmp (sym->name, name) == 0) + return sym; + + return 0; +} + +static void +add_symbol (const char *name, const char *mod) +{ + unsigned k; + struct symbol *sym; + + if (get_symbol (name)) + err ("duplicated symbol: %s", name); + + sym = (struct symbol *) xmalloc (sizeof (*sym)); + sym->name = xstrdup (name); + sym->mod = xstrdup (mod); + + k = symbol_hash (name); + sym->next = symtab[k]; + symtab[k] = sym; +} + +static void +free_symbols (void) +{ + int i; + + for (i = 0; i < SYMTAB_SIZE; i++) + { + struct symbol *p, *q; + + p = symtab[i]; + while (p) + { + q = p->next; + free ((void *) p->name); + free ((void *) p->mod); + free (p); + p = q; + } + } +} + +static void +read_defined_symbols (FILE *fp) +{ + while (fgets (buf, sizeof (buf), fp)) + { + char *p; + + if (! *buf) + err ("empty symbol name: %s", buf); + + p = strchr (buf, ' '); + if (! p) + err ("invalid line format: %s", buf); + + p++; + + if (! *p) + err ("empty module name: %s", buf); + + *(p - 1) = '\0'; + chomp (p); + + add_symbol (buf, p); + } +} + +static void +add_module (struct module **head, const char *name) +{ + struct module *mod; + + for (mod = *head; mod; mod = mod->next) + if (strcmp (mod->name, name) == 0) + return; + + mod = (struct module *) xmalloc (sizeof (*mod)); + mod->name = xstrdup (name); + + mod->next = *head; + *head = mod; +} + +static void +free_modules (struct module *head) +{ + struct module *next; + + while (head) + { + next = head->next; + free ((void *) head->name); + free (head); + head = next; + } +} + +static void +find_dependencies (FILE *fp) +{ + char *mod_name; + struct module *mod_list = 0; + struct module *mod; + + if (! fgets (buf, sizeof (buf), fp) || buf[0] == '\n' || buf[0] == '\0') + err ("no module name"); + + chomp (buf); + mod_name = xstrdup (buf); + + while (fgets (buf, sizeof (buf), fp)) + { + struct symbol *sym; + + chomp (buf); + sym = get_symbol (buf); + if (! sym) + err ("%s in %s is not defined", buf, mod_name); + + add_module (&mod_list, sym->mod); + } + + printf ("%s:", mod_name); + + for (mod = mod_list; mod; mod = mod->next) + if (strcmp (mod->name, "kernel") != 0) + printf (" %s", mod->name); + + putchar ('\n'); + + free_modules (mod_list); +} + +int +main (int argc, char *argv[]) +{ + int i; + + /* First, get defined symbols. */ + read_defined_symbols (stdin); + + /* Second, find the dependecies. */ + for (i = 1; i < argc; i++) + { + FILE *fp; + + fp = fopen (argv[i], "r"); + if (! fp) + err ("cannot open %s", argv[i]); + + find_dependencies (fp); + + fclose (fp); + } + + /* Last, free memory. */ + free_symbols (); + + return 0; +} diff --git a/util/i386/pc/grub-mkimage.c b/util/i386/pc/grub-mkimage.c new file mode 100644 index 000000000..68a28c510 --- /dev/null +++ b/util/i386/pc/grub-mkimage.c @@ -0,0 +1,223 @@ +/* pupa-mkimage.c - make a bootable image */ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define _GNU_SOURCE 1 +#include + +static void +generate_image (const char *dir, FILE *out, char *mods[]) +{ + pupa_addr_t module_addr = 0; + char *kernel_img, *boot_img; + size_t kernel_size, boot_size, total_module_size; + char *kernel_path, *boot_path; + unsigned num; + struct pupa_util_path_list *path_list, *p, *next; + + path_list = pupa_util_resolve_dependencies (dir, "moddep.lst", mods); + + kernel_path = pupa_util_get_path (dir, "kernel.img"); + kernel_size = pupa_util_get_image_size (kernel_path); + + total_module_size = 0; + for (p = path_list; p; p = p->next) + total_module_size += (pupa_util_get_image_size (p->name) + + sizeof (struct pupa_module_header)); + + pupa_util_info ("the total module size is 0x%x", total_module_size); + + num = ((kernel_size + total_module_size + PUPA_DISK_SECTOR_SIZE - 1) + >> PUPA_DISK_SECTOR_BITS); + if (num > 0xffff) + pupa_util_error ("the core image is too big"); + + boot_path = pupa_util_get_path (dir, "diskboot.img"); + boot_size = pupa_util_get_image_size (boot_path); + if (boot_size != PUPA_DISK_SECTOR_SIZE) + pupa_util_error ("diskboot.img is not one sector size"); + + boot_img = pupa_util_read_image (boot_path); + + /* i386 is a little endian architecture. */ + *((pupa_uint16_t *) (boot_img + PUPA_DISK_SECTOR_SIZE + - PUPA_BOOT_MACHINE_LIST_SIZE + 4)) + = pupa_cpu_to_le16 (num); + + pupa_util_write_image (boot_img, boot_size, out); + free (boot_img); + free (boot_path); + + kernel_img = pupa_util_read_image (kernel_path); + module_addr = (path_list + ? (PUPA_BOOT_MACHINE_KERNEL_ADDR + PUPA_DISK_SECTOR_SIZE + + kernel_size) + : 0); + + pupa_util_info ("the first module address is 0x%x", module_addr); + *((pupa_uint32_t *) (kernel_img + PUPA_KERNEL_MACHINE_TOTAL_MODULE_SIZE)) + = pupa_cpu_to_le32 (total_module_size); + *((pupa_uint32_t *) (kernel_img + PUPA_KERNEL_MACHINE_KERNEL_IMAGE_SIZE)) + = pupa_cpu_to_le32 (kernel_size); + + pupa_util_write_image (kernel_img, kernel_size, out); + free (kernel_img); + free (kernel_path); + + while (path_list) + { + struct pupa_module_header header; + size_t mod_size; + char *mod_img; + + next = path_list->next; + + mod_size = pupa_util_get_image_size (path_list->name); + + header.offset = pupa_cpu_to_le32 (sizeof (header)); + header.size = pupa_cpu_to_le32 (mod_size + sizeof (header)); + + pupa_util_info ("offset=0x%x, size=0x%x", header.offset, header.size); + pupa_util_write_image ((char *) &header, sizeof (header), out); + + mod_img = pupa_util_read_image (path_list->name); + pupa_util_write_image (mod_img, mod_size, out); + free (mod_img); + + free ((void *) path_list->name); + free (path_list); + path_list = next; + } +} + + + +static struct option options[] = + { + {"directory", required_argument, 0, 'd'}, + {"output", required_argument, 0, 'o'}, + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'V'}, + {"verbose", no_argument, 0, 'v'}, + {0, 0, 0, 0} + }; + +static void +usage (int status) +{ + if (status) + fprintf (stderr, "Try ``pupa-mkimage --help'' for more information.\n"); + else + printf ("\ +Usage: pupa-mkimage [OPTION]... [MODULES]\n\ +\n\ +Make a bootable image of PUPA.\n\ +\n\ + -d, --directory=DIR use images and modules under DIR [default=%s]\n\ + -o, --output=FILE output a generated image to FILE [default=stdout]\n\ + -h, --help display this image and exit\n\ + -V, --version print version information and exit\n\ + -v, --verbose print verbose messages\n\ +\n\ +Report bugs to .\n\ +", PUPA_DATADIR); + + exit (status); +} + +int +main (int argc, char *argv[]) +{ + char *output = 0; + char *dir = 0; + FILE *fp = stdout; + + progname = "pupa-mkimage"; + + while (1) + { + int c = getopt_long (argc, argv, "d:o:hVv", options, 0); + + if (c == -1) + break; + else + switch (c) + { + case 'o': + if (output) + free (output); + + output = xstrdup (optarg); + break; + + case 'd': + if (dir) + free (dir); + + dir = xstrdup (optarg); + break; + + case 'h': + usage (0); + break; + + case 'V': + printf ("pupa-mkimage (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION); + return 0; + + case 'v': + verbosity++; + break; + + default: + usage (1); + break; + } + } + + if (output) + { + fp = fopen (output, "wb"); + if (! fp) + pupa_util_error ("cannot open %s", output); + } + + generate_image (dir ? : PUPA_DATADIR, fp, argv + optind); + + fclose (fp); + + if (dir) + free (dir); + + return 0; +} diff --git a/util/misc.c b/util/misc.c new file mode 100644 index 000000000..6f65eb151 --- /dev/null +++ b/util/misc.c @@ -0,0 +1,137 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +#include + +char *progname = 0; +int verbosity = 0; + +void +pupa_util_info (const char *fmt, ...) +{ + if (verbosity > 0) + { + va_list ap; + + fprintf (stderr, "%s: info: ", progname); + va_start (ap, fmt); + vfprintf (stderr, fmt, ap); + va_end (ap); + fputc ('\n', stderr); + } +} + +void +pupa_util_error (const char *fmt, ...) +{ + va_list ap; + + fprintf (stderr, "%s: error: ", progname); + va_start (ap, fmt); + vfprintf (stderr, fmt, ap); + va_end (ap); + fputc ('\n', stderr); + exit (1); +} + +void * +xmalloc (size_t size) +{ + void *p; + + p = malloc (size); + if (! p) + pupa_util_error ("out of memory"); + + return p; +} + +char * +xstrdup (const char *str) +{ + size_t len; + char *dup; + + len = strlen (str); + dup = (char *) xmalloc (len + 1); + memcpy (dup, str, len + 1); + + return dup; +} + +char * +pupa_util_get_path (const char *dir, const char *file) +{ + char *path; + + path = (char *) xmalloc (strlen (dir) + 1 + strlen (file) + 1); + sprintf (path, "%s/%s", dir, file); + return path; +} + +size_t +pupa_util_get_image_size (const char *path) +{ + struct stat st; + + pupa_util_info ("getting the size of %s", path); + + if (stat (path, &st) == -1) + pupa_util_error ("cannot stat %s", path); + + return st.st_size; +} + +char * +pupa_util_read_image (const char *path) +{ + char *img; + FILE *fp; + size_t size; + + pupa_util_info ("reading %s", path); + + size = pupa_util_get_image_size (path); + img = (char *) xmalloc (size); + + fp = fopen (path, "rb"); + if (! fp) + pupa_util_error ("cannot open %s", path); + + if (fread (img, 1, size, fp) != size) + pupa_util_error ("cannot read %s", path); + + return img; +} + +void +pupa_util_write_image (const char *img, size_t size, FILE *out) +{ + pupa_util_info ("writing 0x%x bytes", size); + if (fwrite (img, 1, size, out) != size) + pupa_util_error ("write failed"); +} + diff --git a/util/resolve.c b/util/resolve.c new file mode 100644 index 000000000..8f985698e --- /dev/null +++ b/util/resolve.c @@ -0,0 +1,257 @@ +/* + * PUPA -- Preliminary Universal Programming Architecture for GRUB + * Copyright (C) 2002 Yoshinori K. Okuji + * + * PUPA 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 PUPA; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +#include +#include + +/* Module. */ +struct mod_list +{ + const char *name; + struct mod_list *next; +}; + +/* Dependency. */ +struct dep_list +{ + const char *name; + struct mod_list *list; + struct dep_list *next; +}; + +static char buf[1024]; + +static void +free_mod_list (struct mod_list *head) +{ + while (head) + { + struct mod_list *next; + + next = head->next; + free ((void *) head->name); + free (head); + head = next; + } +} + +static void +free_dep_list (struct dep_list *head) +{ + while (head) + { + struct dep_list *next; + + next = head->next; + free ((void *) head->name); + free_mod_list (head->list); + free (head); + head = next; + } +} + +/* Read the list of dependencies. */ +static struct dep_list * +read_dep_list (FILE *fp) +{ + struct dep_list *dep_list = 0; + + while (fgets (buf, sizeof (buf), fp)) + { + char *p; + struct dep_list *dep; + + /* Get the target name. */ + p = strchr (buf, ':'); + if (! p) + pupa_util_error ("invalid line format: %s", buf); + + *p++ = '\0'; + + dep = xmalloc (sizeof (*dep)); + dep->name = xstrdup (buf); + dep->list = 0; + + dep->next = dep_list; + dep_list = dep; + + /* Add dependencies. */ + while (*p) + { + struct mod_list *mod; + char *name; + + /* Skip white spaces. */ + while (*p && isspace (*p)) + p++; + + if (! *p) + break; + + name = p; + + /* Skip non-WSPs. */ + while (*p && ! isspace (*p)) + p++; + + *p++ = '\0'; + + mod = (struct mod_list *) xmalloc (sizeof (*mod)); + mod->name = xstrdup (name); + mod->next = dep->list; + dep->list = mod; + } + } + + return dep_list; +} + +static char * +get_module_name (const char *str) +{ + char *base; + char *ext; + + base = strrchr (str, '/'); + if (! base) + base = (char *) str; + else + base++; + + ext = strrchr (base, '.'); + if (ext && strcmp (ext, ".mod") == 0) + { + char *name; + + name = xmalloc (ext - base + 1); + memcpy (name, base, ext - base); + name[ext - base] = '\0'; + return name; + } + + return xstrdup (base); +} + +static char * +get_module_path (const char *prefix, const char *str) +{ + char *dir; + char *base; + char *ext; + char *ret; + + ext = strrchr (str, '.'); + if (ext && strcmp (ext, ".mod") == 0) + base = xstrdup (str); + else + { + base = xmalloc (strlen (str) + 4 + 1); + sprintf (base, "%s.mod", str); + } + + dir = strchr (str, '/'); + if (dir) + return base; + + ret = pupa_util_get_path (prefix, base); + free (base); + return ret; +} + +static void +add_module (const char *dir, + struct dep_list *dep_list, + struct mod_list **mod_head, + struct pupa_util_path_list **path_head, + const char *name) +{ + char *mod_name; + struct pupa_util_path_list *path; + struct mod_list *mod; + struct dep_list *dep; + + mod_name = get_module_name (name); + + /* Check if the module has already been added. */ + for (mod = *mod_head; mod; mod = mod->next) + if (strcmp (mod->name, mod_name) == 0) + { + free (mod_name); + return; + } + + /* Resolve dependencies. */ + for (dep = dep_list; dep; dep = dep->next) + if (strcmp (dep->name, mod_name) == 0) + { + for (mod = dep->list; mod; mod = mod->next) + add_module (dir, dep_list, mod_head, path_head, mod->name); + + break; + } + + /* Add this module. */ + mod = (struct mod_list *) xmalloc (sizeof (*mod)); + mod->name = mod_name; + mod->next = *mod_head; + *mod_head = mod; + + /* Add this path. */ + path = (struct pupa_util_path_list *) xmalloc (sizeof (*path)); + path->name = get_module_path (dir, name); + path->next = *path_head; + *path_head = path; +} + +struct pupa_util_path_list * +pupa_util_resolve_dependencies (const char *prefix, + const char *dep_list_file, + char *modules[]) +{ + char *path; + FILE *fp; + struct dep_list *dep_list; + struct mod_list *mod_list = 0; + struct pupa_util_path_list *path_list = 0; + + path = pupa_util_get_path (prefix, dep_list_file); + fp = fopen (path, "r"); + if (! fp) + pupa_util_error ("cannot open %s", path); + + free (path); + dep_list = read_dep_list (fp); + fclose (fp); + + while (*modules) + { + add_module (prefix, dep_list, &mod_list, &path_list, *modules); + modules++; + } + + free_dep_list (dep_list); + free_mod_list (mod_list); + + return path_list; +}