summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS6
-rw-r--r--COPYING341
-rw-r--r--Makefile249
-rw-r--r--Makefile.conf.in52
-rw-r--r--News73
-rw-r--r--TODO11
-rwxr-xr-xconfig/config.guess1441
-rwxr-xr-xconfig/config.sub1552
-rwxr-xr-xconfig/install-sh251
-rwxr-xr-xconfigure4840
-rw-r--r--configure.ac129
-rw-r--r--doc/linux-i386-boot.txt438
-rw-r--r--doc/linux-i386-zero-page.txt79
-rw-r--r--doc/multiboot.html664
-rw-r--r--doc/nbi-spec.txt660
-rw-r--r--include/boot/beoboot.h39
-rw-r--r--include/boot/elf_boot.h104
-rw-r--r--include/boot/linuxbios_tables.h82
-rw-r--r--include/elf.h2367
-rw-r--r--include/x86/mb_header.h90
-rw-r--r--include/x86/mb_info.h219
-rw-r--r--include/x86/x86-linux.h212
-rw-r--r--kdump/Makefile35
-rw-r--r--kdump/kdump.c311
-rw-r--r--kexec-tools.spec.in40
-rw-r--r--kexec/Makefile63
-rw-r--r--kexec/arch/alpha/include/arch/options.h11
-rw-r--r--kexec/arch/i386/Makefile11
-rw-r--r--kexec/arch/i386/compat_x86_64.S131
-rw-r--r--kexec/arch/i386/include/arch/options.h22
-rw-r--r--kexec/arch/i386/kexec-beoboot-x86.c140
-rw-r--r--kexec/arch/i386/kexec-bzImage.c296
-rw-r--r--kexec/arch/i386/kexec-elf-rel-x86.c35
-rw-r--r--kexec/arch/i386/kexec-elf-x86.c245
-rw-r--r--kexec/arch/i386/kexec-multiboot-x86.c393
-rw-r--r--kexec/arch/i386/kexec-nbi.c249
-rw-r--r--kexec/arch/i386/kexec-x86.c262
-rw-r--r--kexec/arch/i386/kexec-x86.h67
-rw-r--r--kexec/arch/i386/x86-linux-setup.c178
-rw-r--r--kexec/arch/i386/x86-linux-setup.h17
-rw-r--r--kexec/arch/ia64/Makefile6
-rw-r--r--kexec/arch/ia64/include/arch/options.h11
-rw-r--r--kexec/arch/ia64/kexec-elf-ia64.c141
-rw-r--r--kexec/arch/ia64/kexec-elf-rel-ia64.c45
-rw-r--r--kexec/arch/ia64/kexec-ia64.c156
-rw-r--r--kexec/arch/ia64/kexec-ia64.h9
-rw-r--r--kexec/arch/ppc/Makefile9
-rw-r--r--kexec/arch/ppc/include/arch/options.h11
-rw-r--r--kexec/arch/ppc/kexec-dol-ppc.c479
-rw-r--r--kexec/arch/ppc/kexec-elf-ppc.c225
-rw-r--r--kexec/arch/ppc/kexec-elf-rel-ppc.c64
-rw-r--r--kexec/arch/ppc/kexec-ppc.c151
-rw-r--r--kexec/arch/ppc/kexec-ppc.h28
-rw-r--r--kexec/arch/ppc/ppc-setup-dol.S174
-rw-r--r--kexec/arch/ppc/ppc-setup-simple.S39
-rw-r--r--kexec/arch/ppc/ppc_asm.h506
-rw-r--r--kexec/arch/ppc64/Makefile7
-rw-r--r--kexec/arch/ppc64/include/arch/options.h11
-rw-r--r--kexec/arch/ppc64/kexec-elf-ppc64.c123
-rw-r--r--kexec/arch/ppc64/kexec-elf-rel-ppc64.c95
-rw-r--r--kexec/arch/ppc64/kexec-ppc64.h9
-rw-r--r--kexec/arch/ppc64/kexec-zImage-ppc64.c173
-rw-r--r--kexec/arch/x86_64/Makefile12
-rw-r--r--kexec/arch/x86_64/include/arch/options.h22
-rw-r--r--kexec/arch/x86_64/kexec-elf-rel-x86_64.c93
-rw-r--r--kexec/arch/x86_64/kexec-elf-x86_64.c239
-rw-r--r--kexec/arch/x86_64/kexec-x86_64.c247
-rw-r--r--kexec/arch/x86_64/kexec-x86_64.h31
-rw-r--r--kexec/ifdown.c74
-rw-r--r--kexec/kexec-elf-boot.c95
-rw-r--r--kexec/kexec-elf-boot.h8
-rw-r--r--kexec/kexec-elf-exec.c149
-rw-r--r--kexec/kexec-elf-rel.c531
-rw-r--r--kexec/kexec-elf.c760
-rw-r--r--kexec/kexec-elf.h125
-rw-r--r--kexec/kexec-sha256.h11
-rw-r--r--kexec/kexec-syscall.h73
-rw-r--r--kexec/kexec.845
-rw-r--r--kexec/kexec.c810
-rw-r--r--kexec/kexec.h194
-rw-r--r--kexec_test/Makefile30
-rw-r--r--kexec_test/kexec_test.S475
-rw-r--r--kexec_test/kexec_test16.S1004
-rw-r--r--kexec_test/x86-setup-legacy-pic.S53
-rw-r--r--purgatory/Makefile68
-rw-r--r--purgatory/arch/alpha/Makefile7
-rw-r--r--purgatory/arch/alpha/include/limits.h57
-rw-r--r--purgatory/arch/alpha/include/stdint.h16
-rw-r--r--purgatory/arch/i386/Makefile14
-rw-r--r--purgatory/arch/i386/compat_x86_64.S100
-rw-r--r--purgatory/arch/i386/console-x86.c134
-rw-r--r--purgatory/arch/i386/entry16.S160
-rw-r--r--purgatory/arch/i386/entry32-16-debug.S195
-rw-r--r--purgatory/arch/i386/entry32-16.S160
-rw-r--r--purgatory/arch/i386/entry32.S110
-rw-r--r--purgatory/arch/i386/include/arch/debug.h316
-rw-r--r--purgatory/arch/i386/include/arch/io.h98
-rw-r--r--purgatory/arch/i386/include/limits.h58
-rw-r--r--purgatory/arch/i386/include/stdint.h16
-rw-r--r--purgatory/arch/i386/linux-entry16.S623
-rw-r--r--purgatory/arch/i386/pic.c51
-rw-r--r--purgatory/arch/i386/purgatory-x86.c40
-rw-r--r--purgatory/arch/i386/purgatory-x86.h8
-rw-r--r--purgatory/arch/i386/setup-x86.S72
-rw-r--r--purgatory/arch/i386/stack.S39
-rw-r--r--purgatory/arch/i386/timer.c10
-rw-r--r--purgatory/arch/i386/vga.c152
-rw-r--r--purgatory/arch/ia64/Makefile9
-rw-r--r--purgatory/arch/ia64/console-ia64.c5
-rw-r--r--purgatory/arch/ia64/include/limits.h57
-rw-r--r--purgatory/arch/ia64/include/stdint.h16
-rw-r--r--purgatory/arch/ia64/purgatory-ia64.c7
-rw-r--r--purgatory/arch/ia64/purgatory-ia64.h6
-rw-r--r--purgatory/arch/ppc/Makefile8
-rw-r--r--purgatory/arch/ppc/console-ppc.c5
-rw-r--r--purgatory/arch/ppc/include/limits.h58
-rw-r--r--purgatory/arch/ppc/include/stdint.h16
-rw-r--r--purgatory/arch/ppc/misc.S72
-rw-r--r--purgatory/arch/ppc/ppc_asm.h506
-rw-r--r--purgatory/arch/ppc/purgatory-ppc.c7
-rw-r--r--purgatory/arch/ppc/purgatory-ppc.h6
-rw-r--r--purgatory/arch/ppc64/Makefile7
-rw-r--r--purgatory/arch/ppc64/include/limits.h57
-rw-r--r--purgatory/arch/ppc64/include/stdint.h16
-rw-r--r--purgatory/arch/x86_64/Makefile15
-rw-r--r--purgatory/arch/x86_64/entry64-32.S134
-rw-r--r--purgatory/arch/x86_64/entry64.S100
-rw-r--r--purgatory/arch/x86_64/include/arch/debug.h317
-rw-r--r--purgatory/arch/x86_64/include/arch/io.h98
-rw-r--r--purgatory/arch/x86_64/include/limits.h57
-rw-r--r--purgatory/arch/x86_64/include/stdint.h16
-rw-r--r--purgatory/arch/x86_64/purgatory-x86_64.c12
-rw-r--r--purgatory/arch/x86_64/purgatory-x86_64.h4
-rw-r--r--purgatory/arch/x86_64/setup-x86_64.S73
-rw-r--r--purgatory/arch/x86_64/stack.S44
-rw-r--r--purgatory/include/purgatory.h8
-rw-r--r--purgatory/include/string.h10
-rw-r--r--purgatory/printf.c128
-rw-r--r--purgatory/purgatory.c47
-rw-r--r--purgatory/string.c53
-rw-r--r--util/Makefile4
-rw-r--r--util/bin-to-hex.c25
-rw-r--r--util_lib/Makefile23
-rw-r--r--util_lib/compute_ip_checksum.c102
-rw-r--r--util_lib/include/ip_checksum.h8
-rw-r--r--util_lib/include/sha256.h21
-rw-r--r--util_lib/sha256.c368
147 files changed, 28987 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..3f2ad12
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,6 @@
+Eric Biederman <ebiederm@xmission.com>
+Albert Herranz
+Jesse Barnes <jbarnes@sgi.com>
+Khalid Aziz <khalid.aziz@hp.com>
+Hariprasad Nellitheertha <hari@in.ibm.com>
+Tim Deegan <tjd21@cl.cam.ac.uk> \ No newline at end of file
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..a52b16e
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,341 @@
+
+ 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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ 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.
+
+ <signature of Ty Coon>, 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/Makefile b/Makefile
new file mode 100644
index 0000000..c75af67
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,249 @@
+# Hey Emacs this is a -*- makefile-*-
+include Makefile.conf
+VERSION=1.101
+DATE=15 February 2005
+PACKAGE=kexec-tools
+
+pkgdatadir = $(datadir)/$(PACKAGE)
+pkglibdir = $(libdir)/$(PACKAGE)
+pkgincludedir = $(includedir)/$(PACKAGE)
+
+# You can specify DESTDIR on the command line to do a add
+# a prefix to the install so it doesn't really happen
+# Useful for building binary packages
+DESTDIR =
+
+CPPFLAGS:= -I./include -I./util_lib/include \
+ -DVERSION='"$(VERSION)"' -DRELEASE_DATE='"$(DATE)"' \
+ $(DEFS) $(EXTRA_CFLAGS)
+
+PREFIX:=$(OBJDIR)/build
+SBINDIR=$(PREFIX)/sbin
+BINDIR=$(PREFIX)/bin
+LIBEXECDIR=$(PREFIX)/libexec
+DATADIR=$(PREFIX)/share
+SYSCONFDIR=$(PREFIX)/etc
+SHAREDSTATEDIR=$(PREFIX)/com
+LOCALSTATEDIR=$(PREFIX)/var
+LIBDIR=$(PREFIX)/lib
+INFODIR=$(PREFIX)/info
+MANDIR=$(PREFIX)/man
+MAN1DIR=$(MANDIR)/man1
+MAN2DIR=$(MANDIR)/man2
+MAN3DIR=$(MANDIR)/man3
+MAN4DIR=$(MANDIR)/man4
+MAN5DIR=$(MANDIR)/man5
+MAN6DIR=$(MANDIR)/man6
+MAN7DIR=$(MANDIR)/man7
+MAN8DIR=$(MANDIR)/man8
+INCLUDEDIR=$(PREFIX)/include
+
+PKGDATADIR=$(DATADIR)/$(PACKAGE)
+PKGLIBDIR=$(LIBDIR)/$(PACKAGE)
+PKGINCLUDEIR=$(INCLUDEDIR)/$(PACKAGE)
+
+MAN_PAGES:= kexec/kexec.8
+BINARIES_i386:= $(SBINDIR)/kexec $(PKGLIBDIR)/kexec_test
+BINARIES_x86_64:=$(SBINDIR)/kexec $(PKGLIBDIR)/kexec_test
+BINARIES:=$(SBINDIR)/kexec $(SBINDIR)/kdump $(BINARIES_$(ARCH))
+
+TARGETS:=$(BINARIES) $(MAN_PAGES)
+
+all: $(TARGETS)
+
+# cc-option
+# Usage: cflags-y += $(call cc-option, -march=winchip-c6, -march=i586)
+cc-option = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
+ > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
+
+# Utility function library
+#
+include util_lib/Makefile
+
+#
+# Stand alone utilities
+#
+include util/Makefile
+
+#
+# purgatory (code between kernels)
+#
+include purgatory/Makefile
+
+#
+# kexec (linux booting linux)
+#
+include kexec/Makefile
+
+
+# kdump (read a crashdump from memory)
+#
+include kdump/Makefile
+
+#
+# kexec_test (test program)
+#
+ifeq ($(ARCH),i386)
+include kexec_test/Makefile
+endif
+ifeq ($(ARCH),x86_64)
+include kexec_test/Makefile
+endif
+
+GENERATED_SRCS:= ./configure
+SPEC=$(OBJDIR)/$(PACKAGE)-$(VERSION).spec
+TARBALL=$(OBJDIR)/$(PACKAGE)-$(VERSION).tar.gz
+SRCS:=$(shell $(FIND) \
+ ./AUTHORS ./COPYING ./News ./TODO \
+ ./Makefile ./Makefile.conf.in ./configure.ac \
+ ./kexec-tools.spec.in ./config ./doc \
+ ./include ./kexec ./purgatory ./kexec_test ./kdump ./util ./util_lib \
+ ! -path '*CVS*' ! -name '*~' ! -name '.*' \
+ -type f -print )
+SRCS+=$(GENERATED_SRCS)
+PSRCS:=$(patsubst ./%,$(PACKAGE)-$(VERSION)/%,$(SRCS))
+PSRCS+=$(PACKAGE)-$(VERSION).spec
+
+Makefile.conf: Makefile.conf.in configure
+ /bin/sh ./configure
+
+configure: configure.ac
+ autoconf
+ $(RM) -rf autom4te.cache
+
+tarball: $(TARBALL)
+
+$(TARBALL): $(SRCS) $(SPEC)
+ $(MKDIR) -p $(OBJDIR)
+ $(RM) -f $(OBJDIR)/$(PACKAGE)-$(VERSION)
+ $(LN) -s .. $(OBJDIR)/$(PACKAGE)-$(VERSION)
+ (cd $(OBJDIR); $(TAR) -cf - $(PSRCS) | gzip -9) > $@
+
+rpm: $(TARBALL)
+ $(MKDIR) -p $(OBJDIR)/RPM $(OBJDIR)/SRPM $(OBJDIR)/BUILD $(OBJDIR)/SPECS \
+ $(OBJDIR)/TMP $(OBJDIR)/SOURCES
+ unset MAKEFLAGS MAKELEVEL; \
+ $(RPMBUILD) -ta \
+ --define '_rpmdir $(OBJDIR)/RPM' \
+ --define '_srcrpmdir $(OBJDIR)/SRPM' \
+ --define '_builddir $(OBJDIR)/BUILD' \
+ --define '_specdir $(OBJDIR)/SPECS' \
+ --define '_tmppath $(OBJDIR)/TMP' \
+ --define '_sourcedir $(OBJDIR)/SOURCES' \
+ $(TARBALL)
+
+$(SPEC): kexec-tools.spec.in Makefile
+ $(SED) -e 's,^Version: $$,Version: $(VERSION),' $< > $@
+
+echo::
+ @echo ARCH=$(ARCH)
+ @echo BINARIES=$(BINARIES)
+ @echo TARGETS=$(TARGETS)
+ @echo CC=$(CC)
+ @echo AR=$(AR)
+ @echo LD=$(LD)
+
+clean:
+ @$(FIND) $(OBJDIR) ! -name '*.d' -type f | $(XARGS) $(RM) rm -f
+ @$(RM) -rf rpm
+ @$(RM) -f config.log config.status config.cache
+ @$(RM) -f $(TARBALL)
+
+dist-clean: clean
+ @$(RM) -rf $(OBJDIR)
+ @$(FIND) . -type f -name '*~' -o -name '*.orig' | $(XARGS) $(RM) -f
+ @$(RM) -f Makefile.conf
+
+maintainer-clean: dist-clean
+ @$(RM) -f $(GENERATED_SRCS)
+
+
+install: $(TARGETS)
+ for file in $(TARGETS) ; do \
+ if test `$(DIRNAME) $$file` = "$(SBINDIR)" ; then \
+ $(MKDIR) -p $(DESTDIR)/$(sbindir)/; \
+ $(INSTALL) -m 555 $$file $(DESTDIR)/$(sbindir)/; \
+ fi; \
+ if test `$(DIRNAME) $$file` = "$(BINDIR)" ; then \
+ $(MKDIR) -p $(DESTDIR)/$(bindir)/; \
+ $(INSTALL) -m 555 $$file $(DESTDIR)/$(bindir)/; \
+ fi; \
+ if test `$(DIRNAME) $$file` = "$(LIBEXECDIR)" ; then \
+ $(MKDIR) -p $(DESTDIR)/$(libexecdir)/; \
+ $(INSTALL) -m 555 $$file $(DESTDIR)/$(libexecdir)/; \
+ fi; \
+ if test `$(DIRNAME) $$file` = "$(DATADIR)" ; then \
+ $(MKDIR) -p $(DESTDIR)/$(datadir)/; \
+ $(INSTALL) -m 444 $$file $(DESTDIR)/$(datadir)/; \
+ fi; \
+ if test `$(DIRNAME) $$file` = "$(SYSCONFDIR)" ; then \
+ $(MKDIR) -p $(DESTDIR)/$(sysconfdir)/; \
+ $(INSTALL) -m 444 $$file $(DESTDIR)/$(sysconfdir)/; \
+ fi; \
+ if test `$(DIRNAME) $$file` = "$(SHAREDSTATEDIR)" ; then \
+ $(MKDIR) -p $(DESTDIR)/$(sharedstatedir)/; \
+ $(INSTALL) -m 444 $$file $(DESTDIR)/$(sharedstatedir)/; \
+ fi; \
+ if test `$(DIRNAME) $$file` = "$(LOCALSTATEDIR)" ; then \
+ $(MKDIR) -p $(DESTDIR)/$(localstatedir)/; \
+ $(INSTALL) -m 444 $$file $(DESTDIR)/$(localstatedir)/; \
+ fi; \
+ if test `$(DIRNAME) $$file` = "$(LIBDIR)" ; then \
+ $(MKDIR) -p $(DESTDIR)/$(libdir)/; \
+ $(INSTALL) -m 444 $$file $(DESTDIR)/$(libdir)/; \
+ fi; \
+ if test `$(DIRNAME) $$file` = "$(INFODIR)" ; then \
+ $(MKDIR) -p $(DESTDIR)/$(infodir)/; \
+ $(INSTALL) -m 444 $$file $(DESTDIR)/$(infodir)/; \
+ fi; \
+ if test `$(DIRNAME) $$file` = "$(MAN1DIR)" ; then \
+ $(MKDIR) -p $(DESTDIR)/$(mandir)/man1; \
+ $(INSTALL) -m 444 $$file $(DESTDIR)/$(mandir)/man1; \
+ fi; \
+ if test `$(DIRNAME) $$file` = "$(MAN2DIR)" ; then \
+ $(MKDIR) -p $(DESTDIR)/$(mandir)/man2; \
+ $(INSTALL) -m 444 $$file $(DESTDIR)/$(mandir)/man2; \
+ fi; \
+ if test `$(DIRNAME) $$file` = "$(MAN3DIR)" ; then \
+ $(MKDIR) -p $(DESTDIR)/$(mandir)/man3/; \
+ $(INSTALL) -m 444 $$file $(DESTDIR)/$(mandir)/man3/; \
+ fi; \
+ if test `$(DIRNAME) $$file` = "$(MAN4DIR)" ; then \
+ $(MKDIR) -p $(DESTDIR)/$(mandir)/man4/; \
+ $(INSTALL) -m 444 $$file $(DESTDIR)/$(mandir)/man4/; \
+ fi; \
+ if test `$(DIRNAME) $$file` = "$(MAN5DIR)" ; then \
+ $(MKDIR) -p $(DESTDIR)/$(mandir)/man5/; \
+ $(INSTALL) -m 444 $$file $(DESTDIR)/$(mandir)/man5/; \
+ fi; \
+ if test `$(DIRNAME) $$file` = "$(MAN6DIR)" ; then \
+ $(MKDIR) -p $(DESTDIR)/$(mandir)/man6/; \
+ $(INSTALL) -m 444 $$file $(DESTDIR)/$(mandir)/man6/; \
+ fi; \
+ if test `$(DIRNAME) $$file` = "$(MAN7DIR)" ; then \
+ $(MKDIR) -p $(DESTDIR)/$(mandir)/man7/; \
+ $(INSTALL) -m 444 $$file $(DESTDIR)/$(mandir)/man7/; \
+ fi; \
+ if test `$(DIRNAME) $$file` = "$(MAN8DIR)" ; then \
+ $(MKDIR) -p $(DESTDIR)/$(mandir)/man8/; \
+ $(INSTALL) -m 444 $$file $(DESTDIR)/$(mandir)/man8/; \
+ fi; \
+ if test `$(DIRNAME) $$file` = "$(INCLUDEDIR)" ; then \
+ $(MKDIR) -p $(DESTDIR)/$(includedir)/; \
+ $(INSTALL) -m 444 $$file $(DESTDIR)/$(includedir)/; \
+ fi; \
+ if test `$(DIRNAME) $$file` = "$(PKGDATADIR)" ; then \
+ $(MKDIR) -p $(DESTDIR)/$(pkgdatadir)/; \
+ $(INSTALL) -m 444 $$file $(DESTDIR)/$(pkgdatadir)/; \
+ fi; \
+ if test `$(DIRNAME) $$file` = "$(PKGLIBDIR)" ; then \
+ $(MKDIR) -p $(DESTDIR)/$(pkglibdir)/; \
+ $(INSTALL) -m 444 $$file $(DESTDIR)/$(pkglibdir)/; \
+ fi; \
+ if test `$(DIRNAME) $$file` = "$(PKGINCLUDEDIR)" ; then \
+ $(MKDIR) -p $(DESTDIR)/$(pkgincludedir)/; \
+ $(INSTALL) -m 444 $$file $(DESTDIR)/$(pkgincludedir)/; \
+ fi; \
+ done
+
+.PHONY: echo install all clean dist-clean maintainer-clean tarball rpm
diff --git a/Makefile.conf.in b/Makefile.conf.in
new file mode 100644
index 0000000..40111b2
--- /dev/null
+++ b/Makefile.conf.in
@@ -0,0 +1,52 @@
+# Hey Emacs this is a -*- makefile-*-
+
+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@
+
+DEFS=@DEFS@
+LIBS=@LIBS@
+
+# The target architecture
+ARCH =@ARCH@
+OBJDIR=@OBJDIR@
+
+# Compiler for building kexec
+CC =@CC@
+CPP =@CPP@
+LD =@LD@
+AS =@AS@
+OBJCOPY =@OBJCOPY@
+AR =@AR@
+CFLAGS =@CFLAGS@
+EXTRA_CFLAGS=@EXTRA_CFLAGS@
+LDFLAGS =@LDFLAGS@
+
+# Utilities called by the makefiles
+INSTALL=@INSTALL@
+MKDIR=@MKDIR@
+RM=@RM@
+CP=@CP@
+LN=@LN@
+TAR=@TAR@
+RPMBUILD=@RPMBUILD@
+SED=@SED@
+FIND=@FIND@
+XARGS=@XARGS@
+DIRNAME=@DIRNAME@
+
+# C compiler for building utilities to use
+# during the build
+BUILD_CC=@BUILD_CC@
+BUILD_CFLAGS=@BUILD_CFLAGS@ $(DEFS)
diff --git a/News b/News
new file mode 100644
index 0000000..560c4e5
--- /dev/null
+++ b/News
@@ -0,0 +1,73 @@
+* 2.0
+ - In purgatory added -fno-zero-initialized-in-bss to prevent issues with
+ recent versions of gcc
+ - Add an option to configure to disable zlib support
+ - Add mismatched architecture support
+ - Updated the x86 architecture help
+ - Updated the x86_64 architecture help
+ - Fixed bzImage support
+ - Added support for finding either the highest or lowest usable window.
+ - Change the version number to 2.0 to reflect the major change in
+ the code base. 1.99 was effectively the release canidate.
+* 1.99
+ - Rearchitect so the code is maintainable.
+ - Add multiboot support
+ - Add ia64 support
+ - Add beoboot image support
+ - Create generic elf loader code.
+ - Created the relocated shared object purgatory to hold
+ the code that runs between kernels.
+ - Added a configure script
+ - Added an rpm target
+ - Added kexec on panic support
+ - Initial stab at adding documentation
+ - Added loader support for ET_DYN objects
+* 1.98
+ - Add mysteriously dropped changes to make x86_64 work
+ - Update the distclean target to remove *.orig and *~ files
+* 1.97
+ - Add support for cross compiling x86_64
+* 1.96
+ - add x86_64 support
+ - add support for linux style arguments to the elf32-x86 loader
+ - disable clearing of cr4 on x86
+* 1.95
+ - add kexec-zImage-ppc64.c source file
+ - GameCube/PPC32 sync'ed to 1.94
+ - use syscall() to call sys_kexec_load() and reboot()
+ - add kexec-syscall.h, remove kexec-syscall.c
+ - makefiles know about ARCH-es
+ - add noifdown kexec option (Albert Herranz)
+* 1.94
+ - revert a bad 1.92 change (not setting optind & opterr for subsequent
+ calls to getopt_long())
+* 1.93
+ - restored "shutdown" functionality;
+ - more help/usage text clarification;
+ - add GPLv2 license to source files (with permission from Eric Biederman)
+* 1.92
+ - my_kexec(): call kexec() only one time;
+ - add "unload" option;
+ - fix some compiler warnings about "<var> might be used uninitialized";
+ - commented out shutdown capability since it was unreachable;
+* 1.91
+ - fix "-t" option: strcmp() was inverted (Albert Herranz)
+ - check specified kernel image file for file type (Albert Herranz)
+* 1.9
+ - change reboot function to return type long (was int)
+ - use kexec reserved syscall numbers (in Linux 2.6.6-mm3)
+* 1.8
+ - Fixed bug where ramdisk wasn't loaded when specified
+ - Memory information is now read from /proc/iomem.
+ Information that is not needed is ignored.
+* 1.7
+ - Update to new tentative syscall number....
+* 1.6
+ - Redo all of the command line arguments.
+ - Use the 32-bit kernel entry point.
+ - Work around a failure to clear %cr4.
+* 1.5
+ - Port to a new kernel interface (Hopefully the final one).
+ - Start working on setting up legacy hardware
+ - Add --load and --exec options so the parts can be done at different times.
+###
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..d99bba9
--- /dev/null
+++ b/TODO
@@ -0,0 +1,11 @@
+- Restore enough state that DOS/arbitrary BIOS calls can be run on some
+ platforms. Currently disk-related calls are quite likely to blow up.
+- x86 filling in other kernel parameters.
+- Merge reboot via kexec functionality into /sbin/reboot
+- In the kexec-on-panic case preserving memory the both kernels
+ must use.
+- Finish the kexec-on-panic case.
+- Improve the documentation
+- Add support for loading a boot sector
+- Autobuilding of initramfs
+###
diff --git a/config/config.guess b/config/config.guess
new file mode 100755
index 0000000..77c7cba
--- /dev/null
+++ b/config/config.guess
@@ -0,0 +1,1441 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+timestamp='2004-08-13'
+
+# 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 <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>. 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 <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+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
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ 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
+ armeb) machine=armeb-unknown ;;
+ 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
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # 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 ;;
+ amd64:OpenBSD:*:*)
+ echo x86_64-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ amiga:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ cats:OpenBSD:*:*)
+ echo arm-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hp300:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ luna88k:OpenBSD:*:*)
+ echo m88k-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 ;;
+ sgi:OpenBSD:*:*)
+ echo mips64-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:OpenBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit 0 ;;
+ macppc:MirBSD:*:*)
+ echo powerppc-unknown-mirbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit 0 ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # 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.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | 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 ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ 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 ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit 0 ;;
+ DRS?6000:UNIX_SV:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7 && exit 0 ;;
+ esac ;;
+ 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 ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${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 <stdio.h> /* 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 -o $dummy $dummy.c \
+ && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+ && exit 0
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit 0 ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit 0 ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit 0 ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-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 <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+ 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 <stdlib.h>
+ #include <unistd.h>
+
+ 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 -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ # avoid double evaluation of $set_cc_for_build
+ test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ 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 <unistd.h>
+ 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 -o $dummy $dummy.c && $dummy && exit 0
+ 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*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 ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${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 ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-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*:[34]*)
+ echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
+ exit 0 ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ 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 i586-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:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit 0 ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit 0 ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit 0 ;;
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit 0 ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ m32r*: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=`
+ test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+ ;;
+ mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && echo "${CPU}-unknown-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 ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ 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 <features.h>
+ #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
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ 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:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit 0 ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit 0 ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit 0 ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit 0 ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ 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' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ 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 ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit 0 ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit 0 ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*: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 ;;
+ 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 <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit 0 ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # 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 ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-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:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ case $UNAME_PROCESSOR in
+ *86) UNAME_PROCESSOR=i686 ;;
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-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-?: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 ;;
+ *: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 ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit 0 ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit 0 ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms && exit 0 ;;
+ I*) echo ia64-dec-vms && exit 0 ;;
+ V*) echo vax-dec-vms && exit 0 ;;
+ esac
+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 <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#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 <sys/param.h>
+ 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 <sys/param.h>
+# 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 -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0
+
+# 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 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> 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/config.sub b/config/config.sub
new file mode 100755
index 0000000..ac6de98
--- /dev/null
+++ b/config/config.sub
@@ -0,0 +1,1552 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+timestamp='2004-06-24'
+
+# 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 <config-patches@gnu.org>. 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 <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+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* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
+ kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | 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 | -knuth | -cray)
+ 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] \
+ | am33_2.0 \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+ | c4x | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | m32r | m32rle | m68000 | m68k | m88k | mcore \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64vr | mips64vrel \
+ | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | msp430 \
+ | ns16k | ns32k \
+ | openrisc | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv8 | sparcv9 | sparcv9b \
+ | strongarm \
+ | tahoe | thumb | tic4x | 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-* | armeb-* | armv*-* \
+ | avr-* \
+ | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | mcore-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | msp430-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | 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
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ 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
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ 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
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16c)
+ basic_machine=cr16c-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ 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
+ ;;
+ 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
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ 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 | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-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-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`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
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ 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
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-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
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ 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
+ ;;
+ 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
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ 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 | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparc | sparcv8 | 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
+ ;;
+ *-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* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
+ | -ekkobsd* | -kfreebsd* | -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* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -mks* | -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* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|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-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -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
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -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
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -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
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -kaos*)
+ os=-kaos
+ ;;
+ -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
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ # 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
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-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
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -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/config/install-sh b/config/install-sh
new file mode 100755
index 0000000..e9de238
--- /dev/null
+++ b/config/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/configure b/configure
new file mode 100755
index 0000000..d4267f1
--- /dev/null
+++ b/configure
@@ -0,0 +1,4840 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.59.
+#
+# Copyright (C) 2003 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$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" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.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
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ 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
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval 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="eval 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
+
+
+# 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
+ac_config_libobj_dir=.
+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=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="Makefile.conf.in"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+# include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP LD ac_ct_LD AS ac_ct_AS OBJCOPY ac_ct_OBJCOPY AR ac_ct_AR INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA MKDIR RM CP LN TAR RPMBUILD SED FIND XARGS DIRNAME EGREP BUILD_CC BUILD_CFLAGS EXTRA_CFLAGS ARCH OBJDIR INSTALL LIBOBJS LTLIBOBJS'
+ac_subst_files=''
+
+# 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
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+ { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+ { (exit 1); exit 1; }; }
+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 this package 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
+
+ cat <<\_ACEOF
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-objdir=<dir> select directory for object files
+ --with-gamecube enable gamecube support
+ --without-zlib disable gamecube support
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have
+ headers in a nonstandard directory <include dir>
+ 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.
+
+_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
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
+ 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
+
+Copyright (C) 2003 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 $as_me, which was
+generated by GNU Autoconf 2.59. 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.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_sep=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+ # Get rid of the leading space.
+ ac_sep=" "
+ ;;
+ esac
+ done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# 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
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------- ##
+## Output files. ##
+## ------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ sed "/^$/d" confdefs.h | sort
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f 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_aux_dir=
+for ac_dir in ./config $srcdir/./config; 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 ./config $srcdir/./config" >&5
+echo "$as_me: error: cannot find install-sh or install.sh in ./config $srcdir/./config" >&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?86 )
+ host_cpu="i386"
+ ;;
+ powerpc )
+ host_cpu="ppc"
+ ;;
+ * )
+ host_cpu="$host_cpu"
+ ;;
+esac
+case $host_cpu in
+ i386|ppc|x86_64|alpha|ppc64|ia64)
+ ;;
+ * )
+ { { echo "$as_me:$LINENO: error: unsupported architecture $host_cpu" >&5
+echo "$as_me: error: unsupported architecture $host_cpu" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+esac
+ARCH=$host_cpu
+
+
+OBJDIR=`pwd`/objdir
+if test "${host_alias}" ; then
+ OBJDIR="$OBJDIR-${host_alias}"
+fi
+EXTRA_CFLAGS=""
+
+# Check whether --with-objdir or --without-objdir was given.
+if test "${with_objdir+set}" = set; then
+ withval="$with_objdir"
+ OBJDIR="$withval"
+else
+ OBJDIR="$OBJDIR"
+fi;
+
+
+# Check whether --with-gamecube or --without-gamecube was given.
+if test "${with_gamecube+set}" = set; then
+ withval="$with_gamecube"
+ EXTRA_CFLAGS="$EXTRA_CFLAGS -DCONFIG_GAMECUBE=1"
+fi;
+
+
+# Check whether --with-zlib or --without-zlib was given.
+if test "${with_zlib+set}" = set; then
+ withval="$with_zlib"
+ with_zlib="$withval"
+else
+ with_zlib=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
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ 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
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&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 </dev/null >&5\"") >&5
+ (eval $ac_compiler --version </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+ (eval $ac_compiler -v </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+ (eval $ac_compiler -V </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# 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 file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $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=
+# b.out is created by i960 compilers.
+for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+ ;;
+ conftest.$ac_ext )
+ # This is the source file.
+ ;;
+ [ab].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,
+ # but it would be cool to find out if it's true. Does anybody
+ # maintain Libtool? --akim.
+ export ac_cv_exeext
+ break;;
+ * )
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&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'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&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 b.out
+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 conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+ *.* ) 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
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&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
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+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 | *.xSYM | *.bb | *.bbg ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&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
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+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>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (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); }; } &&
+ { 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
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err 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
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (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); }; } &&
+ { 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
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.err 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
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std1 is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std1. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX -qlanglvl=ansi
+# Ultrix and OSF/1 -std1
+# HP-UX 10.20 and later -Ae
+# HP-UX older versions -Aa -D_HPUX_SOURCE
+# SVR4 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (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); }; } &&
+ { 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_stdc=$ac_arg
+break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
+
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+ x|xno)
+ echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+ *)
+ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+ CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+# 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>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (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); }; } &&
+ { 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 \
+ '' \
+ '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
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+#include <stdlib.h>
+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>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (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); }; } &&
+ { 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
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+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>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (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); }; } &&
+ { 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
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err 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
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err 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
+
+
+if test "${build}" != "${host}" ; then
+ BUILD_CC=${CC_FOR_BUILD-gcc}
+else
+ BUILD_CC="\$(CC)"
+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 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.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # 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
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ 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=$?
+ grep -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
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_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
+sed 's/^/| /' 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
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -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
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_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
+sed 's/^/| /' 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.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # 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
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ 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=$?
+ grep -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
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_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
+sed 's/^/| /' 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
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -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
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_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
+sed 's/^/| /' 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
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&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
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ld", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ld; 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_LD+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$LD"; then
+ ac_cv_prog_LD="$LD" # 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_LD="${ac_tool_prefix}ld"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+LD=$ac_cv_prog_LD
+if test -n "$LD"; then
+ echo "$as_me:$LINENO: result: $LD" >&5
+echo "${ECHO_T}$LD" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_LD"; then
+ ac_ct_LD=$LD
+ # Extract the first word of "ld", so it can be a program name with args.
+set dummy ld; 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_LD+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_LD"; then
+ ac_cv_prog_ac_ct_LD="$ac_ct_LD" # 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_LD="ld"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_ac_ct_LD" && ac_cv_prog_ac_ct_LD=""no""
+fi
+fi
+ac_ct_LD=$ac_cv_prog_ac_ct_LD
+if test -n "$ac_ct_LD"; then
+ echo "$as_me:$LINENO: result: $ac_ct_LD" >&5
+echo "${ECHO_T}$ac_ct_LD" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ LD=$ac_ct_LD
+else
+ LD="$ac_cv_prog_LD"
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args.
+set dummy ${ac_tool_prefix}as; 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_AS+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$AS"; then
+ ac_cv_prog_AS="$AS" # 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_AS="${ac_tool_prefix}as"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+AS=$ac_cv_prog_AS
+if test -n "$AS"; then
+ echo "$as_me:$LINENO: result: $AS" >&5
+echo "${ECHO_T}$AS" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_AS"; then
+ ac_ct_AS=$AS
+ # Extract the first word of "as", so it can be a program name with args.
+set dummy as; 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_AS+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_AS"; then
+ ac_cv_prog_ac_ct_AS="$ac_ct_AS" # 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_AS="as"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_ac_ct_AS" && ac_cv_prog_ac_ct_AS=""no""
+fi
+fi
+ac_ct_AS=$ac_cv_prog_ac_ct_AS
+if test -n "$ac_ct_AS"; then
+ echo "$as_me:$LINENO: result: $ac_ct_AS" >&5
+echo "${ECHO_T}$ac_ct_AS" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ AS=$ac_ct_AS
+else
+ AS="$ac_cv_prog_AS"
+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
+
+ test -z "$ac_cv_prog_ac_ct_OBJCOPY" && ac_cv_prog_ac_ct_OBJCOPY=""no""
+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
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; 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_AR+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # 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_AR="${ac_tool_prefix}ar"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ echo "$as_me:$LINENO: result: $AR" >&5
+echo "${ECHO_T}$AR" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+ ac_ct_AR=$AR
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; 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_AR+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # 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_AR="ar"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_ac_ct_AR" && ac_cv_prog_ac_ct_AR=""""
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ echo "$as_me:$LINENO: result: $ac_ct_AR" >&5
+echo "${ECHO_T}$ac_ct_AR" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ AR=$ac_ct_AR
+else
+ AR="$ac_cv_prog_AR"
+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"
+# OS/2's system install, which has a completely different semantic
+# ./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/* | \
+ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+ /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'
+
+# Extract the first word of "mkdir", so it can be a program name with args.
+set dummy mkdir; 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_MKDIR+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$MKDIR"; then
+ ac_cv_prog_MKDIR="$MKDIR" # 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_MKDIR="mkdir"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_MKDIR" && ac_cv_prog_MKDIR=""no""
+fi
+fi
+MKDIR=$ac_cv_prog_MKDIR
+if test -n "$MKDIR"; then
+ echo "$as_me:$LINENO: result: $MKDIR" >&5
+echo "${ECHO_T}$MKDIR" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+# Extract the first word of "rm", so it can be a program name with args.
+set dummy rm; 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_RM+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$RM"; then
+ ac_cv_prog_RM="$RM" # 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_RM="rm"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_RM" && ac_cv_prog_RM=""no""
+fi
+fi
+RM=$ac_cv_prog_RM
+if test -n "$RM"; then
+ echo "$as_me:$LINENO: result: $RM" >&5
+echo "${ECHO_T}$RM" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+# Extract the first word of "cp", so it can be a program name with args.
+set dummy cp; 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_CP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CP"; then
+ ac_cv_prog_CP="$CP" # 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_CP="cp"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_CP" && ac_cv_prog_CP=""no""
+fi
+fi
+CP=$ac_cv_prog_CP
+if test -n "$CP"; then
+ echo "$as_me:$LINENO: result: $CP" >&5
+echo "${ECHO_T}$CP" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+# Extract the first word of "ln", so it can be a program name with args.
+set dummy ln; 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_LN+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$LN"; then
+ ac_cv_prog_LN="$LN" # 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_LN="ln"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_LN" && ac_cv_prog_LN=""no""
+fi
+fi
+LN=$ac_cv_prog_LN
+if test -n "$LN"; then
+ echo "$as_me:$LINENO: result: $LN" >&5
+echo "${ECHO_T}$LN" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+# Extract the first word of "tar", so it can be a program name with args.
+set dummy tar; 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_TAR+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$TAR"; then
+ ac_cv_prog_TAR="$TAR" # 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_TAR="tar"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_TAR" && ac_cv_prog_TAR=""no""
+fi
+fi
+TAR=$ac_cv_prog_TAR
+if test -n "$TAR"; then
+ echo "$as_me:$LINENO: result: $TAR" >&5
+echo "${ECHO_T}$TAR" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+# Extract the first word of "rpmbuild", so it can be a program name with args.
+set dummy rpmbuild; 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_RPMBUILD+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$RPMBUILD"; then
+ ac_cv_prog_RPMBUILD="$RPMBUILD" # 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_RPMBUILD="rpmbuild"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_RPMBUILD" && ac_cv_prog_RPMBUILD=""no""
+fi
+fi
+RPMBUILD=$ac_cv_prog_RPMBUILD
+if test -n "$RPMBUILD"; then
+ echo "$as_me:$LINENO: result: $RPMBUILD" >&5
+echo "${ECHO_T}$RPMBUILD" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+# Extract the first word of "sed", so it can be a program name with args.
+set dummy sed; 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_SED+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$SED"; then
+ ac_cv_prog_SED="$SED" # 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_SED="sed"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_SED" && ac_cv_prog_SED=""no""
+fi
+fi
+SED=$ac_cv_prog_SED
+if test -n "$SED"; then
+ echo "$as_me:$LINENO: result: $SED" >&5
+echo "${ECHO_T}$SED" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+# Extract the first word of "find", so it can be a program name with args.
+set dummy find; 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_FIND+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$FIND"; then
+ ac_cv_prog_FIND="$FIND" # 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_FIND="find"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_FIND" && ac_cv_prog_FIND=""no""
+fi
+fi
+FIND=$ac_cv_prog_FIND
+if test -n "$FIND"; then
+ echo "$as_me:$LINENO: result: $FIND" >&5
+echo "${ECHO_T}$FIND" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+# Extract the first word of "xargs", so it can be a program name with args.
+set dummy xargs; 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_XARGS+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$XARGS"; then
+ ac_cv_prog_XARGS="$XARGS" # 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_XARGS="xargs"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_XARGS" && ac_cv_prog_XARGS=""no""
+fi
+fi
+XARGS=$ac_cv_prog_XARGS
+if test -n "$XARGS"; then
+ echo "$as_me:$LINENO: result: $XARGS" >&5
+echo "${ECHO_T}$XARGS" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+# Extract the first word of "dirname", so it can be a program name with args.
+set dummy dirname; 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_DIRNAME+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$DIRNAME"; then
+ ac_cv_prog_DIRNAME="$DIRNAME" # 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_DIRNAME="dirname"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_DIRNAME" && ac_cv_prog_DIRNAME=""no""
+fi
+fi
+DIRNAME=$ac_cv_prog_DIRNAME
+if test -n "$DIRNAME"; then
+ echo "$as_me:$LINENO: result: $DIRNAME" >&5
+echo "${ECHO_T}$DIRNAME" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+
+if test "$with_zlib" = yes ; then
+
+echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6
+if test "${ac_cv_prog_egrep+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+ then ac_cv_prog_egrep='grep -E'
+ else ac_cv_prog_egrep='egrep'
+ fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
+echo "${ECHO_T}$ac_cv_prog_egrep" >&6
+ EGREP=$ac_cv_prog_egrep
+
+
+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
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (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); }; } &&
+ { 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_header_stdc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_objext 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
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string.h>
+
+_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
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_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
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ctype.h>
+#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
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out 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
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end 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>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (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); }; } &&
+ { 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
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err 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
+
+
+if test "${ac_cv_header_zlib_h+set}" = set; then
+ echo "$as_me:$LINENO: checking for zlib.h" >&5
+echo $ECHO_N "checking for zlib.h... $ECHO_C" >&6
+if test "${ac_cv_header_zlib_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_zlib_h" >&5
+echo "${ECHO_T}$ac_cv_header_zlib_h" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking zlib.h usability" >&5
+echo $ECHO_N "checking zlib.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <zlib.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (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); }; } &&
+ { 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_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking zlib.h presence" >&5
+echo $ECHO_N "checking zlib.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <zlib.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -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
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: zlib.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: zlib.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: zlib.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: zlib.h: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: zlib.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: zlib.h: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: zlib.h: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: zlib.h: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: zlib.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: zlib.h: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: zlib.h: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: zlib.h: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: zlib.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: zlib.h: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: zlib.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: zlib.h: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists. ##
+## ------------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for zlib.h" >&5
+echo $ECHO_N "checking for zlib.h... $ECHO_C" >&6
+if test "${ac_cv_header_zlib_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_header_zlib_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_zlib_h" >&5
+echo "${ECHO_T}$ac_cv_header_zlib_h" >&6
+
+fi
+if test $ac_cv_header_zlib_h = yes; then
+ echo "$as_me:$LINENO: checking for inflateInit_ in -lz" >&5
+echo $ECHO_N "checking for inflateInit_ in -lz... $ECHO_C" >&6
+if test "${ac_cv_lib_z_inflateInit_+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lz $LIBS"
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char inflateInit_ ();
+int
+main ()
+{
+inflateInit_ ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (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); }; } &&
+ { 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
+ ac_cv_lib_z_inflateInit_=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_z_inflateInit_=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_z_inflateInit_" >&5
+echo "${ECHO_T}$ac_cv_lib_z_inflateInit_" >&6
+if test $ac_cv_lib_z_inflateInit_ = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_ZLIB_H 1
+_ACEOF
+ LIBS="$LIBS -lz"
+fi
+
+fi
+
+
+fi
+
+
+CFLAGS='-Wall -g -fno-strict-aliasing $(CPPFLAGS)'
+BUILD_CFLAGS='-O2 -Wall $(CPPFLAGS)'
+
+if test "$CC" = "no"; then { { echo "$as_me:$LINENO: error: cc not found" >&5
+echo "$as_me: error: cc not found" >&2;}
+ { (exit 1); exit 1; }; } fi
+if test "$CPP" = "no"; then { { echo "$as_me:$LINENO: error: cpp not found" >&5
+echo "$as_me: error: cpp not found" >&2;}
+ { (exit 1); exit 1; }; } fi
+if test "$LD" = "no"; then { { echo "$as_me:$LINENO: error: ld not found" >&5
+echo "$as_me: error: ld not found" >&2;}
+ { (exit 1); exit 1; }; } fi
+if test "$AS" = "no"; then { { echo "$as_me:$LINENO: error: as not found" >&5
+echo "$as_me: error: as not found" >&2;}
+ { (exit 1); exit 1; }; } fi
+if test "$OBJCOPY" = "no"; then { { echo "$as_me:$LINENO: error: objcopy not found" >&5
+echo "$as_me: error: objcopy not found" >&2;}
+ { (exit 1); exit 1; }; } fi
+if test "$AR" = "no"; then { { echo "$as_me:$LINENO: error: ar not found" >&5
+echo "$as_me: error: ar not found" >&2;}
+ { (exit 1); exit 1; }; } fi
+
+if test "$MKDIR" = "no"; then { { echo "$as_me:$LINENO: error: mkdir not found" >&5
+echo "$as_me: error: mkdir not found" >&2;}
+ { (exit 1); exit 1; }; } fi
+if test "$RM" = "no"; then { { echo "$as_me:$LINENO: error: rm not found" >&5
+echo "$as_me: error: rm not found" >&2;}
+ { (exit 1); exit 1; }; } fi
+if test "$CP" = "no"; then { { echo "$as_me:$LINENO: error: cp not found" >&5
+echo "$as_me: error: cp not found" >&2;}
+ { (exit 1); exit 1; }; } fi
+if test "$LN" = "no"; then { { echo "$as_me:$LINENO: error: ln not found" >&5
+echo "$as_me: error: ln not found" >&2;}
+ { (exit 1); exit 1; }; } fi
+if test "$TAR" = "no"; then { { echo "$as_me:$LINENO: error: tar not found" >&5
+echo "$as_me: error: tar not found" >&2;}
+ { (exit 1); exit 1; }; } fi
+if test "$RPM" = "no"; then { { echo "$as_me:$LINENO: error: rpm not found" >&5
+echo "$as_me: error: rpm not found" >&2;}
+ { (exit 1); exit 1; }; } fi
+if test "$SED" = "no"; then { { echo "$as_me:$LINENO: error: sed not found" >&5
+echo "$as_me: error: sed not found" >&2;}
+ { (exit 1); exit 1; }; } fi
+if test "$FIND" = "no"; then { { echo "$as_me:$LINENO: error: find not found" >&5
+echo "$as_me: error: find not found" >&2;}
+ { (exit 1); exit 1; }; } fi
+if test "$XARGS" = "no"; then { { echo "$as_me:$LINENO: error: xargs not found" >&5
+echo "$as_me: error: xargs not found" >&2;}
+ { (exit 1); exit 1; }; } fi
+if test "$DIRNAME" = "no"; then { { echo "$as_me:$LINENO: error: dirname not found" >&5
+echo "$as_me: error: dirname not found" >&2;}
+ { (exit 1); exit 1; }; } fi
+
+
+
+
+
+
+
+
+
+
+ ac_config_files="$ac_config_files Makefile.conf"
+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 overridden 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 diff $cache_file confcache >/dev/null 2>&1; 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
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then we branch to the quote section. Otherwise,
+# look for a macro that doesn't take arguments.
+cat >confdef2opt.sed <<\_ACEOF
+t clear
+: clear
+s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\),-D\1=\2,g
+t quote
+s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\),-D\1=\2,g
+t quote
+d
+: quote
+s,[ `~#$^&*(){}\\|;'"<>?],\\&,g
+s,\[,\\&,g
+s,\],\\&,g
+s,\$,$$,g
+p
+_ACEOF
+# We use echo to avoid assuming a particular line-breaking character.
+# The extra dot is to prevent the shell from consuming trailing
+# line-breaks from the sub-command output. A line-break within
+# single-quotes doesn't work because, if this script is created in a
+# platform that uses two characters for line-breaks (e.g., DOS), tr
+# would break.
+ac_LF_and_DOT=`echo; echo .`
+DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'`
+rm -f confdef2opt.sed
+
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_i=`echo "$ac_i" |
+ sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+ # 2. Add them.
+ ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+ ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${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
+ac_cs_recheck=false
+ac_cs_silent=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=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$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" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.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
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ 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
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval 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="eval 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
+
+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 $as_me, which was
+generated by GNU Autoconf 2.59. 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
+ -q, --quiet do not print progress messages
+ -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
+
+Configuration files:
+$config_files
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.59,
+ with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2003 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[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ -*)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ *) # This is not an option, so the user has probably given explicit
+ # arguments.
+ ac_option=$1
+ ac_need_defaults=false;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --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 )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ ac_need_defaults=false;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # 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
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+ echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+ exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+
+
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+ case "$ac_config_target" in
+ # Handling of arguments.
+ "Makefile.conf" ) CONFIG_FILES="$CONFIG_FILES Makefile.conf" ;;
+ *) { { 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
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# 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.
+
+{
+ tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./confstat$$-$RANDOM
+ (umask 077 && mkdir $tmp)
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&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,@CPP@,$CPP,;t t
+s,@LD@,$LD,;t t
+s,@ac_ct_LD@,$ac_ct_LD,;t t
+s,@AS@,$AS,;t t
+s,@ac_ct_AS@,$ac_ct_AS,;t t
+s,@OBJCOPY@,$OBJCOPY,;t t
+s,@ac_ct_OBJCOPY@,$ac_ct_OBJCOPY,;t t
+s,@AR@,$AR,;t t
+s,@ac_ct_AR@,$ac_ct_AR,;t t
+s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t
+s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
+s,@INSTALL_DATA@,$INSTALL_DATA,;t t
+s,@MKDIR@,$MKDIR,;t t
+s,@RM@,$RM,;t t
+s,@CP@,$CP,;t t
+s,@LN@,$LN,;t t
+s,@TAR@,$TAR,;t t
+s,@RPMBUILD@,$RPMBUILD,;t t
+s,@SED@,$SED,;t t
+s,@FIND@,$FIND,;t t
+s,@XARGS@,$XARGS,;t t
+s,@DIRNAME@,$DIRNAME,;t t
+s,@EGREP@,$EGREP,;t t
+s,@BUILD_CC@,$BUILD_CC,;t t
+s,@BUILD_CFLAGS@,$BUILD_CFLAGS,;t t
+s,@EXTRA_CFLAGS@,$EXTRA_CFLAGS,;t t
+s,@ARCH@,$ARCH,;t t
+s,@OBJDIR@,$OBJDIR,;t t
+s,@INSTALL@,$INSTALL,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
+s,@LTLIBOBJS@,$LTLIBOBJS,;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'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ 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
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_builddir$INSTALL ;;
+ esac
+
+ # 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; }
+
+ 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
+_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
+
+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=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || 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 0000000..c77e4da
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,129 @@
+dnl
+dnl configure.ac for mkelfImage
+dnl
+dnl
+
+dnl ---Required
+AC_INIT(Makefile.conf.in)
+AC_CONFIG_AUX_DIR(./config)
+
+dnl -- Compilation platform configuration
+AC_CANONICAL_HOST
+dnl Currentl AC_CANONICAL_HOST is sufficient for my needs
+dnl as there are only a small number of targets that kexec
+dnl can support on a given host system. If it stops making
+dnl sense compile support for all possible targets a given
+dnl host can support AC_CANONICAL_TARGET may help
+dnl AC_CANONICAL_TARGET
+
+
+dnl Compute host cpu
+case $host_cpu in
+ i?86 )
+ host_cpu="i386"
+ ;;
+ powerpc )
+ host_cpu="ppc"
+ ;;
+ * )
+ host_cpu="$host_cpu"
+ ;;
+esac
+case $host_cpu in
+ i386|ppc|x86_64|alpha|ppc64|ia64)
+ ;;
+ * )
+ AC_MSG_ERROR([ unsupported architecture $host_cpu])
+ ;;
+esac
+ARCH=$host_cpu
+
+dnl ---Options
+
+OBJDIR=`pwd`/objdir
+if test "${host_alias}" ; then
+ OBJDIR="$OBJDIR-${host_alias}"
+fi
+EXTRA_CFLAGS=""
+AC_ARG_WITH([objdir], AC_HELP_STRING([--with-objdir=<dir>],[select directory for object files]),
+ [ OBJDIR="$withval" ], [ OBJDIR="$OBJDIR" ])
+
+AC_ARG_WITH([gamecube], AC_HELP_STRING([--with-gamecube],[enable gamecube support]),
+ [ EXTRA_CFLAGS="$EXTRA_CFLAGS -DCONFIG_GAMECUBE=1" ])
+
+AC_ARG_WITH([zlib], AC_HELP_STRING([--without-zlib],[disable gamecube support]),
+ [ with_zlib="$withval"], [ with_zlib=yes ] )
+
+dnl ---Programs
+dnl To specify a different compiler, just 'export CC=/path/to/compiler'
+
+AC_PROG_CC
+
+if test "${build}" != "${host}" ; then
+ BUILD_CC=${CC_FOR_BUILD-gcc}
+else
+ BUILD_CC="\$(CC)"
+fi
+
+
+dnl Find the compiler tool chain
+AC_PROG_CPP
+AC_CHECK_TOOL([LD], ld, "no", $PATH)
+AC_CHECK_TOOL([AS], as, "no", $PATH)
+AC_CHECK_TOOL([OBJCOPY], objcopy, "no", $PATH)
+AC_CHECK_TOOL([AR], ar, "", $PATH)
+
+dnl Find the helper functions
+AC_PROG_INSTALL
+AC_CHECK_PROG([MKDIR], mkdir, mkdir, "no", [$PATH])
+AC_CHECK_PROG([RM], rm, rm, "no", [$PATH])
+AC_CHECK_PROG([CP], cp, cp, "no", [$PATH])
+AC_CHECK_PROG([LN], ln, ln, "no", [$PATH])
+AC_CHECK_PROG([TAR], tar, tar, "no", [$PATH])
+AC_CHECK_PROG([RPMBUILD], rpmbuild, rpmbuild, "no", [$PATH])
+AC_CHECK_PROG([SED], sed, sed, "no", [$PATH])
+AC_CHECK_PROG([FIND], find, find, "no", [$PATH])
+AC_CHECK_PROG([XARGS], xargs, xargs, "no", [$PATH])
+AC_CHECK_PROG([DIRNAME], dirname, dirname, "no", [$PATH])
+
+dnl See if I have a usable copy of zlib available
+if test "$with_zlib" = yes ; then
+ AC_CHECK_HEADER(zlib.h, AC_CHECK_LIB(z, inflateInit_, [AC_DEFINE(HAVE_ZLIB_H, 1) LIBS="$LIBS -lz"]))
+fi
+
+dnl ---Hard codes
+
+CFLAGS='-Wall -g -fno-strict-aliasing $(CPPFLAGS)'
+BUILD_CFLAGS='-O2 -Wall $(CPPFLAGS)'
+
+dnl ---Sanity checks
+if test "$CC" = "no"; then AC_MSG_ERROR([cc not found]) fi
+if test "$CPP" = "no"; then AC_MSG_ERROR([cpp not found]) fi
+if test "$LD" = "no"; then AC_MSG_ERROR([ld not found]) fi
+if test "$AS" = "no"; then AC_MSG_ERROR([as not found]) fi
+if test "$OBJCOPY" = "no"; then AC_MSG_ERROR([objcopy not found]) fi
+if test "$AR" = "no"; then AC_MSG_ERROR([ar not found]) fi
+
+if test "$MKDIR" = "no"; then AC_MSG_ERROR([ mkdir not found]) fi
+if test "$RM" = "no"; then AC_MSG_ERROR([ rm not found]) fi
+if test "$CP" = "no"; then AC_MSG_ERROR([ cp not found]) fi
+if test "$LN" = "no"; then AC_MSG_ERROR([ ln not found]) fi
+if test "$TAR" = "no"; then AC_MSG_ERROR([ tar not found]) fi
+if test "$RPM" = "no"; then AC_MSG_ERROR([ rpm not found]) fi
+if test "$SED" = "no"; then AC_MSG_ERROR([ sed not found]) fi
+if test "$FIND" = "no"; then AC_MSG_ERROR([ find not found]) fi
+if test "$XARGS" = "no"; then AC_MSG_ERROR([ xargs not found]) fi
+if test "$DIRNAME" = "no"; then AC_MSG_ERROR([ dirname not found]) fi
+
+dnl ---Output variables...
+
+AC_SUBST([BUILD_CC])
+AC_SUBST([BUILD_CFLAGS])
+
+AC_SUBST([EXTRA_CFLAGS])
+AC_SUBST([ARCH])
+AC_SUBST([OBJDIR])
+AC_SUBST([INSTALL])
+
+dnl ---Output
+AC_OUTPUT([Makefile.conf])
diff --git a/doc/linux-i386-boot.txt b/doc/linux-i386-boot.txt
new file mode 100644
index 0000000..afa6d12
--- /dev/null
+++ b/doc/linux-i386-boot.txt
@@ -0,0 +1,438 @@
+ THE LINUX/I386 BOOT PROTOCOL
+ ----------------------------
+
+ H. Peter Anvin <hpa@zytor.com>
+ Last update 2002-01-01
+
+On the i386 platform, the Linux kernel uses a rather complicated boot
+convention. This has evolved partially due to historical aspects, as
+well as the desire in the early days to have the kernel itself be a
+bootable image, the complicated PC memory model and due to changed
+expectations in the PC industry caused by the effective demise of
+real-mode DOS as a mainstream operating system.
+
+Currently, four versions of the Linux/i386 boot protocol exist.
+
+Old kernels: zImage/Image support only. Some very early kernels
+ may not even support a command line.
+
+Protocol 2.00: (Kernel 1.3.73) Added bzImage and initrd support, as
+ well as a formalized way to communicate between the
+ boot loader and the kernel. setup.S made relocatable,
+ although the traditional setup area still assumed
+ writable.
+
+Protocol 2.01: (Kernel 1.3.76) Added a heap overrun warning.
+
+Protocol 2.02: (Kernel 2.4.0-test3-pre3) New command line protocol.
+ Lower the conventional memory ceiling. No overwrite
+ of the traditional setup area, thus making booting
+ safe for systems which use the EBDA from SMM or 32-bit
+ BIOS entry points. zImage deprecated but still
+ supported.
+
+Protocol 2.03: (Kernel 2.4.18-pre1) Explicitly makes the highest possible
+ initrd address available to the bootloader.
+
+
+**** MEMORY LAYOUT
+
+The traditional memory map for the kernel loader, used for Image or
+zImage kernels, typically looks like:
+
+ | |
+0A0000 +------------------------+
+ | Reserved for BIOS | Do not use. Reserved for BIOS EBDA.
+09A000 +------------------------+
+ | Stack/heap/cmdline | For use by the kernel real-mode code.
+098000 +------------------------+
+ | Kernel setup | The kernel real-mode code.
+090200 +------------------------+
+ | Kernel boot sector | The kernel legacy boot sector.
+090000 +------------------------+
+ | Protected-mode kernel | The bulk of the kernel image.
+010000 +------------------------+
+ | Boot loader | <- Boot sector entry point 0000:7C00
+001000 +------------------------+
+ | Reserved for MBR/BIOS |
+000800 +------------------------+
+ | Typically used by MBR |
+000600 +------------------------+
+ | BIOS use only |
+000000 +------------------------+
+
+
+When using bzImage, the protected-mode kernel was relocated to
+0x100000 ("high memory"), and the kernel real-mode block (boot sector,
+setup, and stack/heap) was made relocatable to any address between
+0x10000 and end of low memory. Unfortunately, in protocols 2.00 and
+2.01 the command line is still required to live in the 0x9XXXX memory
+range, and that memory range is still overwritten by the early kernel.
+The 2.02 protocol resolves that problem.
+
+It is desirable to keep the "memory ceiling" -- the highest point in
+low memory touched by the boot loader -- as low as possible, since
+some newer BIOSes have begun to allocate some rather large amounts of
+memory, called the Extended BIOS Data Area, near the top of low
+memory. The boot loader should use the "INT 12h" BIOS call to verify
+how much low memory is available.
+
+Unfortunately, if INT 12h reports that the amount of memory is too
+low, there is usually nothing the boot loader can do but to report an
+error to the user. The boot loader should therefore be designed to
+take up as little space in low memory as it reasonably can. For
+zImage or old bzImage kernels, which need data written into the
+0x90000 segment, the boot loader should make sure not to use memory
+above the 0x9A000 point; too many BIOSes will break above that point.
+
+
+**** THE REAL-MODE KERNEL HEADER
+
+In the following text, and anywhere in the kernel boot sequence, "a
+sector" refers to 512 bytes. It is independent of the actual sector
+size of the underlying medium.
+
+The first step in loading a Linux kernel should be to load the
+real-mode code (boot sector and setup code) and then examine the
+following header at offset 0x01f1. The real-mode code can total up to
+32K, although the boot loader may choose to load only the first two
+sectors (1K) and then examine the bootup sector size.
+
+The header looks like:
+
+Offset Proto Name Meaning
+/Size
+
+01F1/1 ALL setup_sects The size of the setup in sectors
+01F2/2 ALL root_flags If set, the root is mounted readonly
+01F4/2 ALL syssize DO NOT USE - for bootsect.S use only
+01F6/2 ALL swap_dev DO NOT USE - obsolete
+01F8/2 ALL ram_size DO NOT USE - for bootsect.S use only
+01FA/2 ALL vid_mode Video mode control
+01FC/2 ALL root_dev Default root device number
+01FE/2 ALL boot_flag 0xAA55 magic number
+0200/2 2.00+ jump Jump instruction
+0202/4 2.00+ header Magic signature "HdrS"
+0206/2 2.00+ version Boot protocol version supported
+0208/4 2.00+ realmode_swtch Boot loader hook (see below)
+020C/2 2.00+ start_sys The load-low segment (0x1000) (obsolete)
+020E/2 2.00+ kernel_version Pointer to kernel version string
+0210/1 2.00+ type_of_loader Boot loader identifier
+0211/1 2.00+ loadflags Boot protocol option flags
+0212/2 2.00+ setup_move_size Move to high memory size (used with hooks)
+0214/4 2.00+ code32_start Boot loader hook (see below)
+0218/4 2.00+ ramdisk_image initrd load address (set by boot loader)
+021C/4 2.00+ ramdisk_size initrd size (set by boot loader)
+0220/4 2.00+ bootsect_kludge DO NOT USE - for bootsect.S use only
+0224/2 2.01+ heap_end_ptr Free memory after setup end
+0226/2 N/A pad1 Unused
+0228/4 2.02+ cmd_line_ptr 32-bit pointer to the kernel command line
+022C/4 2.03+ initrd_addr_max Highest legal initrd address
+
+For backwards compatibility, if the setup_sects field contains 0, the
+real value is 4.
+
+If the "HdrS" (0x53726448) magic number is not found at offset 0x202,
+the boot protocol version is "old". Loading an old kernel, the
+following parameters should be assumed:
+
+ Image type = zImage
+ initrd not supported
+ Real-mode kernel must be located at 0x90000.
+
+Otherwise, the "version" field contains the protocol version,
+e.g. protocol version 2.01 will contain 0x0201 in this field. When
+setting fields in the header, you must make sure only to set fields
+supported by the protocol version in use.
+
+The "kernel_version" field, if set to a nonzero value, contains a
+pointer to a null-terminated human-readable kernel version number
+string, less 0x200. This can be used to display the kernel version to
+the user. This value should be less than (0x200*setup_sects). For
+example, if this value is set to 0x1c00, the kernel version number
+string can be found at offset 0x1e00 in the kernel file. This is a
+valid value if and only if the "setup_sects" field contains the value
+14 or higher.
+
+Most boot loaders will simply load the kernel at its target address
+directly. Such boot loaders do not need to worry about filling in
+most of the fields in the header. The following fields should be
+filled out, however:
+
+ vid_mode:
+ Please see the section on SPECIAL COMMAND LINE OPTIONS.
+
+ type_of_loader:
+ If your boot loader has an assigned id (see table below), enter
+ 0xTV here, where T is an identifier for the boot loader and V is
+ a version number. Otherwise, enter 0xFF here.
+
+ Assigned boot loader ids:
+ 0 LILO
+ 1 Loadlin
+ 2 bootsect-loader
+ 3 SYSLINUX
+ 4 EtherBoot
+
+ Please contact <hpa@zytor.com> if you need a bootloader ID
+ value assigned.
+
+ loadflags, heap_end_ptr:
+ If the protocol version is 2.01 or higher, enter the
+ offset limit of the setup heap into heap_end_ptr and set the
+ 0x80 bit (CAN_USE_HEAP) of loadflags. heap_end_ptr appears to
+ be relative to the start of setup (offset 0x0200).
+
+ setup_move_size:
+ When using protocol 2.00 or 2.01, if the real mode
+ kernel is not loaded at 0x90000, it gets moved there later in
+ the loading sequence. Fill in this field if you want
+ additional data (such as the kernel command line) moved in
+ addition to the real-mode kernel itself.
+
+ ramdisk_image, ramdisk_size:
+ If your boot loader has loaded an initial ramdisk (initrd),
+ set ramdisk_image to the 32-bit pointer to the ramdisk data
+ and the ramdisk_size to the size of the ramdisk data.
+
+ The initrd should typically be located as high in memory as
+ possible, as it may otherwise get overwritten by the early
+ kernel initialization sequence. However, it must never be
+ located above the address specified in the initrd_addr_max
+ field. The initrd should be at least 4K page aligned.
+
+ cmd_line_ptr:
+ If the protocol version is 2.02 or higher, this is a 32-bit
+ pointer to the kernel command line. The kernel command line
+ can be located anywhere between the end of setup and 0xA0000.
+ Fill in this field even if your boot loader does not support a
+ command line, in which case you can point this to an empty
+ string (or better yet, to the string "auto".) If this field
+ is left at zero, the kernel will assume that your boot loader
+ does not support the 2.02+ protocol.
+
+ ramdisk_max:
+ The maximum address that may be occupied by the initrd
+ contents. For boot protocols 2.02 or earlier, this field is
+ not present, and the maximum address is 0x37FFFFFF. (This
+ address is defined as the address of the highest safe byte, so
+ if your ramdisk is exactly 131072 bytes long and this field is
+ 0x37FFFFFF, you can start your ramdisk at 0x37FE0000.)
+
+
+**** THE KERNEL COMMAND LINE
+
+The kernel command line has become an important way for the boot
+loader to communicate with the kernel. Some of its options are also
+relevant to the boot loader itself, see "special command line options"
+below.
+
+The kernel command line is a null-terminated string up to 255
+characters long, plus the final null.
+
+If the boot protocol version is 2.02 or later, the address of the
+kernel command line is given by the header field cmd_line_ptr (see
+above.)
+
+If the protocol version is *not* 2.02 or higher, the kernel
+command line is entered using the following protocol:
+
+ At offset 0x0020 (word), "cmd_line_magic", enter the magic
+ number 0xA33F.
+
+ At offset 0x0022 (word), "cmd_line_offset", enter the offset
+ of the kernel command line (relative to the start of the
+ real-mode kernel).
+
+ The kernel command line *must* be within the memory region
+ covered by setup_move_size, so you may need to adjust this
+ field.
+
+
+**** SAMPLE BOOT CONFIGURATION
+
+As a sample configuration, assume the following layout of the real
+mode segment:
+
+ 0x0000-0x7FFF Real mode kernel
+ 0x8000-0x8FFF Stack and heap
+ 0x9000-0x90FF Kernel command line
+
+Such a boot loader should enter the following fields in the header:
+
+ unsigned long base_ptr; /* base address for real-mode segment */
+
+ if ( setup_sects == 0 ) {
+ setup_sects = 4;
+ }
+
+ if ( protocol >= 0x0200 ) {
+ type_of_loader = <type code>;
+ if ( loading_initrd ) {
+ ramdisk_image = <initrd_address>;
+ ramdisk_size = <initrd_size>;
+ }
+ if ( protocol >= 0x0201 ) {
+ heap_end_ptr = 0x9000 - 0x200;
+ loadflags |= 0x80; /* CAN_USE_HEAP */
+ }
+ if ( protocol >= 0x0202 ) {
+ cmd_line_ptr = base_ptr + 0x9000;
+ } else {
+ cmd_line_magic = 0xA33F;
+ cmd_line_offset = 0x9000;
+ setup_move_size = 0x9100;
+ }
+ } else {
+ /* Very old kernel */
+
+ cmd_line_magic = 0xA33F;
+ cmd_line_offset = 0x9000;
+
+ /* A very old kernel MUST have its real-mode code
+ loaded at 0x90000 */
+
+ if ( base_ptr != 0x90000 ) {
+ /* Copy the real-mode kernel */
+ memcpy(0x90000, base_ptr, (setup_sects+1)*512);
+ /* Copy the command line */
+ memcpy(0x99000, base_ptr+0x9000, 256);
+
+ base_ptr = 0x90000; /* Relocated */
+ }
+
+ /* It is recommended to clear memory up to the 32K mark */
+ memset(0x90000 + (setup_sects+1)*512, 0,
+ (64-(setup_sects+1))*512);
+ }
+
+
+**** LOADING THE REST OF THE KERNEL
+
+The non-real-mode kernel starts at offset (setup_sects+1)*512 in the
+kernel file (again, if setup_sects == 0 the real value is 4.) It
+should be loaded at address 0x10000 for Image/zImage kernels and
+0x100000 for bzImage kernels.
+
+The kernel is a bzImage kernel if the protocol >= 2.00 and the 0x01
+bit (LOAD_HIGH) in the loadflags field is set:
+
+ is_bzImage = (protocol >= 0x0200) && (loadflags & 0x01);
+ load_address = is_bzImage ? 0x100000 : 0x10000;
+
+Note that Image/zImage kernels can be up to 512K in size, and thus use
+the entire 0x10000-0x90000 range of memory. This means it is pretty
+much a requirement for these kernels to load the real-mode part at
+0x90000. bzImage kernels allow much more flexibility.
+
+
+**** SPECIAL COMMAND LINE OPTIONS
+
+If the command line provided by the boot loader is entered by the
+user, the user may expect the following command line options to work.
+They should normally not be deleted from the kernel command line even
+though not all of them are actually meaningful to the kernel. Boot
+loader authors who need additional command line options for the boot
+loader itself should get them registered in
+Documentation/kernel-parameters.txt to make sure they will not
+conflict with actual kernel options now or in the future.
+
+ vga=<mode>
+ <mode> here is either an integer (in C notation, either
+ decimal, octal, or hexadecimal) or one of the strings
+ "normal" (meaning 0xFFFF), "ext" (meaning 0xFFFE) or "ask"
+ (meaning 0xFFFD). This value should be entered into the
+ vid_mode field, as it is used by the kernel before the command
+ line is parsed.
+
+ mem=<size>
+ <size> is an integer in C notation optionally followed by K, M
+ or G (meaning << 10, << 20 or << 30). This specifies the end
+ of memory to the kernel. This affects the possible placement
+ of an initrd, since an initrd should be placed near end of
+ memory. Note that this is an option to *both* the kernel and
+ the bootloader!
+
+ initrd=<file>
+ An initrd should be loaded. The meaning of <file> is
+ obviously bootloader-dependent, and some boot loaders
+ (e.g. LILO) do not have such a command.
+
+In addition, some boot loaders add the following options to the
+user-specified command line:
+
+ BOOT_IMAGE=<file>
+ The boot image which was loaded. Again, the meaning of <file>
+ is obviously bootloader-dependent.
+
+ auto
+ The kernel was booted without explicit user intervention.
+
+If these options are added by the boot loader, it is highly
+recommended that they are located *first*, before the user-specified
+or configuration-specified command line. Otherwise, "init=/bin/sh"
+gets confused by the "auto" option.
+
+
+**** RUNNING THE KERNEL
+
+The kernel is started by jumping to the kernel entry point, which is
+located at *segment* offset 0x20 from the start of the real mode
+kernel. This means that if you loaded your real-mode kernel code at
+0x90000, the kernel entry point is 9020:0000.
+
+At entry, ds = es = ss should point to the start of the real-mode
+kernel code (0x9000 if the code is loaded at 0x90000), sp should be
+set up properly, normally pointing to the top of the heap, and
+interrupts should be disabled. Furthermore, to guard against bugs in
+the kernel, it is recommended that the boot loader sets fs = gs = ds =
+es = ss.
+
+In our example from above, we would do:
+
+ /* Note: in the case of the "old" kernel protocol, base_ptr must
+ be == 0x90000 at this point; see the previous sample code */
+
+ seg = base_ptr >> 4;
+
+ cli(); /* Enter with interrupts disabled! */
+
+ /* Set up the real-mode kernel stack */
+ _SS = seg;
+ _SP = 0x9000; /* Load SP immediately after loading SS! */
+
+ _DS = _ES = _FS = _GS = seg;
+ jmp_far(seg+0x20, 0); /* Run the kernel */
+
+If your boot sector accesses a floppy drive, it is recommended to
+switch off the floppy motor before running the kernel, since the
+kernel boot leaves interrupts off and thus the motor will not be
+switched off, especially if the loaded kernel has the floppy driver as
+a demand-loaded module!
+
+
+**** ADVANCED BOOT TIME HOOKS
+
+If the boot loader runs in a particularly hostile environment (such as
+LOADLIN, which runs under DOS) it may be impossible to follow the
+standard memory location requirements. Such a boot loader may use the
+following hooks that, if set, are invoked by the kernel at the
+appropriate time. The use of these hooks should probably be
+considered an absolutely last resort!
+
+IMPORTANT: All the hooks are required to preserve %esp, %ebp, %esi and
+%edi across invocation.
+
+ realmode_swtch:
+ A 16-bit real mode far subroutine invoked immediately before
+ entering protected mode. The default routine disables NMI, so
+ your routine should probably do so, too.
+
+ code32_start:
+ A 32-bit flat-mode routine *jumped* to immediately after the
+ transition to protected mode, but before the kernel is
+ uncompressed. No segments, except CS, are set up; you should
+ set them up to KERNEL_DS (0x18) yourself.
+
+ After completing your hook, you should jump to the address
+ that was in this field before your boot loader overwrote it.
diff --git a/doc/linux-i386-zero-page.txt b/doc/linux-i386-zero-page.txt
new file mode 100644
index 0000000..bbdf726
--- /dev/null
+++ b/doc/linux-i386-zero-page.txt
@@ -0,0 +1,79 @@
+Summary of boot_params layout (kernel point of view)
+ ( collected by Hans Lermen and Martin Mares )
+
+The contents of boot_params are used to pass parameters from the
+16-bit realmode code of the kernel to the 32-bit part. References/settings
+to it mainly are in:
+
+ arch/i386/boot/setup.S
+ arch/i386/boot/video.S
+ arch/i386/kernel/head.S
+ arch/i386/kernel/setup.c
+
+
+Offset Type Description
+------ ---- -----------
+ 0 32 bytes struct screen_info, SCREEN_INFO
+ ATTENTION, overlaps the following !!!
+ 2 unsigned short EXT_MEM_K, extended memory size in Kb (from int 0x15)
+ 0x20 unsigned short CL_MAGIC, commandline magic number (=0xA33F)
+ 0x22 unsigned short CL_OFFSET, commandline offset
+ Address of commandline is calculated:
+ 0x90000 + contents of CL_OFFSET
+ (only taken, when CL_MAGIC = 0xA33F)
+ 0x40 20 bytes struct apm_bios_info, APM_BIOS_INFO
+ 0x60 16 bytes Intel SpeedStep (IST) BIOS support information
+ 0x80 16 bytes hd0-disk-parameter from intvector 0x41
+ 0x90 16 bytes hd1-disk-parameter from intvector 0x46
+
+ 0xa0 16 bytes System description table truncated to 16 bytes.
+ ( struct sys_desc_table_struct )
+ 0xb0 - 0x1c3 Free. Add more parameters here if you really need them.
+
+0x1c4 unsigned long EFI system table pointer
+0x1c8 unsigned long EFI memory descriptor size
+0x1cc unsigned long EFI memory descriptor version
+0x1d0 unsigned long EFI memory descriptor map pointer
+0x1d4 unsigned long EFI memory descriptor map size
+0x1e0 unsigned long ALT_MEM_K, alternative mem check, in Kb
+0x1e8 char number of entries in E820MAP (below)
+0x1e9 unsigned char number of entries in EDDBUF (below)
+0x1ea unsigned char number of entries in EDD_MBR_SIG_BUFFER (below)
+0x1f1 char size of setup.S, number of sectors
+0x1f2 unsigned short MOUNT_ROOT_RDONLY (if !=0)
+0x1f4 unsigned short size of compressed kernel-part in the
+ (b)zImage-file (in 16 byte units, rounded up)
+0x1f6 unsigned short swap_dev (unused AFAIK)
+0x1f8 unsigned short RAMDISK_FLAGS
+0x1fa unsigned short VGA-Mode (old one)
+0x1fc unsigned short ORIG_ROOT_DEV (high=Major, low=minor)
+0x1ff char AUX_DEVICE_INFO
+
+0x200 short jump to start of setup code aka "reserved" field.
+0x202 4 bytes Signature for SETUP-header, ="HdrS"
+0x206 unsigned short Version number of header format
+ Current version is 0x0201...
+0x208 8 bytes (used by setup.S for communication with boot loaders,
+ look there)
+0x210 char LOADER_TYPE, = 0, old one
+ else it is set by the loader:
+ 0xTV: T=0 for LILO
+ 1 for Loadlin
+ 2 for bootsect-loader
+ 3 for SYSLINUX
+ 4 for ETHERBOOT
+ V = version
+0x211 char loadflags:
+ bit0 = 1: kernel is loaded high (bzImage)
+ bit7 = 1: Heap and pointer (see below) set by boot
+ loader.
+0x212 unsigned short (setup.S)
+0x214 unsigned long KERNEL_START, where the loader started the kernel
+0x218 unsigned long INITRD_START, address of loaded ramdisk image
+0x21c unsigned long INITRD_SIZE, size in bytes of ramdisk image
+0x220 4 bytes (setup.S)
+0x224 unsigned short setup.S heap end pointer
+0x290 - 0x2cf EDD_MBR_SIG_BUFFER (edd.S)
+0x2d0 - 0x600 E820MAP
+0x600 - 0x7ff EDDBUF (edd.S) for disk signature read sector
+0x600 - 0x7eb EDDBUF (edd.S) for edd data
diff --git a/doc/multiboot.html b/doc/multiboot.html
new file mode 100644
index 0000000..bd41444
--- /dev/null
+++ b/doc/multiboot.html
@@ -0,0 +1,664 @@
+<HTML>
+
+<HEAD>
+<TITLE>Multiboot Standard</TITLE>
+</HEAD>
+
+<BODY>
+
+<CENTER><H1>Multiboot Standard</H1></CENTER>
+<CENTER><H3>Version 0.6</H3></CENTER>
+
+<HR>
+
+<H2>Contents</H2>
+
+<UL>
+<LI> <A HREF="#motivation">Motivation</A>
+<LI> <A HREF="#terminology">Terminology</A>
+<LI> <A HREF="#scope">Scope and Requirements</A>
+<LI> <A HREF="#details">Details</A>
+<LI> <A HREF="#author">Authors</A>
+<LI> <B>NOTE: The following items are not part of the standards document,
+but are included for prospective OS and bootloader writers.</B>
+<LI> <A HREF="#notes">Notes on PCs</A>
+<LI> <A HREF="#example_os">Example OS Code</A>
+<LI> <A HREF="#example_boot">Example Bootloader Code</A>
+</UL>
+
+<HR>
+
+<H2><A NAME="motivation">Motivation</A></H2>
+
+Every OS ever created tends to have its own boot loader. Installing a new
+OS on a machine generally involves installing a whole new set of boot
+mechanisms, each with completely different install-time and boot-time user
+interfaces. Getting multiple operating systems to coexist reliably on one
+machine through typical "chaining" mechanisms can be a nightmare. There is
+little or no choice of boot loaders for a particular operating system - if
+the one that comes with the OS doesn't do exactly what you want, or doesn't
+work on your machine, you're screwed.<P>
+
+While we may not be able to fix this problem in existing commercial
+operating systems, it shouldn't be too difficult for a few people in the
+free OS communities to put their heads together and solve this problem for
+the popular free operating systems. That's what this standard aims for.
+Basically, it specifies an interface between a boot loader and a operating
+system, such that any complying boot loader should be able to load any
+complying operating system. This standard does NOT specify how boot
+loaders should work - only how they must interface with the OS being
+loaded.<P>
+
+<HR>
+
+<H2><A NAME="terminology">Terminology</A></H2>
+
+Throughout this document, the term "boot loader" means whatever program or
+set of programs loads the image of the final operating system to be run on
+the machine. The boot loader may itself consist of several stages, but
+that is an implementation detail not relevant to this standard. Only the
+"final" stage of the boot loader - the stage that eventually transfers
+control to the OS - needs to follow the rules specified in this document
+in order to be "MultiBoot compliant"; earlier boot loader stages can be
+designed in whatever way is most convenient.<P>
+
+The term "OS image" is used to refer to the initial binary image that the
+boot loader loads into memory and transfers control to to start the OS.
+The OS image is typically an executable containing the OS kernel.<P>
+
+The term "boot module" refers to other auxiliary files that the boot loader
+loads into memory along with the OS image, but does not interpret in any
+way other than passing their locations to the OS when it is invoked.<P>
+
+<HR>
+
+<H2><A NAME="scope">Scope and Requirements</A></H2>
+
+<H3>Architectures</H3>
+
+This standard is primarily targetted at PC's, since they are the most
+common and have the largest variety of OS's and boot loaders. However, to
+the extent that certain other architectures may need a boot standard and do
+not have one already, a variation of this standard, stripped of the
+x86-specific details, could be adopted for them as well.<P>
+
+<H3>Operating systems</H3>
+
+This standard is targetted toward free 32-bit operating systems that can be
+fairly easily modified to support the standard without going through lots of
+bureaucratic rigmarole. The particular free OS's that this standard is
+being primarily designed for are Linux, FreeBSD, NetBSD, Mach, and VSTa.
+It is hoped that other emerging free OS's will adopt it from the start, and
+thus immediately be able to take advantage of existing boot loaders. It
+would be nice if commercial operating system vendors eventually adopted
+this standard as well, but that's probably a pipe dream.<P>
+
+<H3>Boot sources</H3>
+
+It should be possible to write compliant boot loaders that
+load the OS image from a variety of sources, including floppy disk, hard
+disk, and across a network.<P>
+
+Disk-based boot loaders may use a variety of techniques to find the
+relevant OS image and boot module data on disk, such as by interpretation
+of specific file systems (e.g. the BSD/Mach boot loader), using
+precalculated "block lists" (e.g. LILO), loading from a special "boot
+partition" (e.g. OS/2), or even loading from within another operating
+system (e.g. the VSTa boot code, which loads from DOS). Similarly,
+network-based boot loaders could use a variety of network hardware and
+protocols.<P>
+
+It is hoped that boot loaders will be created that support multiple loading
+mechanisms, increasing their portability, robustness, and
+user-friendliness.<P>
+
+<H3>Boot-time configuration</H3>
+
+It is often necessary for one reason or another for the user to be able to
+provide some configuration information to the OS dynamically at boot time.
+While this standard should not dictate how this configuration information
+is obtained by the boot loader, it should provide a standard means for the
+boot loader to pass such information to the OS.<P>
+
+<H3>Convenience to the OS</H3>
+
+OS images should be easy to generate. Ideally, an OS image should simply
+be an ordinary 32-bit executable file in whatever file format the OS
+normally uses. It should be possible to 'nm' or disassemble OS images just
+like normal executables. Specialized tools should not be needed to create
+OS images in a "special" file format. If this means shifting some work
+from the OS to the boot loader, that is probably appropriate, because all
+the memory consumed by the boot loader will typically be made available
+again after the boot process is created, whereas every bit of code in the
+OS image typically has to remain in memory forever. The OS should not have
+to worry about getting into 32-bit mode initially, because mode switching
+code generally needs to be in the boot loader anyway in order to load OS
+data above the 1MB boundary, and forcing the OS to do this makes creation
+of OS images much more difficult.<P>
+
+Unfortunately, there is a horrendous variety of executable file formats
+even among free Unix-like PC-based OS's - generally a different format for
+each OS. Most of the relevant free OS's use some variant of a.out format,
+but some are moving to ELF. It is highly desirable for boot loaders not to
+have to be able to interpret all the different types of executable file
+formats in existence in order to load the OS image - otherwise the boot
+loader effectively becomes OS-specific again.<P>
+
+This standard adopts a compromise solution to this problem.
+MultiBoot compliant boot images always either (a) are in ELF format, or (b)
+contain a "magic MultiBoot header", described below, which allows the boot
+loader to load the image without having to understand numerous a.out
+variants or other executable formats. This magic header does not need
+to be at the very beginning of the executable file, so kernel images can
+still conform to the local a.out format variant in addition to being
+MultiBoot compliant.<P>
+
+<H3>Boot modules</H3>
+
+Many modern operating system kernels, such as those of VSTa and Mach, do
+not by themselves contain enough mechanism to get the system fully
+operational: they require the presence of additional software modules at
+boot time in order to access devices, mount file systems, etc. While these
+additional modules could be embedded in the main OS image along with the
+kernel itself, and the resulting image be split apart manually by the OS
+when it receives control, it is often more flexible, more space-efficient,
+and more convenient to the OS and user if the boot loader can load these
+additional modules independently in the first place.<P>
+
+Thus, this standard should provide a standard method for a boot loader to
+indicate to the OS what auxiliary boot modules were loaded, and where they
+can be found. Boot loaders don't have to support multiple boot modules,
+but they are strongly encouraged to, because some OS's will be unable to
+boot without them.<P>
+
+<HR>
+
+<H2><A NAME="details">Details</H2>
+
+There are three main aspects of the boot-loader/OS image interface this
+standard must specify:<P>
+
+<UL>
+<LI>The format of the OS image as seen by the boot loader.
+<LI>The state of the machine when the boot loader starts the OS.
+<LI>The format of the information passed by the boot loader to the OS.
+</UL>
+
+<H3>OS Image Format</H3>
+
+An OS image is generally just an ordinary 32-bit executable file in the
+standard format for that particular OS, except that it may be linked at a
+non-default load address to avoid loading on top of the PC's I/O region
+or other reserved areas, and of course it can't use shared libraries or
+other fancy features. Initially, only images in a.out format are
+supported; ELF support will probably later be specified in the standard.<P>
+
+Unfortunately, the exact meaning of the text, data, bss, and entry fields
+of a.out headers tends to vary widely between different executable flavors,
+and it is sometimes very difficult to distinguish one flavor from another
+(e.g. Linux ZMAGIC executables and Mach ZMAGIC executables). Furthermore,
+there is no simple, reliable way of determining at what address in memory
+the text segment is supposed to start. Therefore, this standard requires
+that an additional header, known as a 'multiboot_header', appear somewhere
+near the beginning of the executable file. In general it should come "as
+early as possible", and is typically embedded in the beginning of the text
+segment after the "real" executable header. It _must_ be contained
+completely within the first 8192 bytes of the executable file, and must be
+longword (32-bit) aligned. These rules allow the boot loader to find and
+synchronize with the text segment in the a.out file without knowing
+beforehand the details of the a.out variant. The layout of the header is
+as follows:<P>
+
+<pre>
+ +-------------------+
+0 | magic: 0x1BADB002 | (required)
+4 | flags | (required)
+8 | checksum | (required)
+ +-------------------+
+8 | header_addr | (present if flags[16] is set)
+12 | load_addr | (present if flags[16] is set)
+16 | load_end_addr | (present if flags[16] is set)
+20 | bss_end_addr | (present if flags[16] is set)
+24 | entry_addr | (present if flags[16] is set)
+ +-------------------+
+</pre>
+
+All fields are in little-endian byte order, of course. The first field is
+the magic number identifying the header, which must be the hex value
+0x1BADB002.<P>
+
+The flags field specifies features that the OS image requests or requires
+of the boot loader. Bits 0-15 indicate requirements; if the boot loader
+sees any of these bits set but doesn't understand the flag or can't fulfill
+the requirements it indicates for some reason, it must notify the user and
+fail to load the OS image. Bits 16-31 indicate optional features; if any
+bits in this range are set but the boot loader doesn't understand them, it
+can simply ignore them and proceed as usual. Naturally, all
+as-yet-undefined bits in the flags word must be set to zero in OS
+images. This way, the flags fields serves for version control as well as
+simple feature selection.<P>
+
+If bit 0 in the flags word is set, then all boot modules loaded along with
+the OS must be aligned on page (4KB) boundaries. Some OS's expect to be
+able to map the pages containing boot modules directly into a paged address
+space during startup, and thus need the boot modules to be page-aligned.<P>
+
+If bit 1 in the flags word is set, then information on available memory
+via at least the 'mem_*' fields of the multiboot_info structure defined
+below must be included. If the bootloader is capable of passing a memory
+map (the 'mmap_*' fields) and one exists, then it must be included as
+well.<P>
+
+If bit 16 in the flags word is set, then the fields at offsets 8-24 in the
+multiboot_header are valid, and the boot loader should use them instead of
+the fields in the actual executable header to calculate where to load the
+OS image. This information does not need to be provided if the kernel
+image is in ELF format, but it should be provided if the images is in a.out
+format or in some other format. Compliant boot loaders must be able to
+load images that either are in ELF format or contain the load address
+information embedded in the multiboot_header; they may also directly
+support other executable formats, such as particular a.out variants, but
+are not required to.<P>
+
+All of the address fields enabled by flag bit 16 are physical addresses.
+The meaning of each is as follows:<P>
+
+<UL>
+<LI><B>header_addr</B> -- Contains the address corresponding to the
+beginning of the multiboot_header - the physical memory location at which
+the magic value is supposed to be loaded. This field serves to "synchronize"
+the mapping between OS image offsets and physical memory addresses.
+<LI><B>load_addr</B> -- Contains the physical address of the beginning
+of the text segment. The offset in the OS image file at which to start
+loading is defined by the offset at which the header was found, minus
+(header_addr - load_addr). load_addr must be less than or equal to
+header_addr.
+<LI><B>load_end_addr</B> -- Contains the physical address of the end of the
+data segment. (load_end_addr - load_addr) specifies how much data to load.
+This implies that the text and data segments must be consecutive in the
+OS image; this is true for existing a.out executable formats.
+<LI><B>bss_end_addr</B> -- Contains the physical address of the end of
+the bss segment. The boot loader initializes this area to zero, and
+reserves the memory it occupies to avoid placing boot modules and other
+data relevant to the OS in that area.
+<LI><B>entry</B> -- The physical address to which the boot loader should
+jump in order to start running the OS.
+</UL>
+
+The checksum is a 32-bit unsigned value which, when added to
+the other required fields, must have a 32-bit unsigned sum of zero.<P>
+
+<H3>Machine State</H3>
+
+When the boot loader invokes the 32-bit operating system,
+the machine must have the following state:<P>
+
+<UL>
+<LI>CS must be a 32-bit read/execute code segment with an offset of 0
+and a limit of 0xffffffff.
+<LI>DS, ES, FS, GS, and SS must be a 32-bit read/write data segment with
+an offset of 0 and a limit of 0xffffffff.
+<LI>The address 20 line must be usable for standard linear 32-bit
+addressing of memory (in standard PC hardware, it is wired to
+0 at bootup, forcing addresses in the 1-2 MB range to be mapped to the
+0-1 MB range, 3-4 is mapped to 2-3, etc.).
+<LI>Paging must be turned off.
+<LI>The processor interrupt flag must be turned off.
+<LI>EAX must contain the magic value 0x2BADB002; the presence of this value
+indicates to the OS that it was loaded by a MultiBoot-compliant boot
+loader (e.g. as opposed to another type of boot loader that the OS can
+also be loaded from).
+<LI>EBX must contain the 32-bit physical address of the multiboot_info
+structure provided by the boot loader (see below).
+</UL>
+
+All other processor registers and flag bits are undefined. This includes,
+in particular:<P>
+
+<UL>
+<LI>ESP: the 32-bit OS must create its own stack as soon as it needs one.
+<LI>GDTR: Even though the segment registers are set up as described above,
+the GDTR may be invalid, so the OS must not load any segment registers
+(even just reloading the same values!) until it sets up its own GDT.
+<LI>IDTR: The OS must leave interrupts disabled until it sets up its own IDT.
+</UL>
+
+However, other machine state should be left by the boot loader in "normal
+working order", i.e. as initialized by the BIOS (or DOS, if that's what
+the boot loader runs from). In other words, the OS should be able to make
+BIOS calls and such after being loaded, as long as it does not overwrite
+the BIOS data structures before doing so. Also, the boot loader must leave
+the PIC programmed with the normal BIOS/DOS values, even if it changed them
+during the switch to 32-bit mode.<P>
+
+<H3>Boot Information Format</H3>
+
+Upon entry to the OS, the EBX register contains the physical address of
+a 'multiboot_info' data structure, through which the boot loader
+communicates vital information to the OS. The OS can use or ignore any
+parts of the structure as it chooses; all information passed by the boot
+loader is advisory only.<P>
+
+The multiboot_info structure and its related substructures may be placed
+anywhere in memory by the boot loader (with the exception of the memory
+reserved for the kernel and boot modules, of course). It is the OS's
+responsibility to avoid overwriting this memory until it is done using it.<P>
+
+The format of the multiboot_info structure (as defined so far) follows:<P>
+
+<pre>
+ +-------------------+
+0 | flags | (required)
+ +-------------------+
+4 | mem_lower | (present if flags[0] is set)
+8 | mem_upper | (present if flags[0] is set)
+ +-------------------+
+12 | boot_device | (present if flags[1] is set)
+ +-------------------+
+16 | cmdline | (present if flags[2] is set)
+ +-------------------+
+20 | mods_count | (present if flags[3] is set)
+24 | mods_addr | (present if flags[3] is set)
+ +-------------------+
+28 - 40 | syms | (present if flags[4] or flags[5] is set)
+ +-------------------+
+44 | mmap_length | (present if flags[6] is set)
+48 | mmap_addr | (present if flags[6] is set)
+ +-------------------+
+</pre>
+
+The first longword indicates the presence and validity of other fields in
+the multiboot_info structure. All as-yet-undefined bits must be set to
+zero by the boot loader. Any set bits that the OS does not understand
+should be ignored. Thus, the flags field also functions as a version
+indicator, allowing the multiboot_info structure to be expanded in the
+future without breaking anything.<P>
+
+If bit 0 in the multiboot_info.flags word is set, then the 'mem_*' fields
+are valid. 'mem_lower' and 'mem_upper' indicate the amount of lower and upper
+memory, respectively, in kilobytes. Lower memory starts at address 0, and
+upper memory starts at address 1 megabyte. The maximum possible
+value for lower memory is 640 kilobytes. The value returned for upper
+memory is maximally the address of the first upper memory hole minus
+1 megabyte. It is not guaranteed to be this value.<P>
+
+If bit 1 in the multiboot_info.flags word is set, then the 'boot_device'
+field is valid, and indicates which BIOS disk device the boot loader loaded
+the OS from. If the OS was not loaded from a BIOS disk, then this field
+must not be present (bit 3 must be clear). The OS may use this field as a
+hint for determining its own "root" device, but is not required to. The
+boot_device field is layed out in four one-byte subfields as follows:<P>
+
+<pre>
+ +-------+-------+-------+-------+
+ | drive | part1 | part2 | part3 |
+ +-------+-------+-------+-------+
+</pre>
+
+The first byte contains the BIOS drive number as understood by the BIOS
+INT 0x13 low-level disk interface: e.g. 0x00 for the first floppy disk or
+0x80 for the first hard disk.<P>
+
+The three remaining bytes specify the boot partition. 'part1' specifies
+the "top-level" partition number, 'part2' specifies a "sub-partition" in
+the top-level partition, etc. Partition numbers always start from zero.
+Unused partition bytes must be set to 0xFF. For example, if the disk is
+partitioned using a simple one-level DOS partitioning scheme, then 'part1'
+contains the DOS partition number, and 'part2' and 'part3' are both zero.
+As another example, if a disk is partitioned first into DOS partitions, and
+then one of those DOS partitions is subdivided into several BSD partitions
+using BSD's "disklabel" strategy, then 'part1' contains the DOS partition
+number, 'part2' contains the BSD sub-partition within that DOS partition,
+and 'part3' is 0xFF.<P>
+
+DOS extended partitions are indicated as partition numbers starting from 4
+and increasing, rather than as nested sub-partitions, even though the
+underlying disk layout of extended partitions is hierarchical in nature.
+For example, if the boot loader boots from the second extended partition
+on a disk partitioned in conventional DOS style, then 'part1' will be 5,
+and 'part2' and 'part3' will both be 0xFF.<P>
+
+If bit 2 of the flags longword is set, the 'cmdline' field is valid, and
+contains the physical address of the the command line to be passed to the
+kernel. The command line is a normal C-style null-terminated string.<P>
+
+If bit 3 of the flags is set, then the 'mods' fields indicate to the kernel
+what boot modules were loaded along with the kernel image, and where they
+can be found. 'mods_count' contains the number of modules loaded;
+'mods_addr' contains the physical address of the first module structure.
+'mods_count' may be zero, indicating no boot modules were loaded, even if
+bit 1 of 'flags' is set. Each module structure is formatted as follows:<P>
+
+<pre>
+ +-------------------+
+0 | mod_start |
+4 | mod_end |
+ +-------------------+
+8 | string |
+ +-------------------+
+12 | reserved (0) |
+ +-------------------+
+</pre>
+
+The first two fields contain the start and end addresses of the boot module
+itself. The 'string' field provides an arbitrary string to be associated
+with that particular boot module; it is a null-terminated ASCII string,
+just like the kernel command line. The 'string' field may be 0 if there is
+no string associated with the module. Typically the string might be a
+command line (e.g. if the OS treats boot modules as executable programs),
+or a pathname (e.g. if the OS treats boot modules as files in a file
+system), but its exact use is specific to the OS. The 'reserved' field
+must be set to 0 by the boot loader and ignored by the OS.<P>
+
+NOTE: Bits 4 & 5 are mutually exclusive.<P>
+
+If bit 4 in the multiboot_info.flags word is set, then the following
+fields in the multiboot_info structure starting at byte 28 are valid:<P>
+
+<pre>
+ +-------------------+
+28 | tabsize |
+32 | strsize |
+36 | addr |
+40 | reserved (0) |
+ +-------------------+
+</pre>
+
+These indicate where the symbol table from an a.out kernel image can be
+found. 'addr' is the physical address of the size (4-byte unsigned
+long) of an array of a.out-format 'nlist' structures, followed immediately
+by the array itself, then the size (4-byte unsigned long) of a set of
+null-terminated ASCII strings (plus sizeof(unsigned long) in this case),
+and finally the set of strings itself. 'tabsize' is equal to it's size
+parameter (found at the beginning of the symbol section), and 'strsize'
+is equal to it's size parameter (found at the beginning of the string section)
+of the following string table to which the symbol table refers. Note that
+'tabsize' may be 0, indicating no symbols, even if bit 4 in the flags
+word is set.<P>
+
+If bit 5 in the multiboot_info.flags word is set, then the following
+fields in the multiboot_info structure starting at byte 28 are valid:<P>
+
+<pre>
+ +-------------------+
+28 | num |
+32 | size |
+36 | addr |
+40 | shndx |
+ +-------------------+
+</pre>
+
+These indicate where the section header table from an ELF kernel is, the
+size of each entry, number of entries, and the string table used as the
+index of names. They correspond to the 'shdr_*' entries ('shdr_num', etc.)
+in the Executable and Linkable Format (ELF) specification in the program
+header. All sections are loaded, and the physical address fields
+of the elf section header then refer to where the sections are in memory
+(refer to the i386 ELF documentation for details as to how to read the
+section header(s)). Note that 'shdr_num' may be 0, indicating no symbols,
+even if bit 5 in the flags word is set.<P>
+
+If bit 6 in the multiboot_info.flags word is set, then the 'mmap_*' fields
+are valid, and indicate the address and length of a buffer containing a
+memory map of the machine provided by the BIOS. 'mmap_addr' is the address,
+and 'mmap_length' is the total size of the buffer. The buffer consists of
+one or more of the following size/structure pairs ('size' is really used
+for skipping to the next pair):<P>
+
+<pre>
+ +-------------------+
+-4 | size |
+ +-------------------+
+0 | BaseAddrLow |
+4 | BaseAddrHigh |
+8 | LengthLow |
+12 | LengthHigh |
+16 | Type |
+ +-------------------+
+</pre>
+
+where 'size' is the size of the associated structure in bytes, which can
+be greater than the minimum of 20 bytes. 'BaseAddrLow' is the lower 32
+bits of the starting address, and 'BaseAddrHigh' is the upper 32 bits,
+for a total of a 64-bit starting address. 'LengthLow' is the lower 32 bits
+of the size of the memory region in bytes, and 'LengthHigh' is the upper 32
+bits, for a total of a 64-bit length. 'Type' is the variety of address
+range represented, where a value of 1 indicates available RAM, and all
+other values currently indicated a reserved area.<P>
+
+The map provided is guaranteed to list all standard RAM that should
+be available for normal use.<P>
+
+<HR>
+
+<H2><A NAME="author">Authors</A></H2>
+
+<pre>
+Bryan Ford
+Computer Systems Laboratory
+University of Utah
+Salt Lake City, UT 84112
+(801) 581-4280
+baford@cs.utah.edu
+
+Erich Stefan Boleyn
+924 S.W. 16th Ave, #202
+Portland, OR, USA 97205
+(503) 226-0741
+erich@uruk.org
+</pre>
+
+We would also like to thank the many other people have provided comments,
+ideas, information, and other forms of support for our work.<P>
+
+<H3>Revision History</H3>
+
+<pre>
+Version 0.6 3/29/96 (a few wording changes, header checksum, and
+ clarification of machine state passed to the OS)
+Version 0.5 2/23/96 (name change)
+Version 0.4 2/1/96 (major changes plus HTMLification)
+Version 0.3 12/23/95
+Version 0.2 10/22/95
+Version 0.1 6/26/95
+</pre>
+
+<HR>
+
+<H2><A NAME="notes">Notes on PCs</A></H2>
+
+In reference to bit 0 of the multiboot_info.flags parameter,
+if the bootloader
+in question uses older BIOS interfaces, or the newest ones are not
+available (see description about bit 6), then a maximum of either
+15 or 63 megabytes of memory may be reported. It is HIGHLY recommended
+that bootloaders perform a thorough memory probe.<P>
+
+In reference to bit 1 of the multiboot_info.flags parameter, it is
+recognized that determination of which BIOS drive maps to which
+OS-level device-driver is non-trivial, at best. Many kludges have
+been made to various OSes instead of solving this problem, most of
+them breaking under many conditions. To encourage the use of
+general-purpose solutions to this problem, here are 2
+<A HREF=bios_mapping.txt>BIOS Device Mapping Techniques</A>.<P>
+
+In reference to bit 6 of the multiboot_info.flags parameter, it is
+important to note that the data structure used there
+(starting with 'BaseAddrLow') is the data returned by the
+<A HREF=mem64mb.html>INT 15h, AX=E820h
+- Query System Address Map</A> call. More information
+on reserved memory regions is defined on that web page.
+The interface here is meant to allow a bootloader to
+work unmodified with any reasonable extensions of the BIOS interface,
+passing along any extra data to be interpreted by the OS as desired.<P>
+
+<HR>
+
+<H2><A NAME="example_os">Example OS Code</A> (from Bryan Ford)</H2>
+
+EDITOR'S NOTE: These examples are relevant to the Proposal version 0.5,
+which is basically identical except for the multiboot OS header, which was
+missing the checksum. A patch to bring Mach4 UK22 up to version 0.6 is
+available in the GRUB FTP area mentioned in the
+<A HREF="#example_boot">Example Bootloader Code</A> section below.<P>
+
+The Mach 4 distribution, available by anonymous FTP from
+flux.cs.utah.edu:/flux, contains a C header file that defines the
+MultiBoot data structures described above; anyone is welcome to rip it
+out and use it for other boot loaders and OS's:<P>
+
+<pre>
+ mach4-i386/include/mach/machine/multiboot.h
+</pre>
+
+This distribution also contains code implementing a "Linux boot adaptor",
+which collects a MultiBoot-compliant OS image and an optional set of boot
+modules, compresses them, and packages them into a single traditional Linux
+boot image that can be loaded from LILO or other Linux boot loaders. There
+is also a corresponding "BSD boot adaptor" which can be used to wrap a
+MultiBoot kernel and set of modules and produce an image that can be loaded
+from the FreeBSD and NetBSD boot loaders. All of this code can be used as-is
+or as a basis for other boot loaders. These are the directories of primary
+relevance:<P>
+
+<pre>
+ mach4-i386/boot
+ mach4-i386/boot/bsd
+ mach4-i386/boot/linux
+</pre>
+
+The Mach kernel itself in this distribution contains code that demonstrates
+how to create a compliant OS. The following files are of primary
+relevance:<P>
+
+<pre>
+ mach4-i386/kernel/i386at/boothdr.S
+ mach4-i386/kernel/i386at/model_dep.c
+</pre>
+
+Finally, I have created patches against the Linux 1.2.2 and FreeBSD 2.0
+kernels, in order to make them compliant with this proposed standard.
+These patches are available in kahlua.cs.utah.edu:/private/boot.<P>
+
+<HR>
+
+<H2><A NAME"example_boot">Example Bootloader Code</A> (from Erich Boleyn)</H2>
+
+The <A HREF=http://www.uruk.org/grub/>GRUB</A> bootloader project
+will be fully
+Multiboot-compliant, supporting all required and optional
+features present in this standard.<P>
+
+A final release has not been made, but both the GRUB beta release
+(which is quite stable) and a patch for Multiboot version 0.6 for
+Mach4 UK22 are available in the GRUB
+<A HREF=ftp://ftp.uruk.org/public/grub/>public release</A>
+area.<P>
+
+<HR>
+
+<A HREF=mailto:erich@uruk.org><I>erich@uruk.org</I></A><P>
+
+</BODY>
+</HTML>
+
diff --git a/doc/nbi-spec.txt b/doc/nbi-spec.txt
new file mode 100644
index 0000000..320f025
--- /dev/null
+++ b/doc/nbi-spec.txt
@@ -0,0 +1,660 @@
+ Draft Net Boot Image Proposal 0.3
+ Jamie Honan and Gero Kuhlmann, gero@minix.han.de
+ June 15, 1997
+
+ This is the specification of the "tagged image" format
+ ______________________________________________________________________
+
+ Table of Contents
+
+
+ 1. Note
+
+ 2. Preamble - the why
+
+ 3. The target
+
+ 4. Net Boot Process Description.
+
+ 5. Image Format with Initial Magic Number.
+
+ 6. Boot prom entry points.
+
+ 7. Example of a boot image.
+
+ 8. Terms
+
+ 9. References
+
+
+
+ ______________________________________________________________________
+
+ 11.. NNoottee
+
+
+ In order to provide more functionality to the boot rom code I changed
+ Jamie's draft a little bit. All my changes are preceded and followed
+ by ((ggkk)).
+
+
+
+ Gero Kuhlmann
+
+
+ 22.. PPrreeaammbbllee -- tthhee wwhhyy
+
+
+ Whilst researching what other boot proms do (at least those
+ implementing TCP/IP protocols) it is clear that each 'does their own
+ thing' in terms of what they expect in a boot image.
+
+
+
+ If we could all agree on working toward an open standard, O/S
+ suppliers and boot rom suppliers can build their products to this
+ norm, and be confident that they will work with each other.
+
+
+
+ This is a description of how I will implement the boot rom for Linux.
+ I believe it to be flexible enough for any OS that will be loaded
+ when a PC boots from a network in the TCP/IP environment.
+
+
+
+
+ It would be good if this could be turned into some form of standard.
+
+
+
+ This is very much a first draft. I am inviting comment.
+
+
+
+ The ideas presented here should be independant of any implementation.
+ In the end, where there is a conflict between the final of this draft,
+ and an implementation, this description should prevail.
+
+
+
+ The terms I use are defined at the end.
+
+
+
+ ((ggkk))IMPORTANT NOTE: The scope of this document starts at the point
+ where the net boot process gains control from the BIOS, to where the
+ booted image reaches a state from which there is no return to the net
+ boot program possible.((ggkk))
+
+
+ 33.. TThhee ttaarrggeett
+
+
+ The target is to have a PC retrieve a boot image from a network in the
+ TCP/IP environment.
+
+
+
+ ((ggkk))The boot may take place from a network adaptor rom, from a boot
+ floppy.((ggkk))
+
+
+ 44.. NNeett BBoooott PPrroocceessss DDeessccrriippttiioonn..
+
+
+ ((ggkk))The net boot process is started as a result of the PC boot
+ process. The net boot program can reside on a rom, e.g. on an adaptor
+ card, or in ram as a result of reading off disk.((ggkk))
+
+
+
+ The boot process may execute in any mode (e.g. 8086, 80386) it
+ desires. When it jumps to the start location in the boot image, it
+ must be in 8086 mode and be capable of going into any mode supported
+ by the underlying processor.
+
+
+
+ The image cannot be loaded into address spaces below 10000h, or
+ between A0000h through FFFFFh, or between 98000h through 9FFFFh.
+ ((ggkk))Only when the image is not going to return to the boot process,
+ all the memory is available to it once it has been started, so it can
+ relocate parts of itself to these areas.((ggkk))
+
+
+
+ The boot process must be capable of loading the image into all other
+ memory locations. Specifically, where the machine supports this, this
+ means memory over 100000h.
+
+
+
+ The net boot process must execute the bootp protocol, followed by the
+ tftp protocol, as defined in the relevant rfc's.
+
+
+
+ The file name used in the tftp protocol must be that given by the
+ bootp record.
+
+
+
+ If less than 512 bytes are loaded, the net boot process attempts to
+ display on the screen any ascii data at the start of the image. The
+ net boot process then exits in the normal manner. For a boot prom,
+ this will allow normal disk booting. ((ggkk))Reference to DOS deleted.((ggkk))
+
+
+
+ When the first 512 bytes have been loaded, the boot process checks for
+ an initial magic number, which is defined later. If this number is
+ present, the net process continues loading under the control of the
+ image format. The image, which is described later, tells the net boot
+ process where to put this record and all subsequent data.
+
+
+
+ If no initial magic number is present the net boot process checks for
+ a second magic number at offset 510. If the magic number 510 = 55h,
+ 511 = AAh, then the net process continues. If this second magic number
+ is not present, then the net boot process terminates the tftp
+ protocol, displays an error message and exits in the normal manner.
+
+
+
+ If no initial magic number is present and the second one is, the net
+ boot process relocates the 512 bytes to location 7c00h. The net boot
+ process continues to load any further image data to 10000h up. This
+ data can overwrite the first 512 boot bytes. If the image reaches
+ 98000h, then any further data is continued to be loaded above 100000h.
+ When all the data has been loaded, the net boot process jumps to
+ location 0:7c00.
+
+
+
+ ((ggkk))When the net boot program calls the image, it places 2 far
+ pointers onto the stack, in standard intel order (e.g. segment:offset
+ representation). The first far pointer which immediately follows the
+ return address on the stack, points to the loaded boot image header.
+ The second far pointer which is placed above the first one, shows to
+ the memory area where the net boot process saved the bootp reply.
+
+
+
+ If the boot image is flagged as being returnable to the boot process,
+ the boot program has to provide the boot image with interrupt vector
+ 78h. It's an interface to services provided by the net boot program
+ (see below for further description).
+
+
+
+ If the boot image is not flagged as being returnable to the boot
+ process, before the boot image is called, the boot program has to set
+ the system into a state in which it was before the net boot process
+ has started.((ggkk))
+
+
+
+ 55.. IImmaaggee FFoorrmmaatt wwiitthh IInniittiiaall MMaaggiicc NNuummbbeerr..
+
+
+ The first 512 bytes of the image file contain the image header, and
+ image loading information records. This contains all the information
+ needed by the net boot process as to where data is to be loaded.
+
+ The magic number (in time-honoured tradition (well why not?)) is:
+
+
+ ______________________________________________________________________
+ 0 = 36h
+ 1 = 13h
+ 2 = 03h
+ 3 = 1Bh
+ ______________________________________________________________________
+
+
+
+ Apart from the two magic numbers, all words and double words are in PC
+ native endian.
+
+
+
+ Including the initial magic number the header record is:
+
+
+ ______________________________________________________________________
+ +---------------------+
+ | |
+ | Initial Magic No. | 4 bytes
+ +---------------------+
+ | |
+ | Flags and length | double word
+ +---------------------+
+ | |
+ | Location Address | double word in ds:bx format
+ +---------------------+
+ | |
+ | Execute Address | double word in cs:ip format
+ +---------------------+
+ ______________________________________________________________________
+
+
+
+ The Location address is where to place the 512 bytes. The net boot
+ process does this before loading the rest of the image. The location
+ address cannot be one of the reserved locations mentioned above, but
+ must be an address lower than 100000h.
+
+
+
+ The rest of the image must not overwrite these initial 512 bytes,
+ placed at the required location. The writing of data by the net boot
+ process into these 512 bytes is deprecated. These 512 bytes must be
+ available for the image to interogate once it is loaded and running.
+
+
+
+ The execute address is the location in cs:ip of the initial
+ instruction once the full image has been loaded. This must be lower
+ than 100000h, since the initial instructions will be executed in 8086
+ mode. When the jump (actaully a far call) is made to the boot image,
+ the stack contains a far return address, with a far pointer parameter
+ above that, pointing to the location of this header.
+
+ The flags and length field is broken up in the following way:
+
+
+
+ Bits 0 to 3 (lowest 4 bits) define the length of the non vendor header
+ in double words. Currently the value is 4.
+
+
+
+ Bits 4 to 7 define the length required by the vendor extra information
+ in double words. A value of zero indicates no extra vendor
+ information.
+
+
+
+ ((ggkk))Bit 8 is set if the boot image can return to the net boot process
+ after execution. If this bit is not set the boot image does never
+ return to the net boot process, and the net boot program has to set
+ the system into a clean state before calling the boot image.
+
+
+
+ Bits 9 to 31 are reserved for future use and must be set to zero.((ggkk))
+
+
+
+ After this header, and any vendor header, come the image loading
+ information records. These specify where data is to be loaded, how
+ long it is, and communicates to the loaded image what sort of data it
+ is.
+
+
+
+ The format of each image loading information record is :
+
+
+
+ ______________________________________________________________________
+ +---------------------+
+ | Flags, tags and | double word
+ | lengths |
+ +---------------------+
+ | |
+ | Load Address | double word
+ +---------------------+
+ | |
+ | Image Length | double word
+ +---------------------+
+ | |
+ | Memory Length | double word
+ +---------------------+
+ ______________________________________________________________________
+
+
+
+ Each image loading information record follows the previous, or the
+ header.
+
+
+
+ The memory length, image length and load address fields are unsigned
+ 32 numbers. They do not have the segment:offset format used by the
+ 8086.
+
+
+
+ The flags, tags and lengths field is broken up as follows:
+
+
+
+ Bits 0 to 3 (lowest 4 bits) are the length of the non vendor part of
+ this header in double words. Currently this value is 4.
+
+
+
+ Bits 4 to 7 indicate the length of any vendor information, in double
+ words.
+
+
+
+ Bits 8 to 15 are for vendor's tags. The vendor tag is a private number
+ that the loaded image can use to determine what sort of image is at
+ this particular location.
+
+
+
+ Bits 16 to 23 are for future expansion and should be set to zero.
+
+
+
+ Bits 24 to 31 are for flags, which are defined later.
+
+
+
+ Vendors may place further information after this information record,
+ and before the next. Each information record may have a different
+ vendor length.
+
+
+
+ There are two restrictions on vendor information.
+
+
+
+ One is that the header and all information records that the net boot
+ process is to use fall within the first 512 bytes.
+
+
+
+ The second restriction is that the net boot process must ignore all
+ vendor additions. The net boot process may not overwrite vendor
+ supplied information, or other undefined data in the initial 512
+ bytes.
+
+
+
+ The flags are used to modify the load address field, and to indicate
+ that this is the last information record that the net boot process
+ should use.
+
+
+
+ Bit 24 works in conjunction with bit 25 to specify the meaning of the
+ load address.
+
+
+
+
+
+
+
+
+ ______________________________________________________________________
+ B24 B25
+
+ 0 0 load address is an absolute 32 number
+
+ 1 0 add the load address to the location one past the last byte
+ of the memory area required by the last image loaded.
+ If the first image, then add to 512 plus the location
+ where the 512 bytes were placed
+
+ 0 1 subtract the load address from the one past the
+ last writeable location in memory. Thus 1 would
+ be the last location one could write in memory.
+
+ 1 1 load address is subtracted from the start of
+ the last image loaded. If the first image, then
+ subtract from the start of where the 512 bytes were
+ placed
+ ______________________________________________________________________
+
+
+
+ (For convenience bit 24 is byte 0 of the flag field)
+
+
+
+ Bit 26 is the end marker for the net boot process. It is set when this
+ is the last information record the net boot process should look at.
+ More records may be present, but the net boot process will not look at
+ them. (Vendors can continue information records out past the 512
+ boundary for private use in this manner).
+
+
+
+ The image length tells the net boot process how many bytes are to be
+ loaded. Zero is a valid value. This can be used to mark memory areas
+ such as shared memory for interprocessor communication, flash eproms,
+ data in eproms.
+
+
+
+ The image length can also be different from the memory length. This
+ allows decompression programs to fluff up the kernel image. It also
+ allows a file system to be larger then the loaded file system image.
+
+
+
+ Bits 27 through 31 are not defined as yet and must be set to zero
+ until they are.
+
+
+ 66.. BBoooott pprroomm eennttrryy ppooiinnttss..
+
+
+ ((ggkk))As mentioned above the net boot process has to provide interrupt
+ 78h as an entry point in case, the returnable flag (bit 9 of the flags
+ field in the image header) of the boot image has been set. When
+ calling this interface interrupt, the caller has to load the AH
+ register with a value indicating the type of operation requested:
+
+
+
+
+
+
+
+ ______________________________________________________________________
+ 00h - Installation check
+ Input: none
+ Output: AX - returns the value 474Bh
+ BX - flags indicating what further services are
+ provided by the net boot program:
+ Bit 0 - packet driver interface (see below)
+ Bits 1 to 15 are unused and have to be zero
+
+ 01h - Cleanup and terminate the boot process services. This will
+ also remove the services provided by interrupt 87h.
+ Input: none
+ Output: none
+ ______________________________________________________________________
+
+
+
+
+
+ Further functions are not yet defined. These functions are only
+ available to boot images which have the first magic number at the
+ beginning of the image header, and have the returnable flag set in the
+ flags field.
+
+
+
+ In order to provide compatibility with net boot programs written to
+ match an earlier version of this document, the loaded image should
+ check for the existence of interrupt 78h by looking at it's vector. If
+ that's 0:0, or if it does not return a proper magic ID after calling
+ the installation check function, the boot image has to assume that the
+ net boot program does not support this services interrupt.
+
+
+
+ If the bit 0 of register BX of function 00h is set, the boot program
+ has to provide a packet driver <http://www.crynwr.com> interface at
+ interrupt 79h as described in the packet driver interface standard,
+ version 1.09, published by FTP Software, Inc., which is not repeated
+ here. It serves as an interface to the system's network card. It is
+ important to note that the net boot process has to provide a clean
+ packet driver interface without any handles being defined when the
+ boot image gets started. It is expected that the boot image sets up
+ it's own TCP/IP or other network's stack on top of this packet driver
+ interface. When the boot image returns to the net boot process, it
+ has to return a clean packet driver interface as well, without any
+ handles being defined.((ggkk))
+
+
+ 77.. EExxaammppllee ooff aa bboooott iimmaaggee..
+
+
+ Here is an example of how the boot image would look for Linux:
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ______________________________________________________________________
+ 0x1B031336, /* magic number */
+ 0x4, /* length of header is 16 bytes, no vendor info */
+ 0x90000000, /* location in ds:bx format */
+ 0x90000200, /* execute address in cs:ip format */
+
+ /* 2048 setup.S bytes */
+ 0x4, /* flags, not end, absolute address, 16 bytes this
+ record, no vendor info */
+ 0x90200, /* load address - note format */
+ 0x800, /* 4 8 512 byte blocks for linux */
+ 0x800,
+
+ /* kernel image */
+ 0x4, /* flags, not end, absolute address, 16 bytes this
+ record, no vendor info */
+ 0x10000, /* load address - note format */
+ 0x80000, /* 512K (this could be shorter */
+ 0x80000,
+
+ /* ramdisk for root file system */
+ 0x04000004, /* flags = last, absolute address, 16 bytes this
+ record, no vendor info *//
+ 0x100000, /* load address - in extended memory */
+ 0x80000, /* 512K for instance */
+ 0x80000,
+
+ /* Then follows linux specific information */
+ ______________________________________________________________________
+
+
+
+
+ 88.. TTeerrmmss
+
+
+ When I say 'the net boot process', I mean the act of loading the image
+ into memory, setting up any tables, up until the jump to the required
+ location in the image.
+
+
+
+ The net booting program executes the net boot process. The net boot
+ program may be a rom, but not neccassarily. It is a set of
+ instructions and data residing on the booting machine.
+
+
+
+ The image, or boot image, consists of the data loaded by the net boot
+ process.
+
+
+
+ When I say 'the PC boot process', I mean the general PC rom bios boot
+ process, the setting up of hardware, the scanning for adaptor roms,
+ the execution of adaptor roms, the loading in of the initial boot
+ track. The PC boot process will include the net boot process, if one
+ is present.
+
+
+
+ When I say client, I mean the PC booting up.
+
+
+
+
+ When I say 'image host', I mean the host where the boot image is
+ comming from. This may not have the same architecture as the client.
+
+
+
+ The bootp protocol is defined in RFC951 and RFC1084. The tftp protocol
+ is defined in RFC783. These are available on many sites. See Comer
+ 1991 for details on how to obtain them.
+
+
+
+ A bootp server is the machine that answers the bootp request. It is
+ not neccessarily the image host.
+
+
+
+ "Can" and "may" means doesn't have to, but is allowed to and might.
+ "Must" means just that. "Cannot" means must not.
+
+
+ 99.. RReeffeerreenncceess
+
+
+ Comer, D.E. 1991, Internetworking with TCP/IP Vol I: Principles,
+ Protocols, and Architecture Second Edition, Prentice Hall, Englewood
+ Cliffs, N.J., 1991
+
+
+
+ Stevens, W.R 1990, Unix Network Programming, Prentice Hall, Englewood
+ Cliffs, N.J., 1990
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/include/boot/beoboot.h b/include/boot/beoboot.h
new file mode 100644
index 0000000..d22fef1
--- /dev/null
+++ b/include/boot/beoboot.h
@@ -0,0 +1,39 @@
+
+/*--- Boot image definitions ---------------------------------------*/
+struct beoboot_header {
+ char magic[4];
+ uint8_t arch;
+ uint8_t flags;
+ uint16_t cmdline_size;/* length of command line (including null) */
+ /* The alpha chunk is a backward compatibility hack. The original
+ * assumption was that integer sizes didn't matter because we
+ * would never mix architectures. x86_64 + i386 broke that
+ * assumption. It's fixed for that combination and the future.
+ * However, alpha needs a little hack now... */
+#ifdef __alpha__
+ unsigned long kernel_size;
+ unsigned long initrd_size;
+#else
+ uint32_t kernel_size;
+ uint32_t initrd_size;
+#endif
+};
+#define BEOBOOT_MAGIC "BeoB"
+#define BEOBOOT_ARCH_I386 1
+#define BEOBOOT_ARCH_ALPHA 2
+#define BEOBOOT_ARCH_PPC 3
+#define BEOBOOT_ARCH_PPC64 4
+#if defined(__i386__) || defined(__x86_64__)
+#define BEOBOOT_ARCH BEOBOOT_ARCH_I386
+#elif defined(__alpha__)
+#define BEOBOOT_ARCH BEOBOOT_ARCH_ALPHA
+#elif defined(powerpc)
+#define BEOBOOT_ARCH BEOBOOT_ARCH_PPC
+#elif defined(__powerpc64__)
+#define BEOBOOT_ARCH BEOBOOT_ARCH_PPC64
+#else
+#error Unsupported architecture.
+#endif
+#define BEOBOOT_INITRD_PRESENT 1
+/*------------------------------------------------------------------*/
+
diff --git a/include/boot/elf_boot.h b/include/boot/elf_boot.h
new file mode 100644
index 0000000..08f561e
--- /dev/null
+++ b/include/boot/elf_boot.h
@@ -0,0 +1,104 @@
+#ifndef ELF_BOOT_H
+#define ELF_BOOT_H
+
+/* This defines the structure of a table of parameters useful for ELF
+ * bootable images. These parameters are all passed and generated
+ * by the bootloader to the booted image. For simplicity and
+ * consistency the Elf Note format is reused.
+ *
+ * All of the information must be Position Independent Data.
+ * That is it must be safe to relocate the whole ELF boot parameter
+ * block without changing the meaning or correctnes of the data.
+ * Additionally it must be safe to permute the order of the ELF notes
+ * to any possible permutation without changing the meaning or correctness
+ * of the data.
+ *
+ */
+
+#define ELF_BOOT_MAGIC 0x0E1FB007
+
+#ifndef ASSEMBLY
+#include <stdint.h>
+typedef uint16_t Elf_Half;
+typedef uint32_t Elf_Word;
+typedef uint64_t Elf_Xword;
+
+/*
+ * Elf boot notes...
+ */
+
+typedef struct Elf_Bhdr
+{
+ Elf_Word b_signature; /* "0x0E1FB007" */
+ Elf_Word b_size;
+ Elf_Half b_checksum;
+ Elf_Half b_records;
+} Elf_Bhdr;
+
+/*
+ * ELF Notes.
+ */
+
+typedef struct Elf_Nhdr
+{
+ Elf_Word n_namesz; /* Length of the note's name. */
+ Elf_Word n_descsz; /* Length of the note's descriptor. */
+ Elf_Word n_type; /* Type of the note. */
+} Elf_Nhdr;
+
+#endif /* ASSEMBLY */
+
+
+/* Standardized Elf image notes for booting... The name for all of these is ELFBoot */
+#define ELF_NOTE_BOOT "ELFBoot"
+
+#define EIN_PROGRAM_NAME 0x00000001
+/* The program in this ELF file */
+#define EIN_PROGRAM_VERSION 0x00000002
+/* The version of the program in this ELF file */
+#define EIN_PROGRAM_CHECKSUM 0x00000003
+/* ip style checksum of the memory image. */
+
+
+/* Linux image notes for booting... The name for all of these is Linux */
+
+#if 0
+#define LIN_COMMAND_LINE_PTR 0x00000006
+/* Pointer to the command line to pass to the loaded kernel. */
+#define LIN_INITRD_START_PTR 0x00000007
+/* Pointer to the start of the ramdisk in bytes */
+#define LIN_INITRD_SIZE_PTR 0x00000008
+/* Pointer to the size of the ramdisk in bytes */
+#define LIN_VID_MODE_PTR 0x00000009
+/* Pointer to the vid_mode parameter */
+#endif
+
+/* Etherboot specific notes */
+#define EB_PARAM_NOTE "Etherboot"
+#define EB_IA64_SYSTAB 0x00000001
+#define EB_IA64_MEMMAP 0x00000002
+#define EB_IA64_FPSWA 0x00000003
+#define EB_IA64_CONINFO 0x00000004
+#define EB_BOOTP_DATA 0x00000005
+#define EB_HEADER 0x00000006
+#define EB_IA64_IMAGE_HANDLE 0x00000007
+#define EB_I386_MEMMAP 0x00000008
+
+/* For standard notes n_namesz must be zero */
+/* All of the following standard note types provide a single null
+ * terminated string in the descriptor.
+ */
+#define EBN_FIRMWARE_TYPE 0x00000001
+/* On platforms that support multiple classes of firmware this field
+ * specifies the class of firmware you are loaded under.
+ */
+#define EBN_BOOTLOADER_NAME 0x00000002
+/* This specifies just the name of the bootloader for easy comparison */
+#define EBN_BOOTLOADER_VERSION 0x00000003
+/* This specifies the version of the bootlader */
+#define EBN_COMMAND_LINE 0x00000004
+/* This specifies a command line that can be set by user interaction,
+ * and is provided as a free form string to the loaded image.
+ */
+
+#endif /* ELF_BOOT_H */
diff --git a/include/boot/linuxbios_tables.h b/include/boot/linuxbios_tables.h
new file mode 100644
index 0000000..c324cf5
--- /dev/null
+++ b/include/boot/linuxbios_tables.h
@@ -0,0 +1,82 @@
+#ifndef LINUXBIOS_TABLES_H
+#define LINUXBIOS_TABLES_H
+
+#include <stdint.h>
+
+/* The linuxbios table information is for conveying information
+ * from the firmware to the loaded OS image. Primarily this
+ * is expected to be information that cannot be discovered by
+ * other means, such as quering the hardware directly.
+ *
+ * All of the information should be Position Independent Data.
+ * That is it should be safe to relocated any of the information
+ * without it's meaning/correctnes changing. For table that
+ * can reasonably be used on multiple architectures the data
+ * size should be fixed. This should ease the transition between
+ * 32 bit and 64 bit architectures etc.
+ *
+ * The completeness test for the information in this table is:
+ * - Can all of the hardware be detected?
+ * - Are the per motherboard constants available?
+ * - Is there enough to allow a kernel to run that was written before
+ * a particular motherboard is constructed? (Assuming the kernel
+ * has drivers for all of the hardware but it does not have
+ * assumptions on how the hardware is connected together).
+ *
+ * With this test it should be straight forward to determine if a
+ * table entry is required or not. This should remove much of the
+ * long term compatibility burden as table entries which are
+ * irrelevant or have been replaced by better alternatives may be
+ * dropped. Of course it is polite and expidite to include extra
+ * table entries and be backwards compatible, but it is not required.
+ */
+
+
+struct lb_header
+{
+ uint8_t signature[4]; /* LBIO */
+ uint32_t header_bytes;
+ uint32_t header_checksum;
+ uint32_t table_bytes;
+ uint32_t table_checksum;
+ uint32_t table_entries;
+};
+
+/* Every entry in the boot enviroment list will correspond to a boot
+ * info record. Encoding both type and size. The type is obviously
+ * so you can tell what it is. The size allows you to skip that
+ * boot enviroment record if you don't know what it easy. This allows
+ * forward compatibility with records not yet defined.
+ */
+struct lb_record {
+ uint32_t tag; /* tag ID */
+ uint32_t size; /* size of record (in bytes) */
+};
+
+#define LB_TAG_UNUSED 0x0000
+
+#define LB_TAG_MEMORY 0x0001
+
+struct lb_memory_range {
+ uint64_t start;
+ uint64_t size;
+ uint32_t type;
+#define LB_MEM_RAM 1
+#define LB_MEM_RESERVED 2
+
+};
+
+struct lb_memory {
+ uint32_t tag;
+ uint32_t size;
+ struct lb_memory_range map[0];
+};
+
+#define LB_TAG_HWRPB 0x0002
+struct lb_hwrpb {
+ uint32_t tag;
+ uint32_t size;
+ uint64_t hwrpb;
+};
+
+#endif /* LINUXBIOS_TABLES_H */
diff --git a/include/elf.h b/include/elf.h
new file mode 100644
index 0000000..c958a40
--- /dev/null
+++ b/include/elf.h
@@ -0,0 +1,2367 @@
+
+/* This file defines standard ELF types, structures, and macros.
+ Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ian Lance Taylor <ian@cygnus.com>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ 12 April 2002 Modified by Eric Biederman <ebiederm@xmission.com> so
+ it can be used outside of glibc.
+
+*/
+
+#ifndef ELF_H
+#define ELF_H
+
+/* Standard ELF types. */
+
+#include <stdint.h>
+#include <stddef.h>
+
+/* Type for a 16-bit quantity. */
+typedef uint16_t Elf32_Half;
+typedef uint16_t Elf64_Half;
+
+/* Types for signed and unsigned 32-bit quantities. */
+typedef uint32_t Elf32_Word;
+typedef int32_t Elf32_Sword;
+typedef uint32_t Elf64_Word;
+typedef int32_t Elf64_Sword;
+
+/* Types for signed and unsigned 64-bit quantities. */
+typedef uint64_t Elf32_Xword;
+typedef int64_t Elf32_Sxword;
+typedef uint64_t Elf64_Xword;
+typedef int64_t Elf64_Sxword;
+
+/* Type of addresses. */
+typedef uint32_t Elf32_Addr;
+typedef uint64_t Elf64_Addr;
+
+/* Type of file offsets. */
+typedef uint32_t Elf32_Off;
+typedef uint64_t Elf64_Off;
+
+/* Type for section indices, which are 16-bit quantities. */
+typedef uint16_t Elf32_Section;
+typedef uint16_t Elf64_Section;
+
+/* Type of symbol indices. */
+typedef uint32_t Elf32_Symndx;
+typedef uint64_t Elf64_Symndx;
+
+/* 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_486 6 /* Intel 80486 */
+#define EM_860 7 /* Intel 80860 */
+#define EM_MIPS 8 /* MIPS R3000 big-endian */
+#define EM_S370 9 /* Amdahl */
+#define EM_MIPS_RS4_BE 10 /* MIPS R4000 big-endian */
+#define EM_RS6000 11 /* RS6000 */
+
+#define EM_PARISC 15 /* HPPA */
+#define EM_nCUBE 16 /* nCUBE */
+#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_ST19 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; /* No defined meaning, 0 */
+ 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; /* No defined meaning, 0 */
+ 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
+
+
+/* Special section index. */
+
+#define SHN_UNDEF 0 /* No section, undefined symbol. */
+
+/* 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_GNU_STACK 0x6474e551 /* Indicates stack executability */
+#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_TASKSTRUCT 4 /* Contains copy of task structure */
+#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 */
+#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 0x60000000 /* Start of OS-specific */
+#define DT_HIOS 0x6fffffff /* 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 <elf.h> 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. */
+
+#define AT_SECURE 23 /* Boolean, was exec setuid-like? */
+
+/* Pointer to the global system page used for system calls and other
+ nice things. */
+#define AT_SYSINFO 32
+#define AT_SYSINFO_EHDR 33
+
+
+/* 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
+#define ELF_NOTE_OS_FREEBSD 3
+
+
+/* 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_TRAPNL 1 /* Trap nil pointer dereference. */
+#define EF_PARISC_EXT 2 /* Program uses arch. extensions. */
+#define EF_PARISC_ARCH 0xffff0000 /* Architecture version. */
+/* Defined values are:
+ 0x020b PA-RISC 1.0 big-endian
+ 0x0210 PA-RISC 1.1 big-endian
+ 0x028b PA-RISC 1.0 little-endian
+ 0x0290 PA-RISC 1.1 little-endian
+*/
+
+/* Legal values for sh_type field of Elf32_Shdr. */
+
+#define SHT_PARISC_GOT 0x70000000 /* GOT for external data. */
+#define SHT_PARISC_ARCH 0x70000001 /* Architecture extensions. */
+#define SHT_PARISC_GLOBAL 0x70000002 /* Definition of $global$. */
+#define SHT_PARISC_MILLI 0x70000003 /* Millicode routines. */
+#define SHT_PARISC_UNWIND 0x70000004 /* Unwind information. */
+#define SHT_PARISC_PLT 0x70000005 /* Procedure linkage table. */
+#define SHT_PARISC_SDATA 0x70000006 /* Short initialized data. */
+#define SHT_PARISC_SBSS 0x70000007 /* Short uninitialized data. */
+#define SHT_PARISC_SYMEXTN 0x70000008 /* Argument/relocation info. */
+#define SHT_PARISC_STUBS 0x70000009 /* Linker stubs. */
+
+/* Legal values for sh_flags field of Elf32_Shdr. */
+
+#define SHF_PARISC_GLOBAL 0x10000000 /* Section defines dp. */
+#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_DIR14R 4 /* Right 14 bits of eff. address. */
+#define R_PARISC_PCREL21L 5 /* PC-relative, left 21 bits. */
+#define R_PARISC_PCREL14R 6 /* PC-relative, right 14 bits. */
+#define R_PARISC_PCREL17C 7 /* Conditional PC-relative, ignore
+ if displacement > 17bits. */
+#define R_PARISC_PCREL17F 8 /* Conditional PC-relative, must
+ fit in 17bits. */
+#define R_PARISC_DPREL21L 9 /* DP-relative, left 21 bits. */
+#define R_PARISC_DPREL14R 10 /* DP-relative, right 14 bits. */
+#define R_PARISC_DPREL14F 11 /* DP-relative, must bit in 14 bits. */
+#define R_PARISC_DLTREL21L 12 /* DLT-relative, left 21 bits. */
+#define R_PARISC_DLTREL14R 13 /* DLT-relative, right 14 bits. */
+#define R_PARISC_DLTREL14F 14 /* DLT-relative, must fit in 14 bits.*/
+#define R_PARISC_DLTIND21L 15 /* DLT-relative indirect, left
+ 21 bits. */
+#define R_PARISC_DLTIND14R 16 /* DLT-relative indirect, right
+ 14 bits. */
+#define R_PARISC_DLTIND14F 17 /* DLT-relative indirect, must fit
+ int 14 bits. */
+#define R_PARISC_PLABEL32 18 /* Direct 32-bit reference to proc. */
+
+/* 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_OP_PUSH 12 /* OP stack push */
+#define R_ALPHA_OP_STORE 13 /* OP stack pop and store */
+#define R_ALPHA_OP_PSUB 14 /* OP stack subtract */
+#define R_ALPHA_OP_PRSHIFT 15 /* OP stack right shift */
+#define R_ALPHA_GPVALUE 16
+#define R_ALPHA_GPRELHIGH 17
+#define R_ALPHA_GPRELLOW 18
+#define R_ALPHA_IMMED_GP_16 19
+#define R_ALPHA_IMMED_GP_HI32 20
+#define R_ALPHA_IMMED_SCN_HI32 21
+#define R_ALPHA_IMMED_BR_HI32 22
+#define R_ALPHA_IMMED_LO32 23
+#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
+
+/* PowerPC relocations defined for the TLS access ABI. */
+#define R_PPC_TLS 67 /* none (sym+add)@tls */
+#define R_PPC_DTPMOD32 68 /* word32 (sym+add)@dtpmod */
+#define R_PPC_TPREL16 69 /* half16* (sym+add)@tprel */
+#define R_PPC_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */
+#define R_PPC_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */
+#define R_PPC_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */
+#define R_PPC_TPREL32 73 /* word32 (sym+add)@tprel */
+#define R_PPC_DTPREL16 74 /* half16* (sym+add)@dtprel */
+#define R_PPC_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */
+#define R_PPC_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */
+#define R_PPC_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */
+#define R_PPC_DTPREL32 78 /* word32 (sym+add)@dtprel */
+#define R_PPC_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */
+#define R_PPC_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */
+#define R_PPC_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */
+#define R_PPC_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */
+#define R_PPC_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */
+#define R_PPC_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */
+#define R_PPC_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */
+#define R_PPC_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */
+#define R_PPC_GOT_TPREL16 87 /* half16* (sym+add)@got@tprel */
+#define R_PPC_GOT_TPREL16_LO 88 /* half16 (sym+add)@got@tprel@l */
+#define R_PPC_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */
+#define R_PPC_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */
+#define R_PPC_GOT_DTPREL16 91 /* half16* (sym+add)@got@dtprel */
+#define R_PPC_GOT_DTPREL16_LO 92 /* half16* (sym+add)@got@dtprel@l */
+#define R_PPC_GOT_DTPREL16_HI 93 /* half16* (sym+add)@got@dtprel@h */
+#define R_PPC_GOT_DTPREL16_HA 94 /* half16* (sym+add)@got@dtprel@ha */
+
+/* Keep this the last entry. */
+#define R_PPC_NUM 95
+
+/* 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 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 address */
+#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of 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-rel. 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 */
+
+/* PowerPC64 relocations defined for the TLS access ABI. */
+#define R_PPC64_TLS 67 /* none (sym+add)@tls */
+#define R_PPC64_DTPMOD64 68 /* doubleword64 (sym+add)@dtpmod */
+#define R_PPC64_TPREL16 69 /* half16* (sym+add)@tprel */
+#define R_PPC64_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */
+#define R_PPC64_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */
+#define R_PPC64_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */
+#define R_PPC64_TPREL64 73 /* doubleword64 (sym+add)@tprel */
+#define R_PPC64_DTPREL16 74 /* half16* (sym+add)@dtprel */
+#define R_PPC64_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */
+#define R_PPC64_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */
+#define R_PPC64_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */
+#define R_PPC64_DTPREL64 78 /* doubleword64 (sym+add)@dtprel */
+#define R_PPC64_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */
+#define R_PPC64_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */
+#define R_PPC64_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */
+#define R_PPC64_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */
+#define R_PPC64_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */
+#define R_PPC64_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */
+#define R_PPC64_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */
+#define R_PPC64_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */
+#define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got@tprel */
+#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got@tprel@l */
+#define R_PPC64_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */
+#define R_PPC64_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */
+#define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds* (sym+add)@got@dtprel */
+#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got@dtprel@l */
+#define R_PPC64_GOT_DTPREL16_HI 93 /* half16 (sym+add)@got@dtprel@h */
+#define R_PPC64_GOT_DTPREL16_HA 94 /* half16 (sym+add)@got@dtprel@ha */
+#define R_PPC64_TPREL16_DS 95 /* half16ds* (sym+add)@tprel */
+#define R_PPC64_TPREL16_LO_DS 96 /* half16ds (sym+add)@tprel@l */
+#define R_PPC64_TPREL16_HIGHER 97 /* half16 (sym+add)@tprel@higher */
+#define R_PPC64_TPREL16_HIGHERA 98 /* half16 (sym+add)@tprel@highera */
+#define R_PPC64_TPREL16_HIGHEST 99 /* half16 (sym+add)@tprel@highest */
+#define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel@highesta */
+#define R_PPC64_DTPREL16_DS 101 /* half16ds* (sym+add)@dtprel */
+#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel@l */
+#define R_PPC64_DTPREL16_HIGHER 103 /* half16 (sym+add)@dtprel@higher */
+#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */
+#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */
+#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel@highesta */
+
+/* Keep this the last entry. */
+#define R_PPC64_NUM 107
+
+/* 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_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_GOTOFF32 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. */
+#define R_390_GOTOFF16 27 /* 16 bit offset to GOT. */
+#define R_390_GOTOFF64 28 /* 64 bit offset to GOT. */
+#define R_390_GOTPLT12 29 /* 12 bit offset to jump slot. */
+#define R_390_GOTPLT16 30 /* 16 bit offset to jump slot. */
+#define R_390_GOTPLT32 31 /* 32 bit offset to jump slot. */
+#define R_390_GOTPLT64 32 /* 64 bit offset to jump slot. */
+#define R_390_GOTPLTENT 33 /* 32 bit rel. offset to jump slot. */
+#define R_390_PLTOFF16 34 /* 16 bit offset from GOT to PLT. */
+#define R_390_PLTOFF32 35 /* 32 bit offset from GOT to PLT. */
+#define R_390_PLTOFF64 36 /* 16 bit offset from GOT to PLT. */
+#define R_390_TLS_LOAD 37 /* Tag for load insn in TLS code. */
+#define R_390_TLS_GDCALL 38 /* Tag for function call in general
+ dynamic TLS code. */
+#define R_390_TLS_LDCALL 39 /* Tag for function call in local
+ dynamic TLS code. */
+#define R_390_TLS_GD32 40 /* Direct 32 bit for general dynamic
+ thread local data. */
+#define R_390_TLS_GD64 41 /* Direct 64 bit for general dynamic
+ thread local data. */
+#define R_390_TLS_GOTIE12 42 /* 12 bit GOT offset for static TLS
+ block offset. */
+#define R_390_TLS_GOTIE32 43 /* 32 bit GOT offset for static TLS
+ block offset. */
+#define R_390_TLS_GOTIE64 44 /* 64 bit GOT offset for static TLS
+ block offset. */
+#define R_390_TLS_LDM32 45 /* Direct 32 bit for local dynamic
+ thread local data in LE code. */
+#define R_390_TLS_LDM64 46 /* Direct 64 bit for local dynamic
+ thread local data in LE code. */
+#define R_390_TLS_IE32 47 /* 32 bit address of GOT entry for
+ negated static TLS block offset. */
+#define R_390_TLS_IE64 48 /* 64 bit address of GOT entry for
+ negated static TLS block offset. */
+#define R_390_TLS_IEENT 49 /* 32 bit rel. offset to GOT entry for
+ negated static TLS block offset. */
+#define R_390_TLS_LE32 50 /* 32 bit negated offset relative to
+ static TLS block. */
+#define R_390_TLS_LE64 51 /* 64 bit negated offset relative to
+ static TLS block. */
+#define R_390_TLS_LDO32 52 /* 32 bit offset relative to TLS
+ block. */
+#define R_390_TLS_LDO64 53 /* 64 bit offset relative to TLS
+ block. */
+#define R_390_TLS_DTPMOD 54 /* ID of module containing symbol. */
+#define R_390_TLS_DTPOFF 55 /* Offset in TLS block. */
+#define R_390_TLS_TPOFF 56 /* Negated offset in static TLS
+ block. */
+
+/* Keep this the last entry. */
+#define R_390_NUM 57
+
+/* 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 /* elf.h */
diff --git a/include/x86/mb_header.h b/include/x86/mb_header.h
new file mode 100644
index 0000000..9bf5e6c
--- /dev/null
+++ b/include/x86/mb_header.h
@@ -0,0 +1,90 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * MultiBoot Header description
+ */
+
+struct multiboot_header
+{
+ /* Must be MULTIBOOT_MAGIC - see below. */
+ uint32_t magic;
+
+ /* Feature flags - see below. */
+ uint32_t flags;
+
+ /*
+ * Checksum
+ *
+ * The above fields plus this one must equal 0 mod 2^32.
+ */
+ uint32_t checksum;
+
+ /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */
+ uint32_t header_addr;
+ uint32_t load_addr;
+ uint32_t load_end_addr;
+ uint32_t bss_end_addr;
+ uint32_t entry_addr;
+
+ /* These are only valid if MULTIBOOT_VIDEO_MODE is set. */
+ uint32_t mode_type;
+ uint32_t width;
+ uint32_t height;
+ uint32_t depth;
+};
+
+/*
+ * The entire multiboot_header must be contained
+ * within the first MULTIBOOT_SEARCH bytes of the kernel image.
+ */
+#define MULTIBOOT_SEARCH 8192
+#define MULTIBOOT_FOUND(addr, len) \
+ (! ((addr) & 0x3) \
+ && (len) >= 12 \
+ && *((int *) (addr)) == MULTIBOOT_MAGIC \
+ && ! (*((uint32_t *) (addr)) + *((uint32_t *) (addr + 4)) \
+ + *((uint32_t *) (addr + 8))) \
+ && (! (MULTIBOOT_AOUT_KLUDGE & *((int *) (addr + 4))) || (len) >= 32) \
+ && (! (MULTIBOOT_VIDEO_MODE & *((int *) (addr + 4))) || (len) >= 48))
+
+/* Magic value identifying the multiboot_header. */
+#define MULTIBOOT_MAGIC 0x1BADB002
+
+/*
+ * Features flags for 'flags'.
+ * If a boot loader sees a flag in MULTIBOOT_MUSTKNOW set
+ * and it doesn't understand it, it must fail.
+ */
+#define MULTIBOOT_MUSTKNOW 0x0000FFFF
+
+/* currently unsupported flags... this is a kind of version number. */
+#define MULTIBOOT_UNSUPPORTED 0x0000FFF8
+
+/* Align all boot modules on i386 page (4KB) boundaries. */
+#define MULTIBOOT_PAGE_ALIGN 0x00000001
+
+/* Must pass memory information to OS. */
+#define MULTIBOOT_MEMORY_INFO 0x00000002
+
+/* Must pass video information to OS. */
+#define MULTIBOOT_VIDEO_MODE 0x00000004
+
+/* This flag indicates the use of the address fields in the header. */
+#define MULTIBOOT_AOUT_KLUDGE 0x00010000
diff --git a/include/x86/mb_info.h b/include/x86/mb_info.h
new file mode 100644
index 0000000..317bdfa
--- /dev/null
+++ b/include/x86/mb_info.h
@@ -0,0 +1,219 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * The structure type "mod_list" is used by the "multiboot_info" structure.
+ */
+
+struct mod_list
+{
+ /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */
+ uint32_t mod_start;
+ uint32_t mod_end;
+
+ /* Module command line */
+ uint32_t cmdline;
+
+ /* padding to take it to 16 bytes (must be zero) */
+ uint32_t pad;
+};
+
+
+/*
+ * INT-15, AX=E820 style "AddressRangeDescriptor"
+ * ...with a "size" parameter on the front which is the structure size - 4,
+ * pointing to the next one, up until the full buffer length of the memory
+ * map has been reached.
+ */
+
+struct AddrRangeDesc
+{
+ uint32_t size;
+ uint32_t base_addr_low;
+ uint32_t base_addr_high;
+ uint32_t length_low;
+ uint32_t length_high;
+ uint32_t Type;
+
+ /* unspecified optional padding... */
+};
+
+/* usable memory "Type", all others are reserved. */
+#define MB_ARD_MEMORY 1
+
+
+/* Drive Info structure. */
+struct drive_info
+{
+ /* The size of this structure. */
+ uint32_t size;
+
+ /* The BIOS drive number. */
+ uint8_t drive_number;
+
+ /* The access mode (see below). */
+ uint8_t drive_mode;
+
+ /* The BIOS geometry. */
+ uint16_t drive_cylinders;
+ uint8_t drive_heads;
+ uint8_t drive_sectors;
+
+ /* The array of I/O ports used for the drive. */
+ uint16_t drive_ports[0];
+};
+
+/* Drive Mode. */
+#define MB_DI_CHS_MODE 0
+#define MB_DI_LBA_MODE 1
+
+
+/* APM BIOS info. */
+struct apm_info
+{
+ uint16_t version;
+ uint16_t cseg;
+ uint32_t offset;
+ uint32_t cseg_16;
+ uint32_t dseg_16;
+ uint32_t cseg_len;
+ uint32_t cseg_16_len;
+ uint32_t dseg_16_len;
+};
+
+
+/*
+ * MultiBoot Info description
+ *
+ * This is the struct passed to the boot image. This is done by placing
+ * its address in the EAX register.
+ */
+
+struct multiboot_info
+{
+ /* MultiBoot info version number */
+ uint32_t flags;
+
+ /* Available memory from BIOS */
+ uint32_t mem_lower;
+ uint32_t mem_upper;
+
+ /* "root" partition */
+ uint32_t boot_device;
+
+ /* Kernel command line */
+ uint32_t cmdline;
+
+ /* Boot-Module list */
+ uint32_t mods_count;
+ uint32_t mods_addr;
+
+ union
+ {
+ struct
+ {
+ /* (a.out) Kernel symbol table info */
+ uint32_t tabsize;
+ uint32_t strsize;
+ uint32_t addr;
+ uint32_t pad;
+ }
+ a;
+
+ struct
+ {
+ /* (ELF) Kernel section header table */
+ uint32_t num;
+ uint32_t size;
+ uint32_t addr;
+ uint32_t shndx;
+ }
+ e;
+ }
+ syms;
+
+ /* Memory Mapping buffer */
+ uint32_t mmap_length;
+ uint32_t mmap_addr;
+
+ /* Drive Info buffer */
+ uint32_t drives_length;
+ uint32_t drives_addr;
+
+ /* ROM configuration table */
+ uint32_t config_table;
+
+ /* Boot Loader Name */
+ uint32_t boot_loader_name;
+
+ /* APM table */
+ uint32_t apm_table;
+
+ /* Video */
+ uint32_t vbe_control_info;
+ uint32_t vbe_mode_info;
+ uint16_t vbe_mode;
+ uint16_t vbe_interface_seg;
+ uint16_t vbe_interface_off;
+ uint16_t vbe_interface_len;
+};
+
+/*
+ * Flags to be set in the 'flags' parameter above
+ */
+
+/* is there basic lower/upper memory information? */
+#define MB_INFO_MEMORY 0x00000001
+/* is there a boot device set? */
+#define MB_INFO_BOOTDEV 0x00000002
+/* is the command-line defined? */
+#define MB_INFO_CMDLINE 0x00000004
+/* are there modules to do something with? */
+#define MB_INFO_MODS 0x00000008
+
+/* These next two are mutually exclusive */
+
+/* is there a symbol table loaded? */
+#define MB_INFO_AOUT_SYMS 0x00000010
+/* is there an ELF section header table? */
+#define MB_INFO_ELF_SHDR 0x00000020
+
+/* is there a full memory map? */
+#define MB_INFO_MEM_MAP 0x00000040
+
+/* Is there drive info? */
+#define MB_INFO_DRIVE_INFO 0x00000080
+
+/* Is there a config table? */
+#define MB_INFO_CONFIG_TABLE 0x00000100
+
+/* Is there a boot loader name? */
+#define MB_INFO_BOOT_LOADER_NAME 0x00000200
+
+/* Is there a APM table? */
+#define MB_INFO_APM_TABLE 0x00000400
+
+/* Is there video information? */
+#define MB_INFO_VIDEO_INFO 0x00000800
+
+/*
+ * The following value must be present in the EAX register.
+ */
+
+#define MULTIBOOT_VALID 0x2BADB002
diff --git a/include/x86/x86-linux.h b/include/x86/x86-linux.h
new file mode 100644
index 0000000..daab50a
--- /dev/null
+++ b/include/x86/x86-linux.h
@@ -0,0 +1,212 @@
+#ifndef X86_LINUX_H
+#define X86_LINUX_H
+
+#define TENATIVE 0 /* Code that is tenatively correct but hasn't yet been officially accepted */
+
+#define E820MAP 0x2d0 /* our map */
+#define E820MAX 32 /* number of entries in E820MAP */
+#define E820NR 0x1e8 /* # entries in E820MAP */
+
+#ifndef ASSEMBLY
+
+#define PACKED __attribute__((packed))
+
+struct e820entry {
+ uint64_t addr; /* start of memory segment */
+ uint64_t size; /* size of memory segment */
+ uint32_t type; /* type of memory segment */
+#define E820_RAM 1
+#define E820_RESERVED 2
+#define E820_ACPI 3 /* usable as RAM once ACPI tables have been read */
+#define E820_NVS 4
+} PACKED;
+
+/* FIXME expand on drive_info_)struct... */
+struct drive_info_struct {
+ uint8_t dummy[32];
+};
+struct sys_desc_table {
+ uint16_t length;
+ uint8_t table[318];
+};
+
+struct apm_bios_info {
+ uint16_t version; /* 0x40 */
+ uint16_t cseg; /* 0x42 */
+ uint32_t offset; /* 0x44 */
+ uint16_t cseg_16; /* 0x48 */
+ uint16_t dseg; /* 0x4a */
+ uint16_t flags; /* 0x4c */
+ uint16_t cseg_len; /* 0x4e */
+ uint16_t cseg_16_len; /* 0x50 */
+ uint16_t dseg_len; /* 0x52 */
+ uint8_t reserved[44]; /* 0x54 */
+};
+
+
+struct x86_linux_param_header {
+ uint8_t orig_x; /* 0x00 */
+ uint8_t orig_y; /* 0x01 */
+ uint16_t ext_mem_k; /* 0x02 -- EXT_MEM_K sits here */
+ uint16_t orig_video_page; /* 0x04 */
+ uint8_t orig_video_mode; /* 0x06 */
+ uint8_t orig_video_cols; /* 0x07 */
+ uint16_t unused2; /* 0x08 */
+ uint16_t orig_video_ega_bx; /* 0x0a */
+ uint16_t unused3; /* 0x0c */
+ uint8_t orig_video_lines; /* 0x0e */
+ uint8_t orig_video_isVGA; /* 0x0f */
+ uint16_t orig_video_points; /* 0x10 */
+
+ /* VESA graphic mode -- linear frame buffer */
+ uint16_t lfb_width; /* 0x12 */
+ uint16_t lfb_height; /* 0x14 */
+ uint16_t lfb_depth; /* 0x16 */
+ uint32_t lfb_base; /* 0x18 */
+ uint32_t lfb_size; /* 0x1c */
+ uint16_t cl_magic; /* 0x20 */
+#define CL_MAGIC_VALUE 0xA33F
+ uint16_t cl_offset; /* 0x22 */
+ uint16_t lfb_linelength; /* 0x24 */
+ uint8_t red_size; /* 0x26 */
+ uint8_t red_pos; /* 0x27 */
+ uint8_t green_size; /* 0x28 */
+ uint8_t green_pos; /* 0x29 */
+ uint8_t blue_size; /* 0x2a */
+ uint8_t blue_pos; /* 0x2b */
+ uint8_t rsvd_size; /* 0x2c */
+ uint8_t rsvd_pos; /* 0x2d */
+ uint16_t vesapm_seg; /* 0x2e */
+ uint16_t vesapm_off; /* 0x30 */
+ uint16_t pages; /* 0x32 */
+ uint8_t reserved4[12]; /* 0x34 -- 0x3f reserved for future expansion */
+
+ struct apm_bios_info apm_bios_info; /* 0x40 */
+ struct drive_info_struct drive_info; /* 0x80 */
+ struct sys_desc_table sys_desc_table; /* 0xa0 */
+ uint32_t alt_mem_k; /* 0x1e0 */
+ uint8_t reserved5[4]; /* 0x1e4 */
+ uint8_t e820_map_nr; /* 0x1e8 */
+ uint8_t reserved6[8]; /* 0x1e9 */
+ uint8_t setup_sects; /* 0x1f1 */
+ uint16_t mount_root_rdonly; /* 0x1f2 */
+ uint16_t syssize; /* 0x1f4 */
+ uint16_t swapdev; /* 0x1f6 */
+ uint16_t ramdisk_flags; /* 0x1f8 */
+#define RAMDISK_IMAGE_START_MASK 0x07FF
+#define RAMDISK_PROMPT_FLAG 0x8000
+#define RAMDISK_LOAD_FLAG 0x4000
+ uint16_t vid_mode; /* 0x1fa */
+ uint16_t root_dev; /* 0x1fc */
+ uint8_t reserved9[1]; /* 0x1fe */
+ uint8_t aux_device_info; /* 0x1ff */
+ /* 2.00+ */
+ uint8_t reserved10[2]; /* 0x200 */
+ uint8_t header_magic[4]; /* 0x202 */
+ uint16_t protocol_version; /* 0x206 */
+ uint16_t rmode_switch_ip; /* 0x208 */
+ uint16_t rmode_switch_cs; /* 0x20a */
+ uint8_t reserved11[4]; /* 0x208 */
+ uint8_t loader_type; /* 0x210 */
+#define LOADER_TYPE_LOADLIN 1
+#define LOADER_TYPE_BOOTSECT_LOADER 2
+#define LOADER_TYPE_SYSLINUX 3
+#define LOADER_TYPE_ETHERBOOT 4
+#define LOADER_TYPE_UNKNOWN 0xFF
+ uint8_t loader_flags; /* 0x211 */
+ uint8_t reserved12[2]; /* 0x212 */
+ uint32_t kernel_start; /* 0x214 */
+ uint32_t initrd_start; /* 0x218 */
+ uint32_t initrd_size; /* 0x21c */
+ uint8_t reserved13[4]; /* 0x220 */
+ /* 2.01+ */
+ uint16_t heap_end_ptr; /* 0x224 */
+ uint8_t reserved14[2]; /* 0x226 */
+ /* 2.02+ */
+ uint32_t cmd_line_ptr; /* 0x228 */
+ /* 2.03+ */
+ uint32_t initrd_addr_max; /* 0x22c */
+#if TENATIVE
+ /* 2.04+ */
+ uint16_t entry32_off; /* 0x230 */
+ uint16_t internal_cmdline_off; /* 0x232 */
+ uint32_t low_base; /* 0x234 */
+ uint32_t low_memsz; /* 0x238 */
+ uint32_t low_filesz; /* 0x23c */
+ uint32_t real_base; /* 0x240 */
+ uint32_t real_memsz; /* 0x244 */
+ uint32_t real_filesz; /* 0x248 */
+ uint32_t high_base; /* 0x24C */
+ uint32_t high_memsz; /* 0x250 */
+ uint32_t high_filesz; /* 0x254 */
+ uint8_t reserved15[0x2d0 - 0x258]; /* 0x258 */
+#else
+ uint8_t reserved15[0x2d0 - 0x230]; /* 0x230 */
+#endif
+ struct e820entry e820_map[E820MAX]; /* 0x2d0 */
+ /* 0x550 */
+#define COMMAND_LINE_SIZE 256
+};
+
+struct x86_linux_faked_param_header {
+ struct x86_linux_param_header hdr; /* 0x00 */
+ uint8_t reserved16[688]; /* 0x550 */
+ uint8_t command_line[COMMAND_LINE_SIZE]; /* 0x800 */
+ uint8_t reserved17[1792]; /* 0x900 - 0x1000 */
+};
+
+struct x86_linux_header {
+ uint8_t reserved1[0x1f1]; /* 0x000 */
+ uint8_t setup_sects; /* 0x1f1 */
+ uint16_t root_flags; /* 0x1f2 */
+ uint16_t syssize; /* 0x1f4 */
+ uint16_t swapdev; /* 0x1f6 */
+ uint16_t ramdisk_flags; /* 0x1f6 */
+ uint16_t vid_mode; /* 0x1fa */
+ uint16_t root_dev; /* 0x1fc */
+ uint16_t boot_sector_magic; /* 0x1fe */
+ /* 2.00+ */
+ uint8_t reserved3[2]; /* 0x200 */
+ uint8_t header_magic[4]; /* 0x202 */
+ uint16_t protocol_version; /* 0x206 */
+ uint32_t realmode_swtch; /* 0x208 */
+ uint16_t start_sys; /* 0x20c */
+ uint16_t kver_addr; /* 0x20e */
+ uint8_t type_of_loader; /* 0x210 */
+ uint8_t loadflags; /* 0x211 */
+ uint16_t setup_move_size; /* 0x212 */
+ uint32_t code32_start; /* 0x214 */
+ uint32_t ramdisk_image; /* 0x218 */
+ uint32_t ramdisk_size; /* 0x21c */
+ uint8_t reserved4[4]; /* 0x220 */
+ /* 2.01+ */
+ uint16_t heap_end_ptr; /* 0x224 */
+ uint8_t reserved5[2]; /* 0x226 */
+ /* 2.02+ */
+ uint32_t cmd_line_ptr; /* 0x228 */
+ /* 2.03+ */
+ uint32_t initrd_addr_max; /* 0x22c */
+#if TENATIVE
+ /* 2.04+ */
+ uint16_t entry32_off; /* 0x230 */
+ uint16_t internal_cmdline_off; /* 0x232 */
+ uint32_t low_base; /* 0x234 */
+ uint32_t low_memsz; /* 0x238 */
+ uint32_t low_filesz; /* 0x23c */
+ uint32_t real_base; /* 0x240 */
+ uint32_t real_memsz; /* 0x244 */
+ uint32_t real_filesz; /* 0x248 */
+ uint32_t high_base; /* 0x24C */
+ uint32_t high_memsz; /* 0x250 */
+ uint32_t high_filesz; /* 0x254 */
+ uint32_t tail[32*1024 - 0x258]; /* 0x258 */
+#else
+ uint8_t tail[32*1024 - 0x230]; /* 0x230 */
+#endif
+} PACKED;
+
+#endif /* ASSEMBLY */
+
+#define DEFAULT_INITRD_ADDR_MAX 0x37FFFFFF
+
+#endif /* X86_LINUX_H */
diff --git a/kdump/Makefile b/kdump/Makefile
new file mode 100644
index 0000000..d9a7ab7
--- /dev/null
+++ b/kdump/Makefile
@@ -0,0 +1,35 @@
+#
+# kdump (reading a crashdump from memory)
+#
+
+KDUMP_C_SRCS:= kdump/kdump.c
+
+KDUMP_C_OBJS:= $(patsubst %.c, $(OBJDIR)/%.o, $(KDUMP_C_SRCS))
+KDUMP_C_DEPS:= $(patsubst %.c, $(OBJDIR)/%.d, $(KDUMP_C_SRCS))
+KDUMP_SRCS:= $(KDUMP_C_SRCS)
+KDUMP_OBJS:= $(KDUMP_C_OBJS)
+KDUMP_DEPS:= $(KDUMP_C_DEPS)
+KDUMP:= $(SBINDIR)/kdump
+
+include $(KDUMP_DEPS)
+
+$(KDUMP_C_DEPS): $(OBJDIR)/%.d: %.c
+ mkdir -p $(@D)
+ $(CC) $(CFLAGS) -M $< | sed -e 's|$(patsubst %.d,%.o,$(@F))|$(patsubst %.d,%.o,$(@))|' > $@
+
+$(KDUMP_C_OBJS): $(OBJDIR)/%.o: %.c $(OBJDIR)/%.d
+ mkdir -p $(@D)
+ $(CC) $(CFLAGS) -o $@ -c $<
+
+$(KDUMP): $(KDUMP_OBJS)
+ mkdir -p $(@D)
+ $(CC) $(CFLAGS) -o $@ $(KDUMP_OBJS)
+
+echo::
+ @echo "KDUMP_C_SRCS $(KDUMP_C_SRCS)"
+ @echo "KDUMP_C_DEPS $(KDUMP_C_DEPS)"
+ @echo "KDUMP_C_OBJS $(KDUMP_C_OBJS)"
+ @echo "KDUMP_SRCS $(KDUMP_SRCS)"
+ @echo "KDUMP_DEPS $(KDUMP_DEPS)"
+ @echo "KDUMP_OBJS $(KDUMP_OBJS)"
+
diff --git a/kdump/kdump.c b/kdump/kdump.c
new file mode 100644
index 0000000..6745982
--- /dev/null
+++ b/kdump/kdump.c
@@ -0,0 +1,311 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <endian.h>
+#include <elf.h>
+
+#if !defined(__BYTE_ORDER) || !defined(__LITTLE_ENDIAN) || !defined(__BIG_ENDIAN)
+#error Endian defines missing
+#endif
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# define ELFDATALOCAL ELFDATA2LSB
+#elif __BYTE_ORDER == __BIG_ENDIAN
+# define ELFDATALOCAL ELFDATA2MSB
+#else
+# error Unknown byte order
+#endif
+
+#define MAP_WINDOW_SIZE (64*1024*1024)
+#define DEV_MEM "/dev/mem"
+
+static void *map_addr(int fd, unsigned long size, off_t offset)
+{
+ void *result;
+ result = mmap(0, size, PROT_READ, MAP_SHARED, fd, offset);
+ if (result == MAP_FAILED) {
+ fprintf(stderr, "Cannot mmap " DEV_MEM " offset: %llu size: %lu: %s\n",
+ (unsigned long long)offset, size, strerror(errno));
+ exit(5);
+ }
+ return result;
+}
+
+static void unmap_addr(void *addr, unsigned long size)
+{
+ int ret;
+ ret = munmap(addr, size);
+ if (ret < 0) {
+ fprintf(stderr, "munmap failed: %s\n",
+ strerror(errno));
+ exit(6);
+ }
+}
+
+static void *xmalloc(size_t size)
+{
+ void *result;
+ result = malloc(size);
+ if (result == NULL) {
+ fprintf(stderr, "malloc of %u bytes failed: %s\n",
+ size, strerror(errno));
+ exit(7);
+ }
+ return result;
+}
+
+static void *collect_notes(
+ int fd, Elf64_Ehdr *ehdr, Elf64_Phdr *phdr, size_t *note_bytes)
+{
+ int i;
+ size_t bytes, result_bytes;
+ char *notes;
+
+ result_bytes = 0;
+ /* Find the worst case note memory usage */
+ bytes = 0;
+ for(i = 0; i < ehdr->e_phnum; i++) {
+ if (phdr[i].p_type == PT_NOTE) {
+ bytes += phdr[i].p_filesz;
+ }
+ }
+
+ /* Allocate the worst case note array */
+ notes = xmalloc(bytes);
+
+ /* Walk through and capture the notes */
+ for(i = 0; i < ehdr->e_phnum; i++) {
+ Elf64_Nhdr *hdr, *lhdr, *nhdr;
+ void *pnotes;
+ if (phdr[i].p_type != PT_NOTE) {
+ continue;
+ }
+ /* First snapshot the notes */
+ pnotes = map_addr(fd, phdr[i].p_filesz, phdr[i].p_offset);
+ memcpy(notes + result_bytes, pnotes, phdr[i].p_filesz);
+ unmap_addr(pnotes, phdr[i].p_filesz);
+
+ /* Walk through the new notes and find the real length */
+ hdr = (Elf64_Nhdr *)(notes + result_bytes);
+ lhdr = (Elf64_Nhdr *)(notes + result_bytes + phdr[i].p_filesz);
+ for(; hdr < lhdr; hdr = nhdr) {
+ size_t hdr_size;
+ /* If there is not a name this is a invalid/reserved note
+ * stop here.
+ */
+ if (hdr->n_namesz == 0) {
+ break;
+ }
+ hdr_size =
+ sizeof(*hdr) +
+ ((hdr->n_namesz + 3) & ~3) +
+ ((hdr->n_descsz + 3) & ~3);
+
+ nhdr = (Elf64_Nhdr *)(((char *)hdr) + hdr_size);
+ /* if the note does not fit in the segment stop here */
+ if (nhdr > lhdr) {
+ break;
+ }
+ /* Update result_bytes for after each good header */
+ result_bytes = ((char *)hdr) - notes;
+ }
+ }
+ *note_bytes = result_bytes;
+ return notes;
+}
+
+static void *generate_new_headers(
+ Elf64_Ehdr *ehdr, Elf64_Phdr *phdr, size_t note_bytes, size_t *header_bytes)
+{
+ unsigned phnum;
+ size_t bytes;
+ char *headers;
+ Elf64_Ehdr *nehdr;
+ Elf64_Phdr *nphdr;
+ unsigned long long offset;
+ int i;
+ /* Count the number of program headers.
+ * When we are done there will be only one note header.
+ */
+ phnum = 1;
+ for(i = 0; i < ehdr->e_phnum; i++) {
+ if (phdr[i].p_type == PT_NOTE) {
+ continue;
+ }
+ phnum++;
+ }
+
+ /* Compute how many bytes we will need for headers */
+ bytes = sizeof(*ehdr) + sizeof(*phdr)*phnum;
+
+ /* Allocate memory for the headers */
+ headers = xmalloc(bytes);
+
+ /* Setup pointers to the new headers */
+ nehdr = (Elf64_Ehdr *)headers;
+ nphdr = (Elf64_Phdr *)(headers + sizeof(*nehdr));
+
+ /* Copy and adjust the Elf header */
+ memcpy(nehdr, ehdr, sizeof(*nehdr));
+ nehdr->e_phoff = sizeof(*nehdr);
+ nehdr->e_phnum = phnum;
+ nehdr->e_shoff = 0;
+ nehdr->e_shentsize = 0;
+ nehdr->e_shnum = 0;
+ nehdr->e_shstrndx = 0;
+
+ /* Write the note program header */
+ nphdr->p_type = PT_NOTE;
+ nphdr->p_offset = bytes;
+ nphdr->p_vaddr = 0;
+ nphdr->p_paddr = 0;
+ nphdr->p_filesz = note_bytes;
+ nphdr->p_memsz = note_bytes;
+ nphdr->p_flags = 0;
+ nphdr->p_align = 0;
+ nphdr++;
+
+ /* Write the rest of the program headers */
+ offset = bytes + note_bytes;
+ for(i = 0; i < ehdr->e_phnum; i++) {
+ if (phdr[i].p_type == PT_NOTE) {
+ continue;
+ }
+ memcpy(nphdr, &phdr[i], sizeof(*nphdr));
+ nphdr->p_offset = offset;
+ offset += phdr[i].p_filesz;
+ }
+
+ *header_bytes = bytes;
+ return headers;
+}
+
+static void write_all(int fd, const void *buf, size_t count)
+{
+ ssize_t result, written;
+ const char *ptr;
+ size_t left;
+ ptr = buf;
+ left = count;
+ do {
+ result = write(fd, ptr, left);
+ if (result >= 0) {
+ written += result;
+ ptr += result;
+ left -= result;
+ }
+ else if ((errno != EAGAIN) && (errno != EINTR)) {
+ fprintf(stderr, "write failed: %s\n",
+ strerror(errno));
+ exit(8);
+ }
+ } while(written < count);
+}
+
+int main(int argc, char **argv)
+{
+ char *start_addr_str, *end;
+ unsigned long long start_addr;
+ Elf64_Ehdr *ehdr;
+ Elf64_Phdr *phdr;
+ void *notes, *headers;
+ size_t note_bytes, header_bytes;
+ int fd;
+ int i;
+ start_addr_str = 0;
+ if (argc > 2) {
+ fprintf(stderr, "Invalid argument count\n");
+ exit(9);
+ }
+ if (argc == 2) {
+ start_addr_str = argv[1];
+ }
+ if (!start_addr_str) {
+ start_addr_str = getenv("elfcorehdr");
+ }
+ if (!start_addr_str) {
+ fprintf(stderr, "Cannot find the start of the core dump\n");
+ exit(1);
+ }
+ start_addr = strtoull(start_addr_str, &end, 0);
+ if ((start_addr_str == end) || (*end != '\0')) {
+ fprintf(stderr, "Bad core dump start addres: %s\n",
+ start_addr_str);
+ exit(2);
+ }
+
+ fd = open(DEV_MEM, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "Cannot open " DEV_MEM ": %s\n",
+ strerror(errno));
+ exit(3);
+ }
+
+ /* Get the elf header */
+ ehdr = map_addr(fd, sizeof(*ehdr), start_addr);
+
+ /* Verify the ELF header */
+ if ( (ehdr->e_ident[EI_MAG0] != ELFMAG0) ||
+ (ehdr->e_ident[EI_MAG1] != ELFMAG1) ||
+ (ehdr->e_ident[EI_MAG2] != ELFMAG2) ||
+ (ehdr->e_ident[EI_MAG3] != ELFMAG3) ||
+ (ehdr->e_ident[EI_CLASS] != ELFCLASS64) ||
+ (ehdr->e_ident[EI_DATA] != ELFDATALOCAL) ||
+ (ehdr->e_ident[EI_VERSION] != EV_CURRENT) ||
+ (ehdr->e_type != ET_CORE) ||
+ (ehdr->e_version != EV_CURRENT) ||
+ (ehdr->e_ehsize != sizeof(Elf64_Ehdr)) ||
+ (ehdr->e_phentsize != sizeof(Elf64_Phdr)) ||
+ (ehdr->e_phnum == 0))
+ {
+ fprintf(stderr, "Invalid Elf header\n");
+ exit(4);
+ }
+
+ /* Get the program header */
+ phdr = map_addr(fd, sizeof(*phdr)*(ehdr->e_phnum), ehdr->e_phoff);
+
+ /* Collect up the notes */
+ note_bytes = 0;
+ notes = collect_notes(fd, ehdr, phdr, &note_bytes);
+
+ /* Generate new headers */
+ header_bytes = 0;
+ headers = generate_new_headers(ehdr, phdr, note_bytes, &header_bytes);
+
+ /* Write out everything */
+ write_all(STDOUT_FILENO, headers, header_bytes);
+ write_all(STDOUT_FILENO, notes, note_bytes);
+ for(i = 0; i < ehdr->e_phnum; i++) {
+ unsigned long long offset, size;
+ size_t wsize;
+ if (phdr[i].p_type != PT_NOTE) {
+ continue;
+ }
+ offset = phdr[i].p_offset;
+ size = phdr[i].p_filesz;
+ wsize = MAP_WINDOW_SIZE;
+ if (wsize > size) {
+ wsize = size;
+ }
+ for(;size > 0; size -= wsize, offset += wsize) {
+ void *buf;
+ wsize = MAP_WINDOW_SIZE;
+ if (wsize > size) {
+ wsize = size;
+ }
+ buf = map_addr(fd, wsize, offset);
+ write_all(STDOUT_FILENO, buf, wsize);
+ unmap_addr(buf, wsize);
+ }
+ }
+ free(notes);
+ close(fd);
+ return 0;
+}
diff --git a/kexec-tools.spec.in b/kexec-tools.spec.in
new file mode 100644
index 0000000..6605cbb
--- /dev/null
+++ b/kexec-tools.spec.in
@@ -0,0 +1,40 @@
+Summary: Load one kernel from another
+Name: kexec-tools
+Version:
+Release: 0
+Copyright: GPL
+Group: Development/Tools
+Source0:%{name}-%{version}.tar.gz
+Packager: Eric Biederman <ebiederman@xmission.com>
+BuildRoot: %{_tmppath}/%{name}
+
+%description
+/sbin/kexec is a user space utiltity for loading another kernel
+and asking the currently running kernel to do something with it.
+A currently running kernel may be asked to start the loaded
+kernel on reboot, or to start the loaded kernel after it panics.
+
+The panic case is useful for having an intact kernel for writing
+crash dumps. But other uses may be imagined.
+
+%prep
+%setup -q -n %{name}-%{version}
+
+%build
+%configure
+make
+
+%install
+make install DESTDIR=${RPM_BUILD_ROOT}
+
+%files
+%defattr(-,root,root)
+%{_sbindir}/kexec
+%doc News
+%doc COPYING
+%doc TODO
+#%{_mandir}/man8/kexec.8.gz
+
+%changelog
+* Tue Dec 16 2004 Eric Biederman <ebiederman@lnxi.com>
+- kexec-tools initialy packaged as an rpm.
diff --git a/kexec/Makefile b/kexec/Makefile
new file mode 100644
index 0000000..812da81
--- /dev/null
+++ b/kexec/Makefile
@@ -0,0 +1,63 @@
+#
+# kexec (linux booting linux)
+#
+PURGATORY_HEX_C:= $(OBJDIR)/kexec/purgatory.c
+
+$(PURGATORY_HEX_C): $(PURGATORY) $(BIN_TO_HEX)
+ $(MKDIR) -p $(@D)
+ $(BIN_TO_HEX) purgatory < $(PURGATORY) > $@
+
+KCFLAGS:= $(CFLAGS) -Ikexec/arch/$(ARCH)/include
+
+KEXEC_C_SRCS:= kexec/kexec.c
+KEXEC_C_SRCS+= kexec/ifdown.c
+KEXEC_C_SRCS+= kexec/kexec-elf.c
+KEXEC_C_SRCS+= kexec/kexec-elf-exec.c
+KEXEC_C_SRCS+= kexec/kexec-elf-rel.c
+KEXEC_C_SRCS+= kexec/kexec-elf-boot.c
+KEXEC_C_SRCS+= $(PURGATORY_HEX_C)
+KEXEC_S_SRCS:=
+include kexec/arch/$(ARCH)/Makefile
+
+KEXEC_C_OBJS:= $(patsubst %.c, $(OBJDIR)/%.o, $(KEXEC_C_SRCS))
+KEXEC_C_DEPS:= $(patsubst %.c, $(OBJDIR)/%.d, $(KEXEC_C_SRCS))
+KEXEC_S_OBJS:= $(patsubst %.S, $(OBJDIR)/%.o, $(KEXEC_S_SRCS))
+KEXEC_S_DEPS:= $(patsubst %.S, $(OBJDIR)/%.d, $(KEXEC_S_SRCS))
+KEXEC_SRCS:= $(KEXEC_C_SRCS) $(KEXEC_S_SRCS)
+KEXEC_OBJS:= $(KEXEC_C_OBJS) $(KEXEC_S_OBJS)
+KEXEC_DEPS:= $(KEXEC_C_DEPS) $(KEXEC_S_DEPS)
+KEXEC:= $(SBINDIR)/kexec
+
+include $(KEXEC_DEPS)
+
+$(KEXEC_C_DEPS): $(OBJDIR)/%.d: %.c
+ mkdir -p $(@D)
+ $(CC) $(KCFLAGS) -M $< | sed -e 's|$(patsubst %.d,%.o,$(@F))|$(patsubst %.d,%.o,$(@))|' > $@
+
+$(KEXEC_S_DEPS): $(OBJDIR)/%.d: %.S
+ mkdir -p $(@D)
+ $(CC) $(KCFLAGS) -M $< | sed -e 's|$(patsubst %.d,%.o,$(@F))|$(patsubst %.d,%.o,$(@))|' > $@
+
+$(KEXEC_C_OBJS): $(OBJDIR)/%.o: %.c $(OBJDIR)/%.d
+ mkdir -p $(@D)
+ $(CC) $(KCFLAGS) -o $@ -c $<
+
+$(KEXEC_S_OBJS): $(OBJDIR)/%.o: %.S $(OBJDIR)/%.d
+ mkdir -p $(@D)
+ $(CC) $(KCFLAGS) -o $@ -c $<
+
+$(KEXEC): $(KEXEC_OBJS) $(UTIL_LIB)
+ mkdir -p $(@D)
+ $(CC) $(KCFLAGS) -o $@ $(KEXEC_OBJS) $(UTIL_LIB) $(LIBS)
+
+echo::
+ @echo "KEXEC_C_SRCS $(KEXEC_C_SRCS)"
+ @echo "KEXEC_C_DEPS $(KEXEC_C_DEPS)"
+ @echo "KEXEC_C_OBJS $(KEXEC_C_OBJS)"
+ @echo "KEXEC_S_SRCS $(KEXEC_S_SRCS)"
+ @echo "KEXEC_S_DEPS $(KEXEC_S_DEPS)"
+ @echo "KEXEC_S_OBJS $(KEXEC_S_OBJS)"
+ @echo "KEXEC_SRCS $(KEXEC_SRCS)"
+ @echo "KEXEC_DEPS $(KEXEC_DEPS)"
+ @echo "KEXEC_OBJS $(KEXEC_OBJS)"
+
diff --git a/kexec/arch/alpha/include/arch/options.h b/kexec/arch/alpha/include/arch/options.h
new file mode 100644
index 0000000..11557a4
--- /dev/null
+++ b/kexec/arch/alpha/include/arch/options.h
@@ -0,0 +1,11 @@
+#ifndef KEXEC_ARCH_ALPHA_OPTIONS_H
+#define KEXEC_ARCH_ALPHA_OPTIONS_H
+
+#define OPT_ARCH_MAX (OPT_MAX+0)
+
+#define KEXEC_ARCH_OPTIONS \
+ KEXEC_OPTIONS \
+
+#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR ""
+
+#endif /* KEXEC_ARCH_ALPHA_OPTIONS_H */
diff --git a/kexec/arch/i386/Makefile b/kexec/arch/i386/Makefile
new file mode 100644
index 0000000..306ac3b
--- /dev/null
+++ b/kexec/arch/i386/Makefile
@@ -0,0 +1,11 @@
+#
+# kexec i386 (linux booting linux)
+#
+KEXEC_C_SRCS+= kexec/arch/i386/kexec-x86.c
+KEXEC_C_SRCS+= kexec/arch/i386/kexec-elf-x86.c
+KEXEC_C_SRCS+= kexec/arch/i386/kexec-elf-rel-x86.c
+KEXEC_C_SRCS+= kexec/arch/i386/kexec-bzImage.c
+KEXEC_C_SRCS+= kexec/arch/i386/kexec-multiboot-x86.c
+KEXEC_C_SRCS+= kexec/arch/i386/kexec-beoboot-x86.c
+KEXEC_C_SRCS+= kexec/arch/i386/kexec-nbi.c
+KEXEC_C_SRCS+= kexec/arch/i386/x86-linux-setup.c
diff --git a/kexec/arch/i386/compat_x86_64.S b/kexec/arch/i386/compat_x86_64.S
new file mode 100644
index 0000000..f8a04e9
--- /dev/null
+++ b/kexec/arch/i386/compat_x86_64.S
@@ -0,0 +1,131 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2003,2004,2005 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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.
+ */
+
+#define USE_LRET 0
+
+.data
+ .equ MSR_K6_EFER, 0xC0000080
+ .equ EFER_LME, 0x00000100
+ .equ X86_CR4_PAE, 0x00000020
+ .equ CR0_PG, 0x80000000
+
+ .globl compat_x86_64, compat_x86_64_size, compat_x86_64_entry32
+ .code64
+ .balign 16
+compat_x86_64:
+ /* Compute where I am running at */
+ leaq compat_x86_64(%rip), %rbx
+
+ /* Relocate the code */
+ addq %rbx, gdt_addr(%rip)
+#if !USE_LRET
+ addl %ebx, lm_exit_addr(%rip)
+#endif
+
+ /* Lookup the 32bit start address */
+ movl compat_x86_64_entry32(%rip), %ebx
+ pushq %rbx
+
+#if USE_LRET
+ /* Push the 64bit start address */
+ pushq $0x10
+ pushq lm_exit(%rip)
+#endif
+
+ /* This also acts as a serializing instruction ensuring
+ * my self modifying code works.
+ */
+ lgdt gdt(%rip)
+
+#if USE_LRET
+ lret
+#else
+ /* Switch to 32bit compatiblity mode */
+ ljmp *lm_exit_addr(%rip)
+#endif
+lm_exit:
+ .code32
+
+ /* Disable paging */
+ movl %cr0, %eax
+ andl $~CR0_PG, %eax
+ movl %eax, %cr0
+
+ /* Disable long mode */
+ movl $MSR_K6_EFER, %ecx
+ rdmsr
+ andl $~EFER_LME, %eax
+ wrmsr
+
+ /* Disable PAE */
+ xorl %eax, %eax
+ movl %eax, %cr4
+
+ /* load the data segments */
+ movl $0x18, %eax /* data segment */
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %ss
+ movl %eax, %fs
+ movl %eax, %gs
+
+ /* Remove the 32 bits of the 64 bit start address */
+ popl %eax
+
+ /* set all of the registers to known values */
+ /* leave %esp alone */
+
+ xorl %eax, %eax
+ xorl %ebx, %ebx
+ xorl %ecx, %ecx
+ xorl %edx, %edx
+ xorl %esi, %esi
+ xorl %edi, %edi
+ xorl %ebp, %ebp
+
+ ret
+
+ .balign 16
+gdt: /* 0x00 unusable segment
+ * 0x08 unused
+ * so use them as the gdt ptr
+ */
+ .word gdt_end - gdt - 1
+gdt_addr:
+ .quad gdt - compat_x86_64
+ .word 0, 0, 0
+
+ /* 0x10 4GB flat code segment */
+ .word 0xFFFF, 0x0000, 0x9A00, 0x00CF
+ /* 0x18 4GB flat data segment */
+ .word 0xFFFF, 0x0000, 0x9200, 0x00CF
+gdt_end:
+
+#if !USE_LRET
+lm_exit_addr:
+ .long lm_exit - compat_x86_64
+ .long 0x10
+#endif
+
+compat_x86_64_entry32:
+ .long 0
+
+compat_x86_64_end:
+compat_x86_64_size:
+ .long compat_x86_64_end - compat_x86_64
diff --git a/kexec/arch/i386/include/arch/options.h b/kexec/arch/i386/include/arch/options.h
new file mode 100644
index 0000000..60bccd6
--- /dev/null
+++ b/kexec/arch/i386/include/arch/options.h
@@ -0,0 +1,22 @@
+#ifndef KEXEC_ARCH_I386_OPTIONS_H
+#define KEXEC_ARCH_I386_OPTIONS_H
+
+#define OPT_RESET_VGA (OPT_MAX+0)
+#define OPT_SERIAL (OPT_MAX+1)
+#define OPT_SERIAL_BAUD (OPT_MAX+2)
+#define OPT_CONSOLE_VGA (OPT_MAX+3)
+#define OPT_CONSOLE_SERIAL (OPT_MAX+4)
+#define OPT_ARCH_MAX (OPT_MAX+5)
+
+#define KEXEC_ARCH_OPTIONS \
+ KEXEC_OPTIONS \
+ { "reset-vga", 0, 0, OPT_RESET_VGA }, \
+ { "serial", 1, 0, OPT_SERIAL }, \
+ { "serial-baud", 1, 0, OPT_SERIAL_BAUD }, \
+ { "console-vga", 0, 0, OPT_CONSOLE_VGA }, \
+ { "console-serial", 0, 0, OPT_CONSOLE_SERIAL }, \
+
+#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR ""
+
+#endif /* KEXEC_ARCH_I386_OPTIONS_H */
+
diff --git a/kexec/arch/i386/kexec-beoboot-x86.c b/kexec/arch/i386/kexec-beoboot-x86.c
new file mode 100644
index 0000000..a73a3cb
--- /dev/null
+++ b/kexec/arch/i386/kexec-beoboot-x86.c
@@ -0,0 +1,140 @@
+/*------------------------------------------------------------ -*- C -*-
+ * Eric Biederman <ebiederman@xmission.com>
+ * Erik Arjan Hendriks <hendriks@lanl.gov>
+ *
+ * 14 December 2004
+ * This file is a derivative of the beoboot image loader, modified
+ * to work with kexec.
+ *
+ * This version is derivative from the orignal mkbootimg.c which is
+ * Copyright (C) 2000 Scyld Computing Corporation
+ *
+ * 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.
+ *
+
+ *
+ *--------------------------------------------------------------------*/
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <getopt.h>
+#include <x86/x86-linux.h>
+#include <boot/beoboot.h>
+#include "../../kexec.h"
+#include "kexec-x86.h"
+#include <arch/options.h>
+
+int beoboot_probe(const char *buf, off_t len)
+{
+ struct beoboot_header bb_header;
+ const char *cmdline, *kernel;
+ int result;
+ if (len < sizeof(bb_header)) {
+ return -1;
+ }
+ memcpy(&bb_header, buf, sizeof(bb_header));
+ if (memcmp(bb_header.magic, BEOBOOT_MAGIC, 4) != 0) {
+ return -1;
+ }
+ if (bb_header.arch != BEOBOOT_ARCH) {
+ return -1;
+ }
+ /* Make certain a bzImage is packed into there.
+ */
+ cmdline = buf + sizeof(bb_header);
+ kernel = cmdline + bb_header.cmdline_size;
+ result = bzImage_probe(kernel, bb_header.kernel_size);
+
+ return result;
+}
+
+void beoboot_usage(void)
+{
+ printf( "-d, --debug Enable debugging to help spot a failure.\n"
+ " --real-mode Use the kernels real mode entry point.\n"
+ );
+
+ /* No parameters are parsed */
+}
+
+#define SETUP_BASE 0x90000
+#define KERN32_BASE 0x100000 /* 1MB */
+#define INITRD_BASE 0x1000000 /* 16MB */
+
+int beoboot_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info)
+{
+ struct beoboot_header bb_header;
+ const unsigned char *command_line, *kernel, *initrd;
+
+ int debug, real_mode_entry;
+ int opt;
+ int result;
+#define OPT_REAL_MODE (OPT_ARCH_MAX+0)
+ static const struct option options[] = {
+ KEXEC_ARCH_OPTIONS
+ { "debug", 0, 0, OPT_DEBUG },
+ { "real-mode", 0, 0, OPT_REAL_MODE },
+ { 0, 0, 0, 0 },
+ };
+ static const char short_options[] = KEXEC_ARCH_OPT_STR "";
+
+ /*
+ * Parse the command line arguments
+ */
+ debug = 0;
+ real_mode_entry = 0;
+ while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
+ switch(opt) {
+ default:
+ /* Ignore core options */
+ if (opt < OPT_ARCH_MAX) {
+ break;
+ }
+ case '?':
+ usage();
+ return -1;
+ case OPT_DEBUG:
+ debug = 1;
+ break;
+ case OPT_REAL_MODE:
+ real_mode_entry = 1;
+ break;
+ }
+ }
+
+
+ /*
+ * Parse the file
+ */
+ memcpy(&bb_header, buf, sizeof(bb_header));
+ command_line = buf + sizeof(bb_header);
+ kernel = command_line + bb_header.cmdline_size;
+ initrd = NULL;
+ if (bb_header.flags & BEOBOOT_INITRD_PRESENT) {
+ initrd = kernel + bb_header.kernel_size;
+ }
+
+ result = do_bzImage_load(info,
+ kernel, bb_header.kernel_size,
+ command_line, bb_header.cmdline_size,
+ initrd, bb_header.initrd_size,
+ real_mode_entry, debug);
+
+ return result;
+}
+
diff --git a/kexec/arch/i386/kexec-bzImage.c b/kexec/arch/i386/kexec-bzImage.c
new file mode 100644
index 0000000..9de2dc8
--- /dev/null
+++ b/kexec/arch/i386/kexec-bzImage.c
@@ -0,0 +1,296 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2003-2005 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <elf.h>
+#include <boot/elf_boot.h>
+#include <ip_checksum.h>
+#include <x86/x86-linux.h>
+#include "../../kexec.h"
+#include "../../kexec-elf.h"
+#include "kexec-x86.h"
+#include "x86-linux-setup.h"
+#include <arch/options.h>
+
+static const int probe_debug = 0;
+
+int bzImage_probe(const char *buf, off_t len)
+{
+ struct x86_linux_header header;
+ if (len < sizeof(header)) {
+ return -1;
+ }
+ memcpy(&header, buf, sizeof(header));
+ if (memcmp(header.header_magic, "HdrS", 4) != 0) {
+ if (probe_debug) {
+ fprintf(stderr, "Not a bzImage\n");
+ }
+ return -1;
+ }
+ if (header.boot_sector_magic != 0xAA55) {
+ if (probe_debug) {
+ fprintf(stderr, "No x86 boot sector present\n");
+ }
+ /* No x86 boot sector present */
+ return -1;
+ }
+ if (header.protocol_version < 0x0200) {
+ if (probe_debug) {
+ fprintf(stderr, "Must be at least protocol version 2.00\n");
+ }
+ /* Must be at least protocol version 2.00 */
+ return -1;
+ }
+ if ((header.loadflags & 1) == 0) {
+ if (probe_debug) {
+ fprintf(stderr, "zImage not a bzImage\n");
+ }
+ /* Not a bzImage */
+ return -1;
+ }
+ /* I've got a bzImage */
+ if (probe_debug) {
+ fprintf(stderr, "It's a bzImage\n");
+ }
+ return 0;
+}
+
+
+void bzImage_usage(void)
+{
+ printf( "-d, --debug Enable debugging to help spot a failure.\n"
+ " --real-mode Use the kernels real mode entry point.\n"
+ " --command-line=STRING Set the kernel command line to STRING.\n"
+ " --append=STRING Set the kernel command line to STRING.\n"
+ " --initrd=FILE Use FILE as the kernel's initial ramdisk.\n"
+ " --ramdisk=FILE Use FILE as the kernel's initial ramdisk.\n"
+ );
+
+}
+
+int do_bzImage_load(struct kexec_info *info,
+ const char *kernel, off_t kernel_len,
+ const char *command_line, off_t command_line_len,
+ const char *initrd, off_t initrd_len,
+ int real_mode_entry, int debug)
+{
+ struct x86_linux_header setup_header;
+ struct x86_linux_param_header *real_mode;
+ int setup_sects;
+ char *kernel_version;
+ size_t size;
+ int kern16_size;
+ unsigned long setup_base, setup_size;
+ struct entry32_regs regs32;
+ struct entry16_regs regs16;
+
+ /*
+ * Find out about the file I am about to load.
+ */
+ if (kernel_len < sizeof(setup_header)) {
+ return -1;
+ }
+ memcpy(&setup_header, kernel, sizeof(setup_header));
+ setup_sects = setup_header.setup_sects;
+ if (setup_sects == 0) {
+ setup_sects = 4;
+ }
+ kern16_size = (setup_sects +1) *512;
+ kernel_version = ((unsigned char *)&setup_header) + 512 + setup_header.kver_addr;
+ if (kernel_len < kern16_size) {
+ fprintf(stderr, "BzImage truncated?\n");
+ return -1;
+ }
+
+ /* Load the trampoline. This must load at a higher address
+ * the the argument/parameter segment or the kernel will stomp
+ * it's gdt.
+ */
+ elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
+ 0x3000, 640*1024, -1);
+
+ /* The argument/parameter segment */
+ setup_size = kern16_size + command_line_len;
+ real_mode = xmalloc(setup_size);
+ memcpy(real_mode, kernel, kern16_size);
+ if (real_mode->protocol_version >= 0x0200) {
+ /* Careful setup_base must be greater than 8K */
+ setup_base = add_buffer(info, real_mode, setup_size, setup_size,
+ 16, 0x3000, 640*1024, -1);
+ } else {
+ add_segment(info, real_mode, setup_size, SETUP_BASE, setup_size);
+ setup_base = SETUP_BASE;
+ }
+ /* Verify purgatory loads higher than the parameters */
+ if (info->rhdr.rel_addr < setup_base) {
+ die("Could not put setup code above the kernel parameters\n");
+ }
+
+ /* The main kernel segment */
+ size = kernel_len - kern16_size;
+ add_segment(info, kernel + kern16_size, size, KERN32_BASE, size);
+
+
+ /* Tell the kernel what is going on */
+ setup_linux_bootloader_parameters(info, real_mode, setup_base,
+ kern16_size, command_line, command_line_len,
+ initrd, initrd_len);
+
+ /* Get the initial register values */
+ elf_rel_get_symbol(&info->rhdr, "entry16_regs", &regs16, sizeof(regs16));
+ elf_rel_get_symbol(&info->rhdr, "entry32_regs", &regs32, sizeof(regs32));
+ /*
+
+ * Initialize the 32bit start information.
+ */
+ regs32.eax = 0; /* unused */
+ regs32.ebx = 0; /* 0 == boot not AP processor start */
+ regs32.ecx = 0; /* unused */
+ regs32.edx = 0; /* unused */
+ regs32.esi = setup_base; /* kernel parameters */
+ regs32.edi = 0; /* unused */
+ regs32.esp = elf_rel_get_addr(&info->rhdr, "stack_end"); /* stack, unused */
+ regs32.ebp = 0; /* unused */
+ regs32.eip = KERN32_BASE; /* kernel entry point */
+
+ /*
+ * Initialize the 16bit start information.
+ */
+ regs16.cs = setup_base + 0x20;
+ regs16.ip = 0;
+ regs16.ss = (elf_rel_get_addr(&info->rhdr, "stack_end") - 64*1024) >> 4;
+ regs16.esp = 0xFFFC;
+ if (real_mode_entry) {
+ printf("Starting the kernel in real mode\n");
+ regs32.eip = elf_rel_get_addr(&info->rhdr, "entry16");
+ }
+ if (real_mode && debug) {
+ unsigned long entry16_debug, pre32, first32;
+ uint32_t old_first32;
+ /* Find the location of the symbols */
+ entry16_debug = elf_rel_get_addr(&info->rhdr, "entry16_debug");
+ pre32 = elf_rel_get_addr(&info->rhdr, "entry16_debug_pre32");
+ first32 = elf_rel_get_addr(&info->rhdr, "entry16_debug_first32");
+
+ /* Hook all of the linux kernel hooks */
+ real_mode->rmode_switch_cs = entry16_debug >> 4;
+ real_mode->rmode_switch_ip = pre32 - entry16_debug;
+ old_first32 = real_mode->kernel_start;
+ real_mode->kernel_start = first32;
+ elf_rel_set_symbol(&info->rhdr, "entry16_debug_old_first32",
+ &old_first32, sizeof(old_first32));
+
+ regs32.eip = entry16_debug;
+ }
+ elf_rel_set_symbol(&info->rhdr, "entry16_regs", &regs16, sizeof(regs16));
+ elf_rel_set_symbol(&info->rhdr, "entry16_debug_regs", &regs16, sizeof(regs16));
+ elf_rel_set_symbol(&info->rhdr, "entry32_regs", &regs32, sizeof(regs32));
+
+ /* Fill in the information BIOS calls would normally provide. */
+ if (!real_mode_entry) {
+ setup_linux_system_parameters(real_mode);
+ }
+
+ return 0;
+}
+
+int bzImage_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info)
+{
+ const char *command_line;
+ const char *ramdisk;
+ char *ramdisk_buf;
+ off_t ramdisk_length;
+ int command_line_len;
+ int debug, real_mode_entry;
+ int opt;
+ int result;
+#define OPT_APPEND (OPT_ARCH_MAX+0)
+#define OPT_RAMDISK (OPT_ARCH_MAX+1)
+#define OPT_REAL_MODE (OPT_ARCH_MAX+2)
+ static const struct option options[] = {
+ KEXEC_ARCH_OPTIONS
+ { "debug", 0, 0, OPT_DEBUG },
+ { "command-line", 1, 0, OPT_APPEND },
+ { "append", 1, 0, OPT_APPEND },
+ { "initrd", 1, 0, OPT_RAMDISK },
+ { "ramdisk", 1, 0, OPT_RAMDISK },
+ { "real-mode", 0, 0, OPT_REAL_MODE },
+ { 0, 0, 0, 0 },
+ };
+ static const char short_options[] = KEXEC_ARCH_OPT_STR "d";
+
+ /*
+ * Parse the command line arguments
+ */
+ debug = 0;
+ real_mode_entry = 0;
+ command_line = 0;
+ ramdisk = 0;
+ ramdisk_length = 0;
+ while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
+ switch(opt) {
+ default:
+ /* Ignore core options */
+ if (opt < OPT_ARCH_MAX) {
+ break;
+ }
+ case '?':
+ usage();
+ return -1;
+ case OPT_DEBUG:
+ debug = 1;
+ break;
+ case OPT_APPEND:
+ command_line = optarg;
+ break;
+ case OPT_RAMDISK:
+ ramdisk = optarg;
+ break;
+ case OPT_REAL_MODE:
+ real_mode_entry = 1;
+ break;
+ }
+ }
+ command_line_len = 0;
+ if (command_line) {
+ command_line_len = strlen(command_line) +1;
+ }
+ ramdisk_buf = 0;
+ if (ramdisk) {
+ ramdisk_buf = slurp_file(ramdisk, &ramdisk_length);
+ }
+ result = do_bzImage_load(info,
+ buf, len,
+ command_line, command_line_len,
+ ramdisk_buf, ramdisk_length,
+ real_mode_entry, debug);
+
+ return result;
+}
diff --git a/kexec/arch/i386/kexec-elf-rel-x86.c b/kexec/arch/i386/kexec-elf-rel-x86.c
new file mode 100644
index 0000000..e2f1748
--- /dev/null
+++ b/kexec/arch/i386/kexec-elf-rel-x86.c
@@ -0,0 +1,35 @@
+#include <stdio.h>
+#include <elf.h>
+#include "../../kexec.h"
+#include "../../kexec-elf.h"
+
+int machine_verify_elf_rel(struct mem_ehdr *ehdr)
+{
+ if (ehdr->ei_data != ELFDATA2LSB) {
+ return 0;
+ }
+ if (ehdr->ei_class != ELFCLASS32) {
+ return 0;
+ }
+ if ((ehdr->e_machine != EM_386) && (ehdr->e_machine != EM_486))
+ {
+ return 0;
+ }
+ return 1;
+}
+
+void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type,
+ void *location, unsigned long address, unsigned long value)
+{
+ switch(r_type) {
+ case R_386_32:
+ *((uint32_t *)location) += value;
+ break;
+ case R_386_PC32:
+ *((uint32_t *)location) += value - address;
+ break;
+ default:
+ die("Unknown rel relocation: %lu\n", r_type);
+ break;
+ }
+}
diff --git a/kexec/arch/i386/kexec-elf-x86.c b/kexec/arch/i386/kexec-elf-x86.c
new file mode 100644
index 0000000..5cfa0d4
--- /dev/null
+++ b/kexec/arch/i386/kexec-elf-x86.c
@@ -0,0 +1,245 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2003-2005 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <elf.h>
+#include <x86/x86-linux.h>
+#include "../../kexec.h"
+#include "../../kexec-elf.h"
+#include "../../kexec-elf-boot.h"
+#include "x86-linux-setup.h"
+#include "kexec-x86.h"
+#include <arch/options.h>
+
+static const int probe_debug = 0;
+
+int elf_x86_probe(const char *buf, off_t len)
+{
+
+ struct mem_ehdr ehdr;
+ int result;
+ result = build_elf_exec_info(buf, len, &ehdr);
+ if (result < 0) {
+ if (probe_debug) {
+ fprintf(stderr, "Not an ELF executable\n");
+ }
+ goto out;
+ }
+
+ /* Verify the architecuture specific bits */
+ if ((ehdr.e_machine != EM_386) && (ehdr.e_machine != EM_486)) {
+ /* for a different architecture */
+ if (probe_debug) {
+ fprintf(stderr, "Not x86_64 ELF executable\n");
+ }
+ result = -1;
+ goto out;
+ }
+ result = 0;
+ out:
+ free_elf_info(&ehdr);
+ return result;
+}
+
+void elf_x86_usage(void)
+{
+ printf( " --command-line=STRING Set the kernel command line to STRING\n"
+ " --append=STRING Set the kernel command line to STRING\n"
+ " --initrd=FILE Use FILE as the kernel's initial ramdisk.\n"
+ " --ramdisk=FILE Use FILE as the kernel's initial ramdisk.\n"
+ " --args-linux Pass linux kernel style options\n"
+ " --args-elf Pass elf boot notes\n"
+ );
+
+
+}
+
+int elf_x86_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info)
+{
+ struct mem_ehdr ehdr;
+ const char *command_line;
+ int command_line_len;
+ const char *ramdisk;
+ unsigned long entry, max_addr;
+ int arg_style;
+#define ARG_STYLE_ELF 0
+#define ARG_STYLE_LINUX 1
+#define ARG_STYLE_NONE 2
+ int opt;
+#define OPT_APPEND (OPT_ARCH_MAX+0)
+#define OPT_RAMDISK (OPT_ARCH_MAX+1)
+#define OPT_ARGS_ELF (OPT_ARCH_MAX+2)
+#define OPT_ARGS_LINUX (OPT_ARCH_MAX+3)
+#define OPT_ARGS_NONE (OPT_ARCH_MAX+4)
+
+ static const struct option options[] = {
+ KEXEC_ARCH_OPTIONS
+ { "command-line", 1, NULL, OPT_APPEND },
+ { "append", 1, NULL, OPT_APPEND },
+ { "initrd", 1, NULL, OPT_RAMDISK },
+ { "ramdisk", 1, NULL, OPT_RAMDISK },
+ { "args-elf", 0, NULL, OPT_ARGS_ELF },
+ { "args-linux", 0, NULL, OPT_ARGS_LINUX },
+ { "args-none", 0, NULL, OPT_ARGS_NONE },
+ { 0, 0, NULL, 0 },
+ };
+
+ static const char short_options[] = KEXEC_OPT_STR "";
+
+ /*
+ * Parse the command line arguments
+ */
+ arg_style = ARG_STYLE_ELF;
+ command_line = 0;
+ ramdisk = 0;
+ while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
+ switch(opt) {
+ default:
+ /* Ignore core options */
+ if (opt < OPT_ARCH_MAX) {
+ break;
+ }
+ case '?':
+ usage();
+ return -1;
+ case OPT_APPEND:
+ command_line = optarg;
+ break;
+ case OPT_RAMDISK:
+ ramdisk = optarg;
+ break;
+ case OPT_ARGS_ELF:
+ arg_style = ARG_STYLE_ELF;
+ break;
+ case OPT_ARGS_LINUX:
+ arg_style = ARG_STYLE_LINUX;
+ break;
+ case OPT_ARGS_NONE:
+#ifdef __i386___
+ arg_style = ARG_STYLE_NONE;
+#else
+ die("--args-none only works on arch i386\n");
+#endif
+ break;
+ }
+ }
+ command_line_len = 0;
+ if (command_line) {
+ command_line_len = strlen(command_line) +1;
+ }
+
+ /* Load the ELF executable */
+ elf_exec_build_load(info, &ehdr, buf, len);
+
+ entry = ehdr.e_entry;
+ max_addr = elf_max_addr(&ehdr);
+
+ /* Do we want arguments? */
+ if (arg_style != ARG_STYLE_NONE) {
+ /* Load the setup code */
+ elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
+ 0, ULONG_MAX, 1);
+ }
+ if (arg_style == ARG_STYLE_NONE) {
+ info->entry = (void *)entry;
+
+ }
+ else if (arg_style == ARG_STYLE_ELF) {
+ unsigned long note_base;
+ struct entry32_regs regs;
+ uint32_t arg1, arg2;
+
+ /* Setup the ELF boot notes */
+ note_base = elf_boot_notes(info, max_addr,
+ command_line, command_line_len);
+
+ /* Initialize the stack arguments */
+ arg2 = 0; /* No return address */
+ arg1 = note_base;
+ elf_rel_set_symbol(&info->rhdr, "stack_arg32_1", &arg1, sizeof(arg1));
+ elf_rel_set_symbol(&info->rhdr, "stack_arg32_2", &arg2, sizeof(arg2));
+
+ /* Initialize the registers */
+ elf_rel_get_symbol(&info->rhdr, "entry32_regs", &regs, sizeof(regs));
+ regs.eip = entry; /* The entry point */
+ regs.esp = elf_rel_get_addr(&info->rhdr, "stack_arg32_2");
+ elf_rel_set_symbol(&info->rhdr, "entry32_regs", &regs, sizeof(regs));
+
+ if (ramdisk) {
+ die("Ramdisks not supported with generic elf arguments");
+ }
+ }
+ else if (arg_style == ARG_STYLE_LINUX) {
+ struct x86_linux_faked_param_header *hdr;
+ unsigned long param_base;
+ const unsigned char *ramdisk_buf;
+ off_t ramdisk_length;
+ struct entry32_regs regs;
+
+ /* Get the linux parameter header */
+ hdr = xmalloc(sizeof(*hdr));
+ param_base = add_buffer(info, hdr, sizeof(*hdr), sizeof(*hdr),
+ 16, 0, max_addr, 1);
+
+ /* Initialize the parameter header */
+ memset(hdr, 0, sizeof(*hdr));
+ init_linux_parameters(&hdr->hdr);
+
+ /* Add a ramdisk to the current image */
+ ramdisk_buf = NULL;
+ ramdisk_length = 0;
+ if (ramdisk) {
+ unsigned char *ramdisk_buf;
+ ramdisk_buf = slurp_file(ramdisk, &ramdisk_length);
+ }
+
+ /* Tell the kernel what is going on */
+ setup_linux_bootloader_parameters(info, &hdr->hdr, param_base,
+ offsetof(struct x86_linux_faked_param_header, command_line),
+ command_line, command_line_len,
+ ramdisk_buf, ramdisk_length);
+
+ /* Fill in the information bios calls would usually provide */
+ setup_linux_system_parameters(&hdr->hdr);
+
+ /* Initialize the registers */
+ elf_rel_get_symbol(&info->rhdr, "entry32_regs", &regs, sizeof(regs));
+ regs.ebx = 0; /* Bootstrap processor */
+ regs.esi = param_base; /* Pointer to the parameters */
+ regs.eip = entry; /* The entry point */
+ regs.esp = elf_rel_get_addr(&info->rhdr, "stack_end"); /* Stack, unused */
+ elf_rel_set_symbol(&info->rhdr, "entry32_regs", &regs, sizeof(regs));
+ }
+ else {
+ die("Unknown argument style\n");
+ }
+ return 0;
+}
diff --git a/kexec/arch/i386/kexec-multiboot-x86.c b/kexec/arch/i386/kexec-multiboot-x86.c
new file mode 100644
index 0000000..0efefc9
--- /dev/null
+++ b/kexec/arch/i386/kexec-multiboot-x86.c
@@ -0,0 +1,393 @@
+/*
+ * kexec-multiboot-x86.c
+ *
+ * (partial) multiboot support for kexec. Only supports ELF32
+ * kernels, and a subset of the multiboot info page options
+ * (i.e. enough to boot the Xen hypervisor).
+ *
+ * TODO:
+ * - smarter allocation of new segments
+ * - proper support for the MULTIBOOT_VIDEO_MODE bit
+ * - support for the MULTIBOOT_AOUT_KLUDGE bit
+ *
+ *
+ * Copyright (C) 2003 Tim Deegan (tjd21 at cl.cam.ac.uk)
+ *
+ * Parts based on GNU GRUB, Copyright (C) 2000 Free Software Foundation, Inc
+ * Parts copied from kexec-elf32-x86.c, written by Eric Biederman
+ *
+ * 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.
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <elf.h>
+#include <boot/elf_boot.h>
+#include <asm/page.h>
+#include <ip_checksum.h>
+#include "../../kexec.h"
+#include "../../kexec-elf.h"
+#include "kexec-x86.h"
+#include <arch/options.h>
+
+/* From GNU GRUB */
+#include <x86/mb_header.h>
+#include <x86/mb_info.h>
+
+/* Static storage */
+static char headerbuf[MULTIBOOT_SEARCH];
+static struct multiboot_header *mbh = NULL;
+
+#define BOOTLOADER "kexec"
+#define BOOTLOADER_VERSION VERSION
+#define MIN(_x,_y) (((_x)<=(_y))?(_x):(_y))
+
+
+int multiboot_x86_probe(const char *buf, off_t buf_len)
+/* Is it a good idea to try booting this file? */
+{
+ int i, len;
+ /* First of all, check that this is an ELF file */
+ if ((i=elf_x86_probe(buf, buf_len)) < 0) {
+ return i;
+ }
+ /* Now look for a multiboot header in the first 8KB */
+ len = MULTIBOOT_SEARCH;
+ if (len > buf_len) {
+ len = buf_len;
+ }
+ memcpy(headerbuf, buf, len);
+ if (len < 12) {
+ /* Short file */
+ return -1;
+ }
+ for (i = 0; i <= (len - 12); i += 4)
+ {
+ /* Search for a multiboot header */
+ mbh = (struct multiboot_header *)(headerbuf + i);
+ if (mbh->magic != MULTIBOOT_MAGIC
+ || ((mbh->magic+mbh->flags+mbh->checksum) & 0xffffffff))
+ {
+ /* Not a multiboot header */
+ continue;
+ }
+ if (mbh->flags & MULTIBOOT_AOUT_KLUDGE) {
+ /* Requires options we don't support */
+ fprintf(stderr,
+ "Found a multiboot header, but it uses "
+ "a non-ELF header layout,\n"
+ "and I can't do that (yet). Sorry.\n");
+ return -1;
+ }
+ if (mbh->flags & MULTIBOOT_UNSUPPORTED) {
+ /* Requires options we don't support */
+ fprintf(stderr,
+ "Found a multiboot header, but it "
+ "requires multiboot options that I\n"
+ "don't understand. Sorry.\n");
+ return -1;
+ }
+ if (mbh->flags & MULTIBOOT_VIDEO_MODE) {
+ /* Asked for screen mode information */
+ /* XXX carry on regardless */
+ fprintf(stderr,
+ "BEWARE! Found a multiboot header which asks "
+ "for screen mode information.\n"
+ "BEWARE! I am NOT supplying screen mode "
+ "information, but loading it regardless.\n");
+
+ }
+ /* Bootable */
+ return 0;
+ }
+ /* Not multiboot */
+ return -1;
+}
+
+
+void multiboot_x86_usage(void)
+/* Multiboot-specific options */
+{
+ printf(" --command-line=STRING Set the kernel command line to STRING.\n");
+ printf(" --module=\"MOD arg1 arg2...\" Load module MOD with command-line \"arg1...\"\n");
+ printf(" (can be used multiple times).\n");
+}
+
+int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info)
+/* Marshal up a multiboot-style kernel */
+{
+ struct multiboot_info *mbi;
+ void *mbi_buf;
+ struct mod_list *modp;
+ unsigned long freespace;
+ unsigned long long mem_lower = 0, mem_upper = 0;
+ struct mem_ehdr ehdr;
+ unsigned long mbi_base;
+ struct entry32_regs regs;
+ size_t mbi_bytes, mbi_offset;
+ const char *command_line=NULL;
+ char *imagename, *cp;
+ struct memory_range *range;
+ int ranges;
+ struct AddrRangeDesc *mmap;
+ int command_line_len;
+ int i;
+ int opt;
+ int modules, mod_command_line_space;
+#define OPT_CL (OPT_ARCH_MAX+0)
+#define OPT_MOD (OPT_ARCH_MAX+1)
+#define OPT_VGA (OPT_ARCH_MAX+2)
+ static const struct option options[] = {
+ KEXEC_ARCH_OPTIONS
+ { "command-line", 1, 0, OPT_CL },
+ { "append", 1, 0, OPT_CL },
+ { "module", 1, 0, OPT_MOD },
+ { 0, 0, 0, 0 },
+ };
+ static const char short_options[] = KEXEC_ARCH_OPT_STR "";
+
+ /* Probe for the MB header if it's not already found */
+ if (mbh == NULL && multiboot_x86_probe(buf, len) != 1)
+ {
+ fprintf(stderr, "Cannot find a loadable multiboot header.\n");
+ return -1;
+ }
+
+
+ /* Parse the command line */
+ command_line = "";
+ command_line_len = 0;
+ modules = 0;
+ mod_command_line_space = 0;
+ while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1)
+ {
+ switch(opt) {
+ default:
+ /* Ignore core options */
+ if (opt < OPT_ARCH_MAX) {
+ break;
+ }
+ case '?':
+ usage();
+ return -1;
+ case OPT_CL:
+ command_line = optarg;
+ break;
+ case OPT_MOD:
+ modules++;
+ mod_command_line_space += strlen(optarg) + 1;
+ break;
+ }
+ }
+ imagename = argv[optind];
+ command_line_len = strlen(command_line) + strlen(imagename) + 2;
+
+
+
+ /* Load the ELF executable */
+ elf_exec_build_load(info, &ehdr, buf, len);
+
+ /* Load the setup code */
+ elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size, 0, ULONG_MAX, 1);
+
+ /* The first segment will contain the multiboot headers:
+ * =============
+ * multiboot information (mbi)
+ * -------------
+ * kernel command line
+ * -------------
+ * bootloader name
+ * -------------
+ * module information entries
+ * -------------
+ * module command lines
+ * ==============
+ */
+ mbi_bytes = (sizeof(*mbi) + command_line_len
+ + strlen (BOOTLOADER " " BOOTLOADER_VERSION) + 1
+ + 3) & ~3;
+ mbi_buf = xmalloc(mbi_bytes);
+ mbi = mbi_buf;
+ memset(mbi, 0, sizeof(*mbi));
+ sprintf(((char *)mbi) + sizeof(*mbi), "%s %s",
+ imagename, command_line);
+ sprintf(((char *)mbi) + sizeof(*mbi) + command_line_len, "%s",
+ BOOTLOADER " " BOOTLOADER_VERSION);
+ mbi->flags = MB_INFO_CMDLINE | MB_INFO_BOOT_LOADER_NAME;
+ /* We'll relocate these to absolute addresses later. For now,
+ * all addresses within the first segment are relative to the
+ * start of the MBI. */
+ mbi->cmdline = sizeof(*mbi);
+ mbi->boot_loader_name = sizeof(*mbi) + command_line_len;
+
+ /* Memory map */
+ if ((get_memory_ranges(&range, &ranges) < 0) || ranges == 0) {
+ fprintf(stderr, "Cannot get memory information\n");
+ return -1;
+ }
+ mmap = xmalloc(ranges * sizeof(*mmap));
+ for (i=0; i<ranges; i++) {
+ unsigned long long length;
+ length = range[i].end - range[i].start;
+ /* Translate bzImage mmap to multiboot-speak */
+ mmap[i].size = sizeof(mmap[i]) - 4;
+ mmap[i].base_addr_low = range[i].start & 0xffffffff;
+ mmap[i].base_addr_high = range[i].start >> 32;
+ mmap[i].length_low = length & 0xffffffff;
+ mmap[i].length_high = length >> 32;
+ if (range[i].type == RANGE_RAM) {
+ mmap[i].Type = 1; /* RAM */
+ /* Is this the "low" memory? */
+ if ((range[i].start == 0)
+ && (range[i].end > mem_lower))
+ mem_lower = range[i].end;
+ /* Is this the "high" memory? */
+ if ((range[i].start <= 0x100000)
+ && (range[i].end > mem_upper + 0x100000))
+ mem_upper = range[i].end - 0x100000;
+ }
+ else
+ mmap[i].Type = 0xbad; /* Not RAM */
+ }
+
+
+ if (mbh->flags & MULTIBOOT_MEMORY_INFO) {
+ /* Provide a copy of the memory map to the kernel */
+
+ mbi->flags |= MB_INFO_MEMORY | MB_INFO_MEM_MAP;
+
+ freespace = add_buffer(info,
+ mmap, ranges * sizeof(*mmap), ranges * sizeof(*mmap),
+ 4, 0, 0xFFFFFFFFUL, 1);
+
+ mbi->mmap_addr = freespace;
+ mbi->mmap_length = ranges * sizeof(*mmap);
+
+ /* For kernels that care naught for fancy memory maps
+ * and just want the size of low and high memory */
+ mbi->mem_lower = MIN(mem_lower>>10, 0xffffffff);
+ mbi->mem_upper = MIN(mem_upper>>10, 0xffffffff);
+
+ /* done */
+ }
+
+
+ /* Load modules */
+ if (modules) {
+ char *mod_filename, *mod_command_line, *mod_clp, *buf;
+ off_t mod_size;
+
+ /* We'll relocate this to an absolute address later */
+ mbi->mods_addr = mbi_bytes;
+ mbi->mods_count = 0;
+ mbi->flags |= MB_INFO_MODS;
+
+ /* Add room for the module descriptors to the MBI buffer */
+ mbi_bytes += (sizeof(*modp) * modules)
+ + mod_command_line_space;
+ mbi_buf = xrealloc(mbi_buf, mbi_bytes);
+
+ /* mbi might have moved */
+ mbi = mbi_buf;
+ /* module descriptors go in the newly added space */
+ modp = ((void *)mbi) + mbi->mods_addr;
+ /* module command lines go after the descriptors */
+ mod_clp = ((void *)modp) + (sizeof(*modp) * modules);
+
+ /* Go back and parse the module command lines */
+ optind = opterr = 1;
+ while((opt = getopt_long(argc, argv,
+ short_options, options, 0)) != -1)
+ {
+ if (opt != OPT_MOD) continue;
+
+ /* Split module filename from command line */
+ mod_command_line = mod_filename = optarg;
+ if ((cp = strchr(mod_filename, ' ')) != NULL) {
+ /* See as I discard the 'const' modifier */
+ *cp = '\0';
+ }
+
+ /* Load the module */
+ buf = slurp_decompress_file(mod_filename, &mod_size);
+
+ if (cp != NULL) *cp = ' ';
+
+ /* Pick the next aligned spot to load it in */
+ freespace = add_buffer(info,
+ buf, mod_size, mod_size,
+ PAGE_SIZE, 0, 0xffffffffUL, 1);
+
+ /* Add the module command line */
+ sprintf(mod_clp, "%s", mod_command_line);
+
+ modp->mod_start = freespace;
+ modp->mod_end = freespace + mod_size;
+ modp->cmdline = (void *)mod_clp - (void *)mbi;
+ modp->pad = 0;
+
+ /* Done */
+ mbi->mods_count++;
+ mod_clp += strlen(mod_clp) + 1;
+ modp++;
+ }
+
+ }
+
+
+ /* Find a place for the MBI to live */
+ if (sort_segments(info) < 0) {
+ return -1;
+ }
+ mbi_base = add_buffer(info,
+ mbi_buf, mbi_bytes, mbi_bytes, 4, 0, 0xFFFFFFFFUL, 1);
+
+ /* Relocate offsets in the MBI to absolute addresses */
+ mbi_offset = mbi_base;
+ modp = ((void *)mbi) + mbi->mods_addr;
+ for (i=0; i<mbi->mods_count; i++) {
+ modp[i].cmdline += mbi_offset;
+ }
+ mbi->mods_addr += mbi_offset;
+ mbi->cmdline += mbi_offset;
+ mbi->boot_loader_name += mbi_offset;
+
+ /* Specify the initial CPU state and copy the setup code */
+ elf_rel_get_symbol(&info->rhdr, "entry32_regs", &regs, sizeof(regs));
+ regs.eax = 0x2BADB002;
+ regs.ebx = mbi_offset;
+ regs.eip = ehdr.e_entry;
+ elf_rel_set_symbol(&info->rhdr, "entry32_regs", &regs, sizeof(regs));
+
+ return 0;
+}
+
+/*
+ * EOF (kexec-multiboot-x86.c)
+ */
+
diff --git a/kexec/arch/i386/kexec-nbi.c b/kexec/arch/i386/kexec-nbi.c
new file mode 100644
index 0000000..00ba1c1
--- /dev/null
+++ b/kexec/arch/i386/kexec-nbi.c
@@ -0,0 +1,249 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2005 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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.
+ */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <elf.h>
+#include "../../kexec.h"
+#include "../../kexec-elf.h"
+#include "../../kexec-elf-boot.h"
+#include "kexec-x86.h"
+#include <arch/options.h>
+
+struct segheader
+{
+ uint8_t length;
+ uint8_t vendortag;
+ uint8_t reserved;
+ uint8_t flags;
+#define NBI_SEG 0x3
+#define NBI_SEG_ABSOLUTE 0
+#define NBI_SEG_APPEND 1
+#define NBI_SEG_NEGATIVE 2
+#define NBI_SEG_PREPEND 3
+#define NBI_LAST_SEG (1 << 2)
+ uint32_t loadaddr;
+ uint32_t imglength;
+ uint32_t memlength;
+};
+
+struct imgheader
+{
+#define NBI_MAGIC "\x36\x13\x03\x1b"
+ uint8_t magic[4];
+#define NBI_RETURNS (1 << 8)
+#define NBI_ENTRY32 (1 << 31)
+ uint32_t length; /* and flags */
+ struct { uint16_t bx, ds; } segoff;
+ union {
+ struct { uint16_t ip, cs; } segoff;
+ uint32_t linear;
+ } execaddr;
+};
+
+
+static const int probe_debug = 0;
+
+int nbi_probe(const char *buf, off_t len)
+{
+ struct imgheader hdr;
+ struct segheader seg;
+ off_t seg_off;
+ /* If we don't have enough data give up */
+ if ((len < sizeof(hdr)) || (len < 512)) {
+ return -1;
+ }
+ memcpy(&hdr, buf, sizeof(hdr));
+ if (memcmp(hdr.magic, NBI_MAGIC, sizeof(hdr.magic)) != 0) {
+ return -1;
+ }
+ /* Ensure we have a properly sized header */
+ if (((hdr.length & 0xf)*4) != sizeof(hdr)) {
+ if (probe_debug) {
+ fprintf(stderr, "NBI: Bad vendor header size\n");
+ }
+ return -1;
+ }
+ /* Ensure the vendor header is not too large.
+ * This can't actually happen but....
+ */
+ if ((((hdr.length & 0xf0) >> 4)*4) > (512 - sizeof(hdr))) {
+ if (probe_debug) {
+ fprintf(stderr, "NBI: vendor headr too large\n");
+ }
+ return -1;
+ }
+ /* Reserved bits are set in the image... */
+ if ((hdr.length & 0x7ffffe00)) {
+ if (probe_debug) {
+ fprintf(stderr, "NBI: Reserved header bits set\n");
+ }
+ return -1;
+ }
+ /* If the image can return refuse to load it */
+ if (hdr.length & (1 << 8)) {
+ if (probe_debug) {
+ printf("NBI: image wants to return\n");
+ }
+ return -1;
+ }
+ /* Now verify the segments all fit within 512 bytes */
+ seg_off = (((hdr.length & 0xf0) >> 4) + (hdr.length & 0x0f)) << 2;
+ do {
+ memcpy(&seg, buf + seg_off, sizeof(seg));
+ if ((seg.length & 0xf) != 4) {
+ if (probe_debug) {
+ fprintf(stderr, "NBI: Invalid segment length\n");
+ }
+ return -1;
+ }
+ seg_off += ((seg.length & 0xf) + ((seg.length >> 4) & 0xf)) << 2;
+ if (seg.flags & 0xf8) {
+ if (probe_debug) {
+ fprintf(stderr, "NBI: segment reserved flags set\n");
+ }
+ return -1;
+ }
+ if ((seg.flags & NBI_SEG) == NBI_SEG_NEGATIVE) {
+ if (probe_debug) {
+ fprintf(stderr, "NBI: negative segment addresses not supported\n");
+ }
+ return -1;
+ }
+ if (seg_off > 512) {
+ if (probe_debug) {
+ fprintf(stderr, "NBI: segment outside 512 header\n");
+ }
+ return -1;
+ }
+ } while(!(seg.flags & NBI_LAST_SEG));
+ return 0;
+}
+
+void nbi_usage(void)
+{
+ printf( "\n"
+ );
+}
+
+int nbi_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info)
+{
+ struct imgheader hdr;
+ struct segheader seg;
+ off_t seg_off;
+ off_t file_off;
+ uint32_t last0, last1;
+ int opt;
+
+ static const struct option options[] = {
+ KEXEC_ARCH_OPTIONS
+ { 0, 0, NULL, 0 },
+ };
+
+ static const char short_options[] = KEXEC_OPT_STR "";
+
+ /*
+ * Parse the command line arguments
+ */
+ while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
+ switch(opt) {
+ default:
+ /* Ignore core options */
+ if (opt < OPT_ARCH_MAX) {
+ break;
+ }
+ case '?':
+ usage();
+ return -1;
+ break;
+ }
+ }
+ /* Get a copy of the header */
+ memcpy(&hdr, buf, sizeof(hdr));
+
+ /* Load the first 512 bytes */
+ add_segment(info, buf + 0, 512,
+ (hdr.segoff.ds << 4) + hdr.segoff.bx, 512);
+
+ /* Initialize variables */
+ file_off = 512;
+ last0 = (hdr.segoff.ds << 4) + hdr.segoff.bx;
+ last1 = last0 + 512;
+
+ /* Load the segments */
+ seg_off = (((hdr.length & 0xf0) >> 4) + (hdr.length & 0x0f)) << 2;
+ do {
+ uint32_t loadaddr;
+ memcpy(&seg, buf + seg_off, sizeof(seg));
+ seg_off += ((seg.length & 0xf) + ((seg.length >> 4) & 0xf)) << 2;
+ if ((seg.flags & NBI_SEG) == NBI_SEG_ABSOLUTE) {
+ loadaddr = seg.loadaddr;
+ }
+ else if ((seg.flags & NBI_SEG) == NBI_SEG_APPEND) {
+ loadaddr = last1 + seg.loadaddr;
+ }
+#if 0
+ else if ((seg.flags & NBI_SEG) == NBI_SEG_NEGATIVE) {
+ loadaddr = memsize - seg.loadaddr;
+ }
+#endif
+ else if ((seg.flags & NBI_SEG) == NBI_SEG_PREPEND) {
+ loadaddr = last0 - seg.loadaddr;
+ }
+ add_segment(info, buf + file_off, seg.imglength,
+ loadaddr, seg.memlength);
+ last0 = loadaddr;
+ last1 = last0 + seg.memlength;
+ file_off += seg.imglength;
+ } while(!(seg.flags & NBI_LAST_SEG));
+
+ if (hdr.length & NBI_ENTRY32) {
+ struct entry32_regs regs32;
+ /* Initialize the registers */
+ elf_rel_get_symbol(&info->rhdr, "entry32_regs32", &regs32, sizeof(regs32));
+ regs32.eip = hdr.execaddr.linear;
+ elf_rel_set_symbol(&info->rhdr, "entry32_regs32", &regs32, sizeof(regs32));
+ }
+ else {
+ struct entry32_regs regs32;
+ struct entry16_regs regs16;
+
+ /* Initialize the 16 bit registers */
+ elf_rel_get_symbol(&info->rhdr, "entry16_regs", &regs16, sizeof(regs16));
+ regs16.cs = hdr.execaddr.segoff.cs;
+ regs16.ip = hdr.execaddr.segoff.ip;
+ elf_rel_set_symbol(&info->rhdr, "entry16_regs", &regs16, sizeof(regs16));
+
+ /* Initialize the 32 bit registers */
+ elf_rel_get_symbol(&info->rhdr, "entry32_regs", &regs32, sizeof(regs32));
+ regs32.eip = elf_rel_get_addr(&info->rhdr, "entry16");
+ elf_rel_set_symbol(&info->rhdr, "entry32_regs", &regs32, sizeof(regs32));
+ }
+ return 0;
+}
diff --git a/kexec/arch/i386/kexec-x86.c b/kexec/arch/i386/kexec-x86.c
new file mode 100644
index 0000000..31ea17b
--- /dev/null
+++ b/kexec/arch/i386/kexec-x86.c
@@ -0,0 +1,262 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2003-2005 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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 <stddef.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <sys/utsname.h>
+#include "../../kexec.h"
+#include "../../kexec-elf.h"
+#include "../../kexec-syscall.h"
+#include "kexec-x86.h"
+#include <arch/options.h>
+
+#define MAX_MEMORY_RANGES 64
+#define MAX_LINE 160
+static struct memory_range memory_range[MAX_MEMORY_RANGES];
+
+/* Return a sorted list of memory ranges. */
+int get_memory_ranges(struct memory_range **range, int *ranges)
+{
+ const char iomem[]= "/proc/iomem";
+ int memory_ranges = 0;
+ char line[MAX_LINE];
+ FILE *fp;
+ fp = fopen(iomem, "r");
+ if (!fp) {
+ fprintf(stderr, "Cannot open %s: %s\n",
+ iomem, strerror(errno));
+ return -1;
+ }
+ while(fgets(line, sizeof(line), fp) != 0) {
+ unsigned long long start, end;
+ char *str;
+ int type;
+ int consumed;
+ int count;
+ if (memory_ranges >= MAX_MEMORY_RANGES)
+ break;
+ count = sscanf(line, "%Lx-%Lx : %n",
+ &start, &end, &consumed);
+ if (count != 2)
+ continue;
+ str = line + consumed;
+ end = end + 1;
+#if 0
+ printf("%016Lx-%016Lx : %s",
+ start, end, str);
+#endif
+ if (memcmp(str, "System RAM\n", 11) == 0) {
+ type = RANGE_RAM;
+ }
+ else if (memcmp(str, "reserved\n", 9) == 0) {
+ type = RANGE_RESERVED;
+ }
+ else if (memcmp(str, "ACPI Tables\n", 12) == 0) {
+ type = RANGE_ACPI;
+ }
+ else if (memcmp(str, "ACPI Non-volatile Storage\n", 26) == 0) {
+ type = RANGE_ACPI_NVS;
+ }
+ else {
+ continue;
+ }
+ /* Don't report the interrupt table as ram */
+ if (type == RANGE_RAM && (start < 0x100)) {
+ start = 0x100;
+ }
+ memory_range[memory_ranges].start = start;
+ memory_range[memory_ranges].end = end;
+ memory_range[memory_ranges].type = type;
+#if 0
+ printf("%016Lx-%016Lx : %x\n",
+ start, end, type);
+#endif
+ memory_ranges++;
+ }
+ fclose(fp);
+ *range = memory_range;
+ *ranges = memory_ranges;
+ return 0;
+}
+
+struct file_type file_type[] = {
+ { "multiboot-x86", multiboot_x86_probe, multiboot_x86_load,
+ multiboot_x86_usage },
+ { "elf-x86", elf_x86_probe, elf_x86_load, elf_x86_usage },
+ { "bzImage", bzImage_probe, bzImage_load, bzImage_usage },
+ { "beoboot-x86", beoboot_probe, beoboot_load, beoboot_usage },
+ { "nbi-x86", nbi_probe, nbi_load, nbi_usage },
+};
+int file_types = sizeof(file_type)/sizeof(file_type[0]);
+
+
+void arch_usage(void)
+{
+ printf(
+ " --reset-vga Attempt to reset a standard vga device\n"
+ " --serial=<port> Specify the serial port for debug output\n"
+ " --serial-baud=<buad_rate> Specify the serial port baud rate\n"
+ " --console-vga Enable the vga console\n"
+ " --console-serial Enable the serial console\n"
+ );
+}
+
+static struct {
+ uint8_t reset_vga;
+ uint16_t serial_base;
+ uint32_t serial_baud;
+ uint8_t console_vga;
+ uint8_t console_serial;
+} arch_options = {
+ .reset_vga = 0,
+ .serial_base = 0x3f8,
+ .serial_baud = 0,
+ .console_vga = 0,
+ .console_serial = 0,
+};
+
+int arch_process_options(int argc, char **argv)
+{
+ static const struct option options[] = {
+ KEXEC_ARCH_OPTIONS
+ { 0, 0, NULL, 0 },
+ };
+ static const char short_options[] = KEXEC_ARCH_OPT_STR;
+ int opt;
+ unsigned long value;
+ char *end;
+
+ opterr = 0; /* Don't complain about unrecognized options here */
+ while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
+ switch(opt) {
+ default:
+ break;
+ case OPT_RESET_VGA:
+ arch_options.reset_vga = 1;
+ break;
+ case OPT_CONSOLE_VGA:
+ arch_options.console_vga = 1;
+ break;
+ case OPT_CONSOLE_SERIAL:
+ arch_options.console_serial = 1;
+ break;
+ case OPT_SERIAL:
+ value = ULONG_MAX;
+ if (strcmp(optarg, "ttyS0") == 0) {
+ value = 0x3f8;
+ }
+ else if (strcmp(optarg, "ttyS1") == 0) {
+ value = 0x2f8;
+ }
+ else if (strncmp(optarg, "0x", 2) == 0) {
+ value = strtoul(optarg +2, &end, 16);
+ if (*end != '\0') {
+ value = ULONG_MAX;
+ }
+ }
+ if (value >= 65536) {
+ fprintf(stderr, "Bad serial port base '%s'\n",
+ optarg);
+ usage();
+ return -1;
+
+ }
+ arch_options.serial_base = value;
+ break;
+ case OPT_SERIAL_BAUD:
+ value = strtoul(optarg, &end, 0);
+ if ((value > 115200) || ((115200 %value) != 0) ||
+ (value < 9600) || (*end))
+ {
+ fprintf(stderr, "Bad serial port baud rate '%s'\n",
+ optarg);
+ usage();
+ return -1;
+
+ }
+ arch_options.serial_baud = value;
+ break;
+ }
+ }
+ /* Reset getopt for the next pass; called in other source modules */
+ opterr = 1;
+ optind = 1;
+ return 0;
+}
+
+int arch_compat_trampoline(struct kexec_info *info, unsigned long *flags)
+{
+ int result;
+ struct utsname utsname;
+ result = uname(&utsname);
+ if (result < 0) {
+ fprintf(stderr, "uname failed: %s\n",
+ strerror(errno));
+ return -1;
+ }
+ if ( (strcmp(utsname.machine, "i386") == 0) ||
+ (strcmp(utsname.machine, "i486") == 0) ||
+ (strcmp(utsname.machine, "i586") == 0) ||
+ (strcmp(utsname.machine, "i686") == 0))
+ {
+ /* For compatibility with older patches
+ * use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_386 here.
+ */
+ *flags |= KEXEC_ARCH_DEFAULT;
+ }
+ else if (strcmp(utsname.machine, "x86_64") == 0)
+ {
+ *flags |= KEXEC_ARCH_X86_64;
+ if (!info->rhdr.e_shdr) {
+ fprintf(stderr,
+ "A trampoline is required for cross architecture support\n");
+ return -1;
+ }
+ elf_rel_set_symbol(&info->rhdr, "compat_x86_64_entry32",
+ &info->entry, sizeof(info->entry));
+
+ info->entry = elf_rel_get_addr(&info->rhdr, "compat_x86_64");
+ }
+ else {
+ fprintf(stderr, "Unsupported machine type: %s\n",
+ utsname.machine);
+ return -1;
+ }
+ return 0;
+}
+
+void arch_update_purgatory(struct kexec_info *info)
+{
+ elf_rel_set_symbol(&info->rhdr, "reset_vga",
+ &arch_options.reset_vga, sizeof(arch_options.reset_vga));
+ elf_rel_set_symbol(&info->rhdr, "serial_base",
+ &arch_options.serial_base, sizeof(arch_options.serial_base));
+ elf_rel_set_symbol(&info->rhdr, "serial_baud",
+ &arch_options.serial_baud, sizeof(arch_options.serial_baud));
+ elf_rel_set_symbol(&info->rhdr, "console_vga",
+ &arch_options.console_vga, sizeof(arch_options.console_vga));
+ elf_rel_set_symbol(&info->rhdr, "console_serial",
+ &arch_options.console_serial, sizeof(arch_options.console_serial));
+}
diff --git a/kexec/arch/i386/kexec-x86.h b/kexec/arch/i386/kexec-x86.h
new file mode 100644
index 0000000..a21fad5
--- /dev/null
+++ b/kexec/arch/i386/kexec-x86.h
@@ -0,0 +1,67 @@
+#ifndef KEXEC_X86_H
+#define KEXEC_X86_H
+
+extern unsigned char compat_x86_64[];
+extern uint32_t compat_x86_64_size, compat_x86_64_entry32;
+
+struct entry32_regs {
+ uint32_t eax;
+ uint32_t ebx;
+ uint32_t ecx;
+ uint32_t edx;
+ uint32_t esi;
+ uint32_t edi;
+ uint32_t esp;
+ uint32_t ebp;
+ uint32_t eip;
+};
+
+struct entry16_regs {
+ uint32_t eax;
+ uint32_t ebx;
+ uint32_t ecx;
+ uint32_t edx;
+ uint32_t esi;
+ uint32_t edi;
+ uint32_t esp;
+ uint32_t ebp;
+ uint16_t ds;
+ uint16_t es;
+ uint16_t ss;
+ uint16_t fs;
+ uint16_t gs;
+ uint16_t ip;
+ uint16_t cs;
+ uint16_t pad;
+};
+
+int multiboot_x86_probe(const char *buf, off_t len);
+int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info);
+void multiboot_x86_usage(void);
+
+int elf_x86_probe(const char *buf, off_t len);
+int elf_x86_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info);
+void elf_x86_usage(void);
+
+int bzImage_probe(const char *buf, off_t len);
+int bzImage_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info);
+void bzImage_usage(void);
+int do_bzImage_load(struct kexec_info *info,
+ const char *kernel, off_t kernel_len,
+ const char *command_line, off_t command_line_len,
+ const char *initrd, off_t initrd_len,
+ int real_mode_entry, int debug);
+
+int beoboot_probe(const char *buf, off_t len);
+int beoboot_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info);
+void beoboot_usage(void);
+
+int nbi_probe(const char *buf, off_t len);
+int nbi_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info);
+void nbi_usage(void);
+#endif /* KEXEC_X86_H */
diff --git a/kexec/arch/i386/x86-linux-setup.c b/kexec/arch/i386/x86-linux-setup.c
new file mode 100644
index 0000000..80a156a
--- /dev/null
+++ b/kexec/arch/i386/x86-linux-setup.c
@@ -0,0 +1,178 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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.
+ *
+ */
+#define _GNU_SOURCE
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <x86/x86-linux.h>
+#include "../../kexec.h"
+#include "kexec-x86.h"
+#include "x86-linux-setup.h"
+
+void init_linux_parameters(struct x86_linux_param_header *real_mode)
+{
+ /* Fill in the values that are usually provided by the kernel. */
+
+ /* Boot block magic */
+ memcpy(real_mode->header_magic, "HdrS", 4);
+ real_mode->protocol_version = 0x0203;
+ real_mode->initrd_addr_max = DEFAULT_INITRD_ADDR_MAX;
+}
+
+void setup_linux_bootloader_parameters(
+ struct kexec_info *info, struct x86_linux_param_header *real_mode,
+ unsigned long real_mode_base, unsigned long cmdline_offset,
+ const char *cmdline, off_t cmdline_len,
+ const unsigned char *initrd_buf, off_t initrd_size)
+{
+ char *cmdline_ptr;
+ unsigned long initrd_base, initrd_addr_max;
+
+ /* Say I'm a boot loader */
+ real_mode->loader_type = LOADER_TYPE_UNKNOWN;
+
+ /* No loader flags */
+ real_mode->loader_flags = 0;
+
+ /* Find the maximum initial ramdisk address */
+ initrd_addr_max = DEFAULT_INITRD_ADDR_MAX;
+ if (real_mode->protocol_version >= 0x0203) {
+ initrd_addr_max = real_mode->initrd_addr_max;
+ }
+
+ /* Load the initrd if we have one */
+ if (initrd_buf) {
+ initrd_base = add_buffer(info,
+ initrd_buf, initrd_size, initrd_size,
+ 4096, INITRD_BASE, initrd_addr_max, -1);
+ } else {
+ initrd_base = 0;
+ initrd_size = 0;
+ }
+
+ /* Ramdisk address and size */
+ real_mode->initrd_start = initrd_base;
+ real_mode->initrd_size = initrd_size;
+
+ /* The location of the command line */
+ /* if (real_mode_base == 0x90000) { */
+ real_mode->cl_magic = CL_MAGIC_VALUE;
+ real_mode->cl_offset = cmdline_offset;
+ /* setup_move_size */
+ /* } */
+ if (real_mode->protocol_version >= 0x0202) {
+ real_mode->cmd_line_ptr = real_mode_base + cmdline_offset;
+ }
+
+ /* Fill in the command line */
+ if (cmdline_len > COMMAND_LINE_SIZE) {
+ cmdline_len = COMMAND_LINE_SIZE;
+ }
+ cmdline_ptr = ((char *)real_mode) + cmdline_offset;
+ memcpy(cmdline_ptr, cmdline, cmdline_len);
+ cmdline_ptr[cmdline_len - 1] = '\0';
+}
+
+void setup_linux_system_parameters(struct x86_linux_param_header *real_mode)
+{
+ /* Fill in information the BIOS would usually provide */
+ struct memory_range *range;
+ int i, ranges;
+
+ /* Default screen size */
+ real_mode->orig_x = 0;
+ real_mode->orig_y = 0;
+ real_mode->orig_video_page = 0;
+ real_mode->orig_video_mode = 0;
+ real_mode->orig_video_cols = 80;
+ real_mode->orig_video_lines = 25;
+ real_mode->orig_video_ega_bx = 0;
+ real_mode->orig_video_isVGA = 1;
+ real_mode->orig_video_points = 16;
+
+ /* Fill in the memsize later */
+ real_mode->ext_mem_k = 0;
+ real_mode->alt_mem_k = 0;
+ real_mode->e820_map_nr = 0;
+
+ /* Default APM info */
+ memset(&real_mode->apm_bios_info, 0, sizeof(real_mode->apm_bios_info));
+ /* Default drive info */
+ memset(&real_mode->drive_info, 0, sizeof(real_mode->drive_info));
+ /* Default sysdesc table */
+ real_mode->sys_desc_table.length = 0;
+
+ /* default yes: this can be overridden on the command line */
+ real_mode->mount_root_rdonly = 0xFFFF;
+
+ /* default /dev/hda
+ * this can be overrident on the command line if necessary.
+ */
+ real_mode->root_dev = (0x3 <<8)| 0;
+
+ /* another safe default */
+ real_mode->aux_device_info = 0;
+
+ /* Fill in the memory info */
+ if ((get_memory_ranges(&range, &ranges) < 0) || ranges == 0) {
+ die("Cannot get memory information\n");
+ }
+ if (ranges > E820MAX) {
+ fprintf(stderr, "Too many memory ranges, truncating...\n");
+ ranges = E820MAX;
+ }
+ real_mode->e820_map_nr = ranges;
+ for(i = 0; i < ranges; i++) {
+ real_mode->e820_map[i].addr = range[i].start;
+ real_mode->e820_map[i].size = range[i].end - range[i].start;
+ switch (range[i].type) {
+ case RANGE_RAM:
+ real_mode->e820_map[i].type = E820_RAM;
+ break;
+ case RANGE_ACPI:
+ real_mode->e820_map[i].type = E820_ACPI;
+ break;
+ case RANGE_ACPI_NVS:
+ real_mode->e820_map[i].type = E820_NVS;
+ break;
+ default:
+ case RANGE_RESERVED:
+ real_mode->e820_map[i].type = E820_RESERVED;
+ break;
+ }
+ if (range[i].type != RANGE_RAM)
+ continue;
+ if ((range[i].start <= 0x100000) && range[i].end > 0x100000) {
+ unsigned long long mem_k = (range[i].end >> 10) - 0x100000;
+ real_mode->ext_mem_k = mem_k;
+ real_mode->alt_mem_k = mem_k;
+ if (mem_k > 0xfc00) {
+ real_mode->ext_mem_k = 0xfc00; /* 64M */
+ }
+ if (mem_k > 0xffffffff) {
+ real_mode->alt_mem_k = 0xffffffff;
+ }
+ }
+ }
+}
diff --git a/kexec/arch/i386/x86-linux-setup.h b/kexec/arch/i386/x86-linux-setup.h
new file mode 100644
index 0000000..79e65f3
--- /dev/null
+++ b/kexec/arch/i386/x86-linux-setup.h
@@ -0,0 +1,17 @@
+#ifndef X86_LINUX_SETUP_H
+#define X86_LINUX_SETUP_H
+
+void init_linux_parameters(struct x86_linux_param_header *real_mode);
+void setup_linux_bootloader_parameters(
+ struct kexec_info *info, struct x86_linux_param_header *real_mode,
+ unsigned long real_mode_base, unsigned long cmdline_offset,
+ const char *cmdline, off_t cmdline_len,
+ const unsigned char *initrd_buf, off_t initrd_size);
+void setup_linux_system_parameters(struct x86_linux_param_header *real_mode);
+
+
+#define SETUP_BASE 0x90000
+#define KERN32_BASE 0x100000 /* 1MB */
+#define INITRD_BASE 0x1000000 /* 16MB */
+
+#endif /* X86_LINUX_SETUP_H */
diff --git a/kexec/arch/ia64/Makefile b/kexec/arch/ia64/Makefile
new file mode 100644
index 0000000..d5d42e7
--- /dev/null
+++ b/kexec/arch/ia64/Makefile
@@ -0,0 +1,6 @@
+#
+# kexec ia64 (linux booting linux)
+#
+KEXEC_C_SRCS+= kexec/arch/ia64/kexec-ia64.c
+KEXEC_C_SRCS+= kexec/arch/ia64/kexec-elf-ia64.c
+KEXEC_C_SRCS+= kexec/arch/ia64/kexec-elf-rel-ia64.c
diff --git a/kexec/arch/ia64/include/arch/options.h b/kexec/arch/ia64/include/arch/options.h
new file mode 100644
index 0000000..3053576
--- /dev/null
+++ b/kexec/arch/ia64/include/arch/options.h
@@ -0,0 +1,11 @@
+#ifndef KEXEC_ARCH_IA64_OPTIONS_H
+#define KEXEC_ARCH_IA64_OPTIONS_H
+
+#define OPT_ARCH_MAX (OPT_MAX+0)
+
+#define KEXEC_ARCH_OPTIONS \
+ KEXEC_OPTIONS \
+
+#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR ""
+
+#endif /* KEXEC_ARCH_IA64_OPTIONS_H */
diff --git a/kexec/arch/ia64/kexec-elf-ia64.c b/kexec/arch/ia64/kexec-elf-ia64.c
new file mode 100644
index 0000000..4a91b95
--- /dev/null
+++ b/kexec/arch/ia64/kexec-elf-ia64.c
@@ -0,0 +1,141 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com)
+ * Copyright (C) 2004 Albert Herranz
+ * Copyright (C) 2004 Silicon Graphics, Inc.
+ * Jesse Barnes <jbarnes@sgi.com>
+ * Copyright (C) 2004 Khalid Aziz <khalid.aziz@hp.com> Hewlett Packard Co
+ *
+ * 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 (version 2 of the License).
+ *
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <elf.h>
+#include <boot/elf_boot.h>
+#include <ip_checksum.h>
+#include "../../kexec.h"
+#include "../../kexec-elf.h"
+#include <arch/options.h>
+
+static const int probe_debug = 0;
+
+/*
+ * elf_ia64_probe - sanity check the elf image
+ *
+ * Make sure that the file image has a reasonable chance of working.
+ */
+int elf_ia64_probe(const char *buf, off_t len)
+{
+ struct mem_ehdr ehdr;
+ int result;
+ result = build_elf_exec_info(buf, len, &ehdr);
+ if (result < 0) {
+ if (probe_debug) {
+ fprintf(stderr, "Not an ELF executable\n");
+ }
+ return -1;
+ }
+ /* Verify the architecuture specific bits */
+ if (ehdr.e_machine != EM_IA_64) {
+ /* for a different architecture */
+ if (probe_debug) {
+ fprintf(stderr, "Not for this architecture.\n");
+ }
+ return -1;
+ }
+ return 0;
+}
+
+void elf_ia64_usage(void)
+{
+ printf(
+ " --command-line=STRING Set the kernel command line to STRING.\n"
+ " --append=STRING Set the kernel command line to STRING.\n");
+}
+
+int elf_ia64_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info)
+{
+ struct mem_ehdr ehdr;
+ const char *command_line;
+ int command_line_len;
+ unsigned long entry, max_addr;
+ int result;
+ int opt;
+#define OPT_APPEND (OPT_ARCH_MAX+0)
+ static const struct option options[] = {
+ KEXEC_ARCH_OPTIONS
+ {"command-line", 1, 0, OPT_APPEND},
+ {"append", 1, 0, OPT_APPEND},
+ {0, 0, 0, 0},
+ };
+
+ static const char short_options[] = KEXEC_ARCH_OPT_STR "";
+
+ command_line = 0;
+ while ((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
+ switch (opt) {
+ default:
+ /* Ignore core options */
+ if (opt < OPT_ARCH_MAX) {
+ break;
+ }
+ case '?':
+ usage();
+ return -1;
+ case OPT_APPEND:
+ command_line = optarg;
+ break;
+ }
+ }
+ command_line_len = 0;
+ if (command_line) {
+ command_line_len = strlen(command_line) + 1;
+ }
+
+ /* Parse the Elf file */
+ result = build_elf_exec_info(buf, len, &ehdr);
+ if (result < 0) {
+ fprintf(stderr, "ELF parse failed\n");
+ free_elf_info(&ehdr);
+ return result;
+ }
+ entry = ehdr.e_entry;
+ max_addr = elf_max_addr(&ehdr);
+
+ /* Load the Elf data */
+ result = elf_exec_load(&ehdr, info);
+ free_elf_info(&ehdr);
+ if (result < 0) {
+ fprintf(stderr, "ELF load failed\n");
+ return result;
+ }
+
+ /* For now we don't have arguments to pass :( */
+ info->entry = (void *)entry;
+ return 0;
+}
diff --git a/kexec/arch/ia64/kexec-elf-rel-ia64.c b/kexec/arch/ia64/kexec-elf-rel-ia64.c
new file mode 100644
index 0000000..eb5f662
--- /dev/null
+++ b/kexec/arch/ia64/kexec-elf-rel-ia64.c
@@ -0,0 +1,45 @@
+#include <stdio.h>
+#include <elf.h>
+#include "../../kexec.h"
+#include "../../kexec-elf.h"
+
+int machine_verify_elf_rel(struct mem_ehdr *ehdr)
+{
+ if (ehdr->ei_data != ELFDATA2LSB) {
+ return 0;
+ }
+ if (ehdr->ei_class != ELFCLASS64) {
+ return 0;
+ }
+ if (ehdr->e_machine != EM_IA_64) {
+ return 0;
+ }
+ return 1;
+}
+
+void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type,
+ void *location, unsigned long address, unsigned long value)
+{
+ switch(r_type) {
+ case R_IA64_NONE:
+ break;
+ case R_IA64_DIR64LSB:
+ *((uint64_t *)location) = value;
+ break;
+ case R_IA64_DIR32LSB:
+ *((uint32_t *)location) = value;
+ if (value != *((uint32_t *)location))
+ goto overflow;
+ break;
+ case R_IA64_PCREL21B:
+ case R_IA64_LTOFF22:
+ case R_IA64_SEGREL64LSB:
+ default:
+ die("Unknown rela relocation: %lu\n", r_type);
+ break;
+ }
+ return;
+ overflow:
+ die("overflow in relocation type %lu val %Lx\n",
+ r_type, value);
+}
diff --git a/kexec/arch/ia64/kexec-ia64.c b/kexec/arch/ia64/kexec-ia64.c
new file mode 100644
index 0000000..b876318
--- /dev/null
+++ b/kexec/arch/ia64/kexec-ia64.c
@@ -0,0 +1,156 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2003-2005 Eric Biederman (ebiederm@xmission.com)
+ * Copyright (C) 2004 Albert Herranz
+ * Copyright (C) 2004 Silicon Graphics, Inc.
+ * Jesse Barnes <jbarnes@sgi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <stddef.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include <getopt.h>
+#include <sys/utsname.h>
+#include "../../kexec.h"
+#include "../../kexec-syscall.h"
+#include "kexec-ia64.h"
+#include <arch/options.h>
+
+#define MAX_MEMORY_RANGES 64
+#define MAX_LINE 160
+static struct memory_range memory_range[MAX_MEMORY_RANGES];
+
+/* Return a sorted list of available memory ranges. */
+int get_memory_ranges(struct memory_range **range, int *ranges)
+{
+ int memory_ranges;
+ /*
+ * /proc/iomem on ia64 does not show where all memory is. If
+ * that is fixed up, we can make use of that to validate
+ * the memory range kernel will be loade din. Until then.....
+ * -- Khalid Aziz
+ */
+
+ /* Note that the ia64 architecture mandates all systems will
+ * have at least 64MB at 0-64M. The SGI altix does not follow
+ * that restriction, but a reasonable guess is better than nothing
+ * at all.
+ * -- Eric Biederman
+ */
+ fprintf(stderr, "Warning assuming memory at 0-64MB is present\n");
+ memory_ranges = 0;
+ memory_range[memory_ranges].start = 0x00010000;
+ memory_range[memory_ranges].end = 0x10000000;
+ memory_range[memory_ranges].type = RANGE_RAM;
+ memory_ranges++;
+ *range = memory_range;
+ *ranges = memory_ranges;
+ return 0;
+}
+
+/* Supported file types and callbacks */
+struct file_type file_type[] = {
+ {"elf-ia64", elf_ia64_probe, elf_ia64_load, elf_ia64_usage},
+};
+int file_types = sizeof(file_type) / sizeof(file_type[0]);
+
+
+void arch_usage(void)
+{
+}
+
+static struct {
+} arch_options = {
+};
+int arch_process_options(int argc, char **argv)
+{
+ static const struct option options[] = {
+ KEXEC_ARCH_OPTIONS
+ { 0, 0, NULL, 0 },
+ };
+ static const char short_options[] = KEXEC_ARCH_OPT_STR;
+ int opt;
+ unsigned long value;
+ char *end;
+
+ opterr = 0; /* Don't complain about unrecognized options here */
+ while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
+ switch(opt) {
+ default:
+ break;
+ }
+ }
+ /* Reset getopt for the next pass; called in other source modules */
+ opterr = 1;
+ optind = 1;
+ return 0;
+}
+
+int arch_compat_trampoline(struct kexec_info *info, unsigned long *flags)
+{
+ int result;
+ struct utsname utsname;
+ result = uname(&utsname);
+ if (result < 0) {
+ fprintf(stderr, "uname failed: %s\n",
+ strerror(errno));
+ return -1;
+ }
+ if (strcmp(utsname.machine, "ia64") == 0)
+ {
+ *flags |= KEXEC_ARCH_X86_64;
+ }
+ else {
+ fprintf(stderr, "Unsupported machine type: %s\n",
+ utsname.machine);
+ return -1;
+ }
+ return 0;
+}
+
+int arch_compat_trampoline(struct kexec_info *info, unsigned long *flags)
+{
+ int result;
+ struct utsname utsname;
+ result = uname(&utsname);
+ if (result < 0) {
+ fprintf(stderr, "uname failed: %s\n",
+ strerror(errno));
+ return -1;
+ }
+ if (strcmp(utsname.machine, "ia64") == 0)
+ {
+ /* For compatibility with older patches
+ * use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_IA64 here.
+ */
+ *flags |= KEXEC_ARCH_DEFAULT;
+ }
+ else {
+ fprintf(stderr, "Unsupported machine type: %s\n",
+ utsname.machine);
+ return -1;
+ }
+ return 0;
+}
+
+void arch_update_purgatory(struct kexec_info *info)
+{
+}
+
diff --git a/kexec/arch/ia64/kexec-ia64.h b/kexec/arch/ia64/kexec-ia64.h
new file mode 100644
index 0000000..df49852
--- /dev/null
+++ b/kexec/arch/ia64/kexec-ia64.h
@@ -0,0 +1,9 @@
+#ifndef KEXEC_IA64_H
+#define KEXEC_IA64_H
+
+int elf_ia64_probe(const char *buf, off_t len);
+int elf_ia64_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info);
+void elf_ia64_usage(void);
+
+#endif /* KEXEC_IA64_H */
diff --git a/kexec/arch/ppc/Makefile b/kexec/arch/ppc/Makefile
new file mode 100644
index 0000000..972a2f2
--- /dev/null
+++ b/kexec/arch/ppc/Makefile
@@ -0,0 +1,9 @@
+#
+# kexec ppc (linux booting linux)
+#
+KEXEC_C_SRCS+= kexec/arch/ppc/kexec-ppc.c
+KEXEC_C_SRCS+= kexec/arch/ppc/kexec-elf-ppc.c
+KEXEC_C_SRCS+= kexec/arch/ppc/kexec-elf-rel-ppc.c
+KEXEC_C_SRCS+= kexec/arch/ppc/kexec-dol-ppc.c
+KEXEC_S_SRCS+= kexec/arch/ppc/ppc-setup-simple.S
+KEXEC_S_SRCS+= kexec/arch/ppc/ppc-setup-dol.S
diff --git a/kexec/arch/ppc/include/arch/options.h b/kexec/arch/ppc/include/arch/options.h
new file mode 100644
index 0000000..df14db5
--- /dev/null
+++ b/kexec/arch/ppc/include/arch/options.h
@@ -0,0 +1,11 @@
+#ifndef KEXEC_ARCH_PPC_OPTIONS_H
+#define KEXEC_ARCH_PPC_OPTIONS_H
+
+#define OPT_ARCH_MAX (OPT_MAX+0)
+
+#define KEXEC_ARCH_OPTIONS \
+ KEXEC_OPTIONS \
+
+#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR ""
+
+#endif /* KEXEC_ARCH_PPC_OPTIONS_H */
diff --git a/kexec/arch/ppc/kexec-dol-ppc.c b/kexec/arch/ppc/kexec-dol-ppc.c
new file mode 100644
index 0000000..1b34f2a
--- /dev/null
+++ b/kexec/arch/ppc/kexec-dol-ppc.c
@@ -0,0 +1,479 @@
+/*
+ * kexec-dol-ppc.c - kexec DOL executable loader for the PowerPC
+ * Copyright (C) 2004 Albert Herranz
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <elf.h>
+#include <boot/elf_boot.h>
+#include <ip_checksum.h>
+#include "../../kexec.h"
+#include "kexec-ppc.h"
+#include <arch/options.h>
+
+static int debug = 0;
+
+/*
+ * I've found out there DOLs with unaligned and/or overlapping sections.
+ * I assume that sizes of sections can be wrong on these DOLs so I trust
+ * better start of sections.
+ * In order to load DOLs, I first extend sections to page aligned boundaries
+ * and then merge overlapping sections starting from lower addresses.
+ * -- Albert Herranz
+ */
+
+/* DOL related stuff */
+
+#define DOL_HEADER_SIZE 0x100
+
+#define DOL_SECT_MAX_TEXT 7 /* text sections */
+#define DOL_SECT_MAX_DATA 11 /* data sections */
+#define DOL_MAX_SECT (DOL_SECT_MAX_TEXT+DOL_SECT_MAX_DATA)
+
+/* this is the DOL executable header */
+typedef struct {
+ uint32_t offset_text[DOL_SECT_MAX_TEXT]; /* in the file */
+ uint32_t offset_data[DOL_SECT_MAX_DATA];
+ uint32_t address_text[DOL_SECT_MAX_TEXT]; /* in memory */
+ uint32_t address_data[DOL_SECT_MAX_DATA];
+ uint32_t size_text[DOL_SECT_MAX_TEXT];
+ uint32_t size_data[DOL_SECT_MAX_DATA];
+ uint32_t address_bss;
+ uint32_t size_bss;
+ uint32_t entry_point;
+} dol_header;
+
+#define dol_sect_offset(hptr, index) \
+ ((index >= DOL_SECT_MAX_TEXT)? \
+ hptr->offset_data[index - DOL_SECT_MAX_TEXT] \
+ :hptr->offset_text[index])
+#define dol_sect_address(hptr, index) \
+ ((index >= DOL_SECT_MAX_TEXT)? \
+ hptr->address_data[index - DOL_SECT_MAX_TEXT] \
+ :hptr->address_text[index])
+#define dol_sect_size(hptr, index) \
+ ((index >= DOL_SECT_MAX_TEXT)? \
+ hptr->size_data[index - DOL_SECT_MAX_TEXT] \
+ :hptr->size_text[index])
+#define dol_sect_type(index) \
+ ((index >= DOL_SECT_MAX_TEXT) ? "data" : "text")
+
+typedef struct {
+ uint32_t sects_bitmap;
+ uint32_t start;
+ uint32_t size;
+} dol_segment;
+
+#define dol_seg_end(s1) \
+ (s1->start + s1->size)
+#define dol_seg_after_sect(s1, s2) \
+ (s1->start >= dol_seg_end(s2))
+#define dol_seg_overlaps(s1, s2) \
+ (!(dol_seg_after_sect(s1,s2) || dol_seg_after_sect(s2,s1)))
+
+/* same as in asm/page.h */
+#define PAGE_SHIFT 12
+#define PAGE_SIZE (1UL << PAGE_SHIFT)
+#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1))
+#define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
+
+#define BOOTLOADER "kexec"
+#define BOOTLOADER_VERSION VERSION
+#define MAX_COMMAND_LINE 256
+
+#define UPSZ(X) ((sizeof(X) + 3) & ~3)
+static struct boot_notes {
+ Elf_Bhdr hdr;
+ Elf_Nhdr bl_hdr;
+ unsigned char bl_desc[UPSZ(BOOTLOADER)];
+ Elf_Nhdr blv_hdr;
+ unsigned char blv_desc[UPSZ(BOOTLOADER_VERSION)];
+ Elf_Nhdr cmd_hdr;
+ unsigned char command_line[0];
+} elf_boot_notes = {
+ .hdr = {
+ .b_signature = 0x0E1FB007,
+ .b_size = sizeof(elf_boot_notes),
+ .b_checksum = 0,
+ .b_records = 3,
+ },
+ .bl_hdr = {
+ .n_namesz = 0,
+ .n_descsz = sizeof(BOOTLOADER),
+ .n_type = EBN_BOOTLOADER_NAME,
+ },
+ .bl_desc = BOOTLOADER,
+ .blv_hdr = {
+ .n_namesz = 0,
+ .n_descsz = sizeof(BOOTLOADER_VERSION),
+ .n_type = EBN_BOOTLOADER_VERSION,
+ },
+ .blv_desc = BOOTLOADER_VERSION,
+ .cmd_hdr = {
+ .n_namesz = 0,
+ .n_descsz = 0,
+ .n_type = EBN_COMMAND_LINE,
+ },
+};
+
+void print_sects_bitmap(dol_segment * seg)
+{
+ int i, first_seen;
+
+ printf("\t" "sects_bitmap");
+ first_seen = 0;
+ for (i = 0; i < DOL_MAX_SECT; i++) {
+ if ((seg->sects_bitmap & (1 << i)) == 0)
+ continue;
+ printf("%c%d", (first_seen ? ',' : '='), i);
+ first_seen = 1;
+ }
+ printf("\n");
+}
+
+void print_dol_segment(dol_segment * seg)
+{
+ printf("dol segment:\n");
+ printf("\t" "start=%08lx, size=%ld (%08lx)\n",
+ (unsigned long)seg->start, (unsigned long)seg->size,
+ (unsigned long)seg->size);
+ printf("\t" "end=%08lx\n", (unsigned long)dol_seg_end(seg));
+ print_sects_bitmap(seg);
+}
+
+int load_dol_segments(dol_segment * seg, int max_segs, dol_header * h)
+{
+ int i, n, remaining;
+ unsigned int start, size;
+ unsigned long adj1, adj2, end1;
+
+ n = 0;
+ remaining = max_segs;
+ for (i = 0; i < DOL_MAX_SECT && remaining > 0; i++) {
+ /* zero here means the section is not in use */
+ if (dol_sect_size(h, i) == 0)
+ continue;
+
+ /* we initially map 1 seg to 1 sect */
+ seg->sects_bitmap = (1 << i);
+
+ start = dol_sect_address(h, i);
+ size = dol_sect_size(h, i);
+
+ /* page align the segment */
+ seg->start = start & PAGE_MASK;
+ end1 = start + size;
+ adj1 = start - seg->start;
+ adj2 = PAGE_ALIGN(end1) - end1;
+ seg->size = adj1 + size + adj2;
+
+ //print_dol_segment(seg);
+
+ seg++;
+ remaining--;
+ n++;
+ }
+ return n;
+}
+
+void fix_dol_segments_overlaps(dol_segment * seg, int max_segs)
+{
+ int i, j;
+ dol_segment *p, *pp;
+ long extra_length;
+
+ /* look for overlapping segments and fix them */
+ for (i = 0; i < max_segs; i++) {
+ p = seg + i; /* segment p */
+
+ /* not really a segment */
+ if (p->size == 0)
+ continue;
+
+ /* check if overlaps any previous segments */
+ for (j = 0; j < i; j++) {
+ pp = seg + j; /* segment pp */
+
+ /* not a segment or no overlap */
+ if (pp->size == 0 || !dol_seg_overlaps(p, pp))
+ continue;
+
+ /* merge the two segments */
+ if (pp->start < p->start) {
+ /* extend pp to include p and delete p */
+ extra_length = dol_seg_end(p) - dol_seg_end(pp);
+ if (extra_length > 0) {
+ pp->size += extra_length;
+ }
+ pp->sects_bitmap |= p->sects_bitmap;
+ p->size = p->start = p->sects_bitmap = 0;
+
+ /* restart the loop because p was deleted */
+ i = 0;
+ break;
+ } else {
+ /* extend p to include pp and delete pp */
+ extra_length = dol_seg_end(pp) - dol_seg_end(p);
+ if (extra_length > 0) {
+ p->size += extra_length;
+ }
+ p->sects_bitmap |= pp->sects_bitmap;
+ pp->size = pp->start = pp->sects_bitmap = 0;
+ }
+ }
+ }
+}
+
+int dol_ppc_probe(const char *buf, off_t dol_length)
+{
+ dol_header header, *h;
+ int i, valid = 0;
+
+ /* the DOL file should be at least as long as the DOL header */
+ if (dol_length < DOL_HEADER_SIZE) {
+ if (debug) {
+ fprintf(stderr, "Not a DOL file, too short.\n");
+ }
+ return -1;
+ }
+
+ /* read the DOL header */
+ memcpy(&header, buf, sizeof(header));
+ h = &header;
+
+ /* now perform some sanity checks */
+ for (i = 0; i < DOL_MAX_SECT; i++) {
+ /* DOL segment MAY NOT be physically stored in the header */
+ if ((dol_sect_offset(h, i) != 0)
+ && (dol_sect_offset(h, i) < DOL_HEADER_SIZE)) {
+ if (debug) {
+ fprintf(stderr,
+ "%s segment offset within DOL header\n",
+ dol_sect_type(i));
+ }
+ return -1;
+ }
+
+ /* end of physical storage must be within file */
+ if (dol_sect_offset(h, i) + dol_sect_size(h, i) > dol_length) {
+ if (debug) {
+ fprintf(stderr,
+ "%s segment past DOL file size\n",
+ dol_sect_type(i));
+ }
+ return -1;
+ }
+
+ /* we only should accept DOLs with segments above 2GB */
+ if (dol_sect_address(h, i) != 0
+ && !(dol_sect_address(h, i) & 0x80000000)) {
+ fprintf(stderr, "warning, %s segment below 2GB\n",
+ dol_sect_type(i));
+ }
+
+ if (i < DOL_SECT_MAX_TEXT) {
+ /* remember that entrypoint was in a code segment */
+ if (h->entry_point >= dol_sect_address(h, i)
+ && h->entry_point < dol_sect_address(h, i) +
+ dol_sect_size(h, i))
+ valid = 1;
+ }
+ }
+
+ /* if there is a BSS segment it must^H^H^H^Hshould be above 2GB, too */
+ if (h->address_bss != 0 && !(h->address_bss & 0x80000000)) {
+ fprintf(stderr, "warning, BSS segment below 2GB\n");
+ }
+
+ /* if entrypoint is not within a code segment reject this file */
+ if (!valid) {
+ if (debug) {
+ fprintf(stderr, "Entry point out of text segment\n");
+ }
+ return -1;
+ }
+
+ /* I've got a dol */
+ return 0;
+}
+
+void dol_ppc_usage(void)
+{
+ printf
+ ("-d, --debug Enable debugging to help spot a failure.\n"
+ " --command-line=STRING Set the kernel command line to STRING.\n"
+ " --append=STRING Set the kernel command line to STRING.\n");
+
+}
+
+int dol_ppc_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info)
+{
+ dol_header header, *h;
+ unsigned long entry;
+ char *arg_buf;
+ size_t arg_bytes;
+ unsigned long arg_base;
+ struct boot_notes *notes;
+ size_t note_bytes;
+ const char *command_line;
+ int command_line_len;
+ unsigned long mstart;
+ dol_segment dol_segs[DOL_MAX_SECT];
+ unsigned int sects_bitmap;
+ unsigned long lowest_start;
+ int i, j, k;
+ int opt;
+#define OPT_APPEND (OPT_ARCH_MAX+0)
+
+ static const struct option options[] = {
+ KEXEC_ARCH_OPTIONS
+ {"debug", 0, 0, OPT_DEBUG},
+ {"command-line", 1, 0, OPT_APPEND},
+ {"append", 1, 0, OPT_APPEND},
+ {0, 0, 0, 0},
+ };
+ static const char short_options[] = KEXEC_ARCH_OPT_STR "d";
+
+ /*
+ * Parse the command line arguments
+ */
+ debug = 0;
+ command_line = 0;
+ while ((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
+ switch (opt) {
+ default:
+ /* Ignore core options */
+ if (opt < OPT_ARCH_MAX) {
+ break;
+ }
+ case '?':
+ usage();
+ return -1;
+ case OPT_DEBUG:
+ debug = 1;
+ break;
+ case OPT_APPEND:
+ command_line = optarg;
+ break;
+ }
+ }
+ command_line_len = 0;
+ if (command_line) {
+ command_line_len = strlen(command_line) + 1;
+ }
+
+ /* read the DOL header */
+ memcpy(&header, buf, sizeof(header));
+ h = &header;
+
+ /* set entry point */
+ entry = h->entry_point;
+
+ /* convert the DOL sections into suitable page aligned segments */
+ memset(dol_segs, 0, sizeof(dol_segs));
+
+ load_dol_segments(dol_segs, DOL_MAX_SECT, h);
+ fix_dol_segments_overlaps(dol_segs, DOL_MAX_SECT);
+
+ /* load rest of segments */
+ for (i = 0; i < DOL_MAX_SECT; i++) {
+ unsigned char *seg_buf;
+ /* not a segment */
+ if (dol_segs[i].size == 0)
+ continue;
+
+ //print_dol_segment(&dol_segs[i]);
+
+ /* prepare segment */
+ seg_buf = xmalloc(dol_segs[i].size);
+ mstart = dol_segs[i].start;
+ if (mstart & 0xf0000000) {
+ /*
+ * GameCube DOLs expect memory mapped this way:
+ *
+ * 80000000 - 817fffff 24MB RAM, cached
+ * c0000000 - c17fffff 24MB RAM, not cached
+ *
+ * kexec, instead, needs physical memory layout, so
+ * we clear the upper bits of the address.
+ * (2 bits should be enough, indeed)
+ */
+ mstart &= ~0xf0000000; /* clear bits 0-3, ibm syntax */
+ }
+ add_segment(info,
+ seg_buf, dol_segs[i].size,
+ mstart, dol_segs[i].size);
+
+
+ /* load sections into segment memory, according to bitmap */
+ sects_bitmap = 0;
+ while (sects_bitmap != dol_segs[i].sects_bitmap) {
+ unsigned char *sec_buf;
+ /* find lowest start address for section */
+ lowest_start = 0xffffffff;
+ for (j = -1, k = 0; k < DOL_MAX_SECT; k++) {
+ /* continue if section is already done */
+ if ((sects_bitmap & (1 << k)) != 0)
+ continue;
+ /* do nothing for non sections */
+ if ((dol_segs[i].sects_bitmap & (1 << k)) == 0)
+ continue;
+ /* found new candidate */
+ if (dol_sect_address(h, k) < lowest_start) {
+ lowest_start = dol_sect_address(h, k);
+ j = k;
+ }
+ }
+ /* mark section as being loaded */
+ sects_bitmap |= (1 << j);
+
+ /* read it from file to the right place */
+ sec_buf = seg_buf +
+ (dol_sect_address(h, j) - dol_segs[i].start);
+ memcpy(sec_buf, buf + dol_sect_offset(h, j),
+ dol_sect_size(h, j));
+ }
+ }
+
+ /* build the setup glue and argument segment (segment 0) */
+ note_bytes = sizeof(elf_boot_notes) + ((command_line_len + 3) & ~3);
+ arg_bytes = note_bytes + ((setup_dol_size + 3) & ~3);
+
+ arg_buf = xmalloc(arg_bytes);
+ arg_base = add_buffer(info,
+ arg_buf, arg_bytes, arg_bytes, 4, 0, 0xFFFFFFFFUL, 1);
+
+ notes = (struct boot_notes *)(arg_buf + ((setup_dol_size + 3) & ~3));
+
+ notes->hdr.b_size = note_bytes;
+ notes->cmd_hdr.n_descsz = command_line_len;
+ notes->hdr.b_checksum = compute_ip_checksum(notes, note_bytes);
+
+ setup_dol_regs.spr8 = entry; /* Link Register */
+
+ memcpy(arg_buf, setup_dol_start, setup_dol_size);
+ memcpy(notes, &elf_boot_notes, sizeof(elf_boot_notes));
+ memcpy(notes->command_line, command_line, command_line_len);
+
+ if (debug) {
+ fprintf(stdout, "entry = %p\n", (void *)arg_base);
+ print_segments(stdout, info);
+ }
+
+ info->entry = (void *)arg_base;
+ return 0;
+}
diff --git a/kexec/arch/ppc/kexec-elf-ppc.c b/kexec/arch/ppc/kexec-elf-ppc.c
new file mode 100644
index 0000000..0e6888e
--- /dev/null
+++ b/kexec/arch/ppc/kexec-elf-ppc.c
@@ -0,0 +1,225 @@
+/*
+ * kexec-elf-ppc.c - kexec Elf loader for the PowerPC
+ * Copyright (C) 2004 Albert Herranz
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <elf.h>
+#include <boot/elf_boot.h>
+#include <ip_checksum.h>
+#include "../../kexec.h"
+#include "../../kexec-elf.h"
+#include "kexec-ppc.h"
+#include <arch/options.h>
+
+static const int probe_debug = 0;
+
+#define BOOTLOADER "kexec"
+#define BOOTLOADER_VERSION VERSION
+#define MAX_COMMAND_LINE 256
+
+#define UPSZ(X) ((sizeof(X) + 3) & ~3)
+static struct boot_notes {
+ Elf_Bhdr hdr;
+ Elf_Nhdr bl_hdr;
+ unsigned char bl_desc[UPSZ(BOOTLOADER)];
+ Elf_Nhdr blv_hdr;
+ unsigned char blv_desc[UPSZ(BOOTLOADER_VERSION)];
+ Elf_Nhdr cmd_hdr;
+ unsigned char command_line[0];
+} elf_boot_notes = {
+ .hdr = {
+ .b_signature = 0x0E1FB007,
+ .b_size = sizeof(elf_boot_notes),
+ .b_checksum = 0,
+ .b_records = 3,
+ },
+ .bl_hdr = {
+ .n_namesz = 0,
+ .n_descsz = sizeof(BOOTLOADER),
+ .n_type = EBN_BOOTLOADER_NAME,
+ },
+ .bl_desc = BOOTLOADER,
+ .blv_hdr = {
+ .n_namesz = 0,
+ .n_descsz = sizeof(BOOTLOADER_VERSION),
+ .n_type = EBN_BOOTLOADER_VERSION,
+ },
+ .blv_desc = BOOTLOADER_VERSION,
+ .cmd_hdr = {
+ .n_namesz = 0,
+ .n_descsz = 0,
+ .n_type = EBN_COMMAND_LINE,
+ },
+};
+
+
+int elf_ppc_probe(const char *buf, off_t len)
+{
+
+ struct mem_ehdr ehdr;
+ int result;
+ result = build_elf_exec_info(buf, len, &ehdr);
+ if (result < 0) {
+ goto out;
+ }
+
+ /* Verify the architecuture specific bits */
+ if (ehdr.e_machine != EM_PPC) {
+ /* for a different architecture */
+ if (probe_debug) {
+ fprintf(stderr, "Not for this architecture.\n");
+ }
+ result = -1;
+ goto out;
+ }
+ result = 0;
+ out:
+ free_elf_info(&ehdr);
+ return result;
+}
+
+void elf_ppc_usage(void)
+{
+ printf
+ (
+ " --command-line=STRING Set the kernel command line to STRING.\n"
+ " --append=STRING Set the kernel command line to STRING.\n"
+ " --gamecube=1|0 Enable/disable support for ELFs with changed\n"
+ " addresses suitable for the GameCube.\n");
+}
+
+static void gamecube_hack_addresses(struct mem_ehdr *ehdr)
+{
+ struct mem_phdr *phdr, *phdr_end;
+ phdr_end = ehdr->e_phdr + ehdr->e_phnum;
+ for(phdr = ehdr->e_phdr; phdr != phdr_end; phdr++) {
+ /*
+ * GameCube ELF kernel is linked with memory mapped
+ * this way (to easily transform it into a DOL
+ * suitable for being loaded with psoload):
+ *
+ * 80000000 - 817fffff 24MB RAM, cached
+ * c0000000 - c17fffff 24MB RAM, not cached
+ *
+ * kexec, instead, needs physical memory layout, so
+ * we clear the upper bits of the address.
+ * (2 bits should be enough, indeed)
+ */
+ phdr->p_paddr &= ~0xf0000000; /* clear bits 0-3, ibm syntax */
+ }
+}
+
+int elf_ppc_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info)
+{
+ struct mem_ehdr ehdr;
+ char *arg_buf;
+ size_t arg_bytes;
+ unsigned long arg_base;
+ struct boot_notes *notes;
+ size_t note_bytes;
+ const char *command_line;
+ int command_line_len;
+ unsigned char *setup_start;
+ uint32_t setup_size;
+ int result;
+#ifdef CONFIG_GAMECUBE
+ int target_is_gamecube = 1;
+#else
+ int target_is_gamecube = 0;
+#endif
+ int opt;
+#define OPT_APPEND (OPT_ARCH_MAX+0)
+#define OPT_GAMECUBE (OPT_ARCH_MAX+1)
+ static const struct option options[] = {
+ KEXEC_ARCH_OPTIONS
+ {"command-line", 1, 0, OPT_APPEND},
+ {"append", 1, 0, OPT_APPEND},
+ {"gamecube", 1, 0, OPT_GAMECUBE},
+ {0, 0, 0, 0},
+ };
+
+ static const char short_options[] = KEXEC_ARCH_OPT_STR "d";
+
+ command_line = 0;
+ while ((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
+ switch (opt) {
+ default:
+ /* Ignore core options */
+ if (opt < OPT_ARCH_MAX) {
+ break;
+ }
+ case '?':
+ usage();
+ return -1;
+ case OPT_APPEND:
+ command_line = optarg;
+ break;
+ case OPT_GAMECUBE:
+ target_is_gamecube = atoi(optarg);
+ break;
+ }
+ }
+ command_line_len = 0;
+ if (command_line) {
+ command_line_len = strlen(command_line) + 1;
+ }
+
+ /* Parse the Elf file */
+ result = build_elf_exec_info(buf, len, &ehdr);
+ if (result < 0) {
+ free_elf_info(&ehdr);
+ return result;
+ }
+ if (target_is_gamecube) {
+ gamecube_hack_addresses(&ehdr);
+ }
+ /* Load the Elf data */
+ result = elf_exec_load(&ehdr, info);
+ if (result < 0) {
+ free_elf_info(&ehdr);
+ return result;
+ }
+
+ if (target_is_gamecube) {
+ setup_start = setup_dol_start;
+ setup_size = setup_dol_size;
+ setup_dol_regs.spr8 = ehdr.e_entry; /* Link Register */
+ } else {
+ setup_start = setup_simple_start;
+ setup_size = setup_simple_size;
+ setup_simple_regs.spr8 = ehdr.e_entry; /* Link Register */
+ }
+ note_bytes = sizeof(elf_boot_notes) + ((command_line_len + 3) & ~3);
+ arg_bytes = note_bytes + ((setup_size + 3) & ~3);
+
+ arg_buf = xmalloc(arg_bytes);
+ arg_base = add_buffer(info,
+ arg_buf, arg_bytes, arg_bytes, 4, 0, elf_max_addr(&ehdr), 1);
+
+ notes = (struct boot_notes *)(arg_buf + ((setup_size + 3) & ~3));
+
+ memcpy(arg_buf, setup_start, setup_size);
+ memcpy(notes, &elf_boot_notes, sizeof(elf_boot_notes));
+ memcpy(notes->command_line, command_line, command_line_len);
+ notes->hdr.b_size = note_bytes;
+ notes->cmd_hdr.n_descsz = command_line_len;
+ notes->hdr.b_checksum = compute_ip_checksum(notes, note_bytes);
+
+ info->entry = (void *)arg_base;
+ return 0;
+}
diff --git a/kexec/arch/ppc/kexec-elf-rel-ppc.c b/kexec/arch/ppc/kexec-elf-rel-ppc.c
new file mode 100644
index 0000000..e711f3b
--- /dev/null
+++ b/kexec/arch/ppc/kexec-elf-rel-ppc.c
@@ -0,0 +1,64 @@
+#include <stdio.h>
+#include <elf.h>
+#include "../../kexec.h"
+#include "../../kexec-elf.h"
+
+int machine_verify_elf_rel(struct mem_ehdr *ehdr)
+{
+ if (ehdr->ei_data != ELFDATA2MSB) {
+ return 0;
+ }
+ if (ehdr->ei_class != ELFCLASS32) {
+ return 0;
+ }
+ if (ehdr->e_machine != EM_PPC) {
+ return 0;
+ }
+ return 1;
+}
+
+void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type,
+ void *location, unsigned long address, unsigned long value)
+{
+ switch(r_type) {
+ case R_PPC_ADDR32:
+ /* Simply set it */
+ *(uint32_t *)location = value;
+ break;
+
+ case R_PPC_ADDR16_LO:
+ /* Low half of the symbol */
+ *(uint16_t *)location = value;
+ break;
+
+ case R_PPC_ADDR16_HA:
+ /* Sign-adjusted lower 16 bits: PPC ELF ABI says:
+ (((x >> 16) + ((x & 0x8000) ? 1 : 0))) & 0xFFFF.
+ This is the same, only sane.
+ */
+ *(uint16_t *)location = (value + 0x8000) >> 16;
+ break;
+
+ case R_PPC_REL24:
+ if ((int)(value - address) < -0x02000000
+ || (int)(value - address) >= 0x02000000)
+ {
+ die("Symbol more than 16MiB away");
+ }
+ /* Only replace bits 2 through 26 */
+ *(uint32_t *)location
+ = (*(uint32_t *)location & ~0x03fffffc)
+ | ((value - address)
+ & 0x03fffffc);
+ break;
+
+ case R_PPC_REL32:
+ /* 32-bit relative jump. */
+ *(uint32_t *)location = value - address;
+ break;
+ default:
+ die("Unknown rela relocation: %lu\n", r_type);
+ break;
+ }
+ return;
+}
diff --git a/kexec/arch/ppc/kexec-ppc.c b/kexec/arch/ppc/kexec-ppc.c
new file mode 100644
index 0000000..72c5b95
--- /dev/null
+++ b/kexec/arch/ppc/kexec-ppc.c
@@ -0,0 +1,151 @@
+/*
+ * kexec-ppc.c - kexec for the PowerPC
+ * Copyright (C) 2004, 2005 Albert Herranz
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include <getopt.h>
+#include <sys/utsname.h>
+#include "../../kexec.h"
+#include "../../kexec-syscall.h"
+#include "kexec-ppc.h"
+#include <arch/options.h>
+
+#define MAX_MEMORY_RANGES 64
+#define MAX_LINE 160
+static struct memory_range memory_range[MAX_MEMORY_RANGES];
+
+/* Return a sorted list of memory ranges. */
+int get_memory_ranges(struct memory_range **range, int *ranges)
+{
+ int memory_ranges = 0;
+#ifdef CONFIG_GAMECUBE
+ /* RAM - lowmem used by DOLs - framebuffer */
+ memory_range[memory_ranges].start = 0x00003000;
+ memory_range[memory_ranges].end = 0x0174bfff;
+ memory_range[memory_ranges].type = RANGE_RAM;
+ memory_ranges++;
+#else
+#error Please, fix this for your platform
+ const char iomem[] = "/proc/iomem";
+ char line[MAX_LINE];
+ FILE *fp;
+ unsigned long long start, end;
+ char *str;
+ int type, consumed, count;
+
+ fp = fopen(iomem, "r");
+ if (!fp) {
+ fprintf(stderr, "Cannot open %s: %s\n", iomem, strerror(errno));
+ return -1;
+ }
+ while (fgets(line, sizeof(line), fp) != 0) {
+ if (memory_ranges >= MAX_MEMORY_RANGES)
+ break;
+ count = sscanf(line, "%Lx-%Lx : %n", &start, &end, &consumed);
+ if (count != 2)
+ continue;
+ str = line + consumed;
+ end = end + 1;
+#if 0
+ printf("%016Lx-%016Lx : %s\n", start, end, str);
+#endif
+ if (memcmp(str, "System RAM\n", 11) == 0) {
+ type = RANGE_RAM;
+ } else if (memcmp(str, "reserved\n", 9) == 0) {
+ type = RANGE_RESERVED;
+ } else if (memcmp(str, "ACPI Tables\n", 12) == 0) {
+ type = RANGE_ACPI;
+ } else if (memcmp(str, "ACPI Non-volatile Storage\n", 26) == 0) {
+ type = RANGE_ACPI_NVS;
+ } else {
+ continue;
+ }
+ memory_range[memory_ranges].start = start;
+ memory_range[memory_ranges].end = end;
+ memory_range[memory_ranges].type = type;
+#if 0
+ printf("%016Lx-%016Lx : %x\n", start, end, type);
+#endif
+ memory_ranges++;
+ }
+ fclose(fp);
+#endif
+ *range = memory_range;
+ *ranges = memory_ranges;
+ return 0;
+}
+
+struct file_type file_type[] = {
+ {"elf-ppc", elf_ppc_probe, elf_ppc_load, elf_ppc_usage},
+ {"dol-ppc", dol_ppc_probe, dol_ppc_load, dol_ppc_usage},
+};
+int file_types = sizeof(file_type) / sizeof(file_type[0]);
+
+void arch_usage(void)
+{
+}
+
+static struct {
+} arch_options = {
+};
+int arch_process_options(int argc, char **argv)
+{
+ static const struct option options[] = {
+ KEXEC_ARCH_OPTIONS
+ { 0, 0, NULL, 0 },
+ };
+ static const char short_options[] = KEXEC_ARCH_OPT_STR;
+ int opt;
+ unsigned long value;
+ char *end;
+
+ opterr = 0; /* Don't complain about unrecognized options here */
+ while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
+ switch(opt) {
+ default:
+ break;
+ }
+ }
+ /* Reset getopt for the next pass; called in other source modules */
+ opterr = 1;
+ optind = 1;
+ return 0;
+}
+
+int arch_compat_trampoline(struct kexec_info *info, unsigned long *flags)
+{
+ int result;
+ struct utsname utsname;
+ result = uname(&utsname);
+ if (result < 0) {
+ fprintf(stderr, "uname failed: %s\n",
+ strerror(errno));
+ return -1;
+ }
+ if (strcmp(utsname.machine, "ppc") == 0)
+ {
+ /* For compatibility with older patches
+ * use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_PPC here.
+ */
+ *flags |= KEXEC_ARCH_DEFAULT;
+ }
+ else {
+ fprintf(stderr, "Unsupported machine type: %s\n",
+ utsname.machine);
+ return -1;
+ }
+ return 0;
+}
+
+void arch_update_purgatory(struct kexec_info *info)
+{
+}
+
diff --git a/kexec/arch/ppc/kexec-ppc.h b/kexec/arch/ppc/kexec-ppc.h
new file mode 100644
index 0000000..6a40cc8
--- /dev/null
+++ b/kexec/arch/ppc/kexec-ppc.h
@@ -0,0 +1,28 @@
+#ifndef KEXEC_PPC_H
+#define KEXEC_PPC_H
+
+extern unsigned char setup_simple_start[];
+extern uint32_t setup_simple_size;
+
+extern struct {
+ uint32_t spr8;
+} setup_simple_regs;
+
+extern unsigned char setup_dol_start[];
+extern uint32_t setup_dol_size;
+
+extern struct {
+ uint32_t spr8;
+} setup_dol_regs;
+
+int elf_ppc_probe(const char *buf, off_t len);
+int elf_ppc_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info);
+void elf_ppc_usage(void);
+
+int dol_ppc_probe(const char *buf, off_t len);
+int dol_ppc_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info);
+void dol_ppc_usage(void);
+
+#endif /* KEXEC_PPC_H */
diff --git a/kexec/arch/ppc/ppc-setup-dol.S b/kexec/arch/ppc/ppc-setup-dol.S
new file mode 100644
index 0000000..17169bd
--- /dev/null
+++ b/kexec/arch/ppc/ppc-setup-dol.S
@@ -0,0 +1,174 @@
+/*
+ * ppc-setup-dol.S - setup glue for Nintendo's GameCube
+ * Copyright (C) 2004 Albert Herranz
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include "ppc_asm.h"
+
+ .data
+ .globl setup_dol_start
+setup_dol_start:
+
+ /* Try to reproduce the GameCube "native" environment */
+
+ /* Setup BATs */
+ isync
+ li r8, 0
+ mtspr DBAT0U, r8
+ mtspr DBAT0L, r8
+ mtspr DBAT1U, r8
+ mtspr DBAT1L, r8
+ mtspr DBAT2U, r8
+ mtspr DBAT2L, r8
+ mtspr DBAT3U, r8
+ mtspr DBAT3L, r8
+ mtspr IBAT0U, r8
+ mtspr IBAT0L, r8
+ mtspr IBAT1U, r8
+ mtspr IBAT1L, r8
+ mtspr IBAT2U, r8
+ mtspr IBAT2L, r8
+ mtspr IBAT3U, r8
+ mtspr IBAT3L, r8
+
+ /*
+ * Memory Map
+ * start end size description
+ * 0x80000000 0x817fffff 24MB RAM, uncached
+ * 0xc0000000 0xc17fffff 24MB RAM, cached
+ * 0xc8000000 0xc81fffff 2MB Embedded Framebuffer
+ * 0xcc000000 Hardware registers
+ * 0xe0000000 Layer 2 transfer cache ??? 256KB
+ *
+ */
+
+ isync
+ lis r8, 0x8000 /* IBAT0,DBAT0 for first 16Mbytes */
+ ori r8, r8, 0x01ff /* 16MB */
+ mtspr IBAT0U, r8
+ mtspr DBAT0U, r8
+ li r8, 0x0002 /* rw */
+ mtspr IBAT0L, r8
+ mtspr DBAT0L, r8
+
+ lis r8, 0xc000 /* DBAT1 for IO mem */
+ ori r8, r8, 0x1fff /* 256MB */
+ mtspr DBAT1U, r8
+ li r8, 0x002a /* uncached, guarded ,rw */
+ mtspr DBAT1L, r8
+
+ lis r8, 0x8100 /* IBAT2,DBAT2 for next 8Mbytes */
+ ori r8, r8, 0x00ff /* 8MB */
+ mtspr IBAT2U, r8
+ mtspr DBAT2U, r8
+ lis r8, 0x0100
+ ori r8, r8, 0x0002 /* rw */
+ mtspr IBAT2L, r8
+ mtspr DBAT2L, r8
+
+ lis r8, 0xe000 /* DBAT3 for layer 2 transfer cache ??? */
+ ori r8, r8, 0x01fe /* 16MB ??? */
+ mtspr DBAT3U, r8
+ lis r8, 0xe000
+ ori r8, r8, 0x0002 /* rw */
+ mtspr DBAT3L, r8
+
+ sync
+ isync
+
+/* AFAIK, this is not strictly needed, although seems sane */
+#if 1
+ li r9, 0
+
+ /* page table pointer */
+ sync
+ mtspr SDR1, r9
+
+ /* segment registers */
+ li r8, 16
+ mtctr r8
+ li r8, 0
+1: mtsrin r9, r8 /* zero */
+ sync
+ addis r8,r8,0x1000 /* next register */
+ bdnz 1b
+#endif
+
+ /* switch MMU on and continue */
+ RELOC_SYM(1f)
+ mfmsr r0
+ ori r0, r0, MSR_RI|MSR_ME|MSR_DR|MSR_IR
+ mtspr SRR1, r0
+ oris r3, r3, 0x8000 /* adjust text address */
+ mtspr SRR0, r3
+ oris r1, r1, 0x8000 /* adjust stack */
+ sync
+ rfi
+
+1:
+ /* from now on we run in a DOL-like environment */
+
+
+ /* first, sanitize the hardware a little bit */
+ /* although seems to be not needed in the general case */
+
+#if 1
+ /* audio */
+ lis r8, 0xcc00 /* io mem */
+ li r9, 0
+ sth r9, 0x5036(r8) /* stop audio sample */
+ stw r9, 0x6c00(r8) /* stop streaming */
+ stw r9, 0x6c04(r8) /* mute */
+
+ /* video */
+ mfspr r8, 920 /* spr920 = HID2 */
+ rlwinm r8, r8, 0, 4, 2 /* stop GX FIFO, and more */
+ mtspr 920, r8
+
+ /* exi */
+ lis r8, 0xcc00 /* io mem */
+1: lwz r9,0x680c(r8) /* wait for dma transfer to complete */
+ andi. r9,r9,1
+ bne+ 1b
+ stw r9,0x6800(r8) /* disable exi interrupts */
+ addi r8,r8,0x14 /* next channel */
+ andi. r9,r8,0x40 /* XXX 4 channels? */
+ beq+ 1b
+
+ /* pic */
+ lis r8, 0xcc00 /* io mem */
+ li r9, 0
+ stw r9, 0x3004(r8) /* mask all interrupts */
+ stw r9, 0x3000(r8) /* clear interrupt cause */
+
+ /* invalidate L1 data and instructions caches */
+ mfspr r8, HID0
+ ori r8, r8, HID0_ICFI|HID0_DCI
+ mtspr HID0, r8
+#endif
+
+ /* jump to our entry point */
+ RELOC_SYM(setup_dol_regs)
+ mr r9, r3
+ lwz r5, spr8 - setup_dol_regs(r9)
+
+ mtlr r5
+ blr
+
+ .balign 4
+ .globl setup_dol_regs
+setup_dol_regs:
+spr8: .long 0x00000000
+
+ .balign 4
+//#include "isobel_reloc_debug_console.s"
+
+setup_dol_end:
+
+ .globl setup_dol_size
+setup_dol_size:
+ .long setup_dol_end - setup_dol_start
+
diff --git a/kexec/arch/ppc/ppc-setup-simple.S b/kexec/arch/ppc/ppc-setup-simple.S
new file mode 100644
index 0000000..1317a8d
--- /dev/null
+++ b/kexec/arch/ppc/ppc-setup-simple.S
@@ -0,0 +1,39 @@
+/*
+ * ppc-setup-simple.S - (hopefully) setup for simple embedded platforms
+ * Copyright (C) 2004 Albert Herranz
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+/*
+ * Only suitable for platforms booting with MMU turned off.
+ * -- Albert Herranz
+ */
+
+#include "ppc_asm.h"
+
+ .data
+ .globl setup_simple_start
+setup_simple_start:
+
+ /* should perform here any required setup */
+
+ RELOC_SYM(setup_simple_regs)
+ mr r9, r3
+ lwz r5, spr8 - setup_simple_regs(r9)
+
+ mtlr r5
+ blr
+
+ .balign 4
+ .globl setup_simple_regs
+setup_simple_regs:
+spr8: .long 0x00000000
+
+setup_simple_end:
+
+ .globl setup_simple_size
+setup_simple_size:
+ .long setup_simple_end - setup_simple_start
+
diff --git a/kexec/arch/ppc/ppc_asm.h b/kexec/arch/ppc/ppc_asm.h
new file mode 100644
index 0000000..36503a9
--- /dev/null
+++ b/kexec/arch/ppc/ppc_asm.h
@@ -0,0 +1,506 @@
+/*
+ * ppc_asm.h - mainly bits stolen from Linux kernel asm/reg.h and asm/ppc_asm.h
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+/* Condition Register Bit Fields */
+
+#define cr0 0
+#define cr1 1
+#define cr2 2
+#define cr3 3
+#define cr4 4
+#define cr5 5
+#define cr6 6
+#define cr7 7
+
+
+/* General Purpose Registers (GPRs) */
+
+#define r0 0
+#define r1 1
+#define r2 2
+#define r3 3
+#define r4 4
+#define r5 5
+#define r6 6
+#define r7 7
+#define r8 8
+#define r9 9
+#define r10 10
+#define r11 11
+#define r12 12
+#define r13 13
+#define r14 14
+#define r15 15
+#define r16 16
+#define r17 17
+#define r18 18
+#define r19 19
+#define r20 20
+#define r21 21
+#define r22 22
+#define r23 23
+#define r24 24
+#define r25 25
+#define r26 26
+#define r27 27
+#define r28 28
+#define r29 29
+#define r30 30
+#define r31 31
+
+/* Machine State Register (MSR) Fields */
+#define MSR_SF (1<<63)
+#define MSR_ISF (1<<61)
+#define MSR_VEC (1<<25) /* Enable AltiVec */
+#define MSR_POW (1<<18) /* Enable Power Management */
+#define MSR_WE (1<<18) /* Wait State Enable */
+#define MSR_TGPR (1<<17) /* TLB Update registers in use */
+#define MSR_CE (1<<17) /* Critical Interrupt Enable */
+#define MSR_ILE (1<<16) /* Interrupt Little Endian */
+#define MSR_EE (1<<15) /* External Interrupt Enable */
+#define MSR_PR (1<<14) /* Problem State / Privilege Level */
+#define MSR_FP (1<<13) /* Floating Point enable */
+#define MSR_ME (1<<12) /* Machine Check Enable */
+#define MSR_FE0 (1<<11) /* Floating Exception mode 0 */
+#define MSR_SE (1<<10) /* Single Step */
+#define MSR_BE (1<<9) /* Branch Trace */
+#define MSR_DE (1<<9) /* Debug Exception Enable */
+#define MSR_FE1 (1<<8) /* Floating Exception mode 1 */
+#define MSR_IP (1<<6) /* Exception prefix 0x000/0xFFF */
+#define MSR_IR (1<<5) /* Instruction Relocate */
+#define MSR_DR (1<<4) /* Data Relocate */
+#define MSR_PE (1<<3) /* Protection Enable */
+#define MSR_PX (1<<2) /* Protection Exclusive Mode */
+#define MSR_RI (1<<1) /* Recoverable Exception */
+#define MSR_LE (1<<0) /* Little Endian */
+
+/* Special Purpose Registers (SPRNs)*/
+#define SPRN_CTR 0x009 /* Count Register */
+#define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */
+#define SPRN_DAR 0x013 /* Data Address Register */
+#define SPRN_TBRL 0x10C /* Time Base Read Lower Register (user, R/O) */
+#define SPRN_TBRU 0x10D /* Time Base Read Upper Register (user, R/O) */
+#define SPRN_TBWL 0x11C /* Time Base Lower Register (super, R/W) */
+#define SPRN_TBWU 0x11D /* Time Base Upper Register (super, R/W) */
+#define SPRN_HIOR 0x137 /* 970 Hypervisor interrupt offset */
+#define SPRN_DBAT0L 0x219 /* Data BAT 0 Lower Register */
+#define SPRN_DBAT0U 0x218 /* Data BAT 0 Upper Register */
+#define SPRN_DBAT1L 0x21B /* Data BAT 1 Lower Register */
+#define SPRN_DBAT1U 0x21A /* Data BAT 1 Upper Register */
+#define SPRN_DBAT2L 0x21D /* Data BAT 2 Lower Register */
+#define SPRN_DBAT2U 0x21C /* Data BAT 2 Upper Register */
+#define SPRN_DBAT3L 0x21F /* Data BAT 3 Lower Register */
+#define SPRN_DBAT3U 0x21E /* Data BAT 3 Upper Register */
+#define SPRN_DBAT4L 0x239 /* Data BAT 4 Lower Register */
+#define SPRN_DBAT4U 0x238 /* Data BAT 4 Upper Register */
+#define SPRN_DBAT5L 0x23B /* Data BAT 5 Lower Register */
+#define SPRN_DBAT5U 0x23A /* Data BAT 5 Upper Register */
+#define SPRN_DBAT6L 0x23D /* Data BAT 6 Lower Register */
+#define SPRN_DBAT6U 0x23C /* Data BAT 6 Upper Register */
+#define SPRN_DBAT7L 0x23F /* Data BAT 7 Lower Register */
+#define SPRN_DBAT7U 0x23E /* Data BAT 7 Upper Register */
+
+#define SPRN_DEC 0x016 /* Decrement Register */
+#define SPRN_DER 0x095 /* Debug Enable Regsiter */
+#define DER_RSTE 0x40000000 /* Reset Interrupt */
+#define DER_CHSTPE 0x20000000 /* Check Stop */
+#define DER_MCIE 0x10000000 /* Machine Check Interrupt */
+#define DER_EXTIE 0x02000000 /* External Interrupt */
+#define DER_ALIE 0x01000000 /* Alignment Interrupt */
+#define DER_PRIE 0x00800000 /* Program Interrupt */
+#define DER_FPUVIE 0x00400000 /* FP Unavailable Interrupt */
+#define DER_DECIE 0x00200000 /* Decrementer Interrupt */
+#define DER_SYSIE 0x00040000 /* System Call Interrupt */
+#define DER_TRE 0x00020000 /* Trace Interrupt */
+#define DER_SEIE 0x00004000 /* FP SW Emulation Interrupt */
+#define DER_ITLBMSE 0x00002000 /* Imp. Spec. Instruction TLB Miss */
+#define DER_ITLBERE 0x00001000 /* Imp. Spec. Instruction TLB Error */
+#define DER_DTLBMSE 0x00000800 /* Imp. Spec. Data TLB Miss */
+#define DER_DTLBERE 0x00000400 /* Imp. Spec. Data TLB Error */
+#define DER_LBRKE 0x00000008 /* Load/Store Breakpoint Interrupt */
+#define DER_IBRKE 0x00000004 /* Instruction Breakpoint Interrupt */
+#define DER_EBRKE 0x00000002 /* External Breakpoint Interrupt */
+#define DER_DPIE 0x00000001 /* Dev. Port Nonmaskable Request */
+#define SPRN_DMISS 0x3D0 /* Data TLB Miss Register */
+#define SPRN_DSISR 0x012 /* Data Storage Interrupt Status Register */
+#define SPRN_EAR 0x11A /* External Address Register */
+#define SPRN_HASH1 0x3D2 /* Primary Hash Address Register */
+#define SPRN_HASH2 0x3D3 /* Secondary Hash Address Resgister */
+#define SPRN_HID0 0x3F0 /* Hardware Implementation Register 0 */
+#define HID0_EMCP (1<<31) /* Enable Machine Check pin */
+#define HID0_EBA (1<<29) /* Enable Bus Address Parity */
+#define HID0_EBD (1<<28) /* Enable Bus Data Parity */
+#define HID0_SBCLK (1<<27)
+#define HID0_EICE (1<<26)
+#define HID0_TBEN (1<<26) /* Timebase enable - 745x */
+#define HID0_ECLK (1<<25)
+#define HID0_PAR (1<<24)
+#define HID0_STEN (1<<24) /* Software table search enable - 745x */
+#define HID0_HIGH_BAT (1<<23) /* Enable high BATs - 7455 */
+#define HID0_DOZE (1<<23)
+#define HID0_NAP (1<<22)
+#define HID0_SLEEP (1<<21)
+#define HID0_DPM (1<<20)
+#define HID0_BHTCLR (1<<18) /* Clear branch history table - 7450 */
+#define HID0_XAEN (1<<17) /* Extended addressing enable - 7450 */
+#define HID0_NHR (1<<16) /* Not hard reset (software bit-7450)*/
+#define HID0_ICE (1<<15) /* Instruction Cache Enable */
+#define HID0_DCE (1<<14) /* Data Cache Enable */
+#define HID0_ILOCK (1<<13) /* Instruction Cache Lock */
+#define HID0_DLOCK (1<<12) /* Data Cache Lock */
+#define HID0_ICFI (1<<11) /* Instr. Cache Flash Invalidate */
+#define HID0_DCI (1<<10) /* Data Cache Invalidate */
+#define HID0_SPD (1<<9) /* Speculative disable */
+#define HID0_SGE (1<<7) /* Store Gathering Enable */
+#define HID0_SIED (1<<7) /* Serial Instr. Execution [Disable] */
+#define HID0_DFCA (1<<6) /* Data Cache Flush Assist */
+#define HID0_LRSTK (1<<4) /* Link register stack - 745x */
+#define HID0_BTIC (1<<5) /* Branch Target Instr Cache Enable */
+#define HID0_ABE (1<<3) /* Address Broadcast Enable */
+#define HID0_FOLD (1<<3) /* Branch Folding enable - 745x */
+#define HID0_BHTE (1<<2) /* Branch History Table Enable */
+#define HID0_BTCD (1<<1) /* Branch target cache disable */
+#define HID0_NOPDST (1<<1) /* No-op dst, dstt, etc. instr. */
+#define HID0_NOPTI (1<<0) /* No-op dcbt and dcbst instr. */
+
+#define SPRN_HID1 0x3F1 /* Hardware Implementation Register 1 */
+#define HID1_EMCP (1<<31) /* 7450 Machine Check Pin Enable */
+#define HID1_PC0 (1<<16) /* 7450 PLL_CFG[0] */
+#define HID1_PC1 (1<<15) /* 7450 PLL_CFG[1] */
+#define HID1_PC2 (1<<14) /* 7450 PLL_CFG[2] */
+#define HID1_PC3 (1<<13) /* 7450 PLL_CFG[3] */
+#define HID1_SYNCBE (1<<11) /* 7450 ABE for sync, eieio */
+#define HID1_ABE (1<<10) /* 7450 Address Broadcast Enable */
+#define SPRN_HID2 0x3F8 /* Hardware Implementation Register 2 */
+#define SPRN_IABR 0x3F2 /* Instruction Address Breakpoint Register */
+#define SPRN_HID4 0x3F4 /* 970 HID4 */
+#define SPRN_HID5 0x3F6 /* 970 HID5 */
+#if !defined(SPRN_IAC1) && !defined(SPRN_IAC2)
+#define SPRN_IAC1 0x3F4 /* Instruction Address Compare 1 */
+#define SPRN_IAC2 0x3F5 /* Instruction Address Compare 2 */
+#endif
+#define SPRN_IBAT0L 0x211 /* Instruction BAT 0 Lower Register */
+#define SPRN_IBAT0U 0x210 /* Instruction BAT 0 Upper Register */
+#define SPRN_IBAT1L 0x213 /* Instruction BAT 1 Lower Register */
+#define SPRN_IBAT1U 0x212 /* Instruction BAT 1 Upper Register */
+#define SPRN_IBAT2L 0x215 /* Instruction BAT 2 Lower Register */
+#define SPRN_IBAT2U 0x214 /* Instruction BAT 2 Upper Register */
+#define SPRN_IBAT3L 0x217 /* Instruction BAT 3 Lower Register */
+#define SPRN_IBAT3U 0x216 /* Instruction BAT 3 Upper Register */
+#define SPRN_IBAT4L 0x231 /* Instruction BAT 4 Lower Register */
+#define SPRN_IBAT4U 0x230 /* Instruction BAT 4 Upper Register */
+#define SPRN_IBAT5L 0x233 /* Instruction BAT 5 Lower Register */
+#define SPRN_IBAT5U 0x232 /* Instruction BAT 5 Upper Register */
+#define SPRN_IBAT6L 0x235 /* Instruction BAT 6 Lower Register */
+#define SPRN_IBAT6U 0x234 /* Instruction BAT 6 Upper Register */
+#define SPRN_IBAT7L 0x237 /* Instruction BAT 7 Lower Register */
+#define SPRN_IBAT7U 0x236 /* Instruction BAT 7 Upper Register */
+#define SPRN_ICMP 0x3D5 /* Instruction TLB Compare Register */
+#define SPRN_ICTC 0x3FB /* Instruction Cache Throttling Control Reg */
+#define SPRN_ICTRL 0x3F3 /* 1011 7450 icache and interrupt ctrl */
+#define ICTRL_EICE 0x08000000 /* enable icache parity errs */
+#define ICTRL_EDC 0x04000000 /* enable dcache parity errs */
+#define ICTRL_EICP 0x00000100 /* enable icache par. check */
+#define SPRN_IMISS 0x3D4 /* Instruction TLB Miss Register */
+#define SPRN_IMMR 0x27E /* Internal Memory Map Register */
+#define SPRN_L2CR 0x3F9 /* Level 2 Cache Control Regsiter */
+#define SPRN_L2CR2 0x3f8
+#define L2CR_L2E 0x80000000 /* L2 enable */
+#define L2CR_L2PE 0x40000000 /* L2 parity enable */
+#define L2CR_L2SIZ_MASK 0x30000000 /* L2 size mask */
+#define L2CR_L2SIZ_256KB 0x10000000 /* L2 size 256KB */
+#define L2CR_L2SIZ_512KB 0x20000000 /* L2 size 512KB */
+#define L2CR_L2SIZ_1MB 0x30000000 /* L2 size 1MB */
+#define L2CR_L2CLK_MASK 0x0e000000 /* L2 clock mask */
+#define L2CR_L2CLK_DISABLED 0x00000000 /* L2 clock disabled */
+#define L2CR_L2CLK_DIV1 0x02000000 /* L2 clock / 1 */
+#define L2CR_L2CLK_DIV1_5 0x04000000 /* L2 clock / 1.5 */
+#define L2CR_L2CLK_DIV2 0x08000000 /* L2 clock / 2 */
+#define L2CR_L2CLK_DIV2_5 0x0a000000 /* L2 clock / 2.5 */
+#define L2CR_L2CLK_DIV3 0x0c000000 /* L2 clock / 3 */
+#define L2CR_L2RAM_MASK 0x01800000 /* L2 RAM type mask */
+#define L2CR_L2RAM_FLOW 0x00000000 /* L2 RAM flow through */
+#define L2CR_L2RAM_PIPE 0x01000000 /* L2 RAM pipelined */
+#define L2CR_L2RAM_PIPE_LW 0x01800000 /* L2 RAM pipelined latewr */
+#define L2CR_L2DO 0x00400000 /* L2 data only */
+#define L2CR_L2I 0x00200000 /* L2 global invalidate */
+#define L2CR_L2CTL 0x00100000 /* L2 RAM control */
+#define L2CR_L2WT 0x00080000 /* L2 write-through */
+#define L2CR_L2TS 0x00040000 /* L2 test support */
+#define L2CR_L2OH_MASK 0x00030000 /* L2 output hold mask */
+#define L2CR_L2OH_0_5 0x00000000 /* L2 output hold 0.5 ns */
+#define L2CR_L2OH_1_0 0x00010000 /* L2 output hold 1.0 ns */
+#define L2CR_L2SL 0x00008000 /* L2 DLL slow */
+#define L2CR_L2DF 0x00004000 /* L2 differential clock */
+#define L2CR_L2BYP 0x00002000 /* L2 DLL bypass */
+#define L2CR_L2IP 0x00000001 /* L2 GI in progress */
+#define SPRN_L3CR 0x3FA /* Level 3 Cache Control Regsiter */
+#define L3CR_L3E 0x80000000 /* L3 enable */
+#define L3CR_L3PE 0x40000000 /* L3 data parity enable */
+#define L3CR_L3APE 0x20000000 /* L3 addr parity enable */
+#define L3CR_L3SIZ 0x10000000 /* L3 size */
+#define L3CR_L3CLKEN 0x08000000 /* L3 clock enable */
+#define L3CR_L3RES 0x04000000 /* L3 special reserved bit */
+#define L3CR_L3CLKDIV 0x03800000 /* L3 clock divisor */
+#define L3CR_L3IO 0x00400000 /* L3 instruction only */
+#define L3CR_L3SPO 0x00040000 /* L3 sample point override */
+#define L3CR_L3CKSP 0x00030000 /* L3 clock sample point */
+#define L3CR_L3PSP 0x0000e000 /* L3 P-clock sample point */
+#define L3CR_L3REP 0x00001000 /* L3 replacement algorithm */
+#define L3CR_L3HWF 0x00000800 /* L3 hardware flush */
+#define L3CR_L3I 0x00000400 /* L3 global invalidate */
+#define L3CR_L3RT 0x00000300 /* L3 SRAM type */
+#define L3CR_L3NIRCA 0x00000080 /* L3 non-integer ratio clock adj. */
+#define L3CR_L3DO 0x00000040 /* L3 data only mode */
+#define L3CR_PMEN 0x00000004 /* L3 private memory enable */
+#define L3CR_PMSIZ 0x00000001 /* L3 private memory size */
+#define SPRN_MSSCR0 0x3f6 /* Memory Subsystem Control Register 0 */
+#define SPRN_MSSSR0 0x3f7 /* Memory Subsystem Status Register 1 */
+#define SPRN_LDSTCR 0x3f8 /* Load/Store control register */
+#define SPRN_LDSTDB 0x3f4 /* */
+#define SPRN_LR 0x008 /* Link Register */
+#define SPRN_MMCR0 0x3B8 /* Monitor Mode Control Register 0 */
+#define SPRN_MMCR1 0x3BC /* Monitor Mode Control Register 1 */
+#ifndef SPRN_PIR
+#define SPRN_PIR 0x3FF /* Processor Identification Register */
+#endif
+#define SPRN_PMC1 0x3B9 /* Performance Counter Register 1 */
+#define SPRN_PMC2 0x3BA /* Performance Counter Register 2 */
+#define SPRN_PMC3 0x3BD /* Performance Counter Register 3 */
+#define SPRN_PMC4 0x3BE /* Performance Counter Register 4 */
+#define SPRN_PTEHI 0x3D5 /* 981 7450 PTE HI word (S/W TLB load) */
+#define SPRN_PTELO 0x3D6 /* 982 7450 PTE LO word (S/W TLB load) */
+#define SPRN_PVR 0x11F /* Processor Version Register */
+#define SPRN_RPA 0x3D6 /* Required Physical Address Register */
+#define SPRN_SDA 0x3BF /* Sampled Data Address Register */
+#define SPRN_SDR1 0x019 /* MMU Hash Base Register */
+#define SPRN_SIA 0x3BB /* Sampled Instruction Address Register */
+#define SPRN_SPRG0 0x110 /* Special Purpose Register General 0 */
+#define SPRN_SPRG1 0x111 /* Special Purpose Register General 1 */
+#define SPRN_SPRG2 0x112 /* Special Purpose Register General 2 */
+#define SPRN_SPRG3 0x113 /* Special Purpose Register General 3 */
+#define SPRN_SPRG4 0x114 /* Special Purpose Register General 4 */
+#define SPRN_SPRG5 0x115 /* Special Purpose Register General 5 */
+#define SPRN_SPRG6 0x116 /* Special Purpose Register General 6 */
+#define SPRN_SPRG7 0x117 /* Special Purpose Register General 7 */
+#define SPRN_SRR0 0x01A /* Save/Restore Register 0 */
+#define SPRN_SRR1 0x01B /* Save/Restore Register 1 */
+#define SPRN_THRM1 0x3FC /* Thermal Management Register 1 */
+/* these bits were defined in inverted endian sense originally, ugh, confusing */
+#define THRM1_TIN (1 << 31)
+#define THRM1_TIV (1 << 30)
+#define THRM1_THRES(x) ((x&0x7f)<<23)
+#define THRM3_SITV(x) ((x&0x3fff)<<1)
+#define THRM1_TID (1<<2)
+#define THRM1_TIE (1<<1)
+#define THRM1_V (1<<0)
+#define SPRN_THRM2 0x3FD /* Thermal Management Register 2 */
+#define SPRN_THRM3 0x3FE /* Thermal Management Register 3 */
+#define THRM3_E (1<<0)
+#define SPRN_TLBMISS 0x3D4 /* 980 7450 TLB Miss Register */
+#define SPRN_UMMCR0 0x3A8 /* User Monitor Mode Control Register 0 */
+#define SPRN_UMMCR1 0x3AC /* User Monitor Mode Control Register 0 */
+#define SPRN_UPMC1 0x3A9 /* User Performance Counter Register 1 */
+#define SPRN_UPMC2 0x3AA /* User Performance Counter Register 2 */
+#define SPRN_UPMC3 0x3AD /* User Performance Counter Register 3 */
+#define SPRN_UPMC4 0x3AE /* User Performance Counter Register 4 */
+#define SPRN_USIA 0x3AB /* User Sampled Instruction Address Register */
+#define SPRN_VRSAVE 0x100 /* Vector Register Save Register */
+#define SPRN_XER 0x001 /* Fixed Point Exception Register */
+
+/* Bit definitions for MMCR0 and PMC1 / PMC2. */
+#define MMCR0_PMC1_CYCLES (1 << 7)
+#define MMCR0_PMC1_ICACHEMISS (5 << 7)
+#define MMCR0_PMC1_DTLB (6 << 7)
+#define MMCR0_PMC2_DCACHEMISS 0x6
+#define MMCR0_PMC2_CYCLES 0x1
+#define MMCR0_PMC2_ITLB 0x7
+#define MMCR0_PMC2_LOADMISSTIME 0x5
+
+/* Short-hand versions for a number of the above SPRNs */
+#define CTR SPRN_CTR /* Counter Register */
+#define DAR SPRN_DAR /* Data Address Register */
+#define DABR SPRN_DABR /* Data Address Breakpoint Register */
+#define DBAT0L SPRN_DBAT0L /* Data BAT 0 Lower Register */
+#define DBAT0U SPRN_DBAT0U /* Data BAT 0 Upper Register */
+#define DBAT1L SPRN_DBAT1L /* Data BAT 1 Lower Register */
+#define DBAT1U SPRN_DBAT1U /* Data BAT 1 Upper Register */
+#define DBAT2L SPRN_DBAT2L /* Data BAT 2 Lower Register */
+#define DBAT2U SPRN_DBAT2U /* Data BAT 2 Upper Register */
+#define DBAT3L SPRN_DBAT3L /* Data BAT 3 Lower Register */
+#define DBAT3U SPRN_DBAT3U /* Data BAT 3 Upper Register */
+#define DBAT4L SPRN_DBAT4L /* Data BAT 4 Lower Register */
+#define DBAT4U SPRN_DBAT4U /* Data BAT 4 Upper Register */
+#define DBAT5L SPRN_DBAT5L /* Data BAT 5 Lower Register */
+#define DBAT5U SPRN_DBAT5U /* Data BAT 5 Upper Register */
+#define DBAT6L SPRN_DBAT6L /* Data BAT 6 Lower Register */
+#define DBAT6U SPRN_DBAT6U /* Data BAT 6 Upper Register */
+#define DBAT7L SPRN_DBAT7L /* Data BAT 7 Lower Register */
+#define DBAT7U SPRN_DBAT7U /* Data BAT 7 Upper Register */
+#define DEC SPRN_DEC /* Decrement Register */
+#define DMISS SPRN_DMISS /* Data TLB Miss Register */
+#define DSISR SPRN_DSISR /* Data Storage Interrupt Status Register */
+#define EAR SPRN_EAR /* External Address Register */
+#define HASH1 SPRN_HASH1 /* Primary Hash Address Register */
+#define HASH2 SPRN_HASH2 /* Secondary Hash Address Register */
+#define HID0 SPRN_HID0 /* Hardware Implementation Register 0 */
+#define HID1 SPRN_HID1 /* Hardware Implementation Register 1 */
+#define IABR SPRN_IABR /* Instruction Address Breakpoint Register */
+#define IBAT0L SPRN_IBAT0L /* Instruction BAT 0 Lower Register */
+#define IBAT0U SPRN_IBAT0U /* Instruction BAT 0 Upper Register */
+#define IBAT1L SPRN_IBAT1L /* Instruction BAT 1 Lower Register */
+#define IBAT1U SPRN_IBAT1U /* Instruction BAT 1 Upper Register */
+#define IBAT2L SPRN_IBAT2L /* Instruction BAT 2 Lower Register */
+#define IBAT2U SPRN_IBAT2U /* Instruction BAT 2 Upper Register */
+#define IBAT3L SPRN_IBAT3L /* Instruction BAT 3 Lower Register */
+#define IBAT3U SPRN_IBAT3U /* Instruction BAT 3 Upper Register */
+#define IBAT4L SPRN_IBAT4L /* Instruction BAT 4 Lower Register */
+#define IBAT4U SPRN_IBAT4U /* Instruction BAT 4 Upper Register */
+#define IBAT5L SPRN_IBAT5L /* Instruction BAT 5 Lower Register */
+#define IBAT5U SPRN_IBAT5U /* Instruction BAT 5 Upper Register */
+#define IBAT6L SPRN_IBAT6L /* Instruction BAT 6 Lower Register */
+#define IBAT6U SPRN_IBAT6U /* Instruction BAT 6 Upper Register */
+#define IBAT7L SPRN_IBAT7L /* Instruction BAT 7 Lower Register */
+#define IBAT7U SPRN_IBAT7U /* Instruction BAT 7 Upper Register */
+#define ICMP SPRN_ICMP /* Instruction TLB Compare Register */
+#define IMISS SPRN_IMISS /* Instruction TLB Miss Register */
+#define IMMR SPRN_IMMR /* PPC 860/821 Internal Memory Map Register */
+#define L2CR SPRN_L2CR /* Classic PPC L2 cache control register */
+#define L3CR SPRN_L3CR /* PPC 745x L3 cache control register */
+#define LR SPRN_LR
+#define PVR SPRN_PVR /* Processor Version */
+#define RPA SPRN_RPA /* Required Physical Address Register */
+#define SDR1 SPRN_SDR1 /* MMU hash base register */
+#define SPR0 SPRN_SPRG0 /* Supervisor Private Registers */
+#define SPR1 SPRN_SPRG1
+#define SPR2 SPRN_SPRG2
+#define SPR3 SPRN_SPRG3
+#define SPR4 SPRN_SPRG4
+#define SPR5 SPRN_SPRG5
+#define SPR6 SPRN_SPRG6
+#define SPR7 SPRN_SPRG7
+#define SPRG0 SPRN_SPRG0
+#define SPRG1 SPRN_SPRG1
+#define SPRG2 SPRN_SPRG2
+#define SPRG3 SPRN_SPRG3
+#define SPRG4 SPRN_SPRG4
+#define SPRG5 SPRN_SPRG5
+#define SPRG6 SPRN_SPRG6
+#define SPRG7 SPRN_SPRG7
+#define SRR0 SPRN_SRR0 /* Save and Restore Register 0 */
+#define SRR1 SPRN_SRR1 /* Save and Restore Register 1 */
+#define SRR2 SPRN_SRR2 /* Save and Restore Register 2 */
+#define SRR3 SPRN_SRR3 /* Save and Restore Register 3 */
+#define ICTC SPRN_ICTC /* Instruction Cache Throttling Control Reg */
+#define THRM1 SPRN_THRM1 /* Thermal Management Register 1 */
+#define THRM2 SPRN_THRM2 /* Thermal Management Register 2 */
+#define THRM3 SPRN_THRM3 /* Thermal Management Register 3 */
+#define XER SPRN_XER
+#define TBRL SPRN_TBRL /* Time Base Read Lower Register */
+#define TBRU SPRN_TBRU /* Time Base Read Upper Register */
+#define TBWL SPRN_TBWL /* Time Base Write Lower Register */
+#define TBWU SPRN_TBWU /* Time Base Write Upper Register */
+
+/* Processor Version Register */
+
+/* Processor Version Register (PVR) field extraction */
+
+#define PVR_VER(pvr) (((pvr) >> 16) & 0xFFFF) /* Version field */
+#define PVR_REV(pvr) (((pvr) >> 0) & 0xFFFF) /* Revison field */
+
+/*
+ * IBM has further subdivided the standard PowerPC 16-bit version and
+ * revision subfields of the PVR for the PowerPC 403s into the following:
+ */
+
+#define PVR_FAM(pvr) (((pvr) >> 20) & 0xFFF) /* Family field */
+#define PVR_MEM(pvr) (((pvr) >> 16) & 0xF) /* Member field */
+#define PVR_CORE(pvr) (((pvr) >> 12) & 0xF) /* Core field */
+#define PVR_CFG(pvr) (((pvr) >> 8) & 0xF) /* Configuration field */
+#define PVR_MAJ(pvr) (((pvr) >> 4) & 0xF) /* Major revision field */
+#define PVR_MIN(pvr) (((pvr) >> 0) & 0xF) /* Minor revision field */
+
+/* Processor Version Numbers */
+
+#define PVR_403GA 0x00200000
+#define PVR_403GB 0x00200100
+#define PVR_403GC 0x00200200
+#define PVR_403GCX 0x00201400
+#define PVR_405GP 0x40110000
+#define PVR_STB03XXX 0x40310000
+#define PVR_NP405H 0x41410000
+#define PVR_NP405L 0x41610000
+#define PVR_440GP_RB 0x40120440
+#define PVR_440GP_RC1 0x40120481
+#define PVR_440GP_RC2 0x40200481
+#define PVR_440GX_RA 0x51b21850
+#define PVR_440GX_RB 0x51b21851
+#define PVR_440GX_RB1 0x51b21852
+#define PVR_601 0x00010000
+#define PVR_602 0x00050000
+#define PVR_603 0x00030000
+#define PVR_603e 0x00060000
+#define PVR_603ev 0x00070000
+#define PVR_603r 0x00071000
+#define PVR_604 0x00040000
+#define PVR_604e 0x00090000
+#define PVR_604r 0x000A0000
+#define PVR_620 0x00140000
+#define PVR_740 0x00080000
+#define PVR_750 PVR_740
+#define PVR_740P 0x10080000
+#define PVR_750P PVR_740P
+#define PVR_7400 0x000C0000
+#define PVR_7410 0x800C0000
+#define PVR_7450 0x80000000
+/*
+ * For the 8xx processors, all of them report the same PVR family for
+ * the PowerPC core. The various versions of these processors must be
+ * differentiated by the version number in the Communication Processor
+ * Module (CPM).
+ */
+#define PVR_821 0x00500000
+#define PVR_823 PVR_821
+#define PVR_850 PVR_821
+#define PVR_860 PVR_821
+#define PVR_8240 0x00810100
+#define PVR_8245 0x80811014
+#define PVR_8260 PVR_8240
+
+/* Segment Registers */
+#define SR0 0
+#define SR1 1
+#define SR2 2
+#define SR3 3
+#define SR4 4
+#define SR5 5
+#define SR6 6
+#define SR7 7
+#define SR8 8
+#define SR9 9
+#define SR10 10
+#define SR11 11
+#define SR12 12
+#define SR13 13
+#define SR14 14
+#define SR15 15
+
+
+/* returns r3 = relocated address of sym */
+/* modifies r0 */
+#define RELOC_SYM(sym) \
+ mflr r3; \
+ bl 1f; \
+1: mflr r0; \
+ mtlr r3; \
+ lis r3, 1b@ha; \
+ ori r3, r3, 1b@l; \
+ subf r0, r3, r0; \
+ lis r3, sym@ha; \
+ ori r3, r3, sym@l; \
+ add r3, r3, r0
+
diff --git a/kexec/arch/ppc64/Makefile b/kexec/arch/ppc64/Makefile
new file mode 100644
index 0000000..66d1140
--- /dev/null
+++ b/kexec/arch/ppc64/Makefile
@@ -0,0 +1,7 @@
+#
+# kexec ppc64 (linux booting linux)
+#
+KEXEC_C_SRCS+= kexec/arch/ppc64/kexec-elf-rel-ppc64.c
+KEXEC_C_SRCS+= kexec/arch/ppc64/kexec-zImage-ppc64.c
+
+KEXEC_S_SRCS+=
diff --git a/kexec/arch/ppc64/include/arch/options.h b/kexec/arch/ppc64/include/arch/options.h
new file mode 100644
index 0000000..3fb04a7
--- /dev/null
+++ b/kexec/arch/ppc64/include/arch/options.h
@@ -0,0 +1,11 @@
+#ifndef KEXEC_ARCH_PPC64_OPTIONS_H
+#define KEXEC_ARCH_PPC64_OPTIONS_H
+
+#define OPT_ARCH_MAX (OPT_MAX+0)
+
+#define KEXEC_ARCH_OPTIONS \
+ KEXEC_OPTIONS \
+
+#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR ""
+
+#endif /* KEXEC_ARCH_PPC64_OPTIONS_H */
diff --git a/kexec/arch/ppc64/kexec-elf-ppc64.c b/kexec/arch/ppc64/kexec-elf-ppc64.c
new file mode 100644
index 0000000..16f3299
--- /dev/null
+++ b/kexec/arch/ppc64/kexec-elf-ppc64.c
@@ -0,0 +1,123 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2004 Adam Litke (agl@us.ibm.com)
+ * Copyright (C) 2004 IBM Corp.
+ *
+ * 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 (version 2 of the License).
+ *
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <linux/elf.h>
+#include "../../kexec.h"
+#include "../../kexec-elf.h"
+#include "kexec-ppc64.h"
+
+#define BOOTLOADER "kexec"
+#define BOOTLOADER_VERSION VERSION
+#define MAX_COMMAND_LINE 256
+
+#define UPSZ(X) ((sizeof(X) + 3) & ~3)
+static struct boot_notes {
+ Elf_Bhdr hdr;
+ Elf_Nhdr bl_hdr;
+ unsigned char bl_desc[UPSZ(BOOTLOADER)];
+ Elf_Nhdr blv_hdr;
+ unsigned char blv_desc[UPSZ(BOOTLOADER_VERSION)];
+ Elf_Nhdr cmd_hdr;
+ unsigned char command_line[0];
+} elf_boot_notes = {
+ .hdr = {
+ .b_signature = 0x0E1FB007,
+ .b_size = sizeof(elf_boot_notes),
+ .b_checksum = 0,
+ .b_records = 3,
+ },
+ .bl_hdr = {
+ .n_namesz = 0,
+ .n_descsz = sizeof(BOOTLOADER),
+ .n_type = EBN_BOOTLOADER_NAME,
+ },
+ .bl_desc = BOOTLOADER,
+ .blv_hdr = {
+ .n_namesz = 0,
+ .n_descsz = sizeof(BOOTLOADER_VERSION),
+ .n_type = EBN_BOOTLOADER_VERSION,
+ },
+ .blv_desc = BOOTLOADER_VERSION,
+ .cmd_hdr = {
+ .n_namesz = 0,
+ .n_descsz = 0,
+ .n_type = EBN_COMMAND_LINE,
+ },
+};
+
+int elf_ppc64_probe(const char *buf, off_t len)
+{
+ struct mem_ehdr ehdr;
+ int result;
+ result = build_elf_exec_info(buf, len, &ehdr);
+ if (result < 0) {
+ goto out;
+ }
+
+ /* Verify the architecuture specific bits */
+ if ((ehdr.e_machine != EM_PPC64) && (ehdr.e_machine != EM_PPC)) {
+ /* for a different architecture */
+ result = -1;
+ goto out;
+ }
+ result = 0;
+ out:
+ free_elf_info(&ehdr);
+ return result;
+}
+
+int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info)
+{
+ struct mem_ehdr ehdr;
+
+ /* Parse command line arguments */
+
+ /* Parse the Elf file */
+ result = build_elf_exec_info(buf, len, &ehdr);
+ if (result < 0) {
+ free_elf_info(&ehdr);
+ return result;
+ }
+
+ /* Load the Elf data */
+ result = elf_exec_load(&ehdr, info);
+ if (result < 0) {
+ free_elf_info(&ehdr);
+ return result;
+ }
+ return 1;
+}
+
+void elf_ppc64_usage(void)
+{
+ fprintf(stderr, "elf support is still broken\n");
+}
diff --git a/kexec/arch/ppc64/kexec-elf-rel-ppc64.c b/kexec/arch/ppc64/kexec-elf-rel-ppc64.c
new file mode 100644
index 0000000..e2e82f4
--- /dev/null
+++ b/kexec/arch/ppc64/kexec-elf-rel-ppc64.c
@@ -0,0 +1,95 @@
+#include <stdio.h>
+#include <elf.h>
+#include "../../kexec.h"
+#include "../../kexec-elf.h"
+
+int machine_verify_elf_rel(struct mem_ehdr *ehdr)
+{
+ if (ehdr->ei_data != ELFDATA2MSB) {
+ return 0;
+ }
+ if (ehdr->ei_class != ELFCLASS64) {
+ return 0;
+ }
+ if (ehdr->e_machine != EM_PPC64) {
+ return 0;
+ }
+ return 1;
+}
+
+static struct mem_shdr *toc_section(const struct mem_ehdr *ehdr)
+{
+ struct mem_shdr *shdr, *shdr_end;
+ unsigned char *strtab;
+ strtab = ehdr->e_shdr[ehdr->e_shstrndx].sh_data;
+ shdr_end = &ehdr->e_shdr[ehdr->shnum];
+ for(shdr = ehdr->e_shdr; shdr != shdr_end; shdr++) {
+ if (strcmp(shdr->sh_name, ".toc") == 0) {
+ return shdr;
+ }
+ }
+ return NULL;
+}
+
+/* r2 is the TOC pointer: it actually points 0x8000 into the TOC (this
+ gives the value maximum span in an instruction which uses a signed
+ offset) */
+static unsigned long my_r2(const struct mem_ehdr *ehdr)
+{
+ struct mem_shdr *shdr;
+ shdr = toc_section(ehdr);
+ if (!shdr) {
+ die("TOC reloc without a toc section?");
+ }
+ return shdr->sh_addr + 0x8000;
+}
+
+
+void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type,
+ void *location, unsigned long address, unsigned long value)
+{
+ switch(r_type) {
+ case R_PPC64_ADDR32:
+ /* Simply set it */
+ *(uint32_t *)location = value;
+ break;
+
+ case R_PPC64_ADDR64:
+ /* Simply set it */
+ *(uint64_t *)location = value;
+ break;
+
+ case R_PPC64_TOC:
+ *(uint64_t *)location = my_r2(ehdr);
+ break;
+
+ case R_PPC64_TOC16_DS:
+ /* Subtact TOC pointer */
+ value -= my_r2(ehdr);
+ if ((value & 3) != 0 || value + 0x8000 > 0xffff) {
+ die("bad TOC16_DS relocation (%lu)\n", value);
+ }
+ *((uint16_t *) location)
+ = (*((uint16_t *) location) & ~0xfffc)
+ | (value & 0xfffc);
+ break;
+
+ case R_PPC64_REL24:
+ /* Convert value to relative */
+ value -= address;
+ if (value + 0x2000000 > 0x3ffffff || (value & 3) != 0){
+ die("REL24 %li out of range!\n",
+ (long int)value);
+ }
+
+ /* Only replace bits 2 through 26 */
+ *(uint32_t *)location
+ = (*(uint32_t *)location & ~0x03fffffc)
+ | (value & 0x03fffffc);
+ break;
+ default:
+ die("Unknown rela relocation: %lu\n", r_type);
+ break;
+ }
+ return;
+}
diff --git a/kexec/arch/ppc64/kexec-ppc64.h b/kexec/arch/ppc64/kexec-ppc64.h
new file mode 100644
index 0000000..73555cf
--- /dev/null
+++ b/kexec/arch/ppc64/kexec-ppc64.h
@@ -0,0 +1,9 @@
+#ifndef KEXEC_PPC64_H
+#define KEXEC_PPC64_H
+
+int elf_ppc64_probe(const char *buf, off_t len);
+int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info);
+void elf_ppc64_usage(void);
+
+#endif /* KEXEC_PPC_H */
diff --git a/kexec/arch/ppc64/kexec-zImage-ppc64.c b/kexec/arch/ppc64/kexec-zImage-ppc64.c
new file mode 100644
index 0000000..2b5e00f
--- /dev/null
+++ b/kexec/arch/ppc64/kexec-zImage-ppc64.c
@@ -0,0 +1,173 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2004 Adam Litke (agl@us.ibm.com)
+ * Copyright (C) 2004 IBM Corp.
+ *
+ * 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 (version 2 of the License).
+ *
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <linux/elf.h>
+#include "../../kexec.h"
+
+#define MAX_HEADERS 32
+
+int zImage_ppc64_probe(FILE *file)
+{
+ Elf32_Ehdr elf;
+
+ if (fseek(file, 0, SEEK_SET) < 0) {
+ fprintf(stderr, "seek error: %s\n",
+ strerror(errno));
+ return -1;
+ }
+ if (fread(&elf, sizeof(Elf32_Ehdr), 1, file) != 1) {
+ fprintf(stderr, "read error: %s\n",
+ strerror(errno));
+ return -1;
+ }
+
+ if (elf.e_machine == EM_PPC64) {
+ fprintf(stderr, "Elf64 not supported\n");
+ return -1;
+ }
+
+ return (elf.e_ident[EI_MAG0] == ELFMAG0 &&
+ elf.e_ident[EI_MAG1] == ELFMAG1 &&
+ elf.e_ident[EI_MAG2] == ELFMAG2 &&
+ elf.e_ident[EI_MAG3] == ELFMAG3 &&
+ elf.e_ident[EI_CLASS] == ELFCLASS32 &&
+ elf.e_ident[EI_DATA] == ELFDATA2MSB &&
+ elf.e_type == ET_EXEC &&
+ elf.e_machine == EM_PPC);
+}
+
+int zImage_ppc64_load(FILE *file, int argc, char **argv, void **ret_entry,
+ struct kexec_segment **ret_segments, int *ret_nr_segments)
+{
+ Elf32_Ehdr elf;
+ Elf32_Phdr *p, *ph;
+ struct kexec_segment *segment;
+ int i;
+ unsigned long memsize, filesize, offset, load_loc;
+
+ /* Parse command line arguments */
+
+ /* Read in the Elf32 header */
+ if (fseek(file, 0, SEEK_SET) < 0) {
+ perror("seek error:");
+ return -1;
+ }
+ if (fread(&elf, sizeof(Elf32_Ehdr), 1, file) != 1) {
+ perror("read error: ");
+ return -1;
+ }
+ if (elf.e_phnum > MAX_HEADERS) {
+ fprintf(stderr,
+ "Only kernels with %i program headers are supported\n",
+ MAX_HEADERS);
+ return -1;
+ }
+
+ /* Read the section header */
+ ph = (Elf32_Phdr *)malloc(sizeof(Elf32_Phdr) * elf.e_phnum);
+ if (ph == 0) {
+ perror("malloc failed: ");
+ return -1;
+ }
+ if (fseek(file, elf.e_phoff, SEEK_SET) < 0) {
+ perror("seek failed: ");
+ return -1;
+ }
+ if (fread(ph, sizeof(Elf32_Phdr) * elf.e_phnum, 1, file) != 1) {
+ perror("read error: ");
+ return -1;
+ }
+
+ *ret_segments = malloc(elf.e_phnum * sizeof(struct kexec_segment));
+ if (*ret_segments == 0) {
+ fprintf(stderr, "malloc failed: %s\n",
+ strerror(errno));
+ return -1;
+ }
+ segment = ret_segments[0];
+
+ /* Scan through the program header */
+ memsize = filesize = offset = 0;
+ p = ph;
+ for (i = 0; i < elf.e_phnum; ++i, ++p) {
+ if (p->p_type != PT_LOAD || p->p_offset == 0)
+ continue;
+ if (memsize == 0) {
+ offset = p->p_offset;
+ memsize = p->p_memsz;
+ filesize = p->p_filesz;
+ load_loc = p->p_vaddr;
+ } else {
+ memsize = p->p_offset + p->p_memsz - offset;
+ filesize = p->p_offset + p->p_filesz - offset;
+ }
+ }
+ if (memsize == 0) {
+ fprintf(stderr, "Can't find a loadable segment.\n");
+ return -1;
+ }
+
+ /* Load program segments */
+ p = ph;
+ segment->buf = malloc(filesize);
+ if (segment->buf == 0) {
+ perror("malloc failed: ");
+ return -1;
+ }
+ for (i = 0; i < elf.e_phnum; ++i, ++p) {
+ unsigned long mem_offset;
+ if (p->p_type != PT_LOAD || p->p_offset == 0)
+ continue;
+
+ /* skip to the actual image */
+ if (fseek(file, p->p_offset, SEEK_SET) < 0) {
+ perror("seek error: ");
+ return -1;
+ }
+ mem_offset = p->p_vaddr - load_loc;
+ if (fread(segment->buf+mem_offset, p->p_filesz, 1, file) != 1) {
+ perror("read error: ");
+ return -1;
+ }
+ }
+ segment->mem = (void *) load_loc;
+ segment->memsz = memsize;
+ segment->bufsz = filesize;
+ *ret_entry = elf.e_entry;
+ *ret_nr_segments = i - 1;
+ free(ph);
+ return 0;
+}
+
+void zImage_ppc64_usage(void)
+{
+ fprintf(stderr, "zImage support is still broken\n");
+}
diff --git a/kexec/arch/x86_64/Makefile b/kexec/arch/x86_64/Makefile
new file mode 100644
index 0000000..366e792
--- /dev/null
+++ b/kexec/arch/x86_64/Makefile
@@ -0,0 +1,12 @@
+#
+# kexec x86_64 (linux booting linux)
+#
+KEXEC_C_SRCS+= kexec/arch/i386/kexec-elf-x86.c
+KEXEC_C_SRCS+= kexec/arch/i386/kexec-bzImage.c
+KEXEC_C_SRCS+= kexec/arch/i386/kexec-multiboot-x86.c
+KEXEC_C_SRCS+= kexec/arch/i386/kexec-beoboot-x86.c
+KEXEC_C_SRCS+= kexec/arch/i386/kexec-nbi.c
+KEXEC_C_SRCS+= kexec/arch/i386/x86-linux-setup.c
+KEXEC_C_SRCS+= kexec/arch/x86_64/kexec-x86_64.c
+KEXEC_C_SRCS+= kexec/arch/x86_64/kexec-elf-x86_64.c
+KEXEC_C_SRCS+= kexec/arch/x86_64/kexec-elf-rel-x86_64.c
diff --git a/kexec/arch/x86_64/include/arch/options.h b/kexec/arch/x86_64/include/arch/options.h
new file mode 100644
index 0000000..75065b9
--- /dev/null
+++ b/kexec/arch/x86_64/include/arch/options.h
@@ -0,0 +1,22 @@
+#ifndef KEXEC_ARCH_X86_64_OPTIONS_H
+#define KEXEC_ARCH_X86_64_OPTIONS_H
+
+#define OPT_RESET_VGA (OPT_MAX+0)
+#define OPT_SERIAL (OPT_MAX+1)
+#define OPT_SERIAL_BAUD (OPT_MAX+2)
+#define OPT_CONSOLE_VGA (OPT_MAX+3)
+#define OPT_CONSOLE_SERIAL (OPT_MAX+4)
+#define OPT_ARCH_MAX (OPT_MAX+5)
+
+#define KEXEC_ARCH_OPTIONS \
+ KEXEC_OPTIONS \
+ { "reset-vga", 0, 0, OPT_RESET_VGA }, \
+ { "serial", 1, 0, OPT_SERIAL }, \
+ { "serial-baud", 1, 0, OPT_SERIAL_BAUD }, \
+ { "console-vga", 0, 0, OPT_CONSOLE_VGA }, \
+ { "console-serial", 0, 0, OPT_CONSOLE_SERIAL }, \
+
+#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR ""
+
+#endif /* KEXEC_ARCH_X86_64_OPTIONS_H */
+
diff --git a/kexec/arch/x86_64/kexec-elf-rel-x86_64.c b/kexec/arch/x86_64/kexec-elf-rel-x86_64.c
new file mode 100644
index 0000000..afcb171
--- /dev/null
+++ b/kexec/arch/x86_64/kexec-elf-rel-x86_64.c
@@ -0,0 +1,93 @@
+#include <stdio.h>
+#include <elf.h>
+#include "../../kexec.h"
+#include "../../kexec-elf.h"
+
+int machine_verify_elf_rel(struct mem_ehdr *ehdr)
+{
+ if (ehdr->ei_data != ELFDATA2LSB) {
+ return 0;
+ }
+ if (ehdr->ei_class != ELFCLASS64) {
+ return 0;
+ }
+ if (ehdr->e_machine != EM_X86_64) {
+ return 0;
+ }
+ return 1;
+}
+
+static const char *reloc_name(unsigned long r_type)
+{
+ static const char *r_name[] = {
+ "R_X86_64_NONE",
+ "R_X86_64_64",
+ "R_X86_64_PC32",
+ "R_X86_64_GOT32",
+ "R_X86_64_PLT32",
+ "R_X86_64_COPY",
+ "R_X86_64_GLOB_DAT",
+ "R_X86_64_JUMP_SLOT",
+ "R_X86_64_RELATIVE",
+ "R_X86_64_GOTPCREL",
+ "R_X86_64_32",
+ "R_X86_64_32S",
+ "R_X86_64_16",
+ "R_X86_64_PC16",
+ "R_X86_64_8",
+ "R_X86_64_PC8",
+ "R_X86_64_DTPMOD64",
+ "R_X86_64_DTPOFF64",
+ "R_X86_64_TPOFF64",
+ "R_X86_64_TLSGD",
+ "R_X86_64_TLSLD",
+ "R_X86_64_DTPOFF32",
+ "R_X86_64_GOTTPOFF",
+ "R_X86_64_TPOFF32",
+ };
+ static char buf[100];
+ const char *name;
+ if (r_type < (sizeof(reloc_name)/sizeof(r_name[0]))){
+ name = r_name[r_type];
+ }
+ else {
+ sprintf(buf, "R_X86_64_%lu", r_type);
+ name = buf;
+ }
+ return name;
+}
+
+void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type,
+ void *location, unsigned long address, unsigned long value)
+{
+#if 0
+ fprintf(stderr, "%s\n", reloc_name(r_type));
+#endif
+ switch(r_type) {
+ case R_X86_64_NONE:
+ break;
+ case R_X86_64_64:
+ *(uint64_t *)location = value;
+ break;
+ case R_X86_64_32:
+ *(uint32_t *)location = value;
+ if (value != *(uint32_t *)location)
+ goto overflow;
+ break;
+ case R_X86_64_32S:
+ *(uint32_t *)location = value;
+ if ((int64_t)value != *(int32_t *)location)
+ goto overflow;
+ break;
+ case R_X86_64_PC32:
+ *(uint32_t *)location = value - address;
+ break;
+ default:
+ die("Unhandled rela relocation: %lu\n", reloc_name(r_type));
+ break;
+ }
+ return;
+ overflow:
+ die("overflow in relocation type %s val %Lx\n",
+ reloc_name(r_type), value);
+}
diff --git a/kexec/arch/x86_64/kexec-elf-x86_64.c b/kexec/arch/x86_64/kexec-elf-x86_64.c
new file mode 100644
index 0000000..88f78c9
--- /dev/null
+++ b/kexec/arch/x86_64/kexec-elf-x86_64.c
@@ -0,0 +1,239 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2003-2005 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <elf.h>
+#include <x86/x86-linux.h>
+#include "../../kexec.h"
+#include "../../kexec-elf.h"
+#include "../../kexec-elf-boot.h"
+#include "../i386/x86-linux-setup.h"
+#include "kexec-x86_64.h"
+#include <arch/options.h>
+
+static const int probe_debug = 0;
+
+int elf_x86_64_probe(const char *buf, off_t len)
+{
+
+ struct mem_ehdr ehdr;
+ int result;
+ result = build_elf_exec_info(buf, len, &ehdr);
+ if (result < 0) {
+ if (probe_debug) {
+ fprintf(stderr, "Not an ELF executable\n");
+ }
+ goto out;
+ }
+
+ /* Verify the architecuture specific bits */
+ if (ehdr.e_machine != EM_X86_64) {
+ /* for a different architecture */
+ if (probe_debug) {
+ fprintf(stderr, "Not x86_64 ELF executable\n");
+ }
+ result = -1;
+ goto out;
+ }
+ result = 0;
+ out:
+ free_elf_info(&ehdr);
+ return result;
+}
+
+void elf_x86_64_usage(void)
+{
+ printf( " --command-line=STRING Set the kernel command line to STRING\n"
+ " --append=STRING Set the kernel command line to STRING\n"
+ " --initrd=FILE Use FILE as the kernel's initial ramdisk.\n"
+ " --ramdisk=FILE Use FILE as the kernel's initial ramdisk.\n"
+ " --args-linux Pass linux kernel style options\n"
+ " --args-elf Pass elf boot notes\n"
+ " --args-none Jump directly from the kernel\n"
+ );
+}
+
+int elf_x86_64_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info)
+{
+ struct mem_ehdr ehdr;
+ const char *command_line;
+ int command_line_len;
+ const char *ramdisk;
+ unsigned long entry, max_addr;
+ int arg_style;
+#define ARG_STYLE_ELF 0
+#define ARG_STYLE_LINUX 1
+#define ARG_STYLE_NONE 2
+ int opt;
+#define OPT_APPEND (OPT_ARCH_MAX+0)
+#define OPT_RAMDISK (OPT_ARCH_MAX+1)
+#define OPT_ARGS_ELF (OPT_ARCH_MAX+2)
+#define OPT_ARGS_LINUX (OPT_ARCH_MAX+3)
+#define OPT_ARGS_NONE (OPT_ARCH_MAX+4)
+
+ static const struct option options[] = {
+ KEXEC_ARCH_OPTIONS
+ { "command-line", 1, NULL, OPT_APPEND },
+ { "append", 1, NULL, OPT_APPEND },
+ { "initrd", 1, NULL, OPT_RAMDISK },
+ { "ramdisk", 1, NULL, OPT_RAMDISK },
+ { "args-elf", 0, NULL, OPT_ARGS_ELF },
+ { "args-linux", 0, NULL, OPT_ARGS_LINUX },
+ { "args-none", 0, NULL, OPT_ARGS_NONE },
+ { 0, 0, NULL, 0 },
+ };
+
+ static const char short_options[] = KEXEC_ARCH_OPT_STR "";
+
+ /*
+ * Parse the command line arguments
+ */
+ arg_style = ARG_STYLE_ELF;
+ command_line = 0;
+ ramdisk = 0;
+ while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
+ switch(opt) {
+ default:
+ /* Ignore core options */
+ if (opt < OPT_ARCH_MAX) {
+ break;
+ }
+ fprintf(stderr, "Unknown option: opt: %d\n", opt);
+ case '?':
+ usage();
+ return -1;
+ case OPT_APPEND:
+ command_line = optarg;
+ break;
+ case OPT_RAMDISK:
+ ramdisk = optarg;
+ break;
+ case OPT_ARGS_ELF:
+ arg_style = ARG_STYLE_ELF;
+ break;
+ case OPT_ARGS_LINUX:
+ arg_style = ARG_STYLE_LINUX;
+ break;
+ case OPT_ARGS_NONE:
+#ifdef __x86_64___
+ arg_style = ARG_STYLE_NONE;
+#else
+ die("--args-none only works on arch x86_64\n");
+#endif
+ break;
+ }
+ }
+ command_line_len = 0;
+ if (command_line) {
+ command_line_len = strlen(command_line) +1;
+ }
+
+ /* Load the ELF executable */
+ elf_exec_build_load(info, &ehdr, buf, len);
+
+ entry = ehdr.e_entry;
+ max_addr = elf_max_addr(&ehdr);
+
+ /* Do we want arguments? */
+ if (arg_style != ARG_STYLE_NONE) {
+ /* Load the setup code */
+ elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
+ 0, ULONG_MAX, 1);
+ }
+ if (arg_style == ARG_STYLE_NONE) {
+ info->entry = (void *)entry;
+
+ }
+ else if (arg_style == ARG_STYLE_ELF) {
+ unsigned long note_base;
+ struct entry64_regs regs;
+
+ /* Setup the ELF boot notes */
+ note_base = elf_boot_notes(info, max_addr,
+ command_line, command_line_len);
+
+ /* Initialize the registers */
+ elf_rel_get_symbol(&info->rhdr, "entry64_regs", &regs, sizeof(regs));
+ regs.rdi = note_base; /* The notes (arg1) */
+ regs.rip = entry; /* The entry point */
+ regs.rsp = elf_rel_get_addr(&info->rhdr, "stack_end"); /* Stack, unused */
+ elf_rel_set_symbol(&info->rhdr, "entry64_regs", &regs, sizeof(regs));
+
+ if (ramdisk) {
+ die("Ramdisks not supported with generic elf arguments");
+ }
+ }
+ else if (arg_style == ARG_STYLE_LINUX) {
+ struct x86_linux_faked_param_header *hdr;
+ unsigned long param_base;
+ const unsigned char *ramdisk_buf;
+ off_t ramdisk_length;
+ struct entry64_regs regs;
+
+ /* Get the linux parameter header */
+ hdr = xmalloc(sizeof(*hdr));
+ param_base = add_buffer(info, hdr, sizeof(*hdr), sizeof(*hdr),
+ 16, 0, max_addr, 1);
+
+ /* Initialize the parameter header */
+ memset(hdr, 0, sizeof(*hdr));
+ init_linux_parameters(&hdr->hdr);
+
+ /* Add a ramdisk to the current image */
+ ramdisk_buf = 0;
+ ramdisk_length = 0;
+ if (ramdisk) {
+ unsigned char *ramdisk_buf;
+ ramdisk_buf = slurp_file(ramdisk, &ramdisk_length);
+ }
+
+ /* Tell the kernel what is going on */
+ setup_linux_bootloader_parameters(info, &hdr->hdr, param_base,
+ offsetof(struct x86_linux_faked_param_header, command_line),
+ command_line, command_line_len,
+ ramdisk_buf, ramdisk_length);
+
+ /* Fill in the information bios calls would usually provide */
+ setup_linux_system_parameters(&hdr->hdr);
+
+ /* Initialize the registers */
+ elf_rel_get_symbol(&info->rhdr, "entry64_regs", &regs, sizeof(regs));
+ regs.rbx = 0; /* Bootstrap processor */
+ regs.rsi = param_base; /* Pointer to the parameters */
+ regs.rip = entry; /* the entry point */
+ regs.rsp = elf_rel_get_addr(&info->rhdr, "stack_end"); /* Stack, unused */
+ elf_rel_set_symbol(&info->rhdr, "entry64_regs", &regs, sizeof(regs));
+ }
+ else {
+ die("Unknown argument style\n");
+ }
+ return 0;
+}
diff --git a/kexec/arch/x86_64/kexec-x86_64.c b/kexec/arch/x86_64/kexec-x86_64.c
new file mode 100644
index 0000000..523b2b0
--- /dev/null
+++ b/kexec/arch/x86_64/kexec-x86_64.c
@@ -0,0 +1,247 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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 <stddef.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <sys/utsname.h>
+#include "../../kexec.h"
+#include "../../kexec-elf.h"
+#include "../../kexec-syscall.h"
+#include "kexec-x86_64.h"
+#include <arch/options.h>
+
+#define MAX_MEMORY_RANGES 64
+#define MAX_LINE 160
+static struct memory_range memory_range[MAX_MEMORY_RANGES];
+
+/* Return a sorted list of memory ranges. */
+int get_memory_ranges(struct memory_range **range, int *ranges)
+{
+ const char iomem[]= "/proc/iomem";
+ int memory_ranges = 0;
+ char line[MAX_LINE];
+ FILE *fp;
+ fp = fopen(iomem, "r");
+ if (!fp) {
+ fprintf(stderr, "Cannot open %s: %s\n",
+ iomem, strerror(errno));
+ return -1;
+ }
+ while(fgets(line, sizeof(line), fp) != 0) {
+ unsigned long long start, end;
+ char *str;
+ int type;
+ int consumed;
+ int count;
+ if (memory_ranges >= MAX_MEMORY_RANGES)
+ break;
+ count = sscanf(line, "%Lx-%Lx : %n",
+ &start, &end, &consumed);
+ if (count != 2)
+ continue;
+ str = line + consumed;
+ end = end + 1;
+#if 0
+ printf("%016Lx-%016Lx : %s",
+ start, end, str);
+#endif
+ if (memcmp(str, "System RAM\n", 11) == 0) {
+ type = RANGE_RAM;
+ }
+ else if (memcmp(str, "reserved\n", 9) == 0) {
+ type = RANGE_RESERVED;
+ }
+ else if (memcmp(str, "ACPI Tables\n", 12) == 0) {
+ type = RANGE_ACPI;
+ }
+ else if (memcmp(str, "ACPI Non-volatile Storage\n", 26) == 0) {
+ type = RANGE_ACPI_NVS;
+ }
+ else {
+ continue;
+ }
+ /* Don't report the interrupt table as ram */
+ if (type == RANGE_RAM && (start < 0x100)) {
+ start = 0x100;
+ }
+ memory_range[memory_ranges].start = start;
+ memory_range[memory_ranges].end = end;
+ memory_range[memory_ranges].type = type;
+#if 0
+ printf("%016Lx-%016Lx : %x\n",
+ start, end, type);
+#endif
+ memory_ranges++;
+ }
+ fclose(fp);
+ *range = memory_range;
+ *ranges = memory_ranges;
+ return 0;
+}
+
+struct file_type file_type[] = {
+ { "elf-x86_64", elf_x86_64_probe, elf_x86_64_load, elf_x86_64_usage },
+ { "multiboot-x86", multiboot_x86_probe, multiboot_x86_load,
+ multiboot_x86_usage },
+ { "elf-x86", elf_x86_probe, elf_x86_load, elf_x86_usage },
+ { "bzImage", bzImage_probe, bzImage_load, bzImage_usage },
+ { "beoboot-x86", beoboot_probe, beoboot_load, beoboot_usage },
+ { "nbi-x86", nbi_probe, nbi_load, nbi_usage },
+};
+int file_types = sizeof(file_type)/sizeof(file_type[0]);
+
+
+void arch_usage(void)
+{
+ printf(
+ " --reset-vga Attempt to reset a standard vga device\n"
+ " --serial=<port> Specify the serial port for debug output\n"
+ " --serial-baud=<buad_rate> Specify the serial port baud rate\n"
+ " --console-vga Enable the vga console\n"
+ " --console-serial Enable the serial console\n"
+ );
+}
+
+static struct {
+ uint8_t reset_vga;
+ uint16_t serial_base;
+ uint32_t serial_baud;
+ uint8_t console_vga;
+ uint8_t console_serial;
+} arch_options = {
+ .reset_vga = 0,
+ .serial_base = 0x3f8,
+ .serial_baud = 0,
+ .console_vga = 0,
+ .console_serial = 0,
+};
+
+int arch_process_options(int argc, char **argv)
+{
+ static const struct option options[] = {
+ KEXEC_ARCH_OPTIONS
+ { 0, 0, NULL, 0 },
+ };
+ static const char short_options[] = KEXEC_ARCH_OPT_STR;
+ int opt;
+ unsigned long value;
+ char *end;
+
+ opterr = 0; /* Don't complain about unrecognized options here */
+ while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
+ switch(opt) {
+ default:
+ break;
+ case OPT_RESET_VGA:
+ arch_options.reset_vga = 1;
+ break;
+ case OPT_CONSOLE_VGA:
+ arch_options.console_vga = 1;
+ break;
+ case OPT_CONSOLE_SERIAL:
+ arch_options.console_serial = 1;
+ break;
+ case OPT_SERIAL:
+ value = ULONG_MAX;
+ if (strcmp(optarg, "ttyS0") == 0) {
+ value = 0x3f8;
+ }
+ else if (strcmp(optarg, "ttyS1") == 0) {
+ value = 0x2f8;
+ }
+ else if (strncmp(optarg, "0x", 2) == 0) {
+ value = strtoul(optarg +2, &end, 16);
+ if (*end != '\0') {
+ value = ULONG_MAX;
+ }
+ }
+ if (value >= 65536) {
+ fprintf(stderr, "Bad serial port base '%s'\n",
+ optarg);
+ usage();
+ return -1;
+
+ }
+ arch_options.serial_base = value;
+ break;
+ case OPT_SERIAL_BAUD:
+ value = strtoul(optarg, &end, 0);
+ if ((value > 115200) || ((115200 %value) != 0) ||
+ (value < 9600) || (*end))
+ {
+ fprintf(stderr, "Bad serial port baud rate '%s'\n",
+ optarg);
+ usage();
+ return -1;
+
+ }
+ arch_options.serial_baud = value;
+ break;
+ }
+ }
+ /* Reset getopt for the next pass; called in other source modules */
+ opterr = 1;
+ optind = 1;
+ return 0;
+}
+
+int arch_compat_trampoline(struct kexec_info *info, unsigned long *flags)
+{
+ int result;
+ struct utsname utsname;
+ result = uname(&utsname);
+ if (result < 0) {
+ fprintf(stderr, "uname failed: %s\n",
+ strerror(errno));
+ return -1;
+ }
+ if (strcmp(utsname.machine, "x86_64") == 0)
+ {
+ /* For compatibility with older patches
+ * use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_X86_64 here.
+ */
+ *flags |= KEXEC_ARCH_DEFAULT;
+ }
+ else {
+ fprintf(stderr, "Unsupported machine type: %s\n",
+ utsname.machine);
+ return -1;
+ }
+ return 0;
+}
+
+void arch_update_purgatory(struct kexec_info *info)
+{
+ elf_rel_set_symbol(&info->rhdr, "reset_vga",
+ &arch_options.reset_vga, sizeof(arch_options.reset_vga));
+ elf_rel_set_symbol(&info->rhdr, "serial_base",
+ &arch_options.serial_base, sizeof(arch_options.serial_base));
+ elf_rel_set_symbol(&info->rhdr, "serial_baud",
+ &arch_options.serial_baud, sizeof(arch_options.serial_baud));
+ elf_rel_set_symbol(&info->rhdr, "console_vga",
+ &arch_options.console_vga, sizeof(arch_options.console_vga));
+ elf_rel_set_symbol(&info->rhdr, "console_serial",
+ &arch_options.console_serial, sizeof(arch_options.console_serial));
+}
diff --git a/kexec/arch/x86_64/kexec-x86_64.h b/kexec/arch/x86_64/kexec-x86_64.h
new file mode 100644
index 0000000..a97cd71
--- /dev/null
+++ b/kexec/arch/x86_64/kexec-x86_64.h
@@ -0,0 +1,31 @@
+#ifndef KEXEC_X86_64_H
+#define KEXEC_X86_64_H
+
+#include "../i386/kexec-x86.h"
+
+struct entry64_regs {
+ uint64_t rax;
+ uint64_t rbx;
+ uint64_t rcx;
+ uint64_t rdx;
+ uint64_t rsi;
+ uint64_t rdi;
+ uint64_t rsp;
+ uint64_t rbp;
+ uint64_t r8;
+ uint64_t r9;
+ uint64_t r10;
+ uint64_t r11;
+ uint64_t r12;
+ uint64_t r13;
+ uint64_t r14;
+ uint64_t r15;
+ uint64_t rip;
+};
+
+int elf_x86_64_probe(const char *buf, off_t len);
+int elf_x86_64_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info);
+void elf_x86_64_usage(void);
+
+#endif /* KEXEC_X86_64_H */
diff --git a/kexec/ifdown.c b/kexec/ifdown.c
new file mode 100644
index 0000000..d480b3b
--- /dev/null
+++ b/kexec/ifdown.c
@@ -0,0 +1,74 @@
+/*
+ * ifdown.c Find all network interfaces on the system and
+ * shut them down.
+ *
+ */
+char *v_ifdown = "@(#)ifdown.c 1.11 02-Jun-1998 miquels@cistron.nl";
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <string.h>
+
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/errno.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+
+#define MAX_IFS 64
+
+/*
+ * First, we find all shaper devices and down them. Then we
+ * down all real interfaces. This is because the comment in the
+ * shaper driver says "if you down the shaper device before the
+ * attached inerface your computer will follow".
+ */
+int ifdown(void)
+{
+ struct ifreq ifr[MAX_IFS];
+ struct ifconf ifc;
+ int i, fd;
+ int numif;
+ int shaper;
+
+ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ fprintf(stderr, "ifdown: ");
+ perror("socket");
+ return -1;
+ }
+ ifc.ifc_len = sizeof(ifr);
+ ifc.ifc_req = ifr;
+
+ if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) {
+ fprintf(stderr, "ifdown: ");
+ perror("SIOCGIFCONF");
+ close(fd);
+ return -1;
+ }
+ numif = ifc.ifc_len / sizeof(struct ifreq);
+
+ for (shaper = 1; shaper >= 0; shaper--) {
+ for (i = 0; i < numif; i++) {
+
+ if ((strncmp(ifr[i].ifr_name, "shaper", 6) == 0)
+ != shaper) continue;
+
+ if (strcmp(ifr[i].ifr_name, "lo") == 0)
+ continue;
+ if (strchr(ifr[i].ifr_name, ':') != NULL)
+ continue;
+ ifr[i].ifr_flags &= ~(IFF_UP);
+ if (ioctl(fd, SIOCSIFFLAGS, &ifr[i]) < 0) {
+ fprintf(stderr, "ifdown: shutdown ");
+ perror(ifr[i].ifr_name);
+ }
+ }
+ }
+ close(fd);
+
+ return 0;
+}
diff --git a/kexec/kexec-elf-boot.c b/kexec/kexec-elf-boot.c
new file mode 100644
index 0000000..bc650b7
--- /dev/null
+++ b/kexec/kexec-elf-boot.c
@@ -0,0 +1,95 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2003-2005 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <elf.h>
+#include <boot/elf_boot.h>
+#include <ip_checksum.h>
+#include <x86/x86-linux.h>
+#include "kexec.h"
+#include "kexec-elf.h"
+#include "kexec-elf-boot.h"
+
+
+#define UPSZ(X) ((sizeof(X) + 3) &~3)
+
+static struct boot_notes {
+ Elf_Bhdr hdr;
+ Elf_Nhdr bl_hdr;
+ unsigned char bl_desc[UPSZ(BOOTLOADER)];
+ Elf_Nhdr blv_hdr;
+ unsigned char blv_desc[UPSZ(BOOTLOADER_VERSION)];
+ Elf_Nhdr cmd_hdr;
+ unsigned char command_line[0];
+} boot_notes = {
+ .hdr = {
+ .b_signature = ELF_BOOT_MAGIC,
+ .b_size = sizeof(boot_notes),
+ .b_checksum = 0,
+ .b_records = 3,
+ },
+ .bl_hdr = {
+ .n_namesz = 0,
+ .n_descsz = sizeof(BOOTLOADER),
+ .n_type = EBN_BOOTLOADER_NAME,
+ },
+ .bl_desc = BOOTLOADER,
+ .blv_hdr = {
+ .n_namesz = 0,
+ .n_descsz = sizeof(BOOTLOADER_VERSION),
+ .n_type = EBN_BOOTLOADER_VERSION,
+ },
+ .blv_desc = BOOTLOADER_VERSION,
+ .cmd_hdr = {
+ .n_namesz = 0,
+ .n_descsz = 0,
+ .n_type = EBN_COMMAND_LINE,
+ },
+};
+
+static inline unsigned long align(unsigned long val, unsigned long align)
+{
+ return (val + align - 1) & ~(align - 1);
+
+}
+
+unsigned long elf_boot_notes(
+ struct kexec_info *info, unsigned long max_addr,
+ const unsigned char *cmdline, int cmdline_len)
+{
+ unsigned long note_bytes;
+ unsigned long note_base;
+ struct boot_notes *notes;
+ note_bytes = sizeof(*notes) + align(cmdline_len, 4);
+ notes = xmalloc(note_bytes);
+ memcpy(notes, &boot_notes, sizeof(boot_notes));
+ memcpy(notes->command_line, cmdline, cmdline_len);
+ notes->hdr.b_size = note_bytes;
+ notes->cmd_hdr.n_descsz = cmdline_len;
+ notes->hdr.b_checksum = compute_ip_checksum(notes, note_bytes);
+
+ note_base = add_buffer(info, notes, note_bytes, note_bytes,
+ 4, 0, max_addr, 1);
+
+ return note_base;
+}
diff --git a/kexec/kexec-elf-boot.h b/kexec/kexec-elf-boot.h
new file mode 100644
index 0000000..843a89b
--- /dev/null
+++ b/kexec/kexec-elf-boot.h
@@ -0,0 +1,8 @@
+#ifndef KEXEC_ELF_BOOT_H
+#define KEXEC_ELF_BOOT_H
+
+unsigned long elf_boot_notes(
+ struct kexec_info *info, unsigned long max_addr,
+ const unsigned char *cmdline, int cmdline_len);
+
+#endif /* KEXEC_ELF_BOOT_H */
diff --git a/kexec/kexec-elf-exec.c b/kexec/kexec-elf-exec.c
new file mode 100644
index 0000000..324516c
--- /dev/null
+++ b/kexec/kexec-elf-exec.c
@@ -0,0 +1,149 @@
+#include <limits.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include "elf.h"
+#include <boot/elf_boot.h>
+#include "kexec.h"
+#include "kexec-elf.h"
+
+static const int probe_debug = 0;
+
+int build_elf_exec_info(const char *buf, off_t len, struct mem_ehdr *ehdr)
+{
+ struct mem_phdr *phdr, *end_phdr;
+ int result;
+ result = build_elf_info(buf, len, ehdr);
+ if (result < 0) {
+ return result;
+ }
+ if ((ehdr->e_type != ET_EXEC) && (ehdr->e_type != ET_DYN)) {
+ /* not an ELF executable */
+ if (probe_debug) {
+ fprintf(stderr, "Not ELF type ET_EXEC or ET_DYN\n");
+ }
+ return -1;
+ }
+ if (!ehdr->e_phdr) {
+ /* No program header */
+ fprintf(stderr, "No ELF program header\n");
+ return -1;
+ }
+ end_phdr = &ehdr->e_phdr[ehdr->e_phnum];
+ for(phdr = ehdr->e_phdr; phdr != end_phdr; phdr++) {
+ /* Kexec does not support loading interpreters.
+ * In addition this check keeps us from attempting
+ * to kexec ordinay executables.
+ */
+ if (phdr->p_type == PT_INTERP) {
+ fprintf(stderr, "Requires an ELF interpreter\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
+int elf_exec_load(const struct mem_ehdr *ehdr, struct kexec_info *info)
+{
+ unsigned long base;
+ int result;
+ int i;
+
+ if (!ehdr->e_phdr) {
+ fprintf(stderr, "No program header?\n");
+ result = -1;
+ goto out;
+ }
+
+ /* If I have a dynamic executable find it's size
+ * and then find a location for it in memory.
+ */
+ base = 0;
+ if (ehdr->e_type == ET_DYN) {
+ unsigned long first, last, align;
+ first = ULONG_MAX;
+ last = 0;
+ align = 0;
+ for(i = 0; i < ehdr->e_phnum; i++) {
+ unsigned long start, stop;
+ struct mem_phdr *phdr;
+ phdr = &ehdr->e_phdr[i];
+ if ((phdr->p_type != PT_LOAD) ||
+ (phdr->p_memsz == 0))
+ {
+ continue;
+ }
+ start = phdr->p_paddr;
+ stop = start + phdr->p_memsz;
+ if (start > first) {
+ start = first;
+ }
+ if (last < stop) {
+ last = stop;
+ }
+ if (align < phdr->p_align) {
+ align = phdr->p_align;
+ }
+ }
+ /* If I can't use the default paddr find a new
+ * hole for the dynamic executable.
+ */
+ if (!valid_memory_range(first, last)) {
+ unsigned long hole;
+ hole = locate_hole(info,
+ last - first + 1, align,
+ 0, elf_max_addr(ehdr), 1);
+ if (hole == ULONG_MAX) {
+ result = -1;
+ goto out;
+ }
+ /* Base is the value that when added
+ * to any virtual address in the file
+ * yields it's load virtual address.
+ */
+ base = hole - first;
+ }
+
+ }
+
+ /* Read in the PT_LOAD segments */
+ for(i = 0; i < ehdr->e_phnum; i++) {
+ struct mem_phdr *phdr;
+ size_t size;
+ phdr = &ehdr->e_phdr[i];
+ if (phdr->p_type != PT_LOAD) {
+ continue;
+ }
+ size = phdr->p_filesz;
+ if (size > phdr->p_memsz) {
+ size = phdr->p_memsz;
+ }
+ add_segment(info,
+ phdr->p_data, size,
+ phdr->p_paddr + base, phdr->p_memsz);
+ }
+ result = 0;
+ out:
+ return result;
+}
+
+void elf_exec_build_load(struct kexec_info *info, struct mem_ehdr *ehdr,
+ const char *buf, off_t len)
+{
+ int result;
+ /* Parse the Elf file */
+ result = build_elf_exec_info(buf, len, ehdr);
+ if (result < 0) {
+ die("ELF exec parse failed\n");
+ }
+
+ /* Load the Elf data */
+ result = elf_exec_load(ehdr, info);
+ if (result < 0) {
+ die("ELF exec load failed\n");
+ }
+}
diff --git a/kexec/kexec-elf-rel.c b/kexec/kexec-elf-rel.c
new file mode 100644
index 0000000..560c659
--- /dev/null
+++ b/kexec/kexec-elf-rel.c
@@ -0,0 +1,531 @@
+#include <limits.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include "elf.h"
+#include <boot/elf_boot.h>
+#include "kexec.h"
+#include "kexec-elf.h"
+
+static const int probe_debug = 0;
+
+static size_t elf_sym_size(struct mem_ehdr *ehdr)
+{
+ size_t sym_size = 0;
+ if (ehdr->ei_class == ELFCLASS32) {
+ sym_size = sizeof(Elf32_Sym);
+ }
+ else if (ehdr->ei_class == ELFCLASS64) {
+ sym_size = sizeof(Elf64_Sym);
+ }
+ else {
+ die("Bad elf class");
+ }
+ return sym_size;
+}
+
+static size_t elf_rel_size(struct mem_ehdr *ehdr)
+{
+ size_t rel_size = 0;
+ if (ehdr->ei_class == ELFCLASS32) {
+ rel_size = sizeof(Elf32_Rel);
+ }
+ else if (ehdr->ei_class == ELFCLASS64) {
+ rel_size = sizeof(Elf64_Rel);
+ }
+ else {
+ die("Bad elf class");
+ }
+ return rel_size;
+}
+
+static size_t elf_rela_size(struct mem_ehdr *ehdr)
+{
+ size_t rel_size = 0;
+ if (ehdr->ei_class == ELFCLASS32) {
+ rel_size = sizeof(Elf32_Rela);
+ }
+ else if (ehdr->ei_class == ELFCLASS64) {
+ rel_size = sizeof(Elf64_Rela);
+ }
+ else {
+ die("Bad elf class");
+ }
+ return rel_size;
+}
+
+static struct mem_sym elf_sym(struct mem_ehdr *ehdr, const unsigned char *ptr)
+{
+ struct mem_sym sym;
+ if (ehdr->ei_class == ELFCLASS32) {
+ Elf32_Sym lsym;
+ memcpy(&lsym, ptr, sizeof(lsym));
+ sym.st_name = elf32_to_cpu(ehdr, lsym.st_name);
+ sym.st_value = elf32_to_cpu(ehdr, lsym.st_value);
+ sym.st_size = elf32_to_cpu(ehdr, lsym.st_size);
+ sym.st_info = lsym.st_info;
+ sym.st_other = lsym.st_other;
+ sym.st_shndx = elf16_to_cpu(ehdr, lsym.st_shndx);
+ }
+ else if (ehdr->ei_class == ELFCLASS64) {
+ Elf64_Sym lsym;
+ memcpy(&lsym, ptr, sizeof(lsym));
+ sym.st_name = elf32_to_cpu(ehdr, lsym.st_name);
+ sym.st_value = elf64_to_cpu(ehdr, lsym.st_value);
+ sym.st_size = elf64_to_cpu(ehdr, lsym.st_size);
+ sym.st_info = lsym.st_info;
+ sym.st_other = lsym.st_other;
+ sym.st_shndx = elf16_to_cpu(ehdr, lsym.st_shndx);
+ }
+ else {
+ die("Bad elf class");
+ }
+ return sym;
+}
+
+static struct mem_rela elf_rel(struct mem_ehdr *ehdr, const unsigned char *ptr)
+{
+ struct mem_rela rela;
+ if (ehdr->ei_class == ELFCLASS32) {
+ Elf32_Rel lrel;
+ memcpy(&lrel, ptr, sizeof(lrel));
+ rela.r_offset = elf32_to_cpu(ehdr, lrel.r_offset);
+ rela.r_sym = ELF32_R_SYM(elf32_to_cpu(ehdr, lrel.r_info));
+ rela.r_type = ELF32_R_TYPE(elf32_to_cpu(ehdr, lrel.r_info));
+ rela.r_addend = 0;
+ }
+ else if (ehdr->ei_class == ELFCLASS64) {
+ Elf64_Rel lrel;
+ memcpy(&lrel, ptr, sizeof(lrel));
+ rela.r_offset = elf64_to_cpu(ehdr, lrel.r_offset);
+ rela.r_sym = ELF64_R_SYM(elf64_to_cpu(ehdr, lrel.r_info));
+ rela.r_type = ELF64_R_TYPE(elf64_to_cpu(ehdr, lrel.r_info));
+ rela.r_addend = 0;
+ }
+ else {
+ die("Bad elf class");
+ }
+ return rela;
+}
+
+static struct mem_rela elf_rela(struct mem_ehdr *ehdr, const unsigned char *ptr)
+{
+ struct mem_rela rela;
+ if (ehdr->ei_class == ELFCLASS32) {
+ Elf32_Rela lrela;
+ memcpy(&lrela, ptr, sizeof(lrela));
+ rela.r_offset = elf32_to_cpu(ehdr, lrela.r_offset);
+ rela.r_sym = ELF32_R_SYM(elf32_to_cpu(ehdr, lrela.r_info));
+ rela.r_type = ELF32_R_TYPE(elf32_to_cpu(ehdr, lrela.r_info));
+ rela.r_addend = elf32_to_cpu(ehdr, lrela.r_addend);
+ }
+ else if (ehdr->ei_class == ELFCLASS64) {
+ Elf64_Rela lrela;
+ memcpy(&lrela, ptr, sizeof(lrela));
+ rela.r_offset = elf64_to_cpu(ehdr, lrela.r_offset);
+ rela.r_sym = ELF64_R_SYM(elf64_to_cpu(ehdr, lrela.r_info));
+ rela.r_type = ELF64_R_TYPE(elf64_to_cpu(ehdr, lrela.r_info));
+ rela.r_addend = elf64_to_cpu(ehdr, lrela.r_addend);
+ }
+ else {
+ die("Bad elf class");
+ }
+ return rela;
+}
+
+int build_elf_rel_info(const char *buf, off_t len, struct mem_ehdr *ehdr)
+{
+ int result;
+ result = build_elf_info(buf, len, ehdr);
+ if (result < 0) {
+ return result;
+ }
+ if (ehdr->e_type != ET_REL) {
+ /* not an ELF relocate object */
+ if (probe_debug) {
+ fprintf(stderr, "Not ELF type ET_REL\n");
+ fprintf(stderr, "ELF Type: %x\n", ehdr->e_type);
+ }
+ return -1;
+ }
+ if (!ehdr->e_shdr) {
+ /* No section headers */
+ if (probe_debug) {
+ fprintf(stderr, "No ELF section headers\n");
+ }
+ return -1;
+ }
+ if (!machine_verify_elf_rel(ehdr)) {
+ /* It does not meant the native architecture constraints */
+ if (probe_debug) {
+ fprintf(stderr, "ELF architecture constraint failure\n");
+ }
+ return -1;
+ }
+ return 0;
+}
+
+
+int elf_rel_load(struct mem_ehdr *ehdr, struct kexec_info *info,
+ unsigned long min, unsigned long max, int end)
+{
+ struct mem_shdr *shdr, *shdr_end, *entry_shdr;
+ unsigned long entry;
+ int result;
+ unsigned char *buf;
+ unsigned long buf_align, bufsz, bss_align, bsssz, bss_pad;
+ unsigned long buf_addr, data_addr, bss_addr;
+
+ if (max > elf_max_addr(ehdr)) {
+ max = elf_max_addr(ehdr);
+ }
+ if (!ehdr->e_shdr) {
+ fprintf(stderr, "No section header?\n");
+ result = -1;
+ goto out;
+ }
+ shdr_end = &ehdr->e_shdr[ehdr->e_shnum];
+
+ /* Find which section entry is in */
+ entry_shdr = NULL;
+ entry = ehdr->e_entry;
+ for(shdr = ehdr->e_shdr; shdr != shdr_end; shdr++) {
+ if (!(shdr->sh_flags & SHF_ALLOC)) {
+ continue;
+ }
+ if (!(shdr->sh_flags & SHF_EXECINSTR)) {
+ continue;
+ }
+ /* Make entry section relative */
+ if ((shdr->sh_addr <= ehdr->e_entry) &&
+ ((shdr->sh_addr + shdr->sh_size) > ehdr->e_entry)) {
+ entry_shdr = shdr;
+ entry -= shdr->sh_addr;
+ break;
+ }
+ }
+
+ /* Find the memory footprint of the relocatable object */
+ buf_align = 1;
+ bss_align = 1;
+ bufsz = 0;
+ bsssz = 0;
+ for(shdr = ehdr->e_shdr; shdr != shdr_end; shdr++) {
+ if (!(shdr->sh_flags & SHF_ALLOC)) {
+ continue;
+ }
+ if (shdr->sh_type != SHT_NOBITS) {
+ unsigned long align;
+ align = shdr->sh_addralign;
+ /* See if I need more alignment */
+ if (buf_align < align) {
+ buf_align = align;
+ }
+ /* Now align bufsz */
+ bufsz = (bufsz + (align - 1)) & ~(align - 1);
+ /* And now add our buffer */
+ bufsz += shdr->sh_size;
+ }
+ else {
+ unsigned long align;
+ align = shdr->sh_addralign;
+ /* See if I need more alignment */
+ if (bss_align < align) {
+ bss_align = align;
+ }
+ /* Now align bsssz */
+ bsssz = (bsssz + (align - 1)) & ~(align -1);
+ /* And now add our buffer */
+ bsssz += shdr->sh_size;
+ }
+ }
+ if (buf_align < bss_align) {
+ buf_align = bss_align;
+ }
+ bss_pad = 0;
+ if (bufsz & (bss_align - 1)) {
+ bss_pad = bss_align - (bufsz & (bss_align - 1));
+ }
+
+ /* Allocate where we will put the relocated object */
+ buf = xmalloc(bufsz);
+ buf_addr = add_buffer(info, buf, bufsz, bufsz + bss_pad + bsssz,
+ buf_align, min, max, end);
+ ehdr->rel_addr = buf_addr;
+ ehdr->rel_size = bufsz + bss_pad + bsssz;
+
+ /* Walk through and find an address for each SHF_ALLOC section */
+ data_addr = buf_addr;
+ bss_addr = buf_addr + bufsz + bss_pad;
+ for(shdr = ehdr->e_shdr; shdr != shdr_end; shdr++) {
+ unsigned long align;
+ if (!(shdr->sh_flags & SHF_ALLOC)) {
+ continue;
+ }
+ align = shdr->sh_addralign;
+ if (shdr->sh_type != SHT_NOBITS) {
+ unsigned long off;
+ /* Adjust the address */
+ data_addr = (data_addr + (align - 1)) & ~(align -1);
+
+ /* Update the section */
+ off = data_addr - buf_addr;
+ memcpy(buf + off, shdr->sh_data, shdr->sh_size);
+ shdr->sh_addr = data_addr;
+ shdr->sh_data = buf + off;
+
+ /* Advance to the next address */
+ data_addr += shdr->sh_size;
+ } else {
+ /* Adjust the address */
+ bss_addr = (bss_addr + (align - 1)) & ~(align -1);
+
+ /* Update the section */
+ shdr->sh_addr = bss_addr;
+
+ /* Advance to the next address */
+ bss_addr += shdr->sh_size;
+ }
+ }
+ /* Compute the relocated value for entry, and load it */
+ if (entry_shdr) {
+ entry += entry_shdr->sh_addr;
+ ehdr->e_entry = entry;
+ }
+ info->entry = (void *)entry;
+
+ /* Now that the load address is known apply relocations */
+ for(shdr = ehdr->e_shdr; shdr != shdr_end; shdr++) {
+ struct mem_shdr *section, *symtab;
+ const unsigned char *strtab;
+ size_t rel_size;
+ const unsigned char *ptr, *rel_end;
+ if ((shdr->sh_type != SHT_RELA) && (shdr->sh_type != SHT_REL)) {
+ continue;
+ }
+ if ((shdr->sh_info > ehdr->e_shnum) ||
+ (shdr->sh_link > ehdr->e_shnum))
+ {
+ die("Invalid section number\n");
+ }
+ section = &ehdr->e_shdr[shdr->sh_info];
+ symtab = &ehdr->e_shdr[shdr->sh_link];
+
+ if (!(section->sh_flags & SHF_ALLOC)) {
+ continue;
+ }
+
+ if (symtab->sh_link > ehdr->e_shnum) {
+ /* Invalid section number? */
+ continue;
+ }
+ strtab = ehdr->e_shdr[symtab->sh_link].sh_data;
+
+ rel_size = 0;
+ if (shdr->sh_type == SHT_REL) {
+ rel_size = elf_rel_size(ehdr);
+ }
+ else if (shdr->sh_type == SHT_RELA) {
+ rel_size = elf_rela_size(ehdr);
+ }
+ else {
+ die("Cannot find elf rel size\n");
+ }
+ rel_end = shdr->sh_data + shdr->sh_size;
+ for(ptr = shdr->sh_data; ptr < rel_end; ptr += rel_size) {
+ struct mem_rela rel;
+ struct mem_sym sym;
+ const void *location;
+ unsigned long address, value, sec_base;
+ if (shdr->sh_type == SHT_REL) {
+ rel = elf_rel(ehdr, ptr);
+ }
+ else if (shdr->sh_type == SHT_RELA) {
+ rel = elf_rela(ehdr, ptr);
+ }
+ /* the location to change */
+ location = section->sh_data + rel.r_offset;
+
+ /* The final address of that location */
+ address = section->sh_addr + rel.r_offset;
+
+ /* The relevant symbol */
+ sym = elf_sym(ehdr, symtab->sh_data + (rel.r_sym * elf_sym_size(ehdr)));
+#if 0
+ fprintf(stderr, "sym: %10s info: %02x other: %02x shndx: %lx value: %lx size: %lx\n",
+ strtab + sym.st_name,
+ sym.st_info,
+ sym.st_other,
+ sym.st_shndx,
+ sym.st_value,
+ sym.st_size);
+
+#endif
+ if (sym.st_shndx == STN_UNDEF) {
+ die("Undefined symbol: %s\n",
+ strtab + sym.st_name);
+ }
+ sec_base = 0;
+ if (sym.st_shndx == SHN_COMMON) {
+ die("symbol: '%s' in common section\n",
+ strtab + sym.st_name);
+ }
+ else if (sym.st_shndx == SHN_ABS) {
+ sec_base = 0;
+ }
+ else if (sym.st_shndx > ehdr->e_shnum) {
+ die("Invalid section: %d for symbol %s\n",
+ sym.st_shndx,
+ strtab + sym.st_name);
+ }
+ else {
+ sec_base = ehdr->e_shdr[sym.st_shndx].sh_addr;
+ }
+#if 0
+ fprintf(stderr, "sym: %s value: %lx addr: %lx\n",
+ strtab + sym.st_name, value, address);
+#endif
+ value = sym.st_value;
+ value += sec_base;
+ value += rel.r_addend;
+ machine_apply_elf_rel(ehdr, rel.r_type,
+ (void *)location, address, value);
+ }
+ }
+ result = 0;
+ out:
+ return result;
+}
+
+void elf_rel_build_load(struct kexec_info *info, struct mem_ehdr *ehdr,
+ const char *buf, off_t len, unsigned long min, unsigned long max,
+ int end)
+{
+ int result;
+
+ /* Parse the Elf file */
+ result = build_elf_rel_info(purgatory, purgatory_size, ehdr);
+ if (result < 0) {
+ die("ELF rel parse failed\n");
+ }
+ /* Load the Elf data */
+ result = elf_rel_load(ehdr, info, min, max, end);
+ if (result < 0) {
+ die("ELF rel load failed\n");
+ }
+}
+
+int elf_rel_find_symbol(struct mem_ehdr *ehdr,
+ const char *name, struct mem_sym *ret_sym)
+{
+ struct mem_shdr *shdr, *shdr_end;
+
+ if (!ehdr->e_shdr) {
+ /* "No section header? */
+ return -1;
+ }
+ /* Walk through the sections and find the symbol table */
+ shdr_end = &ehdr->e_shdr[ehdr->e_shnum];
+ for (shdr = ehdr->e_shdr; shdr != shdr_end; shdr++) {
+ const char *strtab;
+ size_t sym_size;
+ const unsigned char *ptr, *sym_end;
+ if (shdr->sh_type != SHT_SYMTAB) {
+ continue;
+ }
+ if (shdr->sh_link > ehdr->e_shnum) {
+ /* Invalid strtab section number? */
+ continue;
+ }
+ strtab = ehdr->e_shdr[shdr->sh_link].sh_data;
+ /* Walk through the symbol table and find the symbol */
+ sym_size = elf_sym_size(ehdr);
+ sym_end = shdr->sh_data + shdr->sh_size;
+ for(ptr = shdr->sh_data; ptr < sym_end; ptr += sym_size) {
+ struct mem_sym sym;
+ sym = elf_sym(ehdr, ptr);
+ if (ELF32_ST_BIND(sym.st_info) != STB_GLOBAL) {
+ continue;
+ }
+ if (strcmp(strtab + sym.st_name, name) != 0) {
+ continue;
+ }
+ if ((sym.st_shndx == STN_UNDEF) ||
+ (sym.st_shndx > ehdr->e_shnum))
+ {
+ die("Symbol: %s has Bad section index %d\n",
+ name, sym.st_shndx);
+ }
+ *ret_sym = sym;
+ return 0;
+ }
+ }
+ /* I did not find it :( */
+ return -1;
+
+}
+
+unsigned long elf_rel_get_addr(struct mem_ehdr *ehdr, const char *name)
+{
+ struct mem_shdr *shdr;
+ struct mem_sym sym;
+ int result;
+ result = elf_rel_find_symbol(ehdr, name, &sym);
+ if (result < 0) {
+ die("Symbol: %s not found cannot retrive it's address\n",
+ name);
+ }
+ shdr = &ehdr->e_shdr[sym.st_shndx];
+ return shdr->sh_addr + sym.st_value;
+}
+
+void elf_rel_set_symbol(struct mem_ehdr *ehdr,
+ const char *name, const void *buf, size_t size)
+{
+ unsigned char *sym_buf;
+ struct mem_shdr *shdr;
+ struct mem_sym sym;
+ int result;
+
+ result = elf_rel_find_symbol(ehdr, name, &sym);
+ if (result < 0) {
+ die("Symbol: %s not found cannot set\n",
+ name);
+ }
+ if (sym.st_size != size) {
+ die("Symbol: %s has size: %ld not %ld\n",
+ name, sym.st_size, size);
+ }
+ shdr = &ehdr->e_shdr[sym.st_shndx];
+ if (shdr->sh_type == SHT_NOBITS) {
+ die("Symbol: %s is in a bss section cannot set\n", name);
+ }
+ sym_buf = (unsigned char *)(shdr->sh_data + sym.st_value);
+ memcpy(sym_buf, buf, size);
+}
+
+void elf_rel_get_symbol(struct mem_ehdr *ehdr,
+ const char *name, void *buf, size_t size)
+{
+ const unsigned char *sym_buf;
+ struct mem_shdr *shdr;
+ struct mem_sym sym;
+ int result;
+
+ result = elf_rel_find_symbol(ehdr, name, &sym);
+ if (result < 0) {
+ die("Symbol: %s not found cannot get\n");
+ }
+ if (sym.st_size != size) {
+ die("Symbol: %s has size: %ld not %ld\n",
+ name, sym.st_size, size);
+ }
+ shdr = &ehdr->e_shdr[sym.st_shndx];
+ if (shdr->sh_type == SHT_NOBITS) {
+ die("Symbol: %s is in a bss section cannot set\n", name);
+ }
+ sym_buf = shdr->sh_data + sym.st_value;
+ memcpy(buf, sym_buf,size);
+}
diff --git a/kexec/kexec-elf.c b/kexec/kexec-elf.c
new file mode 100644
index 0000000..e4d07f4
--- /dev/null
+++ b/kexec/kexec-elf.c
@@ -0,0 +1,760 @@
+#include <limits.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include "elf.h"
+#include <boot/elf_boot.h>
+#include "kexec.h"
+#include "kexec-elf.h"
+
+static const int probe_debug = 0;
+
+uint16_t elf16_to_cpu(const struct mem_ehdr *ehdr, uint16_t value)
+{
+ if (ehdr->ei_data == ELFDATA2LSB) {
+ value = le16_to_cpu(value);
+ }
+ else if (ehdr->ei_data == ELFDATA2MSB) {
+ value = be16_to_cpu(value);
+ }
+ return value;
+}
+
+uint32_t elf32_to_cpu(const struct mem_ehdr *ehdr, uint32_t value)
+{
+ if (ehdr->ei_data == ELFDATA2LSB) {
+ value = le32_to_cpu(value);
+ }
+ else if (ehdr->ei_data == ELFDATA2MSB) {
+ value = be32_to_cpu(value);
+ }
+ return value;
+}
+
+uint64_t elf64_to_cpu(const struct mem_ehdr *ehdr, uint64_t value)
+{
+ if (ehdr->ei_data == ELFDATA2LSB) {
+ value = le64_to_cpu(value);
+ }
+ else if (ehdr->ei_data == ELFDATA2MSB) {
+ value = be64_to_cpu(value);
+ }
+ return value;
+}
+
+uint16_t cpu_to_elf16(const struct mem_ehdr *ehdr, uint16_t value)
+{
+ if (ehdr->ei_data == ELFDATA2LSB) {
+ value = cpu_to_le16(value);
+ }
+ else if (ehdr->ei_data == ELFDATA2MSB) {
+ value = cpu_to_be16(value);
+ }
+ return value;
+}
+
+uint32_t cpu_to_elf32(const struct mem_ehdr *ehdr, uint32_t value)
+{
+ if (ehdr->ei_data == ELFDATA2LSB) {
+ value = cpu_to_le32(value);
+ }
+ else if (ehdr->ei_data == ELFDATA2MSB) {
+ value = cpu_to_be32(value);
+ }
+ return value;
+}
+
+uint64_t cpu_to_elf64(const struct mem_ehdr *ehdr, uint64_t value)
+{
+ if (ehdr->ei_data == ELFDATA2LSB) {
+ value = cpu_to_le64(value);
+ }
+ else if (ehdr->ei_data == ELFDATA2MSB) {
+ value = cpu_to_be64(value);
+ }
+ return value;
+}
+
+#define ELF32_MAX 0xffffffff
+#define ELF64_MAX 0xffffffffffffffff
+#if ELF64_MAX > ULONG_MAX
+#undef ELF64_MAX
+#define ELF64_MAX ULONG_MAX
+#endif
+
+unsigned long elf_max_addr(const struct mem_ehdr *ehdr)
+{
+ unsigned long max_addr = 0;
+ if (ehdr->ei_class == ELFCLASS32) {
+ max_addr = ELF32_MAX;
+ }
+ else if (ehdr->ei_class == ELFCLASS64) {
+ max_addr = ELF64_MAX;
+ }
+ return max_addr;
+}
+static int build_mem_elf32_ehdr(const char *buf, off_t len, struct mem_ehdr *ehdr)
+{
+ Elf32_Ehdr lehdr;
+ if (len < sizeof(lehdr)) {
+ /* Buffer is to small to be an elf executable */
+ if (probe_debug) {
+ fprintf(stderr, "Buffer is to small to hold ELF header\n");
+ }
+ return -1;
+ }
+ memcpy(&lehdr, buf, sizeof(lehdr));
+ if (elf16_to_cpu(ehdr, lehdr.e_ehsize) != sizeof(Elf32_Ehdr)) {
+ /* Invalid Elf header size */
+ if (probe_debug) {
+ fprintf(stderr, "Bad ELF header size\n");
+ }
+ return -1;
+ }
+ if (elf32_to_cpu(ehdr, lehdr.e_entry) > ULONG_MAX) {
+ /* entry is to large */
+ if (probe_debug) {
+ fprintf(stderr, "ELF e_entry to large\n");
+ }
+ return -1;
+ }
+ if (elf32_to_cpu(ehdr, lehdr.e_phoff) > ULONG_MAX) {
+ /* phoff is to large */
+ if (probe_debug) {
+ fprintf(stderr, "ELF e_phoff to large\n");
+ }
+ return -1;
+ }
+ if (elf32_to_cpu(ehdr, lehdr.e_shoff) > ULONG_MAX) {
+ /* shoff is to large */
+ if (probe_debug) {
+ fprintf(stderr, "ELF e_shoff to large\n");
+ }
+ return -1;
+ }
+ ehdr->e_type = elf16_to_cpu(ehdr, lehdr.e_type);
+ ehdr->e_machine = elf16_to_cpu(ehdr, lehdr.e_machine);
+ ehdr->e_version = elf32_to_cpu(ehdr, lehdr.e_version);
+ ehdr->e_entry = elf32_to_cpu(ehdr, lehdr.e_entry);
+ ehdr->e_phoff = elf32_to_cpu(ehdr, lehdr.e_phoff);
+ ehdr->e_shoff = elf32_to_cpu(ehdr, lehdr.e_shoff);
+ ehdr->e_flags = elf32_to_cpu(ehdr, lehdr.e_flags);
+ ehdr->e_phnum = elf16_to_cpu(ehdr, lehdr.e_phnum);
+ ehdr->e_shnum = elf16_to_cpu(ehdr, lehdr.e_shnum);
+ ehdr->e_shstrndx = elf16_to_cpu(ehdr, lehdr.e_shstrndx);
+
+ if ((ehdr->e_phnum > 0) &&
+ (elf16_to_cpu(ehdr, lehdr.e_phentsize) != sizeof(Elf32_Phdr)))
+ {
+ /* Invalid program header size */
+ if (probe_debug) {
+ fprintf(stderr, "ELF bad program header size\n");
+ }
+ return -1;
+ }
+ if ((ehdr->e_shnum > 0) &&
+ (elf16_to_cpu(ehdr, lehdr.e_shentsize) != sizeof(Elf32_Shdr)))
+ {
+ /* Invalid section header size */
+ if (probe_debug) {
+ fprintf(stderr, "ELF bad section header size\n");
+ }
+ return -1;
+ }
+
+ return 0;
+}
+
+static int build_mem_elf64_ehdr(const char *buf, off_t len, struct mem_ehdr *ehdr)
+{
+ Elf64_Ehdr lehdr;
+ if (len < sizeof(lehdr)) {
+ /* Buffer is to small to be an elf executable */
+ if (probe_debug) {
+ fprintf(stderr, "Buffer is to small to hold ELF header\n");
+ }
+ return -1;
+ }
+ memcpy(&lehdr, buf, sizeof(lehdr));
+ if (elf16_to_cpu(ehdr, lehdr.e_ehsize) != sizeof(Elf64_Ehdr)) {
+ /* Invalid Elf header size */
+ if (probe_debug) {
+ fprintf(stderr, "Bad ELF header size\n");
+ }
+ return -1;
+ }
+ if (elf32_to_cpu(ehdr, lehdr.e_entry) > ULONG_MAX) {
+ /* entry is to large */
+ if (probe_debug) {
+ fprintf(stderr, "ELF e_entry to large\n");
+ }
+ return -1;
+ }
+ if (elf32_to_cpu(ehdr, lehdr.e_phoff) > ULONG_MAX) {
+ /* phoff is to large */
+ if (probe_debug) {
+ fprintf(stderr, "ELF e_phoff to large\n");
+ }
+ return -1;
+ }
+ if (elf32_to_cpu(ehdr, lehdr.e_shoff) > ULONG_MAX) {
+ /* shoff is to large */
+ if (probe_debug) {
+ fprintf(stderr, "ELF e_shoff to large\n");
+ }
+ return -1;
+ }
+ ehdr->e_type = elf16_to_cpu(ehdr, lehdr.e_type);
+ ehdr->e_machine = elf16_to_cpu(ehdr, lehdr.e_machine);
+ ehdr->e_version = elf32_to_cpu(ehdr, lehdr.e_version);
+ ehdr->e_entry = elf64_to_cpu(ehdr, lehdr.e_entry);
+ ehdr->e_phoff = elf64_to_cpu(ehdr, lehdr.e_phoff);
+ ehdr->e_shoff = elf64_to_cpu(ehdr, lehdr.e_shoff);
+ ehdr->e_flags = elf32_to_cpu(ehdr, lehdr.e_flags);
+ ehdr->e_phnum = elf16_to_cpu(ehdr, lehdr.e_phnum);
+ ehdr->e_shnum = elf16_to_cpu(ehdr, lehdr.e_shnum);
+ ehdr->e_shstrndx = elf16_to_cpu(ehdr, lehdr.e_shstrndx);
+
+ if ((ehdr->e_phnum > 0) &&
+ (elf16_to_cpu(ehdr, lehdr.e_phentsize) != sizeof(Elf64_Phdr)))
+ {
+ /* Invalid program header size */
+ if (probe_debug) {
+ fprintf(stderr, "ELF bad program header size\n");
+ }
+ return -1;
+ }
+ if ((ehdr->e_shnum > 0) &&
+ (elf16_to_cpu(ehdr, lehdr.e_shentsize) != sizeof(Elf64_Shdr)))
+ {
+ /* Invalid section header size */
+ if (probe_debug) {
+ fprintf(stderr, "ELF bad section header size\n");
+ }
+ return -1;
+ }
+
+ return 0;
+}
+
+static int build_mem_ehdr(const char *buf, off_t len, struct mem_ehdr *ehdr)
+{
+ unsigned char e_ident[EI_NIDENT];
+ int result;
+ memset(ehdr, 0, sizeof(*ehdr));
+ if (len < sizeof(e_ident)) {
+ /* Buffer is to small to be an elf executable */
+ if (probe_debug) {
+ fprintf(stderr, "Buffer is to small to hold ELF e_ident\n");
+ }
+ return -1;
+ }
+ memcpy(e_ident, buf, sizeof(e_ident));
+ if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) {
+ /* No ELF header magic */
+ if (probe_debug) {
+ fprintf(stderr, "NO ELF header magic\n");
+ }
+ return -1;
+ }
+ ehdr->ei_class = e_ident[EI_CLASS];
+ ehdr->ei_data = e_ident[EI_DATA];
+ if ( (ehdr->ei_class != ELFCLASS32) &&
+ (ehdr->ei_class != ELFCLASS64))
+ {
+ /* Not a supported elf class */
+ if (probe_debug) {
+ fprintf(stderr, "Not a supported ELF class\n");
+ }
+ return -1;
+ }
+ if ( (ehdr->ei_data != ELFDATA2LSB) &&
+ (ehdr->ei_data != ELFDATA2MSB))
+ {
+ /* Not a supported elf data type */
+ if (probe_debug) {
+ fprintf(stderr, "Not a supported ELF data format\n");
+ }
+ return -1;
+ }
+
+ result = -1;
+ if (ehdr->ei_class == ELFCLASS32) {
+ result = build_mem_elf32_ehdr(buf, len, ehdr);
+ }
+ else if (ehdr->ei_class == ELFCLASS64) {
+ result = build_mem_elf64_ehdr(buf, len, ehdr);
+ }
+ if (result < 0) {
+ return result;
+ }
+ if ((e_ident[EI_VERSION] != EV_CURRENT) ||
+ (ehdr->e_version != EV_CURRENT))
+ {
+ if (probe_debug) {
+ fprintf(stderr, "Unknown ELF version\n");
+ }
+ /* Unknwon elf version */
+ return -1;
+ }
+ return 0;
+}
+
+static int build_mem_elf32_phdr(const char *buf, off_t len,
+ struct mem_ehdr *ehdr, int idx)
+{
+ struct mem_phdr *phdr;
+ const char *pbuf;
+ Elf32_Phdr lphdr;
+ pbuf = buf + ehdr->e_phoff + (idx * sizeof(lphdr));
+ phdr = &ehdr->e_phdr[idx];
+ memcpy(&lphdr, pbuf, sizeof(lphdr));
+
+ if ( (elf32_to_cpu(ehdr, lphdr.p_filesz) > ULONG_MAX) ||
+ (elf32_to_cpu(ehdr, lphdr.p_memsz) > ULONG_MAX) ||
+ (elf32_to_cpu(ehdr, lphdr.p_offset) > ULONG_MAX) ||
+ (elf32_to_cpu(ehdr, lphdr.p_paddr) > ULONG_MAX) ||
+ (elf32_to_cpu(ehdr, lphdr.p_vaddr) > ULONG_MAX) ||
+ (elf32_to_cpu(ehdr, lphdr.p_align) > ULONG_MAX))
+ {
+ fprintf(stderr, "Program segment size out of range\n");
+ return -1;
+ }
+
+ phdr->p_type = elf32_to_cpu(ehdr, lphdr.p_type);
+ phdr->p_paddr = elf32_to_cpu(ehdr, lphdr.p_paddr);
+ phdr->p_vaddr = elf32_to_cpu(ehdr, lphdr.p_vaddr);
+ phdr->p_filesz = elf32_to_cpu(ehdr, lphdr.p_filesz);
+ phdr->p_memsz = elf32_to_cpu(ehdr, lphdr.p_memsz);
+ phdr->p_offset = elf32_to_cpu(ehdr, lphdr.p_offset);
+ phdr->p_flags = elf32_to_cpu(ehdr, lphdr.p_flags);
+ phdr->p_align = elf32_to_cpu(ehdr, lphdr.p_align);
+
+ return 0;
+}
+
+static int build_mem_elf64_phdr(const char *buf, off_t len,
+ struct mem_ehdr *ehdr, int idx)
+{
+ struct mem_phdr *phdr;
+ const char *pbuf;
+ Elf64_Phdr lphdr;
+ pbuf = buf + ehdr->e_phoff + (idx * sizeof(lphdr));
+ phdr = &ehdr->e_phdr[idx];
+ memcpy(&lphdr, pbuf, sizeof(lphdr));
+
+ if ( (elf64_to_cpu(ehdr, lphdr.p_filesz) > ULONG_MAX) ||
+ (elf64_to_cpu(ehdr, lphdr.p_memsz) > ULONG_MAX) ||
+ (elf64_to_cpu(ehdr, lphdr.p_offset) > ULONG_MAX) ||
+ (elf64_to_cpu(ehdr, lphdr.p_paddr) > ULONG_MAX) ||
+ (elf64_to_cpu(ehdr, lphdr.p_vaddr) > ULONG_MAX) ||
+ (elf64_to_cpu(ehdr, lphdr.p_align) > ULONG_MAX))
+ {
+ fprintf(stderr, "Program segment size out of range\n");
+ return -1;
+ }
+
+ phdr->p_type = elf32_to_cpu(ehdr, lphdr.p_type);
+ phdr->p_paddr = elf64_to_cpu(ehdr, lphdr.p_paddr);
+ phdr->p_vaddr = elf64_to_cpu(ehdr, lphdr.p_vaddr);
+ phdr->p_filesz = elf64_to_cpu(ehdr, lphdr.p_filesz);
+ phdr->p_memsz = elf64_to_cpu(ehdr, lphdr.p_memsz);
+ phdr->p_offset = elf64_to_cpu(ehdr, lphdr.p_offset);
+ phdr->p_flags = elf32_to_cpu(ehdr, lphdr.p_flags);
+ phdr->p_align = elf64_to_cpu(ehdr, lphdr.p_align);
+
+ return 0;
+}
+
+static int build_mem_phdrs(const char *buf, off_t len, struct mem_ehdr *ehdr)
+{
+ size_t phdr_size, mem_phdr_size;
+ int i;
+
+ /* e_phnum is at most 65535 so calculating
+ * the size of the program header cannot overflow.
+ */
+ /* Is the program header in the file buffer? */
+ phdr_size = 0;
+ if (ehdr->ei_class == ELFCLASS32) {
+ phdr_size = sizeof(Elf32_Phdr);
+ }
+ else if (ehdr->ei_class == ELFCLASS64) {
+ phdr_size = sizeof(Elf64_Phdr);
+ }
+ else {
+ fprintf(stderr, "Invalid ei_class?\n");
+ return -1;
+ }
+ phdr_size *= ehdr->e_phnum;
+ if (ehdr->e_phoff + phdr_size > len) {
+ /* The program header did not fit in the file buffer */
+ if (probe_debug) {
+ fprintf(stderr, "ELF program segment truncated\n");
+ }
+ return -1;
+ }
+
+ /* Allocate the e_phdr array */
+ mem_phdr_size = sizeof(ehdr->e_phdr[0]) * ehdr->e_phnum;
+ ehdr->e_phdr = xmalloc(mem_phdr_size);
+
+ for(i = 0; i < ehdr->e_phnum; i++) {
+ struct mem_phdr *phdr;
+ int result;
+ result = -1;
+ if (ehdr->ei_class == ELFCLASS32) {
+ result = build_mem_elf32_phdr(buf, len, ehdr, i);
+
+ }
+ else if (ehdr->ei_class == ELFCLASS64) {
+ result = build_mem_elf64_phdr(buf, len, ehdr, i);
+ }
+ if (result < 0) {
+ return result;
+ }
+
+ /* Check the program headers to be certain
+ * they are safe to use.
+ */
+ phdr = &ehdr->e_phdr[i];
+ if ((phdr->p_offset + phdr->p_filesz) > len) {
+ /* The segment does not fit in the buffer */
+ if (probe_debug) {
+ fprintf(stderr, "ELF segment not in file\n");
+ }
+ return -1;
+ }
+ if ((phdr->p_paddr + phdr->p_memsz) < phdr->p_paddr) {
+ /* The memory address wraps */
+ if (probe_debug) {
+ fprintf(stderr, "ELF address wrap around\n");
+ }
+ return -1;
+ }
+ /* Remember where the segment lives in the buffer */
+ phdr->p_data = buf + phdr->p_offset;
+ }
+ return 0;
+}
+
+static int build_mem_elf32_shdr(const char *buf, off_t len,
+ struct mem_ehdr *ehdr, int idx)
+{
+ struct mem_shdr *shdr;
+ const char *sbuf;
+ int size_ok;
+ Elf32_Shdr lshdr;
+ sbuf = buf + ehdr->e_shoff + (idx * sizeof(lshdr));
+ shdr = &ehdr->e_shdr[idx];
+ memcpy(&lshdr, sbuf, sizeof(lshdr));
+
+ if ( (elf32_to_cpu(ehdr, lshdr.sh_flags) > ULONG_MAX) ||
+ (elf32_to_cpu(ehdr, lshdr.sh_addr) > ULONG_MAX) ||
+ (elf32_to_cpu(ehdr, lshdr.sh_offset) > ULONG_MAX) ||
+ (elf32_to_cpu(ehdr, lshdr.sh_size) > ULONG_MAX) ||
+ (elf32_to_cpu(ehdr, lshdr.sh_addralign) > ULONG_MAX) ||
+ (elf32_to_cpu(ehdr, lshdr.sh_entsize) > ULONG_MAX))
+ {
+ fprintf(stderr, "Program section size out of range\n");
+ return -1;
+ }
+
+ shdr->sh_name = elf32_to_cpu(ehdr, lshdr.sh_name);
+ shdr->sh_type = elf32_to_cpu(ehdr, lshdr.sh_type);
+ shdr->sh_flags = elf32_to_cpu(ehdr, lshdr.sh_flags);
+ shdr->sh_addr = elf32_to_cpu(ehdr, lshdr.sh_addr);
+ shdr->sh_offset = elf32_to_cpu(ehdr, lshdr.sh_offset);
+ shdr->sh_size = elf32_to_cpu(ehdr, lshdr.sh_size);
+ shdr->sh_link = elf32_to_cpu(ehdr, lshdr.sh_link);
+ shdr->sh_info = elf32_to_cpu(ehdr, lshdr.sh_info);
+ shdr->sh_addralign = elf32_to_cpu(ehdr, lshdr.sh_addralign);
+ shdr->sh_entsize = elf32_to_cpu(ehdr, lshdr.sh_entsize);
+
+ /* Now verify sh_entsize */
+ size_ok = 0;
+ switch(shdr->sh_type) {
+ case SHT_SYMTAB:
+ size_ok = shdr->sh_entsize == sizeof(Elf32_Sym);
+ break;
+ case SHT_RELA:
+ size_ok = shdr->sh_entsize == sizeof(Elf32_Rela);
+ break;
+ case SHT_DYNAMIC:
+ size_ok = shdr->sh_entsize == sizeof(Elf32_Dyn);
+ break;
+ case SHT_REL:
+ size_ok = shdr->sh_entsize == sizeof(Elf32_Rel);
+ break;
+ case SHT_NOTE:
+ case SHT_NULL:
+ case SHT_PROGBITS:
+ case SHT_HASH:
+ case SHT_NOBITS:
+ default:
+ /* This is a section whose entsize requirements
+ * I don't care about. If I don't know about
+ * the section I can't care about it's entsize
+ * requirements.
+ */
+ size_ok = 1;
+ break;
+ }
+ if (!size_ok) {
+ fprintf(stderr, "Bad section header(%x) entsize: %ld\n",
+ shdr->sh_type, shdr->sh_entsize);
+ return -1;
+ }
+ return 0;
+}
+
+static int build_mem_elf64_shdr(const char *buf, off_t len,
+ struct mem_ehdr *ehdr, int idx)
+{
+ struct mem_shdr *shdr;
+ const char *sbuf;
+ int size_ok;
+ Elf64_Shdr lshdr;
+ sbuf = buf + ehdr->e_shoff + (idx * sizeof(lshdr));
+ shdr = &ehdr->e_shdr[idx];
+ memcpy(&lshdr, sbuf, sizeof(lshdr));
+
+ if ( (elf64_to_cpu(ehdr, lshdr.sh_flags) > ULONG_MAX) ||
+ (elf64_to_cpu(ehdr, lshdr.sh_addr) > ULONG_MAX) ||
+ (elf64_to_cpu(ehdr, lshdr.sh_offset) > ULONG_MAX) ||
+ (elf64_to_cpu(ehdr, lshdr.sh_size) > ULONG_MAX) ||
+ (elf64_to_cpu(ehdr, lshdr.sh_addralign) > ULONG_MAX) ||
+ (elf64_to_cpu(ehdr, lshdr.sh_entsize) > ULONG_MAX))
+ {
+ fprintf(stderr, "Program section size out of range\n");
+ return -1;
+ }
+
+ shdr->sh_name = elf32_to_cpu(ehdr, lshdr.sh_name);
+ shdr->sh_type = elf32_to_cpu(ehdr, lshdr.sh_type);
+ shdr->sh_flags = elf64_to_cpu(ehdr, lshdr.sh_flags);
+ shdr->sh_addr = elf64_to_cpu(ehdr, lshdr.sh_addr);
+ shdr->sh_offset = elf64_to_cpu(ehdr, lshdr.sh_offset);
+ shdr->sh_size = elf64_to_cpu(ehdr, lshdr.sh_size);
+ shdr->sh_link = elf32_to_cpu(ehdr, lshdr.sh_link);
+ shdr->sh_info = elf32_to_cpu(ehdr, lshdr.sh_info);
+ shdr->sh_addralign = elf64_to_cpu(ehdr, lshdr.sh_addralign);
+ shdr->sh_entsize = elf64_to_cpu(ehdr, lshdr.sh_entsize);
+
+ /* Now verify sh_entsize */
+ size_ok = 0;
+ switch(shdr->sh_type) {
+ case SHT_SYMTAB:
+ size_ok = shdr->sh_entsize == sizeof(Elf64_Sym);
+ break;
+ case SHT_RELA:
+ size_ok = shdr->sh_entsize == sizeof(Elf64_Rela);
+ break;
+ case SHT_DYNAMIC:
+ size_ok = shdr->sh_entsize == sizeof(Elf64_Dyn);
+ break;
+ case SHT_REL:
+ size_ok = shdr->sh_entsize == sizeof(Elf64_Rel);
+ break;
+ case SHT_NOTE:
+ case SHT_NULL:
+ case SHT_PROGBITS:
+ case SHT_HASH:
+ case SHT_NOBITS:
+ default:
+ /* This is a section whose entsize requirements
+ * I don't care about. If I don't know about
+ * the section I can't care about it's entsize
+ * requirements.
+ */
+ size_ok = 1;
+ break;
+ }
+ if (!size_ok) {
+ fprintf(stderr, "Bad section header(%x) entsize: %ld\n",
+ shdr->sh_type, shdr->sh_entsize);
+ return -1;
+ }
+ return 0;
+}
+
+static int build_mem_shdrs(const char *buf, off_t len, struct mem_ehdr *ehdr)
+{
+ size_t shdr_size, mem_shdr_size;
+ int i;
+
+ /* e_shnum is at most 65536 so calculating
+ * the size of the section header cannot overflow.
+ */
+ /* Is the program header in the file buffer? */
+ shdr_size = 0;
+ if (ehdr->ei_class == ELFCLASS32) {
+ shdr_size = sizeof(Elf32_Shdr);
+ }
+ else if (ehdr->ei_class == ELFCLASS64) {
+ shdr_size = sizeof(Elf64_Shdr);
+ }
+ else {
+ fprintf(stderr, "Invalid ei_class?\n");
+ return -1;
+ }
+ shdr_size *= ehdr->e_shnum;
+ if (ehdr->e_shoff + shdr_size > len) {
+ /* The section header did not fit in the file buffer */
+ if (probe_debug) {
+ fprintf(stderr, "ELF section header does not fit in file\n");
+ }
+ return -1;
+ }
+
+ /* Allocate the e_shdr array */
+ mem_shdr_size = sizeof(ehdr->e_shdr[0]) * ehdr->e_shnum;
+ ehdr->e_shdr = xmalloc(mem_shdr_size);
+
+ for(i = 0; i < ehdr->e_shnum; i++) {
+ struct mem_shdr *shdr;
+ int result;
+ result = -1;
+ if (ehdr->ei_class == ELFCLASS32) {
+ result = build_mem_elf32_shdr(buf, len, ehdr, i);
+ }
+ else if (ehdr->ei_class == ELFCLASS64) {
+ result = build_mem_elf64_shdr(buf, len, ehdr, i);
+ }
+ if (result < 0) {
+ return result;
+ }
+ /* Check the section headers to be certain
+ * they are safe to use.
+ */
+ shdr = &ehdr->e_shdr[i];
+ if ((shdr->sh_type != SHT_NOBITS) &&
+ ((shdr->sh_offset + shdr->sh_size) > len))
+ {
+ /* The section does not fit in the buffer */
+ if (probe_debug) {
+ fprintf(stderr, "ELF section %d not in file\n",
+ i);
+ }
+ return -1;
+ }
+ if ((shdr->sh_addr + shdr->sh_size) < shdr->sh_addr) {
+ /* The memory address wraps */
+ if (probe_debug) {
+ fprintf(stderr, "ELF address wrap around\n");
+ }
+ return -1;
+ }
+ /* Remember where the section lives in the buffer */
+ shdr->sh_data = buf + shdr->sh_offset;
+ }
+ return 0;
+}
+
+static void read_nhdr(const struct mem_ehdr *ehdr,
+ ElfNN_Nhdr *hdr, const unsigned char *note)
+{
+ memcpy(hdr, note, sizeof(*hdr));
+ hdr->n_namesz = elf32_to_cpu(ehdr, hdr->n_namesz);
+ hdr->n_descsz = elf32_to_cpu(ehdr, hdr->n_descsz);
+ hdr->n_type = elf32_to_cpu(ehdr, hdr->n_type);
+
+}
+static int build_mem_notes(const char *buf, off_t len, struct mem_ehdr *ehdr)
+{
+ const unsigned char *note_start, *note_end, *note;
+ size_t note_size;
+ int i;
+ /* First find the note segment or section */
+ note_start = note_end = NULL;
+ for(i = 0; !note_start && (i < ehdr->e_phnum); i++) {
+ struct mem_phdr *phdr = &ehdr->e_phdr[i];
+ if (phdr->p_type == PT_NOTE) {
+ note_start = phdr->p_data;
+ note_end = note_start + phdr->p_filesz;
+ }
+ }
+ for(i = 0; !note_start && (i < ehdr->e_shnum); i++) {
+ struct mem_shdr *shdr = &ehdr->e_shdr[i];
+ if (shdr->sh_type == SHT_NOTE) {
+ note_start = shdr->sh_data;
+ note_end = note_start + shdr->sh_size;
+ }
+ }
+ if (!note_start) {
+ return 0;
+ }
+
+ /* Walk through and count the notes */
+ ehdr->e_notenum = 0;
+ for(note = note_start; note < note_end; note+= note_size) {
+ ElfNN_Nhdr hdr;
+ read_nhdr(ehdr, &hdr, note);
+ note_size = sizeof(hdr);
+ note_size += (hdr.n_namesz + 3) & ~3;
+ note_size += (hdr.n_descsz + 3) & ~3;
+ ehdr->e_notenum += 1;
+ }
+ /* Now walk and normalize the notes */
+ ehdr->e_note = xmalloc(sizeof(*ehdr->e_note) * ehdr->e_notenum);
+ for(i = 0, note = note_start; note < note_end; note+= note_size, i++) {
+ const unsigned char *name, *desc;
+ ElfNN_Nhdr hdr;
+ read_nhdr(ehdr, &hdr, note);
+ note_size = sizeof(hdr);
+ name = note + note_size;
+ note_size += (hdr.n_namesz + 3) & ~3;
+ desc = note + note_size;
+ note_size += (hdr.n_descsz + 3) & ~3;
+
+ if ((hdr.n_namesz != 0) && (name[hdr.n_namesz -1] != '\0')) {
+ die("Note name is not null termiated");
+ }
+ ehdr->e_note[i].n_type = hdr.n_type;
+ ehdr->e_note[i].n_name = name;
+ ehdr->e_note[i].n_desc = desc;
+ ehdr->e_note[i].n_descsz = hdr.n_descsz;
+
+ }
+ return 0;
+}
+
+
+void free_elf_info(struct mem_ehdr *ehdr)
+{
+ free(ehdr->e_phdr);
+ free(ehdr->e_shdr);
+ memset(ehdr, 0, sizeof(*ehdr));
+}
+
+int build_elf_info(const char *buf, off_t len, struct mem_ehdr *ehdr)
+{
+ int result;
+ result = build_mem_ehdr(buf, len, ehdr);
+ if (result < 0) {
+ return result;
+ }
+ if ((ehdr->e_phoff > 0) && (ehdr->e_phnum > 0)) {
+ result = build_mem_phdrs(buf, len, ehdr);
+ if (result < 0) {
+ free_elf_info(ehdr);
+ return result;
+ }
+ }
+ if ((ehdr->e_shoff > 0) && (ehdr->e_shnum > 0)) {
+ result = build_mem_shdrs(buf, len, ehdr);
+ if (result < 0) {
+ free_elf_info(ehdr);
+ return result;
+ }
+ }
+ result = build_mem_notes(buf, len, ehdr);
+ if (result < 0) {
+ free_elf_info(ehdr);
+ return result;
+ }
+ return 0;
+}
+
diff --git a/kexec/kexec-elf.h b/kexec/kexec-elf.h
new file mode 100644
index 0000000..298d351
--- /dev/null
+++ b/kexec/kexec-elf.h
@@ -0,0 +1,125 @@
+#ifndef KEXEC_ELF_H
+#define KEXEC_ELF_H
+
+struct kexec_info;
+
+struct mem_ehdr {
+ unsigned ei_class;
+ unsigned ei_data;
+ unsigned e_type;
+ unsigned e_machine;
+ unsigned e_version;
+ unsigned e_flags;
+ unsigned e_phnum;
+ unsigned e_shnum;
+ unsigned e_shstrndx;
+ unsigned long e_entry;
+ unsigned long e_phoff;
+ unsigned long e_shoff;
+ unsigned e_notenum;
+ struct mem_phdr *e_phdr;
+ struct mem_shdr *e_shdr;
+ struct mem_note *e_note;
+ unsigned long rel_addr, rel_size;
+};
+
+struct mem_phdr {
+ unsigned long p_paddr;
+ unsigned long p_vaddr;
+ unsigned long p_filesz;
+ unsigned long p_memsz;
+ unsigned long p_offset;
+ const char *p_data;
+ unsigned p_type;
+ unsigned p_flags;
+ unsigned p_align;
+};
+
+struct mem_shdr {
+ unsigned sh_name;
+ unsigned sh_type;
+ unsigned long sh_flags;
+ unsigned long sh_addr;
+ unsigned long sh_offset;
+ unsigned long sh_size;
+ unsigned sh_link;
+ unsigned sh_info;
+ unsigned long sh_addralign;
+ unsigned long sh_entsize;
+ const unsigned char *sh_data;
+};
+
+struct mem_sym {
+ unsigned long st_name; /* Symbol name (string tbl index) */
+ unsigned char st_info; /* No defined meaning, 0 */
+ unsigned char st_other; /* Symbol type and binding */
+ unsigned long st_shndx; /* Section index */
+ unsigned long st_value; /* Symbol value */
+ unsigned long st_size; /* Symbol size */
+};
+
+struct mem_rela {
+ unsigned long r_offset;
+ unsigned long r_sym;
+ unsigned long r_type;
+ unsigned long r_addend;
+};
+
+struct mem_note {
+ unsigned n_type;
+ unsigned n_descsz;
+ const char *n_name;
+ const void *n_desc;
+};
+
+/* The definition of an ELF note does not vary depending
+ * on ELFCLASS.
+ */
+typedef struct
+{
+ uint32_t n_namesz; /* Length of the note's name. */
+ uint32_t n_descsz; /* Length of the note's descriptor. */
+ uint32_t n_type; /* Type of the note. */
+} ElfNN_Nhdr;
+
+
+
+extern void free_elf_info(struct mem_ehdr *ehdr);
+extern int build_elf_info(const char *buf, off_t len, struct mem_ehdr *ehdr);
+extern int build_elf_exec_info(const char *buf, off_t len, struct mem_ehdr *ehdr);
+extern int build_elf_rel_info(const char *buf, off_t len, struct mem_ehdr *ehdr);
+
+extern int elf_exec_load(const struct mem_ehdr *ehdr, struct kexec_info *info);
+extern int elf_rel_load(struct mem_ehdr *ehdr, struct kexec_info *info,
+ unsigned long min, unsigned long max, int end);
+
+extern void elf_exec_build_load(struct kexec_info *info, struct mem_ehdr *ehdr,
+ const char *buf, off_t len);
+extern void elf_rel_build_load(struct kexec_info *info, struct mem_ehdr *ehdr,
+ const char *buf, off_t len, unsigned long min, unsigned long max,
+ int end);
+
+extern int elf_rel_find_symbol(struct mem_ehdr *ehdr,
+ const char *name, struct mem_sym *ret_sym);
+extern unsigned long elf_rel_get_addr(struct mem_ehdr *ehdr, const char *name);
+extern void elf_rel_set_symbol(struct mem_ehdr *ehdr,
+ const char *name, const void *buf, size_t size);
+extern void elf_rel_get_symbol(struct mem_ehdr *ehdr,
+ const char *name, void *buf, size_t size);
+
+uint16_t elf16_to_cpu(const struct mem_ehdr *ehdr, uint16_t value);
+uint32_t elf32_to_cpu(const struct mem_ehdr *ehdr, uint32_t value);
+uint64_t elf64_to_cpu(const struct mem_ehdr *ehdr, uint64_t value);
+
+uint16_t cpu_to_elf16(const struct mem_ehdr *ehdr, uint16_t value);
+uint32_t cpu_to_elf32(const struct mem_ehdr *ehdr, uint32_t value);
+uint64_t cpu_to_elf64(const struct mem_ehdr *ehdr, uint64_t value);
+
+unsigned long elf_max_addr(const struct mem_ehdr *ehdr);
+
+/* Architecture specific helper functions */
+extern int machine_verify_elf_rel(struct mem_ehdr *ehdr);
+extern void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type,
+ void *location, unsigned long address, unsigned long value);
+#endif /* KEXEC_ELF_H */
+
diff --git a/kexec/kexec-sha256.h b/kexec/kexec-sha256.h
new file mode 100644
index 0000000..e0ebfe4
--- /dev/null
+++ b/kexec/kexec-sha256.h
@@ -0,0 +1,11 @@
+#ifndef KEXEC_SHA256_H
+#define KEXEC_SHA256_H
+
+struct sha256_region {
+ const void *start;
+ unsigned long len;
+};
+
+#define SHA256_REGIONS 8
+
+#endif /* KEXEC_SHA256_H */
diff --git a/kexec/kexec-syscall.h b/kexec/kexec-syscall.h
new file mode 100644
index 0000000..7b2670c
--- /dev/null
+++ b/kexec/kexec-syscall.h
@@ -0,0 +1,73 @@
+#ifndef KEXEC_SYSCALL_H
+#define KEXEC_SYSCALL_H
+
+#define __LIBRARY__
+#include <syscall.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#define LINUX_REBOOT_MAGIC1 0xfee1dead
+#define LINUX_REBOOT_MAGIC2 672274793
+#define LINUX_REBOOT_MAGIC2A 85072278
+#define LINUX_REBOOT_MAGIC2B 369367448
+
+#define LINUX_REBOOT_CMD_RESTART 0x01234567
+#define LINUX_REBOOT_CMD_HALT 0xCDEF0123
+#define LINUX_REBOOT_CMD_CAD_ON 0x89ABCDEF
+#define LINUX_REBOOT_CMD_CAD_OFF 0x00000000
+#define LINUX_REBOOT_CMD_POWER_OFF 0x4321FEDC
+#define LINUX_REBOOT_CMD_RESTART2 0xA1B2C3D4
+#define LINUX_REBOOT_CMD_EXEC_KERNEL 0x18273645
+#define LINUX_REBOOT_CMD_KEXEC_OLD 0x81726354
+#define LINUX_REBOOT_CMD_KEXEC_OLD2 0x18263645
+#define LINUX_REBOOT_CMD_KEXEC 0x45584543
+
+#ifdef __i386__
+#define __NR_kexec_load 283
+#endif
+#ifdef __ia64__
+#define __NR_kexec_load 1268
+#endif
+#ifdef __powerpc64__
+#define __NR_kexec_load 268
+#endif
+#ifdef __powerpc__
+#define __NR_kexec_load 268
+#endif
+#ifdef __x86_64__
+#define __NR_kexec_load 246
+#endif
+#ifndef __NR_kexec_load
+#error Unknown processor architecture. Needs a kexec_load syscall number.
+#endif
+
+struct kexec_segment;
+
+static inline long kexec_load(void *entry, unsigned long nr_segments,
+ struct kexec_segment *segments, unsigned long flags)
+{
+ return (long) syscall(__NR_kexec_load, entry, nr_segments, segments, flags);
+}
+
+static inline long kexec_reboot(void)
+{
+ return (long) syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_KEXEC, 0);
+}
+
+
+#define KEXEC_ON_CRASH 0x00000001
+#define KEXEC_ARCH_MASK 0xffff0000
+
+/* These values match the ELF architecture values.
+ * Unless there is a good reason that should continue to be the case.
+ */
+#define KEXEC_ARCH_DEFAULT ( 0 << 16)
+#define KEXEC_ARCH_386 ( 3 << 16)
+#define KEXEC_ARCH_X86_64 (62 << 16)
+#define KEXEC_ARCH_PPC (20 << 16)
+#define KEXEC_ARCH_PPC64 (21 << 16)
+#define KEXEC_ARCH_IA_64 (50 << 16)
+
+#define KEXEC_MAX_SEGMENTS 8
+
+#endif /* KEXEC_SYSCALL_H */
diff --git a/kexec/kexec.8 b/kexec/kexec.8
new file mode 100644
index 0000000..5dcbd80
--- /dev/null
+++ b/kexec/kexec.8
@@ -0,0 +1,45 @@
+.\" Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH KEXEC-TOOLS 8 "October 13, 2004"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh disable hyphenation
+.\" .hy enable hyphenation
+.\" .ad l left justify
+.\" .ad b justify to both left and right margins
+.\" .nf disable filling
+.\" .fi enable filling
+.\" .br insert line break
+.\" .sp <n> insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+kexec-tools \- Tool to load a kernel for warm reboot and initiate a warm reboot
+.SH SYNOPSIS
+.B kexec-tools
+.RI [ options ] " files" ...
+.SH DESCRIPTION
+.PP
+.\" TeX users may be more comfortable with the \fB<whatever>\fP and
+.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
+.\" respectively.
+\fBkexec-tools\fP does not have a man page yet. Please use "kexec -h" for help.
+.SH OPTIONS
+These programs follow the usual GNU command line syntax, with long
+options starting with two dashes (`-').
+A summary of options is included below.
+For a complete description, see the Info files.
+.TP
+.B \-h, \-\-help
+Show summary of options.
+.TP
+.B \-v, \-\-version
+Show version of program.
+.SH SEE ALSO
+.SH AUTHOR
+kexec-tools was written by Eric Biederman.
+.PP
+This manual page was written by Khalid Aziz <khalid_aziz@hp.com>,
+for the Debian project (but may be used by others).
diff --git a/kexec/kexec.c b/kexec/kexec.c
new file mode 100644
index 0000000..3847dbf
--- /dev/null
+++ b/kexec/kexec.c
@@ -0,0 +1,810 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2003-2005 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <getopt.h>
+#ifdef HAVE_ZLIB_H
+#include <zlib.h>
+#endif
+#include <sha256.h>
+#include "kexec.h"
+#include "kexec-syscall.h"
+#include "kexec-elf.h"
+#include "kexec-sha256.h"
+
+static unsigned long long mem_min = 0;
+static unsigned long long mem_max = ULONG_MAX;
+
+void die(char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ fflush(stdout);
+ fflush(stderr);
+ exit(1);
+}
+
+
+void *xmalloc(size_t size)
+{
+ void *buf;
+ buf = malloc(size);
+ if (!buf) {
+ die("Cannot malloc %ld bytes: %s\n",
+ size + 0UL, strerror(errno));
+ }
+ return buf;
+}
+
+void *xrealloc(void *ptr, size_t size)
+{
+ void *buf;
+ buf = realloc(ptr, size);
+ if (!buf) {
+ die("Cannot realloc %ld bytes: %s\n",
+ size + 0UL, strerror(errno));
+ }
+ return buf;
+}
+
+
+/* local variables */
+static struct memory_range *memory_range;
+static int memory_ranges;
+
+int valid_memory_range(unsigned long sstart, unsigned long send)
+{
+ int i;
+ if (sstart > send) {
+ return 0;
+ }
+ if ((send > mem_max) || (sstart < mem_min)) {
+ return 0;
+ }
+ for (i = 0; i < memory_ranges; i++) {
+ unsigned long mstart, mend;
+ /* Only consider memory ranges */
+ if (memory_range[i].type != RANGE_RAM)
+ continue;
+ mstart = memory_range[i].start;
+ mend = memory_range[i].end;
+ /* Check to see if we are fully contained */
+ if ((mstart <= sstart) && (mend >= send)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int valid_memory_segment(struct kexec_segment *segment)
+{
+ unsigned long sstart, send;
+ sstart = (unsigned long)segment->mem;
+ send = sstart + segment->memsz - 1;
+
+ return valid_memory_range(sstart, send);
+}
+
+void print_segments(FILE *f, struct kexec_info *info)
+{
+ int i;
+
+ fprintf(f, "nr_segments = %d\n", info->nr_segments);
+ for (i = 0; i < info->nr_segments; i++) {
+ fprintf(f, "segment[%d].buf = %p\n", i, info->segment[i].buf);
+ fprintf(f, "segment[%d].bufsz = %zx\n", i, info->segment[i].bufsz);
+ fprintf(f, "segment[%d].mem = %p\n", i, info->segment[i].mem);
+ fprintf(f, "segment[%d].memsz = %zx\n", i, info->segment[i].memsz);
+ }
+}
+
+int sort_segments(struct kexec_info *info)
+{
+ int i, j;
+ void *end;
+
+ /* Do a stupid insertion sort... */
+ for (i = 0; i < info->nr_segments; i++) {
+ int tidx;
+ struct kexec_segment temp;
+ tidx = i;
+ for (j = i +1; j < info->nr_segments; j++) {
+ if (info->segment[j].mem < info->segment[tidx].mem) {
+ tidx = j;
+ }
+ }
+ if (tidx != i) {
+ temp = info->segment[tidx];
+ info->segment[tidx] = info->segment[i];
+ info->segment[i] = temp;
+ }
+ }
+ /* Now see if any of the segments overlap */
+ end = 0;
+ for (i = 0; i < info->nr_segments; i++) {
+ if (end > info->segment[i].mem) {
+ fprintf(stderr, "Overlapping memory segments at %p\n",
+ end);
+ return -1;
+ }
+ end = ((char *)info->segment[i].mem) + info->segment[i].memsz;
+ }
+ return 0;
+}
+
+unsigned long locate_hole(struct kexec_info *info,
+ unsigned long hole_size, unsigned long hole_align,
+ unsigned long hole_min, unsigned long hole_max,
+ int hole_end)
+{
+ int i, j;
+ struct memory_range *mem_range;
+ int max_mem_ranges, mem_ranges;
+ unsigned long hole_base;
+
+ if (hole_end == 0) {
+ die("Invalid hole end argument of 0 specified to locate_hole");
+ }
+
+ /* Set an intial invalid value for the hole base */
+ hole_base = ULONG_MAX;
+
+ /* Ensure I have a sane alignment value */
+ if (hole_align == 0) {
+ hole_align = 1;
+ }
+ /* Align everything to at least a page size boundary */
+ if (hole_align < getpagesize()) {
+ hole_align = getpagesize();
+ }
+
+ /* Compute the free memory ranges */
+ max_mem_ranges = memory_ranges + (info->nr_segments -1);
+ mem_range = malloc(max_mem_ranges *sizeof(struct memory_range));
+ mem_ranges = 0;
+
+ /* Perform a merge on the 2 sorted lists of memory ranges */
+ for (j = 0, i = 0; i < memory_ranges; i++) {
+ unsigned long sstart, send;
+ unsigned long mstart, mend;
+ mstart = memory_range[i].start;
+ mend = memory_range[i].end;
+ if (memory_range[i].type != RANGE_RAM)
+ continue;
+ while ((j < info->nr_segments) && (((unsigned long)info->segment[j].mem) <= mend)) {
+ sstart = (unsigned long)info->segment[j].mem;
+ send = sstart + info->segment[j].memsz -1;
+ if (mstart < sstart) {
+ mem_range[mem_ranges].start = mstart;
+ mem_range[mem_ranges].end = sstart -1;
+ mem_range[mem_ranges].type = RANGE_RAM;
+ mem_ranges++;
+ }
+ mstart = send +1;
+ j++;
+ }
+ if (mstart <= mend) {
+ mem_range[mem_ranges].start = mstart;
+ mem_range[mem_ranges].end = mend;
+ mem_range[mem_ranges].type = RANGE_RAM;
+ mem_ranges++;
+ }
+ }
+ /* Now find the end of the last memory_range I can use */
+ for (i = 0; i < mem_ranges; i++) {
+ unsigned long long start, end, size;
+ start = mem_range[i].start;
+ end = mem_range[i].end;
+ /* First filter the range start and end values
+ * through the lens of mem_min, mem_max and hole_align.
+ */
+ if (start < mem_min) {
+ start = mem_min;
+ }
+ if (start < hole_min) {
+ start = hole_min;
+ }
+ start = (start + hole_align - 1) & ~(hole_align - 1);
+ if (end > mem_max) {
+ end = mem_max;
+ }
+ if (end > hole_max) {
+ end = hole_max;
+ }
+ /* Is this still a valid memory range? */
+ if ((start >= end) || (start >= mem_max) || (end <= mem_min)) {
+ continue;
+ }
+ /* Is there enough space left so we can use it? */
+ size = end - start;
+ if (size >= hole_size) {
+ if (hole_end > 0) {
+ hole_base = start;
+ break;
+ } else {
+ hole_base = (end - hole_size) & ~(hole_align - 1);
+ }
+ }
+ }
+ if (hole_base == ULONG_MAX) {
+ fprintf(stderr, "Could not find a free area of memory of %lx bytes...\n",
+ hole_size);
+ return ULONG_MAX;
+ }
+ if ((hole_base + hole_size) > hole_max) {
+ fprintf(stderr, "Could not find a free area of memory below: %lx...\n",
+ hole_max);
+ return ULONG_MAX;
+ }
+ return hole_base;
+}
+
+void add_segment(struct kexec_info *info,
+ const void *buf, size_t bufsz,
+ unsigned long base, size_t memsz)
+{
+ unsigned long last;
+ size_t size;
+ int pagesize;
+
+ if (bufsz > memsz) {
+ bufsz = memsz;
+ }
+ /* Forget empty segments */
+ if (memsz == 0) {
+ return;
+ }
+
+ /* Round memsz up to a multiple of pagesize */
+ pagesize = getpagesize();
+ memsz = (memsz + (pagesize - 1)) & ~(pagesize - 1);
+
+ /* Verify base is pagesize aligned.
+ * Finding a way to cope with this problem
+ * is important but for now error so at least
+ * we are not surprised by the code doing the wrong
+ * thing.
+ */
+ if (base & (pagesize -1)) {
+ die("Base address: %x is not page aligned\n", base);
+ }
+
+ last = base + memsz -1;
+ if (!valid_memory_range(base, last)) {
+ die("Invalid memory segment %p - %p\n",
+ (void *)base, (void *)last);
+ }
+
+ size = (info->nr_segments + 1) * sizeof(info->segment[0]);
+ info->segment = xrealloc(info->segment, size);
+ info->segment[info->nr_segments].buf = buf;
+ info->segment[info->nr_segments].bufsz = bufsz;
+ info->segment[info->nr_segments].mem = (void *)base;
+ info->segment[info->nr_segments].memsz = memsz;
+ info->nr_segments++;
+ if (info->nr_segments > KEXEC_MAX_SEGMENTS) {
+ fprintf(stderr,
+ "Warning: kernel segment limit reached. This will likely fail\n");
+ }
+}
+
+unsigned long add_buffer(struct kexec_info *info,
+ const void *buf, unsigned long bufsz, unsigned long memsz,
+ unsigned long buf_align, unsigned long buf_min, unsigned long buf_max,
+ int buf_end)
+{
+ unsigned long base;
+ int result;
+
+ result = sort_segments(info);
+ if (result < 0) {
+ die("sort_segments failed\n");
+ }
+
+ base = locate_hole(info, memsz, buf_align, buf_min, buf_max, buf_end);
+ if (base == ULONG_MAX) {
+ die("locate_hole failed\n");
+ }
+
+ add_segment(info, buf, bufsz, base, memsz);
+ return base;
+}
+
+char *slurp_file(const char *filename, off_t *r_size)
+{
+ int fd;
+ char *buf;
+ off_t size, progress;
+ ssize_t result;
+ struct stat stats;
+
+
+ if (!filename) {
+ *r_size = 0;
+ return 0;
+ }
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ die("Cannot open `%s': %s\n",
+ filename, strerror(errno));
+ }
+ result = fstat(fd, &stats);
+ if (result < 0) {
+ die("Cannot stat: %s: %s\n",
+ filename, strerror(errno));
+ }
+ size = stats.st_size;
+ *r_size = size;
+ buf = xmalloc(size);
+ progress = 0;
+ while(progress < size) {
+ result = read(fd, buf + progress, size - progress);
+ if (result < 0) {
+ if ((errno == EINTR) || (errno == EAGAIN))
+ continue;
+ die("read on %s of %ld bytes failed: %s\n",
+ filename, (size - progress)+ 0UL, strerror(errno));
+ }
+ progress += result;
+ }
+ result = close(fd);
+ if (result < 0) {
+ die("Close of %s failed: %s\n",
+ filename, strerror(errno));
+ }
+ return buf;
+}
+
+#if HAVE_ZLIB_H
+char *slurp_decompress_file(const char *filename, off_t *r_size)
+{
+ gzFile fp;
+ int errnum;
+ const char *msg;
+ char *buf;
+ off_t size, allocated;
+ ssize_t result;
+
+ if (!filename) {
+ *r_size = 0;
+ return 0;
+ }
+ fp = gzopen(filename, "rb");
+ if (fp == 0) {
+ msg = gzerror(fp, &errnum);
+ if (errnum == Z_ERRNO) {
+ msg = strerror(errno);
+ }
+ die("Cannot open `%s': %s\n", filename, msg);
+ }
+ size = 0;
+ allocated = 65536;
+ buf = xmalloc(allocated);
+ do {
+ if (size == allocated) {
+ allocated <<= 1;
+ buf = xrealloc(buf, allocated);
+ }
+ result = gzread(fp, buf + size, allocated - size);
+ if (result < 0) {
+ if ((errno == EINTR) || (errno == EAGAIN))
+ continue;
+
+ msg = gzerror(fp, &errnum);
+ if (errnum == Z_ERRNO) {
+ msg = strerror(errno);
+ }
+ die ("read on %s of %ld bytes failed: %s\n",
+ filename, (allocated - size) + 0UL, msg);
+ }
+ size += result;
+ } while(result > 0);
+ result = gzclose(fp);
+ if (result != Z_OK) {
+ msg = gzerror(fp, &errnum);
+ if (errnum == Z_ERRNO) {
+ msg = strerror(errno);
+ }
+ die ("Close of %s failed: %s\n", filename, msg);
+ }
+ *r_size = size;
+ return buf;
+}
+#else
+char *slurp_decompress_file(const char *filename, off_t *r_size)
+{
+ return slurp_file(filename, r_size);
+}
+#endif
+
+static void update_purgatory(struct kexec_info *info)
+{
+ static const uint8_t null_buf[256];
+ sha256_context ctx;
+ sha256_digest_t digest;
+ struct sha256_region region[SHA256_REGIONS];
+ int i, j;
+ /* Don't do anything if we are not using purgatory */
+ if (!info->rhdr.e_shdr) {
+ return;
+ }
+ arch_update_purgatory(info);
+ memset(region, 0, sizeof(region));
+ sha256_starts(&ctx);
+ /* Compute a hash of the loaded kernel */
+ for(j = i = 0; i < info->nr_segments; i++) {
+ unsigned long nullsz;
+ /* Don't include purgatory in the checksum. The stack
+ * in the bss will definitely change, and the .data section
+ * will also change when we poke the sha256_digest in there.
+ * A very clever/careful person could probably improve this.
+ */
+ if (info->segment[i].mem == (void *)info->rhdr.rel_addr) {
+ continue;
+ }
+ sha256_update(&ctx, info->segment[i].buf, info->segment[i].bufsz);
+ nullsz = info->segment[i].memsz - info->segment[i].bufsz;
+ while(nullsz) {
+ unsigned long bytes = nullsz;
+ if (bytes > sizeof(null_buf)) {
+ bytes = sizeof(null_buf);
+ }
+ sha256_update(&ctx, null_buf, bytes);
+ nullsz -= bytes;
+ }
+ region[j].start = info->segment[i].mem;
+ region[j].len = info->segment[i].memsz;
+ j++;
+ }
+ sha256_finish(&ctx, digest);
+ elf_rel_set_symbol(&info->rhdr, "sha256_regions", &region, sizeof(region));
+ elf_rel_set_symbol(&info->rhdr, "sha256_digest", &digest, sizeof(digest));
+}
+
+/*
+ * Load the new kernel
+ */
+static int my_load(const char *type, int fileind, int argc, char **argv,
+ unsigned long kexec_flags)
+{
+ char *kernel;
+ char *kernel_buf;
+ off_t kernel_size;
+ int i = 0;
+ int result;
+ struct kexec_info info;
+ int guess_only = 0;
+
+ memset(&info, 0, sizeof(info));
+ info.segment = NULL;
+ info.nr_segments = 0;
+ info.entry = NULL;
+
+ result = 0;
+ if (argc - fileind <= 0) {
+ fprintf(stderr, "No kernel specified\n");
+ usage();
+ return -1;
+ }
+ kernel = argv[fileind];
+ /* slurp in the input kernel */
+ kernel_buf = slurp_decompress_file(kernel, &kernel_size);
+#if 0
+ fprintf(stderr, "kernel: %p kernel_size: %lx\n",
+ kernel_buf, kernel_size);
+#endif
+
+ if (get_memory_ranges(&memory_range, &memory_ranges) < 0) {
+ fprintf(stderr, "Could not get memory layout\n");
+ return -1;
+ }
+ /* if a kernel type was specified, try to honor it */
+ if (type) {
+ for (i = 0; i < file_types; i++) {
+ if (strcmp(type, file_type[i].name) == 0)
+ break;
+ }
+ if (i == file_types) {
+ fprintf(stderr, "Unsupported kernel type %s\n", type);
+ return -1;
+ } else {
+ /* make sure our file is really of that type */
+ if (file_type[i].probe(kernel_buf, kernel_size) < 0)
+ guess_only = 1;
+ }
+ }
+ if (!type || guess_only) {
+ for (i = 0; i < file_types; i++) {
+ if (file_type[i].probe(kernel_buf, kernel_size) >= 0)
+ break;
+ }
+ if (i == file_types) {
+ fprintf(stderr, "Cannot determine the file type "
+ "of %s\n", kernel);
+ return -1;
+ } else {
+ if (guess_only) {
+ fprintf(stderr, "Wrong file type %s, "
+ "file matches type %s\n",
+ type, file_type[i].name);
+ return -1;
+ }
+ }
+ }
+ if (file_type[i].load(argc, argv, kernel_buf, kernel_size, &info) < 0) {
+ fprintf(stderr, "Cannot load %s\n", kernel);
+ return -1;
+ }
+ /* If we are not in native mode setup an appropriate trampoline */
+ if (arch_compat_trampoline(&info, &kexec_flags) < 0) {
+ return -1;
+ }
+ /* Verify all of the segments load to a valid location in memory */
+ for (i = 0; i < info.nr_segments; i++) {
+ if (!valid_memory_segment(info.segment +i)) {
+ fprintf(stderr, "Invalid memory segment %p - %p\n",
+ info.segment[i].mem,
+ ((char *)info.segment[i].mem) +
+ info.segment[i].memsz);
+ return -1;
+ }
+ }
+ /* Sort the segments and verify we don't have overlaps */
+ if (sort_segments(&info) < 0) {
+ return -1;
+ }
+ /* if purgatory is loaded update it */
+ update_purgatory(&info);
+#if 0
+ fprintf(stderr, "kexec_load: entry = %p flags = %lx\n",
+ info.entry, kexec_flags);
+ print_segments(stderr, &info);
+#endif
+ result = kexec_load(
+ info.entry, info.nr_segments, info.segment, kexec_flags);
+ if (result != 0) {
+ /* The load failed, print some debugging information */
+ fprintf(stderr, "kexec_load failed: %s\n",
+ strerror(errno));
+ fprintf(stderr, "entry = %p flags = %lx\n",
+ info.entry, kexec_flags);
+ print_segments(stderr, &info);
+ }
+ return result;
+}
+
+int k_unload (unsigned long kexec_flags)
+{
+ int result;
+
+ result = kexec_load(NULL, 0, NULL, kexec_flags);
+ if (result != 0) {
+ /* The unload failed, print some debugging information */
+ fprintf(stderr, "kexec_load (0 segments) failed: %s\n",
+ strerror(errno));
+ }
+ return result;
+}
+
+/*
+ * Start a reboot.
+ */
+static int my_shutdown(void)
+{
+ char *args[8];
+ int i = 0;
+
+ args[i++] = "shutdown";
+ args[i++] = "-r";
+ args[i++] = "now";
+ args[i++] = NULL;
+
+ execv("/sbin/shutdown", args);
+ execv("/etc/shutdown", args);
+ execv("/bin/shutdown", args);
+
+ perror("shutdown");
+ return -1;
+}
+
+/*
+ * Exec the new kernel (reboot)
+ */
+static int my_exec(void)
+{
+ int result;
+
+ result = kexec_reboot();
+ /* I have failed if I make it here */
+ fprintf(stderr, "kexec failed: %s\n",
+ strerror(errno));
+ return -1;
+}
+
+static void version(void)
+{
+ printf("kexec " VERSION " released " RELEASE_DATE "\n");
+}
+
+void usage(void)
+{
+ int i;
+
+ version();
+ printf(
+ "Usage: kexec [OPTION]... [kernel]\n"
+ "Directly reboot into a new kernel\n"
+ "\n"
+ " -h, --help Print this help.\n"
+ " -v, --version Print the version of kexec.\n"
+ " -f, --force Force an immediate kexec, don't call shutdown.\n"
+ " -x, --no-ifdown Don't bring down network interfaces.\n"
+ " (if used, must be last option specified)\n"
+ " -l, --load Load the new kernel into the current kernel.\n"
+ " -p, --load-panic Load the new kernel for use on panic.\n"
+ " -u, --unload Unload the current kexec target kernel.\n"
+ " -e, --exec Execute a currently loaded kernel.\n"
+ " -t, --type=TYPE Specify the new kernel is of this type.\n"
+ " --mem-min=<addr> Specify the lowest memory addres to load code into.\n"
+ " --mem-max=<addr> Specify the highest memory addres to load code into.\n"
+ "\n"
+ "Supported kernel file types and options: \n"
+ );
+ for (i = 0; i < file_types; i++) {
+ printf("%s\n", file_type[i].name);
+ file_type[i].usage();
+ }
+ printf( "Architecture options: \n");
+ arch_usage();
+ printf("\n");
+}
+
+int main(int argc, char *argv[])
+{
+ int do_load = 1;
+ int do_exec = 0;
+ int do_shutdown = 1;
+ int do_sync = 1;
+ int do_ifdown = 0;
+ int do_unload = 0;
+ unsigned long kexec_flags = 0;
+ char *type = 0;
+ char *endptr;
+ int opt;
+ int result = 0;
+ int fileind;
+ static const struct option options[] = {
+ KEXEC_OPTIONS
+ { 0, 0, 0, 0},
+ };
+ static const char short_options[] = KEXEC_OPT_STR;
+
+ opterr = 0; /* Don't complain about unrecognized options here */
+ while ((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
+ switch(opt) {
+ case OPT_HELP:
+ usage();
+ return 0;
+ case OPT_VERSION:
+ version();
+ return 0;
+ case OPT_NOIFDOWN:
+ do_ifdown = 0;
+ break;
+ case OPT_FORCE:
+ do_load = 1;
+ do_shutdown = 0;
+ do_sync = 1;
+ do_ifdown = 1;
+ do_exec = 1;
+ break;
+ case OPT_LOAD:
+ do_load = 1;
+ do_exec = 0;
+ do_shutdown = 0;
+ break;
+ case OPT_UNLOAD:
+ do_load = 0;
+ do_shutdown = 0;
+ do_sync = 0;
+ do_unload = 1;
+ break;
+ case OPT_EXEC:
+ do_load = 0;
+ do_shutdown = 0;
+ do_sync = 1;
+ do_ifdown = 1;
+ do_exec = 1;
+ break;
+ case OPT_TYPE:
+ type = optarg;
+ break;
+ case OPT_PANIC:
+ do_load = 1;
+ do_exec = 0;
+ do_shutdown = 0;
+ do_sync = 0;
+ kexec_flags = KEXEC_ON_CRASH;
+ break;
+ case OPT_MEM_MIN:
+ mem_min = strtoul(optarg, &endptr, 0);
+ if (*endptr) {
+ fprintf(stderr, "Bad option value in --mem-min=%s\n",
+ optarg);
+ usage();
+ return 1;
+ }
+ break;
+ case OPT_MEM_MAX:
+ mem_max = strtoul(optarg, &endptr, 0);
+ if (*endptr) {
+ fprintf(stderr, "Bad option value in --mem-max=%s\n",
+ optarg);
+ usage();
+ return 1;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ fileind = optind;
+ /* Reset getopt for the next pass; called in other source modules */
+ opterr = 1;
+ optind = 1;
+
+ result = arch_process_options(argc, argv);
+
+ if (do_unload) {
+ result = k_unload(kexec_flags);
+ }
+ if (do_load && (result == 0)) {
+ result = my_load(type, fileind, argc, argv, kexec_flags);
+ }
+ if ((result == 0) && do_shutdown) {
+ result = my_shutdown();
+ }
+ if ((result == 0) && do_sync) {
+ sync();
+ }
+ if ((result == 0) && do_ifdown) {
+ extern int ifdown(void);
+ (void)ifdown();
+ }
+ if ((result == 0) && do_exec) {
+ result = my_exec();
+ }
+
+ fflush(stdout);
+ fflush(stderr);
+ return result;
+}
diff --git a/kexec/kexec.h b/kexec/kexec.h
new file mode 100644
index 0000000..10a95d6
--- /dev/null
+++ b/kexec/kexec.h
@@ -0,0 +1,194 @@
+#ifndef KEXEC_H
+#define KEXEC_H
+
+#include <sys/types.h>
+#include <stdint.h>
+#define USE_BSD
+#include <byteswap.h>
+#include <endian.h>
+#define _GNU_SOURCE
+
+#include "kexec-elf.h"
+
+#ifndef BYTE_ORDER
+#error BYTE_ORDER not defined
+#endif
+
+#ifndef LITTLE_ENDIAN
+#error LITTLE_ENDIAN not defined
+#endif
+
+#ifndef BIG_ENDIAN
+#error BIG_ENDIAN not defined
+#endif
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define cpu_to_le16(val) (val)
+#define cpu_to_le32(val) (val)
+#define cpu_to_le64(val) (val)
+#define cpu_to_be16(val) bswap_16(val)
+#define cpu_to_be32(val) bswap_32(val)
+#define cpu_to_be64(val) bswap_64(val)
+#define le16_to_cpu(val) (val)
+#define le32_to_cpu(val) (val)
+#define le64_to_cpu(val) (val)
+#define be16_to_cpu(val) bswap_16(val)
+#define be32_to_cpu(val) bswap_32(val)
+#define be64_to_cpu(val) bswap_64(val)
+#elif BYTE_ORDER == BIG_ENDIAN
+#define cpu_to_le16(val) bswap_16(val)
+#define cpu_to_le32(val) bswap_32(val)
+#define cpu_to_le64(val) bswap_64(val)
+#define cpu_to_be16(val) (val)
+#define cpu_to_be32(val) (val)
+#define cpu_to_be64(val) (val)
+#define le16_to_cpu(val) bswap_16(val)
+#define le32_to_cpu(val) bswap_32(val)
+#define le64_to_cpu(val) bswap_64(val)
+#define be16_to_cpu(val) (val)
+#define be32_to_cpu(val) (val)
+#define be64_to_cpu(val) (val)
+#else
+#error unknwon BYTE_ORDER
+#endif
+
+
+#if 0
+/*
+ * This function doesn't actually exist. The idea is that when someone uses the macros
+ * below with an unsupported size (datatype), the linker will alert us to the problem via
+ * an unresolved reference error.
+ */
+extern unsigned long bad_unaligned_access_length (void);
+
+#define get_unaligned(loc) \
+({ \
+ __typeof__(*(loc)) value; \
+ size_t size = sizeof(*(loc)); \
+ switch(size) { \
+ case 1: case 2: case 4: case 8: \
+ memcpy(&value, (loc), size); \
+ break; \
+ default: \
+ value = bad_unaligned_access_length(); \
+ break; \
+ } \
+ value; \
+})
+
+#define put_unaligned(value, loc) \
+do { \
+ size_t size = sizeof(*(loc)); \
+ __typeof__(*(loc)) val = value; \
+ switch(size) { \
+ case 1: case 2: case 4: case 8: \
+ memcpy((loc), &val, size); \
+ break; \
+ default: \
+ bad_unaligned_access_length(); \
+ break; \
+ } \
+} while(0)
+#endif
+
+struct kexec_segment {
+ const void *buf;
+ size_t bufsz;
+ const void *mem;
+ size_t memsz;
+};
+
+struct memory_range {
+ unsigned long long start, end;
+ unsigned type;
+#define RANGE_RAM 0
+#define RANGE_RESERVED 1
+#define RANGE_ACPI 2
+#define RANGE_ACPI_NVS 3
+};
+
+struct kexec_info {
+ struct kexec_segment *segment;
+ int nr_segments;
+ void *entry;
+ struct mem_ehdr rhdr;
+};
+
+void usage(void);
+int get_memory_ranges(struct memory_range **range, int *ranges);
+int valid_memory_range(unsigned long sstart, unsigned long send);
+int valid_memory_segment(struct kexec_segment *segment);
+void print_segments(FILE *file, struct kexec_info *info);
+int sort_segments(struct kexec_info *info);
+unsigned long locate_hole(struct kexec_info *info,
+ unsigned long hole_size, unsigned long hole_align,
+ unsigned long hole_min, unsigned long hole_max,
+ int hole_end);
+
+typedef int (probe_t)(const char *kernel_buf, off_t kernel_size);
+typedef int (load_t )(int argc, char **argv,
+ const char *kernel_buf, off_t kernel_size,
+ struct kexec_info *info);
+typedef void (usage_t)(void);
+struct file_type {
+ const char *name;
+ probe_t *probe;
+ load_t *load;
+ usage_t *usage;
+};
+
+extern struct file_type file_type[];
+extern int file_types;
+
+#define OPT_HELP 'h'
+#define OPT_VERSION 'v'
+#define OPT_DEBUG 'd'
+#define OPT_FORCE 'f'
+#define OPT_NOIFDOWN 'x'
+#define OPT_EXEC 'e'
+#define OPT_LOAD 'l'
+#define OPT_UNLOAD 'u'
+#define OPT_TYPE 't'
+#define OPT_PANIC 'p'
+#define OPT_MEM_MIN 256
+#define OPT_MEM_MAX 257
+#define OPT_MAX 258
+#define KEXEC_OPTIONS \
+ { "help", 0, 0, OPT_HELP }, \
+ { "version", 0, 0, OPT_VERSION }, \
+ { "force", 0, 0, OPT_FORCE }, \
+ { "no-ifdown", 0, 0, OPT_NOIFDOWN }, \
+ { "load", 0, 0, OPT_LOAD }, \
+ { "unload", 0, 0, OPT_UNLOAD }, \
+ { "exec", 0, 0, OPT_EXEC }, \
+ { "type", 1, 0, OPT_TYPE }, \
+ { "load-panic", 0, 0, OPT_PANIC }, \
+ { "mem-min", 1, 0, OPT_MEM_MIN }, \
+ { "mem-max", 1, 0, OPT_MEM_MAX }, \
+
+#define KEXEC_OPT_STR "hvdfxluet:p"
+
+extern void die(char *fmt, ...);
+extern void *xmalloc(size_t size);
+extern void *xrealloc(void *ptr, size_t size);
+extern char *slurp_file(const char *filename, off_t *r_size);
+extern char *slurp_decompress_file(const char *filename, off_t *r_size);
+extern void add_segment(struct kexec_info *info,
+ const void *buf, size_t bufsz, unsigned long base, size_t memsz);
+extern unsigned long add_buffer(struct kexec_info *info,
+ const void *buf, unsigned long bufsz, unsigned long memsz,
+ unsigned long buf_align, unsigned long buf_min, unsigned long buf_max,
+ int buf_end);
+
+extern unsigned char purgatory[];
+extern size_t purgatory_size;
+
+#define BOOTLOADER "kexec"
+#define BOOTLOADER_VERSION VERSION
+
+void arch_usage(void);
+int arch_process_options(int argc, char **argv);
+int arch_compat_trampoline(struct kexec_info *info, unsigned long *flags);
+void arch_update_purgatory(struct kexec_info *info);
+
+#endif /* KEXEC_H */
diff --git a/kexec_test/Makefile b/kexec_test/Makefile
new file mode 100644
index 0000000..3e932d5
--- /dev/null
+++ b/kexec_test/Makefile
@@ -0,0 +1,30 @@
+#
+# kexec_test Debugging payload to be certain the infrastructure works
+#
+RELOC:=0x10000
+KEXEC_TEST_S_SRCS:= kexec_test/kexec_test16.S kexec_test/kexec_test.S
+KEXEC_TEST_S_TEMPS:=$(patsubst %.S, $(OBJDIR)/%.s, $(KEXEC_TEST_S_SRCS))
+KEXEC_TEST_S_OBJS:=$(patsubst $(OBJDIR)/%.s, $(OBJDIR)/%.o, $(KEXEC_TEST_S_TEMPS))
+KEXEC_TEST_S_DEPS:=$(patsubst %.S, $(OBJDIR)/%.d, $(KEXEC_TEST_S_SRCS))
+KEXEC_TEST_SRCS:= $(KEXEC_TEST_S_SRCS)
+KEXEC_TEST_OBJS:= $(KEXEC_TEST_S_OBJS)
+KEXEC_TEST_DEPS:= $(KEXEC_TEST_S_DEPS)
+KEXEC_TEST:=$(PKGLIBDIR)/kexec_test
+
+include $(KEXEC_TEST_DEPS)
+
+$(KEXEC_TEST_S_DEPS): $(OBJDIR)/%.d: %.S
+ mkdir -p $(@D)
+ $(CC) -m32 $(CFLAGS) -M $< | sed -e 's|$(patsubst %.d,%.o,$(@F))|$(patsubst %.d,%.o,$(@))|' > $@
+
+$(KEXEC_TEST_S_TEMPS): $(OBJDIR)/%.s: %.S
+ mkdir -p $(@D)
+ $(CPP) $(CPPFLAGS) -DRELOC=$(RELOC) $< > $@
+
+$(KEXEC_TEST_S_OBJS): $(OBJDIR)/%.o: $(OBJDIR)/%.s
+ mkdir -p $(@D)
+ $(AS) --32 -o $@ $<
+
+$(KEXEC_TEST): $(KEXEC_TEST_OBJS)
+ mkdir -p $(@D)
+ $(LD) -m elf_i386 -e _start -Ttext $(RELOC) $(KEXEC_TEST_OBJS) -o $@
diff --git a/kexec_test/kexec_test.S b/kexec_test/kexec_test.S
new file mode 100644
index 0000000..5106c5c
--- /dev/null
+++ b/kexec_test/kexec_test.S
@@ -0,0 +1,475 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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.
+ */
+
+ .equ PROT_CODE_SEG, pmcs - gdt
+ .equ REAL_CODE_SEG, rmcs - gdt
+ .equ PROT_DATA_SEG, pmds - gdt
+ .equ REAL_DATA_SEG, rmds - gdt
+ .equ CR0_PE, 1
+ /* Gas thinks the .equs for these are non-absolute so use a define */
+#define PROT_CODE_SEG 0x08
+#define REAL_CODE_SEG 0x18
+#undef i386
+
+ .text
+ .arch i386
+ .globl _start
+_start:
+ .code32
+ # Disable interrupts
+ cli
+
+ # Save the initial registers
+ movl %eax, orig_eax
+ movl %ebx, orig_ebx
+ movl %ecx, orig_ecx
+ movl %edx, orig_edx
+ movl %esi, orig_esi
+ movl %edi, orig_edi
+ movl %esp, orig_esp
+ movl %ebp, orig_ebp
+
+ # Setup a stack
+ movl $stack_end, %esp
+
+ # Display a message to say everything is working so far
+ pushl $s_hello
+ call print_string
+ addl $4, %esp
+
+ # Save the idt and gdt
+ sidt orig_idtp
+ sgdt orig_gdtp
+
+ # Display the initial register contents
+ call print_orig_regs
+
+ pushl $s_switching_descriptors
+ call print_string
+ addl $4, %esp
+
+ # Load descriptor pointers
+ lgdt gdtp
+ lidt idtp
+ # Reload the data segments
+ movl $PROT_DATA_SEG, %eax
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %ss
+ movl %eax, %fs
+ movl %eax, %gs
+
+ # Reload %cs
+ ljmp $PROT_CODE_SEG, $_start.1
+_start.1:
+
+ pushl $s_descriptors_changed
+ call print_string
+ addl $4, %esp
+
+ call setup_legacy_pic
+ pushl $s_legacy_pic_setup
+ call print_string
+ addl $4, %esp
+
+ call prot_to_real
+ .code16
+
+ callw test16
+
+ /* Return to 32bit mode */
+ data32 call real_to_prot
+ .code32
+ pushl $s_in_protected_mode
+ call print_string
+ addl $4, %esp
+
+ pushl $s_halting
+ call print_string
+ addl $4, %esp
+ jmp halt
+
+
+ /* Go from protected to real mode */
+prot_to_real:
+ .code32
+ /* Load the 16bit idt */
+ lidt idtp_real
+
+ popl %eax
+ subl $RELOC, %eax /* Adjust return address */
+ pushl %eax
+ subl $RELOC, %esp /* Adjust stack pointer */
+ ljmp $REAL_CODE_SEG, $1f - RELOC
+1:
+ .code16
+ /* Reload the segment registers to force a 16bit limit */
+ movw $REAL_DATA_SEG, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %ss
+ movw %ax, %fs
+ movw %ax, %gs
+
+ /* Clear the PE bit of CR0 */
+ movl %cr0, %eax
+ andl $0!CR0_PE, %eax
+ movl %eax, %cr0
+
+ /* make intersegment jmp to flush the processor pipeline
+ * and reload %cs:%eip (to clear upper 16 bits of %eip).
+ */
+ data32 ljmp $(RELOC)>>4,$2f- RELOC
+2:
+ /* we are in real mode now
+ * set up the real mode segment registers
+ */
+ movw %cs,%ax
+ movw %ax,%ds
+ movw %ax,%es
+ movw %ax,%ss
+ movw %ax,%fs
+ movw %ax,%gs
+ data32 ret
+
+real_to_prot:
+ .code16
+ pushl %ebx
+
+ /* Compute the address of gdtp */
+ movw %cs, %ax
+ shlw $4, %ax
+ movl $gdtp, %ebx
+ subw %ax, %bx
+
+ data32 lgdt %cs:(%bx)
+ movl %cr0, %eax
+ orl $CR0_PE, %eax
+ movl %eax, %cr0
+
+ /* flush prefetch queue and reload %cs:%eip */
+ data32 ljmp $PROT_CODE_SEG, $1f
+1:
+ .code32
+ /* reload other segment registers */
+ movl $PROT_DATA_SEG, %eax
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %ss
+ movl %eax, %fs
+ movl %eax, %gs
+
+ popl %ebx /* Restore %ebx */
+
+ addl $RELOC, %esp /* Fix up stack pointer */
+
+ popl %eax /* Fix up return address */
+ addl $RELOC, %eax
+ pushl %eax
+
+ lidt idtp /* Load a dummy idt */
+ ret
+
+
+halt:
+ .code32
+ hlt
+ jmp halt
+
+print_orig_regs:
+ .code32
+ # Display the initial register contents
+ pushl $s_eax
+ call print_string
+ pushl orig_eax
+ call print_hex
+ pushl $space
+ call print_string
+ addl $12, %esp
+
+ pushl $s_ebx
+ call print_string
+ pushl orig_ebx
+ call print_hex
+ pushl $space
+ call print_string
+ addl $12, %esp
+
+
+ pushl $s_ecx
+ call print_string
+ pushl orig_ecx
+ call print_hex
+ pushl $space
+ call print_string
+ addl $12, %esp
+
+
+ pushl $s_edx
+ call print_string
+ pushl orig_edx
+ call print_hex
+ pushl $crlf
+ call print_string
+ addl $12, %esp
+
+
+ pushl $s_esi
+ call print_string
+ pushl orig_esi
+ call print_hex
+ pushl $space
+ call print_string
+ addl $12, %esp
+
+ pushl $s_edi
+ call print_string
+ pushl orig_edi
+ call print_hex
+ pushl $space
+ call print_string
+ addl $12, %esp
+
+
+ pushl $s_esp
+ call print_string
+ pushl orig_esp
+ call print_hex
+ pushl $space
+ call print_string
+ addl $12, %esp
+
+
+ pushl $s_ebp
+ call print_string
+ pushl orig_ebp
+ call print_hex
+ pushl $crlf
+ call print_string
+ addl $12, %esp
+
+ # display the interrupt descritor table pointer
+ pushl $s_idtp
+ call print_string
+ movzwl orig_idtp, %eax
+ pushl %eax
+ call print_hex
+ pushl $space
+ call print_string
+ pushl orig_idt_base
+ call print_hex
+ pushl $crlf
+ call print_string
+ addl $20, %esp
+
+ # display the global descritor table pointer
+ pushl $s_gdtp
+ call print_string
+ movzwl orig_gdtp, %eax
+ pushl %eax
+ call print_hex
+ pushl $space
+ call print_string
+ pushl orig_gdt_base
+ call print_hex
+ pushl $crlf
+ call print_string
+ addl $20, %esp
+
+ ret
+
+
+print_string:
+ .code32
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %esi
+ movl 8(%ebp), %esi
+ xorl %eax, %eax
+print_string.1:
+ lodsb %ds:(%esi), %al
+ testb $0xff, %al
+ jz print_string.2
+ call print_char
+ jmp print_string.1
+print_string.2:
+ popl %esi
+ popl %ebp
+ ret
+
+
+print_hex:
+ .code32
+ pushl %ebp
+ movl %esp, %ebp
+ movb $32, %cl
+print_hex.1:
+ movl 8(%ebp), %eax
+ subb $4, %cl
+ shrl %cl, %eax
+ andb $0x0f, %al
+ cmpb $9, %al
+ ja print_hex.2
+ addb $'0', %al
+ jmp print_hex.3
+print_hex.2:
+ addb $'A' - 10, %al
+print_hex.3:
+ pushl %ecx
+ call print_char
+ popl %ecx
+ testb %cl, %cl
+ jnz print_hex.1
+
+ popl %ebp
+ ret
+
+print_char:
+ .code32
+ # The character to print is in al
+ call serial_print_char
+ retl
+
+
+#define TTYS0_BASE 0x3f8
+#define TTYS0_RBR (TTYS0_BASE + 0x00)
+#define TTYS0_TBR (TTYS0_BASE + 0x00)
+#define TTYS0_LSR (TTYS0_BASE + 0x05)
+serial_print_char:
+ .code32
+ # The character to print is in al
+ pushl %eax
+
+ # Wait until the serial port is ready to receive characters
+serial_print_char.1:
+ movl $TTYS0_LSR, %edx
+ inb %dx, %al
+ testb $0x20, %al
+ jz serial_print_char.1
+
+ # Output the character
+ movl $TTYS0_TBR, %edx
+ movb 0(%esp), %al
+ outb %al, %dx
+
+ # Wait until the serial port has transmitted the character
+serial_print_char.2:
+ movl $TTYS0_LSR, %edx
+ inb %dx, %al
+ testb $0x40, %al
+ jz serial_print_char.2
+
+ # Restore %eax
+ popl %eax
+ # Return to caller
+ ret
+
+ .code32
+
+idtp_real:
+ .word 0x400 # idt limit = 256
+ .word 0, 0
+idtp:
+ .word 0 # idt limit = 0
+ .word 0, 0 # idt base = 0L
+
+gdt:
+gdtp:
+ .word gdt_end - gdt - 1 # gdt limit
+ .long gdt # gdt base
+ .word 0 # dummy
+
+pmcs:
+ # the 32 bit protected mode code segment
+ .word 0xffff,0
+ .byte 0,0x9f,0xcf,0
+
+pmds:
+ # the 32 bit protected mode data segment
+ .word 0xffff,0
+ .byte 0,0x93,0xcf,0
+
+rmcs:
+ # the 16 bit real mode code segment
+ .word 0xffff,(RELOC&0xffff)
+ .byte (RELOC>>16),0x9b,0x00,(RELOC>>24)
+
+rmds:
+ # the 16 bit real mode data segment
+ .word 0xffff,(RELOC&0xffff)
+ .byte (RELOC>>16),0x93,0x00,(RELOC>>24)
+gdt_end:
+
+
+s_hello:
+ .ascii "kexec_test "
+ .ascii VERSION
+ .asciz " starting...\r\n"
+s_switching_descriptors:
+ .asciz "Switching descriptors.\r\n"
+s_descriptors_changed:
+ .asciz "Descriptors changed.\r\n"
+s_legacy_pic_setup:
+ .asciz "Legacy pic setup.\r\n"
+s_in_protected_mode:
+ .asciz "In protected mode.\r\n"
+s_halting:
+ .asciz "Halting.\r\n"
+
+
+space: .asciz " "
+crlf: .asciz "\r\n"
+s_eax: .asciz "eax: "
+s_ebx: .asciz "ebx: "
+s_ecx: .asciz "ecx: "
+s_edx: .asciz "edx: "
+s_esi: .asciz "esi: "
+s_edi: .asciz "edi: "
+s_esp: .asciz "esp: "
+s_ebp: .asciz "ebp: "
+
+
+s_idtp: .asciz "idt: "
+s_gdtp: .asciz "gdt: "
+
+#include "x86-setup-legacy-pic.S"
+
+ .bss
+ .balign 4096
+stack:
+ .skip 4096
+stack_end:
+
+ .bss
+ .balign 4
+orig_eax: .long 0
+orig_ebx: .long 0
+orig_ecx: .long 0
+orig_edx: .long 0
+orig_esi: .long 0
+orig_edi: .long 0
+orig_esp: .long 0
+orig_ebp: .long 0
+
+ .balign 4
+orig_idtp: .short 0
+orig_idt_base: .long 0
+orig_gdtp: .short 0
+orig_gdt_base: .long 0
+
diff --git a/kexec_test/kexec_test16.S b/kexec_test/kexec_test16.S
new file mode 100644
index 0000000..4d37915
--- /dev/null
+++ b/kexec_test/kexec_test16.S
@@ -0,0 +1,1004 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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.
+ */
+
+ .text
+ .code16
+
+ .globl test16
+ .balign 16
+ .globl _start16
+_start16:
+test16:
+ pushw $s_in_real_mode - _start16
+ call print_string16
+ addw $2, %sp
+
+#if 0
+ /* Disable interrupts */
+ movb $0xff, %al
+ outb %al, $0x21
+ outb %al, $0xa1
+#endif
+ /* Enable interrupts, BIOS calls may fail if we don't */
+ sti
+ pushw $s_interrupts_enabled - _start16
+ call print_string16
+ addw $2, %sp
+
+ /* Get the base memory size, via a bios call */
+ /* This is to test BIOS calls more than to achieve anything practical */
+ xorw %ax, %ax
+ int $0x12
+ pushw %ax
+ pushw $s_base_memory_size - _start16
+ call print_string16
+ addw $2, %sp
+ call print_hex16
+ addw $2, %sp
+ pushw $s_crlf - _start16
+ call print_string16
+ addw $2, %sp
+
+
+ /* Some things do not like a20 being enabled so disable it */
+ call disable_a20
+
+ /* Here we test various BIOS calls to determine how much of the system is working */
+ call get_meme820
+ call print_meme820
+ call print_meme801
+ call print_mem88
+ call disable_apm
+ call print_equipment_list
+ call print_sysdesc
+ call print_video
+ call print_cursor
+ call print_video_mode
+ call set_auto_repeat_rate
+ call print_dasd_type
+ call print_edd
+
+ /* Enable a20 */
+ call enable_a20
+ pushw $s_a20_enabled - _start16
+ call print_string16
+ addw $2, %sp
+
+ /* Disable interrupts */
+ cli
+ pushw $s_interrupts_disabled - _start16
+ call print_string16
+ addw $2, %sp
+
+ retw
+
+#
+# Enable A20. This is at the very best an annoying procedure.
+# A20 code ported from SYSLINUX 1.52-1.63 by H. Peter Anvin.
+#
+
+A20_TEST_LOOPS = 32 # Iterations per wait
+A20_ENABLE_LOOPS = 255 # Total loops to try
+A20_DISABLE_LOOPS = 255 # Total loops to try
+
+enable_a20:
+ .code16
+ movb $A20_ENABLE_LOOPS, a20_tries - _start16
+a20_try_loop:
+
+ # First, see if we are on a system with no A20 gate.
+a20_none:
+ call a20_test
+ jnz a20_done
+
+ # Next, try the BIOS (INT 0x15, AX=0x2401)
+a20_bios:
+ movw $0x2401, %ax
+ pushfl # Be paranoid about flags
+ int $0x15
+ popfl
+
+ call a20_test
+ jnz a20_done
+
+ # Try enabling A20 through the keyboard controller
+a20_kbc:
+ call empty_8042
+
+ call a20_test # Just in case the BIOS worked
+ jnz a20_done # but had a delayed reaction.
+
+ movb $0xD1, %al # command write
+ outb %al, $0x64
+ call empty_8042
+
+ movb $0xDF, %al # A20 on
+ outb %al, $0x60
+ call empty_8042
+
+ # Wait until a20 really *is* enabled; it can take a fair amount of
+ # time on certain systems; Toshiba Tecras are known to have this
+ # problem.
+a20_kbc_wait:
+ xorw %cx, %cx
+a20_kbc_wait_loop:
+ call a20_test
+ jnz a20_done
+ loop a20_kbc_wait_loop
+
+ # Final attempt: use "configuration port A"
+a20_fast:
+ inb $0x92, %al # Configuration Port A
+ orb $0x02, %al # "fast A20" version
+ andb $0xFE, %al # dont accidentally reset
+ outb %al, $0x92
+
+ # Wait for configuration port A to take effect
+a20_fast_wait:
+ xorw %cx, %cx
+a20_fast_wait_loop:
+ call a20_test
+ jnz a20_done
+ loop a20_fast_wait_loop
+
+ # A20 is still not responding. Try frobbing it again.
+ #
+ decb (a20_tries - _start16)
+ jnz a20_try_loop
+ jmp a20_die
+
+a20_die:
+ pushw $s_a20_err_msg - _start16
+ call print_string16
+ jmp halt16
+
+ # If we get here, all is good
+a20_done:
+ ret
+
+
+
+# This routine tests whether or not A20 is enabled. If so, it
+# exits with zf = 0.
+#
+# The memory address used, 0x200, is the int $0x80 vector, which
+# should be safe.
+
+A20_TEST_ADDR = 4*0x80
+
+a20_test:
+ .code16
+ pushw %cx
+ pushw %ax
+ xorw %cx, %cx
+ movw %cx, %fs # Low memory
+ decw %cx
+ movw %cx, %gs # High memory area
+ movw $A20_TEST_LOOPS, %cx
+ movw %fs:(A20_TEST_ADDR), %ax
+ pushw %ax
+a20_test_wait:
+ incw %ax
+ movw %ax, %fs:(A20_TEST_ADDR)
+ call delay # Serialize and make delay constant
+ cmpw %gs:(A20_TEST_ADDR+0x10), %ax
+ loope a20_test_wait
+
+ popw %fs:(A20_TEST_ADDR)
+ popw %ax
+ popw %cx
+
+ ret
+
+#
+# Disable A20
+#
+
+disable_a20:
+ .code16
+ movb $A20_DISABLE_LOOPS, a20_disable_tries - _start16
+a20_disable_loop:
+
+ # First see if gate A20 is already disabled
+ call a20_test
+ jz a20_disabled
+
+
+ # Next, try the BIOS (INT 0x15, AX= 0x2400)
+ movw $0x2400, %ax
+ pushfl # Be paranoid about flags
+ int $0x15
+ popfl
+
+ call a20_test
+ jz a20_disabled
+
+ # Try disabling A20 through the keyboard controller
+ call empty_8042
+
+ call a20_test # Just in case the BIOS worked
+ jz a20_disabled # but had a delayed reaction.
+
+ movb $0xD1, %al # command write
+ outb %al, $0x64
+ call empty_8042
+
+ movb $0xDD, %al # A20 off
+ outb %al, $0x60
+ call empty_8042
+
+ # Wait until a20 really *is* disabled
+ xorw %cx, %cx
+a20_kbc_disable_loop:
+ call a20_test
+ jz a20_disabled
+ loop a20_kbc_disable_loop
+
+ # Final attempt: use "configuration port A"
+ inb $0x92, %al # Configuratin Port A
+ andb $0xFD, %al # "fast A20" version
+ andb $0xFE, %al # dont accidentally reset
+ outb %al, $0x92
+
+ # Wait for configuration port A to take affect
+ xorw %cx, %cx
+a20_fast_disable_loop:
+ call a20_test
+ jz a20_disabled
+ loop a20_fast_disable_loop
+
+ # A20 is still not responding. Try it again
+ decb (a20_disable_tries - _start16)
+ jnz a20_disable_loop
+
+ pushw $s_a20_cant_disable - _start16
+ call print_string16
+ addw $2, %sp
+ retw
+
+ # If we get here, all is good
+a20_disabled:
+ pushw $s_a20_disabled - _start16
+ call print_string16
+ addw $2, %sp
+ retw
+
+
+# This routine checks that the keyboard command queue is empty
+# (after emptying the output buffers)
+#
+# Some machines have delusions that the keyboard buffer is always full
+# with no keyboard attached...
+#
+# If there is no keyboard controller, we will usually get 0xff
+# to all the reads. With each IO taking a microsecond and
+# a timeout of 100,000 iterations, this can take about half a
+# second ("delay" == outb to port 0x80). That should be ok,
+# and should also be plenty of time for a real keyboard controller
+# to empty.
+#
+
+empty_8042:
+ .code16
+ pushl %ecx
+ movl $100000, %ecx
+
+empty_8042_loop:
+ decl %ecx
+ jz empty_8042_end_loop
+
+ call delay
+
+ inb $0x64, %al # 8042 status port
+ testb $1, %al # output buffer?
+ jz no_output
+
+ call delay
+ inb $0x60, %al # read it
+ jmp empty_8042_loop
+
+no_output:
+ testb $2, %al # is input buffer full?
+ jnz empty_8042_loop # yes - loop
+empty_8042_end_loop:
+ popl %ecx
+ ret
+
+
+
+
+# method E820H:
+# the memory map from hell. e820h returns memory classified into
+# a whole bunch of different types, and allows memory holes and
+# everything. We scan through this memory map and build a list
+# of the first 32 memory areas, which we return at [E820MAP].
+# This is documented at http://www.teleport.com/~acpi/acpihtml/topic245.htm
+
+#define SMAP 0x534d4150
+#define E820_MAX 32
+#define E820_SIZE 20
+
+get_meme820:
+ .code16
+ pushw %bp
+ movw %sp, %bp
+ pushw %ds
+ pushw %es
+ pushl %esi
+ pushl %edi
+ pushl %ebx
+
+ xorl %eax, %eax
+ movb %al, e820nr - _start16
+ xorl %ebx, %ebx # continuation counter
+ movw $e820_map - _start16, %di # point into the whitelist
+ # so we can have the bios
+ # directly write into it.
+
+jmpe820:
+ movl $0x0000e820, %eax # e820, upper word zeroed
+ movl $SMAP, %edx # ascii SMAP
+ movl $E820_SIZE, %ecx # size of the e820rec
+ pushw %ds # data record.
+ popw %es
+ int $0x15 # make the call
+ jc bail820 # fall to e801 if it fails
+
+ cmpl $SMAP, %eax # check the return is SMAP
+ jne bail820 # fall to e801 if it fails
+
+# cmpl $1, 16(%di) # is this usable memory?
+# jne again820
+
+ # If this is usable memory, we save it by simply advancing %di by
+ # sizeof(e820rec).
+ #
+good820:
+ movb e820nr - _start16, %al # up to 32 entries
+ cmpb $E820_MAX, %al
+ jnl bail820
+
+ incb e820nr - _start16
+ movw %di, %ax
+ addw $20, %ax
+ movw %ax, %di
+again820:
+ cmpl $0, %ebx # check to see if
+ jne jmpe820 # %ebx is set to EOF
+bail820:
+ popl %ebx
+ popl %edi
+ popl %esi
+ popw %es
+ popw %ds
+ popw %bp
+ retw
+
+
+print_meme820:
+ .code16
+ pushw %si
+ xorw %cx, %cx
+ movb (e820nr - _start16), %cl
+ movw $e820_map - _start16, %si
+
+ pushw $s_meme820 - _start16
+ call print_string16
+ addw $2, %sp
+
+print_meme820.1:
+ pushw %cx
+
+ pushw 8(%si)
+ pushw 10(%si)
+ pushw 12(%si)
+ pushw 14(%si)
+ call print_hex16
+ addw $2, %sp
+ call print_hex16
+ addw $2, %sp
+ call print_hex16
+ addw $2, %sp
+ call print_hex16
+ addw $2, %sp
+
+ pushw $s_at - _start16
+ call print_string16
+ addw $2, %sp
+
+ pushw 0(%si)
+ pushw 2(%si)
+ pushw 4(%si)
+ pushw 6(%si)
+ call print_hex16
+ addw $2, %sp
+ call print_hex16
+ addw $2, %sp
+ call print_hex16
+ addw $2, %sp
+ call print_hex16
+ addw $2, %sp
+
+ pushw $s_type - _start16
+ call print_string16
+ addw $2, %sp
+
+ pushw 16(%si)
+ pushw 18(%si)
+ call print_hex16
+ addw $2, %sp
+ call print_hex16
+ addw $2, %sp
+
+ pushw $s_crlf - _start16
+ call print_string16
+ addw $2, %sp
+
+ popw %cx
+ addw $E820_SIZE, %si
+ subw $1, %cx
+ jnz print_meme820.1
+
+ popw %si
+ retw
+
+
+
+print_meme801:
+ .code16
+ pushw %bp
+ movw %sp, %bp
+ pushw %bx
+ pushl $0
+
+# method E801H:
+# memory size is in 1k chunksizes
+
+ stc # fix to work around buggy
+ xorw %cx,%cx # BIOSes which dont clear/set
+ xorw %dx,%dx # carry on pass/error of
+ # e801h memory size call
+ # or merely pass cx,dx though
+ # without changing them.
+ movw $0xe801, %ax
+ int $0x15
+ jc print_meme801.2
+
+ cmpw $0x0, %cx # Kludge to handle BIOSes
+ jne e801usecxdx # which report their extended
+ cmpw $0x0, %dx # memory in AX/BX rather than
+ jne e801usecxdx # CX/DX. The spec I have read
+ movw %ax, %cx # seems to indicate AX/BX
+ movw %bx, %dx # are more reasonable anyway...
+
+e801usecxdx:
+ andl $0xffff, %edx # clear sign extend
+ shll $6, %edx # and go from 64k to 1k chunks
+ movl %edx, -6(%bp) # store extended memory size
+ andl $0xffff, %ecx # clear sign extend
+ addl %ecx, -6(%bp) # and add lower memory into
+
+ pushw $s_meme801 - _start16
+ call print_string16
+ addw $2, %sp
+
+ pushw -6(%bp)
+ pushw -4(%bp)
+ call print_hex16
+ addw $2, %sp
+ call print_hex16
+ addw $2, %sp
+
+ pushw $s_crlf - _start16
+ call print_string16
+ addw $2, %sp
+
+print_meme801.2:
+ addw $4, %sp
+ popw %bx
+ popw %bp
+ retw
+
+print_mem88:
+ .code16
+# Ye Olde Traditional Methode. Returns the memory size (up to 16mb or
+# 64mb, depending on the bios) in ax.
+ movb $0x88, %ah
+ int $0x15
+
+ pushw %ax
+ pushw $s_mem88 - _start16
+ call print_string16
+ addw $2, %sp
+ call print_hex16
+ addw $2, %sp
+ pushw $s_crlf - _start16
+ call print_string16
+ addw $2, %sp
+
+ retw
+
+print_dasd_type:
+ .code16
+ pushw $s_dasd_type - _start16
+ call print_string16
+ addw $2, %sp
+
+ movw $0x1500, %ax
+ movb $0x81, %dl
+ int $0x13
+ jc print_dasd_type.1
+
+ pushw %dx
+ pushw %cx
+ pushw $s_space - _start16
+ pushw %ax
+
+ call print_hex16
+ addw $2, %sp
+ call print_string16
+ addw $2, %sp
+ call print_hex16
+ addw $2, %sp
+ call print_hex16
+ addw $2, %sp
+ jmp print_dasd_type.2
+print_dasd_type.1:
+ pushw $s_none - _start16
+ call print_string16
+ addw $2, %sp
+
+print_dasd_type.2:
+ pushw $s_crlf - _start16
+ call print_string16
+ addw $2, %sp
+
+ retw
+
+print_equipment_list:
+ .code16
+ pushw $s_equipment_list - _start16
+ call print_string16
+ addw $2, %sp
+
+ int $0x11
+ pushw %ax
+ call print_hex16
+ addw $2, %sp
+
+ pushw $s_crlf - _start16
+ call print_string16
+ addw $2, %sp
+
+ retw
+
+print_sysdesc:
+ .code16
+ pushw $s_sysdesc - _start16
+ call print_string16
+ addw $2, %sp
+
+ pushw %es
+ movb $0xc0, %ah
+ stc
+ int $0x15
+ movw %es, %ax
+ popw %es
+ jc print_sysdesc.1
+
+ pushw %bx
+ pushw $s_colon - _start16
+ pushw %ax
+ call print_hex16
+ addw $2, %sp
+ call print_string16
+ addw $2, %sp
+ call print_hex16
+ addw $2, %sp
+ jmp print_sysdesc.2
+
+print_sysdesc.1:
+ pushw $s_none - _start16
+ call print_string16
+ addw $2, %sp
+
+print_sysdesc.2:
+ pushw $s_crlf - _start16
+ call print_string16
+ addw $2, %sp
+
+ retw
+
+print_edd:
+ .code16
+ pushw $s_edd - _start16
+ call print_string16
+ add $2, %sp
+
+ movb $0x80, %dl
+ movb $0x41, %ah # Function 41
+ movw $0x55aa, %bx # magic
+ int $0x13 # make the call
+ jc print_edd.1 # no more BIOS devices
+
+ cmpw $0xAA55, %bx # is magic right?
+ jne print_edd.1 # nope
+
+ pushw $s_ok - _start16
+ call print_string16
+ add $2, %sp
+ jmp print_edd.2
+
+print_edd.1:
+ pushw $s_none - _start16
+ call print_string16
+ add $2, %sp
+
+print_edd.2:
+ pushw $s_crlf - _start16
+ call print_string16
+ addw $2, %sp
+
+ retw
+
+set_auto_repeat_rate:
+ .code16
+ pushw $s_auto_repeat_rate - _start16
+ call print_string16
+ add $2, %sp
+
+# Set the keyboard repeat rate to the max
+ movw $0x0305, %ax
+ xorw %bx, %bx
+ int $0x16
+
+ pushw $s_done - _start16
+ call print_string16
+ add $2, %sp
+
+ retw
+
+print_video:
+ .code16
+ pushw $s_video_type - _start16
+ call print_string16
+ add $2, %sp
+
+ movb $0x12, %ah # Check EGA/VGA
+ movb $0x10, %bl
+ int $0x10
+ movw $s_video_pre_ega - _start16, %cx
+ cmpb $0x10, %bl
+ je print_video.1
+
+ movw $0x1a00, %ax # Check EGA or VGA?
+ int $0x10
+ movw $s_video_vga - _start16, %cx
+ cmpb $0x1a, %al # 1a means VGA...
+ je print_video.1 # anything else is EGA.
+
+ movw $s_video_ega - _start16, %cx
+
+print_video.1:
+ pushw %cx
+ call print_string16
+ addw $2, %sp
+
+ pushw $s_crlf - _start16
+ call print_string16
+ addw $2, %sp
+
+ retw
+
+print_cursor:
+ .code16
+ pushw $s_cursor - _start16
+ call print_string16
+ add $2, %sp
+
+ movb $0x03, %ah # Read cursor position
+ xorb %bh, %bh
+ int $0x10
+
+ xorw %ax, %ax
+ movb %dl, %al
+ pushw %ax
+ pushw $s_space - _start16
+ movb %dh, %al
+ pushw %ax
+
+ call print_hex16
+ add $2, %sp
+ call print_string16
+ add $2, %sp
+ call print_hex16
+ add $2, %sp
+
+ pushw $s_crlf - _start16
+ call print_string16
+ add $2, %sp
+
+ retw
+
+print_video_mode:
+ .code16
+ pushw $s_video_mode - _start16
+ call print_string16
+ add $2, %sp
+
+ movb $0x0f, %ah # Read cursor position
+ int $0x10
+
+ xorb %ah, %ah
+ pushw %ax
+ call print_hex16
+ add $2, %sp
+
+ pushw $s_crlf - _start16
+ call print_string16
+ add $2, %sp
+
+ retw
+
+
+disable_apm:
+ push %bp
+ movw %sp, %bp
+ pushw %bx
+
+ pushw $s_testing_for_apm - _start16
+ call print_string16
+ add $2, %sp
+
+ # check for APM BIOS
+ movw $0x5300, %ax # APM BIOS installation check
+ xorw %bx, %bx
+ int $0x15
+ jc done_apm_bios # error -> no APM BIOS
+
+ cmpw $0x504d, %bx # check for "PM" signature
+ jne done_apm_bios # no signature -> no APM BIOS
+
+ pushw $s_apm_found_disconnecting - _start16
+ call print_string16
+ add $2, %sp
+
+ movw $0x5304, %ax # Disconnect first just in case
+ xorw %bx, %bx
+ int $0x15 # ignore return code
+
+ pushw $s_apm_connecting - _start16
+ call print_string16
+ add $2, %sp
+
+ movw $0x5301, %ax # Real Mode connect
+ xorw %bx, %bx
+ int $0x15
+ jc done_apm_bios # error
+
+ pushw $s_apm_disabling - _start16
+ call print_string16
+ add $2, %sp
+
+ movw $0x5308, %ax # Disable APM
+ mov $0xffff, %bx
+ xorw %cx, %cx
+ int $0x15
+
+ pushw $s_apm_disconnecting - _start16
+ call print_string16
+ add $2, %sp
+
+ movw $0x5304, %ax # Do a final disconnect
+ xorw %bx, %bx
+ int $0x15
+
+done_apm_bios:
+ pushw $s_apm_test_done - _start16
+ call print_string16
+ add $2, %sp
+
+ popw %bx
+ popw %bp
+ retw
+
+
+# Delay is needed after doing I/O
+delay:
+ .code16
+ outb %al,$0x80
+ retw
+
+halt16:
+ .code16
+ hlt
+ jmp halt16
+
+
+print_string16:
+ .code16
+ pushw %bp
+ movw %sp, %bp
+ pushw %si
+ movw 4(%bp), %si
+ xorw %ax, %ax
+print_string16.1:
+ lodsb %ds:(%si), %al
+ testb $0xff, %al
+ jz print_string16.2
+ call print_char16
+ jmp print_string16.1
+print_string16.2:
+ popw %si
+ popw %bp
+ ret
+
+print_hex16:
+ .code16
+ pushw %bp
+ movw %sp, %bp
+ movw $16, %cx
+print_hex16.1:
+ movw 4(%bp), %ax
+ subb $4, %cl
+ shrw %cl, %ax
+ andb $0x0f, %al
+ cmpb $9, %al
+ ja print_hex16.2
+ addb $'0', %al
+ jmp print_hex16.3
+print_hex16.2:
+ addb $'A' - 10, %al
+print_hex16.3:
+ pushw %cx
+ call print_char16
+ popw %cx
+ testb %cl, %cl
+ jnz print_hex16.1
+
+ popw %bp
+ ret
+
+print_char16:
+ .code16
+ # The character to print is in al
+ call serial_print_char16
+ retw
+
+
+#define TTYS0_BASE 0x3f8
+#define TTYS0_RBR (TTYS0_BASE + 0x00)
+#define TTYS0_TBR (TTYS0_BASE + 0x00)
+#define TTYS0_LSR (TTYS0_BASE + 0x05)
+
+serial_print_char16:
+ .code16
+ pushw %bp
+ movw %sp, %bp
+ # The character to print is in al
+ pushw %ax
+
+ # Wait until the serial port is ready to receive characters
+serial_print_char16.1:
+ movw $TTYS0_LSR, %dx
+ inb %dx, %al
+ testb $0x20, %al
+ jz serial_print_char16.1
+
+ # Output the character
+ movw $TTYS0_TBR, %dx
+ movb -2(%bp), %al
+ outb %al, %dx
+
+ # Wait until the serial port has transmitted the character
+serial_print_char16.2:
+ movw $TTYS0_LSR, %dx
+ inb %dx, %al
+ testb $0x40, %al
+ jz serial_print_char16.2
+
+ # Restore %eax
+ popw %ax
+ # Return to caller
+ popw %bp
+ retw
+
+
+s_a20_err_msg:
+ .asciz "A20 gate not responding!\r\n"
+
+s_in_real_mode:
+ .asciz "In real mode.\r\n"
+s_base_memory_size:
+ .asciz "Base memory size: "
+s_interrupts_enabled:
+ .asciz "Interrupts enabled.\r\n"
+s_a20_disabled:
+ .asciz "A20 disabled.\r\n"
+s_a20_cant_disable:
+ .asciz "Can not A20 line.\r\n"
+s_a20_enabled:
+ .asciz "A20 enabled\r\n"
+s_interrupts_disabled:
+ .asciz "Interrupts disabled.\r\n"
+
+s_meme820: .asciz "E820 Memory Map.\r\n"
+s_at: .asciz " @ "
+s_type: .asciz " type: "
+s_space: .asciz " "
+s_colon: .asciz ":"
+s_none: .asciz " none "
+s_ok: .asciz " ok "
+s_done: .asciz " done\r\n"
+
+s_meme801:
+ .asciz "E801 Memory size: "
+s_mem88:
+ .asciz "Mem88 Memory size: "
+
+s_dasd_type:
+ .asciz "DASD type: "
+s_equipment_list:
+ .asciz "Equiptment list: "
+s_sysdesc:
+ .asciz "Sysdesc: "
+s_edd:
+ .asciz "EDD: "
+s_auto_repeat_rate:
+ .asciz "Setting auto repeat rate "
+
+
+s_video_type:
+ .asciz "Video type: "
+s_video_pre_ega:
+ .asciz "CGA/MDA/HGA"
+s_video_ega:
+ .asciz "EGA"
+s_video_vga:
+ .asciz "VGA"
+
+s_cursor:
+ .asciz "Cursor Position(Row,Column): "
+
+s_video_mode:
+ .asciz "Video Mode: "
+
+s_testing_for_apm:
+ .asciz "Testing for APM.\r\n"
+s_apm_found_disconnecting:
+ .asciz "APM Found disconnecting.\r\n"
+s_apm_connecting:
+ .asciz "APM connecting.\r\n"
+s_apm_disabling:
+ .asciz "APM disabling.\r\n"
+s_apm_disconnecting:
+ .asciz "APM disconnecting.\r\n"
+s_apm_test_done:
+ .asciz "APM test done.\r\n"
+
+s_crlf: .asciz "\r\n"
+
+
+
+a20_tries: .byte A20_ENABLE_LOOPS
+a20_disable_tries: .byte A20_DISABLE_LOOPS
+
+
+e820nr: .byte 0
+e820_map: .fill E820_MAX * E820_SIZE, 1, 0
diff --git a/kexec_test/x86-setup-legacy-pic.S b/kexec_test/x86-setup-legacy-pic.S
new file mode 100644
index 0000000..32ef42f
--- /dev/null
+++ b/kexec_test/x86-setup-legacy-pic.S
@@ -0,0 +1,53 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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.
+ */
+
+ .text
+ .code32
+setup_legacy_pic:
+ /* Load the legacy dos settings into the 8259A pic */
+ movb $0xff, %al
+ outb %al, $0x21 /* mask all of 8259A-1 */
+ outb %al, $0xa1 /* mask all of 8259A-1 */
+
+ movb $0x11, %al
+ outb %al, $0x20 /* ICW1: select 8259A-1 init */
+ outb %al, $0x80 /* A short delay */
+ movb $0x08, %al
+ outb %al, $0x21 /* ICW2: 8259A-1 IR0-7 mappend to 0x8-0xf */
+ outb %al, $0x80 /* A short delay */
+ movb $01, %al
+ outb %al, $0x21 /* Normal 8086 auto EOI mode */
+ outb %al, $0x80 /* A short delay */
+
+
+ movb $0x11, %al
+ outb %al, $0xA0 /* ICW1: select 8259A-2 init */
+ outb %al, $0x80 /* A short delay */
+ movb $0x70, %al
+ outb %al, $0xA1 /* ICW2: 8259A-2 IR0-7 mappend to 0x70-0x77 */
+ outb %al, $0x80 /* A short delay */
+ movb $01, %al
+ outb %al, $0xA1 /* Normal 8086 auto EOI mode */
+ outb %al, $0x80 /* A short delay */
+
+ movb $0, %al
+ outb %al, $0x21 /* Unmask all of 8259A-1 */
+ outb %al, $0xa1 /* Unmask all of 8259A-2 */
+
+ ret
diff --git a/purgatory/Makefile b/purgatory/Makefile
new file mode 100644
index 0000000..93f5830
--- /dev/null
+++ b/purgatory/Makefile
@@ -0,0 +1,68 @@
+#
+# Purgatory (an uncomfortable intermediate state)
+# In this case the code that runs between kernels
+#
+
+# There is probably a cleaner way to do this but for now this
+# should keep us from accidentially include unsafe library functions
+# or headers.
+PCFLAGS:=-Wall -Os \
+ -I$(shell $(CC) -print-file-name=include) \
+ -Ipurgatory/include -Ipurgatory/arch/$(ARCH)/include \
+ $(CPPFLAGS)
+
+PCFLAGS += $(call cc-option, -ffreestanding)
+PCFLAGS += $(call cc-option, -fnobuiltin)
+PCFLAGS += $(call cc-option, -fnostdinc)
+PCFLAGS += $(call cc-option, -fno-zero-initialized-in-bss)
+
+PURGATORY_C_SRCS:=
+PURGATORY_C_SRCS += purgatory/purgatory.c
+PURGATORY_C_SRCS += purgatory/printf.c
+PURGATORY_C_SRCS += purgatory/string.c
+PURGATORY_S_OBJS:=
+
+include purgatory/arch/$(ARCH)/Makefile
+
+
+PURGATORY_C_OBJS:= $(patsubst %.c, $(OBJDIR)/%.o, $(PURGATORY_C_SRCS))
+PURGATORY_C_DEPS:= $(patsubst %.c, $(OBJDIR)/%.d, $(PURGATORY_C_SRCS))
+PURGATORY_S_OBJS:= $(patsubst %.S, $(OBJDIR)/%.o, $(PURGATORY_S_SRCS))
+PURGATORY_S_DEPS:= $(patsubst %.S, $(OBJDIR)/%.d, $(PURGATORY_S_SRCS))
+PURGATORY_SRCS:= $(PURGATORY_S_SRCS) $(PURGATORY_C_SRCS)
+PURGATORY_OBJS:= $(PURGATORY_S_OBJS) $(PURGATORY_C_OBJS)
+PURGATORY_DEPS:= $(PURGATORY_S_DEPS) $(PURGATORY_C_DEPS)
+PURGATORY:= $(OBJDIR)/purgatory/purgatory.ro
+
+include $(PURGATORY_DEPS)
+
+$(PURGATORY_C_DEPS): $(OBJDIR)/%.d: %.c
+ $(MKDIR) -p $(@D)
+ $(CC) $(PCFLAGS) -M $< | sed -e 's|$(patsubst %.d,%.o,$(@F))|$(patsubst %.d,%.o,$(@))|' > $@
+
+$(PURGATORY_S_DEPS): $(OBJDIR)/%.d: %.S
+ $(MKDIR) -p $(@D)
+ $(CC) $(PCFLAGS) -M $< | sed -e 's|$(patsubst %.d,%.o,$(@F))|$(patsubst %.d,%.o,$(@))|' > $@
+
+$(PURGATORY_C_OBJS): $(OBJDIR)/%.o: %.c $(OBJDIR)/%.d
+ $(MKDIR) -p $(@D)
+ $(CC) $(PCFLAGS) -o $@ -c $<
+
+$(PURGATORY_S_OBJS): $(OBJDIR)/%.o: %.S $(OBJDIR)/%.d
+ $(MKDIR) -p $(@D)
+ $(CC) $(PCFLAGS) -o $@ -c $<
+
+$(PURGATORY): $(PURGATORY_OBJS) $(UTIL_LIB)
+ $(MKDIR) -p $(@D)
+ $(LD) $(LDFLAGS) --no-undefined -e purgatory_start -r -o $@ $(PURGATORY_OBJS) $(UTIL_LIB)
+
+echo::
+ @echo "PURGATORY_C_SRCS $(PURGATORY_C_SRCS)"
+ @echo "PURGATORY_C_DEPS $(PURGATORY_C_DEPS)"
+ @echo "PURGATORY_C_OBJS $(PURGATORY_C_OBJS)"
+ @echo "PURGATORY_S_SRCS $(PURGATORY_S_SRCS)"
+ @echo "PURGATORY_S_DEPS $(PURGATORY_S_DEPS)"
+ @echo "PURGATORY_S_OBJS $(PURGATORY_S_OBJS)"
+ @echo "PURGATORY_SRCS $(PURGATORY_SRCS)"
+ @echo "PURGATORY_DEPS $(PURGATORY_DEPS)"
+ @echo "PURGATORY_OBJS $(PURGATORY_OBJS)"
diff --git a/purgatory/arch/alpha/Makefile b/purgatory/arch/alpha/Makefile
new file mode 100644
index 0000000..a626bbd
--- /dev/null
+++ b/purgatory/arch/alpha/Makefile
@@ -0,0 +1,7 @@
+#
+# Purgatory alpha
+#
+
+PURGATORY_C_SRCS+=
+PURGATORY_S_SRCS+=
+
diff --git a/purgatory/arch/alpha/include/limits.h b/purgatory/arch/alpha/include/limits.h
new file mode 100644
index 0000000..0c6f21f
--- /dev/null
+++ b/purgatory/arch/alpha/include/limits.h
@@ -0,0 +1,57 @@
+#ifndef LIMITS_H
+#define LIMITS_H 1
+
+/* Number of bits in a `char' */
+#define CHAR_BIT 8
+
+/* Minimum and maximum values a `signed char' can hold */
+#define SCHAR_MIN (-128)
+#define SCHAR_MAX 127
+
+/* Maximum value an `unsigned char' can hold. (Minimum is 0.) */
+#define UCHAR_MAX 255
+
+/* Minimum and maximum values a `char' can hold */
+#define CHAR_MIN SCHAR_MIN
+#define CHAR_MAX SCHAR_MAX
+
+/* Minimum and maximum values a `signed short int' can hold */
+#define SHRT_MIN (-32768)
+#define SHRT_MAX 32767
+
+/* Maximum value an `unsigned short' can hold. (Minimum is 0.) */
+#define USHRT_MAX 65535
+
+
+/* Minimum and maximum values a `signed int' can hold */
+#define INT_MIN (-INT_MAX - 1)
+#define INT_MAX 2147483647
+
+/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */
+#define UINT_MAX 4294967295U
+
+
+/* Minimum and maximum values a `signed int' can hold */
+#define INT_MIN (-INT_MAX - 1)
+#define INT_MAX 2147483647
+
+/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */
+#define UINT_MAX 4294967295U
+
+/* Minimum and maximum values a `signed long' can hold */
+#define LONG_MAX 9223372036854775807L
+#define LONG_MIN (-LONG_MAX - 1L)
+
+/* Maximum value an `unsigned long' can hold. (Minimum is 0.) */
+#define ULONG_MAX 18446744073709551615UL
+
+/* Minimum and maximum values a `signed long long' can hold */
+#define LLONG_MAX 9223372036854775807LL
+#define LLONG_MIN (-LONG_MAX - 1LL)
+
+
+/* Maximum value an `unsigned long long' can hold. (Minimum is 0.) */
+#define ULLONG_MAX 18446744073709551615ULL
+
+
+#endif /* LIMITS_H */
diff --git a/purgatory/arch/alpha/include/stdint.h b/purgatory/arch/alpha/include/stdint.h
new file mode 100644
index 0000000..2f9c592
--- /dev/null
+++ b/purgatory/arch/alpha/include/stdint.h
@@ -0,0 +1,16 @@
+#ifndef STDINT_H
+#define STDINT_H
+
+typedef unsigned long size_t;
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long uint64_t;
+
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed int int32_t;
+typedef signed long int64_t;
+
+#endif /* STDINT_H */
diff --git a/purgatory/arch/i386/Makefile b/purgatory/arch/i386/Makefile
new file mode 100644
index 0000000..8af604c
--- /dev/null
+++ b/purgatory/arch/i386/Makefile
@@ -0,0 +1,14 @@
+#
+# Purgatory i386
+#
+
+PURGATORY_S_SRCS+= purgatory/arch/i386/entry32-16.S
+PURGATORY_S_SRCS+= purgatory/arch/i386/entry32-16-debug.S
+PURGATORY_S_SRCS+= purgatory/arch/i386/entry32.S
+PURGATORY_S_SRCS+= purgatory/arch/i386/setup-x86.S
+PURGATORY_S_SRCS+= purgatory/arch/i386/stack.S
+PURGATORY_S_SRCS+= purgatory/arch/i386/compat_x86_64.S
+PURGATORY_C_SRCS+= purgatory/arch/i386/purgatory-x86.c
+PURGATORY_C_SRCS+= purgatory/arch/i386/console-x86.c
+PURGATORY_C_SRCS+= purgatory/arch/i386/vga.c
+PURGATORY_C_SRCS+= purgatory/arch/i386/pic.c
diff --git a/purgatory/arch/i386/compat_x86_64.S b/purgatory/arch/i386/compat_x86_64.S
new file mode 100644
index 0000000..1649085
--- /dev/null
+++ b/purgatory/arch/i386/compat_x86_64.S
@@ -0,0 +1,100 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2003,2004,2005 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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.
+ */
+
+ .equ MSR_K6_EFER, 0xC0000080
+ .equ EFER_LME, 0x00000100
+ .equ X86_CR4_PAE, 0x00000020
+ .equ CR0_PG, 0x80000000
+
+ .globl compat_x86_64, compat_x86_64_entry32
+ .text
+ .code64
+ .balign 16
+compat_x86_64:
+ /* Setup a temporary gdt */
+ /* This also acts as a serializing instruction ensuring
+ * my self modifying code works.
+ */
+ lgdt gdt(%rip)
+
+ /* Switch to 32bit compatiblity mode */
+ ljmp *lm_exit_addr(%rip)
+lm_exit:
+ .code32
+
+ /* Disable paging */
+ movl %cr0, %eax
+ andl $~CR0_PG, %eax
+ movl %eax, %cr0
+
+ /* Disable long mode */
+ movl $MSR_K6_EFER, %ecx
+ rdmsr
+ andl $~EFER_LME, %eax
+ wrmsr
+
+ /* Disable PAE */
+ xorl %eax, %eax
+ movl %eax, %cr4
+
+ /* load the data segments */
+ movl $0x18, %eax /* data segment */
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %ss
+ movl %eax, %fs
+ movl %eax, %gs
+
+ /* set all of the registers to known values */
+ /* leave %esp alone */
+
+ xorl %eax, %eax
+ xorl %ebx, %ebx
+ xorl %ecx, %ecx
+ xorl %edx, %edx
+ xorl %esi, %esi
+ xorl %edi, %edi
+ xorl %ebp, %ebp
+
+ jmp *compat_x86_64_entry32
+
+ .section ".rodata"
+ .balign 16
+gdt: /* 0x00 unusable segment
+ * 0x08 unused
+ * so use them as the gdt ptr
+ */
+ .word gdt_end - gdt - 1
+ # A quad word pointer to the gdt with the high 32bits 0
+ .long gdt, 0
+ .word 0, 0, 0
+
+ /* 0x10 4GB flat code segment */
+ .word 0xFFFF, 0x0000, 0x9A00, 0x00CF
+ /* 0x18 4GB flat data segment */
+ .word 0xFFFF, 0x0000, 0x9200, 0x00CF
+gdt_end:
+
+lm_exit_addr:
+ .long lm_exit
+ .long 0x10
+
+compat_x86_64_entry32:
+ .long 0
+.size compat_x86_64_entry32, . - compat_x86_64_entry32
diff --git a/purgatory/arch/i386/console-x86.c b/purgatory/arch/i386/console-x86.c
new file mode 100644
index 0000000..128f202
--- /dev/null
+++ b/purgatory/arch/i386/console-x86.c
@@ -0,0 +1,134 @@
+#include <arch/io.h>
+#include <purgatory.h>
+
+/*
+ * VGA
+ * =============================================================================
+ */
+
+/* Simple VGA output */
+
+#define VGABASE ((void *)0xb8000)
+
+#define MAX_YPOS 25
+#define MAX_XPOS 80
+
+static int current_ypos = 1, current_xpos = 0;
+uint8_t console_vga = 0;
+
+static void putchar_vga(int ch)
+{
+ int i, k, j;
+ if (!console_vga)
+ return;
+
+ if (current_ypos >= MAX_YPOS) {
+ /* scroll 1 line up */
+ for (k = 1, j = 0; k < MAX_YPOS; k++, j++) {
+ for (i = 0; i < MAX_XPOS; i++) {
+ writew(readw(VGABASE + 2*(MAX_XPOS*k + i)),
+ VGABASE + 2*(MAX_XPOS*j + i));
+ }
+ }
+ for (i = 0; i < MAX_XPOS; i++)
+ writew(0x720, VGABASE + 2*(MAX_XPOS*j + i));
+ current_ypos = MAX_YPOS-1;
+ }
+ if (ch == '\n') {
+ current_xpos = 0;
+ current_ypos++;
+ } else if (ch != '\r') {
+ writew(((0x7 << 8) | (unsigned short) ch),
+ VGABASE + 2*(MAX_XPOS*current_ypos +
+ current_xpos++));
+ if (current_xpos >= MAX_XPOS) {
+ current_xpos = 0;
+ current_ypos++;
+ }
+ }
+}
+
+/*
+ * Serial
+ * =============================================================================
+ */
+
+/* Base Address */
+uint8_t console_serial = 0;
+uint16_t serial_base = 0x3f8; /* TTYS0 */
+uint32_t serial_baud = 0;
+
+#define XMTRDY 0x20
+
+#define DLAB 0x80
+
+#define TXR 0 /* Transmit register (WRITE) */
+#define TBR 0 /* Transmit register (WRITE) */
+#define RXR 0 /* Receive register (READ) */
+#define IER 1 /* Interrupt Enable */
+#define IIR 2 /* Interrupt ID */
+#define FCR 2 /* FIFO control */
+#define LCR 3 /* Line control */
+#define MCR 4 /* Modem control */
+#define LSR 5 /* Line Status */
+#define MSR 6 /* Modem Status */
+#define DLL 0 /* Divisor Latch Low */
+#define DLH 1 /* Divisor latch High */
+
+static void serial_init(void)
+{
+ static int initialized = 0;
+ if (!initialized) {
+ unsigned lcr;
+ outb(0x3, serial_base + LCR); /* 8n1 */
+ outb(0, serial_base + IER); /* no interrupt */
+ outb(0, serial_base + FCR); /* no fifo */
+ outb(0x3, serial_base + MCR); /* DTR + RTS */
+
+ lcr = inb(serial_base + LCR);
+ outb(lcr | DLAB, serial_base + LCR);
+ /* By default don't change the serial port baud rate */
+ if (serial_baud) {
+ unsigned divisor = 115200 / serial_baud;
+ outb(divisor & 0xff, serial_base + DLL);
+ outb((divisor >> 8) & 0xff, serial_base + DLH);
+ }
+ outb(lcr & ~DLAB, serial_base + LCR);
+ initialized = 1;
+ }
+}
+
+static void serial_tx_byte(unsigned byte)
+{
+ /* Ensure the serial port is initialized */
+ serial_init();
+
+ /* Wait until I can send a byte */
+ while((inb(serial_base + LSR) & 0x20) == 0)
+ ;
+ outb(byte, serial_base + TBR);
+ /* Wait until the byte is transmitted */
+ while(!(inb(serial_base + LSR) & 0x40))
+ ;
+}
+
+static void putchar_serial(int ch)
+{
+ if (!console_serial) {
+ return;
+ }
+ if (ch == '\n') {
+ serial_tx_byte('\r');
+ }
+ serial_tx_byte(ch);
+}
+
+/* Generic wrapper function */
+
+void putchar(int ch)
+{
+ putchar_vga(ch);
+ putchar_serial(ch);
+}
+
+
diff --git a/purgatory/arch/i386/entry16.S b/purgatory/arch/i386/entry16.S
new file mode 100644
index 0000000..c4a3dad
--- /dev/null
+++ b/purgatory/arch/i386/entry16.S
@@ -0,0 +1,160 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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.
+ */
+
+#undef i386
+ .text
+ .globl entry16, entry16_regs
+ .arch i386
+ .balign 16
+entry16:
+ .code32
+ /* Compute where I am running at */
+ movl $entry16, %ebx
+
+ /* Fixup my real mode segment */
+ movl %ebx, %eax
+ shrl $4, %eax
+ movw %ax, 2 + realptr
+
+ /* Fixup the gdt */
+ movl %ebx, %eax
+ shll $16, %eax
+
+ movl %ebx, %ecx
+ shrl $16, %ecx
+ andl $0xff, %ecx
+
+ movl %ebx, %edx
+ andl $0xff000000, %edx
+ orl %edx, %ecx
+
+ orl %eax, 0x08 + gdt
+ orl %ecx, 0x0c + gdt
+ orl %eax, 0x10 + gdt
+ orl %ecx, 0x14 + gdt
+
+
+ /* Setup the classic BIOS interrupt table at 0x0 */
+ lidt idtptr
+
+ /* Provide us with 16bit segments that we can use */
+ lgdt gdt
+
+ /* Note we don't disable the a20 line, (this shouldn't be required)
+ * The code to do it is in kexec_test and it is a real pain.
+ * I will worry about that when I need it.
+ */
+
+ /* Load 16bit data segments, to ensure the segment limits are set */
+ movl $0x10, %eax
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %ss
+ movl %eax, %fs
+ movl %eax, %gs
+
+ /* switch to 16bit mode */
+ ljmp $0x08, $1f - entry16
+1:
+ .code16
+ /* Disable Paging and protected mode */
+ /* clear the PG & PE bits of CR0 */
+ movl %cr0,%eax
+ andl $~((1 << 31)|(1<<0)),%eax
+ movl %eax,%cr0
+
+ /* make intersegment jmp to flush the processor pipeline
+ * and reload %cs:%eip (to clear upper 16 bits of %eip).
+ */
+ ljmp *(realptr - entry16)
+3:
+ /* we are in real mode now
+ * set up the real mode segment registers : %ds, $ss, %es
+ */
+ /* Setup the data segment */
+ movw %cs, %ax
+ movw %ax, %ds
+
+ /* Load the registers */
+ movl eax - entry16, %eax
+ movl ebx - entry16, %ebx
+ movl ecx - entry16, %ecx
+ movl edx - entry16, %edx
+ movl esi - entry16, %esi
+ movl edi - entry16, %esi
+ movl esp - entry16, %esp
+ movl ebp - entry16, %ebp
+ movw es - entry16, %es
+ movw ss - entry16, %ss
+ movw fs - entry16, %fs
+ movw gs - entry16, %gs
+ movw ds - entry16, %ds
+
+ /* Jump to the kernel entrypoint */
+ ljmp %cs:*(realdest - entry16)
+
+ .balign 4
+entry16_regs:
+eax: .long 0x00000000
+ebx: .long 0x00000000
+ecx: .long 0x00000000
+edx: .long 0x00000000
+esi: .long 0x00000000
+edi: .long 0x00000000
+esp: .long 0x00000000
+ebp: .long 0x00000000
+ds: .word 0x0000
+es: .word 0x0000
+ss: .word 0x0000
+fs: .word 0x0000
+gs: .word 0x0000
+realdest:
+ip: .word 0x0000
+cs: .word 0x0000
+pad: .word 0x0000
+ .size entry16_regs, . - entry16_regs
+
+ .balign 16
+realptr:
+ .word 3b - entry16
+ .word 0x0000
+
+ .data
+ .balign 16
+
+idtptr:
+ /* 256 entry idt at 0 */
+ .word 0x400 - 1
+ .word 0, 0
+
+ .balign 16
+gdt:
+ /* 0x00 unusable segment so used as the gdt ptr */
+ .word gdt_end - gdt - 1
+ .long gdt
+ .word 0
+
+ /* 0x08 16 bit real mode code segment */
+ .word 0xffff, 0x0000
+ .byte 0x00, 0x9b, 0x00, 0x00
+
+ /* 0x10 16 bit real mode data segment */
+ .word 0xffff, 0x0000
+ .byte 0x00, 0x93, 0x00, 0x00
+gdt_end:
diff --git a/purgatory/arch/i386/entry32-16-debug.S b/purgatory/arch/i386/entry32-16-debug.S
new file mode 100644
index 0000000..fdf70ed
--- /dev/null
+++ b/purgatory/arch/i386/entry32-16-debug.S
@@ -0,0 +1,195 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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 "arch/debug.h"
+
+#undef i386
+ .text
+ .globl entry16_debug, entry16_debug_regs
+ .globl entry16_debug_pre32
+ .globl entry16_debug_first32
+ .globl entry16_debug_old_first32
+ .arch i386
+ .balign 16
+entry16_debug:
+ .code32
+ /* Compute where I am running at */
+ movl $entry16_debug, %ebx
+
+ /* Fixup my real mode segment */
+ movl %ebx, %eax
+ shrl $4, %eax
+ movw %ax, 2 + realptr
+
+ /* Fixup the gdt */
+ movl %ebx, %eax
+ shll $16, %eax
+
+ movl %ebx, %ecx
+ shrl $16, %ecx
+ andl $0xff, %ecx
+
+ movl %ebx, %edx
+ andl $0xff000000, %edx
+ orl %edx, %ecx
+
+ orl %eax, 0x08 + gdt
+ orl %ecx, 0x0c + gdt
+ orl %eax, 0x10 + gdt
+ orl %ecx, 0x14 + gdt
+
+
+DEBUG('a')
+ /* Setup the classic BIOS interrupt table at 0x0 */
+ lidt idtptr
+
+DEBUG('b')
+ /* Provide us with 16bit segments that we can use */
+ lgdt gdt
+
+DEBUG('c')
+ /* Note we don't disable the a20 line, (this shouldn't be required)
+ * The code to do it is in kexec_test and it is a real pain.
+ * I will worry about that when I need it.
+ */
+
+ /* Load 16bit data segments, to ensure the segment limits are set */
+ movl $0x10, %eax
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %ss
+ movl %eax, %fs
+ movl %eax, %gs
+
+DEBUG('d')
+
+ /* switch to 16bit mode */
+ ljmp $0x08, $1f - entry16_debug
+1:
+ .code16
+DEBUG('e')
+ /* Disable Paging and protected mode */
+ /* clear the PG & PE bits of CR0 */
+ movl %cr0,%eax
+ andl $~((1 << 31)|(1<<0)),%eax
+ movl %eax,%cr0
+
+DEBUG('f')
+ /* make intersegment jmp to flush the processor pipeline
+ * and reload %cs:%eip (to clear upper 16 bits of %eip).
+ */
+ ljmp *(realptr - entry16_debug)
+3:
+DEBUG('g')
+ /* we are in real mode now
+ * set up the real mode segment registers : %ds, $ss, %es
+ */
+ /* Setup the data segment */
+ movw %cs, %ax
+ movw %ax, %ds
+
+DEBUG('h')
+ /* Load the registers */
+ movl eax - entry16_debug, %eax
+ movl ebx - entry16_debug, %ebx
+ movl ecx - entry16_debug, %ecx
+ movl edx - entry16_debug, %edx
+ movl esi - entry16_debug, %esi
+ movl edi - entry16_debug, %esi
+ movl esp - entry16_debug, %esp
+ movl ebp - entry16_debug, %ebp
+ movw es - entry16_debug, %es
+ movw ss - entry16_debug, %ss
+ movw fs - entry16_debug, %fs
+ movw gs - entry16_debug, %gs
+ movw ds - entry16_debug, %ds
+
+ /* Jump to the kernel entrypoint */
+ ljmp %cs:*(realdest - entry16_debug)
+
+ .balign 4
+entry16_debug_regs:
+eax: .long 0x00000000
+ebx: .long 0x00000000
+ecx: .long 0x00000000
+edx: .long 0x00000000
+esi: .long 0x00000000
+edi: .long 0x00000000
+esp: .long 0x00000000
+ebp: .long 0x00000000
+ds: .word 0x0000
+es: .word 0x0000
+ss: .word 0x0000
+fs: .word 0x0000
+gs: .word 0x0000
+realdest:
+ip: .word 0x0000
+cs: .word 0x0000
+pad: .word 0x0000
+ .size entry16_debug_regs, . - entry16_debug_regs
+
+ .balign 16
+realptr:
+ .word 3b - entry16_debug
+ .word 0x0000
+
+ .data
+ .balign 16
+
+idtptr:
+ /* 256 entry idt at 0 */
+ .word 0x400 - 1
+ .word 0, 0
+
+gdt:
+ /* 0x00 unusable segment so used as the gdt ptr */
+ .word gdt_end - gdt - 1
+ .long gdt
+ .word 0
+
+ /* 0x08 16 bit real mode code segment */
+ .word 0xffff, 0x0000
+ .byte 0x00, 0x9b, 0x00, 0x00
+
+ /* 0x10 16 bit real mode data segment */
+ .word 0xffff, 0x0000
+ .byte 0x00, 0x93, 0x00, 0x00
+gdt_end:
+ .size gdt, . - gdt
+
+ .text
+entry16_debug_pre32:
+ .code16
+DEBUG('i')
+ cli # no interrupts allowed !
+ movb $0x80, %al # disable NMI for bootup
+ # sequence
+ outb %al, $0x70
+ lret
+.size entry16_debug_pre32, . - entry16_debug_pre32
+
+entry16_debug_first32:
+ .code32
+DEBUG('j')
+ .byte 0xb8 /* movl $0x10000, %eax */
+entry16_debug_old_first32:
+ .long 0x100000
+ .size entry16_debug_old_first32, . - entry16_debug_old_first32
+ jmp %eax
+.size entry16_debug_first32, . - entry16_debug_first32
diff --git a/purgatory/arch/i386/entry32-16.S b/purgatory/arch/i386/entry32-16.S
new file mode 100644
index 0000000..a37fb55
--- /dev/null
+++ b/purgatory/arch/i386/entry32-16.S
@@ -0,0 +1,160 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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.
+ */
+
+#undef i386
+ .text
+ .globl entry16, entry16_regs
+ .arch i386
+ .balign 16
+entry16:
+ .code32
+ /* Compute where I am running at */
+ movl $entry16_debug, %ebx
+
+ /* Fixup my real mode segment */
+ movl %ebx, %eax
+ shrl $4, %eax
+ movw %ax, 2 + realptr
+
+ /* Fixup the gdt */
+ movl %ebx, %eax
+ shll $16, %eax
+
+ movl %ebx, %ecx
+ shrl $16, %ecx
+ andl $0xff, %ecx
+
+ movl %ebx, %edx
+ andl $0xff000000, %edx
+ orl %edx, %ecx
+
+ orl %eax, 0x08 + gdt
+ orl %ecx, 0x0c + gdt
+ orl %eax, 0x10 + gdt
+ orl %ecx, 0x14 + gdt
+
+
+ /* Setup the classic BIOS interrupt table at 0x0 */
+ lidt idtptr
+
+ /* Provide us with 16bit segments that we can use */
+ lgdt gdt
+
+ /* Note we don't disable the a20 line, (this shouldn't be required)
+ * The code to do it is in kexec_test and it is a real pain.
+ * I will worry about that when I need it.
+ */
+
+ /* Load 16bit data segments, to ensure the segment limits are set */
+ movl $0x10, %eax
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %ss
+ movl %eax, %fs
+ movl %eax, %gs
+
+ /* switch to 16bit mode */
+ ljmp $0x08, $1f - entry16
+1:
+ .code16
+ /* Disable Paging and protected mode */
+ /* clear the PG & PE bits of CR0 */
+ movl %cr0,%eax
+ andl $~((1 << 31)|(1<<0)),%eax
+ movl %eax,%cr0
+
+ /* make intersegment jmp to flush the processor pipeline
+ * and reload %cs:%eip (to clear upper 16 bits of %eip).
+ */
+ ljmp *(realptr - entry16)
+3:
+ /* we are in real mode now
+ * set up the real mode segment registers : %ds, $ss, %es
+ */
+ /* Setup the data segment */
+ movw %cs, %ax
+ movw %ax, %ds
+
+ /* Load the registers */
+ movl eax - entry16, %eax
+ movl ebx - entry16, %ebx
+ movl ecx - entry16, %ecx
+ movl edx - entry16, %edx
+ movl esi - entry16, %esi
+ movl edi - entry16, %esi
+ movl esp - entry16, %esp
+ movl ebp - entry16, %ebp
+ movw es - entry16, %es
+ movw ss - entry16, %ss
+ movw fs - entry16, %fs
+ movw gs - entry16, %gs
+ movw ds - entry16, %ds
+
+ /* Jump to the kernel entrypoint */
+ ljmp %cs:*(realdest - entry16)
+
+ .balign 4
+entry16_regs:
+eax: .long 0x00000000
+ebx: .long 0x00000000
+ecx: .long 0x00000000
+edx: .long 0x00000000
+esi: .long 0x00000000
+edi: .long 0x00000000
+esp: .long 0x00000000
+ebp: .long 0x00000000
+ds: .word 0x0000
+es: .word 0x0000
+ss: .word 0x0000
+fs: .word 0x0000
+gs: .word 0x0000
+realdest:
+ip: .word 0x0000
+cs: .word 0x0000
+pad: .word 0x0000
+ .size entry16_regs, . - entry16_regs
+
+ .balign 16
+realptr:
+ .word 3b - entry16
+ .word 0x0000
+
+ .data
+ .balign 16
+
+idtptr:
+ /* 256 entry idt at 0 */
+ .word 0x400 - 1
+ .word 0, 0
+
+ .balign 16
+gdt:
+ /* 0x00 unusable segment so used as the gdt ptr */
+ .word gdt_end - gdt - 1
+ .long gdt
+ .word 0
+
+ /* 0x08 16 bit real mode code segment */
+ .word 0xffff, 0x0000
+ .byte 0x00, 0x9b, 0x00, 0x00
+
+ /* 0x10 16 bit real mode data segment */
+ .word 0xffff, 0x0000
+ .byte 0x00, 0x93, 0x00, 0x00
+gdt_end:
diff --git a/purgatory/arch/i386/entry32.S b/purgatory/arch/i386/entry32.S
new file mode 100644
index 0000000..f7a494f
--- /dev/null
+++ b/purgatory/arch/i386/entry32.S
@@ -0,0 +1,110 @@
+/*
+ * purgatory: setup code
+ *
+ * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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.
+ */
+
+#undef i386
+
+ .text
+ .arch i386
+ .globl entry32, entry32_regs
+entry32:
+ .code32
+
+ /* Setup a gdt that should that is generally usefully */
+ lgdt %cs:gdt
+
+ /* load the data segments */
+ movl $0x18, %eax /* data segment */
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %ss
+ movl %eax, %fs
+ movl %eax, %gs
+
+ /* load the code segment */
+ ljmp $0x10,$1f
+1:
+
+ /* Load the registers */
+ movl eax, %eax
+ movl ecx, %ecx
+ movl edx, %edx
+ movl esi, %esi
+ movl edi, %edi
+ movl esp, %esp
+ movl ebp, %ebp
+ movl ebx, %ebx
+
+ /* Jump to the loaded image */
+ jmpl *(eip)
+
+ .section ".rodata"
+ .balign 16
+gdt:
+ /* 0x00 unusable segment so used as the gdt ptr */
+ .word gdt_end - gdt - 1
+ .long gdt
+ .word 0
+
+ /* 0x08 dummy */
+ .word 0x0000, 0x0000, 0x0000, 0x000
+
+ /* Documented linux kernel segments */
+ /* 0x10 4GB flat code segment */
+ .word 0xFFFF, 0x0000, 0x9A00, 0x00CF
+ /* 0x18 4GB flat data segment */
+ .word 0xFFFF, 0x0000, 0x9200, 0x00CF
+
+ /* 0x20 dummy */
+ .word 0x0000, 0x0000, 0x0000, 0x000
+ /* 0x28 dummy */
+ .word 0x0000, 0x0000, 0x0000, 0x000
+ /* 0x30 dummy */
+ .word 0x0000, 0x0000, 0x0000, 0x000
+ /* 0x38 dummy */
+ .word 0x0000, 0x0000, 0x0000, 0x000
+ /* 0x40 dummy */
+ .word 0x0000, 0x0000, 0x0000, 0x000
+ /* 0x48 dummy */
+ .word 0x0000, 0x0000, 0x0000, 0x000
+ /* 0x50 dummy */
+ .word 0x0000, 0x0000, 0x0000, 0x000
+ /* 0x58 dummy */
+ .word 0x0000, 0x0000, 0x0000, 0x000
+
+ /* Segments used by the 2.5.x kernel */
+ /* 0x60 4GB flat code segment */
+ .word 0xFFFF, 0x0000, 0x9A00, 0x00CF
+ /* 0x68 4GB flat data segment */
+ .word 0xFFFF, 0x0000, 0x9200, 0x00CF
+gdt_end:
+
+ .data
+ .balign 4
+entry32_regs:
+eax: .long 0x00000000
+ebx: .long 0x00000000
+ecx: .long 0x00000000
+edx: .long 0x00000000
+esi: .long 0x00000000
+edi: .long 0x00000000
+esp: .long 0x00000000
+ebp: .long 0x00000000
+eip: .long entry16
+ .size entry32_regs, . - entry32_regs
+
diff --git a/purgatory/arch/i386/include/arch/debug.h b/purgatory/arch/i386/include/arch/debug.h
new file mode 100644
index 0000000..69deaf1
--- /dev/null
+++ b/purgatory/arch/i386/include/arch/debug.h
@@ -0,0 +1,316 @@
+/* Base Address */
+#define TTYS0_BASE 0x3f8
+/* Data */
+#define TTYS0_RBR (TTYS0_BASE+0x00)
+#define TTYS0_TBR (TTYS0_BASE+0x00)
+/* Control */
+#define TTYS0_IER (TTYS0_BASE+0x01)
+#define TTYS0_IIR (TTYS0_BASE+0x02)
+#define TTYS0_FCR (TTYS0_BASE+0x02)
+#define TTYS0_LCR (TTYS0_BASE+0x03)
+#define TTYS0_MCR (TTYS0_BASE+0x04)
+
+#define TTYS0_DLL (TTYS0_BASE+0x00)
+#define TTYS0_DLM (TTYS0_BASE+0x01)
+/* Status */
+#define TTYS0_LSR (TTYS0_BASE+0x05)
+#define TTYS0_MSR (TTYS0_BASE+0x06)
+#define TTYS0_SCR (TTYS0_BASE+0x07)
+
+#define TTYS0_BAUD 9600
+#define TTYS0_DIV (115200/TTYS0_BAUD)
+#define TTYS0_DIV_LO (TTYS0_DIV&0xFF)
+#define TTYS0_DIV_HI ((TTYS0_DIV >> 8)&0xFF)
+
+#if ((115200%TTYS0_BAUD) != 0)
+#error Bad ttyS0 baud rate
+#endif
+
+#define TTYS0_INIT \
+ /* disable interrupts */ \
+ movb $0x00, %al ; \
+ movw $TTYS0_IER, %dx ; \
+ outb %al, %dx ; \
+ ; \
+ /* enable fifos */ \
+ movb $0x01, %al ; \
+ movw $TTYS0_FCR, %dx ; \
+ outb %al, %dx ; \
+ ; \
+ /* Set Baud Rate Divisor to TTYS0_BAUD */ \
+ movw $TTYS0_LCR, %dx ; \
+ movb $0x83, %al ; \
+ outb %al, %dx ; \
+ ; \
+ movw $TTYS0_DLL, %dx ; \
+ movb $TTYS0_DIV_LO, %al ; \
+ outb %al, %dx ; \
+ ; \
+ movw $TTYS0_DLM, %dx ; \
+ movb $TTYS0_DIV_HI, %al ; \
+ outb %al, %dx ; \
+ ; \
+ movw $TTYS0_LCR, %dx ; \
+ movb $0x03, %al ; \
+ outb %al, %dx
+
+
+ /* uses: ax, dx */
+#define TTYS0_TX_AL \
+ mov %al, %ah ; \
+9: mov $TTYS0_LSR, %dx ; \
+ inb %dx, %al ; \
+ test $0x20, %al ; \
+ je 9b ; \
+ mov $TTYS0_TBR, %dx ; \
+ mov %ah, %al ; \
+ outb %al, %dx
+
+ /* uses: ax, dx */
+#define TTYS0_TX_CHAR(byte) \
+ mov byte, %al ; \
+ TTYS0_TX_AL
+
+ /* uses: eax, dx */
+#define TTYS0_TX_HEX32(lword) \
+ mov lword, %eax ; \
+ shr $28, %eax ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ shr $24, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ shr $20, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ shr $16, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ shr $12, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ shr $8, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ shr $4, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL
+
+ /* uses: rax, dx */
+#define TTYS0_TX_HEX64(lword) \
+ mov lword, %rax ; \
+ shr $60, %rax ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $56, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $52, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $48, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $44, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $40, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $36, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $32, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $28, %rax ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $24, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $20, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $16, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $12, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $8, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $4, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL
+
+
+#define DEBUG(x) TTYS0_TX_CHAR($x) ; TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
+#define DEBUG_TX_HEX32(x) TTYS0_TX_HEX32(x); TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
+#define DEBUG_TX_HEX64(x) TTYS0_TX_HEX64(x); TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
diff --git a/purgatory/arch/i386/include/arch/io.h b/purgatory/arch/i386/include/arch/io.h
new file mode 100644
index 0000000..13ad887
--- /dev/null
+++ b/purgatory/arch/i386/include/arch/io.h
@@ -0,0 +1,98 @@
+#ifndef ARCH_IO_H
+#define ARCH_IO_H
+
+#include <stdint.h>
+/* Helper functions for directly doing I/O */
+
+extern inline uint8_t inb(uint16_t port)
+{
+ uint8_t result;
+
+ __asm__ __volatile__ (
+ "inb %w1,%0"
+ :"=a" (result)
+ :"Nd" (port));
+ return result;
+}
+
+extern inline uint16_t inw(uint16_t port)
+{
+ uint16_t result;
+
+ __asm__ __volatile__ (
+ "inw %w1,%0"
+ :"=a" (result)
+ :"Nd" (port));
+ return result;
+}
+
+extern inline uint32_t inl(uint32_t port)
+{
+ uint32_t result;
+
+ __asm__ __volatile__ (
+ "inl %w1,%0"
+ :"=a" (result)
+ :"Nd" (port));
+ return result;
+}
+
+extern inline void outb (uint8_t value, uint16_t port)
+{
+ __asm__ __volatile__ (
+ "outb %b0,%w1"
+ :
+ :"a" (value), "Nd" (port));
+}
+
+extern inline void outw (uint16_t value, uint16_t port)
+{
+ __asm__ __volatile__ (
+ "outw %w0,%w1"
+ :
+ :"a" (value), "Nd" (port));
+}
+
+extern inline void outl (uint32_t value, uint16_t port)
+{
+ __asm__ __volatile__ (
+ "outl %0,%w1"
+ :
+ :"a" (value), "Nd" (port));
+}
+
+
+/*
+ * readX/writeX() are used to access memory mapped devices. On some
+ * architectures the memory mapped IO stuff needs to be accessed
+ * differently. On the x86 architecture, we just read/write the
+ * memory location directly.
+ */
+
+static inline unsigned char readb(const volatile void *addr)
+{
+ return *(volatile unsigned char *) addr;
+}
+static inline unsigned short readw(const volatile void *addr)
+{
+ return *(volatile unsigned short *) addr;
+}
+static inline unsigned int readl(const volatile void *addr)
+{
+ return *(volatile unsigned int *) addr;
+}
+
+static inline void writeb(unsigned char b, volatile void *addr)
+{
+ *(volatile unsigned char *) addr = b;
+}
+static inline void writew(unsigned short b, volatile void *addr)
+{
+ *(volatile unsigned short *) addr = b;
+}
+static inline void writel(unsigned int b, volatile void *addr)
+{
+ *(volatile unsigned int *) addr = b;
+}
+
+#endif /* ARCH_IO_H */
diff --git a/purgatory/arch/i386/include/limits.h b/purgatory/arch/i386/include/limits.h
new file mode 100644
index 0000000..d5a5a02
--- /dev/null
+++ b/purgatory/arch/i386/include/limits.h
@@ -0,0 +1,58 @@
+#ifndef LIMITS_H
+#define LIMITS_H 1
+
+
+/* Number of bits in a `char' */
+#define CHAR_BIT 8
+
+/* Minimum and maximum values a `signed char' can hold */
+#define SCHAR_MIN (-128)
+#define SCHAR_MAX 127
+
+/* Maximum value an `unsigned char' can hold. (Minimum is 0.) */
+#define UCHAR_MAX 255
+
+/* Minimum and maximum values a `char' can hold */
+#define CHAR_MIN SCHAR_MIN
+#define CHAR_MAX SCHAR_MAX
+
+/* Minimum and maximum values a `signed short int' can hold */
+#define SHRT_MIN (-32768)
+#define SHRT_MAX 32767
+
+/* Maximum value an `unsigned short' can hold. (Minimum is 0.) */
+#define USHRT_MAX 65535
+
+
+/* Minimum and maximum values a `signed int' can hold */
+#define INT_MIN (-INT_MAX - 1)
+#define INT_MAX 2147483647
+
+/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */
+#define UINT_MAX 4294967295U
+
+
+/* Minimum and maximum values a `signed int' can hold */
+#define INT_MIN (-INT_MAX - 1)
+#define INT_MAX 2147483647
+
+/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */
+#define UINT_MAX 4294967295U
+
+/* Minimum and maximum values a `signed long' can hold */
+#define LONG_MAX 2147483647L
+#define LONG_MIN (-LONG_MAX - 1L)
+
+/* Maximum value an `unsigned long' can hold. (Minimum is 0.) */
+#define ULONG_MAX 4294967295UL
+
+/* Minimum and maximum values a `signed long long' can hold */
+#define LLONG_MAX 9223372036854775807LL
+#define LLONG_MIN (-LONG_MAX - 1LL)
+
+
+/* Maximum value an `unsigned long long' can hold. (Minimum is 0.) */
+#define ULLONG_MAX 18446744073709551615ULL
+
+
+#endif /* LIMITS_H */
diff --git a/purgatory/arch/i386/include/stdint.h b/purgatory/arch/i386/include/stdint.h
new file mode 100644
index 0000000..79262c2
--- /dev/null
+++ b/purgatory/arch/i386/include/stdint.h
@@ -0,0 +1,16 @@
+#ifndef STDINT_H
+#define STDINT_H
+
+typedef unsigned long size_t;
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed int int32_t;
+typedef signed long long int64_t;
+
+#endif /* STDINT_H */
diff --git a/purgatory/arch/i386/linux-entry16.S b/purgatory/arch/i386/linux-entry16.S
new file mode 100644
index 0000000..f366a11
--- /dev/null
+++ b/purgatory/arch/i386/linux-entry16.S
@@ -0,0 +1,623 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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.
+ */
+
+#if 1
+#define TTYS0_BASE 0x3f8
+#define TTYS0_RBR (TTYS0_BASE+0x00)
+#define TTYS0_TBR TTYS0_RBR
+#define TTYS0_LSR (TTYS0_BASE+0x05)
+
+
+ /* uses: ax, dx */
+#define TTYS0_TX_AL \
+ mov %al, %ah ; \
+9: mov $TTYS0_LSR, %dx ; \
+ inb %dx, %al ; \
+ test $0x20, %al ; \
+ je 9b ; \
+ mov $TTYS0_TBR, %dx ; \
+ mov %ah, %al ; \
+ outb %al, %dx ; \
+9: mov $TTYS0_LSR, %dx ; \
+ inb %dx, %al ; \
+ test $0x40, %al ; \
+ jz 9b
+
+
+
+ /* uses: ax, dx */
+#define TTYS0_TX_CHAR(byte) \
+ mov byte, %al ; \
+ TTYS0_TX_AL
+
+ /* uses: ax, dx */
+#define TTYS0_TX_HEX32(lword) \
+ mov lword, %eax ; \
+ shr $28, %eax ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ shr $24, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ shr $20, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ shr $16, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ shr $12, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ shr $8, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ shr $4, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL
+
+
+#define DEBUG(x) TTYS0_TX_CHAR($x) ; TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
+#define DEBUG_TX_HEX32(x) TTYS0_TX_HEX32(x) ; TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
+#else
+#define DEBUG(x)
+#define DEBUG_TX_HEX32(x)
+#endif
+
+#undef i386
+ .text
+ .globl entry16, entry16_regs
+ .arch i386
+ .balign 16
+entry16:
+ .code32
+
+DEBUG('a')
+ /* Setup the classic BIOS interrupt table at 0x0 */
+ lidt idtptr
+
+DEBUG('b')
+ /* Provide us with 16bit segments that we can use */
+ lgdt gdt
+
+DEBUG('c')
+ /* Note we don't disable the a20 line, (this shouldn't be required)
+ * The code to do it is in kexec_test and it is a real pain.
+ * I will worry about that when I need it.
+ */
+
+ /* Load 16bit data segments, to ensure the segment limits are set */
+ movl $0x10, %eax
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %ss
+ movl %eax, %fs
+ movl %eax, %gs
+
+DEBUG('d')
+
+ /* switch to 16bit mode */
+ ljmp $0x08, $1f - entry16
+1:
+ .code16
+DEBUG('e')
+ /* Disable Paging and protected mode */
+ /* clear the PG & PE bits of CR0 */
+ movl %cr0,%eax
+ andl $~((1 << 31)|(1<<0)),%eax
+ movl %eax,%cr0
+
+DEBUG('f')
+ /* make intersegment jmp to flush the processor pipeline
+ * and reload %cs:%eip (to clear upper 16 bits of %eip).
+ */
+ ljmp *(realptr - entry16)
+3:
+DEBUG('g')
+ /* we are in real mode now
+ * set up the real mode segment registers : %ds, $ss, %es
+ */
+ /* Setup the data segment */
+ movw %cs, %ax
+ movw %ax, %ds
+
+DEBUG('h')
+ /* Load the registers */
+ movl eax - entry16, %eax
+ movl ebx - entry16, %ebx
+ movl ecx - entry16, %ecx
+ movl edx - entry16, %edx
+ movl esi - entry16, %esi
+ movl edi - entry16, %esi
+ movl esp - entry16, %esp
+ movl ebp - entry16, %ebp
+ movw es - entry16, %es
+ movw ss - entry16, %ss
+ movw fs - entry16, %fs
+ movw gs - entry16, %gs
+ movw ds - entry16, %ds
+
+ /* Jump to the kernel entrypoint */
+ ljmp %cs:*(realdest - entry16)
+
+ .balign 4
+entry16_regs:
+eax: .long 0x00000000
+ebx: .long 0x00000000
+ecx: .long 0x00000000
+edx: .long 0x00000000
+esi: .long 0x00000000
+edi: .long 0x00000000
+esp: .long 0x00000000
+ebp: .long 0x00000000
+ds: .word 0x0000
+es: .word 0x0000
+ss: .word 0x0000
+fs: .word 0x0000
+gs: .word 0x0000
+realdest:
+ip: .word 0x0000
+cs: .word 0x0000
+ .size entry16_regs, . - entry16_regs
+
+ .balign 16
+realptr:
+ .word 3b - entry16
+ .word 0x0000
+
+ .data
+ .balign 4
+
+idtptr:
+ /* 256 entry idt at 0 */
+ .word 0x400 - 1
+ .word 0, 0
+
+gdt:
+ /* 0x00 unusable segment so used as the gdt ptr */
+ .word gdt_end - gdt - 1
+ .long gdt
+ .word 0
+
+ /* 0x08 16 bit real mode code segment */
+ .word 0xffff, 0x0000
+ .byte 0x00, 0x9b, 0x00, 0x00
+
+ /* 0x10 16 bit real mode data segment */
+ .word 0xffff, 0x0000
+ .byte 0x00, 0x93, 0x00, 0x00
+gdt_end:
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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.
+ */
+
+#if 1
+#define TTYS0_BASE 0x3f8
+#define TTYS0_RBR (TTYS0_BASE+0x00)
+#define TTYS0_TBR TTYS0_RBR
+#define TTYS0_LSR (TTYS0_BASE+0x05)
+
+
+ /* uses: ax, dx */
+#define TTYS0_TX_AL \
+ mov %al, %ah ; \
+9: mov $TTYS0_LSR, %dx ; \
+ inb %dx, %al ; \
+ test $0x20, %al ; \
+ je 9b ; \
+ mov $TTYS0_TBR, %dx ; \
+ mov %ah, %al ; \
+ outb %al, %dx ; \
+9: mov $TTYS0_LSR, %dx ; \
+ inb %dx, %al ; \
+ test $0x40, %al ; \
+ jz 9b
+
+
+
+ /* uses: ax, dx */
+#define TTYS0_TX_CHAR(byte) \
+ mov byte, %al ; \
+ TTYS0_TX_AL
+
+ /* uses: ax, dx */
+#define TTYS0_TX_HEX32(lword) \
+ mov lword, %eax ; \
+ shr $28, %eax ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ shr $24, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ shr $20, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ shr $16, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ shr $12, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ shr $8, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ shr $4, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL
+
+
+#define DEBUG(x) TTYS0_TX_CHAR($x) ; TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
+#define DEBUG_TX_HEX32(x) TTYS0_TX_HEX32(x) ; TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
+#else
+#define DEBUG(x)
+#define DEBUG_TX_HEX32(x)
+#endif
+
+.data
+ .globl setup16_debug_start, setup16_debug_end, setup16_debug_size, setup16_debug_align
+ .globl setup16_debug_regs
+ .globl setup16_debug_kernel_pre_protected
+ .globl setup16_debug_first_code32
+ .globl setup16_debug_old_code32
+setup16_debug_start:
+_reloc = .
+ .balign 16
+ .code32
+DEBUG('a')
+ /* Compute where I am running at */
+ call 1f
+1: popl %ebx
+ subl $(1b - _reloc), %ebx
+
+ /* Remember where I am running at */
+ movl %ebx, location - _reloc(%ebx)
+
+DEBUG('b')
+ /* Fixup my real mode segment */
+ movl %ebx, %eax
+ shrl $4, %eax
+ movw %ax, 2 + realptr - _reloc(%ebx)
+
+DEBUG('c')
+ /* Fixup the gdt */
+ movl %ebx, %eax
+ shll $16, %eax
+
+ movl %ebx, %ecx
+ shrl $16, %ecx
+ andl $0xff, %ecx
+
+ movl %ebx, %edx
+ andl $0xff000000, %edx
+ orl %edx, %ecx
+
+ addl %ebx, gdtaddr - _reloc(%ebx)
+ addl %ebx, debug_gdtaddr - _reloc(%ebx)
+ orl %eax, 0x08 + gdt - _reloc(%ebx)
+ orl %ecx, 0x0c + gdt - _reloc(%ebx)
+ orl %eax, 0x10 + gdt - _reloc(%ebx)
+ orl %ecx, 0x14 + gdt - _reloc(%ebx)
+
+
+
+DEBUG('d')
+ /* Setup the classic BIOS interrupt table at 0x0 */
+ lidt idtptr - _reloc(%ebx)
+
+ /* Provide us with 16bit segments that we can use */
+ lgdt gdtptr - _reloc(%ebx)
+
+ /* Note we don't disable the a20 line, (this shouldn't be required)
+ * The code to do it is in kexec_test and it is a real pain.
+ * I will worry about that when I need it.
+ */
+
+ /* Load 16bit data segments, to ensure the segment limits are set */
+ movl $0x10, %eax
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %ss
+ movl %eax, %fs
+ movl %eax, %gs
+
+ /* switch to 16bit mode */
+
+ ljmp $0x08, $2f - _reloc
+2:
+ .code16
+DEBUG('e')
+ /* Disable Paging and protected mode */
+ /* clear the PG & PE bits of CR0 */
+ movl %cr0,%eax
+ andl $~((1 << 31)|(1<<0)),%eax
+ movl %eax,%cr0
+
+DEBUG('f')
+ /* make intersegment jmp to flush the processor pipeline
+ * and reload %cs:%eip (to clear upper 16 bits of %eip).
+ */
+ ljmp *(realptr - _reloc)
+3:
+DEBUG('g')
+ /* we are in real mode now
+ * set up the real mode segment registers : %ds, $ss, %es
+ */
+ /* Setup the data segment */
+ movw %cs, %ax
+ movw %ax, %ds
+
+DEBUG('h')
+ /* Load the registers */
+ movl eax - _reloc, %eax
+ movl ebx - _reloc, %ebx
+ movl ecx - _reloc, %ecx
+ movl edx - _reloc, %edx
+ movl esi - _reloc, %esi
+ movl edi - _reloc, %esi
+ movl esp - _reloc, %esp
+ movl ebp - _reloc, %ebp
+ movw es - _reloc, %es
+ movw ss - _reloc, %ss
+ movw fs - _reloc, %fs
+ movw gs - _reloc, %gs
+ movw ds - _reloc, %ds
+
+ /* Jump to the kernel entrypoint */
+ ljmp %cs:*(realdest - _reloc)
+
+setup16_debug_regs:
+eax: .long 0x00000000
+ebx: .long 0x00000000
+ecx: .long 0x00000000
+edx: .long 0x00000000
+esi: .long 0x00000000
+edi: .long 0x00000000
+esp: .long 0x00000000
+ebp: .long 0x00000000
+ds: .word 0x0000
+es: .word 0x0000
+ss: .word 0x0000
+fs: .word 0x0000
+gs: .word 0x0000
+realdest:
+ip: .word 0x0000
+cs: .word 0x0000
+
+ .balign 16
+realptr:
+ .word 3b - _reloc
+ .word 0x0000
+
+idtptr:
+ /* 256 entry idt at 0 */
+ .word 0x400 - 1
+ .word 0, 0
+
+gdtptr:
+ .word gdt_end - gdt - 1
+gdtaddr:
+ .long gdt - _reloc
+
+gdt:
+ /* dummy */
+ .word 0, 0, 0, 0
+
+ /* 16 bit real mode code segment */
+ .word 0xffff, 0x0000
+ .byte 0x00, 0x9b, 0x00, 0x00
+
+ /* 16 bit real mode data segment */
+ .word 0xffff, 0x0000
+ .byte 0x00, 0x93, 0x00, 0x00
+gdt_end:
+
+debug_gdt:
+ /* 0x00 */
+ .word debug_gdt_end - debug_gdt - 1
+debug_gdtaddr:
+ .long debug_gdt - _reloc
+ .word 0
+
+ /* 0x08 */
+ .word 0, 0, 0, 0 /* Nothing in the first gdt entry */
+
+ /* 0x10 4Gb - (0x100000*0x1000 = 4Gb), base address = 0, code read/exec, granularity = 4096, 386 */
+ .word 0xFFFF, 0x00, 0x9A00, 0x00CF
+ /* 0x18 4Gb - (0x100000*0x1000 = 4Gb*), base address = 0, data read/write, granularity = 4096, 386 */
+ .word 0xFFFF, 0x0000, 0x9200, 0x00CF
+
+
+ /* 0x20 4Gb - (0x100000*0x1000 = 4Gb), base address = 0, code read/exec, granularity = 4096, 386 */
+ .word 0xFFFF, 0x00, 0x9A00, 0x00CF
+ /* 0x28 4Gb - (0x100000*0x1000 = 4Gb*), base address = 0, data read/write, granularity = 4096, 386 */
+ .word 0xFFFF, 0x0000, 0x9200, 0x00CF
+
+
+ /* 0x30 4Gb - (0x100000*0x1000 = 4Gb), base address = 0, code read/exec, granularity = 4096, 386 */
+ .word 0xFFFF, 0x00, 0x9A00, 0x00CF
+ /* 0x38 4Gb - (0x100000*0x1000 = 4Gb*), base address = 0, data read/write, granularity = 4096, 386 */
+ .word 0xFFFF, 0x0000, 0x9200, 0x00CF
+
+
+ /* 0x40 4Gb - (0x100000*0x1000 = 4Gb), base address = 0, code read/exec, granularity = 4096, 386 */
+ .word 0xFFFF, 0x00, 0x9A00, 0x00CF
+ /* 0x48 4Gb - (0x100000*0x1000 = 4Gb*), base address = 0, data read/write, granularity = 4096, 386 */
+ .word 0xFFFF, 0x0000, 0x9200, 0x00CF
+
+
+ /* 0x50 4Gb - (0x100000*0x1000 = 4Gb), base address = 0, code read/exec, granularity = 4096, 386 */
+ .word 0xFFFF, 0x00, 0x9A00, 0x00CF
+ /* 0x58 4Gb - (0x100000*0x1000 = 4Gb*), base address = 0, data read/write, granularity = 4096, 386 */
+ .word 0xFFFF, 0x0000, 0x9200, 0x00CF
+
+
+ /* 0x60 4Gb - (0x100000*0x1000 = 4Gb), base address = 0, code read/exec, granularity = 4096, 386 */
+ .word 0xFFFF, 0x00, 0x9A00, 0x00CF
+ /* 0x68 4Gb - (0x100000*0x1000 = 4Gb*), base address = 0, data read/write, granularity = 4096, 386 */
+ .word 0xFFFF, 0x0000, 0x9200, 0x00CF
+debug_gdt_end:
+
+
+setup16_debug_kernel_pre_protected:
+ .code16
+ DEBUG('i')
+ cli # no interrupts allowed !
+ movb $0x80, %al # disable NMI for bootup
+ # sequence
+ outb %al, $0x70
+ lret
+setup16_debug_first_code32:
+ .code32
+ .byte 0xbf /* movl $0x12345678, %edi */
+location:
+ .long 0x12345678
+ DEBUG('j')
+ .byte 0xb8 /* movl $0x10000, %eax */
+setup16_debug_old_code32:
+ .long 0x10000
+ jmp %eax
+setup16_debug_end:
+setup16_debug_size:
+ .long setup16_debug_end - setup16_debug_start
+setup16_debug_align:
+ .long 16
diff --git a/purgatory/arch/i386/pic.c b/purgatory/arch/i386/pic.c
new file mode 100644
index 0000000..1b73ea9
--- /dev/null
+++ b/purgatory/arch/i386/pic.c
@@ -0,0 +1,51 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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 <arch/io.h>
+#include <purgatory.h>
+#include "purgatory-x86.h"
+
+
+void x86_setup_legacy_pic(void)
+{
+ /* Load the legacy dos settings into the 8259A pic */
+ outb(0xff, 0x21); /* mask all of 8259A-1 */
+ outb(0xff, 0xa1); /* mask all of 8259A-2 */
+
+ outb(0x11, 0x20); /* ICW1: select 8259A-1 init */
+ outb(0x11, 0x80); /* A short delay */
+
+ outb(0x08, 0x21); /* ICW2: 8259A-1 IR0-7 mappend to 0x8-0xf */
+ outb(0x08, 0x80); /* A short delay */
+
+ outb(0x01, 0x21); /* Normal 8086 auto EOI mode */
+ outb(0x01, 0x80); /* A short delay */
+
+ outb(0x11, 0xa0); /* ICW1: select 8259A-2 init */
+ outb(0x11, 0x80); /* A short delay */
+
+ outb(0x70, 0xa1); /* ICW2: 8259A-2 IR0-7 mappend to 0x70-0x77 */
+ outb(0x70, 0x80); /* A short delay */
+
+ outb(0x01, 0xa1); /* Normal 8086 auto EOI mode */
+ outb(0x01, 0x80); /* A short delay */
+
+ outb(0x00, 0x21); /* Unmask all of 8259A-1 */
+ outb(0x00, 0xa1); /* Unmask all of 8259A-2 */
+}
+
diff --git a/purgatory/arch/i386/purgatory-x86.c b/purgatory/arch/i386/purgatory-x86.c
new file mode 100644
index 0000000..442358a
--- /dev/null
+++ b/purgatory/arch/i386/purgatory-x86.c
@@ -0,0 +1,40 @@
+#include <arch/io.h>
+#include <purgatory.h>
+#include "purgatory-x86.h"
+
+/*
+ * CPU
+ * =============================================================================
+ */
+
+void x86_setup_cpu(void)
+{
+#if 0
+ /* This code is only needed for old versions of the kexec kernel patch.
+ * While it is still a good idea doing this unconditionally breaks
+ * on older cpus that did not implemented cr4.
+ * So this code is disabled for now. If this is revisited
+ * I first need to detect cpuid support and then use cpuid
+ * to conditionally change newer cpu registers.
+ */
+ /* clear special bits in %cr4 */
+ asm volatile(
+ "movl %0, %%eax\n\t"
+ "movl %%eax, %%cr4\n\t"
+ : /* outputs */
+ : "r" (0)
+ );
+#endif
+}
+
+uint8_t reset_vga = 0;
+uint8_t legacy_timer = 0;
+uint8_t legacy_pic = 0;
+
+void setup_arch(void)
+{
+ x86_setup_cpu();
+ if (reset_vga) x86_reset_vga();
+ if (legacy_pic) x86_setup_legacy_pic();
+ /* if (legacy_timer) x86_setup_legacy_timer(); */
+}
diff --git a/purgatory/arch/i386/purgatory-x86.h b/purgatory/arch/i386/purgatory-x86.h
new file mode 100644
index 0000000..4178b37
--- /dev/null
+++ b/purgatory/arch/i386/purgatory-x86.h
@@ -0,0 +1,8 @@
+#ifndef PURGATORY_X86_H
+#define PURGATORY_X86_H
+
+void x86_reset_vga(void);
+void x86_setup_legacy_pic(void);
+void x86_setup_legacy_timer(void);
+
+#endif /* PURGATORY_X86_H */
diff --git a/purgatory/arch/i386/setup-x86.S b/purgatory/arch/i386/setup-x86.S
new file mode 100644
index 0000000..f0719d4
--- /dev/null
+++ b/purgatory/arch/i386/setup-x86.S
@@ -0,0 +1,72 @@
+/*
+ * purgatory: setup code
+ *
+ * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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.
+ */
+
+
+#undef i386
+
+ .text
+ .arch i386
+ .globl purgatory_start
+purgatory_start:
+ .code32
+
+ /* Load a gdt so I know what the segment registers are */
+ lgdt %cs:gdt
+
+ /* load the data segments */
+ movl $0x08, %eax /* data segment */
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %ss
+ movl %eax, %fs
+ movl %eax, %gs
+
+ /* load the code segment */
+ ljmp $0x10,$1f
+1:
+
+ /* Setup a stack */
+ movl $lstack_end, %esp
+
+ /* Call the C code */
+ call purgatory
+ jmp entry32
+
+ .section ".rodata"
+ .balign 16
+gdt:
+ /* 0x00 unusable segment so used as the gdt ptr */
+ .word gdt_end - gdt - 1
+ .long gdt
+ .word 0
+
+ /* 0x8 4GB flat data segment */
+ .word 0xFFFF, 0x0000, 0x9200, 0x00CF
+
+ /* 0x10 4GB flat code segment */
+ .word 0xFFFF, 0x0000, 0x9A00, 0x00CF
+gdt_end:
+
+ /* A stack for the purgatory code */
+ .bss
+ .balign 4096
+lstack:
+ .skip 4096
+lstack_end:
+
diff --git a/purgatory/arch/i386/stack.S b/purgatory/arch/i386/stack.S
new file mode 100644
index 0000000..a597b0f
--- /dev/null
+++ b/purgatory/arch/i386/stack.S
@@ -0,0 +1,39 @@
+/*
+ * purgatory: stack
+ *
+ * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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.
+ */
+
+ /* A stack for the loaded kernel.
+ * Seperate and in the data section so it can be prepopulated.
+ */
+ .data
+ .globl stack, stack_end
+ .globl stack_arg32_1, stack_arg32_2, stack_arg32_3 ,stack_arg32_4
+ .globl stack_arg32_5, stack_arg32_6, stack_arg32_7 ,stack_arg32_8
+ .balign 4096
+stack:
+ .skip 4096 - (8*4)
+stack_arg32_8: .long 0 ; .size stack_arg32_8, 4
+stack_arg32_7: .long 0 ; .size stack_arg32_7, 4
+stack_arg32_6: .long 0 ; .size stack_arg32_6, 4
+stack_arg32_5: .long 0 ; .size stack_arg32_5, 4
+stack_arg32_4: .long 0 ; .size stack_arg32_4, 4
+stack_arg32_3: .long 0 ; .size stack_arg32_3, 4
+stack_arg32_2: .long 0 ; .size stack_arg32_2, 4
+stack_arg32_1: .long 0 ; .size stack_arg32_1, 4
+stack_end:
+
diff --git a/purgatory/arch/i386/timer.c b/purgatory/arch/i386/timer.c
new file mode 100644
index 0000000..dec5938
--- /dev/null
+++ b/purgatory/arch/i386/timer.c
@@ -0,0 +1,10 @@
+#include <arch/io.h>
+#include <purgatory.h>
+#include "purgatory-x86.h"
+
+
+void x86_setup_legacy_timer(void)
+{
+ /* Load the legacy timer settings into the 8254 pit */
+}
+
diff --git a/purgatory/arch/i386/vga.c b/purgatory/arch/i386/vga.c
new file mode 100644
index 0000000..effa8ff
--- /dev/null
+++ b/purgatory/arch/i386/vga.c
@@ -0,0 +1,152 @@
+#include <arch/io.h>
+#include <purgatory.h>
+#include "purgatory-x86.h"
+
+/* Crudely reset a VGA card to text mode 3, by writing plausible default */
+/* values into its registers. */
+/* Tim Deegan (tjd21 at cl.cam.ac.uk), March 2003 */
+/* Based on Keir Fraser's start-of-day reset code from the Xen hypervisor */
+/* Converted from Assembly 20 December 2004 -- Eric Biederman */
+
+void x86_reset_vga(void)
+{
+ /* Hello */
+ inb(0x3da);
+ outb(0, 0x3c0);
+
+ /* Sequencer registers */
+ outw(0x0300, 0x3c4);
+ outw(0x0001, 0x3c4);
+ outw(0x0302, 0x3c4);
+ outw(0x0003, 0x3c4);
+ outw(0x0204, 0x3c4);
+
+ /* Ensure CRTC regs 0-7 are unlocked by clearing bit 7 of CRTC[17] */
+ outw(0x0e11, 0x3d4);
+ /* CRTC registers */
+ outw(0x5f00, 0x3d4);
+ outw(0x4f01, 0x3d4);
+ outw(0x5002, 0x3d4);
+ outw(0x8203, 0x3d4);
+ outw(0x5504, 0x3d4);
+ outw(0x8105, 0x3d4);
+ outw(0xbf06, 0x3d4);
+ outw(0x1f07, 0x3d4);
+ outw(0x0008, 0x3d4);
+ outw(0x4f09, 0x3d4);
+ outw(0x200a, 0x3d4);
+ outw(0x0e0b, 0x3d4);
+ outw(0x000c, 0x3d4);
+ outw(0x000d, 0x3d4);
+ outw(0x010e, 0x3d4);
+ outw(0xe00f, 0x3d4);
+ outw(0x9c10, 0x3d4);
+ outw(0x8e11, 0x3d4);
+ outw(0x8f12, 0x3d4);
+ outw(0x2813, 0x3d4);
+ outw(0x1f14, 0x3d4);
+ outw(0x9615, 0x3d4);
+ outw(0xb916, 0x3d4);
+ outw(0xa317, 0x3d4);
+ outw(0xff18, 0x3d4);
+
+ /* Graphic registers */
+ outw(0x0000, 0x3ce);
+ outw(0x0001, 0x3ce);
+ outw(0x0002, 0x3ce);
+ outw(0x0003, 0x3ce);
+ outw(0x0004, 0x3ce);
+ outw(0x1005, 0x3ce);
+ outw(0x0e06, 0x3ce);
+ outw(0x0007, 0x3ce);
+ outw(0xff08, 0x3ce);
+
+ /* Attribute registers */
+ inb(0x3da);
+ outb(0x00, 0x3c0);
+ outb(0x00, 0x3c0);
+
+ inb(0x3da);
+ outb(0x01, 0x3c0);
+ outb(0x01, 0x3c0);
+
+ inb(0x3da);
+ outb(0x02, 0x3c0);
+ outb(0x02, 0x3c0);
+
+ inb(0x3da);
+ outb(0x03, 0x3c0);
+ outb(0x03, 0x3c0);
+
+ inb(0x3da);
+ outb(0x04, 0x3c0);
+ outb(0x04, 0x3c0);
+
+ inb(0x3da);
+ outb(0x05, 0x3c0);
+ outb(0x05, 0x3c0);
+
+ inb(0x3da);
+ outb(0x06, 0x3c0);
+ outb(0x14, 0x3c0);
+
+ inb(0x3da);
+ outb(0x07, 0x3c0);
+ outb(0x07, 0x3c0);
+
+ inb(0x3da);
+ outb(0x08, 0x3c0);
+ outb(0x38, 0x3c0);
+
+ inb(0x3da);
+ outb(0x09, 0x3c0);
+ outb(0x39, 0x3c0);
+
+ inb(0x3da);
+ outb(0x0a, 0x3c0);
+ outb(0x3a, 0x3c0);
+
+ inb(0x3da);
+ outb(0x0b, 0x3c0);
+ outb(0x3b, 0x3c0);
+
+ inb(0x3da);
+ outb(0x0c, 0x3c0);
+ outb(0x3c, 0x3c0);
+
+ inb(0x3da);
+ outb(0x0d, 0x3c0);
+ outb(0x3d, 0x3c0);
+
+ inb(0x3da);
+ outb(0x0e, 0x3c0);
+ outb(0x3e, 0x3c0);
+
+ inb(0x3da);
+ outb(0x0f, 0x3c0);
+ outb(0x3f, 0x3c0);
+
+ inb(0x3da);
+ outb(0x10, 0x3c0);
+ outb(0x0c, 0x3c0);
+
+ inb(0x3da);
+ outb(0x11, 0x3c0);
+ outb(0x00, 0x3c0);
+
+ inb(0x3da);
+ outb(0x12, 0x3c0);
+ outb(0x0f, 0x3c0);
+
+ inb(0x3da);
+ outb(0x13, 0x3c0);
+ outb(0x08, 0x3c0);
+
+ inb(0x3da);
+ outb(0x14, 0x3c0);
+ outb(0x00, 0x3c0);
+
+ /* Goodbye */
+ inb(0x3da);
+ outb(0x20, 0x3c0);
+}
diff --git a/purgatory/arch/ia64/Makefile b/purgatory/arch/ia64/Makefile
new file mode 100644
index 0000000..8ba596e
--- /dev/null
+++ b/purgatory/arch/ia64/Makefile
@@ -0,0 +1,9 @@
+#
+# Purgatory ia64
+#
+
+PURGATORY_S_SRCS+=
+PURGATORY_C_SRCS+= purgatory/arch/ia64/purgatory-ia64.c
+PURGATORY_C_SRCS+= purgatory/arch/ia64/console-ia64.c
+PURGATORY_C_SRCS+=
+
diff --git a/purgatory/arch/ia64/console-ia64.c b/purgatory/arch/ia64/console-ia64.c
new file mode 100644
index 0000000..389b7be
--- /dev/null
+++ b/purgatory/arch/ia64/console-ia64.c
@@ -0,0 +1,5 @@
+#include <purgatory.h>
+void putchar(int ch)
+{
+ /* Nothing for now */
+}
diff --git a/purgatory/arch/ia64/include/limits.h b/purgatory/arch/ia64/include/limits.h
new file mode 100644
index 0000000..0c6f21f
--- /dev/null
+++ b/purgatory/arch/ia64/include/limits.h
@@ -0,0 +1,57 @@
+#ifndef LIMITS_H
+#define LIMITS_H 1
+
+/* Number of bits in a `char' */
+#define CHAR_BIT 8
+
+/* Minimum and maximum values a `signed char' can hold */
+#define SCHAR_MIN (-128)
+#define SCHAR_MAX 127
+
+/* Maximum value an `unsigned char' can hold. (Minimum is 0.) */
+#define UCHAR_MAX 255
+
+/* Minimum and maximum values a `char' can hold */
+#define CHAR_MIN SCHAR_MIN
+#define CHAR_MAX SCHAR_MAX
+
+/* Minimum and maximum values a `signed short int' can hold */
+#define SHRT_MIN (-32768)
+#define SHRT_MAX 32767
+
+/* Maximum value an `unsigned short' can hold. (Minimum is 0.) */
+#define USHRT_MAX 65535
+
+
+/* Minimum and maximum values a `signed int' can hold */
+#define INT_MIN (-INT_MAX - 1)
+#define INT_MAX 2147483647
+
+/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */
+#define UINT_MAX 4294967295U
+
+
+/* Minimum and maximum values a `signed int' can hold */
+#define INT_MIN (-INT_MAX - 1)
+#define INT_MAX 2147483647
+
+/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */
+#define UINT_MAX 4294967295U
+
+/* Minimum and maximum values a `signed long' can hold */
+#define LONG_MAX 9223372036854775807L
+#define LONG_MIN (-LONG_MAX - 1L)
+
+/* Maximum value an `unsigned long' can hold. (Minimum is 0.) */
+#define ULONG_MAX 18446744073709551615UL
+
+/* Minimum and maximum values a `signed long long' can hold */
+#define LLONG_MAX 9223372036854775807LL
+#define LLONG_MIN (-LONG_MAX - 1LL)
+
+
+/* Maximum value an `unsigned long long' can hold. (Minimum is 0.) */
+#define ULLONG_MAX 18446744073709551615ULL
+
+
+#endif /* LIMITS_H */
diff --git a/purgatory/arch/ia64/include/stdint.h b/purgatory/arch/ia64/include/stdint.h
new file mode 100644
index 0000000..2f9c592
--- /dev/null
+++ b/purgatory/arch/ia64/include/stdint.h
@@ -0,0 +1,16 @@
+#ifndef STDINT_H
+#define STDINT_H
+
+typedef unsigned long size_t;
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long uint64_t;
+
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed int int32_t;
+typedef signed long int64_t;
+
+#endif /* STDINT_H */
diff --git a/purgatory/arch/ia64/purgatory-ia64.c b/purgatory/arch/ia64/purgatory-ia64.c
new file mode 100644
index 0000000..c10cbea
--- /dev/null
+++ b/purgatory/arch/ia64/purgatory-ia64.c
@@ -0,0 +1,7 @@
+#include <purgatory.h>
+#include "purgatory-ia64.h"
+
+void setup_arch(void)
+{
+ /* Nothing for now */
+}
diff --git a/purgatory/arch/ia64/purgatory-ia64.h b/purgatory/arch/ia64/purgatory-ia64.h
new file mode 100644
index 0000000..773e3c0
--- /dev/null
+++ b/purgatory/arch/ia64/purgatory-ia64.h
@@ -0,0 +1,6 @@
+#ifndef PURGATORY_IA64_H
+#define PURGATORY_IA64_H
+
+/* nothing yet */
+
+#endif /* PURGATORY_IA64_H */
diff --git a/purgatory/arch/ppc/Makefile b/purgatory/arch/ppc/Makefile
new file mode 100644
index 0000000..4ce40fe
--- /dev/null
+++ b/purgatory/arch/ppc/Makefile
@@ -0,0 +1,8 @@
+#
+# Purgatory ppc
+#
+
+PURGATORY_S_SRCS+= purgatory/arch/ppc/misc.S
+PURGATORY_C_SRCS+= purgatory/arch/ppc/purgatory-ppc.c
+PURGATORY_C_SRCS+= purgatory/arch/ppc/console-ppc.c
+
diff --git a/purgatory/arch/ppc/console-ppc.c b/purgatory/arch/ppc/console-ppc.c
new file mode 100644
index 0000000..389b7be
--- /dev/null
+++ b/purgatory/arch/ppc/console-ppc.c
@@ -0,0 +1,5 @@
+#include <purgatory.h>
+void putchar(int ch)
+{
+ /* Nothing for now */
+}
diff --git a/purgatory/arch/ppc/include/limits.h b/purgatory/arch/ppc/include/limits.h
new file mode 100644
index 0000000..d5a5a02
--- /dev/null
+++ b/purgatory/arch/ppc/include/limits.h
@@ -0,0 +1,58 @@
+#ifndef LIMITS_H
+#define LIMITS_H 1
+
+
+/* Number of bits in a `char' */
+#define CHAR_BIT 8
+
+/* Minimum and maximum values a `signed char' can hold */
+#define SCHAR_MIN (-128)
+#define SCHAR_MAX 127
+
+/* Maximum value an `unsigned char' can hold. (Minimum is 0.) */
+#define UCHAR_MAX 255
+
+/* Minimum and maximum values a `char' can hold */
+#define CHAR_MIN SCHAR_MIN
+#define CHAR_MAX SCHAR_MAX
+
+/* Minimum and maximum values a `signed short int' can hold */
+#define SHRT_MIN (-32768)
+#define SHRT_MAX 32767
+
+/* Maximum value an `unsigned short' can hold. (Minimum is 0.) */
+#define USHRT_MAX 65535
+
+
+/* Minimum and maximum values a `signed int' can hold */
+#define INT_MIN (-INT_MAX - 1)
+#define INT_MAX 2147483647
+
+/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */
+#define UINT_MAX 4294967295U
+
+
+/* Minimum and maximum values a `signed int' can hold */
+#define INT_MIN (-INT_MAX - 1)
+#define INT_MAX 2147483647
+
+/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */
+#define UINT_MAX 4294967295U
+
+/* Minimum and maximum values a `signed long' can hold */
+#define LONG_MAX 2147483647L
+#define LONG_MIN (-LONG_MAX - 1L)
+
+/* Maximum value an `unsigned long' can hold. (Minimum is 0.) */
+#define ULONG_MAX 4294967295UL
+
+/* Minimum and maximum values a `signed long long' can hold */
+#define LLONG_MAX 9223372036854775807LL
+#define LLONG_MIN (-LONG_MAX - 1LL)
+
+
+/* Maximum value an `unsigned long long' can hold. (Minimum is 0.) */
+#define ULLONG_MAX 18446744073709551615ULL
+
+
+#endif /* LIMITS_H */
diff --git a/purgatory/arch/ppc/include/stdint.h b/purgatory/arch/ppc/include/stdint.h
new file mode 100644
index 0000000..79262c2
--- /dev/null
+++ b/purgatory/arch/ppc/include/stdint.h
@@ -0,0 +1,16 @@
+#ifndef STDINT_H
+#define STDINT_H
+
+typedef unsigned long size_t;
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed int int32_t;
+typedef signed long long int64_t;
+
+#endif /* STDINT_H */
diff --git a/purgatory/arch/ppc/misc.S b/purgatory/arch/ppc/misc.S
new file mode 100644
index 0000000..b0a5486
--- /dev/null
+++ b/purgatory/arch/ppc/misc.S
@@ -0,0 +1,72 @@
+/*
+ * This file contains miscellaneous low-level functions.
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras.
+ *
+ * Rewrittten to work with /sbin/kexec 20 December 2004 Eric Biederman
+ *
+ * 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.
+ *
+ */
+
+#include "ppc_asm.h"
+
+ .text
+
+/*
+ * Extended precision shifts.
+ *
+ * Updated to be valid for shift counts from 0 to 63 inclusive.
+ * -- Gabriel
+ *
+ * R3/R4 has 64 bit value
+ * R5 has shift count
+ * result in R3/R4
+ *
+ * ashrdi3: arithmetic right shift (sign propagation)
+ * lshrdi3: logical right shift
+ * ashldi3: left shift
+ */
+ .globl __ashrdi3
+__ashrdi3:
+ subfic r6,r5,32
+ srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
+ addi r7,r5,32 # could be xori, or addi with -32
+ slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
+ rlwinm r8,r7,0,32 # t3 = (count < 32) ? 32 : 0
+ sraw r7,r3,r7 # t2 = MSW >> (count-32)
+ or r4,r4,r6 # LSW |= t1
+ slw r7,r7,r8 # t2 = (count < 32) ? 0 : t2
+ sraw r3,r3,r5 # MSW = MSW >> count
+ or r4,r4,r7 # LSW |= t2
+ blr
+
+ .globl __ashldi3
+__ashldi3:
+ subfic r6,r5,32
+ slw r3,r3,r5 # MSW = count > 31 ? 0 : MSW << count
+ addi r7,r5,32 # could be xori, or addi with -32
+ srw r6,r4,r6 # t1 = count > 31 ? 0 : LSW >> (32-count)
+ slw r7,r4,r7 # t2 = count < 32 ? 0 : LSW << (count-32)
+ or r3,r3,r6 # MSW |= t1
+ slw r4,r4,r5 # LSW = LSW << count
+ or r3,r3,r7 # MSW |= t2
+ blr
+
+ .globl __lshrdi3
+__lshrdi3:
+ subfic r6,r5,32
+ srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
+ addi r7,r5,32 # could be xori, or addi with -32
+ slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
+ srw r7,r3,r7 # t2 = count < 32 ? 0 : MSW >> (count-32)
+ or r4,r4,r6 # LSW |= t1
+ srw r3,r3,r5 # MSW = MSW >> count
+ or r4,r4,r7 # LSW |= t2
+ blr
+
diff --git a/purgatory/arch/ppc/ppc_asm.h b/purgatory/arch/ppc/ppc_asm.h
new file mode 100644
index 0000000..36503a9
--- /dev/null
+++ b/purgatory/arch/ppc/ppc_asm.h
@@ -0,0 +1,506 @@
+/*
+ * ppc_asm.h - mainly bits stolen from Linux kernel asm/reg.h and asm/ppc_asm.h
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+/* Condition Register Bit Fields */
+
+#define cr0 0
+#define cr1 1
+#define cr2 2
+#define cr3 3
+#define cr4 4
+#define cr5 5
+#define cr6 6
+#define cr7 7
+
+
+/* General Purpose Registers (GPRs) */
+
+#define r0 0
+#define r1 1
+#define r2 2
+#define r3 3
+#define r4 4
+#define r5 5
+#define r6 6
+#define r7 7
+#define r8 8
+#define r9 9
+#define r10 10
+#define r11 11
+#define r12 12
+#define r13 13
+#define r14 14
+#define r15 15
+#define r16 16
+#define r17 17
+#define r18 18
+#define r19 19
+#define r20 20
+#define r21 21
+#define r22 22
+#define r23 23
+#define r24 24
+#define r25 25
+#define r26 26
+#define r27 27
+#define r28 28
+#define r29 29
+#define r30 30
+#define r31 31
+
+/* Machine State Register (MSR) Fields */
+#define MSR_SF (1<<63)
+#define MSR_ISF (1<<61)
+#define MSR_VEC (1<<25) /* Enable AltiVec */
+#define MSR_POW (1<<18) /* Enable Power Management */
+#define MSR_WE (1<<18) /* Wait State Enable */
+#define MSR_TGPR (1<<17) /* TLB Update registers in use */
+#define MSR_CE (1<<17) /* Critical Interrupt Enable */
+#define MSR_ILE (1<<16) /* Interrupt Little Endian */
+#define MSR_EE (1<<15) /* External Interrupt Enable */
+#define MSR_PR (1<<14) /* Problem State / Privilege Level */
+#define MSR_FP (1<<13) /* Floating Point enable */
+#define MSR_ME (1<<12) /* Machine Check Enable */
+#define MSR_FE0 (1<<11) /* Floating Exception mode 0 */
+#define MSR_SE (1<<10) /* Single Step */
+#define MSR_BE (1<<9) /* Branch Trace */
+#define MSR_DE (1<<9) /* Debug Exception Enable */
+#define MSR_FE1 (1<<8) /* Floating Exception mode 1 */
+#define MSR_IP (1<<6) /* Exception prefix 0x000/0xFFF */
+#define MSR_IR (1<<5) /* Instruction Relocate */
+#define MSR_DR (1<<4) /* Data Relocate */
+#define MSR_PE (1<<3) /* Protection Enable */
+#define MSR_PX (1<<2) /* Protection Exclusive Mode */
+#define MSR_RI (1<<1) /* Recoverable Exception */
+#define MSR_LE (1<<0) /* Little Endian */
+
+/* Special Purpose Registers (SPRNs)*/
+#define SPRN_CTR 0x009 /* Count Register */
+#define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */
+#define SPRN_DAR 0x013 /* Data Address Register */
+#define SPRN_TBRL 0x10C /* Time Base Read Lower Register (user, R/O) */
+#define SPRN_TBRU 0x10D /* Time Base Read Upper Register (user, R/O) */
+#define SPRN_TBWL 0x11C /* Time Base Lower Register (super, R/W) */
+#define SPRN_TBWU 0x11D /* Time Base Upper Register (super, R/W) */
+#define SPRN_HIOR 0x137 /* 970 Hypervisor interrupt offset */
+#define SPRN_DBAT0L 0x219 /* Data BAT 0 Lower Register */
+#define SPRN_DBAT0U 0x218 /* Data BAT 0 Upper Register */
+#define SPRN_DBAT1L 0x21B /* Data BAT 1 Lower Register */
+#define SPRN_DBAT1U 0x21A /* Data BAT 1 Upper Register */
+#define SPRN_DBAT2L 0x21D /* Data BAT 2 Lower Register */
+#define SPRN_DBAT2U 0x21C /* Data BAT 2 Upper Register */
+#define SPRN_DBAT3L 0x21F /* Data BAT 3 Lower Register */
+#define SPRN_DBAT3U 0x21E /* Data BAT 3 Upper Register */
+#define SPRN_DBAT4L 0x239 /* Data BAT 4 Lower Register */
+#define SPRN_DBAT4U 0x238 /* Data BAT 4 Upper Register */
+#define SPRN_DBAT5L 0x23B /* Data BAT 5 Lower Register */
+#define SPRN_DBAT5U 0x23A /* Data BAT 5 Upper Register */
+#define SPRN_DBAT6L 0x23D /* Data BAT 6 Lower Register */
+#define SPRN_DBAT6U 0x23C /* Data BAT 6 Upper Register */
+#define SPRN_DBAT7L 0x23F /* Data BAT 7 Lower Register */
+#define SPRN_DBAT7U 0x23E /* Data BAT 7 Upper Register */
+
+#define SPRN_DEC 0x016 /* Decrement Register */
+#define SPRN_DER 0x095 /* Debug Enable Regsiter */
+#define DER_RSTE 0x40000000 /* Reset Interrupt */
+#define DER_CHSTPE 0x20000000 /* Check Stop */
+#define DER_MCIE 0x10000000 /* Machine Check Interrupt */
+#define DER_EXTIE 0x02000000 /* External Interrupt */
+#define DER_ALIE 0x01000000 /* Alignment Interrupt */
+#define DER_PRIE 0x00800000 /* Program Interrupt */
+#define DER_FPUVIE 0x00400000 /* FP Unavailable Interrupt */
+#define DER_DECIE 0x00200000 /* Decrementer Interrupt */
+#define DER_SYSIE 0x00040000 /* System Call Interrupt */
+#define DER_TRE 0x00020000 /* Trace Interrupt */
+#define DER_SEIE 0x00004000 /* FP SW Emulation Interrupt */
+#define DER_ITLBMSE 0x00002000 /* Imp. Spec. Instruction TLB Miss */
+#define DER_ITLBERE 0x00001000 /* Imp. Spec. Instruction TLB Error */
+#define DER_DTLBMSE 0x00000800 /* Imp. Spec. Data TLB Miss */
+#define DER_DTLBERE 0x00000400 /* Imp. Spec. Data TLB Error */
+#define DER_LBRKE 0x00000008 /* Load/Store Breakpoint Interrupt */
+#define DER_IBRKE 0x00000004 /* Instruction Breakpoint Interrupt */
+#define DER_EBRKE 0x00000002 /* External Breakpoint Interrupt */
+#define DER_DPIE 0x00000001 /* Dev. Port Nonmaskable Request */
+#define SPRN_DMISS 0x3D0 /* Data TLB Miss Register */
+#define SPRN_DSISR 0x012 /* Data Storage Interrupt Status Register */
+#define SPRN_EAR 0x11A /* External Address Register */
+#define SPRN_HASH1 0x3D2 /* Primary Hash Address Register */
+#define SPRN_HASH2 0x3D3 /* Secondary Hash Address Resgister */
+#define SPRN_HID0 0x3F0 /* Hardware Implementation Register 0 */
+#define HID0_EMCP (1<<31) /* Enable Machine Check pin */
+#define HID0_EBA (1<<29) /* Enable Bus Address Parity */
+#define HID0_EBD (1<<28) /* Enable Bus Data Parity */
+#define HID0_SBCLK (1<<27)
+#define HID0_EICE (1<<26)
+#define HID0_TBEN (1<<26) /* Timebase enable - 745x */
+#define HID0_ECLK (1<<25)
+#define HID0_PAR (1<<24)
+#define HID0_STEN (1<<24) /* Software table search enable - 745x */
+#define HID0_HIGH_BAT (1<<23) /* Enable high BATs - 7455 */
+#define HID0_DOZE (1<<23)
+#define HID0_NAP (1<<22)
+#define HID0_SLEEP (1<<21)
+#define HID0_DPM (1<<20)
+#define HID0_BHTCLR (1<<18) /* Clear branch history table - 7450 */
+#define HID0_XAEN (1<<17) /* Extended addressing enable - 7450 */
+#define HID0_NHR (1<<16) /* Not hard reset (software bit-7450)*/
+#define HID0_ICE (1<<15) /* Instruction Cache Enable */
+#define HID0_DCE (1<<14) /* Data Cache Enable */
+#define HID0_ILOCK (1<<13) /* Instruction Cache Lock */
+#define HID0_DLOCK (1<<12) /* Data Cache Lock */
+#define HID0_ICFI (1<<11) /* Instr. Cache Flash Invalidate */
+#define HID0_DCI (1<<10) /* Data Cache Invalidate */
+#define HID0_SPD (1<<9) /* Speculative disable */
+#define HID0_SGE (1<<7) /* Store Gathering Enable */
+#define HID0_SIED (1<<7) /* Serial Instr. Execution [Disable] */
+#define HID0_DFCA (1<<6) /* Data Cache Flush Assist */
+#define HID0_LRSTK (1<<4) /* Link register stack - 745x */
+#define HID0_BTIC (1<<5) /* Branch Target Instr Cache Enable */
+#define HID0_ABE (1<<3) /* Address Broadcast Enable */
+#define HID0_FOLD (1<<3) /* Branch Folding enable - 745x */
+#define HID0_BHTE (1<<2) /* Branch History Table Enable */
+#define HID0_BTCD (1<<1) /* Branch target cache disable */
+#define HID0_NOPDST (1<<1) /* No-op dst, dstt, etc. instr. */
+#define HID0_NOPTI (1<<0) /* No-op dcbt and dcbst instr. */
+
+#define SPRN_HID1 0x3F1 /* Hardware Implementation Register 1 */
+#define HID1_EMCP (1<<31) /* 7450 Machine Check Pin Enable */
+#define HID1_PC0 (1<<16) /* 7450 PLL_CFG[0] */
+#define HID1_PC1 (1<<15) /* 7450 PLL_CFG[1] */
+#define HID1_PC2 (1<<14) /* 7450 PLL_CFG[2] */
+#define HID1_PC3 (1<<13) /* 7450 PLL_CFG[3] */
+#define HID1_SYNCBE (1<<11) /* 7450 ABE for sync, eieio */
+#define HID1_ABE (1<<10) /* 7450 Address Broadcast Enable */
+#define SPRN_HID2 0x3F8 /* Hardware Implementation Register 2 */
+#define SPRN_IABR 0x3F2 /* Instruction Address Breakpoint Register */
+#define SPRN_HID4 0x3F4 /* 970 HID4 */
+#define SPRN_HID5 0x3F6 /* 970 HID5 */
+#if !defined(SPRN_IAC1) && !defined(SPRN_IAC2)
+#define SPRN_IAC1 0x3F4 /* Instruction Address Compare 1 */
+#define SPRN_IAC2 0x3F5 /* Instruction Address Compare 2 */
+#endif
+#define SPRN_IBAT0L 0x211 /* Instruction BAT 0 Lower Register */
+#define SPRN_IBAT0U 0x210 /* Instruction BAT 0 Upper Register */
+#define SPRN_IBAT1L 0x213 /* Instruction BAT 1 Lower Register */
+#define SPRN_IBAT1U 0x212 /* Instruction BAT 1 Upper Register */
+#define SPRN_IBAT2L 0x215 /* Instruction BAT 2 Lower Register */
+#define SPRN_IBAT2U 0x214 /* Instruction BAT 2 Upper Register */
+#define SPRN_IBAT3L 0x217 /* Instruction BAT 3 Lower Register */
+#define SPRN_IBAT3U 0x216 /* Instruction BAT 3 Upper Register */
+#define SPRN_IBAT4L 0x231 /* Instruction BAT 4 Lower Register */
+#define SPRN_IBAT4U 0x230 /* Instruction BAT 4 Upper Register */
+#define SPRN_IBAT5L 0x233 /* Instruction BAT 5 Lower Register */
+#define SPRN_IBAT5U 0x232 /* Instruction BAT 5 Upper Register */
+#define SPRN_IBAT6L 0x235 /* Instruction BAT 6 Lower Register */
+#define SPRN_IBAT6U 0x234 /* Instruction BAT 6 Upper Register */
+#define SPRN_IBAT7L 0x237 /* Instruction BAT 7 Lower Register */
+#define SPRN_IBAT7U 0x236 /* Instruction BAT 7 Upper Register */
+#define SPRN_ICMP 0x3D5 /* Instruction TLB Compare Register */
+#define SPRN_ICTC 0x3FB /* Instruction Cache Throttling Control Reg */
+#define SPRN_ICTRL 0x3F3 /* 1011 7450 icache and interrupt ctrl */
+#define ICTRL_EICE 0x08000000 /* enable icache parity errs */
+#define ICTRL_EDC 0x04000000 /* enable dcache parity errs */
+#define ICTRL_EICP 0x00000100 /* enable icache par. check */
+#define SPRN_IMISS 0x3D4 /* Instruction TLB Miss Register */
+#define SPRN_IMMR 0x27E /* Internal Memory Map Register */
+#define SPRN_L2CR 0x3F9 /* Level 2 Cache Control Regsiter */
+#define SPRN_L2CR2 0x3f8
+#define L2CR_L2E 0x80000000 /* L2 enable */
+#define L2CR_L2PE 0x40000000 /* L2 parity enable */
+#define L2CR_L2SIZ_MASK 0x30000000 /* L2 size mask */
+#define L2CR_L2SIZ_256KB 0x10000000 /* L2 size 256KB */
+#define L2CR_L2SIZ_512KB 0x20000000 /* L2 size 512KB */
+#define L2CR_L2SIZ_1MB 0x30000000 /* L2 size 1MB */
+#define L2CR_L2CLK_MASK 0x0e000000 /* L2 clock mask */
+#define L2CR_L2CLK_DISABLED 0x00000000 /* L2 clock disabled */
+#define L2CR_L2CLK_DIV1 0x02000000 /* L2 clock / 1 */
+#define L2CR_L2CLK_DIV1_5 0x04000000 /* L2 clock / 1.5 */
+#define L2CR_L2CLK_DIV2 0x08000000 /* L2 clock / 2 */
+#define L2CR_L2CLK_DIV2_5 0x0a000000 /* L2 clock / 2.5 */
+#define L2CR_L2CLK_DIV3 0x0c000000 /* L2 clock / 3 */
+#define L2CR_L2RAM_MASK 0x01800000 /* L2 RAM type mask */
+#define L2CR_L2RAM_FLOW 0x00000000 /* L2 RAM flow through */
+#define L2CR_L2RAM_PIPE 0x01000000 /* L2 RAM pipelined */
+#define L2CR_L2RAM_PIPE_LW 0x01800000 /* L2 RAM pipelined latewr */
+#define L2CR_L2DO 0x00400000 /* L2 data only */
+#define L2CR_L2I 0x00200000 /* L2 global invalidate */
+#define L2CR_L2CTL 0x00100000 /* L2 RAM control */
+#define L2CR_L2WT 0x00080000 /* L2 write-through */
+#define L2CR_L2TS 0x00040000 /* L2 test support */
+#define L2CR_L2OH_MASK 0x00030000 /* L2 output hold mask */
+#define L2CR_L2OH_0_5 0x00000000 /* L2 output hold 0.5 ns */
+#define L2CR_L2OH_1_0 0x00010000 /* L2 output hold 1.0 ns */
+#define L2CR_L2SL 0x00008000 /* L2 DLL slow */
+#define L2CR_L2DF 0x00004000 /* L2 differential clock */
+#define L2CR_L2BYP 0x00002000 /* L2 DLL bypass */
+#define L2CR_L2IP 0x00000001 /* L2 GI in progress */
+#define SPRN_L3CR 0x3FA /* Level 3 Cache Control Regsiter */
+#define L3CR_L3E 0x80000000 /* L3 enable */
+#define L3CR_L3PE 0x40000000 /* L3 data parity enable */
+#define L3CR_L3APE 0x20000000 /* L3 addr parity enable */
+#define L3CR_L3SIZ 0x10000000 /* L3 size */
+#define L3CR_L3CLKEN 0x08000000 /* L3 clock enable */
+#define L3CR_L3RES 0x04000000 /* L3 special reserved bit */
+#define L3CR_L3CLKDIV 0x03800000 /* L3 clock divisor */
+#define L3CR_L3IO 0x00400000 /* L3 instruction only */
+#define L3CR_L3SPO 0x00040000 /* L3 sample point override */
+#define L3CR_L3CKSP 0x00030000 /* L3 clock sample point */
+#define L3CR_L3PSP 0x0000e000 /* L3 P-clock sample point */
+#define L3CR_L3REP 0x00001000 /* L3 replacement algorithm */
+#define L3CR_L3HWF 0x00000800 /* L3 hardware flush */
+#define L3CR_L3I 0x00000400 /* L3 global invalidate */
+#define L3CR_L3RT 0x00000300 /* L3 SRAM type */
+#define L3CR_L3NIRCA 0x00000080 /* L3 non-integer ratio clock adj. */
+#define L3CR_L3DO 0x00000040 /* L3 data only mode */
+#define L3CR_PMEN 0x00000004 /* L3 private memory enable */
+#define L3CR_PMSIZ 0x00000001 /* L3 private memory size */
+#define SPRN_MSSCR0 0x3f6 /* Memory Subsystem Control Register 0 */
+#define SPRN_MSSSR0 0x3f7 /* Memory Subsystem Status Register 1 */
+#define SPRN_LDSTCR 0x3f8 /* Load/Store control register */
+#define SPRN_LDSTDB 0x3f4 /* */
+#define SPRN_LR 0x008 /* Link Register */
+#define SPRN_MMCR0 0x3B8 /* Monitor Mode Control Register 0 */
+#define SPRN_MMCR1 0x3BC /* Monitor Mode Control Register 1 */
+#ifndef SPRN_PIR
+#define SPRN_PIR 0x3FF /* Processor Identification Register */
+#endif
+#define SPRN_PMC1 0x3B9 /* Performance Counter Register 1 */
+#define SPRN_PMC2 0x3BA /* Performance Counter Register 2 */
+#define SPRN_PMC3 0x3BD /* Performance Counter Register 3 */
+#define SPRN_PMC4 0x3BE /* Performance Counter Register 4 */
+#define SPRN_PTEHI 0x3D5 /* 981 7450 PTE HI word (S/W TLB load) */
+#define SPRN_PTELO 0x3D6 /* 982 7450 PTE LO word (S/W TLB load) */
+#define SPRN_PVR 0x11F /* Processor Version Register */
+#define SPRN_RPA 0x3D6 /* Required Physical Address Register */
+#define SPRN_SDA 0x3BF /* Sampled Data Address Register */
+#define SPRN_SDR1 0x019 /* MMU Hash Base Register */
+#define SPRN_SIA 0x3BB /* Sampled Instruction Address Register */
+#define SPRN_SPRG0 0x110 /* Special Purpose Register General 0 */
+#define SPRN_SPRG1 0x111 /* Special Purpose Register General 1 */
+#define SPRN_SPRG2 0x112 /* Special Purpose Register General 2 */
+#define SPRN_SPRG3 0x113 /* Special Purpose Register General 3 */
+#define SPRN_SPRG4 0x114 /* Special Purpose Register General 4 */
+#define SPRN_SPRG5 0x115 /* Special Purpose Register General 5 */
+#define SPRN_SPRG6 0x116 /* Special Purpose Register General 6 */
+#define SPRN_SPRG7 0x117 /* Special Purpose Register General 7 */
+#define SPRN_SRR0 0x01A /* Save/Restore Register 0 */
+#define SPRN_SRR1 0x01B /* Save/Restore Register 1 */
+#define SPRN_THRM1 0x3FC /* Thermal Management Register 1 */
+/* these bits were defined in inverted endian sense originally, ugh, confusing */
+#define THRM1_TIN (1 << 31)
+#define THRM1_TIV (1 << 30)
+#define THRM1_THRES(x) ((x&0x7f)<<23)
+#define THRM3_SITV(x) ((x&0x3fff)<<1)
+#define THRM1_TID (1<<2)
+#define THRM1_TIE (1<<1)
+#define THRM1_V (1<<0)
+#define SPRN_THRM2 0x3FD /* Thermal Management Register 2 */
+#define SPRN_THRM3 0x3FE /* Thermal Management Register 3 */
+#define THRM3_E (1<<0)
+#define SPRN_TLBMISS 0x3D4 /* 980 7450 TLB Miss Register */
+#define SPRN_UMMCR0 0x3A8 /* User Monitor Mode Control Register 0 */
+#define SPRN_UMMCR1 0x3AC /* User Monitor Mode Control Register 0 */
+#define SPRN_UPMC1 0x3A9 /* User Performance Counter Register 1 */
+#define SPRN_UPMC2 0x3AA /* User Performance Counter Register 2 */
+#define SPRN_UPMC3 0x3AD /* User Performance Counter Register 3 */
+#define SPRN_UPMC4 0x3AE /* User Performance Counter Register 4 */
+#define SPRN_USIA 0x3AB /* User Sampled Instruction Address Register */
+#define SPRN_VRSAVE 0x100 /* Vector Register Save Register */
+#define SPRN_XER 0x001 /* Fixed Point Exception Register */
+
+/* Bit definitions for MMCR0 and PMC1 / PMC2. */
+#define MMCR0_PMC1_CYCLES (1 << 7)
+#define MMCR0_PMC1_ICACHEMISS (5 << 7)
+#define MMCR0_PMC1_DTLB (6 << 7)
+#define MMCR0_PMC2_DCACHEMISS 0x6
+#define MMCR0_PMC2_CYCLES 0x1
+#define MMCR0_PMC2_ITLB 0x7
+#define MMCR0_PMC2_LOADMISSTIME 0x5
+
+/* Short-hand versions for a number of the above SPRNs */
+#define CTR SPRN_CTR /* Counter Register */
+#define DAR SPRN_DAR /* Data Address Register */
+#define DABR SPRN_DABR /* Data Address Breakpoint Register */
+#define DBAT0L SPRN_DBAT0L /* Data BAT 0 Lower Register */
+#define DBAT0U SPRN_DBAT0U /* Data BAT 0 Upper Register */
+#define DBAT1L SPRN_DBAT1L /* Data BAT 1 Lower Register */
+#define DBAT1U SPRN_DBAT1U /* Data BAT 1 Upper Register */
+#define DBAT2L SPRN_DBAT2L /* Data BAT 2 Lower Register */
+#define DBAT2U SPRN_DBAT2U /* Data BAT 2 Upper Register */
+#define DBAT3L SPRN_DBAT3L /* Data BAT 3 Lower Register */
+#define DBAT3U SPRN_DBAT3U /* Data BAT 3 Upper Register */
+#define DBAT4L SPRN_DBAT4L /* Data BAT 4 Lower Register */
+#define DBAT4U SPRN_DBAT4U /* Data BAT 4 Upper Register */
+#define DBAT5L SPRN_DBAT5L /* Data BAT 5 Lower Register */
+#define DBAT5U SPRN_DBAT5U /* Data BAT 5 Upper Register */
+#define DBAT6L SPRN_DBAT6L /* Data BAT 6 Lower Register */
+#define DBAT6U SPRN_DBAT6U /* Data BAT 6 Upper Register */
+#define DBAT7L SPRN_DBAT7L /* Data BAT 7 Lower Register */
+#define DBAT7U SPRN_DBAT7U /* Data BAT 7 Upper Register */
+#define DEC SPRN_DEC /* Decrement Register */
+#define DMISS SPRN_DMISS /* Data TLB Miss Register */
+#define DSISR SPRN_DSISR /* Data Storage Interrupt Status Register */
+#define EAR SPRN_EAR /* External Address Register */
+#define HASH1 SPRN_HASH1 /* Primary Hash Address Register */
+#define HASH2 SPRN_HASH2 /* Secondary Hash Address Register */
+#define HID0 SPRN_HID0 /* Hardware Implementation Register 0 */
+#define HID1 SPRN_HID1 /* Hardware Implementation Register 1 */
+#define IABR SPRN_IABR /* Instruction Address Breakpoint Register */
+#define IBAT0L SPRN_IBAT0L /* Instruction BAT 0 Lower Register */
+#define IBAT0U SPRN_IBAT0U /* Instruction BAT 0 Upper Register */
+#define IBAT1L SPRN_IBAT1L /* Instruction BAT 1 Lower Register */
+#define IBAT1U SPRN_IBAT1U /* Instruction BAT 1 Upper Register */
+#define IBAT2L SPRN_IBAT2L /* Instruction BAT 2 Lower Register */
+#define IBAT2U SPRN_IBAT2U /* Instruction BAT 2 Upper Register */
+#define IBAT3L SPRN_IBAT3L /* Instruction BAT 3 Lower Register */
+#define IBAT3U SPRN_IBAT3U /* Instruction BAT 3 Upper Register */
+#define IBAT4L SPRN_IBAT4L /* Instruction BAT 4 Lower Register */
+#define IBAT4U SPRN_IBAT4U /* Instruction BAT 4 Upper Register */
+#define IBAT5L SPRN_IBAT5L /* Instruction BAT 5 Lower Register */
+#define IBAT5U SPRN_IBAT5U /* Instruction BAT 5 Upper Register */
+#define IBAT6L SPRN_IBAT6L /* Instruction BAT 6 Lower Register */
+#define IBAT6U SPRN_IBAT6U /* Instruction BAT 6 Upper Register */
+#define IBAT7L SPRN_IBAT7L /* Instruction BAT 7 Lower Register */
+#define IBAT7U SPRN_IBAT7U /* Instruction BAT 7 Upper Register */
+#define ICMP SPRN_ICMP /* Instruction TLB Compare Register */
+#define IMISS SPRN_IMISS /* Instruction TLB Miss Register */
+#define IMMR SPRN_IMMR /* PPC 860/821 Internal Memory Map Register */
+#define L2CR SPRN_L2CR /* Classic PPC L2 cache control register */
+#define L3CR SPRN_L3CR /* PPC 745x L3 cache control register */
+#define LR SPRN_LR
+#define PVR SPRN_PVR /* Processor Version */
+#define RPA SPRN_RPA /* Required Physical Address Register */
+#define SDR1 SPRN_SDR1 /* MMU hash base register */
+#define SPR0 SPRN_SPRG0 /* Supervisor Private Registers */
+#define SPR1 SPRN_SPRG1
+#define SPR2 SPRN_SPRG2
+#define SPR3 SPRN_SPRG3
+#define SPR4 SPRN_SPRG4
+#define SPR5 SPRN_SPRG5
+#define SPR6 SPRN_SPRG6
+#define SPR7 SPRN_SPRG7
+#define SPRG0 SPRN_SPRG0
+#define SPRG1 SPRN_SPRG1
+#define SPRG2 SPRN_SPRG2
+#define SPRG3 SPRN_SPRG3
+#define SPRG4 SPRN_SPRG4
+#define SPRG5 SPRN_SPRG5
+#define SPRG6 SPRN_SPRG6
+#define SPRG7 SPRN_SPRG7
+#define SRR0 SPRN_SRR0 /* Save and Restore Register 0 */
+#define SRR1 SPRN_SRR1 /* Save and Restore Register 1 */
+#define SRR2 SPRN_SRR2 /* Save and Restore Register 2 */
+#define SRR3 SPRN_SRR3 /* Save and Restore Register 3 */
+#define ICTC SPRN_ICTC /* Instruction Cache Throttling Control Reg */
+#define THRM1 SPRN_THRM1 /* Thermal Management Register 1 */
+#define THRM2 SPRN_THRM2 /* Thermal Management Register 2 */
+#define THRM3 SPRN_THRM3 /* Thermal Management Register 3 */
+#define XER SPRN_XER
+#define TBRL SPRN_TBRL /* Time Base Read Lower Register */
+#define TBRU SPRN_TBRU /* Time Base Read Upper Register */
+#define TBWL SPRN_TBWL /* Time Base Write Lower Register */
+#define TBWU SPRN_TBWU /* Time Base Write Upper Register */
+
+/* Processor Version Register */
+
+/* Processor Version Register (PVR) field extraction */
+
+#define PVR_VER(pvr) (((pvr) >> 16) & 0xFFFF) /* Version field */
+#define PVR_REV(pvr) (((pvr) >> 0) & 0xFFFF) /* Revison field */
+
+/*
+ * IBM has further subdivided the standard PowerPC 16-bit version and
+ * revision subfields of the PVR for the PowerPC 403s into the following:
+ */
+
+#define PVR_FAM(pvr) (((pvr) >> 20) & 0xFFF) /* Family field */
+#define PVR_MEM(pvr) (((pvr) >> 16) & 0xF) /* Member field */
+#define PVR_CORE(pvr) (((pvr) >> 12) & 0xF) /* Core field */
+#define PVR_CFG(pvr) (((pvr) >> 8) & 0xF) /* Configuration field */
+#define PVR_MAJ(pvr) (((pvr) >> 4) & 0xF) /* Major revision field */
+#define PVR_MIN(pvr) (((pvr) >> 0) & 0xF) /* Minor revision field */
+
+/* Processor Version Numbers */
+
+#define PVR_403GA 0x00200000
+#define PVR_403GB 0x00200100
+#define PVR_403GC 0x00200200
+#define PVR_403GCX 0x00201400
+#define PVR_405GP 0x40110000
+#define PVR_STB03XXX 0x40310000
+#define PVR_NP405H 0x41410000
+#define PVR_NP405L 0x41610000
+#define PVR_440GP_RB 0x40120440
+#define PVR_440GP_RC1 0x40120481
+#define PVR_440GP_RC2 0x40200481
+#define PVR_440GX_RA 0x51b21850
+#define PVR_440GX_RB 0x51b21851
+#define PVR_440GX_RB1 0x51b21852
+#define PVR_601 0x00010000
+#define PVR_602 0x00050000
+#define PVR_603 0x00030000
+#define PVR_603e 0x00060000
+#define PVR_603ev 0x00070000
+#define PVR_603r 0x00071000
+#define PVR_604 0x00040000
+#define PVR_604e 0x00090000
+#define PVR_604r 0x000A0000
+#define PVR_620 0x00140000
+#define PVR_740 0x00080000
+#define PVR_750 PVR_740
+#define PVR_740P 0x10080000
+#define PVR_750P PVR_740P
+#define PVR_7400 0x000C0000
+#define PVR_7410 0x800C0000
+#define PVR_7450 0x80000000
+/*
+ * For the 8xx processors, all of them report the same PVR family for
+ * the PowerPC core. The various versions of these processors must be
+ * differentiated by the version number in the Communication Processor
+ * Module (CPM).
+ */
+#define PVR_821 0x00500000
+#define PVR_823 PVR_821
+#define PVR_850 PVR_821
+#define PVR_860 PVR_821
+#define PVR_8240 0x00810100
+#define PVR_8245 0x80811014
+#define PVR_8260 PVR_8240
+
+/* Segment Registers */
+#define SR0 0
+#define SR1 1
+#define SR2 2
+#define SR3 3
+#define SR4 4
+#define SR5 5
+#define SR6 6
+#define SR7 7
+#define SR8 8
+#define SR9 9
+#define SR10 10
+#define SR11 11
+#define SR12 12
+#define SR13 13
+#define SR14 14
+#define SR15 15
+
+
+/* returns r3 = relocated address of sym */
+/* modifies r0 */
+#define RELOC_SYM(sym) \
+ mflr r3; \
+ bl 1f; \
+1: mflr r0; \
+ mtlr r3; \
+ lis r3, 1b@ha; \
+ ori r3, r3, 1b@l; \
+ subf r0, r3, r0; \
+ lis r3, sym@ha; \
+ ori r3, r3, sym@l; \
+ add r3, r3, r0
+
diff --git a/purgatory/arch/ppc/purgatory-ppc.c b/purgatory/arch/ppc/purgatory-ppc.c
new file mode 100644
index 0000000..ab4d941
--- /dev/null
+++ b/purgatory/arch/ppc/purgatory-ppc.c
@@ -0,0 +1,7 @@
+#include <purgatory.h>
+#include "purgatory-ppc.h"
+
+void setup_arch(void)
+{
+ /* Nothing for now */
+}
diff --git a/purgatory/arch/ppc/purgatory-ppc.h b/purgatory/arch/ppc/purgatory-ppc.h
new file mode 100644
index 0000000..e931cae
--- /dev/null
+++ b/purgatory/arch/ppc/purgatory-ppc.h
@@ -0,0 +1,6 @@
+#ifndef PURGATORY_PPC_H
+#define PURGATORY_PPC_H
+
+/* nothing yet */
+
+#endif /* PURGATORY_PPC_H */
diff --git a/purgatory/arch/ppc64/Makefile b/purgatory/arch/ppc64/Makefile
new file mode 100644
index 0000000..c76794b
--- /dev/null
+++ b/purgatory/arch/ppc64/Makefile
@@ -0,0 +1,7 @@
+#
+# Purgatory ppc
+#
+
+PURGATORY_C_SRCS+=
+PURGATORY_S_SRCS+=
+
diff --git a/purgatory/arch/ppc64/include/limits.h b/purgatory/arch/ppc64/include/limits.h
new file mode 100644
index 0000000..0c6f21f
--- /dev/null
+++ b/purgatory/arch/ppc64/include/limits.h
@@ -0,0 +1,57 @@
+#ifndef LIMITS_H
+#define LIMITS_H 1
+
+/* Number of bits in a `char' */
+#define CHAR_BIT 8
+
+/* Minimum and maximum values a `signed char' can hold */
+#define SCHAR_MIN (-128)
+#define SCHAR_MAX 127
+
+/* Maximum value an `unsigned char' can hold. (Minimum is 0.) */
+#define UCHAR_MAX 255
+
+/* Minimum and maximum values a `char' can hold */
+#define CHAR_MIN SCHAR_MIN
+#define CHAR_MAX SCHAR_MAX
+
+/* Minimum and maximum values a `signed short int' can hold */
+#define SHRT_MIN (-32768)
+#define SHRT_MAX 32767
+
+/* Maximum value an `unsigned short' can hold. (Minimum is 0.) */
+#define USHRT_MAX 65535
+
+
+/* Minimum and maximum values a `signed int' can hold */
+#define INT_MIN (-INT_MAX - 1)
+#define INT_MAX 2147483647
+
+/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */
+#define UINT_MAX 4294967295U
+
+
+/* Minimum and maximum values a `signed int' can hold */
+#define INT_MIN (-INT_MAX - 1)
+#define INT_MAX 2147483647
+
+/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */
+#define UINT_MAX 4294967295U
+
+/* Minimum and maximum values a `signed long' can hold */
+#define LONG_MAX 9223372036854775807L
+#define LONG_MIN (-LONG_MAX - 1L)
+
+/* Maximum value an `unsigned long' can hold. (Minimum is 0.) */
+#define ULONG_MAX 18446744073709551615UL
+
+/* Minimum and maximum values a `signed long long' can hold */
+#define LLONG_MAX 9223372036854775807LL
+#define LLONG_MIN (-LONG_MAX - 1LL)
+
+
+/* Maximum value an `unsigned long long' can hold. (Minimum is 0.) */
+#define ULLONG_MAX 18446744073709551615ULL
+
+
+#endif /* LIMITS_H */
diff --git a/purgatory/arch/ppc64/include/stdint.h b/purgatory/arch/ppc64/include/stdint.h
new file mode 100644
index 0000000..2f9c592
--- /dev/null
+++ b/purgatory/arch/ppc64/include/stdint.h
@@ -0,0 +1,16 @@
+#ifndef STDINT_H
+#define STDINT_H
+
+typedef unsigned long size_t;
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long uint64_t;
+
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed int int32_t;
+typedef signed long int64_t;
+
+#endif /* STDINT_H */
diff --git a/purgatory/arch/x86_64/Makefile b/purgatory/arch/x86_64/Makefile
new file mode 100644
index 0000000..d08edff
--- /dev/null
+++ b/purgatory/arch/x86_64/Makefile
@@ -0,0 +1,15 @@
+#
+# Purgatory x86_64
+#
+
+PURGATORY_S_SRCS+= purgatory/arch/i386/entry32-16.S
+PURGATORY_S_SRCS+= purgatory/arch/i386/entry32-16-debug.S
+PURGATORY_S_SRCS+= purgatory/arch/x86_64/entry64-32.S
+PURGATORY_S_SRCS+= purgatory/arch/x86_64/entry64.S
+PURGATORY_S_SRCS+= purgatory/arch/x86_64/setup-x86_64.S
+PURGATORY_S_SRCS+= purgatory/arch/x86_64/stack.S
+PURGATORY_C_SRCS+= purgatory/arch/x86_64/purgatory-x86_64.c
+PURGATORY_C_SRCS+= purgatory/arch/i386/console-x86.c
+PURGATORY_C_SRCS+= purgatory/arch/i386/vga.c
+PURGATORY_C_SRCS+= purgatory/arch/i386/pic.c
+
diff --git a/purgatory/arch/x86_64/entry64-32.S b/purgatory/arch/x86_64/entry64-32.S
new file mode 100644
index 0000000..66f8a85
--- /dev/null
+++ b/purgatory/arch/x86_64/entry64-32.S
@@ -0,0 +1,134 @@
+/*
+ * purgatory: setup code
+ *
+ * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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.
+ */
+
+.data
+ .equ MSR_K6_EFER, 0xC0000080
+ .equ EFER_LME, 0x00000100
+ .equ X86_CR4_PAE, 0x00000020
+ .equ CR0_PG, 0x80000000
+
+ .text
+ .globl entry32, entry32_regs
+entry32:
+ .code64
+
+ /* Setup a gdt that should that is generally usefully */
+ lgdt gdt(%rip)
+
+ /* Switch to 32bit compatiblity mode */
+ ljmp *lm_exit_addr(%rip)
+lm_exit:
+ .code32
+
+ /* Disable paging */
+ movl %cr0, %eax
+ andl $~CR0_PG, %eax
+ movl %eax, %cr0
+
+ /* Disable long mode */
+ movl $MSR_K6_EFER, %ecx
+ rdmsr
+ andl $~EFER_LME, %eax
+ wrmsr
+
+ /* Disable PAE */
+ xorl %eax, %eax
+ movl %eax, %cr4
+
+ /* load the data segments */
+ movl $0x18, %eax /* data segment */
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %ss
+ movl %eax, %fs
+ movl %eax, %gs
+
+ /* Load the registers */
+ movl eax, %eax
+ movl ecx, %ecx
+ movl edx, %edx
+ movl esi, %esi
+ movl edi, %edi
+ movl esp, %esp
+ movl ebp, %ebp
+ movl ebx, %ebx
+
+ /* Jump to the loaded image */
+ jmpl *(eip)
+
+ .section ".rodata"
+ .balign 16
+gdt: /* 0x00 unusable segment
+ * 0x08 unused
+ * so use them as the gdt ptr
+ */
+ .word gdt_end - gdt - 1
+ .quad gdt
+ .word 0, 0, 0
+
+ /* Documented linux kernel segments */
+ /* 0x10 4GB flat code segment */
+ .word 0xFFFF, 0x0000, 0x9A00, 0x00CF
+ /* 0x18 4GB flat data segment */
+ .word 0xFFFF, 0x0000, 0x9200, 0x00CF
+
+ /* 0x20 dummy */
+ .word 0x0000, 0x0000, 0x0000, 0x000
+ /* 0x28 dummy */
+ .word 0x0000, 0x0000, 0x0000, 0x000
+ /* 0x30 dummy */
+ .word 0x0000, 0x0000, 0x0000, 0x000
+ /* 0x38 dummy */
+ .word 0x0000, 0x0000, 0x0000, 0x000
+ /* 0x40 dummy */
+ .word 0x0000, 0x0000, 0x0000, 0x000
+ /* 0x48 dummy */
+ .word 0x0000, 0x0000, 0x0000, 0x000
+ /* 0x50 dummy */
+ .word 0x0000, 0x0000, 0x0000, 0x000
+ /* 0x58 dummy */
+ .word 0x0000, 0x0000, 0x0000, 0x000
+
+ /* Segments used by the 2.5.x kernel */
+ /* 0x60 4GB flat code segment */
+ .word 0xFFFF, 0x0000, 0x9A00, 0x00CF
+ /* 0x68 4GB flat data segment */
+ .word 0xFFFF, 0x0000, 0x9200, 0x00CF
+gdt_end:
+
+ .section ".rodata"
+ .balign 4
+lm_exit_addr:
+ .long lm_exit
+ .long 0x10
+
+ .section ".rodata"
+ .balign 4
+entry32_regs:
+eax: .long 0x00000000
+ebx: .long 0x00000000
+ecx: .long 0x00000000
+edx: .long 0x00000000
+esi: .long 0x00000000
+edi: .long 0x00000000
+esp: .long 0x00000000
+ebp: .long 0x00000000
+eip: .long entry16
+ .size entry32_regs, . - entry32_regs
+
diff --git a/purgatory/arch/x86_64/entry64.S b/purgatory/arch/x86_64/entry64.S
new file mode 100644
index 0000000..1ed6786
--- /dev/null
+++ b/purgatory/arch/x86_64/entry64.S
@@ -0,0 +1,100 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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 "arch/debug.h"
+
+.text
+.code64
+ .balign 16
+ .globl entry64, entry64_regs
+entry64:
+ /* Don't worry about special registers... */
+
+ /* Setup a gdt that should be preserved */
+ lgdt gdt(%rip)
+
+ /* load the data segments */
+ movl $0x18, %eax /* data segment */
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %ss
+ movl %eax, %fs
+ movl %eax, %gs
+
+ /* In 64bit mode the code segment is meaningless */
+
+ /* Load the registers */
+ movq rax(%rip), %rax
+ movq rbx(%rip), %rbx
+ movq rcx(%rip), %rcx
+ movq rdx(%rip), %rdx
+ movq rsi(%rip), %rsi
+ movq rdi(%rip), %rdi
+ movq rsp(%rip), %rsp
+ movq rbp(%rip), %rbp
+ movq r8(%rip), %r8
+ movq r9(%rip), %r9
+ movq r10(%rip), %r10
+ movq r11(%rip), %r11
+ movq r12(%rip), %r12
+ movq r13(%rip), %r13
+ movq r14(%rip), %r14
+ movq r15(%rip), %r15
+
+ /* Jump to the new code... */
+ jmpq *rip(%rip)
+
+ .section ".rodata"
+ .balign 4
+entry64_regs:
+rax: .quad 0x00000000
+rbx: .quad 0x00000000
+rcx: .quad 0x00000000
+rdx: .quad 0x00000000
+rsi: .quad 0x00000000
+rdi: .quad 0x00000000
+rsp: .quad 0x00000000
+rbp: .quad 0x00000000
+r8: .quad 0x00000000
+r9: .quad 0x00000000
+r10: .quad 0x00000000
+r11: .quad 0x00000000
+r12: .quad 0x00000000
+r13: .quad 0x00000000
+r14: .quad 0x00000000
+r15: .quad 0x00000000
+rip: .quad entry32
+ .size entry64_regs, . - entry64_regs
+
+ .section ".rodata"
+ .balign 16
+gdt: /* 0x00 unusable segment
+ * 0x08 unused
+ * so use them as the gdt ptr
+ */
+ .word gdt_end - gdt - 1
+ .quad gdt
+ .word 0, 0, 0
+
+ /* 0x10 4GB flat code segment */
+ .word 0xFFFF, 0x0000, 0x9A00, 0x00CF
+
+ /* 0x18 4GB flat data segment */
+ .word 0xFFFF, 0x0000, 0x9200, 0x00CF
+gdt_end:
diff --git a/purgatory/arch/x86_64/include/arch/debug.h b/purgatory/arch/x86_64/include/arch/debug.h
new file mode 100644
index 0000000..39f2b16
--- /dev/null
+++ b/purgatory/arch/x86_64/include/arch/debug.h
@@ -0,0 +1,317 @@
+/* Base Address */
+#define TTYS0_BASE 0x3f8
+/* Data */
+#define TTYS0_RBR (TTYS0_BASE+0x00)
+#define TTYS0_TBR (TTYS0_BASE+0x00)
+/* Control */
+#define TTYS0_IER (TTYS0_BASE+0x01)
+#define TTYS0_IIR (TTYS0_BASE+0x02)
+#define TTYS0_FCR (TTYS0_BASE+0x02)
+#define TTYS0_LCR (TTYS0_BASE+0x03)
+#define TTYS0_MCR (TTYS0_BASE+0x04)
+
+#define TTYS0_DLL (TTYS0_BASE+0x00)
+#define TTYS0_DLM (TTYS0_BASE+0x01)
+/* Status */
+#define TTYS0_LSR (TTYS0_BASE+0x05)
+#define TTYS0_MSR (TTYS0_BASE+0x06)
+#define TTYS0_SCR (TTYS0_BASE+0x07)
+
+#define TTYS0_BAUD 9600
+#define TTYS0_DIV (115200/TTYS0_BAUD)
+#define TTYS0_DIV_LO (TTYS0_DIV&0xFF)
+#define TTYS0_DIV_HI ((TTYS0_DIV >> 8)&0xFF)
+
+#if ((115200%TTYS0_BAUD) != 0)
+#error Bad ttyS0 baud rate
+#endif
+
+#define TTYS0_INIT \
+ /* disable interrupts */ \
+ movb $0x00, %al ; \
+ movw $TTYS0_IER, %dx ; \
+ outb %al, %dx ; \
+ ; \
+ /* enable fifos */ \
+ movb $0x01, %al ; \
+ movw $TTYS0_FCR, %dx ; \
+ outb %al, %dx ; \
+ ; \
+ /* Set Baud Rate Divisor to TTYS0_BAUD */ \
+ movw $TTYS0_LCR, %dx ; \
+ movb $0x83, %al ; \
+ outb %al, %dx ; \
+ ; \
+ movw $TTYS0_DLL, %dx ; \
+ movb $TTYS0_DIV_LO, %al ; \
+ outb %al, %dx ; \
+ ; \
+ movw $TTYS0_DLM, %dx ; \
+ movb $TTYS0_DIV_HI, %al ; \
+ outb %al, %dx ; \
+ ; \
+ movw $TTYS0_LCR, %dx ; \
+ movb $0x03, %al ; \
+ outb %al, %dx
+
+
+ /* uses: ax, dx */
+#define TTYS0_TX_AL \
+ mov %al, %ah ; \
+9: mov $TTYS0_LSR, %dx ; \
+ inb %dx, %al ; \
+ test $0x20, %al ; \
+ je 9b ; \
+ mov $TTYS0_TBR, %dx ; \
+ mov %ah, %al ; \
+ outb %al, %dx
+
+ /* uses: ax, dx */
+#define TTYS0_TX_CHAR(byte) \
+ mov byte, %al ; \
+ TTYS0_TX_AL
+
+ /* uses: eax, dx */
+#define TTYS0_TX_HEX32(lword) \
+ mov lword, %eax ; \
+ shr $28, %eax ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ shr $24, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ shr $20, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ shr $16, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ shr $12, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ shr $8, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ shr $4, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %eax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL
+
+ /* uses: rax, dx */
+#define TTYS0_TX_HEX64(lword) \
+ mov lword, %rax ; \
+ shr $60, %rax ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $56, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $52, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $48, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $44, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $40, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $36, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $32, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $28, %rax ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $24, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $20, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $16, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $12, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $8, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ shr $4, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL ; \
+ ; \
+ mov lword, %rax ; \
+ and $0x0f, %al ; \
+ add $'0', %al ; \
+ cmp $'9', %al ; \
+ jle 9f ; \
+ add $39, %al ; \
+9: ; \
+ TTYS0_TX_AL
+
+
+#define DEBUG(x) TTYS0_TX_CHAR($x) ; TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
+#define DEBUG_TX_HEX32(x) TTYS0_TX_HEX32(x); TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
+#define DEBUG_TX_HEX64(x) TTYS0_TX_HEX64(x); TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
+
diff --git a/purgatory/arch/x86_64/include/arch/io.h b/purgatory/arch/x86_64/include/arch/io.h
new file mode 100644
index 0000000..13ad887
--- /dev/null
+++ b/purgatory/arch/x86_64/include/arch/io.h
@@ -0,0 +1,98 @@
+#ifndef ARCH_IO_H
+#define ARCH_IO_H
+
+#include <stdint.h>
+/* Helper functions for directly doing I/O */
+
+extern inline uint8_t inb(uint16_t port)
+{
+ uint8_t result;
+
+ __asm__ __volatile__ (
+ "inb %w1,%0"
+ :"=a" (result)
+ :"Nd" (port));
+ return result;
+}
+
+extern inline uint16_t inw(uint16_t port)
+{
+ uint16_t result;
+
+ __asm__ __volatile__ (
+ "inw %w1,%0"
+ :"=a" (result)
+ :"Nd" (port));
+ return result;
+}
+
+extern inline uint32_t inl(uint32_t port)
+{
+ uint32_t result;
+
+ __asm__ __volatile__ (
+ "inl %w1,%0"
+ :"=a" (result)
+ :"Nd" (port));
+ return result;
+}
+
+extern inline void outb (uint8_t value, uint16_t port)
+{
+ __asm__ __volatile__ (
+ "outb %b0,%w1"
+ :
+ :"a" (value), "Nd" (port));
+}
+
+extern inline void outw (uint16_t value, uint16_t port)
+{
+ __asm__ __volatile__ (
+ "outw %w0,%w1"
+ :
+ :"a" (value), "Nd" (port));
+}
+
+extern inline void outl (uint32_t value, uint16_t port)
+{
+ __asm__ __volatile__ (
+ "outl %0,%w1"
+ :
+ :"a" (value), "Nd" (port));
+}
+
+
+/*
+ * readX/writeX() are used to access memory mapped devices. On some
+ * architectures the memory mapped IO stuff needs to be accessed
+ * differently. On the x86 architecture, we just read/write the
+ * memory location directly.
+ */
+
+static inline unsigned char readb(const volatile void *addr)
+{
+ return *(volatile unsigned char *) addr;
+}
+static inline unsigned short readw(const volatile void *addr)
+{
+ return *(volatile unsigned short *) addr;
+}
+static inline unsigned int readl(const volatile void *addr)
+{
+ return *(volatile unsigned int *) addr;
+}
+
+static inline void writeb(unsigned char b, volatile void *addr)
+{
+ *(volatile unsigned char *) addr = b;
+}
+static inline void writew(unsigned short b, volatile void *addr)
+{
+ *(volatile unsigned short *) addr = b;
+}
+static inline void writel(unsigned int b, volatile void *addr)
+{
+ *(volatile unsigned int *) addr = b;
+}
+
+#endif /* ARCH_IO_H */
diff --git a/purgatory/arch/x86_64/include/limits.h b/purgatory/arch/x86_64/include/limits.h
new file mode 100644
index 0000000..0c6f21f
--- /dev/null
+++ b/purgatory/arch/x86_64/include/limits.h
@@ -0,0 +1,57 @@
+#ifndef LIMITS_H
+#define LIMITS_H 1
+
+/* Number of bits in a `char' */
+#define CHAR_BIT 8
+
+/* Minimum and maximum values a `signed char' can hold */
+#define SCHAR_MIN (-128)
+#define SCHAR_MAX 127
+
+/* Maximum value an `unsigned char' can hold. (Minimum is 0.) */
+#define UCHAR_MAX 255
+
+/* Minimum and maximum values a `char' can hold */
+#define CHAR_MIN SCHAR_MIN
+#define CHAR_MAX SCHAR_MAX
+
+/* Minimum and maximum values a `signed short int' can hold */
+#define SHRT_MIN (-32768)
+#define SHRT_MAX 32767
+
+/* Maximum value an `unsigned short' can hold. (Minimum is 0.) */
+#define USHRT_MAX 65535
+
+
+/* Minimum and maximum values a `signed int' can hold */
+#define INT_MIN (-INT_MAX - 1)
+#define INT_MAX 2147483647
+
+/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */
+#define UINT_MAX 4294967295U
+
+
+/* Minimum and maximum values a `signed int' can hold */
+#define INT_MIN (-INT_MAX - 1)
+#define INT_MAX 2147483647
+
+/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */
+#define UINT_MAX 4294967295U
+
+/* Minimum and maximum values a `signed long' can hold */
+#define LONG_MAX 9223372036854775807L
+#define LONG_MIN (-LONG_MAX - 1L)
+
+/* Maximum value an `unsigned long' can hold. (Minimum is 0.) */
+#define ULONG_MAX 18446744073709551615UL
+
+/* Minimum and maximum values a `signed long long' can hold */
+#define LLONG_MAX 9223372036854775807LL
+#define LLONG_MIN (-LONG_MAX - 1LL)
+
+
+/* Maximum value an `unsigned long long' can hold. (Minimum is 0.) */
+#define ULLONG_MAX 18446744073709551615ULL
+
+
+#endif /* LIMITS_H */
diff --git a/purgatory/arch/x86_64/include/stdint.h b/purgatory/arch/x86_64/include/stdint.h
new file mode 100644
index 0000000..2f9c592
--- /dev/null
+++ b/purgatory/arch/x86_64/include/stdint.h
@@ -0,0 +1,16 @@
+#ifndef STDINT_H
+#define STDINT_H
+
+typedef unsigned long size_t;
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long uint64_t;
+
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed int int32_t;
+typedef signed long int64_t;
+
+#endif /* STDINT_H */
diff --git a/purgatory/arch/x86_64/purgatory-x86_64.c b/purgatory/arch/x86_64/purgatory-x86_64.c
new file mode 100644
index 0000000..f839ab5
--- /dev/null
+++ b/purgatory/arch/x86_64/purgatory-x86_64.c
@@ -0,0 +1,12 @@
+#include <arch/io.h>
+#include <purgatory.h>
+#include "purgatory-x86_64.h"
+
+uint8_t reset_vga = 0;
+uint8_t legacy_pic = 0;
+
+void setup_arch(void)
+{
+ if (reset_vga) x86_reset_vga();
+ if (legacy_pic) x86_setup_legacy_pic();
+}
diff --git a/purgatory/arch/x86_64/purgatory-x86_64.h b/purgatory/arch/x86_64/purgatory-x86_64.h
new file mode 100644
index 0000000..209edea
--- /dev/null
+++ b/purgatory/arch/x86_64/purgatory-x86_64.h
@@ -0,0 +1,4 @@
+#ifndef PURGATORY_X86_64_H
+#define PURGATORY_X86_64_H
+#include "../i386/purgatory-x86.h"
+#endif /* PURGATORY_X86_64_H */
diff --git a/purgatory/arch/x86_64/setup-x86_64.S b/purgatory/arch/x86_64/setup-x86_64.S
new file mode 100644
index 0000000..d3b5993
--- /dev/null
+++ b/purgatory/arch/x86_64/setup-x86_64.S
@@ -0,0 +1,73 @@
+/*
+ * purgatory: setup code
+ *
+ * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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 "arch/debug.h"
+
+
+#undef i386
+
+ .text
+ .globl purgatory_start
+ .balign 16
+purgatory_start:
+ .code64
+
+ /* Load a gdt so I know what the segment registers are */
+ lgdt gdt(%rip)
+
+ /* load the data segments */
+ movl $0x18, %eax /* data segment */
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %ss
+ movl %eax, %fs
+ movl %eax, %gs
+
+ /* In 64bit mode the code segment is meaningless */
+
+ /* Setup a stack */
+ movq $lstack_end, %rsp
+
+ /* Call the C code */
+ call purgatory
+ jmp entry64
+
+ .section ".rodata"
+ .balign 16
+gdt: /* 0x00 unusable segment
+ * 0x08 unused
+ * so use them as the gdt ptr
+ */
+ .word gdt_end - gdt - 1
+ .quad gdt
+ .word 0, 0, 0
+
+ /* 0x10 4GB flat code segment */
+ .word 0xFFFF, 0x0000, 0x9A00, 0x00AF
+
+ /* 0x18 4GB flat data segment */
+ .word 0xFFFF, 0x0000, 0x9200, 0x00CF
+gdt_end:
+
+ .bss
+ .balign 4096
+lstack:
+ .skip 4096
+lstack_end:
+
diff --git a/purgatory/arch/x86_64/stack.S b/purgatory/arch/x86_64/stack.S
new file mode 100644
index 0000000..4188ea3
--- /dev/null
+++ b/purgatory/arch/x86_64/stack.S
@@ -0,0 +1,44 @@
+/*
+ * purgatory: stack
+ *
+ * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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.
+ */
+
+ /* A stack for the loaded kernel.
+ * Seperate and in the data section so it can be prepopulated.
+ */
+ .data
+ .balign 4096
+ .globl stack, stack_end
+ .globl stack_arg32_1, stack_arg32_2, stack_arg32_3 ,stack_arg32_4
+ .globl stack_arg32_5, stack_arg32_6, stack_arg32_7 ,stack_arg32_8
+ .globl stack_arg64_1, stack_arg64_2, stack_arg64_3 ,stack_arg64_4
+
+stack:
+ .skip 4096 - (8*4)
+stack_arg64_4: ; .size stack_arg64_4, 8
+stack_arg32_8: .long 0 ; .size stack_arg32_8, 4
+stack_arg32_7: .long 0 ; .size stack_arg32_7, 4
+stack_arg64_3: ; .size stack_arg64_3, 8
+stack_arg32_6: .long 0 ; .size stack_arg32_6, 4
+stack_arg32_5: .long 0 ; .size stack_arg32_5, 4
+stack_arg64_2: ; .size stack_arg64_2, 8
+stack_arg32_4: .long 0 ; .size stack_arg32_4, 4
+stack_arg32_3: .long 0 ; .size stack_arg32_3, 4
+stack_arg64_1: ; .size stack_arg64_1, 8
+stack_arg32_2: .long 0 ; .size stack_arg32_2, 4
+stack_arg32_1: .long 0 ; .size stack_arg32_1, 4
+stack_end:
diff --git a/purgatory/include/purgatory.h b/purgatory/include/purgatory.h
new file mode 100644
index 0000000..93037f2
--- /dev/null
+++ b/purgatory/include/purgatory.h
@@ -0,0 +1,8 @@
+#ifndef PURGATORY_H
+#define PURGATORY_H
+
+void putchar(int ch);
+void printf(const char *fmt, ...);
+void setup_arch(void);
+
+#endif /* PURGATORY_H */
diff --git a/purgatory/include/string.h b/purgatory/include/string.h
new file mode 100644
index 0000000..87cc4e1
--- /dev/null
+++ b/purgatory/include/string.h
@@ -0,0 +1,10 @@
+#ifndef STRING_H
+#define STRING_H
+
+size_t strnlen(const char *s, size_t max);
+void* memset(void* s, int c, size_t n);
+void* memcpy(void *dest, const void *src, size_t len);
+int memcmp(void *src1, void *src2, size_t len);
+
+
+#endif /* STRING_H */
diff --git a/purgatory/printf.c b/purgatory/printf.c
new file mode 100644
index 0000000..962683d
--- /dev/null
+++ b/purgatory/printf.c
@@ -0,0 +1,128 @@
+#include <stdarg.h>
+#include <limits.h>
+#include <stdint.h>
+#include <purgatory.h>
+#include <string.h>
+
+/*
+ * Output
+ * =============================================================================
+ */
+
+#define LONG_LONG_SHIFT ((int)((sizeof(unsigned long long)*CHAR_BIT) - 4))
+#define LONG_SHIFT ((int)((sizeof(unsigned long)*CHAR_BIT) - 4))
+#define INT_SHIFT ((int)((sizeof(unsigned int)*CHAR_BIT) - 4))
+#define SHRT_SHIFT ((int)((sizeof(unsigned short)*CHAR_BIT) - 4))
+#define CHAR_SHIFT ((int)((sizeof(unsigned char)*CHAR_BIT) - 4))
+
+/**************************************************************************
+PRINTF and friends
+
+ Formats:
+ %x - 4 bytes int (8 hex digits, lower case)
+ %X - 4 bytes int (8 hex digits, upper case)
+ %lx - 8 bytes long (16 hex digits, lower case)
+ %lX - 8 bytes long (16 hex digits, upper case)
+ %hx - 2 bytes int (4 hex digits, lower case)
+ %hX - 2 bytes int (4 hex digits, upper case)
+ %hhx - 1 byte int (2 hex digits, lower case)
+ %hhX - 1 byte int (2 hex digits, upper case)
+ - optional # prefixes 0x or 0X
+ %d - decimal int
+ %c - char
+ %s - string
+ Note: width specification not supported
+**************************************************************************/
+void printf(const char *fmt, ...)
+{
+ va_list args;
+ char *p;
+ va_start(args, fmt);
+ for ( ; *fmt != '\0'; ++fmt) {
+ if (*fmt != '%') {
+ putchar(*fmt);
+ continue;
+ }
+ if (*++fmt == 's') {
+ for(p = va_arg(args, char *); *p != '\0'; p++)
+ putchar(*p);
+ }
+ else { /* Length of item is bounded */
+ char tmp[40], *q = tmp;
+ int shift = INT_SHIFT;
+ if (*fmt == 'L') {
+ shift = LONG_LONG_SHIFT;
+ fmt++;
+ }
+ else if (*fmt == 'l') {
+ shift = LONG_SHIFT;
+ fmt++;
+ }
+ else if (*fmt == 'h') {
+ shift = SHRT_SHIFT;
+ fmt++;
+ if (*fmt == 'h') {
+ shift = CHAR_SHIFT;
+ fmt++;
+ }
+ }
+
+ /*
+ * Before each format q points to tmp buffer
+ * After each format q points past end of item
+ */
+ if ((*fmt | 0x20) == 'x') {
+ /* With x86 gcc, sizeof(long) == sizeof(int) */
+ unsigned long long h;
+ int ncase;
+ if (shift > LONG_SHIFT) {
+ h = va_arg(args, unsigned long long);
+ }
+ else if (shift > INT_SHIFT) {
+ h = va_arg(args, unsigned long);
+ } else {
+ h = va_arg(args, unsigned int);
+ }
+ ncase = (*fmt & 0x20);
+ for ( ; shift >= 0; shift -= 4)
+ *q++ = "0123456789ABCDEF"[(h >> shift) & 0xF] | ncase;
+ }
+ else if (*fmt == 'd') {
+ char *r;
+ long i;
+ if (shift > LONG_SHIFT) {
+ i = va_arg(args, long long);
+ }
+ else if (shift > INT_SHIFT) {
+ i = va_arg(args, long);
+ } else {
+ i = va_arg(args, int);
+ }
+ if (i < 0) {
+ *q++ = '-';
+ i = -i;
+ }
+ p = q; /* save beginning of digits */
+ do {
+ *q++ = '0' + (i % 10);
+ i /= 10;
+ } while (i);
+ /* reverse digits, stop in middle */
+ r = q; /* don't alter q */
+ while (--r > p) {
+ i = *r;
+ *r = *p;
+ *p++ = i;
+ }
+ }
+ else if (*fmt == 'c')
+ *q++ = va_arg(args, int);
+ else
+ *q++ = *fmt;
+ /* now output the saved string */
+ for (p = tmp; p < q; ++p)
+ putchar(*p);
+ }
+ }
+ va_end(args);
+}
diff --git a/purgatory/purgatory.c b/purgatory/purgatory.c
new file mode 100644
index 0000000..97fc638
--- /dev/null
+++ b/purgatory/purgatory.c
@@ -0,0 +1,47 @@
+#include <stdarg.h>
+#include <limits.h>
+#include <stdint.h>
+#include <purgatory.h>
+#include <sha256.h>
+#include <string.h>
+#include "../kexec/kexec-sha256.h"
+
+struct sha256_region sha256_regions[SHA256_REGIONS] = {};
+sha256_digest_t sha256_digest = { };
+
+void verify_sha256_digest(void)
+{
+ struct sha256_region *ptr, *end;
+ sha256_digest_t digest;
+ int i;
+ sha256_context ctx;
+ sha256_starts(&ctx);
+ end = &sha256_regions[sizeof(sha256_regions)/sizeof(sha256_regions[0])];
+ for(ptr = sha256_regions; ptr < end; ptr++) {
+ sha256_update(&ctx, ptr->start, ptr->len);
+ }
+ sha256_finish(&ctx, digest);
+ if (memcmp(digest, sha256_digest, sizeof(digest)) != 0) {
+ printf("sha256 digests do not match :(\n");
+ printf(" digest: ");
+ for(i = 0; i < sizeof(digest); i++) {
+ printf("%hhx ", digest[i]);
+ }
+ printf("\n");
+ printf("sha256_digest: ");
+ for(i = 0; i < sizeof(sha256_digest); i++) {
+ printf("%hhx ", sha256_digest[i]);
+ }
+ printf("\n");
+ for(;;) {
+ /* loop forever */
+ }
+ }
+}
+
+void purgatory(void)
+{
+ printf("I'm in purgatory\n");
+ setup_arch();
+ verify_sha256_digest();
+}
diff --git a/purgatory/string.c b/purgatory/string.c
new file mode 100644
index 0000000..4f35613
--- /dev/null
+++ b/purgatory/string.c
@@ -0,0 +1,53 @@
+#include <stddef.h>
+#include <string.h>
+
+size_t strnlen(const char *s, size_t max)
+{
+ size_t len = 0;
+ while(len < max && *s) {
+ len++;
+ s++;
+ }
+ return len;
+}
+
+void* memset(void* s, int c, size_t n)
+{
+ size_t i;
+ char *ss = (char*)s;
+
+ for (i=0;i<n;i++) ss[i] = c;
+ return s;
+}
+
+
+void* memcpy(void *dest, const void *src, size_t len)
+{
+ size_t i;
+ unsigned char *d;
+ const unsigned char *s;
+ d = dest;
+ s = src;
+
+ for (i=0; i < len; i++)
+ d[i] = s[i];
+
+ return dest;
+}
+
+
+int memcmp(void *src1, void *src2, size_t len)
+{
+ unsigned char *s1, *s2;
+ size_t i;
+ s1 = src1;
+ s2 = src2;
+ for(i = 0; i < len; i++) {
+ if (*s1 != *s2) {
+ return *s2 - *s1;
+ }
+ }
+ return 0;
+
+}
+
diff --git a/util/Makefile b/util/Makefile
new file mode 100644
index 0000000..d6e8e79
--- /dev/null
+++ b/util/Makefile
@@ -0,0 +1,4 @@
+BIN_TO_HEX:= $(OBJDIR)/bin/bin-to-hex
+$(BIN_TO_HEX): util/bin-to-hex.c
+ mkdir -p $(@D)
+ $(BUILD_CC) $(BUILD_CFLAGS) $< -o $@
diff --git a/util/bin-to-hex.c b/util/bin-to-hex.c
new file mode 100644
index 0000000..5906f93
--- /dev/null
+++ b/util/bin-to-hex.c
@@ -0,0 +1,25 @@
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+ int c;
+ int i;
+ const char *name = argv[1];
+ printf("#include <stddef.h>\n");
+ printf("const unsigned char %s[] = {\n", name);
+ i = 0;
+ while((c = getchar()) != EOF) {
+ if ((i % 16) != 0) {
+ putchar(' ');
+ }
+ printf("0x%02x,", c);
+ i++;
+ if ((i %16) == 0) {
+ putchar('\n');
+ }
+ }
+ putchar('\n');
+ printf("};\n");
+ printf("size_t %s_size = sizeof(%s);\n", name, name);
+ return 0;
+}
diff --git a/util_lib/Makefile b/util_lib/Makefile
new file mode 100644
index 0000000..4e1a01d
--- /dev/null
+++ b/util_lib/Makefile
@@ -0,0 +1,23 @@
+#
+# Utility function library
+#
+UTIL_LIB_SRCS:=util_lib/compute_ip_checksum.c
+UTIL_LIB_SRCS+=util_lib/sha256.c
+UTIL_LIB_OBJS:=$(patsubst %.c, $(OBJDIR)/%.o, $(UTIL_LIB_SRCS))
+UTIL_LIB_DEPS:=$(patsubst %.c, $(OBJDIR)/%.d, $(UTIL_LIB_SRCS))
+UTIL_LIB:=$(OBJDIR)/libutil.a
+
+include $(UTIL_LIB_DEPS)
+
+$(UTIL_LIB_DEPS): $(OBJDIR)/%.d: %.c
+ $(MKDIR) -p $(@D)
+ $(CC) $(CFLAGS) -M $< | sed -e 's|$(patsubst %.d,%.o,$(@F))|$(patsubst %.d,%.o,$(@))|' > $@
+
+$(UTIL_LIB_OBJS): $(OBJDIR)/%.o: %.c $(OBJDIR)/%.d
+ $(MKDIR) -p $(@D)
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+$(UTIL_LIB): $(UTIL_LIB_OBJS)
+ $(MKDIR) -p $(@D)
+ $(AR) rs $(UTIL_LIB) $(UTIL_LIB_OBJS)
+
diff --git a/util_lib/compute_ip_checksum.c b/util_lib/compute_ip_checksum.c
new file mode 100644
index 0000000..39a371b
--- /dev/null
+++ b/util_lib/compute_ip_checksum.c
@@ -0,0 +1,102 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * 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 <stdint.h>
+#include <ip_checksum.h>
+#include <string.h>
+
+unsigned long compute_ip_checksum(void *addr, unsigned long length)
+{
+ uint16_t *ptr;
+ unsigned long sum;
+ unsigned long len;
+ unsigned long laddr;
+ /* compute an ip style checksum */
+ laddr = (unsigned long )addr;
+ sum = 0;
+ if (laddr & 1) {
+ uint16_t buffer;
+ unsigned char *ptr;
+ /* copy the first byte into a 2 byte buffer.
+ * This way automatically handles the endian question
+ * of which byte (low or high) the last byte goes in.
+ */
+ buffer = 0;
+ ptr = addr;
+ memcpy(&buffer, ptr, 1);
+ sum += buffer;
+ if (sum > 0xFFFF)
+ sum -= 0xFFFF;
+ length -= 1;
+ addr = ptr +1;
+
+ }
+ len = length >> 1;
+ ptr = addr;
+ while (len--) {
+ sum += *(ptr++);
+ if (sum > 0xFFFF)
+ sum -= 0xFFFF;
+ }
+ addr = ptr;
+ if (length & 1) {
+ uint16_t buffer;
+ unsigned char *ptr;
+ /* copy the last byte into a 2 byte buffer.
+ * This way automatically handles the endian question
+ * of which byte (low or high) the last byte goes in.
+ */
+ buffer = 0;
+ ptr = addr;
+ memcpy(&buffer, ptr, 1);
+ sum += buffer;
+ if (sum > 0xFFFF)
+ sum -= 0xFFFF;
+ }
+ return (~sum) & 0xFFFF;
+
+}
+
+unsigned long add_ip_checksums(unsigned long offset, unsigned long sum, unsigned long new)
+{
+ unsigned long checksum;
+ sum = ~sum & 0xFFFF;
+ new = ~new & 0xFFFF;
+ if (offset & 1) {
+ /* byte swap the sum if it came from an odd offset
+ * since the computation is endian independant this
+ * works.
+ */
+ new = ((new >> 8) & 0xff) | ((new << 8) & 0xff00);
+ }
+ checksum = sum + new;
+ if (checksum > 0xFFFF) {
+ checksum -= 0xFFFF;
+ }
+ return (~checksum) & 0xFFFF;
+}
+
+unsigned long negate_ip_checksum(unsigned long sum)
+{
+ sum = ~sum & 0xFFFF;
+
+ sum = 0xFFFF - sum;
+
+ return ~sum & 0xFFFF;
+}
diff --git a/util_lib/include/ip_checksum.h b/util_lib/include/ip_checksum.h
new file mode 100644
index 0000000..5559fa4
--- /dev/null
+++ b/util_lib/include/ip_checksum.h
@@ -0,0 +1,8 @@
+#ifndef IP_CHECKSUM_H
+#define IP_CHECKSUM_H
+
+unsigned long compute_ip_checksum(void *addr, unsigned long length);
+unsigned long add_ip_checksums(unsigned long offset, unsigned long sum, unsigned long new);
+unsigned long negate_ip_checksum(unsigned long sum);
+
+#endif /* IP_CHECKSUM_H */
diff --git a/util_lib/include/sha256.h b/util_lib/include/sha256.h
new file mode 100644
index 0000000..b8278a1
--- /dev/null
+++ b/util_lib/include/sha256.h
@@ -0,0 +1,21 @@
+#ifndef SHA256_H
+#define SHA256_H
+
+#include <stdint.h>
+
+typedef struct
+{
+ size_t total[2];
+ uint32_t state[8];
+ uint8_t buffer[64];
+}
+sha256_context;
+
+typedef uint8_t sha256_digest_t[32];
+
+void sha256_starts( sha256_context *ctx );
+void sha256_update( sha256_context *ctx, const uint8_t *input, size_t length );
+void sha256_finish( sha256_context *ctx, sha256_digest_t digest );
+
+
+#endif /* SHA256_H */
diff --git a/util_lib/sha256.c b/util_lib/sha256.c
new file mode 100644
index 0000000..2e61a31
--- /dev/null
+++ b/util_lib/sha256.c
@@ -0,0 +1,368 @@
+/*
+ * FIPS-180-2 compliant SHA-256 implementation
+ *
+ * Copyright (C) 2001-2003 Christophe Devine
+ *
+ * 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
+ */
+
+#include <string.h>
+
+#include "sha256.h"
+
+#define GET_UINT32(n,b,i) \
+{ \
+ (n) = ( (uint32_t) (b)[(i) ] << 24 ) | \
+ ( (uint32_t) (b)[(i) + 1] << 16 ) | \
+ ( (uint32_t) (b)[(i) + 2] << 8 ) | \
+ ( (uint32_t) (b)[(i) + 3] ); \
+}
+
+#define PUT_UINT32(n,b,i) \
+{ \
+ (b)[(i) ] = (uint8_t) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (uint8_t) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (uint8_t) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (uint8_t) ( (n) ); \
+}
+
+void sha256_starts( sha256_context *ctx )
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ ctx->state[0] = 0x6A09E667;
+ ctx->state[1] = 0xBB67AE85;
+ ctx->state[2] = 0x3C6EF372;
+ ctx->state[3] = 0xA54FF53A;
+ ctx->state[4] = 0x510E527F;
+ ctx->state[5] = 0x9B05688C;
+ ctx->state[6] = 0x1F83D9AB;
+ ctx->state[7] = 0x5BE0CD19;
+}
+
+void sha256_process( sha256_context *ctx, const uint8_t data[64] )
+{
+ uint32_t temp1, temp2, W[64];
+ uint32_t A, B, C, D, E, F, G, H;
+
+ GET_UINT32( W[0], data, 0 );
+ GET_UINT32( W[1], data, 4 );
+ GET_UINT32( W[2], data, 8 );
+ GET_UINT32( W[3], data, 12 );
+ GET_UINT32( W[4], data, 16 );
+ GET_UINT32( W[5], data, 20 );
+ GET_UINT32( W[6], data, 24 );
+ GET_UINT32( W[7], data, 28 );
+ GET_UINT32( W[8], data, 32 );
+ GET_UINT32( W[9], data, 36 );
+ GET_UINT32( W[10], data, 40 );
+ GET_UINT32( W[11], data, 44 );
+ GET_UINT32( W[12], data, 48 );
+ GET_UINT32( W[13], data, 52 );
+ GET_UINT32( W[14], data, 56 );
+ GET_UINT32( W[15], data, 60 );
+
+#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
+#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
+
+#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
+#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
+
+#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
+#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
+
+#define F0(x,y,z) ((x & y) | (z & (x | y)))
+#define F1(x,y,z) (z ^ (x & (y ^ z)))
+
+#define R(t) \
+( \
+ W[t] = S1(W[t - 2]) + W[t - 7] + \
+ S0(W[t - 15]) + W[t - 16] \
+)
+
+#define P(a,b,c,d,e,f,g,h,x,K) \
+{ \
+ temp1 = h + S3(e) + F1(e,f,g) + K + x; \
+ temp2 = S2(a) + F0(a,b,c); \
+ d += temp1; h = temp1 + temp2; \
+}
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+ E = ctx->state[4];
+ F = ctx->state[5];
+ G = ctx->state[6];
+ H = ctx->state[7];
+
+ P( A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98 );
+ P( H, A, B, C, D, E, F, G, W[ 1], 0x71374491 );
+ P( G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF );
+ P( F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5 );
+ P( E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B );
+ P( D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1 );
+ P( C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4 );
+ P( B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5 );
+ P( A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98 );
+ P( H, A, B, C, D, E, F, G, W[ 9], 0x12835B01 );
+ P( G, H, A, B, C, D, E, F, W[10], 0x243185BE );
+ P( F, G, H, A, B, C, D, E, W[11], 0x550C7DC3 );
+ P( E, F, G, H, A, B, C, D, W[12], 0x72BE5D74 );
+ P( D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE );
+ P( C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7 );
+ P( B, C, D, E, F, G, H, A, W[15], 0xC19BF174 );
+ P( A, B, C, D, E, F, G, H, R(16), 0xE49B69C1 );
+ P( H, A, B, C, D, E, F, G, R(17), 0xEFBE4786 );
+ P( G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6 );
+ P( F, G, H, A, B, C, D, E, R(19), 0x240CA1CC );
+ P( E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F );
+ P( D, E, F, G, H, A, B, C, R(21), 0x4A7484AA );
+ P( C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC );
+ P( B, C, D, E, F, G, H, A, R(23), 0x76F988DA );
+ P( A, B, C, D, E, F, G, H, R(24), 0x983E5152 );
+ P( H, A, B, C, D, E, F, G, R(25), 0xA831C66D );
+ P( G, H, A, B, C, D, E, F, R(26), 0xB00327C8 );
+ P( F, G, H, A, B, C, D, E, R(27), 0xBF597FC7 );
+ P( E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3 );
+ P( D, E, F, G, H, A, B, C, R(29), 0xD5A79147 );
+ P( C, D, E, F, G, H, A, B, R(30), 0x06CA6351 );
+ P( B, C, D, E, F, G, H, A, R(31), 0x14292967 );
+ P( A, B, C, D, E, F, G, H, R(32), 0x27B70A85 );
+ P( H, A, B, C, D, E, F, G, R(33), 0x2E1B2138 );
+ P( G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC );
+ P( F, G, H, A, B, C, D, E, R(35), 0x53380D13 );
+ P( E, F, G, H, A, B, C, D, R(36), 0x650A7354 );
+ P( D, E, F, G, H, A, B, C, R(37), 0x766A0ABB );
+ P( C, D, E, F, G, H, A, B, R(38), 0x81C2C92E );
+ P( B, C, D, E, F, G, H, A, R(39), 0x92722C85 );
+ P( A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1 );
+ P( H, A, B, C, D, E, F, G, R(41), 0xA81A664B );
+ P( G, H, A, B, C, D, E, F, R(42), 0xC24B8B70 );
+ P( F, G, H, A, B, C, D, E, R(43), 0xC76C51A3 );
+ P( E, F, G, H, A, B, C, D, R(44), 0xD192E819 );
+ P( D, E, F, G, H, A, B, C, R(45), 0xD6990624 );
+ P( C, D, E, F, G, H, A, B, R(46), 0xF40E3585 );
+ P( B, C, D, E, F, G, H, A, R(47), 0x106AA070 );
+ P( A, B, C, D, E, F, G, H, R(48), 0x19A4C116 );
+ P( H, A, B, C, D, E, F, G, R(49), 0x1E376C08 );
+ P( G, H, A, B, C, D, E, F, R(50), 0x2748774C );
+ P( F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5 );
+ P( E, F, G, H, A, B, C, D, R(52), 0x391C0CB3 );
+ P( D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A );
+ P( C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F );
+ P( B, C, D, E, F, G, H, A, R(55), 0x682E6FF3 );
+ P( A, B, C, D, E, F, G, H, R(56), 0x748F82EE );
+ P( H, A, B, C, D, E, F, G, R(57), 0x78A5636F );
+ P( G, H, A, B, C, D, E, F, R(58), 0x84C87814 );
+ P( F, G, H, A, B, C, D, E, R(59), 0x8CC70208 );
+ P( E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA );
+ P( D, E, F, G, H, A, B, C, R(61), 0xA4506CEB );
+ P( C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7 );
+ P( B, C, D, E, F, G, H, A, R(63), 0xC67178F2 );
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+ ctx->state[4] += E;
+ ctx->state[5] += F;
+ ctx->state[6] += G;
+ ctx->state[7] += H;
+}
+
+void sha256_update( sha256_context *ctx, const uint8_t *input, size_t length )
+{
+ size_t left, fill;
+
+ if( ! length ) return;
+
+ left = ctx->total[0] & 0x3F;
+ fill = 64 - left;
+
+ ctx->total[0] += length;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if( ctx->total[0] < length )
+ ctx->total[1]++;
+
+ if( left && length >= fill )
+ {
+ memcpy( ctx->buffer + left, input, fill );
+ sha256_process( ctx, ctx->buffer );
+ length -= fill;
+ input += fill;
+ left = 0;
+ }
+
+ while( length >= 64 )
+ {
+ sha256_process( ctx, input );
+ length -= 64;
+ input += 64;
+ }
+
+ if( length )
+ {
+ memcpy(ctx->buffer + left, input, length);
+ }
+}
+
+static uint8_t sha256_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+void sha256_finish( sha256_context *ctx, sha256_digest_t digest )
+{
+ uint32_t last, padn;
+ uint32_t high, low;
+ uint8_t msglen[8];
+
+ high = ( ctx->total[0] >> 29 )
+ | ( ctx->total[1] << 3 );
+ low = ( ctx->total[0] << 3 );
+
+ PUT_UINT32( high, msglen, 0 );
+ PUT_UINT32( low, msglen, 4 );
+
+ last = ctx->total[0] & 0x3F;
+ padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+ sha256_update( ctx, sha256_padding, padn );
+ sha256_update( ctx, msglen, 8 );
+
+ PUT_UINT32( ctx->state[0], digest, 0 );
+ PUT_UINT32( ctx->state[1], digest, 4 );
+ PUT_UINT32( ctx->state[2], digest, 8 );
+ PUT_UINT32( ctx->state[3], digest, 12 );
+ PUT_UINT32( ctx->state[4], digest, 16 );
+ PUT_UINT32( ctx->state[5], digest, 20 );
+ PUT_UINT32( ctx->state[6], digest, 24 );
+ PUT_UINT32( ctx->state[7], digest, 28 );
+}
+
+#ifdef TEST
+
+#include <stdlib.h>
+#include <stdio.h>
+
+/*
+ * those are the standard FIPS-180-2 test vectors
+ */
+
+static char *msg[] =
+{
+ "abc",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ NULL
+};
+
+static char *val[] =
+{
+ "ba7816bf8f01cfea414140de5dae2223" \
+ "b00361a396177a9cb410ff61f20015ad",
+ "248d6a61d20638b8e5c026930c3e6039" \
+ "a33ce45964ff2167f6ecedd419db06c1",
+ "cdc76e5c9914fb9281a1c7e284d73e67" \
+ "f1809a48a497200e046d39ccc7112cd0"
+};
+
+int main( int argc, char *argv[] )
+{
+ FILE *f;
+ int i, j;
+ char output[65];
+ sha256_context ctx;
+ unsigned char buf[1000];
+ unsigned char sha256sum[32];
+
+ if( argc < 2 )
+ {
+ printf( "\n SHA-256 Validation Tests:\n\n" );
+
+ for( i = 0; i < 3; i++ )
+ {
+ printf( " Test %d ", i + 1 );
+
+ sha256_starts( &ctx );
+
+ if( i < 2 )
+ {
+ sha256_update( &ctx, (uint8_t *) msg[i],
+ strlen( msg[i] ) );
+ }
+ else
+ {
+ memset( buf, 'a', 1000 );
+
+ for( j = 0; j < 1000; j++ )
+ {
+ sha256_update( &ctx, (uint8_t *) buf, 1000 );
+ }
+ }
+
+ sha256_finish( &ctx, sha256sum );
+
+ for( j = 0; j < 32; j++ )
+ {
+ sprintf( output + j * 2, "%02x", sha256sum[j] );
+ }
+
+ if( memcmp( output, val[i], 64 ) )
+ {
+ printf( "failed!\n" );
+ return( 1 );
+ }
+
+ printf( "passed.\n" );
+ }
+
+ printf( "\n" );
+ }
+ else
+ {
+ if( ! ( f = fopen( argv[1], "rb" ) ) )
+ {
+ perror( "fopen" );
+ return( 1 );
+ }
+
+ sha256_starts( &ctx );
+
+ while( ( i = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+ {
+ sha256_update( &ctx, buf, i );
+ }
+
+ sha256_finish( &ctx, sha256sum );
+
+ for( j = 0; j < 32; j++ )
+ {
+ printf( "%02x", sha256sum[j] );
+ }
+
+ printf( " %s\n", argv[1] );
+ }
+
+ return( 0 );
+}
+
+#endif
+