Browse Source

dec-multia: make netboot possible, add aboot bootloader

Waldemar Brodkorb 6 years ago
parent
commit
3a96085b99
100 changed files with 19350 additions and 0 deletions
  1. 8 0
      mk/kernel-build.mk
  2. 24 0
      package/aboot/Makefile
  3. 339 0
      package/aboot/src/COPYING
  4. 214 0
      package/aboot/src/ChangeLog
  5. 110 0
      package/aboot/src/ChangeLog.cvs
  6. 28 0
      package/aboot/src/INSTALL
  7. 150 0
      package/aboot/src/Makefile
  8. 169 0
      package/aboot/src/README
  9. 11 0
      package/aboot/src/TODO
  10. 289 0
      package/aboot/src/aboot.c
  11. 10 0
      package/aboot/src/aboot.conf
  12. 26 0
      package/aboot/src/aboot.lds
  13. 70 0
      package/aboot/src/b2c.c
  14. 190 0
      package/aboot/src/cons.c
  15. 854 0
      package/aboot/src/disk.c
  16. 1 0
      package/aboot/src/doc/faq/.cvsignore
  17. 9 0
      package/aboot/src/doc/faq/Makefile
  18. 2293 0
      package/aboot/src/doc/faq/SRM-HOWTO.sgml
  19. 51 0
      package/aboot/src/doc/man/Makefile
  20. 32 0
      package/aboot/src/doc/man/README
  21. 57 0
      package/aboot/src/doc/man/aboot.8
  22. 81 0
      package/aboot/src/doc/man/aboot.conf.5
  23. 106 0
      package/aboot/src/doc/man/aboot.conf.sgml
  24. 83 0
      package/aboot/src/doc/man/aboot.sgml
  25. 96 0
      package/aboot/src/doc/man/abootconf.8
  26. 141 0
      package/aboot/src/doc/man/abootconf.sgml
  27. 46 0
      package/aboot/src/doc/man/de/Makefile
  28. 108 0
      package/aboot/src/doc/man/de/aboot.conf.sgml
  29. 89 0
      package/aboot/src/doc/man/de/aboot.sgml
  30. 146 0
      package/aboot/src/doc/man/de/abootconf.sgml
  31. 1304 0
      package/aboot/src/doc/man/de/docbook2man-de-spec.pl
  32. 45 0
      package/aboot/src/doc/man/de/e2writeboot.8
  33. 92 0
      package/aboot/src/doc/man/de/isomarkboot.sgml
  34. 107 0
      package/aboot/src/doc/man/de/netabootwrap.sgml
  35. 247 0
      package/aboot/src/doc/man/de/sdisklabel.sgml
  36. 86 0
      package/aboot/src/doc/man/de/srmbootfat.sgml
  37. 84 0
      package/aboot/src/doc/man/de/srmbootraw.sgml
  38. 61 0
      package/aboot/src/doc/man/de/swriteboot.8
  39. 42 0
      package/aboot/src/doc/man/e2writeboot.8
  40. 58 0
      package/aboot/src/doc/man/isomarkboot.8
  41. 97 0
      package/aboot/src/doc/man/isomarkboot.sgml
  42. 102 0
      package/aboot/src/doc/man/netabootwrap.sgml
  43. 152 0
      package/aboot/src/doc/man/sdisklabel.8
  44. 32 0
      package/aboot/src/doc/man/sdisklabel.copyright
  45. 246 0
      package/aboot/src/doc/man/sdisklabel.sgml
  46. 58 0
      package/aboot/src/doc/man/swriteboot.8
  47. 80 0
      package/aboot/src/fs/dummy.c
  48. 623 0
      package/aboot/src/fs/ext2.c
  49. 59 0
      package/aboot/src/fs/iso.c
  50. 485 0
      package/aboot/src/fs/ufs.c
  51. 173 0
      package/aboot/src/head.S
  52. 47 0
      package/aboot/src/include/aboot.h
  53. 25 0
      package/aboot/src/include/bootfs.h
  54. 12 0
      package/aboot/src/include/config.h
  55. 47 0
      package/aboot/src/include/cons.h
  56. 105 0
      package/aboot/src/include/disklabel.h
  57. 220 0
      package/aboot/src/include/hwrpb.h
  58. 292 0
      package/aboot/src/include/iso.h
  59. 30 0
      package/aboot/src/include/isolib.h
  60. 591 0
      package/aboot/src/include/linux/ext2_fs.h
  61. 51 0
      package/aboot/src/include/pal.h
  62. 68 0
      package/aboot/src/include/setjmp.h
  63. 31 0
      package/aboot/src/include/string.h
  64. 326 0
      package/aboot/src/include/system.h
  65. 691 0
      package/aboot/src/include/ufs.h
  66. 24 0
      package/aboot/src/include/utils.h
  67. 42 0
      package/aboot/src/lib/Makefile
  68. 61 0
      package/aboot/src/lib/_longjmp.S
  69. 36 0
      package/aboot/src/lib/_setjmp.S
  70. 160 0
      package/aboot/src/lib/divide.S
  71. 1590 0
      package/aboot/src/lib/isolib.c
  72. 23 0
      package/aboot/src/lib/memcpy.c
  73. 28 0
      package/aboot/src/lib/memset.c
  74. 252 0
      package/aboot/src/lib/string.c
  75. 317 0
      package/aboot/src/lib/vsprintf.c
  76. 146 0
      package/aboot/src/net.c
  77. 185 0
      package/aboot/src/netabootwrap.c
  78. 17 0
      package/aboot/src/netwrap.h
  79. 2 0
      package/aboot/src/sdisklabel/.cvsignore
  80. 15 0
      package/aboot/src/sdisklabel/Makefile
  81. 105 0
      package/aboot/src/sdisklabel/README
  82. 79 0
      package/aboot/src/sdisklabel/library.c
  83. 8 0
      package/aboot/src/sdisklabel/library.h
  84. 241 0
      package/aboot/src/sdisklabel/sdisklabel.c
  85. 226 0
      package/aboot/src/sdisklabel/swriteboot.c
  86. 349 0
      package/aboot/src/srmbootfat/COPYING
  87. 24 0
      package/aboot/src/srmbootfat/Makefile
  88. 5 0
      package/aboot/src/srmbootfat/README
  89. 160 0
      package/aboot/src/srmbootfat/msdos.h
  90. 246 0
      package/aboot/src/srmbootfat/srmbootfat.c
  91. 85 0
      package/aboot/src/srmbootfat/srmbootfat.sgml
  92. 101 0
      package/aboot/src/srmbootfat/srmbootraw.c
  93. 84 0
      package/aboot/src/srmbootfat/srmbootraw.sgml
  94. 5 0
      package/aboot/src/tools/.cvsignore
  95. 22 0
      package/aboot/src/tools/Makefile
  96. 125 0
      package/aboot/src/tools/abootconf.c
  97. 178 0
      package/aboot/src/tools/bio.c
  98. 4 0
      package/aboot/src/tools/bio.h
  99. 1473 0
      package/aboot/src/tools/e2lib.c
  100. 332 0
      package/aboot/src/tools/e2lib.h

+ 8 - 0
mk/kernel-build.mk

@@ -22,6 +22,14 @@ ifeq ($(ADK_TARGET_KERNEL_ZIMAGE),y)
 KERNEL_FILE:=vmlinux
 KERNEL_TARGET:=$(ADK_TARGET_KERNEL)
 endif
+ifeq ($(ADK_TARGET_KERNEL_VMLINUX_BOOTP),y)
+KERNEL_FILE:=bootpfile
+KERNEL_TARGET:=bootpfile
+endif
+ifeq ($(ADK_TARGET_KERNEL_VMLINUX_GZ),y)
+KERNEL_FILE:=vmlinux
+KERNEL_TARGET:=all
+endif
 ifeq ($(ADK_TARGET_KERNEL_BZIMAGE),y)
 KERNEL_FILE:=vmlinux
 KERNEL_TARGET:=all

+ 24 - 0
package/aboot/Makefile

@@ -0,0 +1,24 @@
+# This file is part of the OpenADK project. OpenADK is copyrighted
+# material, please see the LICENCE file in the top-level directory.
+
+include $(ADK_TOPDIR)/rules.mk
+
+PKG_NAME:=		aboot
+PKG_VERSION:=		1.0
+PKG_RELEASE:=		1
+PKG_DESCR:=		srm boot loader for alpha machines
+PKG_SECTION:=		base/boot
+
+NO_DISTFILES:=		1
+
+PKG_ARCH_DEPENDS:=	alpha
+
+include $(ADK_TOPDIR)/mk/package.mk
+
+$(eval $(call PKG_template,ABOOT,aboot,$(PKG_VERSION)-$(PKG_RELEASE),$(PKG_DEPENDS),$(PKG_DESCR),$(PKG_SECTION)))
+
+CONFIG_STYLE:=		manual
+
+aboot-install:
+
+include $(ADK_TOPDIR)/mk/pkg-bottom.mk

+ 339 - 0
package/aboot/src/COPYING

@@ -0,0 +1,339 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, 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
+
+	Appendix: 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., 675 Mass Ave, Cambridge, MA 02139, 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.

+ 214 - 0
package/aboot/src/ChangeLog

@@ -0,0 +1,214 @@
+2004-04-08  Will Woods <wgwoods@mac.com>
+	* Change include path (should fix compilation for 2.6 kernels)
+	* Add/fix extra_args patch - allows you to add extra arguments after
+	  the configuration number (e.g. "1 console=ttyS0")
+	* Fix warning about bcopy
+	* Version is now 1.0_pre20040408
+
+2003-12-01  Will Woods <wgwoods@mac.com>
+	* Patch for USB console from Jeff.Wiedemeier@hp.com
+	* Patch to check kernel memory against console memory descriptors, also
+	  from Jeff. These two patches should allow booting on Wildfire.
+
+2003-11-07  Will Woods <wgwoods@mac.com>
+	* Changed version number to 1.0pre1 (aboot should hit 1.0 before 
+	  they stop making the Alpha, I think)
+	* Merged doc changes from 0.10 branch
+	* Reverted 0.10 changes out of HEAD (the tag aboot_010pre2 marks the
+	  state just before the rollback)
+
+2003-03-21  Will Woods <will.woods@hp.com>
+	* Added include/string.h, since we have our own string.c, replaced 
+	  #includes of <linux/string.h> with "string.h" since linux/string.h
+	  no longer has user-includable prototypes.
+	  (thanks to Kelledin <kelledin@skarpsey.dyndns.org> for the idea)
+	* Changed #includes of our headers to use quotes instead of <>
+	* Don't build with -mcpu=ev4 (default code works on ev4 and is smaller)
+	* Cleaned up a couple other warnings 
+
+2003-01-14  Will Woods <will.woods@hp.com>
+	* Fixed typos in man pages ("True 64")
+	* Bumped version number to 0.9b
+	* Released 0.9b. Hooray!
+
+2002-09-18  Will Woods <will.woods@hp.com>
+	* branched the 0.9 tree to add bugfixes
+	* fixed some compilation errors with newer gcc/glibc versions
+	* added newer manpages
+
+2001-11-14  Will Woods <will.woods@compaq.com>
+        * sdisklabel/sdisklabel.c: fixed my fix to the cylinder counting bug.
+          oops. also added (currently undocumented) "force" flag, to skip
+          error checking in sdisklabel.
+
+2001-10-26  Will Woods <will.woods@compaq.com>
+        * Released aboot 0.9. Yay!
+
+2001-10-25  Will Woods <will.woods@compaq.com>
+	* sdisklabel/sdisklabel.c: fixed cylinder-counting bug
+
+2001-10-11  Will Woods <will.woods@compaq.com>
+	* applied a patch from the debian version of aboot. Here's the debian
+	maintainer's changelog:
+
+  * New upstream (from CVS)
+  * I am calling this version of aboot from CVS 0.8.
+  * Minor tweeks to make it compile with kernel 2.4.x headers.
+  * e2writeboot now returns non-zero on error.  Closes: #107757
+  -- Gregory W. Johnson <gjohnson@physics.clarku.edu>  Wed, 15 Aug 2001
+
+	Since he called his version 0.8, I will call this the 0.9 tree, to 
+	avoid confusion. Hence this is aboot 0.9pre1. 
+
+2001-10-09  Will Woods <will.woods@compaq.com>
+	* aboot.c, disk.c, include/config.c: replaced ABOOT_MINOR and 
+	ABOOT_MAJOR with ABOOT_VERSION. Bumped version number to 0.8pre2.
+	* aboot.c: fixed ELF header bug that snuck in somewhere.
+	* fs/ext2.c, Makefile: fixes for proper #includes to allow compilation
+	of userspace testing aboot against the 2.4 kernel.
+
+2001-10-08  Will Woods <will.woods@compaq.com>
+	* fs/ext2.c: Fixed elusive overflow bug. If part of the kernel was 
+	past the 524,287th block (given 4096 bytes per block) the byte offset
+	was too big to fit in an int. 
+	* sdisklabel/sdisklabel.c: borrowed code from fdisk for getting
+	the correct size of the disk. 
+	
+2001-07-10  Will Woods <will.woods@compaq.com>
+	* aboot.c, tools/objstrip.c: elf_check_arch takes different arguments
+	in Linux 2.4 than it did in 2.2; added an aboot_elf_check_arch which
+	does the right thing based on version info from linux/version.h. 
+	* disk.c: a function called get_options exists in 2.4 kernels, so
+	aboot's get_options function was renamed get_aboot_options(). 
+	(both changes based on a patch by Christian Groessler <cpg@aladdin.de>)
+
+2001-04-26  Will Woods <will.woods@compaq.com>
+	* disk.c: changed /etc/aboot.conf and aboot.conf back to their
+	original settings. If it ain't broke, why fix it?
+	* added the man pages in doc/man, written by Helge Kreutzmann
+	<kreutzm@itp.uni-hannover.de> (Thanks Helge!)
+
+2001-03-20  Will Woods <will.woods@compaq.com>
+	* disk.c: swapped position of /etc/aboot.conf and aboot.conf in the 
+	configs array, making /aboot.conf the default.
+	* isolib.c: added parse_rock_ridge_inode and get_rock_ridge_symlink
+	adapted from rock.c in the linux kernel source. 
+	* isolib.c: added iso_follow_link and iso_readdir, adapted from
+	fs/ext2.c
+        * made minor changes here and there to quiet gcc warnings - 
+	initializing variables to 0, casting variables properly, etc
+
+2000-06-27  David Huggins-Daines  <dhd@linuxcare.com>
+
+	* sdisklabel/sdisklabel.c (main): Off-by-one error in argument
+	checking (not my fault!).
+	* disk.c (load_raw): This didn't work at all.  I've changed it to
+	use an uncompressed kernel with headers.  Eventually it will be
+	fixed so that it can accept compressed kernels as well (by
+	checking for gzip magic numbers).
+	* lib/vsprintf.c (vsprintf): Patch from Matt Wilson, fix the 'h'
+	format in vsprintf().
+	* utils.c: Patch from Matt Wilson <msw@redhat.com>, to allow
+	compiling against linux 2.3 header files.
+
+2000-05-02  David Huggins-Daines  <dhd@linuxcare.com>
+
+	* Makefile: Added the ability to build a debugging aboot that runs
+	as a userspace program.  Great for filesystem code debugging.
+	Also, optimize for size instead of speed.
+	* aboot.c: Remove a.out support, add multiple ELF pheader
+	support.  Also make the parameter offset, and kernel stack offset
+	non-hardcoded in order to deal with new, bigger consoles.
+	* disk.c: Change "plain" to "uncompressed" and load_aout() to
+	load_uncompressed().  Implement multiple pheaders for raw boot
+	(untested) and uncompressed boot (tested). Also look for
+	alternative config files (needed for CD booting and such)
+	* fs/ext2.c: Cache the root inode, and do proper 64-bit arithmetic
+	in ext2_iget() so that >2G filesystems work reliably (doh!)
+	* head.S: make run_kernel() assembly in order to save a few bytes.
+	* include/aboot.h: prototype run_kernel as attribute((noreturn)),
+	maybe this will save a few bytes too.
+	* fs/ufs.c: Implement dummy fstat().  I don't really know if the
+	UFS code still works, and I'm tempted to remove it.
+	* include/cons.h: Add a definition of the CTB, though we don't
+	really use it yet.
+	* include/iso.h: Rock Ridge constants
+	* lib/isolib.c: Rock Ridge filenames, code cleanup, and fix the
+	bug where 2048-byte blocks don't work.
+	* zip/misc.c: necessary stuff for multiple pheaders.
+
+2000-04-10  David Huggins-Daines  <dhuggins@linuxcare.com>
+
+	* lib/isolib.c (iso_iget): Gar!  More stupidity in the ISO code,
+	now fixed (see comment about *pnt being overwritten).  With luck
+	this should be 0.7 final, so I won't need to do another 0.6
+
+2000-04-02  David Huggins-Daines  <dhuggins@linuxcare.com>
+
+	* lib/isolib.c: Fix some obvious stupidity in the ISO code (could
+	cause a failure to load the kernel in some cases due to reading
+	past the end of the device.
+	* sdisklabel/swriteboot.c (read_configured_partition): Eek!  I
+	thought I had fixed the problems I created with installing aboot
+	on new disks.  Obviously I didn't.  Thanks to Martin Lucina
+	<mato@kotelna.sk> for inadvertently finding the case I missed.
+
+2000-03-23  David Huggins-Daines  <dhuggins@linuxcare.com>
+
+	* cons.c: Patch from David North <d_north@thurien.tditx.com>, via
+	Greg W. Johnson (gwj@debian.org), fixes serial console output on
+	some boxes.
+	* fs/iso.c: gwj@debian.org: silence compiler warnings
+	* include/isolib.h: ditto
+	* lib/string.c: ditto
+	* sdisklabel/swriteboot.c: add abootconf functionality to
+	swriteboot (where it probably belongs)
+
+2000-03-06  David Huggins-Daines  <dhuggins@linuxcare.com>
+
+	* aboot-0.6: At long last we have a new aboot.  This is somewhat
+	of an interim release, as it doesn't have all the features I'd
+	like (it doesn't list directories or follow symlinks on ISO9660 or
+	UFS filesystems, for example, nor does it support initrd), but it
+	integrates the large number of patches that have been added by
+	various distributions, adds symlink-following, initrd, and
+	directory-listing support on ext2 at least, and generally works
+	better.
+
+Sat Aug 17 18:58:36 1996  David Mosberger-Tang  <davidm@azstarnet.com>
+
+	* disk.c (get_boot_device): New function.  If it guesses wrong,
+	explicitly specify bootdevice= via commandline.
+	(get_options): Add support for bootdevice= and bootfile= options
+	to enable Red Hat installation.
+
+	* sdisklabel/library.c (overlaplabel): FORCE is now a bitset.
+	If bit i is set, overlaps with partition i+1 are allowed.
+	* sdisklabel/sdisklabel.c (set_partition): Update accordingly.
+
+	* sdisklabel/swriteboot.c (main): Make 1 be the first partition
+ 	(not 0) to be consistent with Linux kernel numbering.  Make
+ 	force_overlap a bitset so we can force more than one overlapping
+ 	partition.
+
+	* disk.c (load_kernel): If kernel load fails, drop into
+ 	interactive mode.
+
+	* fs/ext2.c (ext2_iget): Make OFFSET a long, not an int so we can
+ 	boot from a partition that starts at an offset > 2GB.
+
+Fri May 10 16:48:25 1996  David Mosberger-Tang  <davidm@koppel.cs.arizona.edu>
+
+	* main.c: split out disk booting into disk.c and netbooting into
+	net.c.
+
+Fairly recently:
+	* Network booting support added by Dave Larson
+	  <dlarson@cs.arizona.edu>
+
+A long time ago:
+ 	* Default commandline argument handling by Michael Schwingen 
+	  <rincewind@discworld.oche.de>
+
+A very long time ago:
+	* Filesystem support added by David Mosberger <davidm@cs.arizona.edu>

+ 110 - 0
package/aboot/src/ChangeLog.cvs

@@ -0,0 +1,110 @@
+2001-07-13 23:06  wwoods
+
+	* ChangeLog, INSTALL, aboot.c, disk.c, lib/isolib.c,
+	tools/objstrip.c: Incorporated patch from Christian Groessler
+	<cpg@aladdin.de> to make aboot compile against Linux 2.4
+
+2001-04-26 23:39  wwoods
+
+	* ChangeLog, Makefile, README, disk.c, doc/man/Makefile,
+	doc/man/README, doc/man/aboot.8, doc/man/aboot.conf.5,
+	doc/man/aboot.conf.sgml, doc/man/aboot.sgml, doc/man/abootconf.8,
+	doc/man/abootconf.sgml, doc/man/e2writeboot.8,
+	doc/man/swriteboot.8, include/config.h: Changed default config file
+	location back to /etc/aboot.conf Added man pages written by Helge
+	Kreutzmann <kreutzm@itp.uni-hannover.de>
+
+2001-04-02 23:21  wwoods
+
+	* ChangeLog: updated ChangeLog
+
+2001-04-02 23:11  wwoods
+
+	* Makefile, README, disk.c, fs/iso.c, include/config.h,
+	include/isolib.h, lib/Makefile, lib/isolib.c: * added full
+	rockridge support - symlinks and long filenames are now properly  
+	supported on ISO filesystems.  * changed default aboot.conf
+	location to /aboot.conf * fixed crash when booting from a directory
+	with a long filename on ISO fs
+
+2000-06-27 18:14  dhd
+
+	* README: Remove reference to documentation directory which no
+	longer exists
+
+2000-06-27 18:08  dhd
+
+	* README: Doh!	Update the README to the correct version number :-)
+
+2000-06-27 18:08  dhd
+
+	* aboot.c: If DEBUG is defined, dump the ELF header information
+	*before* loading the kernel, to aid debugging.
+
+2000-06-27 18:07  dhd
+
+	* ChangeLog, disk.c: Change "raw" booting to actually work, which
+	required making it no longer be "raw".
+	
+	Okay, so maybe this will be 0.7a for real...
+
+2000-06-27 16:52  dhd
+
+	* ChangeLog, sdisklabel/sdisklabel.c: Fix sdisklabel to not
+	segfault with too few arguments.  I wonder if anybody actually uses
+	this program.
+
+2000-06-27 16:47  dhd
+
+	* ChangeLog, disk.c, utils.c, lib/vsprintf.c: 0.7a release, I
+	think.	Fixes:
+	
+	 * Concatenating the kernel with aboot in the boot sectors didn't
+	work.
+	 * aboot didn't compile with Linux 2.3 headers (msw@redhat.com)
+	 * vsprintf() didn't do the right thing in certain obscure cases
+	(msw@redhat.com)
+
+2000-06-27 16:44  dhd
+
+	* .cvsignore, sdisklabel/.cvsignore, tools/.cvsignore: Ignore
+	various generated files
+
+2000-05-03 05:58  dhd
+
+	* COPYING, ChangeLog, INSTALL, Makefile, README, TODO, aboot.c,
+	aboot.conf, aboot.lds, cons.c, disk.c, head.S, net.c, utils.c,
+	fs/dummy.c, fs/ext2.c, fs/iso.c, fs/ufs.c, include/aboot.h,
+	include/bootfs.h, include/config.h, include/cons.h,
+	include/disklabel.h, include/iso.h, include/isolib.h,
+	include/setjmp.h, include/ufs.h, include/utils.h, lib/Makefile,
+	lib/_longjmp.S, lib/_setjmp.S, lib/divide.S, lib/isolib.c,
+	lib/memcpy.c, lib/memset.c, lib/string.c, lib/vsprintf.c,
+	sdisklabel/Makefile, sdisklabel/README, sdisklabel/library.c,
+	sdisklabel/library.h, sdisklabel/sdisklabel.c,
+	sdisklabel/swriteboot.8, sdisklabel/swriteboot.c, tools/Makefile,
+	tools/abootconf.c, tools/bio.c, tools/bio.h, tools/e2writeboot.8,
+	tools/e2lib.c, tools/e2lib.h, tools/e2writeboot.c,
+	tools/elfencap.c, tools/isomarkboot.c, tools/objstrip.c,
+	zip/gzip.h, zip/inflate.c, zip/misc.c, zip/unzip.c: Initial
+	revision
+
+2000-05-03 05:58  dhd
+
+	* COPYING, ChangeLog, INSTALL, Makefile, README, TODO, aboot.c,
+	aboot.conf, aboot.lds, cons.c, disk.c, head.S, net.c, utils.c,
+	fs/dummy.c, fs/ext2.c, fs/iso.c, fs/ufs.c, include/aboot.h,
+	include/bootfs.h, include/config.h, include/cons.h,
+	include/disklabel.h, include/iso.h, include/isolib.h,
+	include/setjmp.h, include/ufs.h, include/utils.h, lib/Makefile,
+	lib/_longjmp.S, lib/_setjmp.S, lib/divide.S, lib/isolib.c,
+	lib/memcpy.c, lib/memset.c, lib/string.c, lib/vsprintf.c,
+	sdisklabel/Makefile, sdisklabel/README, sdisklabel/library.c,
+	sdisklabel/library.h, sdisklabel/sdisklabel.c,
+	sdisklabel/swriteboot.8, sdisklabel/swriteboot.c, tools/Makefile,
+	tools/abootconf.c, tools/bio.c, tools/bio.h, tools/e2writeboot.8,
+	tools/e2lib.c, tools/e2lib.h, tools/e2writeboot.c,
+	tools/elfencap.c, tools/isomarkboot.c, tools/objstrip.c,
+	zip/gzip.h, zip/inflate.c, zip/misc.c, zip/unzip.c: Initial import
+	(from 0.7 release)
+

+ 28 - 0
package/aboot/src/INSTALL

@@ -0,0 +1,28 @@
+Thu Jun 27 03:23:08 1996
+
+- Edit Makefile and include/config.h to suite your needs.  For most
+  purposes, the distributed version should work fine.  Note that
+  the CONFIG_FILE_PARTITION macro is still present like in earlier
+  version, but since aboot-0.5 allows you to select a partition via
+  the boot-commandline, the value for that macro is not as critical
+  anymore. Users of certain versions of gcc (2.96 and later?) 
+  may need to add '-ffreestanding' flag to CFLAGS, in the Makefile.
+
+- Type "make".
+
+- To install the newly created aboot image (named "bootlx"), in most cases,
+  you use swriteboot (found in the sdisklabel directory), like this:
+
+    # swriteboot -c[boot partition #] [boot device] bootlx
+
+  for example, on my system, the kernel images (and aboot.conf) are on my 
+  root partition, /dev/sda2. hence:
+
+    # swriteboot -c2 /dev/sda bootlx
+  
+  DON'T DO THIS UNLESS YOU'RE SURE OF THE PARTITION INFO. If you don't know 
+  exactly what you're doing, and your system already boots okay, there's no 
+  reason to be installing a new bootloader.
+
+  For more info, read the SRM HOWTO, in doc/faq/srm.html, or at:
+  http://www.alphalinux.org/faq/srm.html

+ 150 - 0
package/aboot/src/Makefile

@@ -0,0 +1,150 @@
+#
+# aboot/Makefile
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (c) 1995, 1996 by David Mosberger (davidm@cs.arizona.edu)
+#
+
+# location of linux kernel sources (must be absolute path):
+KSRC		= /usr/src/linux
+VMLINUX		= $(KSRC)/vmlinux
+VMLINUXGZ	= $(KSRC)/arch/alpha/boot/vmlinux.gz
+
+# for userspace testing
+#TESTING	= yes
+
+# for boot testing
+#CFGDEFS       	= -DDEBUG_ISO -DDEBUG_ROCK -DDEBUG_EXT2 -DDEBUG
+
+bindir		= $(DESTDIR)/sbin
+bootdir		= $(DESTDIR)/boot
+
+export
+
+#
+# There shouldn't be any need to change anything below this line.
+#
+TOP 		= $(shell pwd)
+LOADADDR	= 20000000
+
+ifndef $($(CC))
+CC 		?= gcc
+endif
+
+ifeq ($(TESTING),)
+override CPPFLAGS	+= $(CFGDEFS) -I$(TOP)/include
+override CFLAGS		+= $(CPPFLAGS) -D__KERNEL__ -mcpu=ev4 -Os -Wall -fno-builtin -Wcast-align -mno-fp-regs -ffixed-8 -fno-builtin-printf
+else
+override CPPFLAGS	+= -DTESTING $(CFGDEFS) -I$(TOP)/include
+override CFLAGS		+= $(CPPFLAGS) -O -g3 -Wall -D__KERNEL__ -ffixed-8
+endif
+
+ABOOT_LDFLAGS 	= -static -N -Taboot.lds
+override ASFLAGS		+= $(CPPFLAGS)
+
+
+.c.s:
+	$(CC) $(CFLAGS) -S -o $*.s $<
+.s.o:
+	$(AS) -o $*.o $<
+.c.o:
+	$(CC) $(CFLAGS) -c -o $*.o $<
+.S.s:
+	$(CC) $(ASFLAGS) -D__ASSEMBLY__ -traditional -E -o $*.o $<
+.S.o:
+	$(CC) $(ASFLAGS) -D__ASSEMBLY__ -traditional -c -o $*.o $<
+
+NET_OBJS = net.o
+DISK_OBJS = disk.o fs/ext2.o fs/ufs.o fs/dummy.o fs/iso.o
+ifeq ($(TESTING),)
+ABOOT_OBJS = \
+	head.o aboot.o cons.o utils.o \
+	zip/misc.o zip/unzip.o zip/inflate.o
+else
+ABOOT_OBJS = aboot.o zip/misc.o zip/unzip.o zip/inflate.o
+endif
+LIBS	= lib/libaboot.a
+
+all:	diskboot net_aboot.nh
+
+diskboot:	bootlx sdisklabel/sdisklabel sdisklabel/swriteboot \
+		tools/e2writeboot tools/abootconf \
+		tools/elfencap
+
+netboot: vmlinux.bootp
+
+bootloader.h: net_aboot.nh b2c
+	./b2c net_aboot.nh bootloader.h bootloader
+
+netabootwrap: netabootwrap.c bootloader.h
+	$(CC) $@.c $(CFLAGS) -o $@ 
+	
+
+bootlx:	aboot tools/objstrip
+	tools/objstrip -vb aboot bootlx
+
+install-man: 
+	make -C doc/man install
+
+install-man-gz:
+	make -C doc/man install-gz
+
+install: tools/abootconf tools/e2writeboot \
+	sdisklabel/swriteboot
+	install -d $(bindir) $(bootdir)
+	install -c tools/abootconf $(bindir)
+	install -c tools/e2writeboot $(bindir)
+	install -c sdisklabel/swriteboot $(bindir)
+	install -c bootlx $(bootdir)
+
+installondisk:	bootlx sdisklabel/swriteboot
+	sdisklabel/swriteboot -vf0 /dev/sda bootlx vmlinux.gz
+
+ifeq ($(TESTING),)
+aboot:	$(ABOOT_OBJS) $(DISK_OBJS) $(LIBS)
+	$(LD) $(ABOOT_LDFLAGS) $(ABOOT_OBJS) $(DISK_OBJS) -o $@ $(LIBS)
+else
+aboot:	$(ABOOT_OBJS) $(DISK_OBJS) $(LIBS)
+	$(CC) $(ABOOT_OBJS) $(DISK_OBJS) -o $@ $(LIBS)
+endif
+
+vmlinux.bootp: net_aboot.nh $(VMLINUXGZ) net_pad
+	cat net_aboot.nh $(VMLINUXGZ) net_pad > $@
+
+net_aboot.nh: net_aboot tools/objstrip
+	$(CROSS)strip net_aboot
+	tools/objstrip -vb net_aboot $@
+
+net_aboot: $(ABOOT_OBJS) $(ABOOT_OBJS) $(NET_OBJS) $(LIBS)
+	$(LD) $(ABOOT_LDFLAGS) $(ABOOT_OBJS) $(NET_OBJS) -o $@ $(LIBS)
+
+net_pad:
+	dd if=/dev/zero of=$@ bs=512 count=1
+
+clean:	sdisklabel/clean tools/clean lib/clean
+	rm -f aboot abootconf net_aboot net_aboot.nh net_pad vmlinux.bootp \
+		$(ABOOT_OBJS) $(DISK_OBJS) $(NET_OBJS) bootlx \
+		include/ksize.h vmlinux.nh b2c bootloader.h netabootwrap
+
+distclean: clean
+	find . -name \*~ | xargs rm -f
+
+lib/%:
+	make -C lib $* CPPFLAGS="$(CPPFLAGS)" TESTING="$(TESTING)"
+
+tools/%:
+	make -C tools $* CPPFLAGS="$(CPPFLAGS)"
+
+sdisklabel/%:
+	make -C sdisklabel $* CPPFLAGS="$(CPPFLAGS)"
+
+vmlinux.nh: $(VMLINUX) tools/objstrip
+	tools/objstrip -vb $(VMLINUX) vmlinux.nh
+
+include/ksize.h: vmlinux.nh
+	echo "#define KERNEL_SIZE `ls -l vmlinux.nh | awk '{print $$5}'` > $@
+
+dep:

+ 169 - 0
package/aboot/src/README

@@ -0,0 +1,169 @@
+This is release 0.9 of aboot, the Linux/Alpha loader for SRM.
+
+Aboot is based on the standard Linux/Alpha bootloader, with extensions
+by David Mosberger and Michael Schwingen (prompt for arguments, kernel
+argument mapping using /etc/aboot.conf file). It is currently maintained
+by Will Woods.
+
+For more information about aboot and SRM, see the SRM Firmware HOWTO, in 
+doc/faq/srm.html, or at http://www.alphalinux.org/faq/srm.html
+
+Good luck and enjoy...
+
+-Will Woods <will.woods@compaq.com>  Oct 25, 2001
+
+---
+
+New with version 0.9:
+
+ - new and (hopefully) improved man pages
+ - Crash when booting from a path containing a long filename on isofs fixed
+ - listing directories on isofs works
+ - symlinks on isofs work
+ - Failure to boot when kernel was past the 2GB boundary on ext2 fs fixed
+ - cylinder-counting bug in sdisklabel fixed
+
+[Note: there was no (official) version 0.8.]
+
+New with version 0.7:
+
+ - aboot now supports an initial ramdisk, which can be loaded from an
+   arbitrary file on any supported filesystem.  To use this, pass an
+   'initrd=/path/to/file' argument in the boot flags, or use the 'i'
+   command from the interactive menu.
+
+ - a.out support has been removed.
+
+ - (as of 0.7a) "raw" booting no longer is - you must use an
+   uncompressed ELF kernel.
+
+ - Many bugs in the ISO filesystem code have been found and fixed.
+
+ - swriteboot incorporates the functionality of abootconf.
+
+New with version 0.6:
+
+ - The various patches from the Red Hat, Debian, and SuSE packages
+   have been merged back in.
+
+ - ext2 partitions with >1024 byte block sizes and sparse superblocks
+   are now (hopefully) supported. (from Red Hat?)
+
+ - aboot can now follow symbolic links on ext2 filesystems.
+
+ - aboot no longer passes the bootdevice= and bootfile= flags to the
+   kernel, as the code for guessing the boot device was completely
+   broken, and these options are not used at all by current kernels.
+
+ - aboot is now built as an ELF image (since that's what the current
+   toolchain supports), and code to strip it accordingly has been
+   added (from Richard Henderson)
+
+ - isomarkboot now has an option to specify the root filesystem image
+   to be loaded (from Debian)
+
+ - swriteboot tries to preserve the boot partition setting from a
+   previous aboot installation.
+
+New with version 0.5:
+
+ - IMPORTANT: e2writeboot now expects a _raw_ file, not an ECOFF
+   object file.  So be sure to write aboot using the command:
+
+	e2writeboot /dev/fd0 bootlx
+
+   This change has been made so e2writeboot and s2writeboot are more
+   consistent.  It also makes it easier to support multiple object
+   file formats.
+
+ - The location the partition containing /etc/aboot.conf can now be
+   specified on the commandline: -fl 3:0 selects the aboot.conf line
+   0 on partition 3.
+ 
+ - Booting of ELF object files is now supported.  In the process of
+   adding ELF suport, the build tool has been rewritten from scratch
+   (it's now a lot simpler despite supporting two object file
+   formats).
+
+ - Booting from an ext2fs partition that starts at an offset >= 2GB
+   now works.
+
+ - If the kernel load fails, aboot now drops into interactive mode
+   instead of 
+
+ - swriteboot now supports an option to force installation of aboot even
+   if there is an overlap between the aboot image and some partition. E.g.,
+   if partition 1 and 3 start at sector 0 (as is commonly the case for disks
+   partitioned under OSF/1), you can specify:
+
+	swriteboot -f1 -f3 /dev/sdc bootlx
+
+   WARNING: Using -f will obviously destroy any filesystem that may be
+	    present on the specified partition.  Use at your own risk.
+
+ - NOTE: I'd like to remove sdisklabel in future distributions (minlabel
+   should be all you need).  Let me know if you feel strongly about this
+   (one way or the other).
+
+New with version 0.4:
+
+ - abootconf allows to set (or query) the number of the partition that
+   aboot will use to lookup /etc/aboot.conf.
+ - support for net boot added (thanks to Dave Larson <dlarson@cs.arizona.edu>)
+ - iso9660 filesystem support added (based on Dave Rusling's MILO sources)
+
+New with version 0.31:
+
+ - e2writeboot is now included in the distribution.
+ - started with writing man pages for e2writeboot and swriteboot; pretty
+   cryptic, I believe, but heck, it's the best there is! :-)
+
+New with version 0.3:
+
+ - The commandline prompt changed to "aboot>".
+
+ - The contents of /etc/aboot.conf can be displayed with a commandline
+   argument consisting of a single 'h'.  After displaying the configuration
+   file, aboot will prompt for a commandline just like for the 'i' option.
+
+ - At the "aboot>" prompt, the user can enter a single 'h' to display
+   the configuration file.  Entering an empty line or a line consisting
+   of a single 'i' will keep the user in the "aboot>" prompt loop.
+
+ - Booting of raw (headerless) kernels is now supported again.  A raw
+   boot is requested by specifying a filename consisting of a single
+   '-' character only.  Booting ECOFF kernels off a disk without filesystem
+   is now supported via partition number 0 (in aboot-0.2, this was incorrectly
+   called a "raw boot").  For example, to boot a compressed ECOFF file,
+   one could specify the filename "0/-" (filename "-" on the zeroth
+   partition).  You can use the swriteboot command to write the kernel
+   for a filesystem-less boot.
+
+ - Booting from floppy disks now works again.
+
+New with version 0.2:
+
+ - If the kernel commandline consists of a single 'i', aboot prompts for
+   kernel file and commandline arguments (useful on machines such as
+   the Jensen, where the SRM limits commandline arguments to 1 argument).
+
+ - If the kernel commandline consists of a single digit, aboot looks up
+   the default configuration with that number in the file /etc/aboot.conf
+   on a compile-time defined partition of the bootdrive, and uses the
+   parameters given there as commandline arguments for the kernel (useful
+   where the SRM limits default commandline arguments to 8 characters,
+   and does not support setting a default filename).
+
+ - If the kernel filename consists of a single '-' or is empty, aboot
+   will perform a raw boot.  This involves loading a kernel starting at
+   the disk sector after the aboot code (currently, 162).  This kernel
+   must be a header-less ("raw") binary without any ECOFF header.
+
+New with version 0.1:
+
+ - Compressed kernels (using gzip) are supported (faster loading, less
+   disk usage).
+
+ - You can load the kernel from an UFS or EXT2 filesystem on any partition
+   of the boot disk.
+

+ 11 - 0
package/aboot/src/TODO

@@ -0,0 +1,11 @@
+- more documentation (aboot man page, improve e2writeboot & swriteboot
+  man pages)
+
+- I suspect that EOF detection does not work on UFS filesystems -
+  i.e., reading the configuration file may cause a hang on such a
+  filesystem when the desired config line is not found. I have not fixed
+  this since I could not check the changes - look at the top of
+  iext2_breadi to see how I fixed nblks there MS
+
+- Netbooting support and UFS may be broken.  Either they'll get fixed
+  or they will be dropped, as neither is particularly useful.

+ 289 - 0
package/aboot/src/aboot.c

@@ -0,0 +1,289 @@
+/*
+ * aboot.c
+ *
+ * This file is part of aboot, the SRM bootloader for Linux/Alpha
+ * Copyright (C) 1996 Linus Torvalds, David Mosberger, and Michael Schwingen.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <asm/console.h>
+#include "hwrpb.h"
+#include "system.h"
+
+#include <elf.h>
+#include <alloca.h>
+#include <errno.h>
+
+#include "aboot.h"
+#include "config.h"
+#include "cons.h"
+#include "setjmp.h"
+#include "utils.h"
+#include "string.h"
+
+struct bootfs *	bfs = 0;		/* filesystem to boot from */
+char *		dest_addr = 0;
+jmp_buf		jump_buffer;
+
+unsigned long	start_addr = START_ADDR; /* default only */
+struct segment* chunks;
+int             nchunks;
+
+char		boot_file[256] = "";
+char		initrd_file[256] = "";
+char		kernel_args[256] = "";
+char *		bss_start = 0;
+long		bss_size = 0;		 /* size of bss */
+unsigned long   initrd_start = 0;
+unsigned long   initrd_size = 0;
+
+/* Offsets from start_addr (yes, they are negative, because start_addr
+   is actually the load address plus the text offset) */
+#define PARAM_OFFSET	-0x6000 /* load address + 0xa000 */
+#define STACK_OFFSET	-0xe000 /* load address + 0x2000 */
+
+/* eventually we may have to deal with 44-bit physical addressing and
+   also possibly larger pages */
+unsigned long	page_offset = 0xfffffc0000000000;
+unsigned long   page_shift  = 13;
+
+static unsigned long entry_addr = START_ADDR;
+
+/*
+ * The decompression code calls this function after decompressing the
+ * first block of the object file.  The first block must contain all
+ * the relevant header information.
+ */
+long
+first_block (const char *buf, long blocksize)
+{
+	Elf64_Ehdr *elf;
+	Elf64_Phdr *phdrs;
+	int i, j;
+
+	elf  = (Elf64_Ehdr *) buf;
+	
+	if (elf->e_ident[0] != 0x7f
+	    || elf->e_ident[1] != 'E'
+	    || elf->e_ident[2] != 'L'
+	    || elf->e_ident[3] != 'F')
+	{
+		/* Fail silently, it might be a compressed file */
+		return -1;
+	}
+	if (elf->e_ident[EI_CLASS] != ELFCLASS64
+	    || elf->e_ident[EI_DATA] != ELFDATA2LSB
+	    || elf->e_machine != EM_ALPHA)
+	{
+		printf("aboot: ELF executable not for this machine\n");
+		return -1;
+	}
+
+	/* Looks like an ELF binary. */
+	if (elf->e_type != ET_EXEC) {
+		printf("aboot: not an executable ELF file\n");
+		return -1;
+	}
+
+	if (elf->e_phoff + elf->e_phnum * sizeof(*phdrs) > (unsigned) blocksize)
+	{
+		printf("aboot: "
+		       "ELF program headers not in first block (%ld)\n",
+		       (long) elf->e_phoff);
+		return -1;
+	}
+
+	phdrs = (struct elf_phdr *) (buf + elf->e_phoff);
+	chunks = malloc(sizeof(struct segment) * elf->e_phnum);
+	start_addr = phdrs[0].p_vaddr; /* assume they are sorted */
+	entry_addr = elf->e_entry;
+
+#ifdef DEBUG
+	printf("aboot: %d program headers, start address %#lx, entry %#lx\n",
+	       elf->e_phnum, start_addr, entry_addr);
+#endif
+
+	for (i = j = 0; i < elf->e_phnum; ++i) {
+		int status;
+
+		if (phdrs[i].p_type != PT_LOAD)
+			continue;
+
+		chunks[j].addr   = phdrs[i].p_vaddr;
+		chunks[j].offset = phdrs[i].p_offset;
+		chunks[j].size   = phdrs[i].p_filesz;
+
+#ifdef DEBUG
+		printf("aboot: PHDR %d vaddr %#lx offset %#lx size %#lx\n",
+		       i, chunks[j].addr, chunks[j].offset, chunks[j].size);
+#endif
+
+#ifndef TESTING
+		status = check_memory(chunks[j].addr, chunks[j].size);
+		if (status) {
+			printf("aboot: Can't load kernel.\n"
+			       "  Memory at %lx - %lx (PHDR %i) "
+			         "is %s\n",
+			       chunks[j].addr,
+			       chunks[j].addr + chunks[j].size - 1,
+			       i,
+			       (status == -ENOMEM) ?
+			          "Not Found" :
+				  "Busy (Reserved)");
+			return -1;
+		}
+#endif
+
+		if (phdrs[i].p_memsz > phdrs[i].p_filesz) {
+			if (bss_size > 0) {
+				printf("aboot: Can't load kernel.\n"
+				       "  Multiple BSS segments"
+				       " (PHDR %d)\n", i);
+				return -1;
+			}
+			bss_start = (char *) (phdrs[i].p_vaddr +
+				              phdrs[i].p_filesz);
+			bss_size = (phdrs[i].p_memsz - phdrs[i].p_filesz);
+		}
+
+		j++;
+	}
+	nchunks = j;
+#ifdef DEBUG
+	printf("aboot: bss at 0x%p, size %#lx\n", bss_start, bss_size);
+#endif
+
+	return 0;
+}
+
+static void
+get_boot_args(void)
+{
+	long result;
+
+	/* get boot command line: */
+#ifdef TESTING
+	const char *e;
+	if ((e = getenv("BOOTED_FILE"))) {
+		strncpy(boot_file, e, sizeof(boot_file)-1);
+		boot_file[sizeof(boot_file)-1] = 0;
+	} else {
+		strcpy(boot_file, "vmlinux.gz");
+	}
+	if ((e = getenv("BOOTED_OSFLAGS"))) {
+		strncpy(kernel_args, e, sizeof(kernel_args)-1);
+		kernel_args[sizeof(kernel_args)-1] = 0;
+	} else {
+		strcpy(kernel_args, "i");
+	}
+#else
+	result = cons_getenv(ENV_BOOTED_FILE, boot_file, sizeof(boot_file));
+	if (result < 0) {
+		printf("aboot: warning: can't get ENV_BOOTED_FILE "
+		       "(result=%lx)!\n", result);
+		strcpy(boot_file, "vmlinux.gz");
+	}
+	result = cons_getenv(ENV_BOOTED_OSFLAGS,
+			     kernel_args, sizeof(kernel_args));
+	if  (result < 0) {
+		printf("aboot: warning: can't get ENV_BOOTED_OSFLAGS "
+		       "(result=%lx)!\n", result);
+		strcpy(kernel_args, "i");
+	}
+#endif /* TESTING */
+}
+
+#ifdef TESTING
+long config_file_partition = 1;
+void halt()
+{
+	exit(0);
+}
+
+void unzip_error(char *x)
+{
+	printf("unzip: %s\n", x);
+}
+
+
+int main()
+{
+	extern long load_kernel();
+	long result;
+
+	get_boot_args();
+	result = load_kernel();
+	if (result < 0) {
+		printf("aboot: kernel load failed (%ld)\n", result);
+		return 0;
+	}
+	printf("aboot: starting kernel %s with arguments %s\n",
+	       boot_file, kernel_args);
+	return 0;
+}
+#else /* not TESTING */
+/*
+ * Head transfers control to this function.  Don't call it main() to avoid
+ * gcc doing magic initialization things that we don't want.
+ */
+void
+main_ (void)
+{
+	extern long load_kernel (void);
+	long i, result;
+
+	cons_init();
+
+	printf("aboot: Linux/Alpha SRM bootloader version "ABOOT_VERSION"\n");
+
+	/* don't know how to deal with this yet */
+	if (INIT_HWRPB->pagesize != 8192) {
+		printf("aboot: expected 8kB pages, got %ldkB\n",
+		       INIT_HWRPB->pagesize >> 10);
+
+		cons_close_console();
+		return;
+	}
+
+	pal_init();
+	get_boot_args();
+	result = load_kernel();
+	if (result < 0) {
+		printf("aboot: kernel load failed (%ld)\n", result);
+		cons_close_console();
+		return;
+	}
+	printf("aboot: starting kernel %s with arguments %s\n",
+	       boot_file, kernel_args);
+	strcpy((char*)start_addr + PARAM_OFFSET, kernel_args);
+	*(unsigned long *)(start_addr + PARAM_OFFSET + 0x100)
+		= initrd_start;
+	*(unsigned long *)(start_addr + PARAM_OFFSET + 0x108)
+		= initrd_size;
+
+	cons_close_console();
+	run_kernel(entry_addr, start_addr + STACK_OFFSET);
+
+	cons_open_console();
+	printf("aboot: kernel returned unexpectedly.  Halting slowly...\n");
+	for (i = 0 ; i < 0x100000000 ; i++)
+		/* nothing */;
+	cons_close_console();
+	halt();
+}
+#endif /* TESTING */

+ 10 - 0
package/aboot/src/aboot.conf

@@ -0,0 +1,10 @@
+#
+# aboot default configurations
+#
+0:3/vmlinux.gz ro root=/dev/sda2
+1:3/vmlinux.old.gz ro root=/dev/sda2
+2:3/vmlinux.new.gz ro root=/dev/sda2
+3:3/vmlinux ro root=/dev/sda2
+8:- ro root=/dev/sda2		# fs less boot of raw kernel
+9:0/- ro root=/dev/sda2		# fs less boot of (compressed) ECOFF kernel
+-

+ 26 - 0
package/aboot/src/aboot.lds

@@ -0,0 +1,26 @@
+OUTPUT_FORMAT("elf64-alpha")
+ENTRY(__start)
+PHDRS { kernel PT_LOAD; }
+SECTIONS
+{
+  . = 0x20000000;
+  .text : { *(.text) } :kernel
+  _etext = .;
+  PROVIDE (etext = .);
+  .rodata : { *(.rodata) } :kernel
+  .data : { *(.data) } :kernel
+  .got : { *(.got) } :kernel
+  .sdata : { *(.sdata) } :kernel
+  _edata = .;
+  PROVIDE (edata = .);
+  .sbss : { *(.sbss) *(.scommon) } :kernel
+  .bss : { *(.bss) *(COMMON) } :kernel
+  _end = . ;
+  PROVIDE (end = .);
+
+  /DISCARD/ : { *(.eh_frame) }
+
+  .mdebug 0 : { *(.mdebug) }
+  .note 0 : { *(.note) }
+  .comment 0 : { *(.comment) }
+}

+ 70 - 0
package/aboot/src/b2c.c

@@ -0,0 +1,70 @@
+
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+void print_usage(void )
+{
+	printf("Usage: b2c bin_img tar_file.h symname\n");
+	exit(1);
+}
+
+void open_file(char *fn, int *fd, int *sz)
+{
+	struct stat buf;
+
+	*fd = open(fn, O_RDONLY);
+	if (fd < 0) {
+		printf("cannot open %s\n", fn);
+		exit(1);
+	}
+
+	fstat(*fd, &buf);
+
+	if (buf.st_size <= 10*1024) {
+		printf("Is this a right file %s, size = %ld\n", fn, buf.st_size);
+		exit(1);
+	}
+
+	*sz = (int)buf.st_size;
+}
+
+int main(int argc, char **argv)
+{
+	int sfd, ssz, red, i;
+	int buf[1024];
+	char *sfn, *tfn, *symname;
+	FILE *tfd;
+
+	if (argc != 4) {
+		print_usage();
+	}
+
+	sfn = argv[1];
+	tfn = argv[2];
+	symname = argv[3];
+
+	open_file(sfn, &sfd, &ssz);
+
+	tfd = fopen(tfn, "w");
+
+	fprintf(tfd, "int %s[] = {\n", symname);
+
+	while((red=read(sfd, buf, 1024*sizeof(int)))) {
+		for (i=0; i<red/sizeof(int); i++) 
+			fprintf(tfd, "0x%x, \n", buf[i]);
+	}
+
+	fprintf(tfd, "};");
+
+	fclose(tfd);
+	
+	return 0;
+
+}
+
+
+

+ 190 - 0
package/aboot/src/cons.c

@@ -0,0 +1,190 @@
+#include <alloca.h>
+
+#include <linux/kernel.h>
+
+#include <asm/console.h>
+#include "hwrpb.h"
+#include "system.h"
+
+#include "aboot.h"
+#include "cons.h"
+#include "utils.h"
+#include "string.h"
+
+#ifndef CCB_OPEN_CONSOLE	/* new callback w/ ARM v4 */
+# define CCB_OPEN_CONSOLE 0x07
+#endif
+
+#ifndef CCB_CLOSE_CONSOLE	/* new callback w/ ARM v4 */
+# define CCB_CLOSE_CONSOLE 0x08
+#endif
+
+long cons_dev;			/* console device */
+
+long
+cons_puts(const char *str, long len)
+{
+	long remaining, written;
+	union ccb_stsdef {
+		long int l_sts;
+		struct {
+			int written;
+			unsigned discard : 29;
+			unsigned v_sts0  : 1;
+			unsigned v_sts1  : 1;
+			unsigned v_err   : 1;
+		} s;
+	} ccb_sts;
+	
+	for (remaining = len; remaining; remaining -= written) {
+		ccb_sts.l_sts = dispatch(CCB_PUTS, cons_dev, str, remaining);
+		if (!ccb_sts.s.v_err) {
+			written = ccb_sts.s.written;
+			str += written;
+		} else {
+			if (ccb_sts.s.v_sts1)
+				halt();		/* This is a hard error */
+			written = 0;
+		}
+	}
+	return len;
+}
+
+void
+cons_putchar(char c)
+{
+	char buf[2];
+
+	buf[0] = c;
+	buf[1] = 0;
+	cons_puts(buf,1);
+}
+
+int
+cons_getchar(void)
+{
+	long c;
+
+	while ((c = dispatch(CCB_GETC, cons_dev)) < 0)
+		;
+	return c;
+}
+
+
+long
+cons_getenv(long index, char *envval, long maxlen)
+{
+	/*
+	 * This may seem silly, but some SRM implementations have
+	 * problems returning values to buffers that are not 8 byte
+	 * aligned.  We work around this by always using a buffer
+	 * allocated on the stack (which guaranteed to by 8 byte
+	 * aligned).
+	 */
+	char * tmp = alloca(maxlen);
+	long len;
+
+	len = dispatch(CCB_GET_ENV, index, tmp, maxlen - 1);
+	if (len >= 0) {
+		memcpy(envval, tmp, len);
+		envval[len] = '\0';
+	}
+	return len;
+}
+
+
+long
+cons_open(const char *devname)
+{
+	return dispatch(CCB_OPEN, devname, strlen(devname));
+}
+
+
+long
+cons_close(long dev)
+{
+	return dispatch(CCB_CLOSE, dev);
+}
+
+
+long
+cons_read(long dev, void *buf, long count, long offset)
+{
+	static char readbuf[SECT_SIZE];		/* minimize frame size */
+
+	if ((count & (SECT_SIZE-1)) == 0 && (offset & (SECT_SIZE-1)) == 0) {
+		/* I/O is aligned... this is easy! */
+		return dispatch(CCB_READ, dev, count, buf,
+				offset / SECT_SIZE);
+	} else {
+		long bytesleft, iocount, blockoffset, iosize, lbn, retval;
+
+		bytesleft = count;
+		iocount = 0;
+		blockoffset = offset % SECT_SIZE;
+		lbn = offset / SECT_SIZE;
+
+		while (bytesleft > 0) {
+			if ((blockoffset == 0) && (bytesleft >= SECT_SIZE)) {
+				/*
+				 * This portion of the I/O is aligned,
+				 * so read it straight in:
+				 */
+				iosize = SECT_SIZE;
+				retval = dispatch(CCB_READ, dev, iosize, buf,
+						  lbn);
+				if (retval != iosize) {
+					printf("read error 0x%lx\n",retval);
+					return -1;
+				}
+			} else {
+				/*
+				 * Not aligned; must read it into a
+				 * temporary buffer and go from there.
+				 */
+				retval = dispatch(CCB_READ, dev, SECT_SIZE,
+						  readbuf, lbn);
+				if (retval != SECT_SIZE) {
+					printf("read error, lbn %ld: 0x%lx\n",
+					       lbn, retval);
+					return -1;
+				}
+				iosize = bytesleft;
+				if (blockoffset + iosize >= SECT_SIZE) {
+					iosize = SECT_SIZE - blockoffset;
+				}
+				memcpy(buf, readbuf + blockoffset, iosize);
+			}
+			buf += iosize;
+			iocount += iosize;
+			bytesleft -= iosize;
+			blockoffset = 0;
+			++lbn;
+		}
+		return iocount;
+	}
+}
+
+
+void cons_open_console(void)
+{
+	dispatch(CCB_OPEN_CONSOLE);
+}
+
+void cons_close_console(void)
+{
+	dispatch(CCB_CLOSE_CONSOLE);
+}
+
+void
+cons_init(void)
+{
+	char envval[256];
+
+	if (cons_getenv(ENV_TTY_DEV, envval, sizeof(envval)) < 0) {
+		halt();		/* better than random crash */
+	}
+	cons_dev = simple_strtoul(envval, 0, 10);
+
+	cons_open_console();
+}

+ 854 - 0
package/aboot/src/disk.c

@@ -0,0 +1,854 @@
+/*
+ * aboot/disk.c
+ *
+ * This file is part of aboot, the SRM bootloader for Linux/Alpha
+ * Copyright (C) 1996 Linus Torvalds, David Mosberger, and Michael Schwingen.
+ *
+ * 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.
+ */
+#ifdef TESTING
+#  include <stdlib.h>
+#  include <stdio.h>
+#  include <fcntl.h>
+#  include <unistd.h>
+#endif
+
+#include "config.h"
+#include "aboot.h"
+#include "bootfs.h"
+#include "cons.h"
+#include "disklabel.h"
+#include "utils.h"
+#include "string.h"
+
+#include <linux/elf.h>
+#include <asm/console.h>
+#include "system.h"
+
+extern struct bootfs ext2fs;
+extern struct bootfs iso;
+extern struct bootfs ufs;
+extern struct bootfs dummyfs;
+
+struct disklabel * label;
+int boot_part = -1;
+
+static struct bootfs *bootfs[] = {
+	&ext2fs,
+	&iso,
+	&ufs
+};
+
+/*
+ * Attempt a "raw" boot (uncompressed ELF kernel follows right after aboot).
+ *
+ * This will eventually be rewritten to accept compressed kernels
+ * (along with net_aboot).  It should also be merged with the other
+ * load methods as there is some code duplication here we don't want.
+ */
+
+int
+load_raw (long dev)
+{
+	extern char _end;
+	char *buf;
+	long aboot_size = &_end - (char *) BOOT_ADDR;
+	long ksect = (aboot_size + SECT_SIZE - 1) / SECT_SIZE + BOOT_SECTOR;
+	long nread;
+	int i;
+
+	printf("aboot: loading kernel from boot sectors...\n");
+
+	/* We only need the program headers so this should be fine */
+	buf = malloc(SECT_SIZE);
+
+	/* Read ELF headers: */
+	nread = cons_read(dev, buf, SECT_SIZE, ksect * SECT_SIZE);
+	if (nread != SECT_SIZE) {
+		printf("aboot: read returned %ld instead of %ld bytes\n",
+		       nread, (long) SECT_SIZE);
+		return -1;
+	}
+	if (first_block(buf, SECT_SIZE) < 0) {
+		return -1;
+	}
+
+	for (i = 0; i < nchunks; ++i) {
+		char *dest;
+
+		printf("aboot: segment %d, %ld bytes at %#lx\n", i, chunks[i].size,
+		       chunks[i].addr);
+#ifdef TESTING
+		dest = malloc(chunks[i].size);
+#else
+		dest = (char *) chunks[i].addr;
+#endif		      
+
+		nread = cons_read(dev, dest, chunks[i].size,
+				  chunks[i].offset + ksect * SECT_SIZE);
+		if (nread != chunks[i].size) {
+			printf("aboot: read returned %ld instead of %ld bytes\n",
+			       nread, chunks[i].size);
+			return -1;
+		}
+	}
+	return 0;
+}
+
+
+int
+load_uncompressed (int fd)
+{
+	long nread, nblocks;
+	unsigned char *buf;
+	int i;
+
+	buf = malloc(bfs->blocksize);
+
+	/* read ELF headers: */
+	nread = (*bfs->bread)(fd, 0, 1, buf);
+	if (nread != bfs->blocksize) {
+		printf("aboot: read returned %ld instead of %ld bytes\n",
+		       nread, sizeof(buf));
+		return -1;
+	}
+#ifdef DEBUG
+	{
+		int i,j,c;
+	
+		for(i = 0; i < 16; i++) {
+			for (j = 0; j < 16; j++)
+				printf("%02X ", buf[j+16*i]);
+			for(j = 0; j < 16; j++) {
+				c = buf[j+16*i];
+				printf("%c", (c >= ' ') ? c : ' ');
+			}
+			printf("\n");
+		}
+	}
+#endif
+	if (first_block(buf, bfs->blocksize) < 0) {
+		return -1;
+	}
+
+	/* read one segment at a time */
+	for (i = 0; i < nchunks; ++i) {
+		char *dest;
+
+		/* include any unaligned bits of the offset */
+		nblocks = (chunks[i].size + (chunks[i].offset & (bfs->blocksize - 1)) +
+			   bfs->blocksize - 1) / bfs->blocksize;
+		printf("aboot: segment %d, %ld bytes at %#lx\n", i, chunks[i].size,
+		       chunks[i].addr);
+#ifdef TESTING
+		dest = malloc(nblocks * bfs->blocksize);
+#else
+		dest = (char *) chunks[i].addr;
+#endif		      
+
+		nread = (*bfs->bread)(fd, chunks[i].offset / bfs->blocksize,
+				      nblocks, dest);
+		if (nread != nblocks * bfs->blocksize) {
+			printf("aboot: read returned %ld instead of %ld bytes\n",
+			       nread, nblocks * bfs->blocksize);
+			return -1;
+		}
+		/* In practice, they will always be aligned */
+		if ((chunks[i].offset & (bfs->blocksize - 1)) != 0)
+			memmove(dest,
+				dest + (chunks[i].offset & (bfs->blocksize - 1)),
+				chunks[i].size);
+	}
+	return 0;
+}
+
+static long
+read_kernel (const char *filename)
+{
+	volatile int attempt, method;
+	long len;
+	int fd;
+	static struct {
+		const char *name;
+		int (*func)(int fd);
+	} read_method[]= {
+		{"uncompressed", load_uncompressed},
+		{"compressed",	 uncompress_kernel}
+	};
+	long res;
+#	define NUM_METHODS ((int)(sizeof(read_method)/sizeof(read_method[0])))
+
+#ifdef DEBUG
+	printf("read_kernel(%s)\n", filename);
+#endif
+
+	method = 0;
+	len = strlen(filename);
+	if (len > 3 && filename[len - 3] == '.'
+	    && filename[len - 2] == 'g' && filename[len - 1] == 'z')
+	{
+		/* if filename ends in .gz we don't try plain method: */
+		method = 1;
+	}
+
+	for (attempt = 0; attempt < NUM_METHODS; ++attempt) {
+		fd = (*bfs->open)(filename);
+		if (fd < 0) {
+			printf("%s: file not found\n", filename);
+			return -1;
+		}
+		printf("aboot: loading %s %s...\n",
+		       read_method[method].name, filename);
+
+		if (!_setjmp(jump_buffer)) {
+			res = (*read_method[method].func)(fd);
+
+			(*bfs->close)(fd);
+			if (res >= 0) {
+				return 0;
+			}
+		}
+		method = (method + 1) % NUM_METHODS;
+	}
+	return -1;
+}
+
+long
+read_initrd()
+{
+	int nblocks, nread, fd;
+	struct stat buf;
+
+	fd = (*bfs->open)(initrd_file);
+	if (fd < 0) {
+		printf("%s: file not found\n", initrd_file);
+		return -1;
+	}
+	(*bfs->fstat)(fd, &buf);
+	initrd_size = buf.st_size;
+
+#ifdef TESTING
+	initrd_start = (unsigned long) malloc(initrd_size);
+#else
+	/* put it as high up in memory as possible */
+	if (!free_mem_ptr)
+		free_mem_ptr = memory_end();
+	/* page aligned (downward) */
+	initrd_start = (free_mem_ptr - initrd_size) & ~(PAGE_SIZE-1);
+	/* update free_mem_ptr so malloc() still works */
+	free_mem_ptr = initrd_start;
+#endif
+
+	nblocks = initrd_size / bfs->blocksize;
+	printf("aboot: loading initrd (%ld bytes/%d blocks) at %#lx\n",
+		initrd_size, nblocks, initrd_start);
+	if (nblocks & (bfs->blocksize - 1)) nblocks++;
+	nread = (*bfs->bread)(fd, 0, nblocks, (char*) initrd_start);
+	if (nread != nblocks * bfs->blocksize) {
+		printf("aboot: read returned %d instead of %d (%d*%d) bytes\n",
+			nread, nblocks * bfs->blocksize,
+			nblocks, bfs->blocksize);
+		return -1;
+	}
+	return 0;
+}
+
+static void
+get_disklabel (long dev)
+{
+	static char lsect[512];
+	long nread;
+
+#ifdef DEBUG
+	printf("load_label(dev=%lx)\n", dev);
+#endif
+	nread = cons_read(dev, &lsect, LABELOFFSET + sizeof(*label),
+			  LABELSECTOR);
+	if (nread != LABELOFFSET + sizeof(*label)) {
+		printf("aboot: read of disklabel sector failed (nread=%ld)\n",
+		       nread);
+		return;
+	}
+	label = (struct disklabel*) &lsect[LABELOFFSET];
+	if (label->d_magic  == DISKLABELMAGIC &&
+	    label->d_magic2 == DISKLABELMAGIC)
+	{
+		printf("aboot: valid disklabel found: %d partitions.\n",
+		       label->d_npartitions);
+	} else {
+		printf("aboot: no disklabel found.\n");
+		label = 0;
+	}
+}
+
+
+struct bootfs *
+mount_fs (long dev, int partition)
+{
+	struct d_partition * part;
+	struct bootfs * fs = 0;
+	int i;
+
+#ifdef DEBUG
+	printf("mount_fs(%lx, %d)\n", dev, partition);
+#endif
+	if (partition == 0) {
+		fs = &dummyfs;
+		if ((*fs->mount)(dev, 0, 0) < 0) {
+			printf("aboot: disk mount failed\n");
+			return 0;
+		}
+	} else if (!label) {
+		/* floppies and such, no disklabel */
+		for (i = 0; i < (int)(sizeof(bootfs)/sizeof(bootfs[0])); ++i) {
+			if ((*bootfs[i]->mount)(dev, 0, 1) >= 0) {
+				fs = bootfs[i];
+				break;
+			}
+		}
+		if (!fs) {
+			printf("aboot: unknown filesystem type\n");
+			return 0;
+		}
+	} else {
+		if ((unsigned) (partition - 1) >= label->d_npartitions) {
+			printf("aboot: invalid partition %u\n", partition);
+			return 0;
+		}
+		part = &label->d_partitions[partition - 1];
+		for (i = 0; bootfs[i]->fs_type != part->p_fstype; ++i) {
+			if (i + 1
+			    >= (int) (sizeof(bootfs)/sizeof(bootfs[0])))
+			{
+				printf("aboot: don't know how to mount "
+				       "partition %d (filesystem type %d)\n",
+				       partition, part->p_fstype);
+				return 0;
+			}
+		}
+		fs = bootfs[i];
+		if ((*fs->mount)(dev, (long)(part->p_offset) * (long)(label->d_secsize), 0)
+		    < 0) {
+			printf("aboot: mount of partition %d failed\n",
+			       partition);
+			return 0;
+		}
+	}
+	return fs;
+}
+
+void
+list_directory (struct bootfs *fs, char *dir)
+{
+	int fd = (*fs->open)(dir);
+	/* yes, our readdir() is not exactly like the real one */
+	int rewind = 0;
+	const char * ent;
+
+	if (fd < 0) {
+		printf("%s: directory not found\n", dir);
+		return;
+	}
+	
+	while ((ent = (*fs->readdir)(fd, !rewind++))) {
+		printf("%s\n", ent);
+	}
+	(*fs->close)(fd);
+}
+
+int
+open_config_file(struct bootfs *fs)
+{
+	static const char *configs[] = {
+		"/etc/aboot.conf",
+		"/aboot.conf",
+		"/etc/aboot.cfg",
+		"/aboot.cfg"
+	};
+	const int nconfigs = sizeof(configs) / sizeof(configs[0]);
+	int i, fd = -1;
+
+	for (i = 0; i < nconfigs; i++) {
+		fd = (*fs->open)(configs[i]);
+		if (fd >= 0)
+			break;
+	}
+	return fd;
+}
+
+void
+print_config_file (struct bootfs *fs)
+{
+	int fd, nread, blkno = 0;
+	char *buf;
+
+	fd = open_config_file(fs);
+	if (fd < 0) {
+		printf("%s: file not found\n", CONFIG_FILE);
+		return;
+	}
+	buf = malloc(fs->blocksize + 1);
+	if (!buf) {
+		printf("aboot: malloc failed!\n");
+		return;
+	}
+	do {
+		nread = (*fs->bread)(fd, blkno++, 1, buf);
+		buf[nread] = '\0';
+		printf("%s", buf);
+	} while (nread > 0);
+	(*fs->close)(fd);
+}
+
+
+int
+get_default_args (struct bootfs *fs, char *str, int num)
+{
+	int fd, nread, state, line, blkno = 0;
+	char *buf, *d, *p;
+
+	*str = '\0';
+	fd = open_config_file(fs);
+	if (fd < 0) {
+		printf("%s: file not found\n", CONFIG_FILE);
+		return -1;
+	}
+	buf = malloc(fs->blocksize);
+	if (!buf) {
+		printf("aboot: malloc failed!\n");
+		return -1;
+	}
+	d = str;
+	line = 1;
+	state = 2;
+	do {
+		nread = (*fs->bread)(fd, blkno++, 1, buf);
+		p = buf;
+		while (p < buf + nread && *p && state != 5) {
+			switch (state) {
+			      case 0: /* ignore rest of line */
+			      case 1: /* in comment */
+				if (*p == '\n') state = 2;
+				break;
+
+			      case 2: /* after end of line */
+				line++;
+				if (*p == num) {
+					state = 3;	/* found it... */
+					break;
+				}
+				if (*p == '#') {
+					state = 1;	/* comment */
+					break;
+				}
+				if (*p == '-') {
+					state = 5;	/* end-of-file mark */
+					break;
+				}
+				state = 0;	/* ignore rest of line */
+				break;
+
+			      case 3: /* after matched number */
+				if (*p == ':') {
+					state = 4;	/* copy string */
+				} else {
+					state = 2;	/* ignore rest */
+					printf("aboot: syntax error in line "
+					       "%d: `:' expected\n", line);
+				}
+				break;
+
+			      case 4: /* copy until EOL */
+				if (*p == '\n') {
+					*d = 0;
+					state=5;
+				} else {
+					*d++ = *p;
+				}
+				break;
+
+			      default:
+				break;
+			}
+			p++;
+		}
+	} while (nread > 0 && state != 5);
+	(*fs->close)(fd);
+#ifdef DEBUG
+	printf("get_default done\n");
+#endif
+
+	if (state != 5) {
+		printf("aboot: could not find default config `%c'\n", num);
+		return -1;
+	}
+#ifdef DEBUG
+	printf("get_default_args(%s,%d)\n", str, num);
+#endif
+	return 0;
+}
+
+
+static void
+print_help(void)
+{
+	printf("Commands:\n"
+	       " h, ?			Display this message\n"
+	       " q			Halt the system and return to SRM\n"
+	       " p 1-8			Look in partition <num> for configuration/kernel\n"
+	       " l			List preconfigured kernels\n"
+	       " d <dir>		List directory <dir> in current filesystem\n"
+	       " b <file> <args>	Boot kernel in <file> (- for raw boot)\n"
+	       " i <file>		Use <file> as initial ramdisk\n"
+	       "			with arguments <args>\n"
+	       " 0-9			Boot preconfiguration 0-9 (list with 'l')\n");
+}
+
+static void
+get_aboot_options (long dev)
+{
+	int preset      = 0; /* no preset */
+	int interactive = 0;  /* non-interactive */
+	char *extra_args = NULL;
+
+#ifdef DEBUG
+	printf("get_aboot_options(%lx)\n",dev);
+	printf("kernel_args=\"%s\"\n",kernel_args);
+#endif
+
+	/* Forms of -flags argument from SRM */
+	if (kernel_args[0] >= '1' && kernel_args[0] <= '9'
+	    && kernel_args[1] == ':' && kernel_args[2]
+	    && (kernel_args[3] == '\0' || kernel_args[3] == ' '))
+	{
+		/* <partition>:<preset> - where <preset> is an entry
+                   in /etc/aboot.conf (to be found on <partition>), or
+                   'i' for interactive */
+		config_file_partition = kernel_args[0] - '0';
+		preset = kernel_args[2];
+		if (kernel_args[3]) {
+			extra_args=&kernel_args[3];
+			while (*extra_args == ' ') { extra_args++; }
+			if (*extra_args == '\0') extra_args = NULL;
+		}
+#ifdef DEBUG
+		printf("partition:preset = %ld:%c\n", config_file_partition,
+		       preset);
+#endif
+	} else if (kernel_args[0] 
+		   && (kernel_args[1] == '\0' || kernel_args[1] == ' '))  {
+		/* Single character option, for Jensen and friends -
+                   this is either a preconfigured entry in
+                   /etc/aboot.conf or 'i' for interactive*/
+		if (kernel_args[0] == 'i') interactive = 1;
+		else {
+			preset = kernel_args[0];
+			if (kernel_args[1]) {
+				/* are there actually extra args? */
+				extra_args=&kernel_args[1];
+				while (*extra_args == ' ') { extra_args++; }
+				if (*extra_args == '\0') extra_args = NULL;
+			}
+		}
+	} else if (kernel_args[0] == '\0') {
+		interactive = 1;
+	} else {
+		/* attempt to parse the arguments given */
+	}
+
+#ifdef DEBUG
+	if (extra_args) printf("extra args: \"%s\"\n",extra_args);
+#endif
+
+	if (preset || interactive) {
+		char buf[256], *p;
+		struct bootfs *fs = 0;
+		static int first = 1;
+		int done = 0;
+
+		while (!done) {
+			/* If we have a setting from /etc/aboot.conf, use it */
+			if (preset) {
+#ifdef DEBUG
+				printf("trying preset %c\n", preset);
+#endif
+				if (!fs) {
+					fs = mount_fs(dev, config_file_partition);
+					if (!fs) {
+						preset = 0;
+						continue;
+					}
+				}
+				if (get_default_args(fs, buf, preset) >= 0)
+					break;
+
+				/* Doh, keep on going */
+				preset = 0;
+				continue;
+			}
+			
+			/* Otherwise, clear out kernel_args and prompt the user */
+			kernel_args[0] = 0;
+			if (first) {
+				printf("Welcome to aboot " ABOOT_VERSION "\n");
+				print_help();
+				first = 0;
+			}
+			printf("aboot> ");
+#ifdef TESTING
+			fgets(buf, sizeof(buf), stdin);
+			buf[strlen(buf)-1] = 0;
+#else
+			getline(buf, sizeof(buf));
+#endif
+			printf("\n");
+
+			switch (buf[0]) {
+			case 'h':
+			case '?':
+				print_help();
+				break;
+			case 'q':
+				halt();
+				break;
+			case 'p':
+				p = strchr(buf, ' ');
+				while (p && *p == ' ') ++p;
+
+				if (p && p[0] >= '1' && p[0] <= '8'
+				    && (p[1] == '\0' || p[1] == ' ')) {
+					config_file_partition = p[0] - '0';
+					fs = 0; /* force reread */
+				} else {
+					printf("Please specify a number between 1 and 8\n");
+				}
+				break;
+			case 'l':
+				if (!fs) {
+					fs = mount_fs(dev, config_file_partition);
+					if (!fs) {
+						printf("Partition %ld is invalid. "
+						       "Please specify another with 'p'\n",
+						       config_file_partition);
+						continue;
+					}
+				}
+				print_config_file(fs);
+				break;
+			case 'd':
+				if (!fs) {
+					fs = mount_fs(dev, config_file_partition);
+					if (!fs) {
+						printf("Partition %ld is invalid. "
+						       "Please specify another with 'p'\n",
+						       config_file_partition);
+						continue;
+					}
+				}
+				/* skip past whitespace */
+				p = strchr(buf, ' ');
+				while (p && *p == ' ') ++p;
+				if (p)
+					list_directory(fs, p);
+				else
+					list_directory(fs, "/");
+				break;
+			case 'b':
+				/* skip past whitespace */
+				p = strchr(buf, ' ');
+				while (p && *p == ' ') ++p;
+				if (p) {
+					strcpy(buf, p);
+					done = 1;
+				} else {
+					printf("Please specify a file to load the kernel from, "
+					       "or '-' to load the kernel from the boot sector\n");
+				}
+				break;
+			case 'i':
+				/* skip past whitespace */
+				p = strchr(buf, ' ');
+				while (p && *p == ' ') ++p;
+				if (p)
+					strcpy(initrd_file, p);
+				else {
+					printf("Please specify a file to use as initial ramdisk\n");
+				}
+				break;
+			case '0' ... '9':
+				preset = buf[0];
+				p = strchr(buf, ' ');
+				while (p && *p == ' ') ++p;
+				if (p) {
+					strcpy(kernel_args, p);
+					extra_args=kernel_args;
+				}
+				break;
+			default:
+				break;
+
+			}
+		}
+
+		/* if we have extra args, append them to buf */
+		if (extra_args) {
+			p=buf; while (p && *p) p++;
+			*p++=' ';
+			strcpy(p, extra_args);
+		}
+
+		/* split on space into kernel + args */
+		p = strchr(buf, ' ');
+		if (p) {
+			/* skip past leading whitespace */
+			*p++ = '\0';
+			while (p && *p == ' ') ++p;
+			strcpy(kernel_args, p);
+		}
+		strcpy(boot_file, buf);
+	}
+
+#ifdef DEBUG
+	printf("boot_file=\"%s\", kernel_args=\"%s\"\n",boot_file,kernel_args);
+#endif
+
+	{
+		/* parse off initrd= option from kernel_args if any */
+		char *p = kernel_args;
+		/* poor man's strstr */
+		do {
+			if (strncmp(p, "initrd=", 7) == 0)
+				break;
+		} while (*p++);
+		
+		if (*p) {
+			char *a = p + 7; /* argument */
+			char *e = strchr (a, ' ');
+			if (e) {
+				strncpy(initrd_file, a, e-a);
+				initrd_file[e-a] = 0;
+				strcpy(p, e);
+			} else {
+				strcpy(initrd_file, a);
+				*p = 0;
+			}
+		}
+	}
+
+
+	/* parse off partition number from boot_file if any: */
+	if (boot_file[0] >= '0' && boot_file[0] <= '9' && boot_file[1] == '/')
+	{
+		boot_part = boot_file[0] - '0';
+		strcpy(boot_file, boot_file + 2);
+	} else {
+		boot_part = config_file_partition;
+	}
+}
+
+static long
+load (long dev)
+{
+	char *fname;
+
+#ifdef DEBUG
+	printf("load(%lx)\n", dev);
+#endif
+	fname = boot_file;
+	if (fname[0] == '-' && fname[1] == '\0') {
+		/* a single "-" implies raw boot: */
+		if (load_raw(dev) < 0) {
+			return -1;
+		}
+	} else {
+		/* if there's no disklabel, boot_part will be ignored anyway */
+		bfs = mount_fs(dev, boot_part);
+		if (!bfs) {
+			printf("aboot: mount of partition %d failed\n", boot_part);
+			return -1;
+		}
+		if (read_kernel(fname) < 0) {
+			return -1;
+		}
+	}
+	/* clear bss: */
+	printf("aboot: zero-filling %ld bytes at 0x%p\n", bss_size, bss_start);
+#ifndef TESTING
+	memset((char*)bss_start, 0, bss_size);
+#endif
+
+	if (initrd_file[0] == 0)
+		return 0;
+
+	/* work around a bug in the ext2 code */
+	bfs = mount_fs(dev, boot_part);
+	if (!bfs) {
+		printf("aboot: mount of partition %d failed\n", boot_part);
+		return -1;
+	}
+	if (read_initrd() < 0) {
+		return -1;
+	}
+	return 0;
+}
+
+
+long
+load_kernel (void)
+{
+	char envval[256];
+	long result;
+	long dev;
+
+#ifdef TESTING
+	const char *e;
+	if ((e = getenv("BOOTED_DEV"))) {
+		strncpy(envval, e, sizeof(envval)-1);
+		envval[sizeof(envval)-1] = 0;
+	} else {
+		printf("aboot: Can't get BOOTED_DEV environment variable!\n");
+		return -1;
+	}
+#else
+	if (cons_getenv(ENV_BOOTED_DEV, envval, sizeof(envval)) < 0) {
+		printf("aboot: Can't get BOOTED_DEV environment variable!\n");
+		return -1;
+	}
+#endif
+
+	printf("aboot: booting from device '%s'\n", envval);
+	dev = cons_open(envval);
+	if (dev < 0) {
+		printf("aboot: unable to open boot device `%s': %lx\n",
+		       envval, dev);
+		return -1;
+	}
+	dev &= 0xffffffff;
+	get_disklabel(dev);
+
+	while (1) {
+		get_aboot_options(dev);
+		result = load(dev);
+		if (result != -1)
+			break;
+		/* load failed---query user interactively */
+		strcpy(kernel_args, "i");
+	}
+#ifdef DEBUG
+	printf("load done\n");
+#endif
+	cons_close(dev);
+	return result;
+}

+ 1 - 0
package/aboot/src/doc/faq/.cvsignore

@@ -0,0 +1 @@
+*.html

+ 9 - 0
package/aboot/src/doc/faq/Makefile

@@ -0,0 +1,9 @@
+all-html : SRM-HOWTO/index.html
+
+clean :
+	rm -rf SRM-HOWTO 
+
+SRM-HOWTO/index.html : SRM-HOWTO.sgml
+	            sgmltools --backend=html SRM-HOWTO.sgml
+
+#.PHONY clean

+ 2293 - 0
package/aboot/src/doc/faq/SRM-HOWTO.sgml

@@ -0,0 +1,2293 @@
+<!DOCTYPE Article PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+
+<!-- <!DOCTYPE Article PUBLIC "-//Davenport//DTD DocBook V3.0//EN"> -->
+
+<Article id="index">
+
+<articleinfo>
+
+<Title>SRM Firmware Howto</Title>
+
+<authorgroup>
+<AUTHOR>
+<firstname>Rich</firstname> <surname>Payne</surname>
+<affiliation><address><email>rdp@alphalinux.org</email></address></affiliation>
+</AUTHOR>
+<!-- and -->
+<AUTHOR>
+<firstname>David</firstname> <surname>Huggins-Daines</surname>
+<affiliation><address><email>dhuggins@linuxcare.com</email></address></affiliation>
+</AUTHOR>
+</authorgroup>
+
+<PubDate>v0.8.1, 14 February 2004</PubDate>
+
+<Abstract>
+<Para>
+This document describes how to boot Linux/Alpha using the SRM console,
+which is the console firmware also used to boot 
+<productname>HP Tru64 Unix</productname>
+(also known as <productname>Digital Unix</productname> and <productname>OSF/1</productname>) and <productname>OpenVMS</productname>.
+</Para>
+</Abstract>
+
+</articleinfo>
+
+<Sect1 id="SRM-about">
+<Title>About this manual</Title>
+
+<Sect2>
+<Title>Who should read this manual</Title>
+
+<Para>
+You should read this manual if you are installing Linux on a new
+Alpha system that can only boot from the SRM console, or if you are
+installing Linux on an older Alpha system that can use the SRM console
+and wish to use SRM to boot your Linux installation.
+</Para>
+
+<Para>
+Because SRM is the only way to boot Linux on modern Alpha systems,
+and because it provides the proper operating environment for Unix and
+Unix-like operating systems (such as Linux), it is the recommended way
+of booting Linux on Alpha when available.
+</Para>
+
+<Para>
+Sometimes, it is preferable to use the ARC, ARCSBIOS, or AlphaBIOS
+console, such as if you have a machine for which SRM is not available,
+if you wish to dual-boot with <productname>Windows NT</productname>
+without switching consoles,
+or if you have hardware that is not supported by SRM.  On these
+machines, you will typically use MILO to boot Linux.  For more
+information, refer to the MILO Howto, available from
+<ULink URL="http://www.alphalinux.org/faq/milo.html">http://www.alphalinux.org/faq/milo.html</ULink>.
+</Para>
+
+</Sect2>
+
+<Sect2>
+<Title>Conventions</Title>
+
+<Para>
+Throughout this manual, we will use the following conventions for
+commands to be entered by the user:
+</Para>
+
+<Para>
+SRM console commands will be shown with the characteristic SRM
+'&#62;&#62;&#62;' prompt, like this: 
+<FOOTNOTE>
+
+<Para>
+On multiprocessor machines, you
+will see 'P00&#62&#62;' instead, or possibly some other number depending on
+which processor SRM is running. 
+</Para>
+
+</FOOTNOTE>
+
+
+<Screen>
+&#62;&#62;&#62; boot dva0 -fi linux.gz -fl "root=/dev/fd0 load_ramdisk=1"
+</Screen>
+
+</Para>
+
+<Para>
+Unix commands will be shown with the '&num;' command prompt if they are
+to be run as <Literal remap="tt">root</Literal>, or '$' if they are to be run by a normal user,
+like this:
+
+<Screen>
+# swriteboot -f3 /dev/sda /boot/bootlx
+</Screen>
+
+</Para>
+
+<Para>
+Aboot commands will be shown with the 'aboot&#62;' command prompt, like
+this:
+
+<Screen>
+aboot&#62; b 6/boot/vmlinuz root=/dev/hda6
+</Screen>
+
+</Para>
+
+</Sect2>
+
+</Sect1>
+
+<Sect1 id="SRM-whatis">
+<Title>What is SRM?</Title>
+
+<Para>
+SRM console is used by Alpha systems as
+Unix-style boot firmware. <productname>Tru64 Unix</productname> and
+<productname>OpenVMS</productname> depend on it and
+Linux can boot from it. You can recognize SRM console as a blue screen
+with a prompt that is presented to you on power-up.
+</Para>
+
+<Sect2>
+<Title>Getting to SRM</Title>
+
+<Para>
+Most Alpha systems have both the SRM and ARC/AlphaBIOS console in
+their firmware.  On one of these machines, if your machine starts up
+with ARC/AlphaBIOS by default, you can switch to SRM through the
+"<guimenuitem>Console Selection</guimenuitem>" option in the Advanced CMOS Setup menu.  To make <!-- FIXME Markup should do the marking -->
+the change permanent, you should set the <Literal remap="tt">os&lowbar;type</Literal> environment
+variable in SRM to "OpenVMS" or "Unix", like this:
+
+<Screen>
+&#62;&#62;&#62; set os_type Unix
+</Screen>
+
+</Para>
+
+<Para>
+Either one will work to boot Linux.  However, if you intend to
+dual-boot OpenVMS on this machine, you must set <Literal remap="tt">os&lowbar;type</Literal> to
+"OpenVMS".  Conversely, to return to ARC/AlphaBIOS, you can set
+<Literal remap="tt">os&lowbar;type</Literal> to "NT".
+</Para>
+
+<Para>
+Some older systems may not have both SRM and ARC in firmware as
+shipped.  On these systems, you will have to upgrade your firmware.
+See <ULink
+URL="http://ftp.digital.com/pub/DEC/Alpha/firmware/"
+>http://ftp.digital.com/pub/DEC/Alpha/firmware</ULink
+> for the 
+latest firmware updates and instructions.
+</Para>
+
+<Para>
+A few older systems (primarily evaluation boards such as the 164SX
+and 164LX) are "half-flash" systems, whose firmware can hold SRM or
+AlphaBIOS, but not both.  If you have one of these machines, you will
+have to reflash your firmware with the SRM console using the AlphaBIOS
+firmware update utility.  Again, see
+<ULink
+URL="http://ftp.digital.com/pub/DEC/Alpha/firmware/"
+>http://ftp.digital.com/pub/DEC/Alpha/firmware</ULink
+> for firmware
+images and instructions.  If you wish to return to AlphaBIOS on these
+machines, you may rerun the firmware update utility from a floppy in
+SRM using the <Literal remap="tt">fwupdate</Literal> command.  You can also start AlphaBIOS
+from a floppy using the <Literal remap="tt">arc</Literal> command.
+</Para>
+
+</Sect2>
+
+<Sect2>
+<Title>Using the SRM console</Title>
+
+<Para>
+The SRM console works very much like a Unix or OpenVMS shell.  It
+views your NVRAM and devices as a pseudo-filesystem.  You can see this
+if you use the <command>ls</command> command.  Also, it contains a fairly large set
+of diagnostic, setup, and debugging utilities, the details of which
+are beyond the scope of this document.  As in the Unix shell, you can
+pipe the output of one command to the input of another, and there is a
+<command>more</command> command that works not unlike the Unix one.  To get a full
+listing of available commands, run:
+
+<Screen>
+&#62;&#62;&#62; help | more
+</Screen>
+
+</Para>
+
+<Para>
+As well, SRM has environment variables, a number of which are
+pre-defined and correspond to locations in NVRAM.  You can view the
+entire list of environment variables and their values with the
+<command>show</command> command (there are quite a few of them, so you will probably
+want to pipe its output to <command>more</command>).  You can also show variables
+matching a "glob" pattern - for example, <command>show boot*</command> will show all
+the variables starting in "boot".
+</Para>
+
+<Para>
+Environment variables are categorized as either <Emphasis>read-only</Emphasis>,
+<Emphasis>warm non-volatile</Emphasis>, or <Emphasis>cold non-volatile</Emphasis>.  The full listing
+of pre-defined variables is detailed in the Alpha Architecture
+Reference Manual.  The most useful pre-defined environment variables
+for the purposes of booting Linux are <varname>bootdef&lowbar;dev</varname>,
+<varname>boot&lowbar;file</varname>, <varname>boot&lowbar;flags</varname>, and
+<varname>auto&lowbar;action</varname>, all of which are cold non-volatile.
+</Para>
+
+<Para>
+To set environment variables, use the <command>set</command> command, like this:
+
+<Screen>
+&#62;&#62;&#62; set bootdef_def dka0
+</Screen>
+
+</Para>
+
+<Para>
+If you set an undefined variable, it will be created for you, however
+it will not persist across reboots.
+</Para>
+
+<Para>
+The <varname>bootdef&lowbar;dev</varname> variable specifies the device (using
+VMS naming conventions - see <XRef LinkEnd="device-naming"> for an
+explanation of these) which will be booted from if no device is
+specified on the <Literal remap="tt">boot</Literal> command line, or in an automatic boot.
+The <varname>boot&lowbar;file</varname> variable contains the filename to be
+loaded by the secondary bootloader, while <varname>boot&lowbar;flags</varname>
+contains any extra flags.  <varname>auto&lowbar;action</varname> specifies the
+action which the console should take on power-up.  By default, it is
+set to <Literal remap="tt">HALT</Literal>, meaning that the machine will start up in the
+SRM console.  Once you have configured your bootloader and the
+boot-related variables, you can set it to <Literal remap="tt">BOOT</Literal> in order to
+boot automatically on power-up.
+</Para>
+
+<Para>
+Finally, two helpful console keystrokes you should know are
+<keycombo action='simul'><keycap>Control</keycap><keycap>C</keycap></keycombo>,
+which, as in the shell, halts a command in progress (such
+as an automatic boot), and 
+<keycombo action='simul'><keycap>Control</keycap><keycap>P</keycap></keycombo>,
+which if issued from the aboot
+prompt (or other secondary bootloader) will halt the bootloader and
+return you to the SRM console.
+</Para>
+
+</Sect2>
+
+<Sect2 id="how-srm-boots">
+<Title>How Does SRM Boot an OS?</Title>
+
+<Para>
+All versions of SRM can boot from SCSI disks and the versions for
+recent platforms, such as the Noname or AlphaStations can boot from
+floppy disks as well.  Network booting via <Literal remap="tt">bootp</Literal> is supported.
+Note that older SRM versions (notably the one for the Jensen)
+cannot boot from floppy disks. Booting from IDE devices
+is supported on newer platforms (164SX, 164LX, 164UX, DS20, DS10, DP264, UP2000(+), UP1000, UP1100 etc.). 
+</Para>
+
+<Para>
+Booting Linux with SRM is a two step process: first, SRM loads and
+transfers control to the secondary bootstrap loader.  Then the
+secondary bootstrap loader sets up the environment for Linux, reads
+the kernel image from a disk filesystem and finally transfers control to Linux.
+</Para>
+
+<Para>
+Currently, there are two secondary bootstrap loaders for Linux:
+the <Emphasis>raw</Emphasis> loader that comes with the Linux kernel and <Literal remap="tt">aboot</Literal>
+which is distributed separately.  These two loaders are described in
+more detail below.
+</Para>
+
+</Sect2>
+
+<Sect2>
+<Title>Loading The Secondary Bootstrap Loader</Title>
+
+<Para>
+SRM knows nothing about filesystems or disk-partitions.  It simply
+expects that the secondary bootstrap loader occupies a consecutive
+range of physical disk sector, starting from a given offset.  The
+information on the size of the secondary bootstrap loader and the
+offset of its first disk sector is stored in the first 512 byte
+sector.  Specifically, the long integer at offset 480 stores the
+<Emphasis>size</Emphasis> of the secondary bootstrap loader (in 512-byte blocks) and
+the long at offset 488 gives the <Emphasis>sector number</Emphasis> at which the
+secondary bootstrap loader starts.  The first sector also stores a
+flag-word at offset 496 which is always 0 and a checksum at offset
+504.  The checksum is simply the sum of the first 63 long integers in
+the first sector.
+</Para>
+
+<Para>
+If the checksum in the first sector is correct, SRM goes ahead and
+reads the <Emphasis>size</Emphasis> sectors starting from the sector given in the
+<Emphasis>sector number</Emphasis> field and places them in <Emphasis>virtual</Emphasis> memory at
+address <Literal remap="tt">0x20000000</Literal>.  If the reading completes successfully,
+SRM performs a jump to address <Literal remap="tt">0x20000000</Literal>.
+</Para>
+
+</Sect2>
+
+</Sect1>
+
+<Sect1 id="SRM-DeviceNaming">
+<Title>SRM Device Naming</Title>
+<Sect2>
+<Title>The First Two Letter</Title>
+<Para>The following is based on the example device dkb1.2.3.4.5 taken from a Digital Server 3300 (Whitebox version of
+an AS800).
+</Para>
+<Para>
+Two letter port or class driver designator:
+<!-- <variablelist>
+<varlistentry><term>DR:</term><listitem><para>RAID set device</Para></ListItem></varlistentry>
+<varlistentry><term>DV:</term><ListItem><Para>Floppy Drive</Para></ListItem></varlistentry>
+<ListItem><Para>         EW:     Ethernet port (TULIP, DEC 21040) </Para></ListItem>
+<ListItem><Para>         EI:     Ethernet port (Intel 82557 or 82559) </Para></ListItem> 
+<ListItem><Para>         PK:     SCSI port (controller) </Para></ListItem>
+<ListItem><Para>         DK:     SCSI disk </Para></ListItem>
+<ListItem><Para>         MK:     SCSI tape </Para></ListItem>
+<ListItem><Para>         PU:     DSSI port </Para></ListItem>
+<ListItem><Para>         DU:     DSSI disk </Para></ListItem>
+<ListItem><Para>         MU:     DSSI tape </Para></ListItem>
+<ListItem><Para>         JK:     SCSI monitor (or robot) </Para></ListItem>
+<ListItem><Para>	 DQ:	 (E)IDE Device (disk or CD-ROM)</Para></ListItem>
+</ItemizedList>
+</variablelist> -->
+<ItemizedList>
+<ListItem><Para>         DR:     RAID set device </Para></ListItem>
+<ListItem><Para>         DV:     Floppy Drive </Para></ListItem>
+<ListItem><Para>         EW:     Ethernet port (TULIP, DEC 21040) </Para></ListItem>
+<ListItem><Para>         EI:     Ethernet port (Intel 82557 or 82559) </Para></ListItem> 
+<ListItem><Para>         PK:     SCSI port (controller) </Para></ListItem>
+<ListItem><Para>         DK:     SCSI disk </Para></ListItem>
+<ListItem><Para>         MK:     SCSI tape </Para></ListItem>
+<ListItem><Para>         PU:     DSSI port </Para></ListItem>
+<ListItem><Para>         DU:     DSSI disk </Para></ListItem>
+<ListItem><Para>         MU:     DSSI tape </Para></ListItem>
+<ListItem><Para>         JK:     SCSI monitor (or robot) </Para></ListItem>
+<ListItem><Para>	 DQ:	 (E)IDE Device (disk or CD-ROM)</Para></ListItem>
+</ItemizedList>
+</Para>
+</Sect2>
+<Sect2>
+<Title>The Rest Of The Device Name</Title>
+<Para>
+
+<ItemizedList>
+<ListItem><Para>
+ b->adapter ID (one letter adapter designator)</Para></ListItem>
+
+<ListItem><Para>
+ 1->Device number (SCSI unit numbers are forced to 100x Node ID)</Para></ListItem>
+
+<ListItem><Para>
+ 2->Bus Node ID</Para></ListItem>
+
+<ListItem><Para>
+ 3->Channel Number</Para></ListItem>
+
+<ListItem><Para>
+ 4->Channel Number (used for multi-channel devices)</Para></ListItem>
+
+<ListItem><Para>
+ 5->Logical Slot number
+
+  <ItemizedList>
+      <ListItem><Para>EISA: they correspond to the physical slot numbers (1-3)</Para></ListItem>
+      <ListItem><Para>PCI:</Para>
+      <ItemizedList>
+         <ListItem><Para>slot 5= SCSI controller on system backplane (DS3300)</Para></ListItem>
+         <ListItem><Para>slot 6= On board VGA (DS3300)</Para></ListItem>
+         <ListItem><Para>slot 7= PCI to EISA bridge chip (DS3300)</Para></ListItem>
+         <ListItem><Para>slots 11 - 14 = Correspond to Physical PCI option slots:
+                 PCI11, PCI12, PCI13 and PCI14 (64bit) (DS3300)</Para></ListItem>
+      </ItemizedList>
+      </ListItem>
+  </ItemizedList>
+</Para>
+</ListItem>
+<ListItem><Para>
+ 6->Hose number: 0 PCI_0 (32bit PCI); 1 EISA (DS3300)</Para></ListItem>
+
+</ItemizedList>
+</Para>
+</Sect2>
+</Sect1>
+
+
+<Sect1 id="SRM-rawloader">
+<Title>The Raw Loader</Title>
+
+<Para>
+The sources for this loader can be found in directory
+<filename>arch/alpha/boot</filename> of the Linux kernel source
+distribution.  It loads the Linux kernel by reading
+<varname>START&lowbar;SIZE</varname> bytes starting at disk offset
+<varname>BOOT&lowbar;SIZE</varname><Literal remap="tt">+512</Literal>
+(also in bytes).  The constants
+<varname>START&lowbar;SIZE</varname> and <varname>BOOT&lowbar;SIZE</varname>
+are defined in
+<filename>linux/include/asm-alpha/system.h</filename>. 
+<varname>START&lowbar;SIZE</varname>
+must be at least as big as the kernel image (i.e., the size of the
+<Literal remap="tt">.text</Literal>, <Literal remap="tt">.data</Literal>, and <Literal remap="tt">.bss</Literal> segments).  Similarly,
+<varname>BOOT&lowbar;SIZE</varname> must be at least as big as the image of the
+raw bootstrap loader.  Both constants should be an integer multiple of the
+sector size, which is 512 bytes.  The default values are currently 2MB
+for <varname>START&lowbar;SIZE</varname> and 16KB for 
+<varname>BOOT&lowbar;SIZE</varname>.  Note
+that if you want to boot from a 1.44MB floppy disk, you have to reduce
+<varname>START&lowbar;SIZE</varname> to 1400KB and make sure that the kernel you
+want to boot is no bigger than that.
+</Para>
+
+<Para>
+To build a raw loader, simply type <command>make rawboot</command> in the top
+directory of your linux source tree (typically
+<filename>/usr/src/linux</filename>).  This should produce the following files 
+in <filename>arch/alpha/boot</filename>:
+</Para>
+
+<Para>
+<VariableList>
+
+<VarListEntry>
+<Term><filename>tools/lxboot</filename>:</Term>
+<ListItem>
+<Para>
+The first
+sector on the disk.  It contains the offset and size of
+the next file in the format described above.
+</Para>
+</Listitem>
+</VarListEntry>
+<VarListEntry>
+<Term><filename>tools/bootlx</filename>:</Term>
+<ListItem>
+<Para>
+The raw boot loader that
+will load the file below.
+</Para>
+</Listitem>
+</VarListEntry>
+<VarListEntry>
+<Term><filename>vmlinux.nh</filename>:</Term>
+<ListItem>
+<Para>
+The raw kernel image consisting of
+the <Literal remap="tt">.text</Literal>, <Literal remap="tt">.data</Literal>, and <Literal remap="tt">.bss</Literal> segments of the
+object file in <Literal remap="tt">/usr/src/linux/vmlinux</Literal>.  The
+extension <Literal remap="tt">.nh</Literal> indicates that this file has no object-file
+header.
+</Para>
+</Listitem>
+</VarListEntry>
+</VariableList>
+</Para>
+
+<Para>
+The concatenation of these three files should be written to the
+disk from which you want to boot.  For example, to boot from a floppy,
+insert an empty floppy disk in, say, <filename>/dev/fd0</filename> and then type:
+
+<Screen>
+# cat tools/lxboot tools/bootlx vmlinux &#62;/dev/fd0
+</Screen>
+
+</Para>
+
+<Para>
+You can then shutdown the system and boot from the floppy by
+issuing the command <command>boot dva0</command>.
+</Para>
+
+</Sect1>
+
+<Sect1 id="SRM-aboot">
+<Title>The aboot Loader</Title>
+
+<Para>
+When using the SRM firmware, <Literal remap="tt">aboot</Literal> is the preferred way of
+booting Linux.  It supports:
+</Para>
+
+<Para>
+
+<ItemizedList>
+<ListItem>
+
+<Para>
+ direct booting from various filesystems (<Literal remap="tt">ext2</Literal>, <Literal remap="tt">ISO9660</Literal>, and
+<Literal remap="tt">UFS</Literal>, the <productname>HP Tru64</productname> filesystem)
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+ listing directories and following symbolic links on ext2 (version 0.6 and later)
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+ booting of executable object files (both ELF and ECOFF)
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+ booting compressed kernels
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+ network booting (using bootp)
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+ partition tables in <productname>HP Tru64</productname> format (which is
+compatible with BSD Unix partition tables)
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+ interactive booting and default configurations for
+SRM consoles that cannot pass long option strings
+</Para>
+</ListItem>
+
+<ListItem>
+
+<Para>
+ load initrd images to load modules at boot time (0.7 and later)
+</Para>
+</ListItem>
+
+</ItemizedList>
+
+</Para>
+
+<Sect2>
+<Title>Getting and Building aboot</Title>
+
+<Para>
+The latest sources for <Literal remap="tt">aboot</Literal> are available from <ULink
+URL="http://www.sf.net/projects/aboot"
+>Sourceforge</ULink>. They can
+also be obtained via anonymous CVS from www.sf.net, to get the latest version from CVS use these commands:
+<Screen>
+bash# cvs -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/aboot login 
+bash# cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/aboot co aboot
+</Screen>
+(Note there is no password for the CVS login, just press enter)
+</Para>
+
+<Para>
+The description in this manual applies to <Literal remap="tt">aboot</Literal> version 0.6
+or newer. Please note that many distributions ship aboot with them so
+downloading aboot from this directory is probably not neccesary.
+</Para>
+
+<Para>
+ Once you downloaded and extracted the latest tar file, take a
+look at the <filename>README</filename> and <filename>INSTALL</filename> files
+for installation hints.  In particular, be sure to adjust the variables in
+<filename>Makefile</filename> and in <filename>include/config.h</filename>
+to match your
+environment.  Normally, you won't need to change anything when
+building under Linux, but it is always a good idea to double check.
+If you're satisfied with the configuration, simply type <command>make</command>
+to build it (if you're not building under Linux, be advised that
+<Literal remap="tt">aboot</Literal> requires GNU <Literal remap="tt">make</Literal>).
+</Para>
+
+<Para>
+After running <Literal remap="tt">make</Literal>, the <filename>aboot</filename>
+directory should contain the following files:
+</Para>
+
+<Para>
+<VariableList>
+
+<VarListEntry>
+<Term><filename>aboot</filename></Term>
+<ListItem>
+<Para>
+This is the actual <Literal remap="tt">aboot</Literal> executable (either an
+ECOFF or ELF object file).
+</Para>
+</Listitem>
+</VarListEntry>
+<VarListEntry>
+<Term><filename>bootlx</filename></Term>
+<ListItem>
+<Para>
+Same as above, but it contains only the text, data
+and bss segments &dash; that is, this file is not an object file.
+</Para>
+</Listitem>
+</VarListEntry>
+<VarListEntry>
+<Term><filename>sdisklabel/swriteboot</filename></Term>
+<ListItem>
+<Para>
+Utility to install <Literal remap="tt">aboot</Literal> on a
+hard disk.
+</Para>
+</Listitem>
+</VarListEntry>
+<VarListEntry>
+<Term><filename>tools/e2writeboot</filename></Term>
+<ListItem>
+<Para>
+Utility to install <Literal remap="tt">aboot</Literal> on an ext2
+filesystem (usually used for floppies only).
+</Para>
+</Listitem>
+</VarListEntry>
+<VarListEntry>
+<Term><filename>tools/isomarkboot</filename></Term>
+<ListItem>
+<Para>
+Utility to install <Literal remap="tt">aboot</Literal> on a iso9660
+filesystem (used by CD-ROM distributors).
+</Para>
+</Listitem>
+</VarListEntry>
+<VarListEntry>
+<Term><filename>tools/abootconf</filename></Term>
+<ListItem>
+<Para>
+Utility to configure an installed <Literal remap="tt">aboot</Literal>.
+</Para>
+</Listitem>
+</VarListEntry>
+</VariableList>
+</Para>
+
+</Sect2>
+
+<Sect2>
+<Title>Floppy Installation</Title>
+
+<Para>
+ The bootloader can be installed on a floppy using the
+<command>e2writeboot</command> command (note: this can't be done on a Jensen 
+since
+its firmware does <Emphasis>not</Emphasis> support booting from floppy).  This command
+requires that the disk is not overly fragmented as it needs to find
+enough contiguous file blocks to store the entire <Literal remap="tt">aboot</Literal> image
+(currently about 90KB).  If <command>e2writeboot</command> fails because of this,
+reformat the floppy and try again (e.g., with <command>fdformat</command>(1)).
+For
+example, the following steps install <Literal remap="tt">aboot</Literal> on floppy disk
+assuming the floppy is in drive <filename>/dev/fd0</filename>:
+
+<Screen>
+# fdformat /dev/fd0
+# mke2fs /dev/fd0
+# e2writeboot /dev/fd0 bootlx
+</Screen>
+
+</Para>
+
+</Sect2>
+
+<Sect2>
+<Title>Harddisk Installation</Title>
+
+<Para>
+Since the <command>e2writeboot</command> command may fail on highly fragmented
+disks and since reformatting a harddisk is not without pain, it is
+generally safer to install <Literal remap="tt">aboot</Literal> on a harddisk using the
+<command>swriteboot</command> command.
+<Literal remap="tt">swriteboot</Literal> requires that the first few
+sectors are reserved for booting purposes.  We suggest that the disk
+be partitioned such that the first partition starts at an offset of
+2048 sectors.  This leaves 1MB of space for storing <Literal remap="tt">aboot</Literal>.  On
+a properly partitioned disk, it is then possible to install <Literal remap="tt">aboot</Literal>
+as follows (assuming the disk is <filename>/dev/sda</filename>):
+
+<Screen>
+# swriteboot /dev/sda bootlx
+</Screen>
+
+</Para>
+
+<Para>
+On systems where partition <Literal remap="tt">c</Literal> in the entire disk it will be
+necessary to 'force' the write of aboot. In this case use the <Literal remap="tt">-f</Literal>
+flag followed by the partition number (in the case of partition <Literal remap="tt">c</Literal>
+this is 3):
+
+<Screen>
+# swriteboot /dev/sda bootlx -f3
+</Screen>
+
+</Para>
+
+<Para>
+On a Jensen, you will want to leave some more space, since you need to
+write a kernel to this place, too---2MB should be sufficient when
+using compressed kernels.  Use <Literal remap="tt">swriteboot</Literal> as described in Section
+<XRef LinkEnd="booting"> to write <filename>bootlx</filename> together with
+the Linux kernel.
+</Para>
+
+</Sect2>
+
+<Sect2>
+<Title>CD-ROM Installation</Title>
+
+<Para>
+ To make a CD-ROM bootable by SRM, simply build <Literal remap="tt">aboot</Literal> as
+described above.  Then, make sure that the <filename>bootlx</filename> file is
+present on the iso9660 filesystem (e.g., copy <filename>bootlx</filename> to
+the directory that is the filesystem master, then run <command>mkisofs</command>
+on that directory).  After that, all that remains to be done is to mark the
+filesystem as SRM bootable.  This is achieved with a command of the
+form:
+
+<Screen>
+# isomarkboot filesystem bootlx
+</Screen>
+
+</Para>
+
+<Para>
+The command above assumes that <filename>filesystem</filename> is a file
+containing the iso9660 filesystem and that <filename>bootlx</filename> has been
+copied into the
+root directory of that filesystem.  That's it!
+</Para>
+
+</Sect2>
+
+<Sect2 id="Building-Linux">
+<Title>Building the Linux Kernel</Title>
+
+<Para>
+A bootable Linux kernel can be built with the following steps.
+During the <command>make config</command>, be sure to answer "yes" to the
+question
+whether you want to boot the kernel via SRM (for certain platforms
+this is automatically selected).  Note that if you build a generic
+kernel (by selecting "Generic" as the alpha system type), the kernel
+is able to guess whether it is running under SRM or not.
+
+<Screen>
+# cd /usr/src/linux
+# make config
+# make dep
+# make boot
+# make modules (if applicable)
+# make modules_install (if applicable)
+</Screen>
+
+</Para>
+
+<Para>
+The last command will build the file
+<filename>arch/alpha/boot/vmlinux.gz</filename> which can then be copied to the
+disk from which you want to boot from.  In our floppy disk example
+above, this would entail:
+
+<Screen>
+# mount /dev/fd0 /mnt
+# cp arch/alpha/boot/vmlinux.gz /mnt
+# umount /mnt
+</Screen>
+
+</Para>
+
+</Sect2>
+
+<Sect2 id="booting">
+<Title>Booting Linux</Title>
+
+<Para>
+ With the SRM firmware and <Literal remap="tt">aboot</Literal> installed, Linux is generally
+booted with a command of the form:
+
+<Screen>
+<Literal remap="tt">boot</Literal> <Emphasis remap="it">devicename</Emphasis> <Literal remap="tt">-fi</Literal> <Emphasis remap="it">filename</Emphasis>
+<Literal remap="tt">-fl</Literal> <Emphasis remap="it">flags</Emphasis>
+</Screen>
+
+</Para>
+
+<Para>
+The <Emphasis remap="it">filename</Emphasis> and <Emphasis remap="it">flags</Emphasis> arguments are optional.  If
+they are not specified, SRM uses the default values stored in
+environment variables <varname>BOOTDEF&lowbar;DEV</varname>,
+<varname>BOOT&lowbar;OSFILE</varname> and 
+<varname>BOOT&lowbar;OSFLAGS</varname>.  The
+syntax and meaning of these two arguments is described in more detail
+below. To list the current values of these variables type 
+<command>show boot*</command> at the SRM command prompt. This will also show a
+<varname>boot&lowbar;dev</varname> variable (among others), this variable is
+read only
+and needs to be changed via the <varname>bootdef&lowbar;dev</varname> variable.
+</Para>
+
+<Sect3 id="device-naming">
+<Title>Device Naming</Title>
+
+<Para>
+This corresponds to the device from which SRM will attempt to boot. Examples include:
+</Para>
+
+<Para>
+<VariableList>
+
+<VarListEntry>
+<Term>dva0</Term>
+<ListItem>
+<Para>
+- First floppy drive, <filename>/dev/fd0</filename> under Linux
+</Para>
+</Listitem>
+</VarListEntry>
+<VarListEntry>
+<Term>dqa0</Term>
+<ListItem>
+<Para>
+- Primary IDE CD-ROM or hard disk as Master, <filename>/dev/hda</filename>
+  under Linux
+</Para>
+</Listitem>
+</VarListEntry>
+<VarListEntry>
+<Term>dqa1</Term>
+<ListItem>
+<Para>
+- Primary IDE CD-ROM or hard disk as Slave, <filename>/dev/hdb</filename>
+  under Linux
+</Para>
+</Listitem>
+</VarListEntry>
+<VarListEntry>
+<Term>dka0</Term>
+<ListItem>
+<Para>
+- SCSI disk on first bus, Device 0, <filename>/dev/sda</filename> under Linux
+</Para>
+</Listitem>
+</VarListEntry>
+<VarListEntry>
+<Term>ewa0</Term>
+<ListItem>
+<Para>
+- First Ethernet Device, <filename>/dev/eth0</filename> under Linux
+</Para>
+</Listitem>
+</VarListEntry>
+</VariableList>
+</Para>
+
+<Para>
+For example to boot from the disk at SCSI id 6, you would enter:
+
+<Screen>
+&#62;&#62;&#62; boot dka600
+</Screen>
+
+</Para>
+
+<Para>
+To list the devices currently installed in the system type
+<command>show dev</command> at the SRM command line.  In contrast to Linux
+device naming, the
+partition number on a disk device is <Emphasis>not</Emphasis> given as part of the
+device name (you may see extra numbers after the device names when
+running <command>show dev</command> - these correspond to things like PCI bus and
+device numbers and are not useful to the user).  Remember, as
+mentioned in <XRef LinkEnd="how-srm-boots">, that SRM knows <Emphasis>nothing</Emphasis>
+about partitions or disklabels - it merely reads a boot block and
+secondary bootstrap from sectors on a disk.  Therefore, the partition
+number is given as part of the boot filename.
+</Para>
+
+</Sect3>
+
+<Sect3>
+<Title>Boot Filename</Title>
+
+<Para>
+The filename argument takes the form:
+<QUOTE
+>&lsqb;<Emphasis>n</Emphasis>/&rsqb;<Emphasis>filename</Emphasis></QUOTE
+>
+</Para>
+
+<Para>
+<Emphasis>n</Emphasis> is a single digit in the range 1..8 that gives the partition
+number from which to boot from.  <filename>filename</filename> is the path of the file 
+you want boot.  For example to boot a kernel named
+<filename>vmlinux.gz</filename> from the second partition of SCSI
+device 6, you would enter:
+
+<Screen>
+&#62;&#62;&#62; boot dka600 -file 2/vmlinux.gz
+</Screen>
+
+</Para>
+
+<Para>
+Or to boot from floppy drive 0, you'd enter:
+
+<Screen>
+&#62;&#62;&#62; boot dva0 -file vmlinux.gz
+</Screen>
+
+</Para>
+
+<Para>
+If a disk has no partition table, <Literal remap="tt">aboot</Literal> pretends the disk
+contains one <Literal remap="tt">ext2</Literal> partition starting at the first diskblock.
+This allows booting from floppy disks.
+</Para>
+
+<Para>
+As a special case, partition number 0 is used to request booting
+from a disk that does not (yet) contain a file system.  When
+specifying "partition" number 0, <Literal remap="tt">aboot</Literal> assumes that the Linux
+kernel is stored right behind the <Literal remap="tt">aboot</Literal> image.  Such a layout
+can be achieved with the <command>swriteboot</command> command.  For example, to
+setup a filesystem-less boot from <filename>/dev/sda</filename>, one could use
+the command:
+
+<Screen>
+# swriteboot /dev/sda bootlx vmlinux.gz
+</Screen>
+
+</Para>
+
+<Para>
+Booting a system in this way is not normally necessary.  The
+reason this feature exists is to make it possible to get Linux
+installed on a systems that can't boot from a floppy disk (e.g., the
+Jensen).
+</Para>
+
+</Sect3>
+
+<Sect3>
+<Title>Boot Flags</Title>
+
+<Para>
+A number of bootflags can be specified.  The syntax is:
+
+<Screen>
+-flags "options..."
+</Screen>
+
+</Para>
+
+<Para>
+Where "options..." is any combination the following options (separated
+by blanks).  There are many more bootoptions, depending on what
+drivers your kernel has installed.  The options listed below are
+therefore just examples to illustrate the general idea:
+</Para>
+
+<Para>
+<VariableList>
+
+<VarListEntry>
+<Term>load&lowbar;ramdisk=1</Term>
+<ListItem>
+<Para>
+Copy root file system from a (floppy) disk to the RAM disk
+before starting the system.  The RAM disk will be used in
+lieu of the root device.  This is useful to bootstrap Linux
+on a system with only one floppy drive.
+</Para>
+</Listitem>
+</VarListEntry>
+<VarListEntry>
+<Term>floppy=<Emphasis>str</Emphasis></Term>
+<ListItem>
+<Para>
+Sets floppy configuration to <Emphasis>str</Emphasis>.
+</Para>
+</Listitem>
+</VarListEntry>
+<VarListEntry>
+<Term>root=<Emphasis>dev</Emphasis></Term>
+<ListItem>
+<Para>
+Select device <Emphasis>dev</Emphasis> as the root-file
+system. The device can be specified as a major/minor hex number (e.g.,
+0x802 for <filename>/dev/sda2</filename>) or one of a few canonical names (e.g.,
+<filename>/dev/fd0</filename>, <filename>/dev/sda2</filename>).
+</Para>
+</Listitem>
+</VarListEntry>
+<VarListEntry>
+<Term>single</Term>
+<ListItem>
+<Para>
+Boot system in single user mode.
+</Para>
+</Listitem>
+</VarListEntry>
+<VarListEntry>
+<Term>kgdb</Term>
+<ListItem>
+<Para>
+Enable kernel-gdb (works only if <varname>CONFIG&lowbar;KGDB</varname> is
+enabled; a second Alpha system needs to be connected over the serial
+port in order to make this work)
+</Para>
+</Listitem>
+</VarListEntry>
+</VariableList>
+</Para>
+
+<Para>
+Some SRM implementations (e.g., the one for the Jensen) are
+handicapped and allow only short option strings (e.g., at most 8
+characters).  In such a case, <Literal remap="tt">aboot</Literal> can be booted with the
+single-character boot flag "i".  With this flag, <Literal remap="tt">aboot</Literal> will
+enter interactive mode
+</Para>
+
+</Sect3>
+
+<Sect3>
+<Title>Using aboot interactively</Title>
+
+<Para>
+As of version 0.6, <Literal remap="tt">aboot</Literal> supports a simple command-oriented
+interactive mode.  Note that this is <Emphasis>different</Emphasis> from the prompt
+which previous versions issued when booted with the "i" flag, or after
+failing to load a kernel.  You can get a summary of the available
+commands by typing "h" or "?" at the prompt:
+
+<Screen>
+&#62;&#62;&#62; boot dka0 -fl i
+aboot&#62; ?
+ h, ?                   Display this message
+ q                      Halt the system and return to SRM
+ p 1-8                  Look in partition &#60;num&#62; for configuration/kernel
+ l                      List pre-configured kernels
+ d &#60;dir&#62;                List directory &#60;dir&#62; in current filesystem
+ b &#60;file&#62; &#60;args&#62;        Boot kernel in &#60;file&#62; (- for raw boot)
+                        with arguments &#60;args&#62;
+ 0-9                    Boot pre-configuration 0-9 (list with 'l')
+aboot&#62; b 3/vmlinux.gz root=/dev/sda3 single
+</Screen>
+
+</Para>
+
+</Sect3>
+
+<Sect3>
+<Title>The <filename>aboot.conf</filename> configuration file</Title>
+
+<Para>
+Since booting in that manner quickly becomes tedious, <Literal remap="tt">aboot</Literal>
+allows to define short-hands for frequently used command lines.  In
+particular, a single digit option (0-9) requests that <Literal remap="tt">aboot</Literal> uses
+the corresponding option string stored in file
+<filename>etc/aboot.conf</filename>.  A sample <filename>aboot.conf</filename> is shown below:
+
+<Screen>
+#
+# aboot default configurations
+#
+0:3/vmlinux.gz root=/dev/sda3
+1:3/vmlinux.gz root=/dev/sda3 single
+2:3/vmlinux.new.gz root=/dev/sda3
+3:3/vmlinux root=/dev/sda3
+8:- root=/dev/sda3            # fs-less boot of raw kernel
+9:0/vmlinux.gz root=/dev/sda3 # fs-less boot of (compressed) ECOFF kernel
+-
+</Screen>
+
+</Para>
+
+<Para>
+With this configuration file, the command
+
+<Screen>
+&#62;&#62;&#62; boot dka0 -fl 1
+</Screen>
+
+corresponds exactly to the boot command shown above.
+</Para>
+
+<Para>
+Finally, at the <Literal remap="tt">aboot</Literal> prompt, it is possible to enter one of the
+single character flags ("0"-"9") to get the same effect as if that
+flag had been specified in the boot command line.  As noted in the
+help text cited above, you can also list the available default
+configurations with the "l" command.
+</Para>
+
+<Sect4>
+<Title>Selecting the Partition of <filename>etc/aboot.conf</filename></Title>
+
+<Para>
+When installed on a harddisk, <Literal remap="tt">aboot</Literal> needs to know what
+partition to search for the <filename>/etc/aboot.conf</filename> file.  A newly
+compiled <Literal remap="tt">aboot</Literal> will search the <Emphasis>second</Emphasis> partition (e.g.,
+<filename>/dev/sda2</filename>).  Since it would be inconvenient to have to
+recompile <Literal remap="tt">aboot</Literal> just to change the partition number,
+<Literal remap="tt">abootconf</Literal> allows to directly modify an installed <Literal remap="tt">aboot</Literal>.
+Specifically, if you want to change <Literal remap="tt">aboot</Literal> to use the <Emphasis>third</Emphasis>
+partition on disk <filename>/dev/sda</filename>, you'd use the command:
+
+<Screen>
+# abootconf /dev/sda 3
+</Screen>
+</Para>
+
+<Para>
+You can verify the current setting by simply omitting the partition
+number.  That is: <command>abootconf /dev/sda</command> will print the currently
+selected partition number.  Note that <Literal remap="tt">aboot</Literal> does have to be
+installed already for this command to succeed.  As of version 0.6,
+<Literal remap="tt">swriteboot</Literal> it will preserve the existing configuration when
+installing a new <Literal remap="tt">aboot</Literal> on a hard disk.
+</Para>
+
+
+<Para>
+Since <Literal remap="tt">aboot</Literal> version 0.5, it is also possible to select the
+<filename>aboot.conf</filename> partition via the boot command line. This can
+be
+done with a command line of the form <Emphasis remap="it">a</Emphasis><Literal remap="tt">:</Literal><Emphasis remap="it">b</Emphasis>
+where <Emphasis remap="it">a</Emphasis>
+is the partition that holds <filename>etc/aboot.conf</filename> and <Emphasis remap="it">b</Emphasis> is a
+single-letter option as described above (<Literal remap="tt">0</Literal>-<Literal remap="tt">9</Literal>, <Literal remap="tt">i</Literal>, or
+<Literal remap="tt">h</Literal>). For example, if you type 
+<command>boot -fl "3:h" dka100</command> the
+system boots from SCSI ID 1, loads <filename>etc/aboot.conf</filename> from the
+third partition, prints its contents on the screen and waits for you
+to enter the boot options.
+</Para>
+
+</Sect4>
+
+</Sect3>
+
+</Sect2>
+
+<Sect2 id="DHCP-and-BOOTPD-server-setup">
+<Title>Setting up a BOOTP capable server using DHCP</Title>
+
+<Para>
+The following configuration assumes that the server is running RH-6.2. 
+Prerequisites packages are,
+<ItemizedList>
+<Listitem>
+<Para>
+dhcp-2.0.5 
+</Para>
+</Listitem>
+<Listitem>
+<Para>
+tftp-server-0.16.5
+</Para>
+</Listitem>
+</Itemizedlist>
+
+</Para>
+
+<Sect3>
+<Title>DHCP & BOOTP configuation</Title>
+<Para>
+Once those packages are installed there are a few setup issues to take care of.
+</Para>
+
+<Para>
+Create the default directory to which files will be pulled from using tftp.
+</Para>
+<Screen>
+# mkdir /tftpboot
+</Screen>
+
+<Para>
+Create the <filename>dhcp.leases</filename> file which is not create per default
+(though it should be) when
+you install the dhcp package so the dhcp server may start. 
+</Para>
+
+<Screen>
+# mkdir -p /var/state/dhcp
+# touch /var/state/dhcp/dhcpd.leases
+</Screen>
+
+<Para>
+Configure the inetd to accept the tftp service. Edit your 
+<filename>/etc/inetd.conf</filename> file and locate
+the following line. Then uncomment it and save the file.
+</Para>
+
+<Screen>
+#tftp	dgram	udp	wait	root	/usr/sbin/tcpd	in.tftpd
+</Screen>
+
+<Para>
+Create the <filename>/etc/dhcp.conf</filename> configuation file. An example
+config is provided below with the directives which allow BOOTP. 
+</Para>
+
+<Screen>
+subnet 192.168.1.0 netmask 255.255.255.0 {
+       option routers                        192.168.1.1;
+       option subnet-mask                  255.255.255.0;
+       option nis-domain                "alphalinux.org";
+       option domain-name	        "alphalinux.org";
+       option domain-name-servers            192.168.1.2;
+       range                 192.168.1.3   192.168.1.254;
+       range dynamic-bootp   192.168.1.3   192.168.1.254;
+       default-lease-time                          21600;
+       max-lease-time                              43200;
+       allow bootp;
+       allow booting;
+       filename "/tftpboot/vmlinux.bootp";	
+}                                 
+</Screen>
+
+<Sect4>
+<Title>Examination of <filename>/etc/dhcp.conf</filename></Title>
+<Para>
+There are four directives that you should be concerned with.
+</Para>
+
+<ItemizedList>
+<Listitem> 
+<Para><Literal remap="tt">range dynamic-bootp 192.168.1.3 192.168.1.254;</Literal>
+which defines the range of ip's available for bootp.
+</Para></Listitem>
+<Listitem><Para> 
+<Literal remap="tt">allow bootp;</Literal>
+which tells the dhcp server to allow the bootp protocol..
+</Para></Listitem> 
+<Listitem><Para> 
+<Literal remap="tt">allow booting;</Literal>
+which tells the dhcp server to allow the transfer of the file specified 
+either in the the "filename" directive or passed in the "-file" flag in SRM. 
+</Para></Listitem> 
+<Listitem><Para> 
+<Literal remap="tt">filename "<filename>/tftpboot/vmlinux.bootp</filename>";</Literal>
+ which is the default file which is transferred and executed when no filename 
+specified in SRM as an argument. 
+</Para></Listitem> 
+</ItemizedList>
+
+
+
+<Para>Lastly, Restart the inetd daemon so that the changes we made can take effect</Para>
+
+<Screen># service inet restart</Screen>
+
+<Para>You should now have a DHCP server that is capable of BOOTP.</Para>
+</Sect4>
+</Sect3>
+
+<Sect3>
+<Title id="bootpd-setup">bootpd configuration</Title>
+<Para>
+The bootpd is the older way of making a bootp server and for the most part is not used anymore
+in lieu of more modern DHCP servers that are capable of handling the protocol with minimal configuration
+and more flexibility. This style of setup does not allow just any client to be granted a BOOTP request. 
+Instead you must specify the ip address and MAC address of the allowed clients. Naturally this could get
+quite tedious if you where say administrating more than a few machines. 
+</Para>
+
+<Para>
+bootpd rpms can be found on older versions of RedHat's distributions like version 5.2 and below. Note:
+the rpm itself is named bootp though the package does contain the bootpd filename. It is available
+for download at your favorite RedHat <ulink url="ftp://ftp.freesoftware.com/.1/linux/redhat/old-releases/redhat-5.2/alpha/RedHat/RPMS/">mirror</ulink>.
+The bootp package requires the tftp-server just as before and the location to where the files are grabbed from is the same.  
+</Para>
+
+<Para>
+Once installed you must configure your inetd service to talk to the bootpd daemon. Uncomment the following line in your <filename>/etc/inetd.conf</filename>.
+</Para>
+<Screen>
+#bootps dgram   udp     wait    root    /usr/sbin/tcpd  bootpd
+</Screen>
+<Para>
+Then restart the inetd.
+</Para>
+<Screen>
+# service inet restart
+</Screen>
+
+<Para>
+Configuring the <filename>/etc/bootptab</filename> file.  The 
+<filename>bootptab</filename> file
+has one entry describing each client that is allowed to boot from
+the server.  For example, if you want to boot the machine
+<Literal remap="tt">voodoo.alphalinux.org</Literal>, then an entry of the following form would
+be needed:
+
+<Screen>
+voodoo.alphalinux.org:\
+	:hd=/tftpboot/:bf=vmlinux.bootp:\
+	:ht=ethernet:ha=08012B1C51F8:hn:vm=rfc1048:\
+	:ip=192.12.69.254:bs=auto:
+</Screen>
+
+</Para>
+
+<Para>
+This entry assumes that the machine's Ethernet address is
+<Literal remap="tt">08012B1C51F8</Literal> and that its IP address is 192.12.69.254.  The
+Ethernet address can be found with the <command>show device</command> command
+of the SRM console or, if Linux is running, with the <command>ifconfig</command>
+command.
+The entry also defines that if the client does not specify otherwise,
+the file that will be booted is <filename>vmlinux.bootp</filename> in directory
+<filename>/tftpboot</filename>.  For more information on configuring <Literal remap="tt">bootpd</Literal>,
+please refer to its man page.
+</Para>
+
+</Sect3>
+
+
+</Sect2> 
+
+
+<Sect2 id="Network-Booting">
+<Title>Booting Over the Network</Title>
+
+<Para>
+Three steps are necessary before Linux can be booted via
+a network.  First you need an Ethernet adapter that is supported by SRM.
+Most version of SRM support the DE500 series of cards, with newer
+versions (5.6 and later) also supporting the Intel EtherExpress/Pro series
+of cards.
+Second, you need to set the SRM environment variables to
+enable booting via the bootp protocol and third you need to setup
+another machine as the your boot server.  Enabling bootp in SRM is
+usually done by setting the ewa0&lowbar;protocol (DE500 cards) or eia0&lowbar;protocol (Intel cards) variable to bootp.
+
+<Screen>
+&#62;&#62;&#62; set ewa0_protocol bootp
+</Screen>
+</Para>
+
+<Para>
+Also check to see that your ethernet device has a link light to whatever hub or switch it is connected to. If you
+do not see a link light try forcing the negotiation of the ethernet device. For example:
+</Para>
+
+<Screen>
+>>> set ewa0_mode FastFD
+</Screen>
+
+<Para> Would set the DE500 ethernet card to fast full duplex operation. To see a list of the available modes</Para>
+
+<Screen>
+>>> set ewa0_mode 
+</Screen>
+
+<Para>
+Netboot using the aboot sources is currently broken though for the curious the steps needed are further below. Instead use the directions for netbooting using the kernel sources. 
+</Para>
+
+<Sect3>
+<Title>Netboot using the kernel sources</Title>
+
+<Para>
+<OrderedList>
+<Listitem>
+<Para>
+Make sure the kernel you want to boot has already been built 
+</Para>
+</Listitem>
+<Listitem>
+<Para>
+Execute the following while in the linux source dir: 
+  <ItemizedList>
+  <Listitem>
+  <Para>
+    <Literal><command>make bootimage</command></Literal> 
+  </Para>
+  </Listitem>
+  <Listitem>
+  <Para>
+    <Literal><command>make bootpfile</command></Literal>
+  </Para>
+  </Listitem>
+  </Itemizedlist>
+</Para>
+
+<Para>
+This creates a uncompressed kernel named <filename>bootpfile</filename> located
+in <filename>arch/alpha/boot/</filename>. Note that this kernel is 
+significantly larger than that produced by the aboot sources. 
+</Para>
+</Listitem>
+<Listitem>
+<Para>
+Copy bootpfile to the bootp server's directory. With a default setup the tftp server would look in 
+<filename>/tftpboot</filename> so copy <filename>bootpfile</filename> into
+<filename>/tftpboot</filename>. 
+  
+</Para>
+</Listitem>
+</Orderedlist>
+</Para>
+</Sect3>
+
+
+<Sect3>
+<Title>Netboot using the aboot sources</Title> 
+<Para>
+<OrderedList>
+<Listitem>
+<Para>
+Build aboot with with the command <command>make netboot</command>. 
+</Para>
+</Listitem>
+<Listitem>
+<Para>
+Make sure the kernel that you want to boot has been built already. 
+
+By default, the aboot Makefile uses the kernel in 
+<filename>/usr/src/linux/arch/alpha/boot/vmlinux.gz</filename> (edit the 
+Makefile if you want to use a different path). The result of 
+<command>make netboot</command> is a file called 
+<filename>vmlinux.bootp</filename> 
+    which contains aboot and the Linux kernel, ready for network booting. 
+</Para>
+</Listitem>
+<Listitem>
+<Para>
+
+Copy <filename>vmlinux.bootp</filename> to the bootp server's directory. In the
+example above, you'd copy it into <filename>/tftpboot/vmlinux.bootp</filename>.
+</Para>
+</Listitem>
+</Orderedlist>
+</Para>
+<Para>
+Next, power up the client machine and boot it, specifying the Ethernet adapter as the boot device. Typically, SRM calls the DEC based Ethernet adapter ewa0 and the Intel based adapter
+eia0, so to boot from that device, you'd use the command: 
+<screen>
+      >>> boot ewa0 
+</screen>
+</Para>
+<Para>
+The -fi and -fl options can be used as usual. For example, 
+</Para>
+<Para>
+<screen>
+      >>> boot ewa0 -fi  bootpfile -fl "root=/dev/hda2" 
+</screen>
+</Para>
+<Para>
+In particular, you can ask aboot to prompt for Linux kernel arguments by specifying the option 
+-fl i .  
+</Para>
+</Sect3>
+<Sect3>
+<Title>Updating the SRM console through BOOTP</Title>
+<Para>
+Updating your SRM console over the network through BOOTP is just as easy as booting the Linux kernel
+in the same manner. The hardware prerequisites are the same as netbooting Linux.
+</Para>
+
+<Para>
+First you have to obtain an SRM image that is able to BOOTP over the network. These images normally
+have a .exe extension. For DEC/Compaq/HP Alpha products these images can be found at 
+<ulink url="ftp://ftp.digital.com/pub/Digital/Alpha/firmware/">ftp://ftp.digital.com/pub/Digital/Alpha/firmware/</ulink>; you will need version 5.8 or later. For access you might need to use an proper ftp client. You can also find these files on the Alpha Systems Firmware Update CD-ROM. <ulink url="http://www.api-networks.com">API NetWorks</ulink> did not offer any net bootable SRM image.
+</Para>
+
+<!--
+ftp://ftp.digital.com/pub/Digital/Alpha/firmware/index.html [openvms ask the wizard link]
+or
+ftp://ftp.digital.com/pub/DEC/Alpha/firmware/index.html [alpha site left nav firmware link]
+but I think they are the same location. 
+ftp://ftp.digital.com/pub/Digital/Alpha/firmware/archive/ for old images
+-->
+
+<Para>
+For example say you had a DS20 and wanted to update it's firmware over the network using BOOTP. You would have to,
+<OrderedList>
+<Listitem><Para>Get the correct firmware image for the DS20 that supported BOOTP execution which in this case the filename is 
+<filename>ds20_v5_8.exe</filename> from  <ulink url="ftp://gatekeeper.dec.com/pub/DEC/Alpha/firmware/v5.8/">ftp://gatekeeper.dec.com/pub/DEC/Alpha/firmware/v5.8/</ulink>.</Para>
+</Listitem>
+<Listitem>
+<Para>Copy the file to the <filename>/tftpboot</filename> folder located on the
+BOOTP server.</Para>  <!-- FIXME Folder vs. Directory -->
+</Listitem>
+</OrderedList>
+</Para>
+
+<Para>
+To execute the update from SRM you would do the following:
+</Para>
+<Screen>>>> b ewa0 -fi ds20_v5_8.exe</Screen>  
+<Para>
+SRM would then proceed to upgrade the firmware in the same fashion as if you had done the firmware update from a CD.
+</Para>
+
+</Sect3>
+
+</Sect2>
+
+
+
+<Sect2>
+<Title>Partitioning Disks</Title>
+
+<Sect3>
+<Title>What is a disklabel?</Title>
+
+<Para>
+A disk label is a partition table. Unfortunately, there are several
+formats the partition table can take, depending on the operating
+system.
+</Para>
+
+<Para>
+DOS partition tables are the standard used by Linux and
+Windows. AlphaBIOS systems and every Linux kernel can read DOS
+partition tables. Unfortunately, the SRM console's boot sector format
+overlaps with parts of the DOS partition table on disk, and therefore
+DOS partition tables cannot be used with SRM.
+</Para>
+
+<Para>
+BSD disklabels are used by several variants of Unix, including
+<productname>Tru64</productname>.  SRM's boot block does not conflict with
+the BSD disklabel (in
+fact, the BSD disklabel resides entirely within "reserved" areas of
+the first sector), and Linux can use a BSD disklabel, provided that
+support for BSD disklabels has been compiled into the kernel.
+</Para>
+
+<Para>
+To boot from a disk using SRM, a BSD disklabel is required. If the
+disk is not a boot disk, the BSD disklabel is not required. A BSD
+disklabel can be created using fdisk, the standard Linux disk
+partitioning tool.
+</Para>
+
+</Sect3>
+
+<Sect3>
+<Title>Partitioning the Easy Way: a DOS Disklabel</Title>
+
+<Para>
+The simplest way to partition your disk is to let your Linux installer
+do it for you, for example by using Red Hat's disk druid or fdisk.  On
+Red Hat 6.1, this will produce a valid BSD disklabel, but
+<Emphasis>only</Emphasis> if the disk in question previously contained one.  In
+most cases, this will produce a DOS disklabel.  It will be readable by
+Linux, but you will not be able to boot from it via SRM.  For this
+reason, you will probably want to create a BSD disklabel manually in
+order to boot Linux
+</Para>
+
+</Sect3>
+
+<Sect3>
+<Title>Partitioning with a BSD Disklabel</Title>
+
+<Para>
+
+<OrderedList>
+<ListItem>
+
+<Para>
+Start fdisk on the disk you're configuring
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+Choose to make a BSD disklabel - option 'b' (newer versions of
+fdisk will detect existing BSD disklabels and automatically enter
+disklabel mode)
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+You'll notice some things: Partitions are letters instead of
+numbers, from a-h Partition 'c' covers the whole of the disk. This is
+the convention, don't touch it.  While you can see it, note down the
+disk parameters as you'll use them more often than with the
+DOS-disklabel approach
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+Creating a new partition uses the same procedure as the
+DOS-disklabel approach, except that the partitions are referred to by
+letter instead of number. That is, 'n' to make a new partition
+followed by the partition letter followed by the starting block
+followed by the end block
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+Setting partition type is slightly different, because the
+numbering scheme is different (1 is swap, 8 is ext2).
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+When you are finished, write ('w') and quit ('q') as normal.
+</Para>
+</ListItem>
+
+</OrderedList>
+
+</Para>
+
+<Para>
+There are some important catches that you must be aware of when
+partitioning using a BSD disklabel:
+
+<ItemizedList>
+<ListItem>
+
+<Para>
+Partition 'a' should start about 1M into the disk: don't start
+it at sector 1, try starting at sector 10 (for example). This leaves
+plenty of space for writing the boot block (see below)
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+There is a bug in some versions of fdisk which makes the disk
+look one sector bigger than it actually is.  The listing when you
+create the BSD disklabel is correct.  The last sector of partition 'c'
+is correct.  The default last sector when creating a new partition is
+1 sector too big
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+Always adjust for this extra sector. This bug exists in the
+version of fdisk shipped with Red Hat 6.0. Not making an adjustment
+for this problem almost always leads to "Access beyond end of device"
+errors from the Linux kernel.
+</Para>
+</ListItem>
+
+</ItemizedList>
+
+</Para>
+
+<Para>
+Once you have made a BSD disklabel, continue the installation. After
+installation, you can write a boot block to your disk to make it
+bootable from SRM.
+</Para>
+
+</Sect3>
+
+</Sect2>
+
+</Sect1>
+
+<Sect1 id="SRM-sharingWithDEC">
+<Title>Sharing a Disk With <productname>HP Tru64</productname></Title>
+
+<Para>
+Unfortunately, <productname>HP Tru64</productname> doesn't know anything about Linux, so sharing
+a single disk between the two OSes is not entirely trivial.  However,
+it is not a difficult task if you heed the tips in this section.  The
+section assumes you are using <Literal remap="tt">aboot</Literal> version 0.5 or newer.
+</Para>
+
+<Sect2>
+<Title>Partitioning the disk</Title>
+
+<Para>
+First and foremost: <Emphasis>never</Emphasis> use any of the Linux partitioning
+programs (<Literal remap="tt">minlabel</Literal> or <Literal remap="tt">fdisk</Literal>) on a disk that is also
+used by <productname>HP Tru64</productname>.  The Linux <Literal remap="tt">minlabel</Literal> program uses the same
+partition table format as <productname>HP Tru64</productname> <Literal remap="tt">disklabel</Literal>, but there are
+some incompatibilities in the data that <Literal remap="tt">minlabel</Literal> fills in, so
+<productname>HP Tru64</productname> will simply refuse to accept a partition table generated by
+<Literal remap="tt">minlabel</Literal>.  To setup a Linux <Literal remap="tt">ext2</Literal> partition under <productname>HP Tru64</productname>,
+you'll have to change the disktab entry for your disk.  For the
+purpose of this discussion, let's assume that you have an rz26 disk (a
+common 1GB drive) on which you want to install Linux.  The disktab
+entry under <productname>HP Tru64</productname> v3.2 looks like this (see file
+<filename>/etc/disktab</filename>):
+
+<Screen>
+rz26|RZ26|DEC RZ26 Winchester:\
+        :ty=winchester:dt=SCSI:ns#57:nt#14:nc#2570:\
+        :oa#0:pa#131072:ba#8192:fa#1024:\
+        :ob#131072:pb#262144:bb#8192:fb#1024:\
+        :oc#0:pc#2050860:bc#8192:fc#1024:\
+        :od#393216:pd#552548:bd#8192:fd#1024:\
+        :oe#945764:pe#552548:be#8192:fe#1024:\
+        :of#1498312:pf#552548:bf#8192:ff#1024:\
+        :og#393216:pg#819200:bg#8192:fg#1024:\
+        :oh#1212416:ph#838444:bh#8192:fh#1024:
+</Screen>
+
+</Para>
+
+<Para>
+The interesting fields here are <Literal remap="tt">o</Literal><Emphasis remap="it">?</Emphasis>, and
+<Literal remap="tt">p</Literal><Emphasis remap="it">?</Emphasis>, where <Emphasis remap="it">?</Emphasis> is a letter in the range
+<Literal remap="tt">a</Literal>-<Literal remap="tt">h</Literal> (first through 8-th partition).  The <Literal remap="tt">o</Literal>
+value gives the starting offset of the partition (in sectors) and the
+<Literal remap="tt">p</Literal> value gives the size of the partition (also in sectors).
+See <Literal remap="tt">disktab</Literal>(4) for more info.  Note that <productname>HP Tru64</productname> likes to
+define overlapping partitions.  For the entry above, the partition
+layout looks like this (you can verify this by adding up the various
+<Literal remap="tt">o</Literal> and <Literal remap="tt">p</Literal> values):
+
+<Screen>
+  a    	b      	  d    	      e	     	  f
+|---|-------|-----------|-----------|-----------|
+
+                        c
+|-----------------------------------------------|
+
+                     g                 h
+            |-----------------|-----------------|
+</Screen> <!-- FIXME This is screen? -->
+
+</Para>
+
+<Para>
+<productname>HP Tru64</productname> insists that partition <Literal remap="tt">a</Literal> starts at offset 0 and that
+partition <Literal remap="tt">c</Literal> spans the entire disk.  Other than that, you can
+setup the partition table any way you like.
+</Para>
+
+<Para>
+Let's suppose you have <productname>HP Tru64</productname> using partition <Literal remap="tt">g</Literal> and want to
+install Linux on partition <Literal remap="tt">h</Literal> with partition <Literal remap="tt">b</Literal> being a
+(largish) swap partition.  To get this layout without destroying the
+existing <productname>HP Tru64</productname> partition, you need to set the partition types
+explicitly.  You can do this by adding a <Literal remap="tt">t</Literal> field for each
+partition.  In our case, we add the following line to the above
+disktab entry.
+
+<Screen>
+	:ta=unused:tb=swap:tg=4.2BSD:th=resrvd8:
+</Screen>
+
+</Para>
+
+<Para>
+Now why do we mark partition <Literal remap="tt">h</Literal> as "reservd8" instead of "ext2"?
+Well, <productname>HP Tru64</productname> doesn't know about Linux.  It so happens that partition
+type "ext2" corresponds to a numeric value of 8, and <productname>HP Tru64</productname> uses the
+string "reservd8" for that value.  Thus, in <productname>HP Tru64</productname> speak, "reservd8"
+means "ext2".  OK, this was the hard part.  Now we just need to
+install the updated disktab entry on the disk.  Let's assume the disk
+has SCSI id 5.  In this case, we'd do:
+
+<Screen>
+# disklabel -rw /dev/rrz5c rz26
+</Screen>
+
+</Para>
+
+<Para>
+You can verify that everything is all right by reading back the
+disklabel with <command>disklabel -r /dev/rrz5c</command>.  At this point, you
+may want to reboot <productname>HP Tru64</productname> and make sure the existing <productname>HP Tru64</productname>
+partition is still alive and well.  If that is the case, you can shut
+down the machine and start with the Linux installation.  Be sure to
+skip the disk partitioning step during the install.  Since we already
+installed a good partition table, you should be able to proceed and
+select the 8th partition as the Linux root partition and the 2nd
+partition as the swap partition.  If the disk is, say, the second SCSI
+disk in the machine, then the device name for these partitions would
+be <filename>/dev/sdb8</filename> and <filename>/dev/sdb2</filename>,
+respectively (note that
+Linux uses letters to name the drives and numbers to name the
+partitions, which is exactly reversed from what <productname>HP Tru64</productname> does; the
+Linux scheme makes more sense, of course ;-).
+</Para>
+
+</Sect2>
+
+<Sect2>
+<Title>Installing <Literal remap="tt">aboot</Literal></Title>
+
+<Para>
+<Emphasis>First big caveat</Emphasis>: with the SRM firmware, you can boot one and
+only one operating system per disk.  For this reason, it is generally
+best to have at least two SCSI disks in a machine that you want to
+dual-boot between Linux and <productname>HP Tru64</productname>.  Of course, you could also boot
+Linux from a floppy if speed doesn't matter or over the network, if
+you have a <Literal remap="tt">bootp</Literal>-capable server.  But in this section we assume
+you want to boot Linux from a disk that contains one or more <productname>HP Tru64</productname>
+partitions.
+</Para>
+
+<Para>
+<Emphasis>Second big caveat</Emphasis>: installing <Literal remap="tt">aboot</Literal> on a disk shared with
+<productname>HP Tru64</productname> renders the first and third partition unusable (since those
+<Emphasis>must</Emphasis> have a starting offset of 0).  For this reason, we recommend
+that you change the size of partition <Literal remap="tt">a</Literal> to something that is just
+big enough to hold <Literal remap="tt">aboot</Literal> (1MB should be plenty).
+</Para>
+
+<Para>
+Once these two caveats are taken care of, installing <Literal remap="tt">aboot</Literal> is
+almost as easy as usual: since partition <Literal remap="tt">a</Literal> and <Literal remap="tt">c</Literal> will
+overlap with <Literal remap="tt">aboot</Literal>, we need to tell <Literal remap="tt">swriteboot</Literal> that this is
+indeed OK.  We can do this under Linux with a command line of the
+following form (again, assuming we're trying to install <Literal remap="tt">aboot</Literal> on
+the second SCSI disk):
+
+<Screen>
+# swriteboot -f1 -f3 /dev/sdb bootlx
+</Screen>
+
+</Para>
+
+<Para>
+The <Literal remap="tt">-f1</Literal> means that we want to force writing 
+<filename>bootlx</filename> even
+though it overlaps with partition 1.  The corresponding applies for
+partition 3.
+</Para>
+
+<Para>
+This is it.  You should now be able to shutdown the system and boot
+Linux from the harddisk.  In our example, the SRM command line to do
+this would be:
+
+<Screen>
+&#62;&#62;&#62; boot dka5 -fi 8/vmlinux.gz -fl root=/dev/sdb8
+</Screen>
+
+</Para>
+
+</Sect2>
+
+</Sect1>
+
+<Sect1 id="SRM-Distributions">
+<Title>Installation of Distributions</Title>
+
+<Sect2>
+<Title>RedHat 6.0, 6.1 and 6.2</Title>
+
+<Sect3>
+<Title>Installation from the Red Hat 6.0, 6.1 or 6.2 CD</Title>
+
+<Para>
+Red Hat have made their distribution CD bootable from SRM console
+<FOOTNOTE>
+
+<Para>
+Please note that through the official RedHat CD-ROM is SRM
+bootable, copies made by various other companies may not be
+bootable.
+</Para>
+
+</FOOTNOTE>
+
+To start an installation, put the CD in and type
+the following:
+
+<Screen>
+&#62;&#62;&#62; boot srm-device -file kernels/generic.gz -flags root=linux-device
+</Screen>
+
+</Para>
+
+<Para>
+In the above, the SRM device name and Linux device name for your
+CD-ROM drive are needed.  For Example if the machine had an IDE CD-ROM
+installed as primary master the command would look like this:
+
+<Screen>
+&#62;&#62;&#62; boot dqa0 -file kernels/generic.gz -flags "root=/dev/hda"
+</Screen>
+
+</Para>
+
+<Para>
+See the section on <XRef LinkEnd="device-naming"> conventions if you don't know what these are.
+</Para>
+
+</Sect3>
+
+</Sect2>
+
+<!-- FIXME Newer RedHat ?? -->
+
+<Sect2>
+<Title>SuSE 6.1</Title>
+
+<Sect3>
+<Title>Installation from the SuSE 6.1 CD</Title>
+
+<Para>
+The SuSE 6.1 CD is not bootable from SRM console. SuSE have an
+alternative approach which involves creating two boot floppies, the
+images of which are included on the CD.  The boot disks can be created
+in various ways, depending on the systems you have available
+</Para>
+
+<Para>
+Writing the boot disks from a linux system
+The command to use is dd. From the mount-point of SuSE CD 1, the commands are:
+
+<Screen>
+# dd if=disks/aboot of=/dev/fd0
+# dd if=disks/install of=/dev/fd0
+</Screen>
+
+</Para>
+
+<Para>
+For writing the boot disks from a windows system, the command to use
+is rawrite. It is available on the CD.
+
+<Screen>
+ D:\tools\&#62; rawrite
+</Screen>
+
+</Para>
+
+<Para>
+The program then prompts for input disk image and output disk
+drive. Run this command once for each of the disk images as shown
+above.
+</Para>
+
+<Para>
+Starting the SuSE installer from the boot disks
+With the floppy disk made from the aboot image in place, type:
+
+<Screen>
+&#62;&#62;&#62; boot dva0 -file vmlinux.gz -flags "root=/dev/fd0 load_ramdisk=1"
+</Screen>
+
+</Para>
+
+<Para>
+This will start the kernel, prompt you for the second boot disk, and start the installer
+</Para>
+
+</Sect3>
+
+</Sect2>
+
+<Sect2>
+<Title>SuSE 6.3</Title>
+
+<Sect3>
+<Title>Installation from the SuSE 6.3 CD</Title>
+
+<Para>
+The SuSE 6.3 CD-ROM is SRM bootable much like the RedHat 6.0 and 6.1 CD-ROMs. The best way
+to start the install from SRM is to use the following command:
+
+<Screen>
+&#62;&#62;&#62; boot srm-device -flags 0
+</Screen>
+
+</Para>
+
+<Para>
+In the above, the SRM device names for your
+CD-ROM drive is needed.  For example if the machine had an IDE CD-ROM
+installed as primary master the command would look like this:
+
+<Screen>
+&#62;&#62;&#62; boot dqa0 -flags 0
+</Screen>
+
+SuSE has added support to aboot to allow it to load initrd files. The above command will from the
+CD-ROM drive and use config number 0 from the <filename>/etc/aboot.conf</filename> file. For other variations
+on this refer to the SuSE installation guide.
+</Para>
+
+</Sect3>
+
+</Sect2>
+<!-- FIXME Newer RedHat ?? -->
+<!-- FIXME Debian ??  -->
+
+</Sect1>
+
+<Sect1 id="SRM-history">
+<Title>Document History</Title>
+<para>
+v0.8.1 14th February 2004 Updated by Helge Kreutzmann <email>kreutzm@physik.uni-hannover.de</email>
+</para>
+<ItemizedList>
+<listitem>
+<para>
+Introduced more SGML-Tags, updated DocBook-Version
+</para>
+</listitem>
+<listitem>
+<para>
+Minor typographic corrections (e.g., whitespaces)
+</para>
+</listitem>
+<listitem>
+<para>
+Fixed some (outdated) URLS
+</para>
+</listitem>
+</ItemizedList>
+<Para>
+v0.8 9th November 2000 Changed from Rich Payne <email>rdp@alphalinux.org</email>
+<ItemizedList>
+<ListItem>
+<Para>
+ Added section on SRM Device names
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+ Many spelling/grammer fixes.
+</Para>
+</ListItem>
+
+</ItemizedList>
+</Para>
+
+<Para>
+v0.7.1 6th November 2000 Changes from Peter Petrakis <email>ppetrakis@alphalinux.org</email>
+
+<ItemizedList>
+<ListItem>
+
+<Para>
+ Cleaned up netbooting section. Avoid duplicate information.
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+ Added DHCP/BOOTP server configuration section. 
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+ Added SRM netbooting section.
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+ Put the older bootpd configuration in it's own section and elaborated on it. 
+</Para>
+</ListItem>
+
+</ItemizedList>
+</Para>
+
+
+<Para>
+v0.7 10th July 2000 Changes from Rich Payne <email>rdp@alphalinux.org</email>
+
+<ItemizedList>
+<ListItem>
+
+<Para>
+ Updated for RedHat 6.2
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+ Fixed aboot link for alphalinux.org and added CVS information.
+</Para>
+</ListItem>
+
+<ListItem>
+<Para>
+ Added additional netboot information from Peter Petrakis <email>ppetrakis@alphalinux.org</email>
+</Para>
+</ListItem>
+</ItemizedList>
+</Para>
+
+
+<Para>
+v0.6.1 21 March 2000 Changes from Rich Payne <email>rdp@alphalinux.org</email>
+
+<ItemizedList>
+<ListItem>
+
+<Para>
+ Made the installation hints a new chapter
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+ Added information on Netbooting
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+ Added to the new section on RedHat 6.1 and BSD disklabels
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+ Removed David Mosberger-Tang's name from the authors list
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+ Marked a few of the feature as being in 0.6 only
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+ Added info for SuSE 6.3 and RedHat 6.1
+</Para>
+</ListItem>
+
+</ItemizedList>
+
+</Para>
+
+<Para>
+v0.6 3 March 2000 Changes and information from David Huggins-Daines
+<email>dhd@linuxcare.com</email>
+
+<ItemizedList>
+<ListItem>
+
+<Para>
+Moved the notes on MILO vs. SRM to an "About this document" section
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+Added sections on switching to SRM, and basic SRM usage
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+Added section on the new interactive use of aboot
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+Updated the note on DOS partition tables to mention the Red Hat 6.1
+installer's behavior.
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+Normalized the markup, and codified the conventions used for
+user-entered commands.
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+Corrected the notes on BSD disklabels (SRM does <Emphasis>not</Emphasis>
+read BSD disklabels, it's just that they don't conflict with the boot
+block).
+</Para>
+</ListItem>
+
+</ItemizedList>
+
+</Para>
+
+<Para>
+v0.5.2 5 December 1999 Added comments and information from Stig Telfer
+(<email>stig@alpha-processor.com</email>).
+
+<ItemizedList>
+<ListItem>
+
+<Para>
+Added chart on SRM to Linux name mappings
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+Added RedHat 6.0 and SuSE 6.1 installation information
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+Added Disk Partitioning Information
+</Para>
+</ListItem>
+
+</ItemizedList>
+
+</Para>
+
+<Para>
+v0.5.1 (Not Released) 13 November 1999 Took the original 0.5 document and updated several parts:
+</Para>
+
+<Para>
+
+<ItemizedList>
+<ListItem>
+
+<Para>
+Update information on SRM booting from IDE devices
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+Fixed URL to aboot source
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+Update toc page to reflect MILO's future
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+Included information on bootdef&lowbar;dev and boot&lowbar;dev to chapter 3
+</Para>
+</ListItem>
+<ListItem>
+
+<Para>
+Added this section
+</Para>
+</ListItem>
+
+</ItemizedList>
+
+</Para>
+
+<Para>
+v0.5 17 August 1996 - Original Document by David Mosberger-Tang
+</Para>
+
+</Sect1>
+
+</Article>

+ 51 - 0
package/aboot/src/doc/man/Makefile

@@ -0,0 +1,51 @@
+# eventually this should have rules for recreating the man pages from the 
+# sgml source, but since this doesn't work on my machine right now i'm
+# leaving it out.
+
+# if this is a recursive make, and mandir was set in the top-level Makefile,
+# use that value. Otherwise default to /usr/man.
+
+ifeq ($(mandir),)
+MANDIR=/usr/man
+else
+MANDIR=$(mandir)
+endif
+MAN1=$(MANDIR)/man1
+MAN5=$(MANDIR)/man5
+MAN8=$(MANDIR)/man8
+
+all: aboot.8 aboot.conf.5 abootconf.8 isomarkboot.1 sdisklabel.8 netabootwrap.1
+
+install: 
+	install -d $(MAN1) $(MAN5) $(MAN8)
+	install -c isomarkboot.1 netabootwrap.1 $(MAN1)
+	install -c aboot.conf.5 $(MAN5)
+	install -c aboot.8 abootconf.8 e2writeboot.8 swriteboot.8 sdisklabel.8 $(MAN8)	
+install-gz: install
+	gzip -f9 $(MAN1)/isomarkboot.1 $(MAN1)/netabootwrap.1
+	gzip -f9 $(MAN5)/aboot.conf.5
+	gzip -f9 $(MAN8)/aboot.8 $(MAN8)/abootconf.8 $(MAN8)/e2writeboot.8 \
+		 $(MAN8)/swriteboot.8 $(MAN8)/sdisklabel.8
+install-gzip: install-gz
+
+clean:
+	rm -f aboot.8 aboot.conf.5 abootconf.8 isomarkboot.1 sdisklabel.8 netabootwrap.1 manpage.log manpage.links manpage.refs
+
+aboot.8: aboot.sgml
+	nsgmls aboot.sgml | sgmlspl sgmlspl-specs/docbook2man-spec.pl
+
+aboot.conf.5: aboot.conf.sgml
+	nsgmls aboot.conf.sgml | sgmlspl sgmlspl-specs/docbook2man-spec.pl
+
+abootconf.8: abootconf.sgml
+	nsgmls abootconf.sgml | sgmlspl sgmlspl-specs/docbook2man-spec.pl
+
+isomarkboot.1: isomarkboot.sgml
+	nsgmls isomarkboot.sgml | sgmlspl sgmlspl-specs/docbook2man-spec.pl
+
+netabootwrap.1: netabootwrap.sgml
+	nsgmls netabootwrap.sgml | sgmlspl sgmlspl-specs/docbook2man-spec.pl
+
+sdisklabel.8: sdisklabel.sgml
+	nsgmls sdisklabel.sgml | sgmlspl sgmlspl-specs/docbook2man-spec.pl
+

+ 32 - 0
package/aboot/src/doc/man/README

@@ -0,0 +1,32 @@
+This compilation contains man pages for various boot aspects on the Linux/Alpha
+platform. They are licensed under the GPL. Comments, suggestions and patches
+should be forwarded either to me or to the current aboot maintainer.
+
+The following files are included:
+
+README             this document
+aboot.8            man pages for aboot
+aboot.sgml         sgml-source for man page for aboot
+aboot.conf.5       man page for configuration file etc/aboot.conf
+aboot.conf.sgml    sgml-source for above man page
+abootconf.8        man page for abootconf
+abootconf.sgml     sgml-source for man page for abootconf
+e2writeboot.8      man page for e2writeboot (from aboot 7a tarball, modified)
+swriteboot.8       man page for swriteboot (from debian distribution, modified)
+isomarkboot.sgml   sgml-source for man page for isomarkboot
+isomarkboot.8      man page for isomarkboot
+sdisklabel.sgml    sgml-source for man page for sdisklabel
+sdisklabel.8       man page for sdisklabel
+
+Since I have no experience regarding e2writeboot and swriteboot I made only
+small modifications in these man pages.
+
+The list of authors was verified as best as possible (by contacting all
+person still reachable via email), if you feel this is not complete/accureate
+please contact me.
+
+Technical note:
+To create the nroff version from the SGML sources, nsgml was used like
+        nsgmls abootconf.sgml | sgmlspl sgmlspl-specs/docbook2man-spec.pl
+
+Hannover, Germany, January 17th 2003

+ 57 - 0
package/aboot/src/doc/man/aboot.8

@@ -0,0 +1,57 @@
+.\" This manpage has been automatically generated by docbook2man-spec
+.\" from a DocBook document.  docbook2man-spec can be found at:
+.\" <http://shell.ipoline.com/~elmert/hacks/docbook2X/> 
+.\" Please send any bug reports, improvements, comments, patches, 
+.\" etc. to Steve Cheng <steve@ggi-project.org>.
+.TH "ABOOT" "8" "11 Juli 2002" "aboot" ""
+.SH NAME
+aboot \- The secondary boot loader for Linux/Alpha
+.SH "COPYRIGHT"
+.PP
+\fBaboot\fR is Copyright (C) 1996 Linus Torvalds, David Mosberger-Tang and Michael Schwingen
+.SH "DESCRIPTION"
+.PP
+
+\fBaboot\fR is the secondary boot loader needed if
+the Linux/Alpha system is booted via SRM. It is usually installed during
+system installation by \fBswriteboot\fR(8). 
+.PP
+To automate the booting process predefined boot configurations can be stored
+in \fIetc/aboot.conf\fR(5). 
+.PP
+\fBaboot\fR can also be used interactively by issuing
+.PP
+\fBboot \fIdka0 -fl "i"\fB\fR
+.PP
+at the SRM-Prompt where dka0 has to be replaced by the device used. 
+.PP
+In the interactive mode you can use the command h to show your current
+\fIetc/aboot.conf\fR and then the appropriate number
+(or a complete boot command as in SRM) to boot Linux.
+.PP
+If you do not want to use the \fIetc/aboot.conf\fR as set
+up by \fBabootconf\fR you can explicitly tell 
+\fBaboot\fR where to look for \fIetc/aboot.conf\fR by prepending the number of the configuration with the proper
+partition, i.e. if your \fIetc/aboot.conf\fR is on your
+second partition and you want to boot the entry labeled three you would
+issue
+.PP
+\fBboot \fIdqa -fl "2:3"\fB\fR
+.PP
+Note that this applies to Linux booting via SRM only as
+VMS, Tru64, *BSD and
+Windows NT each have their own secondary boot loader.
+Furthermore \fBaboot\fR is also not needed if the system is booted via
+\fBmilo\fR.
+.SH "AUTHOR"
+.PP
+This man page was written by Helge Kreutzmann
+<kreutzm@itp.uni-hannover.de> for the Debian GNU/Linux project
+but may be used by others.
+.SH "FILES"
+.PP
+\fIetc/aboot.conf\fR
+.SH "SEE ALSO"
+.PP
+\fBabootconf\fR(8), \fIaboot.conf\fR(5),
+\fBswriteboot\fR(8), HP SRM Manual

+ 81 - 0
package/aboot/src/doc/man/aboot.conf.5

@@ -0,0 +1,81 @@
+.\" This manpage has been automatically generated by docbook2man-spec
+.\" from a DocBook document.  docbook2man-spec can be found at:
+.\" <http://shell.ipoline.com/~elmert/hacks/docbook2X/> 
+.\" Please send any bug reports, improvements, comments, patches, 
+.\" etc. to Steve Cheng <steve@ggi-project.org>.
+.TH "ABOOT.CONF" "5" "16 Juli 2003" "aboot.conf" ""
+.SH NAME
+aboot.conf \- The configuration file for aboot(8)
+.SH "DESCRIPTION"
+.PP
+
+\fIaboot.conf\fR contains a list of boot settings
+for \fBaboot\fR(8). Each boot setting
+has a unique number which can be supplied at the SRM-Prompt.
+.
+.PP
+\fIaboot.conf\fR must be in a directory called
+\fIetc\fR on the \fBsame partition\fR
+as your kernels reside on unless you explicitly list the partitions
+for your kernels (see below for details). So if you create a separate
+boot partition (called \fI/boot\fR) then
+\fIaboot.conf\fR should reside in \fI/boot/etc/\fR.
+.PP
+In the following example the kernels reside on a different partition (hda4)
+then \fI/\fR belongs to (hda5) while in the fourth
+line \fI/boot\fR is on the same partition (hda6) as
+\fI/\fR.
+Therefore \fIaboot.conf\fR can be located on any of the
+three partitions but \fBalways\fR in a directory
+\fIetc\fR at the top level of the file system on that
+partition. You can change the partition to use with
+\fBabootconf\fR(8).
+.PP
+.SS "EXAMPLE ABOOT.CONF"
+.sp
+.RS
+.sp
+.nf
+0:4/vmlinuz root=/dev/hda5
+1:4/vmlinuz root=/dev/hda5 single
+2:4/vmlinuz.old ro root=/dev/hda5
+3:4/vmlinuz-2.4.9-32 root=/dev/sdc3 initrd=/initrd-2.4.9-32.img console=tty0
+8:6/boot/vmlinuz ro root=/dev/hda6
+.sp
+.fi
+.RE
+.sp
+.PP
+The first number is a unique identifier for each boot configuration.
+To boot a certain configuration at the SRM-Prompt you would issue
+.PP
+\fBboot \fIdka0 -fl "0"\fB\fR
+.PP
+where dka0 has to be replaced by your boot device and the boot configuration
+(0 in this case) can be replaced by any defined in 
+\fIetc/aboot.conf\fR.
+.PP
+After the colon the number of the partition the kernel resides on is given. 1
+corresponds to the BSD partition labeled A:, 2 to B: and so on. 
+.PP
+After the slash the name of the kernel to boot is given, including a possible
+path. If your kernel does not reside on a file system but is located directly
+after \fBaboot\fR at the beginning of the hard disk
+you would omit the number, the slash and the kernel name.
+.PP
+Next the name of the partition to mount as \fI/\fR is given.
+Other kernel parameters follow as required. As shown also an initrd can be
+specified.
+.PP
+The contents of this file can be shown before booting if necessary by
+using the interactive
+mode of \fBaboot\fR(8) (booting with the flag "i")
+and then issuing "h" at the \fBaboot\fR-prompt.
+.SH "AUTHOR"
+.PP
+This man page was written by Helge Kreutzmann
+<kreutzm@itp.uni-hannover.de> for the Debian GNU/Linux project but
+may be used by others.
+.SH "SEE ALSO"
+.PP
+\fBaboot\fR(8), \fBabootconf\fR(8), \fBswriteboot\fR(8), HP SRM Manual

+ 106 - 0
package/aboot/src/doc/man/aboot.conf.sgml

@@ -0,0 +1,106 @@
+<!DOCTYPE RefEntry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+<refentry id="aboot.conf">
+
+<refmeta>
+<refentrytitle>aboot.conf</refentrytitle>
+<manvolnum>5</manvolnum>
+<refmiscinfo>aboot.conf</refmiscinfo>
+</refmeta>
+
+<refnamediv>
+<refname>aboot.conf</refname>
+<refpurpose>The configuration file for <application>aboot</application>(8)
+</refpurpose>
+</refnamediv>
+
+<refsect1><title>DESCRIPTION</title>
+<para>
+<indexterm><primary>aboot.conf</primary></indexterm>
+<filename>aboot.conf</filename> contains a list of boot settings
+for <application>aboot</application>(8). Each boot setting
+has a unique number which can be supplied at the SRM-Prompt.
+<indexterm><primary>SRM</primary></indexterm>.
+</para>
+<para>
+<filename>aboot.conf</filename> must be in a directory called
+<filename>etc</filename> on the <emphasis>same partition</emphasis>
+as your kernels reside on unless you explicitly list the partitions
+for your kernels (see below for details). So if you create a separate
+boot partition (called <filename>/boot</filename>) then
+<filename>aboot.conf</filename> should reside in <filename>/boot/etc/</filename>.
+</para>
+<para>
+In the following example the kernels reside on a different partition (hda4)
+then <filename>/</filename> belongs to (hda5), while in the fifth
+line <filename>/boot</filename> is on the same partition (hda6) as
+<filename>/</filename>.
+Therefore <filename>aboot.conf</filename> can be located on any of the
+three partitions but <emphasis>always</emphasis> in a directory
+<filename>etc</filename> at the top level of the file system on that
+partition. You can change the partition to use with
+<application>abootconf</application>(8).
+</para>
+<para><example>
+<title>Example <filename>aboot.conf</filename></title>
+<blockquote>
+<literallayout>
+0:4/vmlinuz root=/dev/hda5
+1:4/vmlinuz root=/dev/hda5 single
+2:4/vmlinuz.old ro root=/dev/hda5
+3:4/vmlinuz-2.4.9-32 root=/dev/sdc3 initrd=/initrd-2.4.9-32.img console=tty0
+8:6/boot/vmlinuz ro root=/dev/hda6
+</literallayout>
+</blockquote>
+</example></para>
+<para>
+The first number is a unique identifier for each boot configuration.
+To boot a certain configuration at the SRM-Prompt you would issue
+</para>
+<para>
+<command>
+boot <parameter>dka0 -fl "0"</parameter>
+</command>
+</para>
+<para>
+where dka0 has to be replaced by your boot device and the boot configuration
+(0 in this case) can be replaced by any defined in 
+<filename>etc/aboot.conf</filename>.
+</para>
+
+<para>
+After the colon the number of the partition the kernel resides on is given. 1
+corresponds to the BSD partition labeled A:, 2 to B: and so on. 
+</para>
+
+<para>
+After the slash the name of the kernel to boot is given, including a possible
+path. If your kernel does not reside on a file system but is located directly
+after <application>aboot</application>(8) at the beginning of the hard disk
+you would omit the number, the slash and the kernel name.
+</para>
+
+<para>
+Next the name of the partition to mount as <filename>/</filename> is given.
+Other kernel parameters follow as required. As shown also an initrd can be
+specified.
+</para>
+
+<para>
+The contents of this file can be shown before booting if necessary by
+using the interactive
+mode of <application>aboot</application>(8) (booting with the flag "i")
+and then issuing "h" at the <application>aboot</application>-prompt.
+</para>
+
+</refsect1>
+<refsect1><title>AUTHOR</title>
+<para>
+This man page was written by Helge Kreutzmann
+<email>debian@helgefjell.de</email> for the Debian GNU/Linux project but
+may be used by others.
+</para>
+</refsect1>
+<refsect1><title>SEE ALSO</title>
+<para><application>aboot</application>(8), <application>abootconf</application>(8), <application>swriteboot</application>(8), HP SRM Manual (<ULink URL="http://h18002.www1.hp.com/alphaserver/download/srm_reference.pdf"></ULink>)
+</refsect1>
+</refentry>

+ 83 - 0
package/aboot/src/doc/man/aboot.sgml

@@ -0,0 +1,83 @@
+<!DOCTYPE RefEntry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+<refentry id="aboot">
+
+<refmeta>
+<refentrytitle>aboot</refentrytitle>
+<manvolnum>8</manvolnum>
+<refmiscinfo>aboot</refmiscinfo>
+</refmeta>
+
+<refnamediv>
+<refname>aboot</refname>
+<refpurpose>The secondary boot loader for Linux/Alpha</refpurpose>
+</refnamediv>
+
+<refsect1><title>COPYRIGHT</title>
+<para>
+<application>aboot</application> is Copyright (C) 1996 Linus Torvalds, David Mosberger-Tang and Michael Schwingen
+</para>
+</refsect1>
+
+<refsect1><title>DESCRIPTION</title>
+<para>
+<indexterm><primary>aboot</primary></indexterm>
+<application>aboot</application> is the secondary boot loader needed if
+the Linux/Alpha system is booted via SRM. It is usually installed during
+system installation by <application>swriteboot</application>(8). 
+</para>
+<para>
+To automate the booting process predefined boot configurations can be stored
+in <filename>etc/aboot.conf</filename>(5). 
+</para>
+<para>
+<application>aboot</application> can also be used interactively by issuing
+</para>
+<para>
+<command>boot <parameter>dka0 -fl "i"</parameter></command>
+</para>
+<para>
+at the SRM-Prompt where dka0 has to be replaced by the device used. 
+</para>
+<para>
+In the interactive mode you can use the command l to show your current
+<filename>etc/aboot.conf</filename> and then the appropriate number
+(or a complete boot command as in SRM) to boot Linux.
+</para>
+<para>
+If you do not want to use the <filename>etc/aboot.conf</filename> as set
+up by <application>abootconf</application>(8) you can explicitly tell 
+<application>aboot</application> where to look for <filename>etc/aboot.conf</filename> by prepending the number of the configuration with the proper
+partition, i.e. if your <filename>etc/aboot.conf</filename> is on your
+second partition and you want to boot the entry labeled three you would
+issue
+</para>
+<para>
+<command>boot <parameter>dqa -fl "2:3"</parameter></command>
+</para>
+<para>
+Note that this applies to Linux booting via SRM only as
+<ProductName>VMS</ProductName>, <ProductName>Tru64</ProductName>, *BSD and
+<ProductName>Windows NT</ProductName> each have their own secondary boot loader.
+Furthermore <application>aboot</application> is also not needed if the system is booted via
+<application>milo</application>.
+</para>
+</refsect1>
+
+
+<refsect1><title>AUTHOR</title>
+<para>
+This man page was written by Helge Kreutzmann
+<email>debian@helgefjell.de</email> for the Debian GNU/Linux project
+but may be used by others.
+</para>
+</refsect1>
+
+<refsect1><title>FILES</title>
+<para><filename>etc/aboot.conf</filename></para>
+</refsect1>
+
+<refsect1><title>SEE ALSO</title>
+<para><application>abootconf</application>(8), <filename>aboot.conf</filename>(5),
+<application>swriteboot</application>(8), HP SRM Manual (<ULink URL="http://h18002.www1.hp.com/alphaserver/download/srm_reference.pdf"></ULink>)</para>
+</refsect1>
+</refentry>

+ 96 - 0
package/aboot/src/doc/man/abootconf.8

@@ -0,0 +1,96 @@
+.\" This manpage has been automatically generated by docbook2man-spec
+.\" from a DocBook document.  docbook2man-spec can be found at:
+.\" <http://shell.ipoline.com/~elmert/hacks/docbook2X/> 
+.\" Please send any bug reports, improvements, comments, patches, 
+.\" etc. to Steve Cheng <steve@ggi-project.org>.
+.TH "ABOOTCONF" "8" "26 Oktober 2003" "abootconf" ""
+.SH NAME
+abootconf \- Configure the location of the configuration file for the secondary bootloader aboot(8) for Linux/Alpha.
+.SH SYNOPSIS
+.sp
+\fBabootconf\fR \fB/dev/xxx num\fR
+.SH "COPYRIGHT"
+.PP
+\fBabootconf\fR is Copyright (C) 1996 Linus Torvalds, David Mosberger-Tang and Michael Schwingen
+.SH "DESCRIPTIONS"
+.PP
+
+
+\fBabootconf\fR is used to change the partition
+the alpha Linux boot loader \fBaboot\fR(8)
+looks for its configuration file in. The configuration file is stored
+in \fIetc/aboot.conf\fR(5)
+relative to the root of the file system in this partition.
+.PP
+\fBabootconf\fR requires the boot device
+(e.g. \fI/dev/hdb\fR, \fI/dev/sda\fR) and the
+partition
+to be used (e.g. 3). Thus if you want to boot from partition E: on your second
+SCSI disk you would enter
+.PP
+\fBabootconf \fI/dev/sdb 5\fB\fR
+.SH "NOTES"
+.PP
+\fBabootconf\fR is not needed if you are booting
+your alpha system via \fBmilo\fR. 
+.PP
+For each disk one partition can be activated to contain the configuration
+for \fBaboot\fR(8) which is located in
+\fIetc/aboot.conf\fR(5).
+The disk chosen to boot from is selected at
+the SRM prompt as the second argument, e.g.
+.PP
+\fBboot \fIdqa\fB\fR
+.PP
+to boot from your first IDE hard disk. See the HP SRM-Manual and
+\fBaboot\fR(8)
+for details.
+.PP
+\fBaboot\fR(8) can load a kernel from an
+arbitrary partition and can even use a different
+root partition than the one \fIetc/aboot.conf\fR
+belongs to. Hence you would usually
+set up one \fIetc/aboot.conf\fR with all combinations and
+would not require \fBabootconf\fR except for initial
+set up. You can then
+boot the requested
+Linux kernel by giving the appropriate flags at the SRM prompt, e.g. to boot
+the entry labeled 2 you would use
+.PP
+\fBboot \fIdqa -fl "2"\fB\fR
+.PP
+See the HP SRM manual and \fIaboot.conf\fR(5)
+for details.
+.PP
+To show the current setting simply omit the last argument (i.e. the partition
+number).
+.PP
+Note that you have to rerun \fBabootconf\fR if you updated
+\fBaboot\fR.
+.PP
+Strictly speaking \fBabootconf\fR is not necessary as
+you can specify the partition which \fIetc/aboot.conf\fR
+resides on at the SRM-Prompt by prepending the partition number and a colon
+in the flags-parameter, i.e. if \fIetc/aboot.conf\fR
+resided on the fourth partition and you want to boot the entry labeled 2
+you could also issue
+.PP
+\fBboot \fIdqa -fl "4:2"\fB\fR
+.PP
+at the SRM prompt.
+.PP
+Note that this applies to Linux only as VMS, Tru64, *BSD and
+Windows NT each have their own secondary boot loader.
+.PP
+Also note that for initial hard disk setup \fBabootconf\fR
+is no longer needed as \fBswriteboot\fR(8) contains the
+entire functionality of \fBabootconf\fR.
+.SH "AUTHOR"
+.PP
+This man page was written by Helge Kreutzmann <kreutzm@itp.uni-hannover.de> for the Debian GNU/Linux project but may be used by others.
+.SH "FILES"
+.PP
+\fIetc/aboot.conf\fR
+.SH "SEE ALSO"
+.PP
+\fBaboot\fR(8), \fBswriteboot\fR(8), \fIaboot.conf\fR(5), HP SRM Manual

+ 141 - 0
package/aboot/src/doc/man/abootconf.sgml

@@ -0,0 +1,141 @@
+<!DOCTYPE RefEntry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+<refentry id="abootconf">
+
+<refmeta>
+<refentrytitle>abootconf</refentrytitle>
+<manvolnum>8</manvolnum>
+<refmiscinfo>abootconf</refmiscinfo>
+</refmeta>
+
+<refnamediv>
+<refname>abootconf</refname>
+<refpurpose>
+Configure the location of the configuration file for the secondary boot
+loader <application>aboot</application>(8) for Linux/Alpha.
+</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv>
+ <cmdsynopsis>
+   <command>abootconf</command> <arg choice="plain">/dev/xxx num</arg>
+ </cmdsynopsis>
+</refsynopsisdiv>
+
+<refsect1><title>COPYRIGHT</title>
+<para>
+<application>abootconf</application> is Copyright (C) 1996 Linus Torvalds, David Mosberger-Tang and Michael Schwingen
+</para>
+</refsect1>
+
+<refsect1><title>DESCRIPTIONS</title>
+<para>
+<indexterm><primary>abootconf</primary></indexterm>
+<indexterm><primary>aboot</primary></indexterm>
+<application>abootconf</application> is used to change the partition<indexterm><primary>partition
+</primary></indexterm>
+the alpha Linux boot loader <application>aboot</application>(8)
+looks for its configuration file in. The configuration file is stored
+in <filename>etc/aboot.conf</filename>(5)
+relative to the root of the file system in this partition.
+</para>
+<para> 
+<application>abootconf</application> requires the boot device
+(e.g. <filename>/dev/hdb</filename>, <filename>/dev/sda</filename>) and the
+partition
+to be used (e.g. 3). Thus if you want to boot from partition E: on your second
+SCSI disk you would enter</para>
+<para>
+<command>
+abootconf <parameter>/dev/sdb 5</parameter>
+</command>
+</para>
+</refsect1>
+<refsect1><title>NOTES</title>
+<para>
+<application>abootconf</application> is not needed if you are booting
+your alpha system via <application>milo</application>. 
+</para>
+<para>
+For each disk one partition can be activated to contain the configuration
+for <application>aboot</application>(8) which is located in
+<filename>etc/aboot.conf</filename>(5).
+The disk chosen to boot from is selected at
+the SRM prompt as the second argument, e.g.
+</para>
+<para>
+<command>
+boot <parameter>dqa</parameter>
+</command>
+</para>
+<para>
+to boot from your first IDE hard disk. See the HP SRM-Manual and
+<application>aboot</application>(8)
+for details.
+</para>
+<para>
+<application>aboot</application>(8) can load a kernel from an
+arbitrary partition and can even use a different
+root partition than the one <filename>etc/aboot.conf</filename>
+belongs to. Hence you would usually
+set up one <filename>etc/aboot.conf</filename> with all combinations and
+would not require <application>abootconf</application> except for initial
+set up. You can then
+boot the requested
+Linux kernel by giving the appropriate flags at the SRM prompt, e.g. to boot
+the entry labeled 2 you would use
+</para>
+<para>
+<command>
+boot <parameter>dqa -fl "2"</parameter>
+</command>
+</para>
+<para>
+See the HP SRM manual and <filename>aboot.conf</filename>(5)
+for details.
+</para>
+<para>
+To show the current setting simply omit the last argument (i.e. the partition
+number).
+</para>
+<para>
+Note that you have to rerun <application>abootconf</application> if you updated
+<application>aboot</application>(8).
+</para>
+<para>
+Strictly speaking <application>abootconf</application> is not necessary as
+you can specify the partition which <filename>etc/aboot.conf</filename>
+resides on at the SRM-Prompt by prepending the partition number and a colon
+in the flags-parameter, i.e. if <filename>etc/aboot.conf</filename>
+resided on the fourth partition and you want to boot the entry labeled 2
+you could also issue
+</para>
+<para>
+<command>
+boot <parameter>dqa -fl "4:2"</parameter>
+</command>
+</para>
+<para>
+at the SRM prompt.
+</para>
+<para>
+Note that this applies to Linux only as <ProductName>VMS</ProductName>, <ProductName>Tru64</ProductName>, *BSD and
+<ProductName>Windows NT</ProductName> each have their own secondary boot loader.
+</para>
+<para>
+Also note that for initial hard disk setup <application>abootconf</application>
+is no longer needed as <application>swriteboot</application>(8) contains the
+entire functionality of <application>abootconf</application>.
+</para>
+</refsect1>
+<refsect1><title>AUTHOR</title>
+<para>
+This man page was written by Helge Kreutzmann <email>debian@helgefjell.de</email> for the Debian GNU/Linux project but may be used by others.
+</para>
+</refsect1>
+<refsect1><title>FILES</title>
+<para><filename>etc/aboot.conf</filename></para>
+</refsect1>
+<refsect1><title>SEE ALSO</title>
+<para><application>aboot</application>(8), <application>swriteboot</application>(8), <filename>aboot.conf</filename>(5), HP SRM Manual (<ULink URL="http://h18002.www1.hp.com/alphaserver/download/srm_reference.pdf"></ULink>)</para>
+</refsect1>
+</refentry>

+ 46 - 0
package/aboot/src/doc/man/de/Makefile

@@ -0,0 +1,46 @@
+all:  srmbootraw.de.8 aboot.de.8 aboot.conf.de.5 abootconf.de.8 isomarkboot.de.1 sdisklabel.de.8 srmbootfat.de.1 e2writeboot.de.8 swriteboot.de.8 netabootwrap.de.1
+
+aboot.de.8: aboot.sgml
+	nsgmls aboot.sgml | sgmlspl docbook2man-de-spec.pl
+	mv aboot.8 aboot.de.8
+
+aboot.conf.de.5: aboot.conf.sgml
+	nsgmls aboot.conf.sgml | sgmlspl docbook2man-de-spec.pl
+	mv aboot.conf.5 aboot.conf.de.5
+
+abootconf.de.8: abootconf.sgml
+	nsgmls abootconf.sgml | sgmlspl docbook2man-de-spec.pl
+	mv abootconf.8 abootconf.de.8
+
+netabootwrap.de.1: netabootwrap.sgml
+	nsgmls netabootwrap.sgml | sgmlspl docbook2man-de-spec.pl
+	mv netabootwrap.1 netabootwrap.de.1
+
+isomarkboot.de.1: isomarkboot.sgml
+	nsgmls isomarkboot.sgml | sgmlspl docbook2man-de-spec.pl
+	mv isomarkboot.1 isomarkboot.de.1
+
+sdisklabel.de.8: sdisklabel.sgml
+	nsgmls sdisklabel.sgml | sgmlspl docbook2man-de-spec.pl
+	mv sdisklabel.8 sdisklabel.de.8
+
+srmbootfat.de.1: srmbootfat.sgml
+	nsgmls srmbootfat.sgml | sgmlspl docbook2man-de-spec.pl
+	mv srmbootfat.1 srmbootfat.de.1
+
+srmbootraw.de.8: srmbootraw.sgml
+	nsgmls srmbootraw.sgml | sgmlspl docbook2man-de-spec.pl
+	mv srmbootraw.8 srmbootraw.de.8
+
+e2writeboot.de.8: e2writeboot.8
+	ln -s e2writeboot.8 e2writeboot.de.8
+
+swriteboot.de.8: swriteboot.8
+	ln -s  swriteboot.8 swriteboot.de.8
+
+clean :
+	rm -f *.html *.de.? srmbootraw.8 srmbootfat.1 sdisklabel.8 isomarkboot.8 abootconf.8 aboot.conf.5 aboot.8 netabootwrap.1 manpage.links manpage.log manpage.refs
+	rm -rf SRM-HOWTO 
+
+
+#.PHONY clean

+ 108 - 0
package/aboot/src/doc/man/de/aboot.conf.sgml

@@ -0,0 +1,108 @@
+<!DOCTYPE RefEntry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+<refentry id="aboot.conf">
+
+<refmeta>
+<refentrytitle>aboot.conf</refentrytitle>
+<manvolnum>5</manvolnum>
+<refmiscinfo>aboot.conf</refmiscinfo>
+</refmeta>
+
+<refnamediv>
+<refname>aboot.conf</refname>
+<refpurpose>Die Konfigurationsdatei für <application>aboot</application>(8)
+</refpurpose>
+</refnamediv>
+
+<refsect1><title>BESCHREIBUNG</title>
+<para>
+<indexterm><primary>aboot.conf</primary></indexterm>
+<filename>aboot.conf</filename> enthält eine Liste von Boot-Einstellungen
+für <application>aboot</application>(8). Jede Boot-Einstellung hat eine
+eindeutige Zahl, die am SRM-Prompt angegeben werden kann.
+<indexterm><primary>SRM</primary></indexterm>.
+</para>
+<para>
+<filename>aboot.conf</filename> muß sich in einem Verzeichnis names
+<filename>etc</filename> auf der <emphasis>gleichen Partition</emphasis>
+wie Ihre Kernel befinden, es sei den, Sie geben explizit die Partition
+für Ihre Kernel an (siehe dazu die Ausführungen weiter unten). Falls Sie
+also eine seperate Boot-Partition (namens <filename>/boot</filename>)
+erzeugen, dann sollte <filename>aboot.conf</filename> in
+<filename>/boot/etc/</filename> liegen.
+</para>
+<para>
+Im folgenden Beispiel liegen die Kernel auf einer anderen Partition (hda4)
+als <filename>/</filename> (hda5), während in der fünften Zeile
+<filename>/boot</filename> auf der gleichen Partition (hda6) wie 
+<filename>/</filename> liegt. Daher kann sich <filename>aboot.conf</filename>
+auf einer der drei Partitionen befinden, muß aber <emphasis>immer</emphasis>
+in einem Verzeichnis namens <filename>etc</filename> relativ zur obersten
+Verzeichnisebene auf dieser Partition angelegt sein. Die zu verwendene
+Partition können Sie mittels <application>abootconf</application>(8)
+ändern.
+</para>
+<para><example>
+<title>BEISPIEL <filename>aboot.conf</filename></title>
+<blockquote>
+<literallayout>
+0:4/vmlinuz root=/dev/hda5
+1:4/vmlinuz root=/dev/hda5 single
+2:4/vmlinuz.old ro root=/dev/hda5
+3:4/vmlinuz-2.4.9-32 root=/dev/sdc3 initrd=/initrd-2.4.9-32.img console=tty0
+8:6/boot/vmlinuz ro root=/dev/hda6
+</literallayout>
+</blockquote>
+</example></para>
+<para>
+Die erste Zahl ist ein eindeutige Identifikation für jede Boot-Konfiguration.
+Um eine bestimmte Konfiguration am SRM-Prompt zu booten, geben Sie
+</para>
+<para>
+<command>
+boot <parameter>dka0 -fl "0"</parameter>
+</command>
+</para>
+<para>
+ein, wobei dka0 durch Ihr Boot-Gerät und die 0 durch die zur bootende,
+in <filename>etc/aboot.conf</filename> angegegebene Konfigurationszahl
+ersetzt werden muß.
+</para>
+
+<para>
+Nach dem Doppelpunkt ist die Partition, auf der sich der Kernel befindet,
+angegeben. 1 entspricht der BSD-Partition mit Namen A:, 2 B: und so weiter.
+</para>
+
+<para>
+Nach dem Schrägstrich ist der Name (ggf. inklusive des zugehörigen Pfads)
+des zu bootenden Kernels angegeben. Falls sich Ihr Kernel nicht in einem
+Dateisystem, sondern direkt nach <application>aboot</application>(8) am Anfang
+der Festplatte befindet lassen Sie die Zahl, den Schrägstrich und den
+Kernelnamen weg.
+</para>
+
+<para>
+Als nächstes ist die als <filename>/</filename> zu montierende Partition
+angegeben. Andere benötigte Kernel-Parameter folgen. Wie gezeigt kann auch
+eine initrd angegeben werden.
+</para>
+
+<para>
+Der Inhalt dieser Datei kann vor dem Booten mittels des interaktiven
+Modus -- durch Booten mit dem Paramter "i" -- 
+von <application>aboot</application>(8) und der Angabe von 
+"h" am <application>aboot</application>-Prompt angezeigt werden.
+</para>
+
+</refsect1>
+<refsect1><title>AUTOR</title>
+<para>
+Diese Handbuchseite wurde von Helge Kreutzmann
+<email>debian@helgefjell.de</email> für das Debian GNU/Linux-Projekt
+geschrieben, sie darf aber auch von anderen verwendet werden.
+</para>
+</refsect1>
+<refsect1><title>SIEHE AUCH</title>
+<para><application>aboot</application>(8), <application>abootconf</application>(8), <application>swriteboot</application>(8), HP SRM Handbuch (<ULink URL="http://h18002.www1.hp.com/alphaserver/download/srm_reference.pdf"></ULink>)
+</refsect1>
+</refentry>

+ 89 - 0
package/aboot/src/doc/man/de/aboot.sgml

@@ -0,0 +1,89 @@
+<!DOCTYPE RefEntry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+<refentry id="aboot">
+
+<refmeta>
+<refentrytitle>aboot</refentrytitle>
+<manvolnum>8</manvolnum>
+<refmiscinfo>aboot</refmiscinfo>
+</refmeta>
+
+<refnamediv>
+<refname>aboot</refname>
+<refpurpose>Der Bootloader (Urlader) der zweiten Stufe auf Linux/Alpha</refpurpose>
+</refnamediv>
+
+<refsect1><title>COPYRIGHT</title>
+<para>
+<application>aboot</application> unterliegt dem Copyright (C) 1996 Linus Torvalds, David Mosberger-Tang und Michael Schwingen
+</para>
+</refsect1>
+
+<refsect1><title>BESCHREIBUNG</title>
+<para>
+<indexterm><primary>aboot</primary></indexterm>
+<application>aboot</application> wird als Bootloader (Urlader) der zweiten
+Stufe benötigt, falls das System via SRM gebootet wird. Er wird normalerweise
+während der Systeminstallation durch
+<application>swriteboot</application>(8) installiert. 
+</para>
+<para>
+Um den Bootprozess zu automatisieren können vordefinierte Boot-Konfigurationen
+in <filename>etc/aboot.conf</filename>(5) eingetragen werden. 
+</para>
+<para>
+<application>aboot</application> kann durch die Angabe von
+</para>
+<para>
+<command>boot <parameter>dka0 -fl "i"</parameter></command>
+</para>
+<para>
+am SRM-Prompt auch interaktiv verwendet werden, wobei dka0 durch das
+verwendete Gerät ersetzt werden muß.
+</para>
+<para>
+Im interaktiven Modus können Sie das Kommando l zur Anzeige der derzeitigen
+<filename>etc/aboot.conf</filename> verwenden, und durch die Angabe der 
+entsprechenden Zahl (oder des kompletten Boot-Kommandos wie bei SRM)
+Linux booten.
+</para>
+<para>
+Falls Sie nicht die von <application>abootconf</application>(8) erstellte
+<filename>etc/aboot.conf</filename> verwenden wollen, können Sie
+<application>aboot</application> explizit angeben, wo es nach der
+<filename>etc/aboot.conf</filename> suchen soll, indem Sie vor die
+Zahl der Konfiguration die passende Partition angeben, d.h. falls
+Ihre <filename>etc/aboot.conf</filename> sich auf Ihrer zweiten Partition
+befindet und Sie den mit 3 benannten Eintrag booten wollen, dann gäben
+Sie an
+</para>
+<para>
+<command>boot <parameter>dqa -fl "2:3"</parameter></command>
+</para>
+<para>
+Beachten Sie, daß dies nur für das Booten von Linux via SRM zutrifft, da
+<ProductName>VMS</ProductName>, <ProductName>Tru64</ProductName>, *BSD und
+<ProductName>Windows NT</ProductName> jeweils über ihren eigenen Bootloader
+für die zweite Stufe verfügen. Desweiteren wird <application>aboot</application>
+nicht benötigt, falls das System mittels <application>milo</application>
+gebootet wird.
+</para>
+</refsect1>
+
+
+<refsect1><title>AUTOR</title>
+<para>
+Diese Handbuchseite wurde von Helge Kreutzmann
+<email>debian@helgefjell.de</email> für das Debian GNU/Linux-Projekt
+geschrieben, sie darf aber auch von anderen verwendet werden.
+</para>
+</refsect1>
+
+<refsect1><title>DATEIEN</title>
+<para><filename>etc/aboot.conf</filename></para>
+</refsect1>
+
+<refsect1><title>SIEHE AUCH</title>
+<para><application>abootconf</application>(8), <filename>aboot.conf</filename>(5),
+<application>swriteboot</application>(8), HP SRM Handbuch (<ULink URL="http://h18002.www1.hp.com/alphaserver/download/srm_reference.pdf"></ULink>)</para>
+</refsect1>
+</refentry>

+ 146 - 0
package/aboot/src/doc/man/de/abootconf.sgml

@@ -0,0 +1,146 @@
+<!DOCTYPE RefEntry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+<refentry id="abootconf">
+
+<refmeta>
+<refentrytitle>abootconf</refentrytitle>
+<manvolnum>8</manvolnum>
+<refmiscinfo>abootconf</refmiscinfo>
+</refmeta>
+
+<refnamediv>
+<refname>abootconf</refname>
+<refpurpose>
+Konfiguration des Ortes der Konfigurationsdatei für den Bootloader der zweiten Stufe <application>aboot</application>(8) von Linux/Alpha.
+</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv>
+ <cmdsynopsis>
+   <command>abootconf</command> <arg choice="plain">/dev/xxx num</arg>
+ </cmdsynopsis>
+</refsynopsisdiv>
+
+<refsect1><title>COPYRIGHT</title>
+<para>
+<application>abootconf</application> unterliegt dem Copyright (C) 1996 Linus Torvalds, David Mosberger-Tang und Michael Schwingen
+</para>
+</refsect1>
+
+<refsect1><title>BESCHREIBUNG</title>
+<para>
+<indexterm><primary>abootconf</primary></indexterm>
+<indexterm><primary>aboot</primary></indexterm>
+<application>abootconf</application> wird zur Änderung der 
+Partition<indexterm><primary>partition</primary></indexterm>, in der der Linux
+Boot-Loader (Urlader) <application>aboot</application>(8) nach seiner
+Konfigurationsdatei schaut, verwendet. Die Konfiguration wird in 
+<filename>etc/aboot.conf</filename>(5) relativ zur Wurzel des Dateisystems
+auf dieser Partition gespeichert.
+</para>
+<para> 
+<application>abootconf</application> benötigt das Boot-Gerät (bspw.
+<filename>/dev/hdb</filename>, <filename>/dev/sda</filename>) und die
+zu verwendende Partition (z.B. 3). Wollen Sie daher von Partition E:
+auf Ihrer zweiten SCSI-Festplatte booten, dann geben Sie</para>
+<para>
+<command>
+abootconf <parameter>/dev/sdb 5</parameter>
+</command>
+</para>
+<para>
+ein.
+</para>
+</refsect1>
+<refsect1><title>HINWEISE</title>
+<para>
+<application>abootconf</application> wird nicht benötigt, wenn Sie Ihr
+alpha-System mittels <application>milo</application> booten.
+</para>
+<para>
+Auf jeder Festplatte kann eine Partition aktiviert werden, die die
+Konfiguration für <application>aboot</application>(8) enthält, welche
+unter <filename>etc/aboot.conf</filename>(5) liegt. Die zu bootende
+Festplatte wird am SRM-Prompt als zweites Argument ausgewählt, also
+beispielsweise
+</para>
+<para>
+<command>
+boot <parameter>dqa</parameter>
+</command>
+</para>
+<para>
+um von der ersten IDE-Festplatte zu booten. Lesen Sie bitte das
+HP SRM-Handbuch und <application>aboot</application>(8) für weitere
+Informationen.
+</para>
+<para>
+<application>aboot</application>(8) kann einen Kernel von einer beliebiegen
+Partition laden und kann soger eine andere Root-Partition verwenden, als die
+zu der <filename>etc/aboot.conf</filename> gehört. Daher sollten Sie
+normalerweise eine <filename>etc/aboot.conf</filename> mit allen Kombinationen
+erstellen und benötigten <application>abootconf</application> außer für
+die Erstinstallation nicht. Sie können dann den gewünschten Linuxkernel über
+die entsprechenden Parameter am SRM-Prompt booten, z.B. um den mit 2
+bezeichneten Eintrag zu booten würden Sie
+</para>
+<para>
+<command>
+boot <parameter>dqa -fl "2"</parameter>
+</command>
+</para>
+<para>
+verwenden. Bitte lesen Sie das HP SRM-Handbuch und 
+<filename>aboot.conf</filename>(5) für weitere Informationen.
+</para>
+<para>
+Um die derzeitigen Einstellungen anzuzeigen, lassen Sie einfach das letzte
+Argument fort (d.h. die Partitionsnummer).
+</para>
+<para>
+Beachten Sie, daß Sie <application>abootconf</application> erneut ausführen
+müssen, wenn Sie <application>aboot</application>(8) aktualisiert haben.
+</para>
+<para>
+Streng genommen wird <application>abootconf</application> nicht benötigt,
+da Sie die Partition, auf der <filename>etc/aboot.conf</filename> liegt
+auf dem SRM-Prompt spezifizieren können, indem Sie den Flags-Parameter mit
+der Partitions-Nummer, gefolgt vom einem Doppelpunkt, einleiten, d.h.
+falls <filename>etc/aboot.conf</filename> auf der vierten Partition liegt
+und Sie den Eintrag mit der Nummer 2 booten wollen, dann könnte Sie am 
+SRM-Prompt auch
+</para>
+<para>
+<command>
+boot <parameter>dqa -fl "4:2"</parameter>
+</command>
+</para>
+<para>
+eingeben.
+</para>
+<para>
+Beachten Sie, daß dies nur auf Linux zutrifft, da 
+<ProductName>VMS</ProductName>, <ProductName>Tru64</ProductName>, *BSD und
+<ProductName>Windows NT</ProductName> jeweils über Ihren eigenen Bootloader
+der zweiten Stufe verfügen. 
+</para>
+<para>
+Beachten Sie desweiteren, daß für das erstmalige Aufsetzen auf der Festplatte
+<application>abootconf</application> ebenfalls nicht mehr benötigt wird, da
+<application>swriteboot</application>(8) über die gesamte Funktionalität
+von <application>abootconf</application> verfügt.
+</para>
+</refsect1>
+<refsect1><title>AUTOR</title>
+<para>
+Diese Handbuchseite wurde von Helge Kreutzmann 
+<email>debian@helgefjell.de</email> für das Debian GNU/Linux-Projekt
+geschrieben, sie darf aber auch von anderen verwendet werden.
+</para>
+</refsect1>
+<refsect1><title>DATEIEN</title>
+<para><filename>etc/aboot.conf</filename></para>
+</refsect1>
+<refsect1><title>SIEHE AUCH</title>
+<para><application>aboot</application>(8), <application>swriteboot</application>(8), <filename>aboot.conf</filename>(5), HP SRM Handbuch (<ULink URL="http://h18002.www1.hp.com/alphaserver/download/srm_reference.pdf"></ULink>)</para>
+</refsect1>
+</refentry>

+ 1304 - 0
package/aboot/src/doc/man/de/docbook2man-de-spec.pl

@@ -0,0 +1,1304 @@
+=head1 NAME
+
+docbook2man-spec - convert DocBook RefEntries to Unix manpages
+
+=head1 SYNOPSIS
+
+The SGMLSpm package from CPAN.  This contains the sgmlspl script which
+is used to grok this file.  Use it like this:
+
+nsgmls some-docbook-document.sgml | sgmlspl sgmlspl-specs/docbook2man-spec.pl
+
+=head1 OPTIONS
+
+=over 4
+
+=item --section <label>
+
+Use the specified manpage section number,
+if not specified in <MANVOLNUM>. Default is one (1).
+
+=item --date <string>
+
+Use the specified date in the .TH header.
+Default is today.
+
+=item --lowercase | --preserve-case
+
+Convert output file names and cross-references to lower case.
+Default is to convert to upper case.
+
+=head1 DESCRIPTION
+
+This is a sgmlspl spec file that produces Unix-style
+manpages from RefEntry markup.
+
+See the accompanying RefEntry man page for 'plain new' documentation. :)
+
+=head1 LIMITATIONS
+
+Trying docbook2man on non-DocBook or non-conformant SGML results in
+undefined behavior. :-)
+
+This program is a slow, dodgy Perl script.
+
+This program does not come close to supporting all the possible markup
+in DocBook, and will produce wrong output in some cases with supported
+markup.
+
+=head1 TODO
+
+Add new element handling and fix existing handling.  Be robust.
+Produce cleanest, readable man output as possible (unlike some
+other converters).  Follow Linux man(7) convention.
+If this results in added logic in this script,
+that's okay.  The code should still be reasonably organized.
+
+Make it faster.  If Perl sucks port it to another language.
+
+=head1 COPYRIGHT
+
+Copyright (C) 1998-1999 Steve Cheng <steve@ggi-project.org>
+
+Copyright (C) 1999 Thomas Lockhart <lockhart@alumni.caltech.edu>
+
+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, or (at your option) any later
+version.
+
+You should have received a copy of the GNU General Public License along with
+this program; see the file COPYING.  If not, please write to the Free
+Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+=cut
+
+# $Id: docbook2man-de-spec.pl,v 1.1 2004/07/05 09:32:10 kreutzm-guest Exp $
+
+use SGMLS;			# Use the SGMLS package.
+use SGMLS::Output;		# Use stack-based output.
+use SGMLS::Refs;
+
+
+########################################################################
+# SGMLSPL script produced automatically by the script sgmlspl.pl
+#
+# Document Type: any, but processes only RefEntries
+# Edited by: me :)
+########################################################################
+
+
+$write_manpages = 0;
+$blank_xrefs = 0;
+
+$default_sect = "1";
+$default_date = `date "+%d %B %Y"`;   # L10N
+
+while (@ARGV) {
+	my $arg = shift @ARGV;
+	if ($arg eq "--section") {
+		$default_sect = shift @ARGV || die "$arg requires an argument\n";   # L10N
+	} elsif ($arg eq "--date") {
+		$default_date = shift @ARGV || die "$arg requires an argument\n";   # L10N
+	} elsif ($arg eq "--lowercase") {
+		$lowercase_names = 1;
+	} elsif ($arg eq "--preserve-case") {
+		$lowercase_names = 0;
+	} elsif ($arg eq "--help") {
+		print "Usage: $0",
+			" [ --section <label> ]",
+			" [ --date <string> ]",
+			" [ --lowercase | --preserve-case ]",
+			"\n";
+		exit;
+	} else {
+		die "unrecognized switch $arg; try $0 --help\n";   # L10N
+	}
+}
+
+sgml('start', sub { 
+	push_output('nul');
+	$raw_cdata = 1;			# Makes it a bit faster.
+	
+	# Links file
+	open(LINKSFILE, ">manpage.links");
+
+	$Refs = new SGMLS::Refs("manpage.refs", "manpage.log");
+});
+sgml('end', sub {
+	close(LINKSFILE);
+
+	# Explicitly invoke destructor,
+	# otherwise cache file may not get written!
+	# Thomas Lockhart, 1999-08-03, perl-5.004, RedHat5.2
+	undef $Refs;
+
+	if($blank_xrefs) {
+		warn "Warning: output contains unresolved XRefs\n";  # L10N
+	}
+});
+
+
+########################################################################
+#
+# Output helpers 
+#
+########################################################################
+
+# Remove leading and trailing blanks.
+
+sub StripString
+{
+	my $str = shift;
+
+	$str = $1 if ($str =~ m#^\s*(\S.*)#);
+	$str = $1 if ($str =~ m#^(.*\S)\s*$#);
+
+	return $str;
+}
+
+# Generate a good file name, for given manpage title and manvolnum
+# (cdata content).
+# Cleanup whitespace and convert to lower case if required.
+
+sub FileInfo
+{
+	my $title = StripString(shift);
+	my $volnum = StripString(shift);
+
+	$title = lc $title if $lowercase_names;
+
+	$title =~ tr/ /_/;
+	$volnum =~ tr/ /_/;
+
+	# The 'package name' part of the section should
+	# not be used when citing it.
+	my $sectcite = $1 if ($volnum =~ /([0-9]*)/);
+	
+	return ("$title.$volnum", "$title($sectcite)");
+}
+
+# Our own version of sgml() and output() to allow simple string output
+# to play well with roff's stupid whitespace rules. 
+
+sub man_sgml
+{
+	if(ref($_[1]) eq 'CODE') {
+		return &sgml;
+	}
+	
+	my $s = $_[1];
+	$s =~ s/\\/\\\\/g;
+	$s =~ s/'/\\'/g;
+
+	sgml($_[0], eval("sub { man_output '$s' }"));
+}
+
+sub man_output
+{
+	if($separator eq 'full') {
+		output "\n" unless $newline_last++;
+		output ".PP\n";
+		$separator = '';
+	}
+	
+	$_ = shift;
+	if(s/^\n//) {
+		output "\n" unless $newline_last++;
+	}
+	return if $_ eq '';
+	
+	output $_;
+
+	if(@_) {
+		output @_;
+		$newline_last = (pop(@_) =~ /\n$/);
+	} else {
+		$newline_last = ($_ =~ /\n$/)
+	}
+}
+
+# Fold lines into one, quote some characters
+sub fold_string
+{
+	$_ = shift;
+	
+	s/\\/\\\\/g;
+	s/"/\\\&"/g;
+
+	# Change tabs and newlines to spaces
+	# The newlines will be swallowed later while trimming
+	tr/[\t\n]/  /;
+
+	# Trim whitespace from beginning and end.
+	s/^ +//;
+	s/ +$//;
+
+	return $_;
+}
+	
+sub save_cdata()
+{
+	$raw_cdata++;
+	push_output('string');
+}
+
+sub bold_on()
+{
+	# If the last font is also bold, don't change anything.
+	# Basically this is to just get more readable man output.
+	if($fontstack[$#fontstack] ne 'bold') {
+		if(!$raw_cdata) {
+			output '\fB';
+			#$newline_last = 0;
+		}
+	}
+	push(@fontstack, 'bold');
+}
+
+sub italic_on()
+{
+	# If the last font is also italic, don't change anything.
+	if($fontstack[$#fontstack] ne 'italic') {
+		if(!$raw_cdata) {
+			output '\fI';
+			#$newline_last = 0;
+		}
+	}
+	push(@fontstack, 'italic');
+}
+
+sub font_off()
+{
+	my $thisfont = pop(@fontstack);
+	my $lastfont = $fontstack[$#fontstack];
+	
+	# Only output font change if it is different
+	if($thisfont ne $lastfont) {
+		if($raw_cdata)			{ return; }
+		elsif($lastfont eq 'bold') 	{ output '\fB'; }
+		elsif($lastfont eq 'italic')	{ output '\fI'; }
+		else				{ output '\fR'; }
+	
+		#$newline_last = 0;
+	}
+}
+
+
+########################################################################
+#
+# Manpage management
+#
+########################################################################
+
+sgml('<REFENTRY>', sub { 
+	# This will be overwritten at end of REFMETA, when we know the name of the page.
+	pop_output();
+	
+	$write_manpages = 1;		# Currently writing manpage.
+	
+	$nocollapse_whitespace = 0;	# Current whitespace collapse counter.
+	$newline_last = 1;		# At beginning of line?
+		# Just a bit of warning, you will see this variable manipulated
+		# manually a lot.  It makes the code harder to follow but it
+		# saves you from having to worry about collapsing at the end of
+		# parse, stopping at verbatims, etc.
+	$raw_cdata = 0;                 # Instructs certain output functions to
+					# leave CDATA alone, so we can assign
+					# it to a string and process it, etc.
+	@fontstack = ();		# Fonts being activated.
+	
+	$list_nestlevel = 0;		# Indent certain nested content.
+
+	# Separator to use between 'elements' in the content of a
+	# paragraph (usually).  This makes sure that PCDATA after a list
+	# in a PARA gets a break in between and not become part of the
+	# last listitem.  Note that we can't do it after the list ends,
+	# because often the list ends the paragraph and we'll get an
+	# extra break.  Anything that changes the separator status from
+	# the default should also save its last state in the parent
+	# element's ext, but I'm not going to explain further.  It's a
+	# gross hack and almost guaranteed to fail in unforseen cases.
+	# The only way to avoid all this is to use a tree/grove model, which
+	# we're _not_ doing.
+	$separator = '';
+	
+	$manpage_title = '';		# Needed for indexing.
+	$manpage_sect = '';
+	@manpage_names = ();
+	
+	$manpage_misc = '';
+});
+sgml('</REFENTRY>', sub {
+	if(!$newline_last) {
+		output "\n";
+	}
+	
+	$raw_cdata = 1;
+	push_output('nul');
+
+	$write_manpages = 0;
+});
+
+sgml('</REFMETA>', sub {
+	my ($filename, $citation) = 
+		FileInfo($manpage_title, $manpage_sect || $default_sect);
+
+	push_output('file', $filename);
+
+	output <<_END_BANNER;
+.\\" This manpage has been automatically generated by docbook2man-spec
+.\\" from a DocBook document.  docbook2man-spec can be found at:
+.\\" <http://shell.ipoline.com/~elmert/hacks/docbook2X/> 
+.\\" Please send any bug reports, improvements, comments, patches, 
+.\\" etc. to Steve Cheng <steve\@ggi-project.org>.
+_END_BANNER
+
+	my $manpage_date = $_[0]->parent->ext->{'date'} || $default_date;
+
+	output '.TH "';
+
+	# If the title is not mixed-case, convention says to
+	# uppercase the whole title.  (The canonical title is
+	# lowercase.)
+	if($manpage_title =~ /[A-Z]/) {
+		output fold_string($manpage_title);
+	} else {
+		output uc(fold_string($manpage_title));
+	}
+	
+	output  '" "', fold_string($manpage_sect), 
+		'" "', fold_string($manpage_date),
+		'" "', $manpage_misc, 
+		'" "', $manpage_manual, 
+		"\"\n";
+
+	$newline_last = 1;
+
+	# References to this RefEntry.
+	if(defined($_[0]->parent->attribute('ID')->value)) {
+		my $id = $_[0]->parent->attribute('ID')->value;
+
+		# Append XREFLABEL content to citations.
+		if(defined($_[0]->parent->attribute('XREFLABEL')->value)) {
+			$citation = $_[0]->parent->attribute('XREFLABEL')->value .
+					' [' . $citation . ']';
+		}
+
+		$Refs->put("refentry:$id", $citation);
+	}
+});
+
+sgml('<REFENTRYTITLE>', sub { 
+	if($_[0]->in('REFMETA')) { 
+		save_cdata();
+	} else { 
+		# Manpage citations are in bold.
+		bold_on();
+	}
+});
+sgml('</REFENTRYTITLE>', sub { 
+	if($_[0]->in('REFMETA')) {
+		$raw_cdata--;
+		$manpage_title = pop_output();
+	}
+	else { font_off(); }
+
+	if (defined($_[0]->attribute('ID')->value)) {
+		my $id = $_[0]->attribute('ID')->value;
+		my ($name, $citation) = FileInfo($manpage_title, $default_sect);
+	
+		$Refs->put("refentrytitle:$id", $citation);
+	}
+});
+
+sgml('<MANVOLNUM>', sub { 
+	if($_[0]->in('REFMETA')) { 
+		save_cdata();	
+	} else {
+		# Manpage citations use ().
+		output '(';
+	}
+});
+sgml('</MANVOLNUM>', sub { 
+	if($_[0]->in('REFMETA')) {
+		$raw_cdata--;
+		$manpage_sect = pop_output();
+	}
+	else { output ')' }
+});
+
+sgml('<REFMISCINFO>', \&save_cdata);
+sgml('</REFMISCINFO>', sub { 
+	$raw_cdata--;
+	$manpage_misc = fold_string(pop_output());
+});
+
+
+# NAME section
+man_sgml('<REFNAMEDIV>', "\n.SH NAME\n");   # L10N
+
+sgml('<REFNAME>', \&save_cdata);
+sgml('</REFNAME>', sub { 
+	$raw_cdata--;
+	push(@manpage_names, pop_output());
+});
+
+sgml('<REFPURPOSE>', \&save_cdata);
+sgml('</REFPURPOSE>', sub { 
+	$raw_cdata--;
+	my $manpage_purpose = fold_string(pop_output());
+	
+	for(my $i = 0; $i < $#manpage_names; $i++) {
+		output fold_string($manpage_names[$i]), ', ';
+	}
+
+	output fold_string($manpage_names[$#manpage_names]);
+	output " \\- $manpage_purpose\n";
+
+	$newline_last = 1;
+
+	foreach(@manpage_names) {
+		# Don't link to itself
+		if($_ ne $manpage_title) {
+			print LINKSFILE "$manpage_title.$manpage_sect	$_.$manpage_sect\n";
+		}
+	}
+});
+	
+man_sgml('<REFCLASS>', "\n.sp\n");
+
+#RefDescriptor
+
+
+########################################################################
+#
+# SYNOPSIS section and synopses
+#
+########################################################################
+
+man_sgml('<REFSYNOPSISDIV>', "\n.SH ÜBERSICHT\n");       # L10N
+man_sgml('</REFSYNOPSISDIV>', "\n");
+
+## FIXME! Must be made into block elements!!
+#sgml('<FUNCSYNOPSIS>', \&bold_on);
+#sgml('</FUNCSYNOPSIS>', \&font_off);
+#sgml('<CMDSYNOPSIS>', \&bold_on);
+#sgml('</CMDSYNOPSIS>', \&font_off);
+
+man_sgml('<FUNCSYNOPSIS>', sub {
+	#man_output("\n.sp\n");
+	bold_on();
+});
+man_sgml('</FUNCSYNOPSIS>', sub {
+	font_off();
+	man_output "\n";
+});
+
+man_sgml('<CMDSYNOPSIS>', "\n.sp\n");
+man_sgml('</CMDSYNOPSIS>', "\n");
+
+man_sgml('<FUNCPROTOTYPE>', "\n.sp\n");
+
+# Arguments to functions.  This is C convention.
+man_sgml('<PARAMDEF>', '(');
+man_sgml('</PARAMDEF>', ");\n");
+man_sgml('<VOID>', "(void);\n");
+
+
+sub arg_start
+{
+	# my $choice = $_[0]->attribute('CHOICE')->value;
+
+	# The content model for CmdSynopsis doesn't include #PCDATA,
+	# so we won't see any of the whitespace in the source file,
+	# so we have to add it after each component.
+	man_output ' ';
+
+	if($_[0]->attribute('CHOICE')->value =~ /opt/i) {
+		man_output '[ ';
+	}
+	bold_on();
+}
+sub arg_end
+{
+	font_off();
+	if($_[0]->attribute('REP')->value =~ /^Repeat/i) {
+		italic_on();
+		man_output '...';
+		font_off();
+	}
+	if($_[0]->attribute('CHOICE')->value =~ /opt/i) {
+		man_output ' ] ';
+	}
+}
+
+sgml('<ARG>', \&arg_start);
+sgml('</ARG>', \&arg_end);
+sgml('<GROUP>', \&arg_start);
+sgml('</GROUP>', \&arg_end);
+
+sgml('<OPTION>', \&bold_on);
+sgml('</OPTION>', \&font_off);
+
+# FIXME: This is one _blank_ line.
+man_sgml('<SBR>', "\n\n");
+
+
+########################################################################
+#
+# General sections
+#
+########################################################################
+
+# The name of the section is handled by TITLE.  This just sets
+# up the roff markup.
+man_sgml('<REFSECT1>', sub { $separator = ''; man_output "\n.SH "});
+man_sgml('<REFSECT2>', sub { $separator = ''; man_output "\n.SS "});
+man_sgml('<REFSECT3>', sub { $separator = ''; man_output "\n.SS "});
+
+
+########################################################################
+#
+# Titles, metadata.
+#
+########################################################################
+
+sgml('<TITLE>', sub {
+	if($_[0]->in('REFERENCE') or $_[0]->in('BOOK')) {
+		$write_manpages = 1;
+	}
+	save_cdata();
+});
+sgml('</TITLE>', sub { 
+	my $title = fold_string(pop_output());
+	$raw_cdata--;
+	
+	if($_[0]->in('REFERENCE') or $_[0]->in('BOOK')) {
+		# We use TITLE of enclosing Reference or Book as manual name
+		$manpage_manual = $title;
+		$write_manpages = 0;
+	}
+	elsif(exists $_[0]->parent->ext->{'title'}) {
+		# By far the easiest case.  Just fold the string as
+		# above, and then set the parent element's variable.
+		$_[0]->parent->ext->{'title'} = $title;
+	}
+	else {
+		# If the parent element's handlers are lazy, 
+		# output the folded string for them :)
+		# We assume they want uppercase and a newline.
+		man_output '"', uc($title), "\"\n";
+	}
+
+	if (defined($_[0]->attribute('ID')->value)) {
+		my $id = $_[0]->attribute('ID')->value;
+		my ($name, $citation) = FileInfo($manpage_title, $default_sect);
+	
+		$Refs->put("title:$id", $citation);
+	}
+});
+
+sgml('<ATTRIBUTION>', sub { 
+	if($_[0]->in('BLOCKQUOTE')) {
+		push_output('string');
+	}
+});
+sgml('</ATTRIBUTION>', sub { 
+	if($_[0]->in('BLOCKQUOTE')) {
+		$_[0]->parent->ext->{'attribution'} = pop_output(); 
+	} else {
+		# For an Epigraph.
+		man_output "\n\n";
+	}
+});
+
+sgml('<DATE>', sub {
+      save_cdata();
+});
+sgml('</DATE>', sub {
+      $_[0]->parent->parent->ext->{'date'} = fold_string(pop_output());
+      $raw_cdata--;
+});
+
+sub ignore_content { push_output 'nul'; }
+sub restore_content { pop_output(); }
+
+sgml('<DOCINFO>', \&ignore_content);
+sgml('</DOCINFO>', \&restore_content);
+sgml('<REFSYNOPSISDIVINFO>', \&ignore_content);
+sgml('</REFSYNOPSISDIVINFO>', \&restore_content);
+sgml('<REFSECT1INFO>', \&ignore_content);
+sgml('</REFSECT1INFO>', \&restore_content);
+sgml('<REFSECT2INFO>', \&ignore_content);
+sgml('</REFSECT2INFO>', \&restore_content);
+sgml('<REFSECT3INFO>', \&ignore_content);
+sgml('</REFSECT3INFO>', \&restore_content);
+
+sgml('<INDEXTERM>', \&ignore_content);
+sgml('</INDEXTERM>', \&restore_content);
+
+sgml('<AUTHORBLURB>', \&ignore_content);
+sgml('</AUTHORBLURB>', \&restore_content);
+
+
+########################################################################
+#
+# Set bold on enclosed content 
+#
+########################################################################
+
+sgml('<APPLICATION>', \&bold_on);
+sgml('</APPLICATION>', \&font_off);
+
+sgml('<CLASSNAME>', \&bold_on);		sgml('</CLASSNAME>', \&font_off);
+sgml('<STRUCTNAME>', \&bold_on);	sgml('</STRUCTNAME>', \&font_off);
+sgml('<STRUCTFIELD>', \&bold_on);	sgml('</STRUCTFIELD>', \&font_off);
+sgml('<SYMBOL>', \&bold_on);		sgml('</SYMBOL>', \&font_off);
+sgml('<TYPE>', \&bold_on);		sgml('</TYPE>', \&font_off);
+
+sgml('<ENVAR>', \&bold_on);	sgml('</ENVAR>', \&font_off);
+
+sgml('<FUNCTION>', \&bold_on);	sgml('</FUNCTION>', \&font_off);
+
+sgml('<EMPHASIS>', \&bold_on);	sgml('</EMPHASIS>', \&font_off);
+
+sgml('<ERRORNAME>', \&bold_on);	sgml('</ERRORNAME>', \&font_off);
+# ERRORTYPE
+
+sgml('<COMMAND>', \&bold_on);	sgml('</COMMAND>', \&font_off);
+
+sgml('<GUIBUTTON>', \&bold_on);	sgml('</GUIBUTTON>', \&font_off);
+sgml('<GUIICON>', \&bold_on);	sgml('</GUIICON>', \&font_off);
+# GUILABEL
+# GUIMENU
+# GUIMENUITEM
+# GUISUBMENU
+# MENUCHOICE
+
+sgml('<ACCEL>', \&bold_on);	sgml('</ACCEL>', \&font_off);
+# KEYCODE
+# SHORTCUT
+
+
+sgml('<KEYCOMBO>', sub {
+	$separator = 'none';
+	$_[0]->ext->{'separator'} = 'none';
+});
+sgml('</KEYCOMBO>', sub { $separator = $_[0]->parent->ext->{'separator'}; });
+
+sub _keycombo {
+	if($_[0]->in('KEYCOMBO')) {
+		if($separator eq 'none') { $separator = '' }
+		else { man_output "+"; }
+	}
+	bold_on();
+}
+sgml('<KEYCAP>', \&_keycombo);	sgml('</KEYCAP>', \&font_off);
+sgml('<KEYSYM>', \&_keycombo);	sgml('</KEYSYM>', \&font_off);
+sgml('<MOUSEBUTTON>', \&_keycombo);	sgml('</MOUSEBUTTON>', \&font_off);
+
+
+sgml('<USERINPUT>', \&bold_on);	sgml('</USERINPUT>', \&font_off);
+
+sgml('<INTERFACEDEFINITION>', \&bold_on);
+sgml('</INTERFACEDEFINITION>', \&font_off);
+
+# May need to look at the CLASS
+sgml('<SYSTEMITEM>', \&bold_on);
+sgml('</SYSTEMITEM>', \&font_off);
+
+
+########################################################################
+#
+# Set italic on enclosed content 
+#
+########################################################################
+
+sgml('<FIRSTTERM>', \&italic_on);	sgml('</FIRSTTERM>', \&font_off);
+
+sgml('<FILENAME>', \&italic_on);	sgml('</FILENAME>', \&font_off);
+sgml('<PARAMETER>', \&italic_on);	sgml('</PARAMETER>', \&font_off);
+sgml('<PROPERTY>', \&italic_on);	sgml('</PROPERTY>', \&font_off);
+
+sgml('<REPLACEABLE>', sub {
+	italic_on();
+	if($_[0]->in('TOKEN')) {
+		# When tokenizing, follow more 'intuitive' convention
+		output "<";
+	}
+});
+sgml('</REPLACEABLE>', sub {
+	if($_[0]->in('TOKEN')) {
+		output ">";
+	}
+	font_off();
+});
+
+sgml('<CITETITLE>', \&italic_on);	sgml('</CITETITLE>', \&font_off);
+sgml('<FOREIGNPHRASE>', \&italic_on);	sgml('</FOREIGNPHRASE>', \&font_off);
+
+sgml('<LINEANNOTATION>', \&italic_on);	sgml('</LINEANNOTATION>', \&font_off);
+
+
+########################################################################
+#
+# Other 'inline' elements 
+#
+########################################################################
+
+man_sgml('<EMAIL>', '<');
+man_sgml('</EMAIL>', '>');
+man_sgml('<OPTIONAL>', '[');
+man_sgml('</OPTIONAL>', ']');
+
+man_sgml('</TRADEMARK>', "\\u\\s-2TM\\s+2\\d");      # L10N
+
+man_sgml('<COMMENT>', "[Kommentar: ");               # L10N
+man_sgml('</COMMENT>', "]");
+
+man_sgml('<QUOTE>', "»");                            # L10N
+man_sgml('</QUOTE>', "«");                           # L10N
+
+#man_sgml('<LITERAL>', '"');
+#man_sgml('</LITERAL>', '"');
+# There doesn't seem to be a good way to represent LITERAL in -man
+# ComputerOutput, SGMLTag, Markup are the same thing.
+
+# These create spaces between content in special elements
+# without PCDATA content.
+man_sgml('</HONORIFIC>', " ");
+man_sgml('</FIRSTNAME>', " ");
+man_sgml('</SURNAME>', " ");
+man_sgml('</LINEAGE>', " ");
+man_sgml('</OTHERNAME>', " ");
+
+man_sgml('<AFFILIATION>', "(");
+man_sgml('</AFFILIATION>', ") ");
+man_sgml('<CONTRIB>', "(");
+man_sgml('</CONTRIB>', ") ");
+
+man_sgml('</STREET>', " ");
+man_sgml('</POB>', " ");
+man_sgml('</POSTCODE>', " ");
+man_sgml('</CITY>', " ");
+man_sgml('</STATE>', " ");
+man_sgml('</COUNTRY>', " ");
+man_sgml('</PHONE>', " ");
+man_sgml('</FAX>', " ");
+man_sgml('</OTHERADDRESS>', " ");
+
+man_sgml('</ALT>', ": ");
+man_sgml('<GRAPHIC>', " [GRAPHIK] ");        # L10N
+
+# No special presentation:
+
+# AUTHORINITIALS
+
+# ABBREV
+# ACTION
+# ACRONYM
+# CITATION
+# PHRASE
+# QUOTE
+# WORDASWORD
+
+# PROMPT
+# RETURNVALUE
+# TOKEN
+
+# DATABASE
+# HARDWARE
+# INTERFACE
+# MEDIALABEL
+
+
+########################################################################
+#
+# Paragraph and paragraph-like elements 
+#
+########################################################################
+
+sub para_start {
+	if($separator eq '' or $separator eq 'full') {
+		$separator = '';
+		man_output "\n.PP\n";
+	} elsif($separator eq 'blank') { 
+		man_output "\n\n";
+	} elsif($separator eq 'none' ) {
+		$_[0]->parent->ext->{'separator'} = 'blank';
+		$separator = 'blank';
+	}
+}
+# Actually applies to a few other block elements as well
+sub para_end {
+	$separator = $_[0]->parent->ext->{'separator'};
+	man_output "\n";
+}
+
+sgml('<PARA>', \&para_start);
+sgml('</PARA>', \&para_end);
+sgml('<SIMPARA>', \&para_start);
+sgml('</SIMPARA>', \&para_end);
+
+# Nothing special, except maybe FIXME set nobreak.
+sgml('<INFORMALEXAMPLE>', \&para_start);
+sgml('</INFORMALEXAMPLE>', \&para_end);
+
+
+########################################################################
+#
+# Blocks using SS sections
+#
+########################################################################
+
+# FIXME: We need to consider the effects of SS
+# in a hanging tag :(
+
+# Complete with the optional-title dilemma (again).
+sgml('<ABSTRACT>', sub {
+	$_[0]->ext->{'title'} = 'ABSTRAKT';      # L10N
+	output "\n" unless $newline_last++;
+	push_output('string');
+});
+sgml('</ABSTRACT>', sub {
+	my $content = pop_output();
+	
+	# As ABSTRACT is never on the same level as RefSect1,
+	# this leaves us with only .SS in terms of -man macros.
+	output ".SS \"", uc($_[0]->ext->{'title'}), "\"\n";
+
+	output $content;
+	output "\n" unless $newline_last++;
+});
+
+
+
+# Ah, I needed a break.  Example always has a title.
+sgml('<EXAMPLE>', sub { $separator = ''; man_output "\n.SS "});
+sgml('</EXAMPLE>', \&para_end);
+
+# Same with sidebar.
+sgml('<SIDEBAR>', sub { $separator = ''; man_output "\n.SS "});
+sgml('</SIDEBAR>', \&para_end);
+
+sgml('<FORMALPARA>', sub { $separator = ''; man_output "\n.SS "});
+sgml('</FORMALPARA>', \&para_end);
+
+sgml('<FIGURE>', sub { $separator = ''; man_output "\n.SS "});
+sgml('</FIGURE>', \&para_end);
+
+
+
+# NO title.               # L10N
+sgml('<HIGHLIGHTS>', sub { $separator = ''; man_output "\n.SS HIGHLIGHTS\n"});
+sgml('</HIGHLIGHTS>', \&para_end);
+
+
+########################################################################
+#
+# Indented 'Block' elements 
+#
+########################################################################
+
+sub indent_block_start
+{
+	$separator = '';
+	man_output "\n.sp\n.RS\n";
+}
+sub indent_block_end
+{
+	$separator = $_[0]->parent->ext->{'separator'};
+	man_output "\n.RE\n.sp\n";
+}
+
+sgml('<ADDRESS>', sub {
+	&indent_block_start;
+	if($_[0]->attribute('FORMAT')->type eq 'NOTATION'
+	   and $_[0]->attribute('FORMAT')->value->name eq 'LINESPECIFIC') {
+		&verbatim_start;
+	}
+});
+sgml('</ADDRESS>', sub {
+	if($_[0]->attribute('FORMAT')->type eq 'NOTATION'
+	   and $_[0]->attribute('FORMAT')->value->name eq 'LINESPECIFIC') {
+		&verbatim_end;
+	}
+	&indent_block_end;
+});
+	
+# This element is almost like an admonition (below),
+# only the default title is blank :)
+
+sgml('<BLOCKQUOTE>', sub { 
+	$_[0]->ext->{'title'} = ''; 
+	&indent_block_start;
+	push_output('string');
+});
+sgml('</BLOCKQUOTE>', sub {
+	my $content = pop_output();
+
+	if($_[0]->ext->{'title'}) {
+		output ".B \"", $_[0]->ext->{'title'}, ":\"\n";
+	}
+	
+	output $content;
+
+	if($_[0]->ext->{'attribution'}) {
+		man_output "\n\n                -- ",
+				$_[0]->ext->{'attribution'}, "\n";
+	}
+	
+	&indent_block_end;
+});
+
+# Set off admonitions from the rest of the text by indenting.
+# FIXME: Need to check if this works inside paragraphs, not enclosing them.
+sub admonition_end {
+	my $content = pop_output();
+
+	# When the admonition is only one paragraph,
+	# it looks nicer if the title was inline.
+	my $num_para;
+	while ($content =~ /^\.PP/gm) { $num_para++ }
+	if($num_para==1) {
+		$content =~ s/^\.PP\n//;
+	}
+	
+	output ".B \"" . $_[0]->ext->{'title'} . ":\"\n";
+	output $content;
+	
+	&indent_block_end;
+}
+
+sgml('<NOTE>', sub {
+	# We can't see right now whether or not there is a TITLE
+	# element, so we have to save the output now and add it back
+	# at the end of this admonition.
+	$_[0]->ext->{'title'} = 'Note';      # L10N
+	
+	&indent_block_start;
+	
+	push_output('string');
+});
+sgml('</NOTE>', \&admonition_end);
+
+# Same as above.
+sgml('<WARNING>', sub { 
+	$_[0]->ext->{'title'} = 'Warnung';       # L10N
+	&indent_block_start;
+	push_output('string');
+});
+sgml('</WARNING>', \&admonition_end);
+
+sgml('<TIP>', sub {
+	$_[0]->ext->{'title'} = 'Tipp';           # L10N
+	&indent_block_start;
+	push_output('string');
+});
+sgml('</TIP>', \&admonition_end);
+sgml('<CAUTION>', sub {
+	$_[0]->ext->{'title'} = 'Caution';        # L10N
+	&indent_block_start;
+	push_output('string');
+});
+sgml('</CAUTION>', \&admonition_end);
+
+sgml('<IMPORTANT>', sub {
+	$_[0]->ext->{'title'} = 'Wichtig';         # L10N
+	&indent_block_start;
+	push_output('string');
+});
+sgml('</IMPORTANT>', \&admonition_end);
+
+
+########################################################################
+#
+# Verbatim displays. 
+#
+########################################################################
+
+sub verbatim_start {
+	$separator = '';
+	man_output "\n.sp\n";
+	man_output "\n.nf\n" unless $nocollapse_whitespace++;
+}
+
+sub verbatim_end {
+	man_output "\n.sp\n";
+	man_output "\n.fi\n" unless --$nocollapse_whitespace;
+	$separator = $_[0]->parent->ext->{'separator'};
+}
+
+sgml('<PROGRAMLISTING>', \&verbatim_start); 
+sgml('</PROGRAMLISTING>', \&verbatim_end);
+
+sgml('<SCREEN>', \&verbatim_start); 
+sgml('</SCREEN>', \&verbatim_end);
+
+sgml('<LITERALLAYOUT>', \&verbatim_start); 
+sgml('</LITERALLAYOUT>', \&verbatim_end);
+
+sgml('<SYNOPSIS>', sub {
+	my $format = $_[0]->attribute('FORMAT');
+
+	if($format->type eq 'NOTATION'
+	   and $format->value->name eq 'LINESPECIFIC')
+	{
+		&verbatim_start;
+	} else {
+		$separator = '';
+		man_output "\n.sp\n";
+	}
+});
+
+sgml('</SYNOPSIS>', sub {
+	my $format = $_[0]->attribute('FORMAT');
+	
+	if($format->type eq 'NOTATION'
+	   and $format->value->name eq 'LINESPECIFIC')
+	{
+		&verbatim_end;
+	} else {
+		man_output "\n";
+		$_[0]->parent->ext->{'separator'} = 'full';
+		$separator = 'full';
+	}
+});
+
+
+########################################################################
+#
+# Lists
+#
+########################################################################
+
+# Indent nested lists.
+sub list_start {
+	man_output "\n.RS\n" if $list_nestlevel++;
+}
+sub list_end {
+	man_output "\n.RE\n" if --$list_nestlevel;
+	$_[0]->parent->ext->{'separator'} = 'full';
+	$separator = 'full';
+}
+
+sgml('<VARIABLELIST>', \&list_start);
+sgml('</VARIABLELIST>', \&list_end);
+sgml('<ITEMIZEDLIST>', \&list_start);
+sgml('</ITEMIZEDLIST>', \&list_end);
+sgml('<ORDEREDLIST>', sub { 
+	&list_start;
+	$_[0]->ext->{'count'} = 1;
+});
+sgml('</ORDEREDLIST>', \&list_end);
+		
+# Output content on one line, bolded.
+sgml('<TERM>', sub { 
+	man_output "\n.TP\n";
+	bold_on();
+	push_output('string');
+});
+sgml('</TERM>', sub { 
+	my $term = StripString(pop_output());
+	$term =~ tr/\n/ /;
+	output $term;
+	font_off();
+	output "\n";
+	$newline_last = 1;
+});
+	
+sgml('<LISTITEM>', sub {
+	# A bulleted list.
+	if($_[0]->in('ITEMIZEDLIST')) {
+		man_output "\n.TP 0.2i\n\\(bu\n";
+	}
+
+	# Need numbers.
+	# Assume Arabic numeration for now.
+	elsif($_[0]->in('ORDEREDLIST')) {
+		man_output "\n.IP ", $_[0]->parent->ext->{'count'}++, ". \n";
+	}
+	
+	$_[0]->ext->{'separator'} = 'none';
+	$separator = 'none';
+});
+
+sgml('<SIMPLELIST>', sub {
+	$_[0]->ext->{'first_member'} = 1;
+});
+sgml('<MEMBER>', sub {
+	my $parent = $_[0]->parent;
+	
+	if($parent->attribute('TYPE')->value =~ /Inline/i) {
+		if($parent->ext->{'first_member'}) {
+			# If this is the first member don't put any commas
+			$parent->ext->{'first_member'} = 0;
+		} else {
+			man_output ", ";
+		}
+
+	# We don't really have Horiz rendering, so it's the same
+	# as Vert.
+	} else {
+		man_output "\n\n";
+	}
+});
+
+# We implement Procedures as indent and lists
+
+sgml('<PROCEDURE>', sub {
+	$_[0]->ext->{'count'} = 1;
+	&indent_block_start;
+});
+sgml('</PROCEDURE>', sub {
+	&indent_block_end;
+	$_[0]->parent->ext->{'separator'} = 'full';
+	$separator = 'full';
+});
+
+sgml('<STEP>', sub {
+	man_output "\n.IP ", $_[0]->parent->ext->{'count'}++, ". \n";
+	$_[0]->ext->{'separator'} = 'none';
+	$separator = 'none';
+});
+
+
+########################################################################
+#
+# Linkage, cross references
+#
+########################################################################
+
+# Print the URL
+sgml('</ULINK>', sub {
+	man_output ' <URL:', $_[0]->attribute('URL')->value, '>';
+});
+
+# If cross reference target is a RefEntry, 
+# output CiteRefEntry-style references.
+sgml('<XREF>', sub {
+	my $id;
+
+	$id = $_[0]->attribute('LINKEND')->value;
+
+	my $manref = $Refs->get("refentry:$id");
+	if(!defined $manref) {
+		$blank_xrefs++ if $write_manpages;
+		man_output "[XRef auf $id]";        # L10N
+		return;
+	}
+
+	# Limited ENDTERM support.
+	if(defined $_[0]->attribute('ENDTERM')->value) {
+		my $content = $Refs->get("title:$id") ||
+				$Refs->get("refentrytitle:$id");
+		man_output $content, ' [';
+	}
+
+	# This also displays the XREFLABEL (as bold)...
+	# It's not worth the bother to fix it though, there
+	# are better tools for this.
+	my ($title, $sect) = ($manref =~ /(.*)(\(.*\))/);
+	bold_on();
+	man_output $title;
+	font_off();
+	man_output $sect;
+
+	if(defined $_[0]->attribute('ENDTERM')->value) {
+		man_output ']';
+	}
+});
+
+# Anchor
+
+
+########################################################################
+#
+# SDATA 
+#
+########################################################################
+
+man_sgml('|[lt    ]|', '<');
+man_sgml('|[gt    ]|', '>');
+man_sgml('|[amp   ]|', '&');
+
+man_sgml('|[ndash ]|', '\(en');
+man_sgml('|[mdash ]|', '\(em');
+
+sgml('sdata',sub { 
+	man_output "|[", $_[0], "]|";
+	warn "Warning: unrecognized SDATA: please add definition to docbook2man-spec.pl\n";   # L10N
+});
+
+#
+# Default handlers (uncomment these if needed).  Right now, these are set
+# up to gag on any unrecognised elements, sdata, processing-instructions,
+# or entities.
+#
+# sgml('start_element',sub { die "Unknown element: " . $_[0]->name; });  # L10N
+# sgml('end_element','');
+
+# This is for weeding out and escaping certain characters.
+# This looks like it's inefficient since it's done on every line, but
+# in reality, SGMLSpm and sgmlspl parsing ESIS takes _much_ longer.
+
+sgml('cdata', sub
+{ 
+	if(!$write_manpages) { return; }
+	elsif($raw_cdata) { output $_[0]; return; }
+
+	if($separator eq 'full') {
+		output "\n" unless $newline_last++;
+		output ".PP\n";
+		$separator = '';
+	}
+	
+	# Escape backslashes
+	$_[0] =~ s/\\/\\\\/g;
+
+	# In non-'pre'-type elements:
+	if(!$nocollapse_whitespace) {
+		# Change tabs to spaces
+		$_[0] =~ tr/\t / /s;
+
+		# Do not allow indents at beginning of line
+		# groff chokes on that.
+		if($newline_last) { 
+			$_[0] =~ s/^ //;
+
+			# If the line is all blank, don't do anything.
+			if($_[0] eq '') { return; }
+			
+			$_[0] =~ s/^\./\\\&\./;
+	
+			# Argh... roff doesn't like ' for some unknown reason 
+			$_[0] =~ s/^\'/\\\&\'/;
+		}
+	}
+
+	$newline_last = 0;
+
+	output $_[0];
+});
+
+
+# When in whitespace-collapsing mode, we disallow consecutive newlines.
+
+sgml('re', sub
+{
+	if($nocollapse_whitespace || !$newline_last) {
+		output "\n";
+	}
+
+	$newline_last = 1;
+});
+
+sgml('pi', sub {});
+sgml('entity',sub { die "Unknown external entity: " . $_[0]->name; });  # L10N
+sgml('start_subdoc',sub { die "Unknown subdoc entity: " . $_[0]->name; });# L10N
+sgml('end_subdoc',sub{});
+sgml('conforming',sub{});
+
+1;
+

+ 45 - 0
package/aboot/src/doc/man/de/e2writeboot.8

@@ -0,0 +1,45 @@
+.\" e2writeboot - Write secondary SRM bootloader to ext2 filesystem.
+.\"
+.\" Translated to German by Helge Kreutzmann <debian@helgefjell.de>
+.TH e2writeboot 8 "27 Juni 2004" "David Mosberger-Tang" ""
+.SH NAME
+e2writeboot \- Schreibt den sekundären Boot-Lader in ein ext2-Dateisystem.
+.SH "ÜBERSICHT"
+\fBe2writeboot\fP <ext2fs> <bootlader>
+.SH BESCHREIBUNG
+
+\fBe2writeboot\fP kann zum Schreiben des sekundären Boot-Laders in ein 
+ext2-formatiertes Dateisystem (normalerweise auf einer Diskette) verwendet
+werden. Der Lader ist so geschrieben, daß die SRM-Firmware von diesem 
+Dateisystem booten kann (SRM ist die Firmware die auch zu Booten von 
+\fBHP Tru64\fP, \fBOpenVMS\fP und *BSD verwendet wird). Insbesondere ist
+der Lader so geschrieben, daß er einen kontinuierlichen Bereich von Sektoren
+belegt und der erste Sektor wird so aktualisiert, daß die SRM-Firmware den
+Boot-Lader finden kann. Der Lader wird immer unter dem Dateinamen 
+\fBlinuxboot\fP gespeichert und falls solch eine Datei bereits existiert, 
+wird diese ohne Rückfrage überschrieben. Dieser Befehl kann fehlschlagen,
+wenn das Dateisystem stark fragmentiert ist. In diesem Fall reformatieren
+Sie das Dateisystem mit \fBmke2fs\fP(8) (dies wird den derzeitigen
+Inhalt des Dateisystems zerstören, daher mit Vorsicht verwenden).
+
+.P
+Das \fI<ext2fs>\fP-Argument spezifiziert das Dateisystem oder spezielle
+Gerät auf das die \fI<bootlader>\fP-Datei geschrieben werden soll. Die
+Boot-Lader-Datei muß eine ECOFF-Objektdatei sein. Ein typischer Befehl,
+um eine Diskette mit dem \fIaboot\fP(8)-Lader zu machen, ist im folgenden
+gezeigt:
+
+.I »e2writeboot /dev/fd0 aboot«
+
+.nf
+.SH SIEHE AUCH
+.IR aboot (8) ,
+.IR mke2fs (8) ,
+.IR swriteboot (8)
+.nf
+.SH AUTOREN
+.nf
+Jim Paradis <paradis@amt.tay1.dec.com>
+Jay Estabrook <Jay.Estabrook@hp.com>
+David Mosberger-Tang <David.Mosberger@acm.org>
+.fi

+ 92 - 0
package/aboot/src/doc/man/de/isomarkboot.sgml

@@ -0,0 +1,92 @@
+<!DOCTYPE RefEntry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+<refentry id="isomarkboot">
+
+<refmeta>
+<refentrytitle>isomarkboot</refentrytitle>
+<manvolnum>1</manvolnum>
+<refmiscinfo>isomarkboot</refmiscinfo>
+</refmeta>
+
+<refnamediv>
+<refname>isomarkboot</refname>
+<refpurpose>
+Erzeugt bootbare CD-ROMs für Linux/Alpha-Systeme.
+</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv>
+ <cmdsynopsis>
+   <command>isomarkboot</command> 
+        <arg choice="plain">/dev/xxx</arg>
+        <arg choice="plain">pfad/zu/bootlx</arg>
+        <arg choice="opt">pfad/zu/root.bin</arg>
+   </cmdsynopsis>
+</refsynopsisdiv>
+
+<refsect1><title>COPYRIGHT</title>
+<para>
+<application>isomarkboot</application> unterliegt dem Copyright (C) 1996 David Mosberger-Tang
+</para>
+</refsect1>
+
+<refsect1><title>BESCHREIBUNG</title>
+<para>
+<indexterm><primary>isomarkboot</primary></indexterm>
+<application>isomarkboot</application>
+befähigt mit <application>mkisofs</application>(8) erstellte oder vom Netz
+heruntergeladene ISO-Images auf Linux/Alpha-Systemen zu booten.
+</para>
+
+<para>
+Zuerst müssen Sie Ihr ISO-Image vorbereiten und über das Loopback-Gerät
+auf <filename>/dev/xxx</filename> (typischerweise 
+<filename>/dev/loop0</filename>) montieren (siehe 
+<application>mount</application>(8) für Details).
+</para>
+
+<para>
+Als nächstes müssen Sie den aboot-Loader (<filename>bootlx</filename> genannt)
+und das RAM-Disk-Image, das das Wurzelverzeichnisdateisystem enthält,
+welches oft <filename>root.bin</filename> heißt, in Ihrem ISO-Image bestimmen.
+Die Angabe letzterm ist optional, aber oft sinnvoll.
+</para>
+<para>
+Schließlich machen Sie das Image bootbar:
+</para>
+<para>
+<command>
+isomarkboot <parameter>/dev/xxx pfad/zu/bootlx pfad/zu/root.bin</parameter>
+</command>
+</para>
+<para>
+Ein typischer Ort für <filename>bootlx</filename> auf dem Disk-Image ist
+<filename>boot/bootlx</filename>. Die Pfade von <filename>bootlx</filename>
+und <filename>root.bin</filename> sind relativ zur Wurzel des Images. Falls
+Ihr Image nicht montiert ist müssen Sie <filename>/dev/xxx</filename> durch
+dem Pfad zu Ihrem Image ersetzen.
+</para>
+
+</refsect1>
+<refsect1><title>FEHLER</title>
+<para>
+<application>isomarkboot</application> ist auf anderen Architekturen
+(außer Alpha) nicht sehr intensiv getestet, obwohl es (mit kleinen Patches)
+dort übersetzt. Bitte berichten Sie uns von Ihren Erfahrungen.
+</para>
+</refsect1>
+<refsect1><title>ANMERKUNGEN</title>
+<para>
+<application>isomarkboot</application> ist in der Lage, Symlinks im Image
+zu verarbeiten.
+</para>
+</refsect1>
+<refsect1><title>AUTOR</title>
+<para>
+Diese Handbuchseite wurde von Helge Kreutzmann <email>debian@helgefjell.de</email> für das Debian GNU/Linux-Projekt geschrieben; sie darf aber auch von
+anderen verwendet werden.
+</refsect1>
+<refsect1><title>SIEHE AUCH</title>
+<para><application>aboot</application>(8), <application>mkisofs</application>(8)
+</para>
+</refsect1>
+</refentry>

+ 107 - 0
package/aboot/src/doc/man/de/netabootwrap.sgml

@@ -0,0 +1,107 @@
+<!DOCTYPE RefEntry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+<refentry id="netabootwrap">
+
+<refmeta>
+<refentrytitle>netabootwrap</refentrytitle>
+<manvolnum>1</manvolnum>
+<refmiscinfo>netabootwrap</refmiscinfo>
+</refmeta>
+
+<refnamediv>
+<refname>netabootwrap</refname>
+<refpurpose>
+erzeugt netzbootbare Images für Linux/Alpha
+</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv>
+ <cmdsynopsis>
+   <command>netabootwrap</command> 
+        <arg choice="opt">-t netboot.img</arg>
+        <arg choice="opt">-k vmlinux.gz</arg>
+	<arg choice="opt">-i initrd.gz</arg>
+	<arg choice="opt">-a "einige Kernelparameter"</arg>
+   </cmdsynopsis>
+</refsynopsisdiv>
+
+<refsect1><title>COPYRIGHT</title>
+<para>
+<application>netabootwrap</application> ist (c) 2000 von Soohoon Lee 
+<email>soohoon.lee@api-networks.com</email>
+</para>
+</refsect1>
+
+<refsect1><title>BESCHREIBUNG</title>
+<para>
+<indexterm><primary>netabootwrap</primary></indexterm>
+<application>netabootwrap</application> fügt <filename>net_aboot</filename>,
+den Kernel und die initrd Images zusammen, um ein netzbootbares Image für
+Linux/Alpha-Systeme zu erstellen.
+<filename>net_aboot.nh</filename> ist nicht funktionstüchtig, aber
+<application>netabootwrap</application> hat die volle Funktionalität.
+Ohne Optionen schaut es nach <filename>vmlinux.gz</filename>
+und baut <filename>netboot.img</filename>, das ist <filename>net_aboot</filename>
++ <filename>vmlinux.gz</filename>.
+</para>
+
+<para>
+<variablelist>
+<varlistentry><term>-t dateiname</term>
+<listitem><para>
+Setzt den Dateinamen des zu erzeugenden Netboot-Images, standardmäßig ist dies
+<filename>netboot.img</filename>. Diese Datei wird überschrieben falls sie
+existiert.
+</para></listitem></varlistentry>
+<varlistentry><term>-k dateiname</term>
+<listitem><para>
+Setzt den Dateinamen des Kernel-Images, standardmäßig ist dies
+<filename>vmlinux.gz</filename>
+</para></listitem></varlistentry>
+<varlistentry><term>-i dateiname</term>
+<listitem><para>
+Setzt den Dateinamen des anfänglichen RAM-Disk-Images, standardmäßig ist dies <filename>initrd.gz</filename>
+</para></listitem></varlistentry>
+<varlistentry><term>-a "einige Kernelparameter"</term>
+<listitem><para>
+Stellt weitere Kerneloptionen bereit, z.B. -a "root=/dev/sda1 single"
+</variablelist>
+</para>
+
+</refsect1>
+
+<!-- <refsect1><title>FEHLER</title>
+<para>
+</para>
+
+</refsect1> -->
+
+<refsect1><title>HINWEISE</title>
+<para>
+Um das Image zu verwenden, benötigen Sie einen
+<application>tftpd</application>(8)- und einen <application>dhcp</application>(8)- 
+oder <application>bootpd</application>(8)-Server.
+Weitere Details finden Sie im SRM-HOWTO:
+(<ULink URL="http://www.alphalinux.org/faq/srm.html"></ULink> oder in
+<filename>/usr/share/doc/aboot/SRM-HOWTO/</filename> auf Debian GNU/Linux-Systemen (und möglicherweise auch anderen))
+</para>
+
+</refsect1>
+
+<refsect1><title>AUTOR</title>
+<para>
+Diese Handbuchseite wurde von Helge Kreutzmann
+<email>debian@helgefjell.de</email> für das Debian GNU/Linux-Projekt geschrieben. Sie darf auch
+von anderen verwendet werden.
+</para>
+</refsect1>
+<refsect1><title>SIEHE AUCH</title>
+<para>
+<application>tftpd</application>(8),
+<application>dhcpd</application>(8),
+<application>bootpd</application>(8),
+<application>aboot</application>(8),
+SRM-HOWTO in <filename>/usr/share/doc/aboot/SRM-HOWTO/</filename> oder <ULink URL="http://www.alphalinux.org/faq/srm.html"></ULink>,
+HP SRM Manual (<ULink URL="http://h18002.www1.hp.com/alphaserver/download/srm_reference.pdf"></ULink>)
+</para>
+</refsect1>
+</refentry>

+ 247 - 0
package/aboot/src/doc/man/de/sdisklabel.sgml

@@ -0,0 +1,247 @@
+<!DOCTYPE RefEntry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+<refentry id="sdisklabel">
+
+<refmeta>
+<refentrytitle>sdisklabel</refentrytitle>
+<manvolnum>8</manvolnum>
+<refmiscinfo>sdisklabel</refmiscinfo>
+</refmeta>
+
+<refnamediv>
+<refname>sdisklabel</refname>
+<refpurpose>
+Erzeugt/verändert Disklabels auf Linux/Alpha-Systemen
+</refpurpose>
+</refnamediv>
+
+<!-- This is the proper SGML way, but somehow doesn't work here -->
+<refsynopsisdiv>
+ <cmdsynopsis>
+   <command>sdisklabel</command>
+     <arg choice="plain">gerät</arg>
+     <group choice="opt"><arg choice="plain">print</arg>
+       <arg choice="plain">zero</arg>
+       <arg choice="plain">sum</arg>
+     </group>
+ </cmdsynopsis>
+ <cmdsynopsis>
+   <command>sdisklabel</command>
+     <arg choice="plain">gerät</arg>
+     <arg choice="plain">size</arg>
+     <arg choice="plain">partitionsgrösse</arg>
+ </cmdsynopsis>
+ <cmdsynopsis>
+   <command>sdisklabel</command>
+     <arg choice="plain">gerät</arg>
+     <arg choice="plain">partnum</arg>
+     <arg choice="plain">offset</arg>
+     <arg choice="plain">größe</arg>
+     <arg choice="plain">parttype</arg>
+ </cmdsynopsis>
+</refsynopsisdiv>
+<!-- <refsect1><title>SYNOPSIS</title>
+<para>sdisklabel <parameter>drive [print|zero|sum]</parameter></para>
+<para>sdisklabel <parameter>drive size partsize</parameter></para>
+<para>sdisklabel <parameter>drive partnum offset size parttype</parameter></para>
+</refsect1> -->
+
+<refsect1><title>COPYRIGHT</title>
+<para>
+<application>sdisklabel</application> unterliegt dem Copyright von Red Hat
+Inc. Der Autor dieser Handbuchseite hat versucht, den Originalautor des
+Programms ausfindig zu machen, was ihm aber nicht gelungen ist. Ein
+abschließender Bugzilla-Eintrag bei Red Hat ergab die folgende Antwort:
+<quote>
+I can't track down a Bob Manson (and I cannot find any record of his association
+with Red Hat in the aboot sources), but any work he did on behalf of Red Hat
+would be property of Red Hat, and you can consider all our changes to be release
+under the GPL the same as the rest of the aboot package.</quote>
+
+</para>
+</refsect1>
+
+<refsect1><title>BESCHREIBUNG</title>
+<para>
+<indexterm><primary>sdisklabel</primary></indexterm>
+<application>sdisklabel</application>
+kann zum Anlegen von Partitionen (genannt Disklabels) auf Linux/Alpha-Systemen
+verwendet werden. Sie <emphasis>müssen</emphasis> Disklabels anstatt des
+<productname>DOS</productname>-artigen Partitionierungsschematas auf jeder
+Festplatte, von der Sie mittels SRM booten, oder welche Sie mit 
+<productname>HP Tru64</productname> gemeinsam nutzen wollen, verwenden.
+Falls Sie stattdessen mit <application>milo</application> booten, dann
+dürfen Sie <emphasis>keine</emphasis> Disklabels auf Ihrer 
+Boot-Festplatte verwenden.
+</para>
+
+<para>
+Selbst wenn Sie Disklabels verwenden, wird der Einsatz von 
+<application>fdisk</application>(8) anstelle von 
+<application>sdisklabel</application> empfohlen.
+</para>
+
+<para>
+<application>sdisklabel</application> nimmt desweiteren an, daß Sie
+eine SCSI-Festplatte mit 512 Byte Sektoren haben, obwohl es auch 
+problemlos auf IDE-Laufwerken arbeiten sollte. Alle Größenangaben werden
+auf der Kommandozeile in Sektoren angegeben.
+</para>
+
+<para>
+Es gibt insgesamt 8 Partitionen, nummeriert von 0 bis 7. Sie entsprechen
+den BSD Disklabels A bis H. Partitionen müssen sequentiell hinzugefügt
+werden, da <application>sdisklabel</application> im Gegensatz zu vielen anderen
+BSD-Disklabel-Programmen keine leeren Partitionen erlaubt. Falls Sie dies
+möchten (oder falls Sie überlappende Disklabels wollen), verwenden Sie
+stattdessen <application>fdisk</application>(8).
+</para>
+
+<para>
+Zuersteinmal, wenn Sie ein ungültiges Disklabel haben (Sie haben
+<application>sdisklabel</application> auf dieser Festplatte nie zuvor
+verwendet), dann müssen Sie
+</para>
+
+<para>
+<command>
+sdisklabel <parameter>/dev/sda zero</parameter>
+</command>
+</para>
+
+<para>
+eingeben (<filename>/dev/sda</filename> ist das Gerät, das Sie
+partitionieren, passen Sie es entsprechend an).
+</para>
+
+<para>
+Dies überschreibt Ihr Disklabel. Verwenden Sie dies nur, wenn Sie das
+Disklabel wirklich überschreiben wollen. Es macht genau das; es fragt
+nicht, oder warnt nicht, oder sonstwas.
+</para>
+
+<para>
+Das Programm hat wahrscheinlich auch die Größe Ihrer Festplatte in kB
+ausgegeben. Falls dies falsch war, können Sie die »<parameter>size 
+xxx</parameter>«-Option zusammen mit den restlichen Kommandos verwenden. 
+Die Größe ist nicht kritisch, sie wird nur verwendet, um zu versuchen, 
+sie am Überschreiten des Endes der Festplatte zu hindern. 
+</para>
+
+<para>
+Als nächstes fügen Sie Ihre erste Partition hinzu. Diese fängt
+<emphasis>nicht</emphasis> bei 0 an, da Sie für den Bootloader und
+anderen Kram Platz lassen müssen. 256 kB (oder 512 Sektoren) sind genug.
+</para>
+
+<para>
+Nehmen wir an, daß Sie eine 250000 kB große Partition, beginnend beim
+Sektor-Offset 512, anlegen wollen:
+</para>
+
+<para>
+<command>
+sdisklabel <parameter>/dev/sda 0 512 500000 8 print</parameter>
+</command>
+</para>
+
+<para>
+Die letzte Zahl ist der Dateisystemtyp, und ist derzeit 8 für ext2fs
+Dateisysteme (Eine andere Zahl würde verwendet, um beispielsweise eine
+<productname>Tru64</productname>-Partition anzugeben).
+</para>
+
+<para>
+Falls alles erfolgreich war, zeigt das Programm die Partition an (das letzte
+Schlüsselwort, »print«, spezifiziert, das es die Partition nach der Veränderung
+mit dem vorhergehenden Befehl anzeigen soll), und Sie sollten etwas ähnlich zu
+</para>
+
+<para>
+<blockquote>
+<literallayout>
+----------------------------------------------------------
+I think your disk is 528870K total size.
+If I'm wrong, override the size with the 'size num' option
+
+partition 0: type 8, starts sector 512, size 500000
+----------------------------------------------------------
+</literallayout>
+</blockquote>
+</para>
+
+<para>
+sehen. Sie können dann die nächste Partition, dies wäre dann Partition 1,
+hinzufügen. Um eine zweite Partition, die 200000 kB lang ist, hinzuzufügen,
+geben Sie 
+</para>
+
+<para>
+<command>
+sdisklabel <parameter>/dev/sda 1 512256 400000 8 print</parameter>
+</command>
+</para>
+<para>
+ein und beide Partitionen würden ausgegeben.
+</para>
+
+<para>
+Falls aus irgendeinem Grund die Größe falsch bestimmt worden wäre, würden
+Sie stattdessen
+</para>
+<para>
+<command>
+sdisklabel <parameter>/dev/sda size 528870 0 512 400000 8 print</parameter>
+</command>
+</para>
+
+<para>
+eingeben. Die »size«-Option sollte direkt dem Gerätenamen folgen, und
+die Größe ist die Gesamtanzahl von Sektoren auf diesem Laufwerk.
+</para>
+
+</refsect1>
+<refsect1><title>FEHLER</title>
+<para>
+<application>sdisklabel</application> prüft nicht auf alle Fehler, bitte
+mit Vorsicht benutzen.
+</para>
+</refsect1>
+<refsect1><title>ANMERKUNGEN</title>
+<para>
+Falls Sie die Festplatte mit <productname>HP Tru64</productname>
+(<productname>OSF/1</productname>) gemeinsam nutzen wollen, wird
+empfohlen, die Partitionierungswerkzeuge von <productname>Tru64</productname> 
+zu verwenden, um die Festplatte vorzubereiten.
+</para>
+<para>
+Um tatsächlich von der frisch markierten Festplatte zu booten müssen Sie
+ebenfalls einen Urlader (boot strap)  installieren, lesen Sie hierzu 
+<application>aboot</application>(8) und <application>swriteboot</application>(8)
+für Einzelheiten.
+</para>
+<para>
+Das »print«-Kommando kann vor oder nach jedem anderen Kommando angegeben werden.
+</para>
+<para>
+Falls Sie leere Partitionen erhalten oder Labels, die über das Ende der
+Festplatte hinausreichen, erstellen wollen (z.B. wenn Sie wissen, daß 
+<application>sdisklabel</application> eine falsche Größe meldet), dann
+können Sie den <parameter>force</parameter>-Schalter auf der Kommandozeile
+verwenden.
+</para>
+</refsect1>
+<refsect1><title>AUTOR</title>
+<para>
+Diese Handbuchseite wurde von Helge Kreutzmann <email>debian@helgefjell.de</email>
+für das Debian GNU/Linux-Projekt geschrieben; Sie kann aber von 
+anderen verwendet werden. Sie basiert wesentlich auf der bei den
+<application>sdisklabel</application>-Quellen mitgelieferten
+<filename>README</filename>-Datei.
+</para>
+</refsect1>
+<refsect1><title>SIEHE AUCH</title>
+<para> 
+<application>fdisk</application>(8), <application>aboot</application>(8), <application>swriteboot</application>(8)
+</para>
+</refsect1>
+</refentry>

+ 86 - 0
package/aboot/src/doc/man/de/srmbootfat.sgml

@@ -0,0 +1,86 @@
+<!DOCTYPE RefEntry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+<refentry id="srmbootfat">
+
+<refmeta>
+<refentrytitle>srmbootfat</refentrytitle>
+<manvolnum>1</manvolnum>
+<refmiscinfo>srmbootfat</refmiscinfo>
+</refmeta>
+
+<refnamediv>
+<refname>srmbootfat</refname>
+<refpurpose>
+Linux/Alpha SRM Boot-Block-Ersteller
+</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv>
+ <cmdsynopsis>
+   <command>srmbootfat</command> 
+        <arg choice="plain">dateisystem_image</arg>
+        <arg choice="plain">boot_datei</arg>
+   </cmdsynopsis>
+</refsynopsisdiv>
+
+<!--  <refsect1><title>COPYRIGHT</title>
+<para>
+</para>
+</refsect1> -->
+
+<refsect1><title>BESCHREIBUNG</title>
+<para>
+<indexterm><primary>srmbootfat</primary></indexterm>
+Dieses Werkzeug ist schnell zusammengestrickt und sollte in seiner
+derzeitigen Form nicht lange existieren.
+</para>
+
+<para>
+<application>Srmbootfat</application> findet die <filename>boot_datei</filename>
+im Wurzelverzeichnis des in der Datei
+<filename>dateisystem_image</filename> gespeicherten
+<acronym>FAT</acronym>-Dateisystems und macht dies bootbar indem es den 
+geeigneten SRM-Boot-Block in diese Dateisystem-Image-Datei schreibt.
+Dies funktioniert nur mit nicht partitionierten Medien (wie beispielsweise
+Disketten), da andernfalls der Boot-Block in die Partitionstabelle geschrieben
+werden müßte, welche sich außerhalb des Dateisystems befindet. Allerdings ist
+eine Festplatte, die ein FAT-Dateisystem enthält, höchstwahrscheinlich mit der
+PC-Partitionstabelle partitioniert, von der SRM sowieso nicht booten kann.
+</para>
+
+<para>
+Der Boot-Lader (<filename>boot_datei</filename>) muß fortlaufend sein, d.h.
+hintereinanderfolgende Blöcke belegen.
+</para>
+</refsect1>
+
+<refsect1><title>ARGUMENTE</title>
+<para>
+<variablelist>
+<varlistentry><term><filename>dateisystem_image</filename></term>
+<listitem><para>
+Der Name der Datei die das FAT-Dateisystem-Image enthält, bspw.
+<filename>/dev/fd0</filename>.
+</para></listitem></varlistentry>
+<varlistentry><term><filename>boot_datei</filename></term>
+<listitem><para>
+Der Dateiname des Boot-Laders.
+</para></listitem></varlistentry>
+</variablelist>
+</refsect1>
+
+<!-- <refsect1><title>FEHLER</title>
+<para>
+</para>
+</refsect1> -->
+
+<refsect1><title>AUTOR</title>
+<para>
+Nikita Schmidt <email>cetus@snowball.ucd.ie</email>
+</para>
+</refsect1>
+<refsect1><title>SIEHE AUCH</title>
+<para>
+<application>aboot</application>(8), <application>mke2fs</application>(8), <application>e2writeboot</application>(8)
+</para>
+</refsect1>
+</refentry>

+ 84 - 0
package/aboot/src/doc/man/de/srmbootraw.sgml

@@ -0,0 +1,84 @@
+<!DOCTYPE RefEntry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+<refentry id="srmbootraw">
+
+<refmeta>
+<refentrytitle>srmbootraw</refentrytitle>
+<manvolnum>8</manvolnum>
+<refmiscinfo>srmbootraw</refmiscinfo>
+</refmeta>
+
+<refnamediv Lang="de">
+<refname>srmbootraw</refname>
+<refpurpose>
+Linux/Alpha SRM Bootblock-Ersteller
+</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv>
+ <cmdsynopsis>
+   <command>srmbootraw</command> 
+        <arg choice="plain">boot_gerät</arg>
+        <arg choice="plain">boot_datei</arg>
+   </cmdsynopsis>
+</refsynopsisdiv>
+
+<!--  <refsect1><title>COPYRIGHT</title>
+<para>
+</para>
+</refsect1> -->
+
+<refsect1><title>BESCHREIBUNG</title>
+<para>
+<indexterm><primary>srmbootraw</primary></indexterm>
+Dieses Werkzeug ist ein schneller Hack und soll in seinem derzeitigen
+Zustand nicht lange exisitieren.
+</para>
+
+<para>
+<application>Srmbootraw</application> schreibt das Image aus
+<filename>boot_datei</filename>
+mit vorangestelltem SRM Bootblock unter Beibehaltung des disklabels
+in die ersten Blocks des <filename>boot_geräts</filename>.
+Es ist dazu gedacht, wenn Sie eine kleine rohe, für den Bootloader
+dedizierte Partition am Anfang Ihrer Festplatte haben. Falls Sie diese
+nicht haben, wird <application>srmbootraw</application> ohne Fehlermeldung
+Ihr System unbenutzbar machen.
+</para>
+</refsect1>
+
+<refsect1><title>ARGUMENTE</title>
+<para>
+<variablelist>
+<varlistentry><term><filename>boot_gerät</filename></term>
+<listitem><para>
+Das Gerät von dem Sie planen zu booten, bspw. <filename>/dev/sda</filename>.
+Es muß genug Platz am Anfang sein, um den Bootblock und den Bootloader 
+aufzunehmen.
+</para></listitem></varlistentry>
+<varlistentry><term><filename>boot_datei</filename></term>
+<listitem><para>
+Der Dateiname des Bootloaders.
+</para></listitem></varlistentry>
+</variablelist>
+</refsect1>
+
+<!-- <refsect1><title>FEHLER</title>
+<para>
+</para>
+</refsect1> -->
+
+<refsect1><title>AUTOR</title>
+<para>
+Nikita Schmidt <email>cetus@snowball.ucd.ie</email>
+</para>
+</refsect1>
+<refsect1><title>SIEHE AUCH</title>
+<para>
+<application>aboot</application>(8), 
+<application>mke2fs</application>(8),
+<application>swriteboot</application>(8),
+<application>e2writeboot</application>(8),
+<application>srmbootfat</application>(1)
+</para>
+</refsect1>
+</refentry>

+ 61 - 0
package/aboot/src/doc/man/de/swriteboot.8

@@ -0,0 +1,61 @@
+.\" sdisklabel - Write secondary SRM bootloader to harddisk
+.\"
+.\" Translated to german by Helge Kreutzmann <debian@helgefjell.de>
+.TH swriteboot 8 "27 Juni 2004" "David Mosberger" ""
+.SH NAME
+swriteboot \- Schreibt sekundären SRM-Boot-Lader auf Festplatte.
+.SH "ÜBERSICHT"
+\fBswriteboot\fP [-v] [-f#] <gerät> <bootlader> [kernel]
+.SH BESCHREIBUNG
+
+\fBswriteboot\fP kann zum Schreiben des sekundären Boot-Laders und --
+optional -- eines Kernels auf die Festplatte verwendet werden. Das
+Ladeprogramm ist so geschrieben, daß es der SRM-Firmware erlaubt, davon
+zu booten (SRM ist die Firmware, die auch zum Booten von \fBHP Tru64\fP,
+\fBOpenVMS\fP und *BSD verwendet wird). Insbesondere ist das Ladeprogramm
+so geschrieben, daß ein physikalisch kontinuierlicher Bereich von Sektoren,
+beginnend bei Sektor 2 belegt wird und das der erste Sektor so aktualisiert
+wird, daß die SRM-Firmware den Boot-Lader finden kann. \fBswriteboot\fP
+kann versagen, falls der Bootstrap-Lader zu groß ist, um in die reservierten
+Sektoren zu passen. Es wird daher empfohlen, die ersten 512 Sektoren
+einer Festplatte für Boot-Zwecke zu reservieren. Dies läßt 256 kB Platz
+für einen sekundären Bootstrap-Lader, was massig ausreichen sollte (derzeit
+ist der \fBaboot\fP(8) Bootstrap-Lader ungefähr 90 kB groß). Reservieren Sie
+mehr, falls Sie dort auch einen Kernel haben wollen - 2 MB sollte in diesem
+Fall ausreichen.
+
+.P
+Das \fI<gerät>\fP-Argument bestimmt das spezielle Gerät auf das die
+\fI<bootlader>\fP-Datei geschrieben werden soll. Die Boot-Lader-Datei
+muß ein »Header-Less«-Image (keine Objekt-Datei) sein, die den rohen
+Inhalt der Text-, Data- und BSS-Sektionen enthält. Ein typisches Kommando
+um SCSI-Platte 0 bootbar mit dem \fIaboot\fP(8)-Lader zu machen wird im
+folgenden gezeigt:
+
+.I »swriteboot /dev/sda bootlx«
+
+.P
+Die \fI-v\fP Option sorgt für etwas ausführlichere Meldungen von
+\fBswriteboot\fP.
+.P
+Die \fI-f#\fP Option teilt \fBswriteboot\fP mit, einen Überlapp des Bootbereichs
+mit der Partition \fI#\fP zu ignorieren.
+.P
+Die \fI-c#\fP Option teilt \fBswriteboot\fP explizit die Boot-Partition mit.
+Falls dieses Argument fehlt, versucht \fBswriteboot\fP falls möglich die
+Boot-Partition automatisch zu erkennen. Beachten Sie, daß Sie die 
+Boot-Partition später ebenfalls mit \fBabootconf\fP(8) setzten können.
+
+.nf
+.SH SIEHE AUCH
+.IR aboot (8) ,
+.IR abootconf (8) ,
+.IR mke2fs (8) ,
+.IR e2writeboot (8)
+.nf
+.SH AUTOREN
+.nf
+Bob Manson <manson@magnus.acs.ohio-state.edu>
+Michael Schwingen <michael@schwingen.org>
+Helge Kreutzmann <debian@helgefjell.de> (Aktualisierung der Handbuchseite)
+.fi

+ 42 - 0
package/aboot/src/doc/man/e2writeboot.8

@@ -0,0 +1,42 @@
+.\" e2writeboot - Write secondary SRM bootloader to ext2 filesystem.
+.TH e2writeboot 8 "17 January 1995" "David Mosberger-Tang" ""
+.SH NAME
+e2writeboot \- Write secondary SRM bootloader to ext2 filesystem.
+.SH SYNOPSIS
+\fBe2writeboot\fP <ext2fs> <bootloader>
+.SH DESCRIPTION
+
+\fBe2writeboot\fP can be used to write a secondary bootstrap loader to
+an ext2 formatted filesystem (normally on a floppy disk).  The loader
+is written in a way that allows the SRM firmware to boot from the
+filesystem (SRM is the firmware that is also used to boot
+\fBHP Tru64\fP, \fBOpenVMS\fP and *BSD).  Specifically, the
+loader is written to occupy a physically
+contiguous range of sectors and the first sector is updated such that
+the SRM firmware can find the boot loader.  The loader is always
+stored with filename \fBlinuxboot\fP and if such a file already
+exists, it will be overwritten unconditionally.  This command may
+fail if the filesystem is highly fragmented.  If so, re-format the
+filesystem with \fBmke2fs\fP(8) (this will destroy the existing contents
+of the filesystem, so use this with care).
+
+.P
+The \fI<ext2fs>\fP argument specifies the filesystem or special device
+to which the \fI<bootloader>\fP file should be written to.  The boot
+loader file must be an ECOFF object file.  A typical command to make a
+floppy disk bootable with the \fIaboot\fP(8) loader is shown below:
+
+.I "e2writeboot /dev/fd0 aboot"
+
+.nf
+.SH SEE ALSO
+.IR aboot (8) ,
+.IR mke2fs (8) ,
+.IR swriteboot (8)
+.nf
+.SH AUTHORS
+.nf
+Jim Paradis <paradis@amt.tay1.dec.com>
+Jay Estabrook <Jay.Estabrook@hp.com>
+David Mosberger-Tang <David.Mosberger@acm.org>
+.fi

+ 58 - 0
package/aboot/src/doc/man/isomarkboot.8

@@ -0,0 +1,58 @@
+.\" This manpage has been automatically generated by docbook2man-spec
+.\" from a DocBook document.  docbook2man-spec can be found at:
+.\" <http://shell.ipoline.com/~elmert/hacks/docbook2X/> 
+.\" Please send any bug reports, improvements, comments, patches, 
+.\" etc. to Steve Cheng <steve@ggi-project.org>.
+.TH "ISOMARKBOOT" "8" "17 Januar 2003" "isomarkboot" ""
+.SH NAME
+isomarkboot \- Create bootable CD-ROMs for Linux/Alpha systems.
+.SH SYNOPSIS
+.sp
+\fBisomarkboot\fR \fB/dev/xxx\fR \fBpath/to/bootlx\fR [ \fBpath/to/root.bin\fR ] 
+.SH "COPYRIGHT"
+.PP
+\fBisomarkboot\fR is Copyright (C) 1996 David Mosberger-Tang
+.SH "DESCRIPTIONS"
+.PP
+
+\fBisomarkboot\fR
+enables ISO images created with \fBmkisofs\fR(8) or
+retrieved from the net
+to be booted on Linux/Alpha systems.
+.PP
+First you have to prepare your ISO image and mount it loopback on
+\fI/dev/xxx\fR (typically \fI/dev/loop0\fR)
+(see \fBmount\fR(8) for details). 
+.PP
+Next you need to locate the aboot-loader (called \fIbootlx\fR)
+and the ram disk image containing the root file system (the latter is optional
+but usually sensible to specify) which is often called 
+\fIroot.bin\fR within your ISO image.
+.PP
+Finally enable the image to be booted:
+.PP
+\fBisomarkboot \fI/dev/xxx path/to/bootlx path/to/root.bin\fB\fR
+.PP
+A typical location of \fIbootlx\fR on the disk image is
+\fIboot/bootlx\fR. The path of \fIbootlx\fR
+and \fIroot.bin\fR are relative to the root of the image. If
+your image is not mounted you have to replace \fI/dev/xxx\fR
+with the path to the image.
+.PP
+Finally you have to burn the CD using e.g.
+\fBxcdroast\fR after unmounting the image.
+.SH "BUGS"
+.PP
+\fBisomarkboot\fR is currently only available on 
+Linux/Alpha systems though it can be compiled and used with minor
+modifications on other platforms as well.
+.SH "NOTES"
+.PP
+\fBisomarkboot\fR is capable of handling symlinks
+within the image.
+.SH "AUTHOR"
+.PP
+This man page was written by Helge Kreutzmann <kreutzm@itp.uni-hannover.de> for the Debian GNU/Linux project but may be used by others.
+.SH "SEE ALSO"
+.PP
+\fBaboot\fR(8), \fBmkisofs\fR(8)

+ 97 - 0
package/aboot/src/doc/man/isomarkboot.sgml

@@ -0,0 +1,97 @@
+<!DOCTYPE RefEntry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+<refentry id="isomarkboot">
+
+<refmeta>
+<refentrytitle>isomarkboot</refentrytitle>
+<manvolnum>1</manvolnum>
+<refmiscinfo>isomarkboot</refmiscinfo>
+</refmeta>
+
+<refnamediv>
+<refname>isomarkboot</refname>
+<refpurpose>
+Create bootable CD-ROMs for Linux/Alpha systems.
+</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv>
+ <cmdsynopsis>
+   <command>isomarkboot</command> 
+        <arg choice="plain">/dev/xxx</arg>
+        <arg choice="plain">path/to/bootlx</arg>
+        <arg choice="opt">path/to/root.bin</arg>
+   </cmdsynopsis>
+</refsynopsisdiv>
+
+<refsect1><title>COPYRIGHT</title>
+<para>
+<application>isomarkboot</application> is Copyright (C) 1996 David Mosberger-Tang
+</para>
+</refsect1>
+
+<refsect1><title>DESCRIPTIONS</title>
+<para>
+<indexterm><primary>isomarkboot</primary></indexterm>
+<application>isomarkboot</application>
+enables ISO images created with <application>mkisofs</application>(8) or
+retrieved from the net
+to be booted on Linux/Alpha systems.
+</para>
+
+<para>
+First you have to prepare your ISO image and mount it loopback on
+<filename>/dev/xxx</filename> (typically <filename>/dev/loop0</filename>)
+(see <application>mount</application>(8) for details). 
+</para>
+
+<para>
+Next you need to locate the aboot-loader (called <filename>bootlx</filename>)
+and the RAM-disk image containing the root file system (the latter is optional
+but usually sensible to specify) which is often called 
+<filename>root.bin</filename> within your ISO image.
+</para>
+<para>
+Finally enable the image to be booted:
+</para>
+<para>
+<command>
+isomarkboot <parameter>/dev/xxx path/to/bootlx path/to/root.bin</parameter>
+</command>
+</para>
+<para>
+A typical location of <filename>bootlx</filename> on the disk image is
+<filename>boot/bootlx</filename>. The paths of <filename>bootlx</filename>
+and <filename>root.bin</filename> are relative to the root of the image. If
+your image is not mounted you have to replace <filename>/dev/xxx</filename>
+with the path to the image.
+</para>
+
+<para>
+Finally you have to burn the CD using e.g.
+<application>xcdroast</application> after unmounting the image.
+</para>
+
+</refsect1>
+<refsect1><title>BUGS</title>
+<para>
+<application>isomarkboot</application> is not heavily tested on
+architectures other than Linux/Alpha, though it compiles (with
+slight patches). Please report bugs if you experience them.
+</para>
+</refsect1>
+<refsect1><title>NOTES</title>
+<para>
+<application>isomarkboot</application> is capable of handling symlinks
+within the image.
+</para>
+</refsect1>
+<refsect1><title>AUTHOR</title>
+<para>
+This man page was written by Helge Kreutzmann <email>debian@helgefjell.de</email> for the Debian GNU/Linux project but may be used by others.
+</para>
+</refsect1>
+<refsect1><title>SEE ALSO</title>
+<para><application>aboot</application>(8), <application>mkisofs</application>(8)
+</para>
+</refsect1>
+</refentry>

+ 102 - 0
package/aboot/src/doc/man/netabootwrap.sgml

@@ -0,0 +1,102 @@
+<!DOCTYPE RefEntry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+<refentry id="netabootwrap">
+
+<refmeta>
+<refentrytitle>netabootwrap</refentrytitle>
+<manvolnum>1</manvolnum>
+<refmiscinfo>netabootwrap</refmiscinfo>
+</refmeta>
+
+<refnamediv>
+<refname>netabootwrap</refname>
+<refpurpose>
+builds network bootable images for Linux/Alpha
+</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv>
+ <cmdsynopsis>
+   <command>netabootwrap</command> 
+        <arg choice="opt">-t netboot.img</arg>
+        <arg choice="opt">-k vmlinux.gz</arg>
+	<arg choice="opt">-i initrd.gz</arg>
+	<arg choice="opt">-a "some kernel parameters"</arg>
+   </cmdsynopsis>
+</refsynopsisdiv>
+
+<refsect1><title>COPYRIGHT</title>
+<para>
+<application>netabootwrap</application> is (c) 2000 by  Soohoon Lee 
+<email>soohoon.lee@api-networks.com</email>
+</para>
+</refsect1>
+
+<refsect1><title>DESCRIPTIONS</title>
+<para>
+<indexterm><primary>netabootwrap</primary></indexterm>
+<application>netabootwrap</application> merges <filename>net_aboot</filename>,
+kernel and initrd
+images to build the network bootable image for Linux/Alpha systems.
+<filename>net_aboot.nh</filename> will not be usable but 
+<application>netabootwrap</application> has all
+the functions.  Without options, It'll look for <filename>vmlinux.gz</filename>
+and build <filename>netboot.img</filename>, which is <filename>net_aboot</filename>
++ <filename>vmlinux.gz</filename>.
+</para>
+
+<para>
+<variablelist>
+<varlistentry><term>-t filename</term>
+<listitem><para>
+Sets the file name of the netboot image to be created, default is <filename>netboot.img</filename>. This file will be unconditionally overwritten if it exists.
+</para></listitem></varlistentry>
+<varlistentry><term>-k filename</term>
+<listitem><para>
+Sets the file name of the kernel image, default is <filename>vmlinux.gz</filename>
+</para></listitem></varlistentry>
+<varlistentry><term>-i filename</term>
+<listitem><para>
+Sets the file name of the initial RAM-disk image, default is <filename>initrd.gz</filename>
+</para></listitem></varlistentry>
+<varlistentry><term>-a "some kernel options"</term>
+<listitem><para>
+Provide additional kernel options, e.g. -a "root=/dev/sda1 single"
+</variablelist>
+</para>
+
+</refsect1>
+
+<!-- <refsect1><title>BUGS</title>
+<para>
+</para>
+
+</refsect1> -->
+
+<refsect1><title>NOTES</title>
+<para>
+To actually use the image, you need a <application>tftpd</application>(8) server and a
+<application>dhcp</application>(8) or <application>bootpd</application>(8)
+server. You can find further details in the SRM-HOWTO: 
+(<ULink URL="http://www.alphalinux.org/faq/srm.html"></ULink> or in
+<filename>/usr/share/doc/aboot/SRM-HOWTO/</filename> on Debian GNU/Linux
+systems (and possibly others))
+</para>
+
+</refsect1>
+
+<refsect1><title>AUTHOR</title>
+<para>
+This man page was written by Helge Kreutzmann <email>debian@helgefjell.de</email> for the Debian GNU/Linux project but may be used by others.
+</para>
+</refsect1>
+<refsect1><title>SEE ALSO</title>
+<para>
+<application>tftpd</application>(8),
+<application>dhcpd</application>(8),
+<application>bootpd</application>(8),
+<application>aboot</application>(8),
+SRM-HOWTO in <filename>/usr/share/doc/aboot/SRM-HOWTO/</filename> or <ULink URL="http://www.alphalinux.org/faq/srm.html"></ULink>,
+HP SRM Manual (<ULink URL="http://h18002.www1.hp.com/alphaserver/download/srm_reference.pdf"></ULink>)
+</para>
+</refsect1>
+</refentry>

+ 152 - 0
package/aboot/src/doc/man/sdisklabel.8

@@ -0,0 +1,152 @@
+.\" This manpage has been automatically generated by docbook2man-spec
+.\" from a DocBook document.  docbook2man-spec can be found at:
+.\" <http://shell.ipoline.com/~elmert/hacks/docbook2X/> 
+.\" Please send any bug reports, improvements, comments, patches, 
+.\" etc. to Steve Cheng <steve@ggi-project.org>.
+.TH "SDISKLABEL" "8" "23 November 2003" "sdisklabel" ""
+.SH NAME
+sdisklabel \- Create/modify disklabels on Linux/Alpha systems
+.SH SYNOPSIS
+.sp
+\fBsdisklabel\fR \fBdrive\fR [ \fB print zero sum\fR ] 
+.sp
+\fBsdisklabel\fR \fBdrive\fR \fBsize\fR \fBpartsize\fR
+.sp
+\fBsdisklabel\fR \fBdrive\fR \fBpartnum\fR \fBoffset\fR \fBsize\fR \fBparttype\fR
+.SH "COPYRIGHT"
+.PP
+\fBsdisklabel\fR is Copyright (C) by Red Hat Inc. The
+author of this man page tried to track down the original author, but was
+unable to do so. A final Bugzilla entry with RedHat yielded the following
+reply:
+``I can't track down a Bob Manson (and I cannot find any record of his association
+with Red Hat in the aboot sources), but any work he did on behalf of Red Hat
+would be property of Red Hat, and you can consider all our changes to be release
+under the GPL the same as the rest of the aboot package.''
+.SH "DESCRIPTIONS"
+.PP
+
+\fBsdisklabel\fR
+can be used to create partitions (called disklabels) on Linux/Alpha
+systems. You \fBmust\fR use disklabels instead of the
+DOS type
+partitioning scheme on any hard disk which you want to boot from via SRM or
+which you want to share with HP Tru64.
+If you instead are booting from \fBmilo\fR
+then you \fBmust not\fR use disklabels on your boot hard disk.
+.PP
+Even if you are using disklabels, it is recommended to use 
+\fBfdisk\fR(8) instead
+of \fBsdisklabel\fR.
+.PP
+\fBsdisklabel\fR also assumes 
+you have a SCSI disk with 512-byte sectors,
+though it should work fine on an IDE drive as well. All sizes are
+specified on the command line in sectors.
+.PP
+There are 8 partitions in total which are numbered from 0 to 7. They
+correspond to BSD disklabels A to H.
+Partitions have to be added sequentially, as 
+\fBsdisklabel\fR won't let
+you leave empty partitions unlike many BSD disklabel programs. If you
+want this (or if you want overlapping disk labels) 
+use \fBfdisk\fR(8) instead.
+.PP
+First off, if you have an invalid disk label (you've never run 
+\fBsdisklabel\fR on this disk
+before) you have to issue
+.PP
+\fBsdisklabel \fI/dev/sda zero\fB\fR
+.PP
+(\fI/dev/sda\fR is the device you're partitioning, 
+substitute as appropriate).
+.PP
+This zeros out your disk label. Only do this if you really want to
+zero your disk label. It just does it; it doesn't ask, or warn, or
+anything.
+.PP
+The program also probably printed out the size of your disk in kb. If
+it was wrong, you now get to use the "\fIsize xxx\fR"
+option along with the
+rest of these commands. The size isn't critical, it's just used to try
+and make sure you don't go past the end of the disk.
+.PP
+Next, add your first partition. This \fBdoesn't\fR
+start from 0, as you
+have to leave room for the boot loader and other stuff. 256K (or 512
+sectors) will be enough.
+.PP
+Let's pretend that you want to make a 250000 kb partition starting
+from sector offset 512:
+.PP
+\fBsdisklabel \fI/dev/sda 0 512 500000 8 print\fB\fR
+.PP
+The last number is the filesystem type, and is currently 8 for ext2fs
+filesystems. (A different number would be used to specify an
+Tru64
+partition, for example).
+.PP
+If all was successful, the program should print out the partition (the
+last keyword, "print", specifies that it should print the partition
+after modifying it with the previous command), and you should see
+something like
+.PP
+.sp
+.RS
+.sp
+.nf
+----------------------------------------------------------
+I think your disk is 528870K total size.
+If I'm wrong, override the size with the 'size num' option
+
+partition 0: type 8, starts sector 512, size 500000
+----------------------------------------------------------
+.sp
+.fi
+.RE
+.sp
+.PP
+You can then add the next partition, which would be partition 1.
+To add a second partition that is 200000 kb long, you'd run
+.PP
+\fBsdisklabel \fI/dev/sda 1 512256 400000 8 print\fB\fR
+.PP
+And both partitions would then be printed out.
+.PP
+If for some reason the size got determined incorrectly, you'd do
+instead
+.PP
+\fBsdisklabel \fI/dev/sda size 528870 0 512 400000 8 print\fB\fR
+.PP
+The size option should come immediately after the device name, and the
+size is the total # of sectors on the drive.
+.SH "BUGS"
+.PP
+\fBsdisklabel\fR does not check for all errors, so
+use with care.
+.SH "NOTES"
+.PP
+If you want to share the disk with HP Tru64
+(OSF/1) it is recommended to
+use the Tru64 
+partitioning tools to prepare the disk.
+.PP
+To actually boot from the freshly labeled disk you also need to install
+a boot strap as well, see
+\fBaboot\fR(8) and \fBswriteboot\fR(8)
+for details.
+.PP
+The print command may be placed before or after any other command.
+.PP
+In case you do want to leave empty partitions or create labels which
+extend beyond the end of the disk (e.g. when you know 
+\fBsdisklabel\fR is reporting a wrong size) then
+use can use the \fIforce\fR switch on the command line.
+.SH "AUTHOR"
+.PP
+This man page was written by Helge Kreutzmann <kreutzm@itp.uni-hannover.de> for the Debian GNU/Linux project but may be used by others. It is
+heavily based on the \fIREADME\fR provided along with the
+\fBsdisklabel\fR source.
+.SH "SEE ALSO"
+.PP
+\fBfdisk\fR(8), \fBaboot\fR(8), \fBswriteboot\fR(8)

+ 32 - 0
package/aboot/src/doc/man/sdisklabel.copyright

@@ -0,0 +1,32 @@
+The author is unkown, it is not David Mosberger-Tang, Jim Paradies, Michael Schwingen
+or Jay Estabrook. I could not locate Bob Manson. An entry in RedHat's bugzilla
+yielded the following notice which I reproduce verbatim here:
+
+https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=71437
+
+--- shadow/71437        Tue Aug 13 13:22:49 2002
++++ shadow/71437.tmp.9824       Thu Aug 15 21:23:45 2002
+@@ -3,8 +3,8 @@
+ Version: 7.1
+ Platform: alpha
+ OS/Version: Linux
+-Status: NEW
+-Resolution:
++Status: CLOSED
++Resolution: WORKSFORME
+ Severity: normal
+ Priority: normal
+ Component: aboot
+@@ -45,3 +45,9 @@
+
+ The reason is that I'd like to know the copyright and I am wrinting the
+ man pages (which can be included in the next RH/Alpha release as well).
+
++------- Additional comments from sopwith@redhat.com 2002-08-15 21:31:59 -------
++I can't track down a Bob Manson (and I cannot find any record of his association
++with Red Hat in the aboot sources), but any work he did on behalf of Red Hat
++would be property of Red Hat, and you can consider all our changes to be release
++under the GPL the same as the rest of the aboot package.
+
+
+Helge Kreutzmann <debian@helgefjell.de>, September 4th 2002

+ 246 - 0
package/aboot/src/doc/man/sdisklabel.sgml

@@ -0,0 +1,246 @@
+<!DOCTYPE RefEntry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+<refentry id="sdisklabel">
+
+<refmeta>
+<refentrytitle>sdisklabel</refentrytitle>
+<manvolnum>8</manvolnum>
+<refmiscinfo>sdisklabel</refmiscinfo>
+</refmeta>
+
+<refnamediv>
+<refname>sdisklabel</refname>
+<refpurpose>
+Create/modify disklabels on Linux/Alpha systems
+</refpurpose>
+</refnamediv>
+
+<!-- This is the proper SGML way, but somehow doesn't work here -->
+<refsynopsisdiv>
+ <cmdsynopsis>
+   <command>sdisklabel</command>
+     <arg choice="plain">device</arg>
+     <group choice="opt"><arg choice="plain">print</arg>
+       <arg choice="plain">zero</arg>
+       <arg choice="plain">sum</arg>
+     </group>
+ </cmdsynopsis>
+ <cmdsynopsis>
+   <command>sdisklabel</command>
+     <arg choice="plain">device</arg>
+     <arg choice="plain">size</arg>
+     <arg choice="plain">partsize</arg>
+ </cmdsynopsis>
+ <cmdsynopsis>
+   <command>sdisklabel</command>
+     <arg choice="plain">device</arg>
+     <arg choice="plain">partnum</arg>
+     <arg choice="plain">offset</arg>
+     <arg choice="plain">size</arg>
+     <arg choice="plain">parttype</arg>
+ </cmdsynopsis>
+</refsynopsisdiv>
+<!-- <refsect1><title>SYNOPSIS</title>
+<para>sdisklabel <parameter>drive [print|zero|sum]</parameter></para>
+<para>sdisklabel <parameter>drive size partsize</parameter></para>
+<para>sdisklabel <parameter>drive partnum offset size parttype</parameter></para>
+</refsect1> -->
+
+<refsect1><title>COPYRIGHT</title>
+<para>
+<application>sdisklabel</application> is Copyright (C) by Red Hat Inc. The
+author of this man page tried to track down the original author, but was
+unable to do so. A final Bugzilla entry with RedHat yielded the following
+reply:
+<quote>
+I can't track down a Bob Manson (and I cannot find any record of his association
+with Red Hat in the aboot sources), but any work he did on behalf of Red Hat
+would be property of Red Hat, and you can consider all our changes to be release
+under the GPL the same as the rest of the aboot package.</quote>
+
+</para>
+</refsect1>
+
+<refsect1><title>DESCRIPTIONS</title>
+<para>
+<indexterm><primary>sdisklabel</primary></indexterm>
+<application>sdisklabel</application>
+can be used to create partitions (called disklabels) on Linux/Alpha
+systems. You <emphasis>must</emphasis> use disklabels instead of the
+<productname>DOS</productname> type
+partitioning scheme on any hard disk which you want to boot from via SRM or
+which you want to share with <productname>HP Tru64</productname>.
+If you instead are booting from <application>milo</application>
+then you <emphasis>must not</emphasis> use disklabels on your boot hard disk.
+</para>
+
+<para>
+Even if you are using disklabels, it is recommended to use 
+<application>fdisk</application>(8) instead
+of <application>sdisklabel</application>.
+</para>
+
+<para>
+<application>sdisklabel</application> also assumes 
+you have a SCSI disk with 512-byte sectors,
+though it should work fine on an IDE drive as well.  All sizes are
+specified on the command line in sectors.
+</para>
+
+<para>
+There are 8 partitions in total which are numbered from 0 to 7. They
+correspond to BSD disklabels A to H.
+Partitions have to be added sequentially, as 
+<application>sdisklabel</application> won't let
+you leave empty partitions unlike many BSD disklabel programs. If you
+want this (or if you want overlapping disk labels) 
+use <application>fdisk</application>(8) instead.
+</para>
+
+<para>
+First off, if you have an invalid disk label (you've never run 
+<application>sdisklabel</application> on this disk
+before) you have to issue
+</para>
+
+<para>
+<command>
+sdisklabel <parameter>/dev/sda zero</parameter>
+</command>
+</para>
+
+<para>
+(<filename>/dev/sda</filename> is the device you're partitioning, 
+substitute as appropriate).
+</para>
+
+<para>
+This zeros out your disk label. Only do this if you really want to
+zero your disk label. It just does it; it doesn't ask, or warn, or
+anything.
+</para>
+
+<para>
+The program also probably printed out the size of your disk in kb. If
+it was wrong, you now get to use the "<parameter>size xxx</parameter>"
+option along with the
+rest of these commands. The size isn't critical, it's just used to try
+and make sure you don't go past the end of the disk.
+</para>
+
+<para>
+Next, add your first partition. This <emphasis>doesn't</emphasis>
+start from 0, as you
+have to leave room for the boot loader and other stuff. 256K (or 512
+sectors) will be enough.
+</para>
+
+<para>
+Let's pretend that you want to make a 250000 kb partition starting
+from sector offset 512:
+</para>
+
+<para>
+<command>
+sdisklabel <parameter>/dev/sda 0 512 500000 8 print</parameter>
+</command>
+</para>
+
+<para>
+The last number is the filesystem type, and is currently 8 for ext2fs
+filesystems. (A different number would be used to specify an
+<productname>Tru64</productname>
+partition, for example).
+</para>
+
+<para>
+If all was successful, the program should print out the partition (the
+last keyword, "print", specifies that it should print the partition
+after modifying it with the previous command), and you should see
+something like
+</para>
+
+<para>
+<blockquote>
+<literallayout>
+----------------------------------------------------------
+I think your disk is 528870K total size.
+If I'm wrong, override the size with the 'size num' option
+
+partition 0: type 8, starts sector 512, size 500000
+----------------------------------------------------------
+</literallayout>
+</blockquote>
+</para>
+
+<para>
+You can then add the next partition, which would be partition 1.
+To add a second partition that is 200000 kb long, you'd run
+</para>
+
+<para>
+<command>
+sdisklabel <parameter>/dev/sda 1 512256 400000 8 print</parameter>
+</command>
+</para>
+<para>
+And both partitions would then be printed out.
+</para>
+
+<para>
+If for some reason the size got determined incorrectly, you'd do
+instead
+</para>
+<para>
+<command>
+sdisklabel <parameter>/dev/sda size 528870 0 512 400000 8 print</parameter>
+</command>
+</para>
+
+<para>
+The size option should come immediately after the device name, and the
+size is the total # of sectors on the drive.
+</para>
+
+</refsect1>
+<refsect1><title>BUGS</title>
+<para>
+<application>sdisklabel</application> does not check for all errors, so
+use with care.
+</para>
+</refsect1>
+<refsect1><title>NOTES</title>
+<para>
+If you want to share the disk with <productname>HP Tru64</productname>
+(<productname>OSF/1</productname>) it is recommended to
+use the <productname>Tru64</productname> 
+partitioning tools to prepare the disk.
+</para>
+<para>
+To actually boot from the freshly labeled disk you also need to install
+a boot strap as well, see
+<application>aboot</application>(8) and <application>swriteboot</application>(8)
+for details.
+</para>
+<para>
+The print command may be placed before or after any other command.
+</para>
+<para>
+In case you do want to leave empty partitions or create labels which
+extend beyond the end of the disk (e.g., when you know 
+<application>sdisklabel</application> is reporting a wrong size) then
+use can use the <parameter>force</parameter> switch on the command line.
+</para>
+</refsect1>
+<refsect1><title>AUTHOR</title>
+<para>
+This man page was written by Helge Kreutzmann <email>debian@helgefjell.de</email> for the Debian GNU/Linux project but may be used by others. It is
+heavily based on the <filename>README</filename> provided along with the
+<application>sdisklabel</application> source.
+</para>
+</refsect1>
+<refsect1><title>SEE ALSO</title>
+<para> 
+<application>fdisk</application>(8), <application>aboot</application>(8), <application>swriteboot</application>(8)
+</para>
+</refsect1>
+</refentry>

+ 58 - 0
package/aboot/src/doc/man/swriteboot.8

@@ -0,0 +1,58 @@
+.\" sdisklabel - Write secondary SRM bootloader to harddisk
+.TH swriteboot 8 "17 January 1995" "David Mosberger" ""
+.SH NAME
+swriteboot \- Write secondary SRM bootloader to harddisk.
+.SH SYNOPSIS
+\fBswriteboot\fP [-v] [-f#] <dev> <bootloader> [kernel]
+.SH DESCRIPTION
+
+\fBswriteboot\fP can be used to write a secondary bootstrap loader
+and - optionally - a kernel to
+a harddisk.  The loader is written in a way that allows the SRM
+firmware to boot from that disk (SRM is the firmware that is also used
+to boot \fBHP Tru64\fP, \fBOpenVMS\fP and *BSD).
+Specifically, the loader is written to occupy
+a physically contiguous range of sectors starting at sector 2 and the
+first sector is updated such that the SRM firmware can find the boot
+loader.  \fBswriteboot\fP may fail if the bootstrap loader is too big
+to fit into the sectors reserved for boot purposes.  It is therefore
+suggested to reserve the first 512 sectors of a harddisk for boot
+purposes.  This will leave 256 kB of space for a secondary bootstrap
+loader which should be plenty (currently, the \fBaboot\fP(8) bootstrap
+loader is about 90 kB large). Use more if you want to have a kernel in this
+area, too - 2 MB should be sufficient in this case.
+
+.P
+The \fI<dev>\fP argument specifies the special device to which the
+\fI<bootloader>\fP file should be written to.  The boot loader file
+must be a header-less image (not an object file) containing the raw
+contents of the text, data, and bss sections.  A typical command to
+make SCSI disk 0 bootable with the \fIaboot\fP(8) loader is shown
+below:
+
+.I "swriteboot /dev/sda bootlx"
+
+.P
+The \fI-v\fP option makes \fBswriteboot\fP be a bit more verbose.
+.P
+The \fI-f#\fP option tells \fBswriteboot\fP to ignore an overlap of the boot area with
+partition \fI#\fP.
+.P
+The \fI-c#\fP option explicitly tells \fBswriteboot\fP the boot partition.
+If this argument is missing, then \fBswriteboot\fP tries to autodetect the
+boot partition if possible. Note that you can set the boot partition later
+on with \fBabootconf\fP(8) as well.
+
+.nf
+.SH SEE ALSO
+.IR aboot (8) ,
+.IR abootconf (8) ,
+.IR mke2fs (8) ,
+.IR e2writeboot (8)
+.nf
+.SH AUTHORS
+.nf
+Bob Manson <manson@magnus.acs.ohio-state.edu>
+Michael Schwingen <michael@schwingen.org>
+Helge Kreutzmann <debian@helgefjell.de> (Update of man page)
+.fi

+ 80 - 0
package/aboot/src/fs/dummy.c

@@ -0,0 +1,80 @@
+/*
+ * This is a set of functions that provides access to a Linux kernel
+ * starting at sector BOOT_SECT+aboot_size/SECT_SIZE
+ *
+ * Michael Schwingen (rincewind@discworld.oche.de).
+ */
+#include "system.h"
+
+#include <config.h>
+#include <aboot.h>
+#include <bootfs.h>
+#include <cons.h>
+#include <utils.h>
+
+#define BLOCKSIZE (16*SECT_SIZE)
+
+static int dummy_mount(long cons_dev, long p_offset, long quiet);
+static int dummy_bread(int fd, long blkno, long nblks, char *buffer);
+static int dummy_open(const char *filename);
+static void dummy_close(int fd);
+
+struct bootfs dummyfs = {
+	0, BLOCKSIZE,
+	dummy_mount,
+	dummy_open,  dummy_bread,  dummy_close
+};
+
+static long dev = -1;
+
+
+/*
+ * Initialize 'filesystem' 
+ * Returns 0 if successful, -1 on failure.
+ */
+static int
+dummy_mount(long cons_dev, long p_offset, long quiet)
+{
+	dev = cons_dev;
+	return 0;
+}
+
+
+/*
+ * Read block number "blkno".
+ */
+static int
+dummy_bread(int fd, long blkno, long nblks, char *buffer)
+{
+	extern char _end;
+	static long aboot_size = 0;
+
+	if (!aboot_size) {
+		aboot_size = &_end - (char *) BOOT_ADDR + SECT_SIZE - 1;
+		aboot_size &= ~(SECT_SIZE - 1);
+	}
+
+	if (cons_read(dev, buffer, nblks*BLOCKSIZE, 
+		      BOOT_SECTOR*SECT_SIZE + blkno*BLOCKSIZE + aboot_size)
+	    != nblks*BLOCKSIZE)
+	{
+		printf("dummy_bread: read error\n");
+		return -1;
+	}
+	return nblks*BLOCKSIZE;
+}
+
+
+/*
+ * Unix-like open routine.  Returns a small integer 
+ * (does not care what file, we say it's OK)
+ */
+static int dummy_open(const char *filename)
+{
+	return 1;
+}
+
+
+static void dummy_close(int fd)
+{
+}

+ 623 - 0
package/aboot/src/fs/ext2.c

@@ -0,0 +1,623 @@
+/*
+ * This is a set of functions that provides minimal filesystem
+ * functionality to the Linux bootstrapper.  All we can do is
+ * open and read files... but that's all we need 8-)
+ *
+ * This file has been ported from the DEC 32-bit Linux version
+ * by David Mosberger (davidm@cs.arizona.edu).
+ */
+#include <linux/stat.h>
+#include <linux/types.h>
+#include <linux/version.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
+
+#  undef __KERNEL__
+#  include <linux/ext2_fs.h>
+#  define __KERNEL__
+#  include <linux/fs.h>
+
+#else /* Linux 2.4.0 or later */
+
+typedef unsigned short umode_t;
+#  undef __KERNEL__
+#  include <linux/ext2_fs.h>
+#  include <linux/fs.h>
+#  define __KERNEL__
+
+#endif
+
+#include "bootfs.h"
+#include "cons.h"
+#include "disklabel.h"
+#include "utils.h"
+#include "string.h"
+
+#define MAX_OPEN_FILES		5
+
+extern struct bootfs ext2fs;
+
+static struct ext2_super_block sb;
+static struct ext2_group_desc *gds;
+static struct ext2_inode *root_inode = NULL;
+static int ngroups = 0;
+static int directlim;			/* Maximum direct blkno */
+static int ind1lim;			/* Maximum single-indir blkno */
+static int ind2lim;			/* Maximum double-indir blkno */
+static int ptrs_per_blk;		/* ptrs/indirect block */
+static char blkbuf[EXT2_MAX_BLOCK_SIZE];
+static int cached_iblkno = -1;
+static char iblkbuf[EXT2_MAX_BLOCK_SIZE];
+static int cached_diblkno = -1;
+static char diblkbuf[EXT2_MAX_BLOCK_SIZE];
+static long dev = -1;
+static long partition_offset;
+
+static struct inode_table_entry {
+	struct	ext2_inode	inode;
+	int			inumber;
+	int			free;
+	unsigned short		old_mode;
+} inode_table[MAX_OPEN_FILES];
+
+
+/*
+ * Initialize an ext2 partition starting at offset P_OFFSET; this is
+ * sort-of the same idea as "mounting" it.  Read in the relevant
+ * control structures and make them available to the user.  Returns 0
+ * if successful, -1 on failure.
+ */
+static int ext2_mount(long cons_dev, long p_offset, long quiet)
+{
+	long sb_block = 1;
+	long sb_offset;
+	int i;
+
+	dev = cons_dev;
+	partition_offset = p_offset;
+
+	/* initialize the inode table */
+	for (i = 0; i < MAX_OPEN_FILES; i++) {
+		inode_table[i].free = 1;
+		inode_table[i].inumber = 0;
+	}
+	/* clear the root inode pointer (very important!) */
+	root_inode = NULL;
+	
+	/* read in the first superblock */
+	sb_offset = sb_block * EXT2_MIN_BLOCK_SIZE;
+	if (cons_read(dev, &sb, sizeof(sb), partition_offset + sb_offset)
+	    != sizeof(sb))
+	{
+		printf("ext2 sb read failed\n");
+		return -1;
+	}
+	
+	if (sb.s_magic != EXT2_SUPER_MAGIC) {
+		if (!quiet) {
+			printf("ext2_init: bad magic 0x%x\n", sb.s_magic);
+		}
+		return -1;
+	}
+
+	ngroups = (sb.s_blocks_count -
+		   sb.s_first_data_block +
+		   EXT2_BLOCKS_PER_GROUP(&sb) - 1)
+		/ EXT2_BLOCKS_PER_GROUP(&sb);
+
+	gds = (struct ext2_group_desc *)
+	          malloc((size_t)(ngroups * sizeof(struct ext2_group_desc)));
+
+	ext2fs.blocksize = EXT2_BLOCK_SIZE(&sb);
+
+	/* read in the group descriptors (immediately follows superblock) */
+	cons_read(dev, gds, ngroups * sizeof(struct ext2_group_desc),
+		  partition_offset +
+                  ext2fs.blocksize * (EXT2_MIN_BLOCK_SIZE/ext2fs.blocksize + 1));
+	/*
+	 * Calculate direct/indirect block limits for this file system
+	 * (blocksize dependent):
+	 */
+	ext2fs.blocksize = EXT2_BLOCK_SIZE(&sb);
+	directlim = EXT2_NDIR_BLOCKS - 1;
+	ptrs_per_blk = ext2fs.blocksize/sizeof(unsigned int);
+	ind1lim = ptrs_per_blk + directlim;
+	ind2lim = (ptrs_per_blk * ptrs_per_blk) + directlim;
+
+	return 0;
+}
+
+
+/*
+ * Read the specified inode from the disk and return it to the user.
+ * Returns NULL if the inode can't be read...
+ */
+static struct ext2_inode *ext2_iget(int ino)
+{
+	int i;
+	struct ext2_inode *ip;
+	struct inode_table_entry *itp = 0;
+	int group;
+	long offset;
+
+	ip = 0;
+	for (i = 0; i < MAX_OPEN_FILES; i++) {
+#ifdef DEBUG_EXT2
+		printf("ext2_iget: looping, entry %d inode %d free %d\n",
+		       i, inode_table[i].inumber, inode_table[i].free);
+#endif
+		if (inode_table[i].free) {
+			itp = &inode_table[i];
+			ip = &itp->inode;
+			break;
+		}
+	}
+	if (!ip) {
+		printf("ext2_iget: no free inodes\n");
+		return NULL;
+	}
+
+	group = (ino-1) / sb.s_inodes_per_group;
+#ifdef DEBUG_EXT2
+	printf("group is %d\n", group);
+#endif
+	offset = partition_offset
+		+ ((long) gds[group].bg_inode_table * (long)ext2fs.blocksize)
+		+ (((ino - 1) % EXT2_INODES_PER_GROUP(&sb))
+		   * EXT2_INODE_SIZE(&sb));
+#ifdef DEBUG_EXT2
+	printf("ext2_iget: reading %ld bytes at offset %ld "
+	       "(%ld + (%d * %d) + ((%d) %% %d) * %d) "
+	       "(inode %d -> table %d)\n", 
+	       sizeof(struct ext2_inode), offset, partition_offset,
+	       gds[group].bg_inode_table, ext2fs.blocksize,
+	       ino - 1, EXT2_INODES_PER_GROUP(&sb), EXT2_INODE_SIZE(&sb),
+	       ino, (int) (itp - inode_table));
+#endif
+	if (cons_read(dev, ip, sizeof(struct ext2_inode), offset) 
+	    != sizeof(struct ext2_inode))
+	{
+		printf("ext2_iget: read error\n");
+		return NULL;
+	}
+
+	itp->free = 0;
+	itp->inumber = ino;
+	itp->old_mode = ip->i_mode;
+
+	return ip;
+}
+
+
+/*
+ * Release our hold on an inode.  Since this is a read-only application,
+ * don't worry about putting back any changes...
+ */
+static void ext2_iput(struct ext2_inode *ip)
+{
+	struct inode_table_entry *itp;
+
+	/* Find and free the inode table slot we used... */
+	itp = (struct inode_table_entry *)ip;
+
+#ifdef DEBUG_EXT2
+	printf("ext2_iput: inode %d table %d\n", itp->inumber,
+	       (int) (itp - inode_table));
+#endif
+	itp->inumber = 0;
+	itp->free = 1;
+}
+
+
+/*
+ * Map a block offset into a file into an absolute block number.
+ * (traverse the indirect blocks if necessary).  Note: Double-indirect
+ * blocks allow us to map over 64Mb on a 1k file system.  Therefore, for
+ * our purposes, we will NOT bother with triple indirect blocks.
+ *
+ * The "allocate" argument is set if we want to *allocate* a block
+ * and we don't already have one allocated.
+ */
+static int ext2_blkno(struct ext2_inode *ip, int blkoff)
+{
+	unsigned int *lp;
+	unsigned int *ilp;
+	unsigned int *dlp;
+	int blkno;
+	int iblkno;
+	int diblkno;
+	unsigned long offset;
+
+	ilp = (unsigned int *)iblkbuf;
+	dlp = (unsigned int *)diblkbuf;
+	lp = (unsigned int *)blkbuf;
+
+	/* If it's a direct block, it's easy! */
+	if (blkoff <= directlim) {
+		return ip->i_block[blkoff];
+	}
+
+	/* Is it a single-indirect? */
+	if (blkoff <= ind1lim) {
+		iblkno = ip->i_block[EXT2_IND_BLOCK];
+
+		if (iblkno == 0) {
+			return 0;
+		}
+
+		/* Read the indirect block */
+		if (cached_iblkno != iblkno) {
+			offset = partition_offset + (long)iblkno * (long)ext2fs.blocksize;
+			if (cons_read(dev, iblkbuf, ext2fs.blocksize, offset)
+			    != ext2fs.blocksize)
+			{
+				printf("ext2_blkno: error on iblk read\n");
+				return 0;
+			}
+			cached_iblkno = iblkno;
+		}
+
+		blkno = ilp[blkoff-(directlim+1)];
+		return blkno;
+	}
+
+	/* Is it a double-indirect? */
+	if (blkoff <= ind2lim) {
+		/* Find the double-indirect block */
+		diblkno = ip->i_block[EXT2_DIND_BLOCK];
+
+		if (diblkno == 0) {
+			return 0;
+		}
+
+		/* Read in the double-indirect block */
+		if (cached_diblkno != diblkno) {
+			offset = partition_offset + (long) diblkno * (long) ext2fs.blocksize;
+			if (cons_read(dev, diblkbuf, ext2fs.blocksize, offset)
+			    != ext2fs.blocksize)
+			{
+				printf("ext2_blkno: err reading dindr blk\n");
+				return 0;
+			}
+			cached_diblkno = diblkno;
+		}
+
+		/* Find the single-indirect block pointer ... */
+		iblkno = dlp[(blkoff - (ind1lim+1)) / ptrs_per_blk];
+
+		if (iblkno == 0) {
+			return 0;
+		}
+
+		/* Read the indirect block */
+    
+		if (cached_iblkno != iblkno) {
+			offset = partition_offset + (long) iblkno * (long) ext2fs.blocksize;
+			if (cons_read(dev, iblkbuf, ext2fs.blocksize, offset)
+			    != ext2fs.blocksize)
+			{
+				printf("ext2_blkno: err on iblk read\n");
+				return 0;
+			}
+			cached_iblkno = iblkno;
+		}
+
+		/* Find the block itself. */
+		blkno = ilp[(blkoff-(ind1lim+1)) % ptrs_per_blk];
+		return blkno;
+	}
+
+	if (blkoff > ind2lim) {
+		printf("ext2_blkno: block number too large: %d\n", blkoff);
+		return 0;
+	}
+	return -1;
+}
+
+
+static int ext2_breadi(struct ext2_inode *ip, long blkno, long nblks,
+		       char *buffer)
+{
+	long dev_blkno, ncontig, offset, nbytes, tot_bytes;
+
+	tot_bytes = 0;
+	if ((blkno+nblks)*ext2fs.blocksize > ip->i_size)
+		nblks = (ip->i_size + ext2fs.blocksize) / ext2fs.blocksize - blkno;
+
+	while (nblks) {
+		/*
+		 * Contiguous reads are a lot faster, so we try to group
+		 * as many blocks as possible:
+		 */
+		ncontig = 0; nbytes = 0;
+		dev_blkno = ext2_blkno(ip, blkno);
+		do {
+			++blkno; ++ncontig; --nblks;
+			nbytes += ext2fs.blocksize;
+		} while (nblks &&
+			 ext2_blkno(ip, blkno) == dev_blkno + ncontig);
+
+		if (dev_blkno == 0) {
+			/* This is a "hole" */
+			memset(buffer, 0, nbytes);
+		} else {
+			/* Read it for real */
+			offset = partition_offset + (long) dev_blkno* (long) ext2fs.blocksize;
+#ifdef DEBUG_EXT2
+			printf("ext2_bread: reading %ld bytes at offset %ld\n",
+			       nbytes, offset);
+#endif
+			if (cons_read(dev, buffer, nbytes, offset)
+			    != nbytes)
+			{
+				printf("ext2_bread: read error\n");
+				return -1;
+			}
+		}
+		buffer    += nbytes;
+		tot_bytes += nbytes;
+	}
+	return tot_bytes;
+}
+
+static struct ext2_dir_entry_2 *ext2_readdiri(struct ext2_inode *dir_inode,
+					      int rewind)
+{
+	struct ext2_dir_entry_2 *dp;
+	static int diroffset = 0, blockoffset = 0;
+
+	/* Reading a different directory, invalidate previous state */
+	if (rewind) {
+		diroffset = 0;
+		blockoffset = 0;
+		/* read first block */
+		if (ext2_breadi(dir_inode, 0, 1, blkbuf) < 0)
+			return NULL;
+	}
+
+#ifdef DEBUG_EXT2
+	printf("ext2_readdiri: blkoffset %d diroffset %d len %d\n",
+		blockoffset, diroffset, dir_inode->i_size);
+#endif
+	if (blockoffset >= ext2fs.blocksize) {
+		diroffset += ext2fs.blocksize;
+		if (diroffset >= dir_inode->i_size)
+			return NULL;
+#ifdef DEBUG_EXT2
+		printf("ext2_readdiri: reading block at %d\n",
+			diroffset);
+#endif
+		/* assume that this will read the whole block */
+		if (ext2_breadi(dir_inode,
+				diroffset / ext2fs.blocksize,
+				1, blkbuf) < 0)
+			return NULL;
+		blockoffset = 0;
+	}
+
+	dp = (struct ext2_dir_entry_2 *) (blkbuf + blockoffset);
+	blockoffset += dp->rec_len;
+#ifdef DEBUG_EXT2
+	printf("ext2_readdiri: returning %p = %.*s\n", dp, dp->name_len, dp->name);
+#endif
+	return dp;
+}
+
+static struct ext2_inode *ext2_namei(const char *name)
+{
+	char namebuf[256];
+	char *component;
+	struct ext2_inode *dir_inode;
+	struct ext2_dir_entry_2 *dp;
+	int next_ino;
+
+	/* squirrel away a copy of "namebuf" that we can modify: */
+	strcpy(namebuf, name);
+
+	/* start at the root: */
+	if (!root_inode)
+		root_inode = ext2_iget(EXT2_ROOT_INO);
+	dir_inode = root_inode;
+	if (!dir_inode)
+	  return NULL;
+
+	component = strtok(namebuf, "/");
+	while (component) {
+		int component_length;
+		int rewind = 0;
+		/*
+		 * Search for the specified component in the current
+		 * directory inode.
+		 */
+		next_ino = -1;
+		component_length = strlen(component);
+
+		/* rewind the first time through */
+		while ((dp = ext2_readdiri(dir_inode, !rewind++))) {
+			if ((dp->name_len == component_length) &&
+			    (strncmp(component, dp->name,
+				     component_length) == 0))
+			{
+				/* Found it! */
+#ifdef DEBUG_EXT2
+				printf("ext2_namei: found entry %s\n",
+					component);
+#endif
+				next_ino = dp->inode;
+				break;
+			}
+#ifdef DEBUG_EXT2
+			printf("ext2_namei: looping\n");
+#endif
+		}
+	
+#ifdef DEBUG_EXT2
+		printf("ext2_namei: next_ino = %d\n", next_ino);
+#endif
+
+		/*
+		 * At this point, we're done with this directory whether
+		 * we've succeeded or failed...
+		 */
+		if (dir_inode != root_inode)
+			ext2_iput(dir_inode);
+
+		/*
+		 * If next_ino is negative, then we've failed (gone
+		 * all the way through without finding anything)
+		 */
+		if (next_ino < 0) {
+			return NULL;
+		}
+
+		/*
+		 * Otherwise, we can get this inode and find the next
+		 * component string...
+		 */
+		dir_inode = ext2_iget(next_ino);
+		if (!dir_inode)
+		  return NULL;
+
+		component = strtok(NULL, "/");
+	}
+
+	/*
+	 * If we get here, then we got through all the components.
+	 * Whatever we got must match up with the last one.
+	 */
+	return dir_inode;
+}
+
+
+/*
+ * Read block number "blkno" from the specified file.
+ */
+static int ext2_bread(int fd, long blkno, long nblks, char *buffer)
+{
+	struct ext2_inode * ip;
+	ip = &inode_table[fd].inode;
+	return ext2_breadi(ip, blkno, nblks, buffer);
+}
+
+/*
+ * Note: don't mix any kind of file lookup or other I/O with this or
+ * you will lose horribly (as it reuses blkbuf)
+ */
+static const char * ext2_readdir(int fd, int rewind)
+{
+	struct ext2_inode * ip = &inode_table[fd].inode;
+	struct ext2_dir_entry_2 * ent;
+	if (!S_ISDIR(ip->i_mode)) {
+		printf("fd %d (inode %d) is not a directory (mode %x)\n",
+		       fd, inode_table[fd].inumber, ip->i_mode);
+		return NULL;
+	}
+	ent = ext2_readdiri(ip, rewind);
+	if (ent) {
+		ent->name[ent->name_len] = '\0';
+		return ent->name;
+	} else { 
+		return NULL;
+	}
+}
+
+static int ext2_fstat(int fd, struct stat* buf)
+{
+	struct ext2_inode * ip = &inode_table[fd].inode;
+
+	if (fd >= MAX_OPEN_FILES)
+		return -1;
+	memset(buf, 0, sizeof(struct stat));
+	/* fill in relevant fields */
+	buf->st_ino = inode_table[fd].inumber;
+	buf->st_mode = ip->i_mode;
+	buf->st_flags = ip->i_flags;
+	buf->st_nlink = ip->i_links_count;
+	buf->st_uid = ip->i_uid;
+	buf->st_gid = ip->i_gid;
+	buf->st_size = ip->i_size;
+	buf->st_blocks = ip->i_blocks;
+	buf->st_atime = ip->i_atime;
+	buf->st_mtime = ip->i_mtime;
+	buf->st_ctime = ip->i_ctime;
+
+	return 0; /* NOTHING CAN GO WROGN! */
+}
+
+static struct ext2_inode * ext2_follow_link(struct ext2_inode * from,
+					    const char * base)
+{
+	char *linkto;
+
+	if (from->i_blocks) {
+		linkto = blkbuf;
+		if (ext2_breadi(from, 0, 1, blkbuf) == -1)
+			return NULL;
+#ifdef DEBUG_EXT2
+		printf("long link!\n");
+#endif
+	} else {
+		linkto = (char*)from->i_block;
+	}
+#ifdef DEBUG_EXT2
+	printf("symlink to %s\n", linkto);
+#endif
+
+	/* Resolve relative links */
+	if (linkto[0] != '/') {
+		char *end = strrchr(base, '/');
+		if (end) {
+			char fullname[(end - base + 1) + strlen(linkto) + 1];
+			strncpy(fullname, base, end - base + 1);
+			fullname[end - base + 1] = '\0';
+			strcat(fullname, linkto);
+#ifdef DEBUG_EXT2
+			printf("resolved to %s\n", fullname);
+#endif
+			return ext2_namei(fullname);
+		} else {
+			/* Assume it's in the root */
+			return ext2_namei(linkto);
+		}
+	} else {
+		return ext2_namei(linkto);
+	}
+}
+
+static int ext2_open(const char *filename)
+{
+	/*
+	 * Unix-like open routine.  Returns a small integer (actually
+	 * an index into the inode table...
+	 */
+	struct ext2_inode * ip;
+
+	ip = ext2_namei(filename);
+	if (ip) {
+		struct inode_table_entry *itp;
+
+		while (S_ISLNK(ip->i_mode)) {
+			ip = ext2_follow_link(ip, filename);
+			if (!ip) return -1;
+		}
+		itp = (struct inode_table_entry *)ip;
+		return itp - inode_table;
+	} else
+		return -1;
+}
+
+
+static void ext2_close(int fd)
+{
+	/* blah, hack, don't close the root inode ever */
+	if (&inode_table[fd].inode != root_inode)
+		ext2_iput(&inode_table[fd].inode);
+}
+
+
+struct bootfs ext2fs = {
+	FS_EXT2, 0,
+	ext2_mount,
+	ext2_open,  ext2_bread,  ext2_close,
+	ext2_readdir, ext2_fstat
+};

+ 59 - 0
package/aboot/src/fs/iso.c

@@ -0,0 +1,59 @@
+/* 
+ * This code is based on the ISO filesystem support in MILO (by
+ * Dave Rusling).
+ *
+ * This is a set of functions that provides minimal filesystem
+ * functionality to the Linux bootstrapper.  All we can do is
+ * open and read files... but that's all we need 8-)
+ */
+#include <stddef.h>
+#include <cons.h>
+#include <bootfs.h>
+#include <isolib.h>
+
+#ifdef DEBUG_ISO
+#include <utils.h>
+#endif
+
+extern const struct bootfs isofs;
+
+static long cd_device = -1;
+
+
+long
+iso_dev_read (void * buf, long offset, long size)
+{
+	return cons_read(cd_device, buf, size, offset);
+}
+
+
+static int
+iso_mount (long cons_dev, long p_offset, long quiet)
+{
+#ifdef DEBUG_ISO 
+	printf("iso_mount() called\n");
+#endif	
+	cd_device = cons_dev;
+	/*
+	 * Read the super block (this determines the file system type
+	 * and other important information)
+	 */
+	return iso_read_super(NULL, quiet);
+}
+
+static const char *
+iso_readdir(int fd, int rewind)
+{
+	return iso_readdir_i(fd,rewind); 
+}
+
+const struct bootfs iso = {
+  -1,	/* isofs is not partitioned */
+  1024,	/* block size */
+  iso_mount,
+  iso_open,
+  iso_bread,
+  iso_close,
+  iso_readdir,
+  iso_fstat
+};

+ 485 - 0
package/aboot/src/fs/ufs.c

@@ -0,0 +1,485 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1993 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * $Log: ufs.c,v $
+ * Revision 1.1.1.2  2007/08/16 07:04:23  vorlon
+ * Import upstream "release" 1.0pre20040408 to CVS to facilitate rebasing
+ * against the current upstream work and avoid copying patches one-by-one.
+ *
+ * Revision 1.2  2003/11/08 00:03:36  wgwoods
+ * Reverted changes from 0.10, merged doc changes
+ *
+ * Revision 1.1.1.1.2.1  2003/03/21 23:32:23  wgwoods
+ * Warning cleanups
+ *
+ * Revision 1.1.1.1  2001/10/08 23:03:52  wgwoods
+ * initial import of CVS source from alphalinux.org, plus a couple bugfixes
+ *
+ * Revision 1.1.1.1  2000/05/03 03:58:22  dhd
+ * Initial import (from 0.7 release)
+ *
+ * Revision 2.2  93/02/05  08:01:36  danner
+ * 	Adapted for alpha.
+ * 	[93/02/04            af]
+ * 
+ */
+/*
+ *	File: ufs.c
+ * 	Author: David Golub, Carnegie Mellon University
+ *	Date:	12/90
+ *
+ *	Stand-alone file reading package.
+ *
+ *	Modified for use by Linux/Alpha by David Mosberger
+ *	(davidm@cs.arizona.edu)
+ */
+#include <linux/kernel.h>
+#include <asm/stat.h>
+
+#include "aboot.h"
+#include "bootfs.h"
+#include "cons.h"
+#include "disklabel.h"
+#include "ufs.h"
+#include "utils.h"
+#include "string.h"
+
+#define MAX_OPEN_FILES	1
+
+extern struct bootfs ufs;
+
+static long dev;
+static long partition_offset;
+static struct fs *fs;
+static struct file {
+	int 		inuse;
+	struct icommon	i_ic;		/* copy of on-disk inode */
+	int		f_nindir[NIADDR+1];
+					/* number of blocks mapped by
+					   indirect block at level i */
+	void		*f_blk[NIADDR];	/* buffer for indir block at level i */
+	long		f_blksize[NIADDR];
+					/* size of buffer */
+	__kernel_daddr_t		f_blkno[NIADDR];
+					/* disk address of block in buffer */
+	void		*f_buf;		/* buffer for data block */
+	long		f_buf_size;	/* size of data block */
+	__kernel_daddr_t		f_buf_blkno;	/* block number of data block */
+} inode_table[MAX_OPEN_FILES];
+
+
+static int read_inode(__kernel_ino_t inumber, struct file *fp)
+{
+	__kernel_daddr_t disk_block;
+	long offset;
+	struct dinode *dp;
+	int level;
+
+	disk_block = itod(fs, inumber);
+
+	offset = fsbtodb(fs, disk_block) * DEV_BSIZE + partition_offset;
+	if (cons_read(dev, fp->f_buf, fs->fs_bsize, offset) != fs->fs_bsize) {
+		printf("ufs_read_inode: read error\n");
+		return 1;
+	}
+	dp = (struct dinode *)fp->f_buf;
+	dp += itoo(fs, inumber);
+	fp->i_ic = dp->di_ic;
+	/*
+	 * Clear out the old buffers
+	 */
+	for (level = 0; level < NIADDR; level++) {
+		if (fp->f_blk[level]) {
+			free(fp->f_blk[level]);
+			fp->f_blk[level] = 0;
+		}
+		fp->f_blkno[level] = -1;
+	}
+	return 0;
+}
+
+
+/*
+ * Given an offset in a file, find the disk block number that
+ * contains that block.
+ */
+static __kernel_daddr_t block_map(struct file *fp, __kernel_daddr_t file_block)
+{
+	__kernel_daddr_t ind_block_num, *ind_p;
+	int level, idx;
+	long offset;
+	/*
+	 * Index structure of an inode:
+	 *
+	 * i_db[0..NDADDR-1]	hold block numbers for blocks
+	 *			0..NDADDR-1
+	 *
+	 * i_ib[0]		index block 0 is the single indirect
+	 *			block
+	 *			holds block numbers for blocks
+	 *			NDADDR .. NDADDR + NINDIR(fs)-1
+	 *
+	 * i_ib[1]		index block 1 is the double indirect
+	 *			block
+	 *			holds block numbers for INDEX blocks
+	 *			for blocks
+	 *			NDADDR + NINDIR(fs) ..
+	 *			NDADDR + NINDIR(fs) + NINDIR(fs)**2 - 1
+	 *
+	 * i_ib[2]		index block 2 is the triple indirect
+	 *			block
+	 *			holds block numbers for double-indirect
+	 *			blocks for blocks
+	 *			NDADDR + NINDIR(fs) + NINDIR(fs)**2 ..
+	 *			NDADDR + NINDIR(fs) + NINDIR(fs)**2
+	 *				+ NINDIR(fs)**3 - 1
+	 */
+	if (file_block < NDADDR) {
+		/* Direct block. */
+		return fp->i_db[file_block];
+	}
+
+	file_block -= NDADDR;
+
+	/*
+	 * nindir[0] = NINDIR
+	 * nindir[1] = NINDIR**2
+	 * nindir[2] = NINDIR**3
+	 *	etc
+	 */
+	for (level = 0; level < NIADDR; level++) {
+		if (file_block < fp->f_nindir[level])
+		  break;
+		file_block -= fp->f_nindir[level];
+	}
+	if (level == NIADDR) {
+		printf("ufs_block_map: block number too high\n");
+		return -1;
+	}
+
+	ind_block_num = fp->i_ib[level];
+
+	for (; level >= 0; level--) {
+		if (ind_block_num == 0) {
+			return 0;
+		}
+
+		if (fp->f_blkno[level] != ind_block_num) {
+			if (fp->f_blk[level]) {
+				free(fp->f_blk[level]);
+			}
+
+			offset = fsbtodb(fs, ind_block_num) * DEV_BSIZE
+			  + partition_offset;
+			fp->f_blk[level] = malloc(fs->fs_bsize);
+			if (cons_read(dev, fp->f_blk[level], fs->fs_bsize,
+				      offset)
+			    != fs->fs_bsize) 
+			{
+				printf("ufs_block_map: read error\n");
+				return -1;
+			}
+			fp->f_blkno[level] = ind_block_num;
+		}
+
+		ind_p = (__kernel_daddr_t *)fp->f_blk[level];
+
+		if (level > 0) {
+			idx = file_block / fp->f_nindir[level-1];
+			file_block %= fp->f_nindir[level-1];
+		} else {
+			idx = file_block;
+		}
+		ind_block_num = ind_p[idx];
+	}
+	return ind_block_num;
+}
+
+
+static int breadi(struct file *fp, long blkno, long nblks, char *buffer)
+{
+	long block_size, offset, tot_bytes, nbytes, ncontig;
+	__kernel_daddr_t disk_block;
+
+	tot_bytes = 0;
+	while (nblks) {
+		/*
+		 * Contiguous reads are a lot faster, so we try to group
+		 * as many blocks as possible:
+		 */
+		ncontig = 0;	/* # of *fragments* that are contiguous */
+		nbytes = 0;
+		disk_block = block_map(fp, blkno);
+		do {
+			block_size = blksize(fs, fp, blkno);
+			nbytes += block_size;
+			ncontig += numfrags(fs, block_size);
+			++blkno; --nblks;
+		} while (nblks &&
+			 block_map(fp, blkno) == disk_block + ncontig);
+
+		if (!disk_block) {
+			/* it's a hole... */
+			memset(buffer, 0, nbytes);
+		} else {
+			offset = fsbtodb(fs, disk_block) * DEV_BSIZE
+			  + partition_offset;
+			if (cons_read(dev, buffer, nbytes, offset) != nbytes) {
+				printf("ufs_breadi: read error\n");
+				return -1;
+			}
+		}
+		buffer    += nbytes;
+		tot_bytes += nbytes;
+	}
+	return tot_bytes;
+}
+
+
+/*
+ * Search a directory for a name and return its
+ * i_number.
+ */
+static int search_dir(const char *name, struct file *fp, __kernel_ino_t *inumber_p)
+{
+	long offset, blockoffset;
+	struct direct *dp;
+	int len;
+
+	len = strlen(name);
+
+	offset = 0;
+	while (offset < fp->i_size) {
+		blockoffset = 0;
+		if (breadi(fp, offset / fs->fs_bsize, 1, fp->f_buf) < 0) {
+			return -1;
+		}
+		while (blockoffset < fs->fs_bsize) {
+			dp = (struct direct *)((char*)fp->f_buf + blockoffset);
+			if (dp->d_ino) {
+				if (dp->d_namlen == len
+				    && strcmp(name, dp->d_name) == 0)
+				{
+					/* found entry */
+					*inumber_p = dp->d_ino;
+					return 0;
+				}
+			}
+			blockoffset += dp->d_reclen;
+		}
+		offset += fs->fs_bsize;
+	}
+	return -1;
+}
+
+
+/*
+ * Initialize a BSD FFS partition starting at offset P_OFFSET; this is
+ * sort-of the same idea as "mounting" it.  Read in the relevant
+ * control structures and make them available to the user.  Returns 0
+ * if successful, -1 on failure.
+ */
+static int ufs_mount(long cons_dev, long p_offset, long quiet)
+{
+	static char buf[SBSIZE];	/* minimize frame size */
+	long rc;
+
+	memset(&inode_table, 0, sizeof(inode_table));
+
+	dev = cons_dev;
+	partition_offset = p_offset;
+
+	rc = cons_read(dev, buf, SBSIZE, SBLOCK*DEV_BSIZE + partition_offset);
+	if (rc != SBSIZE)
+	{
+		printf("ufs_mount: superblock read failed (retval=%ld)\n", rc);
+		return -1;
+	}
+
+	fs = (struct fs *)buf;
+	if (fs->fs_magic != FS_MAGIC ||
+	    fs->fs_bsize > MAXBSIZE ||
+	    fs->fs_bsize < (int) sizeof(struct fs))
+	{
+		if (!quiet) {
+			printf("ufs_mount: invalid superblock "
+			       "(magic=%x, bsize=%d)\n",
+			       fs->fs_magic, fs->fs_bsize);
+		}
+		return -1;
+	}
+	ufs.blocksize = fs->fs_bsize;
+
+	/* don't read cylinder groups - we aren't modifying anything */
+	return 0;
+}
+
+
+static int ufs_open(const char *path)
+{
+	char *cp = 0, *component;
+	int fd;
+	__kernel_ino_t inumber, parent_inumber;
+	int nlinks = 0;
+	struct file *fp;
+	static char namebuf[MAXPATHLEN+1];
+	
+	if (!path || !*path) {
+		return -1;
+	}
+
+	for (fd = 0; inode_table[fd].inuse; ++fd) {
+		if (fd >= MAX_OPEN_FILES) {
+			return -1;
+		}
+	}
+	fp = &inode_table[fd];
+	fp->f_buf_size = fs->fs_bsize;
+	fp->f_buf = malloc(fp->f_buf_size);
+
+	/* copy name into buffer to allow modifying it: */
+	memcpy(namebuf, path, (unsigned)(strlen(path) + 1));
+
+	inumber = (__kernel_ino_t) ROOTINO;
+	if (read_inode(inumber, fp) < 0) {
+		return -1;
+	}
+
+	component = strtok(namebuf, "/");
+	while (component) {
+		/* verify that current node is a directory: */
+		if ((fp->i_mode & IFMT) != IFDIR) {
+			return -1;
+		}
+		/*
+		 * Look up component in current directory.
+		 * Save directory inumber in case we find a
+		 * symbolic link.
+		 */
+		parent_inumber = inumber;
+		if (search_dir(component, fp, &inumber))
+		  return -1;
+
+		/* open next component: */
+		if (read_inode(inumber, fp))
+		  return -1;
+
+		/* check for symbolic link: */
+		if ((fp->i_mode & IFMT) == IFLNK) {
+			int link_len = fp->i_size;
+			int len;
+
+			len = strlen(cp) + 1;
+
+			if (link_len + len >= MAXPATHLEN - 1) {
+				return -1;
+			}
+
+			if (++nlinks > MAXSYMLINKS) {
+				return FS_SYMLINK_LOOP;
+			}
+			memcpy(&namebuf[link_len], cp, len);
+#ifdef IC_FASTLINK
+			if ((fp->i_flags & IC_FASTLINK) != 0) {
+				memcpy(namebuf, fp->i_symlink, link_len);
+			} else
+#endif /* IC_FASTLINK */
+			{
+				/* read file for symbolic link: */
+				long rc, offset;
+				__kernel_daddr_t	disk_block;
+
+				disk_block = block_map(fp, (__kernel_daddr_t)0);
+				offset = fsbtodb(fs, disk_block) * DEV_BSIZE
+				  + partition_offset;
+				rc = cons_read(dev, namebuf, sizeof(namebuf),
+					       offset);
+				if (rc != sizeof(namebuf)) {
+					return -1;
+				}
+			}
+			/*
+			 * If relative pathname, restart at parent directory.
+			 * If absolute pathname, restart at root.
+			 */
+			cp = namebuf;
+			if (*cp != '/') {
+				inumber = parent_inumber;
+			} else
+			  inumber = (__kernel_ino_t)ROOTINO;
+
+			if (read_inode(inumber, fp))
+			  return -1;
+		}
+		component = strtok(NULL, "/");
+	}
+	/* calculate indirect block levels: */
+	{
+		register int mult;
+		register int level;
+
+		mult = 1;
+		for (level = 0; level < NIADDR; level++) {
+			mult *= NINDIR(fs);
+			fp->f_nindir[level] = mult;
+		}
+	}
+	return fd;
+}
+
+
+static int ufs_bread(int fd, long blkno, long nblks, char *buffer)
+{
+	struct file *fp;
+
+	fp = &inode_table[fd];
+	return breadi(fp, blkno, nblks, buffer);
+}
+
+
+static void ufs_close(int fd)
+{
+	inode_table[fd].inuse = 0;
+}
+
+static const char *
+ufs_readdir(int fd, int rewind)
+{
+	return NULL;
+}
+
+static int
+ufs_fstat(int fd, struct stat* buf)
+{
+	return -1;
+}
+
+struct bootfs ufs = {
+	FS_BSDFFS, 0,
+	ufs_mount,
+	ufs_open,  ufs_bread,  ufs_close, ufs_readdir, ufs_fstat
+};

+ 173 - 0
package/aboot/src/head.S

@@ -0,0 +1,173 @@
+/*
+ * arch/alpha/boot/head.S
+ *
+ * initial bootloader stuff..
+ */
+
+#include "pal.h"
+
+#include <config.h>
+
+	.set noreorder
+	.globl	__start
+	.ent	__start
+__start:
+	.prologue 0
+	bis	$31,$31,$31
+	br	1f
+	/* room for the initial PCB, which comes here */
+	.quad	0,0,0,0,0,0,0,0
+1:	br	$27,2f
+2:	ldgp	$29,0($27)
+	lda	$27,main_
+	jsr	$26,($27),main_
+	call_pal PAL_halt
+	.end __start
+
+	/* these must appear within first 512 bytes: */
+	.align 3
+	.quad	ABOOT_MAGIC
+config_file_partition:
+	.globl	config_file_partition
+	.quad	CONFIG_FILE_PARTITION
+raw_initrd_size:
+	.globl	raw_initrd_size
+	.quad	0
+
+	.align 3
+	.globl wrent
+	.ent wrent
+wrent:
+	.prologue 0
+	call_pal PAL_wrent
+	ret ($26)
+	.end wrent
+
+	.align 3
+	.globl wrkgp
+	.ent wrkgp
+wrkgp:	
+	.prologue 0
+	call_pal PAL_wrkgp
+	ret ($26)
+	.end wrkgp
+
+	.align 3
+	.globl tbi
+	.ent tbi
+tbi:	
+	.prologue 0
+        call_pal PAL_tbi
+        ret     ($26)
+        .end tbi
+
+	.align 3
+	.globl switch_to_osf_pal
+	.ent switch_to_osf_pal
+switch_to_osf_pal:
+	.prologue 0
+	subq	$30,128,$30
+	stq	$26,0($30)
+	stq	$1,8($30)	# regs clobbered by swppal
+	stq	$2,16($30)
+	stq	$3,24($30)
+	stq	$4,32($30)
+	stq	$5,40($30)
+	stq	$6,48($30)
+	stq	$7,56($30)
+	stq	$8,64($30)
+	stq	$9,72($30)
+	stq	$10,80($30)
+	stq	$11,88($30)
+	stq	$12,96($30)
+	stq	$13,104($30)
+	stq	$14,112($30)
+	stq	$15,120($30)
+
+	stq	$30,0($17)	/* save KSP in PCB (a1) */
+
+	bis	$30,$30,$20	/* a4 = KSP */
+	br	$17,__do_swppal
+
+	ldq	$26,0($30)
+	ldq	$1,8($30)
+	ldq	$2,16($30)
+	ldq	$3,24($30)
+	ldq	$4,32($30)
+	ldq	$5,40($30)
+	ldq	$6,48($30)
+	ldq	$7,56($30)
+	ldq	$8,64($30)
+	ldq	$9,72($30)
+	ldq	$10,80($30)
+	ldq	$11,88($30)
+	ldq	$12,96($30)
+	ldq	$13,104($30)
+	ldq	$14,112($30)
+	ldq	$15,120($30)
+	addq	$30,128,$30
+	ret ($26)
+
+__do_swppal:
+	call_pal PAL_swppal
+	.end	switch_to_osf_pal
+
+	.align 3
+	.globl dispatch
+	.ent dispatch
+dispatch:	
+	.prologue 0
+	subq	$30,80,$30
+	stq	$26,0($30)
+	stq	$29,8($30)
+
+	stq	$8,16($30)	/* OpenVMS save regs */
+	stq	$9,24($30)
+	stq	$10,32($30)
+	stq	$11,40($30)
+	stq	$12,48($30)
+	stq	$13,56($30)
+	stq	$14,64($30)
+	stq	$15,72($30)
+
+	lda	$1,0x10000000		/* hwrpb */
+	ldq	$2,0xc0($1)		/* crb offset */
+	addq	$2,$1,$2		/* crb */
+	ldq	$27,0($2)		/* dispatch procedure value */
+
+	ldq	$2,8($27)		/* dispatch call address */
+	jsr	$26,($2)		/* call it (weird VMS call seq) */
+
+	ldq	$26,0($30)
+	ldq	$29,8($30)
+
+	ldq	$8,16($30)
+	ldq	$9,24($30)
+	ldq	$10,32($30)
+	ldq	$11,40($30)
+	ldq	$12,48($30)
+	ldq	$13,56($30)
+	ldq	$14,64($30)
+	ldq	$15,72($30)
+
+	addq	$30,80,$30
+	ret	$31,($26)
+.end    dispatch
+
+
+	.align 3
+	.globl halt
+	.ent halt
+halt:	
+	.prologue 0
+	call_pal PAL_halt
+	.end halt
+
+	.ent run_kernel
+	.globl run_kernel
+run_kernel:
+	.prologue 0
+	mov	$16,$27
+	mov	$17,$30
+	jmp	$31,($27)
+	.end run_kernel

+ 47 - 0
package/aboot/src/include/aboot.h

@@ -0,0 +1,47 @@
+#ifndef aboot_h
+#define aboot_h
+
+#include <stdarg.h>
+
+#include "hwrpb.h"
+
+#include <setjmp.h>
+
+#define SECT_SIZE	512	/* console block size for disk reads */
+#define BOOT_SECTOR	2	/* first sector of 2ndary bootstrap loader */
+
+extern struct segment {
+	unsigned long addr, offset, size;
+} *chunks;
+extern int nchunks;
+
+extern struct bootfs *	bfs;
+extern char *		dest_addr;
+extern long		bytes_to_copy;
+extern long		text_offset;
+extern jmp_buf		jump_buffer;
+
+extern long		config_file_partition;
+
+extern char		boot_file[256];
+extern char		initrd_file[256];
+extern char		kernel_args[256];
+extern unsigned long	start_addr;
+extern char *		bss_start;
+extern long		bss_size;
+extern unsigned long	initrd_start, initrd_size;
+/* page size is in the INIT_HWRPB */
+extern unsigned long	page_offset, page_shift;
+
+extern long		first_block (const char *buf, long blocksize);
+extern unsigned long	switch_to_osf_pal (unsigned long nr,
+					   struct pcb_struct *pcb_va,
+					   struct pcb_struct *pcb_pa,
+					   unsigned long vptb,
+					   unsigned long *kstk);
+extern int		uncompress_kernel (int fd);
+extern int		vsprintf (char *, const char *, va_list);
+extern void		run_kernel (unsigned long entry, unsigned long stack)
+			__attribute__((noreturn));
+
+#endif /* aboot_h */

+ 25 - 0
package/aboot/src/include/bootfs.h

@@ -0,0 +1,25 @@
+#ifndef boot_fs_h
+#define boot_fs_h
+
+#include <linux/types.h>
+#include <asm/stat.h>
+
+struct bootfs {
+	int	fs_type;
+	int	blocksize;
+	
+	int	(*mount)(long dev, long partition_start, long quiet);
+
+	int	(*open)(const char *filename);
+	int	(*bread)(int fd, long blkno, long nblks, char *buf);
+	void	(*close)(int fd);
+
+	/* You'll probably want to use this like:
+		while ((ent = fs->readdir(fd, !rewind++)));
+	   so that it rewinds only on the first access.  Also don't
+	   mix it with other I/O or you will die horribly */
+	const char *	(*readdir)(int fd, int rewind);
+	int	(*fstat)(int fd, struct stat* buf);
+} ext2fs;
+
+#endif /* boot_fs_h */

+ 12 - 0
package/aboot/src/include/config.h

@@ -0,0 +1,12 @@
+#ifndef config_h
+#define config_h
+
+#define ABOOT_MAJOR	0
+#define ABOOT_MINOR	9
+#define ABOOT_VERSION	"1.0_pre20040408"
+#define ABOOT_MAGIC	0x30302d746f6f6261 /* "aboot-00" */
+
+#define CONFIG_FILE_PARTITION	1
+#define CONFIG_FILE		"/etc/aboot.conf"
+
+#endif /* config_h */

+ 47 - 0
package/aboot/src/include/cons.h

@@ -0,0 +1,47 @@
+#ifndef cons_h
+#define cons_h
+
+extern long cons_dev;		/* console device */
+
+extern long dispatch(long proc, ...);
+
+#ifdef TESTING
+#define STRINGIFY(sym) #sym
+#define cons_init()
+#define cons_puts(s,l) puts(s, strlen(s))
+#define cons_open(d)   open(d, O_RDONLY)
+#define cons_close(d)  close(d)
+#define cons_read(d,b,c,o) ({ lseek(d, o, 0); read(d,b,c);})
+#define cons_putchar(c)    putchar(c)
+#define cons_getchar()     getchar()
+#define cons_open_console()
+#define cons_close_console()
+#else
+extern void cons_init (void);
+extern long cons_getenv (long index, char *envval, long maxlen);
+extern long cons_puts (const char *str, long len);
+extern long cons_open (const char *devname);
+extern long cons_close (long dev);
+extern long cons_read (long dev, void *buf, long count, long offset);
+extern void cons_putchar(char c);
+extern int cons_getchar(void);
+extern void cons_open_console(void);
+extern void cons_close_console(void);
+#endif
+
+/* this isn't in the kernel for some reason */
+#define CTB_TYPE_NONE     0
+#define CTB_TYPE_DETACHED 1
+#define CTB_TYPE_SERIAL   2
+#define CTB_TYPE_GRAPHICS 3
+#define CTB_TYPE_MULTI    4
+
+struct ctb_struct {
+	unsigned long type;
+	unsigned long id;
+	unsigned long reserved;
+	unsigned long dsd_len;
+	char dsd[0];
+};
+
+#endif /* cons_h */

+ 105 - 0
package/aboot/src/include/disklabel.h

@@ -0,0 +1,105 @@
+#ifndef __disklabel_h__
+#define __disklabel_h__
+
+#ifndef __KERNEL_STRICT_NAMES
+  /* ask kernel to be careful about name-space pollution: */
+# define __KERNEL_STRICT_NAMES
+# define fd_set kernel_fd_set
+#endif
+
+#include <linux/types.h>
+
+#define DISKLABELMAGIC (0x82564557UL)
+
+#define LABELSECTOR	0			/* sector containing label */
+#define LABELOFFSET	64			/* offset of label in sector */
+
+#define MAXPARTITIONS	8			/* max. # of partitions */
+
+/*
+ * Filesystem type and version.  Used to interpret other
+ * filesystem-specific per-partition information.
+ */
+#define	FS_UNUSED	0		/* unused */
+#define	FS_SWAP		1		/* swap */
+#define	FS_V6		2		/* Sixth Edition */
+#define	FS_V7		3		/* Seventh Edition */
+#define	FS_SYSV		4		/* System V */
+#define	FS_V71K		5		/* V7 with 1K blocks (4.1, 2.9) */
+#define	FS_V8		6		/* Eighth Edition, 4K blocks */
+#define	FS_BSDFFS	7		/* 4.2BSD fast file system */
+#define FS_EXT2		8		/* Linux ext2 file system */
+/* OSF will reserve 16--31 for vendor-specific entries */
+#define	FS_ADVFS	16		/* Digital Advanced File System */
+#define	FS_LSMpubl	17		/* Digital Log Strg public region  */
+#define	FS_LSMpriv	18		/* Digital Log Strg private region */
+#define	FS_LSMsimp	19		/* Digital Log Strg simple disk    */
+
+struct disklabel {
+    __u32	d_magic;				/* must be DISKLABELMAGIC */
+    __u16	d_type, d_subtype;
+    __u8	d_typename[16];
+    __u8	d_packname[16];
+    __u32	d_secsize;
+    __u32	d_nsectors;
+    __u32	d_ntracks;
+    __u32	d_ncylinders;
+    __u32	d_secpercyl;
+    __u32	d_secprtunit;
+    __u16	d_sparespertrack;
+    __u16	d_sparespercyl;
+    __u32	d_acylinders;
+    __u16	d_rpm, d_interleave, d_trackskew, d_cylskew;
+    __u32	d_headswitch, d_trkseek, d_flags;
+    __u32	d_drivedata[5];
+    __u32	d_spare[5];
+    __u32	d_magic2;				/* must be DISKLABELMAGIC */
+    __u16	d_checksum;
+    __u16	d_npartitions;
+    __u32	d_bbsize, d_sbsize;
+    struct d_partition {
+	__u32	p_size;
+	__u32	p_offset;
+	__u32	p_fsize;
+	__u8	p_fstype;
+	__u8	p_frag;
+	__u16	p_cpg;
+    } d_partitions[MAXPARTITIONS];
+};
+
+#define DTYPE_SMD		 1
+#define DTYPE_MSCP		 2
+#define DTYPE_DEC		 3
+#define DTYPE_SCSI		 4
+#define DTYPE_ESDI		 5
+#define DTYPE_ST506		 6
+#define DTYPE_FLOPPY		10
+
+#ifdef DKTYPENAMES
+static char *fstypenames[] = {
+	"unused",
+	"swap",
+	"Version 6",
+	"Version 7",
+	"System V",
+	"4.1BSD",
+	"Eighth Edition",
+	"4.2BSD",
+	"ext2",			/* is this a good choice for ext2?? */
+	"resrvd9",
+	"resrvd10",
+	"resrvd11",
+	"resrvd12",
+	"resrvd13",
+	"resrvd14",
+	"resrvd15",
+	"ADVfs",
+	"LSMpubl",
+	"LSMpriv",
+	"LSMsimp",
+	0
+};
+#define FSMAXTYPES	(sizeof(fstypenames) / sizeof(fstypenames[0]) - 1)
+#endif
+
+#endif /* __disklabel_h__ */

+ 220 - 0
package/aboot/src/include/hwrpb.h

@@ -0,0 +1,220 @@
+#ifndef __ALPHA_HWRPB_H
+#define __ALPHA_HWRPB_H
+
+#define INIT_HWRPB ((struct hwrpb_struct *) 0x10000000)
+
+/*
+ * DEC processor types for Alpha systems.  Found in HWRPB.
+ * These values are architected.
+ */
+
+#define EV3_CPU                 1       /* EV3                  */
+#define EV4_CPU                 2       /* EV4 (21064)          */
+#define LCA4_CPU                4       /* LCA4 (21066/21068)   */
+#define EV5_CPU                 5       /* EV5 (21164)          */
+#define EV45_CPU                6       /* EV4.5 (21064/xxx)    */
+#define EV56_CPU		7	/* EV5.6 (21164)	*/
+#define EV6_CPU			8	/* EV6 (21264)		*/
+#define PCA56_CPU		9	/* PCA56 (21164PC)	*/
+#define PCA57_CPU		10	/* PCA57 (notyet)	*/
+#define EV67_CPU		11	/* EV67 (21264A)	*/
+#define EV68CB_CPU		12	/* EV68CB (21264C)	*/
+#define EV68AL_CPU		13	/* EV68AL (21264B)	*/
+#define EV68CX_CPU		14	/* EV68CX (21264D)	*/
+#define EV7_CPU			15	/* EV7 (21364)		*/
+#define EV79_CPU		16	/* EV79 (21364??)	*/
+#define EV69_CPU		17	/* EV69 (21264/EV69A)	*/
+
+/*
+ * DEC system types for Alpha systems.  Found in HWRPB.
+ * These values are architected.
+ */
+
+#define ST_ADU			  1	/* Alpha ADU systype	*/
+#define ST_DEC_4000		  2	/* Cobra systype	*/
+#define ST_DEC_7000		  3	/* Ruby systype		*/
+#define ST_DEC_3000_500		  4	/* Flamingo systype	*/
+#define ST_DEC_2000_300		  6	/* Jensen systype	*/
+#define ST_DEC_3000_300		  7	/* Pelican systype	*/
+#define ST_DEC_2100_A500	  9	/* Sable systype	*/
+#define ST_DEC_AXPVME_64	 10	/* AXPvme system type	*/
+#define ST_DEC_AXPPCI_33	 11	/* NoName system type	*/
+#define ST_DEC_TLASER		 12	/* Turbolaser systype	*/
+#define ST_DEC_2100_A50		 13	/* Avanti systype	*/
+#define ST_DEC_MUSTANG		 14	/* Mustang systype	*/
+#define ST_DEC_ALCOR		 15	/* Alcor (EV5) systype	*/
+#define ST_DEC_1000		 17	/* Mikasa systype	*/
+#define ST_DEC_EB64		 18	/* EB64 systype		*/
+#define ST_DEC_EB66		 19	/* EB66 systype		*/
+#define ST_DEC_EB64P		 20	/* EB64+ systype	*/
+#define ST_DEC_BURNS		 21	/* laptop systype	*/
+#define ST_DEC_RAWHIDE		 22	/* Rawhide systype	*/
+#define ST_DEC_K2		 23	/* K2 systype		*/
+#define ST_DEC_LYNX		 24	/* Lynx systype		*/
+#define ST_DEC_XL		 25	/* Alpha XL systype	*/
+#define ST_DEC_EB164		 26	/* EB164 systype	*/
+#define ST_DEC_NORITAKE		 27	/* Noritake systype	*/
+#define ST_DEC_CORTEX		 28	/* Cortex systype	*/
+#define ST_DEC_MIATA		 30	/* Miata systype        */
+#define ST_DEC_XXM		 31	/* XXM systype		*/
+#define ST_DEC_TAKARA		 32	/* Takara systype	*/
+#define ST_DEC_YUKON		 33	/* Yukon systype	*/
+#define ST_DEC_TSUNAMI		 34	/* Tsunami systype	*/
+#define ST_DEC_WILDFIRE		 35	/* Wildfire systype	*/
+#define ST_DEC_CUSCO		 36	/* CUSCO systype	*/
+#define ST_DEC_EIGER		 37	/* Eiger systype	*/
+#define ST_DEC_TITAN		 38	/* Titan systype	*/
+#define ST_DEC_MARVEL		 39	/* Marvel systype	*/
+
+/* UNOFFICIAL!!! */
+#define ST_UNOFFICIAL_BIAS	100
+#define ST_DTI_RUFFIAN		101	/* RUFFIAN systype	*/
+
+/* Alpha Processor, Inc. systems */
+#define ST_API_BIAS		200
+#define ST_API_NAUTILUS		201	/* UP1000 systype	*/
+
+struct pcb_struct {
+	unsigned long ksp;
+	unsigned long usp;
+	unsigned long ptbr;
+	unsigned int pcc;
+	unsigned int asn;
+	unsigned long unique;
+	unsigned long flags;
+	unsigned long res1, res2;
+};
+
+struct percpu_struct {
+	unsigned long hwpcb[16];
+	unsigned long flags;
+	unsigned long pal_mem_size;
+	unsigned long pal_scratch_size;
+	unsigned long pal_mem_pa;
+	unsigned long pal_scratch_pa;
+	unsigned long pal_revision;
+	unsigned long type;
+	unsigned long variation;
+	unsigned long revision;
+	unsigned long serial_no[2];
+	unsigned long logout_area_pa;
+	unsigned long logout_area_len;
+	unsigned long halt_PCBB;
+	unsigned long halt_PC;
+	unsigned long halt_PS;
+	unsigned long halt_arg;
+	unsigned long halt_ra;
+	unsigned long halt_pv;
+	unsigned long halt_reason;
+	unsigned long res;
+	unsigned long ipc_buffer[21];
+	unsigned long palcode_avail[16];
+	unsigned long compatibility;
+	unsigned long console_data_log_pa;
+	unsigned long console_data_log_length;
+	unsigned long bcache_info;
+};
+
+struct procdesc_struct {
+	unsigned long weird_vms_stuff;
+	unsigned long address;
+};
+
+struct vf_map_struct {
+	unsigned long va;
+	unsigned long pa;
+	unsigned long count;
+};
+
+struct crb_struct {
+	struct procdesc_struct * dispatch_va;
+	struct procdesc_struct * dispatch_pa;
+	struct procdesc_struct * fixup_va;
+	struct procdesc_struct * fixup_pa;
+	/* virtual->physical map */
+	unsigned long map_entries;
+	unsigned long map_pages;
+	struct vf_map_struct map[1];
+};
+
+struct memclust_struct {
+	unsigned long start_pfn;
+	unsigned long numpages;
+	unsigned long numtested;
+	unsigned long bitmap_va;
+	unsigned long bitmap_pa;
+	unsigned long bitmap_chksum;
+	unsigned long usage;
+};
+
+struct memdesc_struct {
+	unsigned long chksum;
+	unsigned long optional_pa;
+	unsigned long numclusters;
+	struct memclust_struct cluster[0];
+};
+
+struct dsr_struct {
+	long smm;			/* SMM nubber used by LMF       */
+	unsigned long  lurt_off;	/* offset to LURT table         */
+	unsigned long  sysname_off;	/* offset to sysname char count */
+};
+
+struct hwrpb_struct {
+	unsigned long phys_addr;	/* check: physical address of the hwrpb */
+	unsigned long id;		/* check: "HWRPB\0\0\0" */
+	unsigned long revision;	
+	unsigned long size;		/* size of hwrpb */
+	unsigned long cpuid;
+	unsigned long pagesize;		/* 8192, I hope */
+	unsigned long pa_bits;		/* number of physical address bits */
+	unsigned long max_asn;
+	unsigned char ssn[16];		/* system serial number: big bother is watching */
+	unsigned long sys_type;
+	unsigned long sys_variation;
+	unsigned long sys_revision;
+	unsigned long intr_freq;	/* interval clock frequency * 4096 */
+	unsigned long cycle_freq;	/* cycle counter frequency */
+	unsigned long vptb;		/* Virtual Page Table Base address */
+	unsigned long res1;
+	unsigned long tbhb_offset;	/* Translation Buffer Hint Block */
+	unsigned long nr_processors;
+	unsigned long processor_size;
+	unsigned long processor_offset;
+	unsigned long ctb_nr;
+	unsigned long ctb_size;		/* console terminal block size */
+	unsigned long ctbt_offset;	/* console terminal block table offset */
+	unsigned long crb_offset;	/* console callback routine block */
+	unsigned long mddt_offset;	/* memory data descriptor table */
+	unsigned long cdb_offset;	/* configuration data block (or NULL) */
+	unsigned long frut_offset;	/* FRU table (or NULL) */
+	void (*save_terminal)(unsigned long);
+	unsigned long save_terminal_data;
+	void (*restore_terminal)(unsigned long);
+	unsigned long restore_terminal_data;
+	void (*CPU_restart)(unsigned long);
+	unsigned long CPU_restart_data;
+	unsigned long res2;
+	unsigned long res3;
+	unsigned long chksum;
+	unsigned long rxrdy;
+	unsigned long txrdy;
+	unsigned long dsr_offset;	/* "Dynamic System Recognition Data Block Table" */
+};
+
+#ifdef __KERNEL__
+
+extern struct hwrpb_struct *hwrpb;
+
+static inline void
+hwrpb_update_checksum(struct hwrpb_struct *h)
+{
+	unsigned long sum = 0, *l;
+        for (l = (unsigned long *) h; l < (unsigned long *) &h->chksum; ++l)
+                sum += *l;
+        h->chksum = sum;
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* __ALPHA_HWRPB_H */

+ 292 - 0
package/aboot/src/include/iso.h

@@ -0,0 +1,292 @@
+#ifndef _ISOFS_FS_H
+#define _ISOFS_FS_H
+
+#include <linux/types.h>
+/*
+ * The isofs filesystem constants/structures
+ */
+
+/* This part borrowed from the bsd386 isofs */
+#define ISODCL(from, to) (to - from + 1)
+
+struct iso_volume_descriptor {
+	char type[ISODCL(1,1)]; /* 711 */
+	char id[ISODCL(2,6)];
+	char version[ISODCL(7,7)];
+	char data[ISODCL(8,2048)];
+};
+
+/* volume descriptor types */
+#define ISO_VD_PRIMARY 1
+#define ISO_VD_END 255
+
+#define ISO_STANDARD_ID "CD001"
+
+struct iso_primary_descriptor {
+	char type			[ISODCL (  1,   1)]; /* 711 */
+	char id				[ISODCL (  2,   6)];
+	char version			[ISODCL (  7,   7)]; /* 711 */
+	char unused1			[ISODCL (  8,   8)];
+	char system_id			[ISODCL (  9,  40)]; /* achars */
+	char volume_id			[ISODCL ( 41,  72)]; /* dchars */
+	char unused2			[ISODCL ( 73,  80)];
+	char volume_space_size		[ISODCL ( 81,  88)]; /* 733 */
+	char unused3			[ISODCL ( 89, 120)];
+	char volume_set_size		[ISODCL (121, 124)]; /* 723 */
+	char volume_sequence_number	[ISODCL (125, 128)]; /* 723 */
+	char logical_block_size		[ISODCL (129, 132)]; /* 723 */
+	char path_table_size		[ISODCL (133, 140)]; /* 733 */
+	char type_l_path_table		[ISODCL (141, 144)]; /* 731 */
+	char opt_type_l_path_table	[ISODCL (145, 148)]; /* 731 */
+	char type_m_path_table		[ISODCL (149, 152)]; /* 732 */
+	char opt_type_m_path_table	[ISODCL (153, 156)]; /* 732 */
+	char root_directory_record	[ISODCL (157, 190)]; /* 9.1 */
+	char volume_set_id		[ISODCL (191, 318)]; /* dchars */
+	char publisher_id		[ISODCL (319, 446)]; /* achars */
+	char preparer_id		[ISODCL (447, 574)]; /* achars */
+	char application_id		[ISODCL (575, 702)]; /* achars */
+	char copyright_file_id		[ISODCL (703, 739)]; /* 7.5 dchars */
+	char abstract_file_id		[ISODCL (740, 776)]; /* 7.5 dchars */
+	char bibliographic_file_id	[ISODCL (777, 813)]; /* 7.5 dchars */
+	char creation_date		[ISODCL (814, 830)]; /* 8.4.26.1 */
+	char modification_date		[ISODCL (831, 847)]; /* 8.4.26.1 */
+	char expiration_date		[ISODCL (848, 864)]; /* 8.4.26.1 */
+	char effective_date		[ISODCL (865, 881)]; /* 8.4.26.1 */
+	char file_structure_version	[ISODCL (882, 882)]; /* 711 */
+	char unused4			[ISODCL (883, 883)];
+	char application_data		[ISODCL (884, 1395)];
+	char unused5			[ISODCL (1396, 2048)];
+};
+
+
+#define HS_STANDARD_ID "CDROM"
+
+struct  hs_volume_descriptor {
+	char foo			[ISODCL (  1,   8)]; /* 733 */
+	char type			[ISODCL (  9,   9)]; /* 711 */
+	char id				[ISODCL ( 10,  14)];
+	char version			[ISODCL ( 15,  15)]; /* 711 */
+	char data[ISODCL(16,2048)];
+};
+
+
+struct hs_primary_descriptor {
+	char foo			[ISODCL (  1,   8)]; /* 733 */
+	char type			[ISODCL (  9,   9)]; /* 711 */
+	char id				[ISODCL ( 10,  14)];
+	char version			[ISODCL ( 15,  15)]; /* 711 */
+	char unused1			[ISODCL ( 16,  16)]; /* 711 */
+	char system_id			[ISODCL ( 17,  48)]; /* achars */
+	char volume_id			[ISODCL ( 49,  80)]; /* dchars */
+	char unused2			[ISODCL ( 81,  88)]; /* 733 */
+	char volume_space_size		[ISODCL ( 89,  96)]; /* 733 */
+	char unused3			[ISODCL ( 97, 128)]; /* 733 */
+	char volume_set_size		[ISODCL (129, 132)]; /* 723 */
+	char volume_sequence_number	[ISODCL (133, 136)]; /* 723 */
+	char logical_block_size		[ISODCL (137, 140)]; /* 723 */
+	char path_table_size		[ISODCL (141, 148)]; /* 733 */
+	char type_l_path_table		[ISODCL (149, 152)]; /* 731 */
+	char unused4			[ISODCL (153, 180)]; /* 733 */
+	char root_directory_record	[ISODCL (181, 214)]; /* 9.1 */
+};
+
+/* We use this to help us look up the parent inode numbers. */
+
+struct iso_path_table{
+	unsigned char  name_len[2];	/* 721 */
+	char extent[4];		/* 731 */
+	char  parent[2];	/* 721 */
+	char name[0];
+};
+
+/* high sierra is identical to iso, except that the date is only 6 bytes, and
+   there is an extra reserved byte after the flags */
+
+struct iso_directory_record {
+	char length			[ISODCL (1, 1)]; /* 711 */
+	char ext_attr_length		[ISODCL (2, 2)]; /* 711 */
+	char extent			[ISODCL (3, 10)]; /* 733 */
+	char size			[ISODCL (11, 18)]; /* 733 */
+	char date			[ISODCL (19, 25)]; /* 7 by 711 */
+	char flags			[ISODCL (26, 26)];
+	char file_unit_size		[ISODCL (27, 27)]; /* 711 */
+	char interleave			[ISODCL (28, 28)]; /* 711 */
+	char volume_sequence_number	[ISODCL (29, 32)]; /* 723 */
+	unsigned char name_len		[ISODCL (33, 33)]; /* 711 */
+	char name			[0];
+};
+
+#define ISOFS_BLOCK_BITS 11
+#define ISOFS_BLOCK_SIZE 2048
+
+#define ISOFS_BUFFER_SIZE(INODE) ((INODE)->i_sb->s_blocksize)
+#define ISOFS_BUFFER_BITS(INODE) ((INODE)->i_sb->s_blocksize_bits)
+
+#if 0
+#ifdef ISOFS_FIXED_BLOCKSIZE
+/* We use these until the buffer cache supports 2048 */
+#define ISOFS_BUFFER_BITS 10
+#define ISOFS_BUFFER_SIZE 1024
+
+#define ISOFS_BLOCK_NUMBER(X) (X<<1)
+#else
+#define ISOFS_BUFFER_BITS 11
+#define ISOFS_BUFFER_SIZE 2048
+
+#define ISOFS_BLOCK_NUMBER(X) (X)
+#endif
+#endif
+
+#define ISOFS_SUPER_MAGIC 0x9660
+#define ISOFS_FILE_UNKNOWN 0
+#define ISOFS_FILE_TEXT 1
+#define ISOFS_FILE_BINARY 2
+#define ISOFS_FILE_TEXT_M 3
+
+struct isofs_super_block {
+  unsigned long s_ninodes;
+  unsigned long s_nzones;
+  unsigned long s_firstdatazone;
+  unsigned long s_log_zone_size;
+  unsigned long s_max_size;
+
+  unsigned char s_high_sierra; /* A simple flag */
+  unsigned char s_mapping;
+  unsigned char s_conversion;
+  unsigned char s_rock;
+  unsigned char s_cruft; /* Broken disks with high
+			    byte of length containing
+			    junk */
+  unsigned int s_blocksize;
+  unsigned int s_blocksize_bits;
+  unsigned int s_mounted;
+  unsigned char s_unhide;
+  unsigned char s_nosuid;
+  unsigned char s_nodev;
+  mode_t s_mode;
+};
+
+/*
+ * iso fs inode data in memory
+ */
+struct iso_inode {
+	unsigned int i_first_extent;
+	unsigned int i_backlink;
+	unsigned char i_file_format;
+};
+
+/* From fs/isofs/rock.h in Linux, (c) 1995, 1996 Eric Youngdale */
+
+/* These structs are used by the system-use-sharing protocol, in which the
+   Rock Ridge extensions are embedded.  It is quite possible that other
+   extensions are present on the disk, and this is fine as long as they
+   all use SUSP */
+
+struct SU_SP{
+  unsigned char magic[2];
+  unsigned char skip;
+};
+
+struct SU_CE{
+  char extent[8];
+  char offset[8];
+  char size[8];
+};
+
+struct SU_ER{
+  unsigned char len_id;
+  unsigned char len_des;
+  unsigned char len_src;
+  unsigned char ext_ver;
+  char data[0];
+};
+
+struct RR_RR{
+  char flags[1];
+};
+
+struct RR_PX{
+  char mode[8];
+  char n_links[8];
+  char uid[8];
+  char gid[8];
+};
+
+struct RR_PN{
+  char dev_high[8];
+  char dev_low[8];
+};
+
+
+struct SL_component{
+  unsigned char flags;
+  unsigned char len;
+  char text[0];
+};
+
+struct RR_SL{
+  unsigned char flags;
+  struct SL_component link;
+};
+
+struct RR_NM{
+  unsigned char flags;
+  char name[0];
+};
+
+struct RR_CL{
+  char location[8];
+};
+
+struct RR_PL{
+  char location[8];
+};
+
+struct stamp{
+  char time[7];
+};
+
+struct RR_TF{
+  char flags;
+  struct stamp times[0];  /* Variable number of these beasts */
+};
+
+/* These are the bits and their meanings for flags in the TF structure. */
+#define TF_CREATE 1
+#define TF_MODIFY 2
+#define TF_ACCESS 4
+#define TF_ATTRIBUTES 8
+#define TF_BACKUP 16
+#define TF_EXPIRATION 32
+#define TF_EFFECTIVE 64
+#define TF_LONG_FORM 128
+
+struct rock_ridge{
+  char signature[2];
+  unsigned char len;
+  unsigned char version;
+  union{
+    struct SU_SP SP;
+    struct SU_CE CE;
+    struct SU_ER ER;
+    struct RR_RR RR;
+    struct RR_PX PX;
+    struct RR_PN PN;
+    struct RR_SL SL;
+    struct RR_NM NM;
+    struct RR_CL CL;
+    struct RR_PL PL;
+    struct RR_TF TF;
+  } u;
+};
+
+#define RR_PX 1   /* POSIX attributes */
+#define RR_PN 2   /* POSIX devices */
+#define RR_SL 4   /* Symbolic link */
+#define RR_NM 8   /* Alternate Name */
+#define RR_CL 16  /* Child link */
+#define RR_PL 32  /* Parent link */
+#define RR_RE 64  /* Relocation directory */
+#define RR_TF 128 /* Timestamps */
+
+#endif

+ 30 - 0
package/aboot/src/include/isolib.h

@@ -0,0 +1,30 @@
+#ifndef isolib_h
+#define isolib_h
+
+#ifndef __KERNEL_STRICT_NAMES
+  /* ask kernel to be careful about name-space pollution: */
+# define __KERNEL_STRICT_NAMES
+# define fd_set kernel_fd_set
+#endif
+
+#include <asm/stat.h>
+
+extern int  iso_read_super (void * data, int quiet);
+extern int  iso_open (const char * filename);
+extern int  iso_bread (int fd, long blkno, long nblks, char * buffer);
+extern void iso_close (int fd);
+extern long iso_map (int fd, long block);
+extern int  iso_fstat (int fd, struct stat * buf);
+extern char *iso_readdir_i(int fd, int rewind);
+extern int  isonum_711 (char *p);
+extern int  isonum_712 (char *p);
+extern int  isonum_721 (char *p);
+extern int  isonum_722 (char *p);
+extern int  isonum_723 (char *p);
+extern int  isonum_731 (char *p);
+extern int  isonum_732 (char *p);
+extern int  isonum_733 (char *p);
+
+#endif /* isolib_h */
+
+

+ 591 - 0
package/aboot/src/include/linux/ext2_fs.h

@@ -0,0 +1,591 @@
+/*
+ *  linux/include/linux/ext2_fs.h
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ *  from
+ *
+ *  linux/include/linux/minix_fs.h
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+#ifndef _LINUX_EXT2_FS_H
+#define _LINUX_EXT2_FS_H
+
+#include <linux/types.h>
+#include <linux/magic.h>
+#include <linux/fs.h>
+
+/*
+ * The second extended filesystem constants/structures
+ */
+
+/*
+ * Define EXT2FS_DEBUG to produce debug messages
+ */
+#undef EXT2FS_DEBUG
+
+/*
+ * Define EXT2_RESERVATION to reserve data blocks for expanding files
+ */
+#define EXT2_DEFAULT_RESERVE_BLOCKS     8
+/*max window size: 1024(direct blocks) + 3([t,d]indirect blocks) */
+#define EXT2_MAX_RESERVE_BLOCKS         1027
+#define EXT2_RESERVE_WINDOW_NOT_ALLOCATED 0
+/*
+ * The second extended file system version
+ */
+#define EXT2FS_DATE		"95/08/09"
+#define EXT2FS_VERSION		"0.5b"
+
+/*
+ * Debug code
+ */
+#ifdef EXT2FS_DEBUG
+#	define ext2_debug(f, a...)	{ \
+					printk ("EXT2-fs DEBUG (%s, %d): %s:", \
+						__FILE__, __LINE__, __func__); \
+				  	printk (f, ## a); \
+					}
+#else
+#	define ext2_debug(f, a...)	/**/
+#endif
+
+/*
+ * Special inode numbers
+ */
+#define	EXT2_BAD_INO		 1	/* Bad blocks inode */
+#define EXT2_ROOT_INO		 2	/* Root inode */
+#define EXT2_BOOT_LOADER_INO	 5	/* Boot loader inode */
+#define EXT2_UNDEL_DIR_INO	 6	/* Undelete directory inode */
+
+/* First non-reserved inode for old ext2 filesystems */
+#define EXT2_GOOD_OLD_FIRST_INO	11
+
+#ifdef __KERNEL__
+#include <linux/ext2_fs_sb.h>
+static inline struct ext2_sb_info *EXT2_SB(struct super_block *sb)
+{
+	return sb->s_fs_info;
+}
+#else
+/* Assume that user mode programs are passing in an ext2fs superblock, not
+ * a kernel struct super_block.  This will allow us to call the feature-test
+ * macros from user land. */
+#define EXT2_SB(sb)	(sb)
+#endif
+
+/*
+ * Maximal count of links to a file
+ */
+#define EXT2_LINK_MAX		32000
+
+/*
+ * Macro-instructions used to manage several block sizes
+ */
+#define EXT2_MIN_BLOCK_SIZE		1024
+#define	EXT2_MAX_BLOCK_SIZE		4096
+#define EXT2_MIN_BLOCK_LOG_SIZE		  10
+#ifdef __KERNEL__
+# define EXT2_BLOCK_SIZE(s)		((s)->s_blocksize)
+#else
+# define EXT2_BLOCK_SIZE(s)		(EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
+#endif
+#define	EXT2_ADDR_PER_BLOCK(s)		(EXT2_BLOCK_SIZE(s) / sizeof (__u32))
+#ifdef __KERNEL__
+# define EXT2_BLOCK_SIZE_BITS(s)	((s)->s_blocksize_bits)
+#else
+# define EXT2_BLOCK_SIZE_BITS(s)	((s)->s_log_block_size + 10)
+#endif
+#ifdef __KERNEL__
+#define	EXT2_ADDR_PER_BLOCK_BITS(s)	(EXT2_SB(s)->s_addr_per_block_bits)
+#define EXT2_INODE_SIZE(s)		(EXT2_SB(s)->s_inode_size)
+#define EXT2_FIRST_INO(s)		(EXT2_SB(s)->s_first_ino)
+#else
+#define EXT2_INODE_SIZE(s)	(((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
+				 EXT2_GOOD_OLD_INODE_SIZE : \
+				 (s)->s_inode_size)
+#define EXT2_FIRST_INO(s)	(((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
+				 EXT2_GOOD_OLD_FIRST_INO : \
+				 (s)->s_first_ino)
+#endif
+
+/*
+ * Macro-instructions used to manage fragments
+ */
+#define EXT2_MIN_FRAG_SIZE		1024
+#define	EXT2_MAX_FRAG_SIZE		4096
+#define EXT2_MIN_FRAG_LOG_SIZE		  10
+#ifdef __KERNEL__
+# define EXT2_FRAG_SIZE(s)		(EXT2_SB(s)->s_frag_size)
+# define EXT2_FRAGS_PER_BLOCK(s)	(EXT2_SB(s)->s_frags_per_block)
+#else
+# define EXT2_FRAG_SIZE(s)		(EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size)
+# define EXT2_FRAGS_PER_BLOCK(s)	(EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s))
+#endif
+
+/*
+ * Structure of a blocks group descriptor
+ */
+struct ext2_group_desc
+{
+	__le32	bg_block_bitmap;		/* Blocks bitmap block */
+	__le32	bg_inode_bitmap;		/* Inodes bitmap block */
+	__le32	bg_inode_table;		/* Inodes table block */
+	__le16	bg_free_blocks_count;	/* Free blocks count */
+	__le16	bg_free_inodes_count;	/* Free inodes count */
+	__le16	bg_used_dirs_count;	/* Directories count */
+	__le16	bg_pad;
+	__le32	bg_reserved[3];
+};
+
+/*
+ * Macro-instructions used to manage group descriptors
+ */
+#ifdef __KERNEL__
+# define EXT2_BLOCKS_PER_GROUP(s)	(EXT2_SB(s)->s_blocks_per_group)
+# define EXT2_DESC_PER_BLOCK(s)		(EXT2_SB(s)->s_desc_per_block)
+# define EXT2_INODES_PER_GROUP(s)	(EXT2_SB(s)->s_inodes_per_group)
+# define EXT2_DESC_PER_BLOCK_BITS(s)	(EXT2_SB(s)->s_desc_per_block_bits)
+#else
+# define EXT2_BLOCKS_PER_GROUP(s)	((s)->s_blocks_per_group)
+# define EXT2_DESC_PER_BLOCK(s)		(EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
+# define EXT2_INODES_PER_GROUP(s)	((s)->s_inodes_per_group)
+#endif
+
+/*
+ * Constants relative to the data blocks
+ */
+#define	EXT2_NDIR_BLOCKS		12
+#define	EXT2_IND_BLOCK			EXT2_NDIR_BLOCKS
+#define	EXT2_DIND_BLOCK			(EXT2_IND_BLOCK + 1)
+#define	EXT2_TIND_BLOCK			(EXT2_DIND_BLOCK + 1)
+#define	EXT2_N_BLOCKS			(EXT2_TIND_BLOCK + 1)
+
+/*
+ * Inode flags (GETFLAGS/SETFLAGS)
+ */
+#define	EXT2_SECRM_FL			FS_SECRM_FL	/* Secure deletion */
+#define	EXT2_UNRM_FL			FS_UNRM_FL	/* Undelete */
+#define	EXT2_COMPR_FL			FS_COMPR_FL	/* Compress file */
+#define EXT2_SYNC_FL			FS_SYNC_FL	/* Synchronous updates */
+#define EXT2_IMMUTABLE_FL		FS_IMMUTABLE_FL	/* Immutable file */
+#define EXT2_APPEND_FL			FS_APPEND_FL	/* writes to file may only append */
+#define EXT2_NODUMP_FL			FS_NODUMP_FL	/* do not dump file */
+#define EXT2_NOATIME_FL			FS_NOATIME_FL	/* do not update atime */
+/* Reserved for compression usage... */
+#define EXT2_DIRTY_FL			FS_DIRTY_FL
+#define EXT2_COMPRBLK_FL		FS_COMPRBLK_FL	/* One or more compressed clusters */
+#define EXT2_NOCOMP_FL			FS_NOCOMP_FL	/* Don't compress */
+#define EXT2_ECOMPR_FL			FS_ECOMPR_FL	/* Compression error */
+/* End compression flags --- maybe not all used */	
+#define EXT2_BTREE_FL			FS_BTREE_FL	/* btree format dir */
+#define EXT2_INDEX_FL			FS_INDEX_FL	/* hash-indexed directory */
+#define EXT2_IMAGIC_FL			FS_IMAGIC_FL	/* AFS directory */
+#define EXT2_JOURNAL_DATA_FL		FS_JOURNAL_DATA_FL /* Reserved for ext3 */
+#define EXT2_NOTAIL_FL			FS_NOTAIL_FL	/* file tail should not be merged */
+#define EXT2_DIRSYNC_FL			FS_DIRSYNC_FL	/* dirsync behaviour (directories only) */
+#define EXT2_TOPDIR_FL			FS_TOPDIR_FL	/* Top of directory hierarchies*/
+#define EXT2_RESERVED_FL		FS_RESERVED_FL	/* reserved for ext2 lib */
+
+#define EXT2_FL_USER_VISIBLE		FS_FL_USER_VISIBLE	/* User visible flags */
+#define EXT2_FL_USER_MODIFIABLE		FS_FL_USER_MODIFIABLE	/* User modifiable flags */
+
+/* Flags that should be inherited by new inodes from their parent. */
+#define EXT2_FL_INHERITED (EXT2_SECRM_FL | EXT2_UNRM_FL | EXT2_COMPR_FL |\
+			   EXT2_SYNC_FL | EXT2_NODUMP_FL |\
+			   EXT2_NOATIME_FL | EXT2_COMPRBLK_FL |\
+			   EXT2_NOCOMP_FL | EXT2_JOURNAL_DATA_FL |\
+			   EXT2_NOTAIL_FL | EXT2_DIRSYNC_FL)
+
+/* Flags that are appropriate for regular files (all but dir-specific ones). */
+#define EXT2_REG_FLMASK (~(EXT2_DIRSYNC_FL | EXT2_TOPDIR_FL))
+
+/* Flags that are appropriate for non-directories/regular files. */
+#define EXT2_OTHER_FLMASK (EXT2_NODUMP_FL | EXT2_NOATIME_FL)
+
+/* Mask out flags that are inappropriate for the given type of inode. */
+static inline __u32 ext2_mask_flags(umode_t mode, __u32 flags)
+{
+	if (S_ISDIR(mode))
+		return flags;
+	else if (S_ISREG(mode))
+		return flags & EXT2_REG_FLMASK;
+	else
+		return flags & EXT2_OTHER_FLMASK;
+}
+
+/*
+ * ioctl commands
+ */
+#define	EXT2_IOC_GETFLAGS		FS_IOC_GETFLAGS
+#define	EXT2_IOC_SETFLAGS		FS_IOC_SETFLAGS
+#define	EXT2_IOC_GETVERSION		FS_IOC_GETVERSION
+#define	EXT2_IOC_SETVERSION		FS_IOC_SETVERSION
+#define	EXT2_IOC_GETRSVSZ		_IOR('f', 5, long)
+#define	EXT2_IOC_SETRSVSZ		_IOW('f', 6, long)
+
+/*
+ * ioctl commands in 32 bit emulation
+ */
+#define EXT2_IOC32_GETFLAGS		FS_IOC32_GETFLAGS
+#define EXT2_IOC32_SETFLAGS		FS_IOC32_SETFLAGS
+#define EXT2_IOC32_GETVERSION		FS_IOC32_GETVERSION
+#define EXT2_IOC32_SETVERSION		FS_IOC32_SETVERSION
+
+/*
+ * Structure of an inode on the disk
+ */
+struct ext2_inode {
+	__le16	i_mode;		/* File mode */
+	__le16	i_uid;		/* Low 16 bits of Owner Uid */
+	__le32	i_size;		/* Size in bytes */
+	__le32	i_atime;	/* Access time */
+	__le32	i_ctime;	/* Creation time */
+	__le32	i_mtime;	/* Modification time */
+	__le32	i_dtime;	/* Deletion Time */
+	__le16	i_gid;		/* Low 16 bits of Group Id */
+	__le16	i_links_count;	/* Links count */
+	__le32	i_blocks;	/* Blocks count */
+	__le32	i_flags;	/* File flags */
+	union {
+		struct {
+			__le32  l_i_reserved1;
+		} linux1;
+		struct {
+			__le32  h_i_translator;
+		} hurd1;
+		struct {
+			__le32  m_i_reserved1;
+		} masix1;
+	} osd1;				/* OS dependent 1 */
+	__le32	i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
+	__le32	i_generation;	/* File version (for NFS) */
+	__le32	i_file_acl;	/* File ACL */
+	__le32	i_dir_acl;	/* Directory ACL */
+	__le32	i_faddr;	/* Fragment address */
+	union {
+		struct {
+			__u8	l_i_frag;	/* Fragment number */
+			__u8	l_i_fsize;	/* Fragment size */
+			__u16	i_pad1;
+			__le16	l_i_uid_high;	/* these 2 fields    */
+			__le16	l_i_gid_high;	/* were reserved2[0] */
+			__u32	l_i_reserved2;
+		} linux2;
+		struct {
+			__u8	h_i_frag;	/* Fragment number */
+			__u8	h_i_fsize;	/* Fragment size */
+			__le16	h_i_mode_high;
+			__le16	h_i_uid_high;
+			__le16	h_i_gid_high;
+			__le32	h_i_author;
+		} hurd2;
+		struct {
+			__u8	m_i_frag;	/* Fragment number */
+			__u8	m_i_fsize;	/* Fragment size */
+			__u16	m_pad1;
+			__u32	m_i_reserved2[2];
+		} masix2;
+	} osd2;				/* OS dependent 2 */
+};
+
+#define i_size_high	i_dir_acl
+
+#if defined(__KERNEL__) || defined(__linux__)
+#define i_reserved1	osd1.linux1.l_i_reserved1
+#define i_frag		osd2.linux2.l_i_frag
+#define i_fsize		osd2.linux2.l_i_fsize
+#define i_uid_low	i_uid
+#define i_gid_low	i_gid
+#define i_uid_high	osd2.linux2.l_i_uid_high
+#define i_gid_high	osd2.linux2.l_i_gid_high
+#define i_reserved2	osd2.linux2.l_i_reserved2
+#endif
+
+#ifdef	__hurd__
+#define i_translator	osd1.hurd1.h_i_translator
+#define i_frag		osd2.hurd2.h_i_frag
+#define i_fsize		osd2.hurd2.h_i_fsize
+#define i_uid_high	osd2.hurd2.h_i_uid_high
+#define i_gid_high	osd2.hurd2.h_i_gid_high
+#define i_author	osd2.hurd2.h_i_author
+#endif
+
+#ifdef	__masix__
+#define i_reserved1	osd1.masix1.m_i_reserved1
+#define i_frag		osd2.masix2.m_i_frag
+#define i_fsize		osd2.masix2.m_i_fsize
+#define i_reserved2	osd2.masix2.m_i_reserved2
+#endif
+
+/*
+ * File system states
+ */
+#define	EXT2_VALID_FS			0x0001	/* Unmounted cleanly */
+#define	EXT2_ERROR_FS			0x0002	/* Errors detected */
+
+/*
+ * Mount flags
+ */
+#define EXT2_MOUNT_CHECK		0x000001  /* Do mount-time checks */
+#define EXT2_MOUNT_OLDALLOC		0x000002  /* Don't use the new Orlov allocator */
+#define EXT2_MOUNT_GRPID		0x000004  /* Create files with directory's group */
+#define EXT2_MOUNT_DEBUG		0x000008  /* Some debugging messages */
+#define EXT2_MOUNT_ERRORS_CONT		0x000010  /* Continue on errors */
+#define EXT2_MOUNT_ERRORS_RO		0x000020  /* Remount fs ro on errors */
+#define EXT2_MOUNT_ERRORS_PANIC		0x000040  /* Panic on errors */
+#define EXT2_MOUNT_MINIX_DF		0x000080  /* Mimics the Minix statfs */
+#define EXT2_MOUNT_NOBH			0x000100  /* No buffer_heads */
+#define EXT2_MOUNT_NO_UID32		0x000200  /* Disable 32-bit UIDs */
+#define EXT2_MOUNT_XATTR_USER		0x004000  /* Extended user attributes */
+#define EXT2_MOUNT_POSIX_ACL		0x008000  /* POSIX Access Control Lists */
+#define EXT2_MOUNT_XIP			0x010000  /* Execute in place */
+#define EXT2_MOUNT_USRQUOTA		0x020000  /* user quota */
+#define EXT2_MOUNT_GRPQUOTA		0x040000  /* group quota */
+#define EXT2_MOUNT_RESERVATION		0x080000  /* Preallocation */
+
+
+#define clear_opt(o, opt)		o &= ~EXT2_MOUNT_##opt
+#define set_opt(o, opt)			o |= EXT2_MOUNT_##opt
+#define test_opt(sb, opt)		(EXT2_SB(sb)->s_mount_opt & \
+					 EXT2_MOUNT_##opt)
+/*
+ * Maximal mount counts between two filesystem checks
+ */
+#define EXT2_DFL_MAX_MNT_COUNT		20	/* Allow 20 mounts */
+#define EXT2_DFL_CHECKINTERVAL		0	/* Don't use interval check */
+
+/*
+ * Behaviour when detecting errors
+ */
+#define EXT2_ERRORS_CONTINUE		1	/* Continue execution */
+#define EXT2_ERRORS_RO			2	/* Remount fs read-only */
+#define EXT2_ERRORS_PANIC		3	/* Panic */
+#define EXT2_ERRORS_DEFAULT		EXT2_ERRORS_CONTINUE
+
+/*
+ * Structure of the super block
+ */
+struct ext2_super_block {
+	__le32	s_inodes_count;		/* Inodes count */
+	__le32	s_blocks_count;		/* Blocks count */
+	__le32	s_r_blocks_count;	/* Reserved blocks count */
+	__le32	s_free_blocks_count;	/* Free blocks count */
+	__le32	s_free_inodes_count;	/* Free inodes count */
+	__le32	s_first_data_block;	/* First Data Block */
+	__le32	s_log_block_size;	/* Block size */
+	__le32	s_log_frag_size;	/* Fragment size */
+	__le32	s_blocks_per_group;	/* # Blocks per group */
+	__le32	s_frags_per_group;	/* # Fragments per group */
+	__le32	s_inodes_per_group;	/* # Inodes per group */
+	__le32	s_mtime;		/* Mount time */
+	__le32	s_wtime;		/* Write time */
+	__le16	s_mnt_count;		/* Mount count */
+	__le16	s_max_mnt_count;	/* Maximal mount count */
+	__le16	s_magic;		/* Magic signature */
+	__le16	s_state;		/* File system state */
+	__le16	s_errors;		/* Behaviour when detecting errors */
+	__le16	s_minor_rev_level; 	/* minor revision level */
+	__le32	s_lastcheck;		/* time of last check */
+	__le32	s_checkinterval;	/* max. time between checks */
+	__le32	s_creator_os;		/* OS */
+	__le32	s_rev_level;		/* Revision level */
+	__le16	s_def_resuid;		/* Default uid for reserved blocks */
+	__le16	s_def_resgid;		/* Default gid for reserved blocks */
+	/*
+	 * These fields are for EXT2_DYNAMIC_REV superblocks only.
+	 *
+	 * Note: the difference between the compatible feature set and
+	 * the incompatible feature set is that if there is a bit set
+	 * in the incompatible feature set that the kernel doesn't
+	 * know about, it should refuse to mount the filesystem.
+	 * 
+	 * e2fsck's requirements are more strict; if it doesn't know
+	 * about a feature in either the compatible or incompatible
+	 * feature set, it must abort and not try to meddle with
+	 * things it doesn't understand...
+	 */
+	__le32	s_first_ino; 		/* First non-reserved inode */
+	__le16   s_inode_size; 		/* size of inode structure */
+	__le16	s_block_group_nr; 	/* block group # of this superblock */
+	__le32	s_feature_compat; 	/* compatible feature set */
+	__le32	s_feature_incompat; 	/* incompatible feature set */
+	__le32	s_feature_ro_compat; 	/* readonly-compatible feature set */
+	__u8	s_uuid[16];		/* 128-bit uuid for volume */
+	char	s_volume_name[16]; 	/* volume name */
+	char	s_last_mounted[64]; 	/* directory where last mounted */
+	__le32	s_algorithm_usage_bitmap; /* For compression */
+	/*
+	 * Performance hints.  Directory preallocation should only
+	 * happen if the EXT2_COMPAT_PREALLOC flag is on.
+	 */
+	__u8	s_prealloc_blocks;	/* Nr of blocks to try to preallocate*/
+	__u8	s_prealloc_dir_blocks;	/* Nr to preallocate for dirs */
+	__u16	s_padding1;
+	/*
+	 * Journaling support valid if EXT3_FEATURE_COMPAT_HAS_JOURNAL set.
+	 */
+	__u8	s_journal_uuid[16];	/* uuid of journal superblock */
+	__u32	s_journal_inum;		/* inode number of journal file */
+	__u32	s_journal_dev;		/* device number of journal file */
+	__u32	s_last_orphan;		/* start of list of inodes to delete */
+	__u32	s_hash_seed[4];		/* HTREE hash seed */
+	__u8	s_def_hash_version;	/* Default hash version to use */
+	__u8	s_reserved_char_pad;
+	__u16	s_reserved_word_pad;
+	__le32	s_default_mount_opts;
+ 	__le32	s_first_meta_bg; 	/* First metablock block group */
+	__u32	s_reserved[190];	/* Padding to the end of the block */
+};
+
+/*
+ * Codes for operating systems
+ */
+#define EXT2_OS_LINUX		0
+#define EXT2_OS_HURD		1
+#define EXT2_OS_MASIX		2
+#define EXT2_OS_FREEBSD		3
+#define EXT2_OS_LITES		4
+
+/*
+ * Revision levels
+ */
+#define EXT2_GOOD_OLD_REV	0	/* The good old (original) format */
+#define EXT2_DYNAMIC_REV	1 	/* V2 format w/ dynamic inode sizes */
+
+#define EXT2_CURRENT_REV	EXT2_GOOD_OLD_REV
+#define EXT2_MAX_SUPP_REV	EXT2_DYNAMIC_REV
+
+#define EXT2_GOOD_OLD_INODE_SIZE 128
+
+/*
+ * Feature set definitions
+ */
+
+#define EXT2_HAS_COMPAT_FEATURE(sb,mask)			\
+	( EXT2_SB(sb)->s_es->s_feature_compat & cpu_to_le32(mask) )
+#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask)			\
+	( EXT2_SB(sb)->s_es->s_feature_ro_compat & cpu_to_le32(mask) )
+#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask)			\
+	( EXT2_SB(sb)->s_es->s_feature_incompat & cpu_to_le32(mask) )
+#define EXT2_SET_COMPAT_FEATURE(sb,mask)			\
+	EXT2_SB(sb)->s_es->s_feature_compat |= cpu_to_le32(mask)
+#define EXT2_SET_RO_COMPAT_FEATURE(sb,mask)			\
+	EXT2_SB(sb)->s_es->s_feature_ro_compat |= cpu_to_le32(mask)
+#define EXT2_SET_INCOMPAT_FEATURE(sb,mask)			\
+	EXT2_SB(sb)->s_es->s_feature_incompat |= cpu_to_le32(mask)
+#define EXT2_CLEAR_COMPAT_FEATURE(sb,mask)			\
+	EXT2_SB(sb)->s_es->s_feature_compat &= ~cpu_to_le32(mask)
+#define EXT2_CLEAR_RO_COMPAT_FEATURE(sb,mask)			\
+	EXT2_SB(sb)->s_es->s_feature_ro_compat &= ~cpu_to_le32(mask)
+#define EXT2_CLEAR_INCOMPAT_FEATURE(sb,mask)			\
+	EXT2_SB(sb)->s_es->s_feature_incompat &= ~cpu_to_le32(mask)
+
+#define EXT2_FEATURE_COMPAT_DIR_PREALLOC	0x0001
+#define EXT2_FEATURE_COMPAT_IMAGIC_INODES	0x0002
+#define EXT3_FEATURE_COMPAT_HAS_JOURNAL		0x0004
+#define EXT2_FEATURE_COMPAT_EXT_ATTR		0x0008
+#define EXT2_FEATURE_COMPAT_RESIZE_INO		0x0010
+#define EXT2_FEATURE_COMPAT_DIR_INDEX		0x0020
+#define EXT2_FEATURE_COMPAT_ANY			0xffffffff
+
+#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER	0x0001
+#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE	0x0002
+#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR	0x0004
+#define EXT2_FEATURE_RO_COMPAT_ANY		0xffffffff
+
+#define EXT2_FEATURE_INCOMPAT_COMPRESSION	0x0001
+#define EXT2_FEATURE_INCOMPAT_FILETYPE		0x0002
+#define EXT3_FEATURE_INCOMPAT_RECOVER		0x0004
+#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV	0x0008
+#define EXT2_FEATURE_INCOMPAT_META_BG		0x0010
+#define EXT2_FEATURE_INCOMPAT_ANY		0xffffffff
+
+#define EXT2_FEATURE_COMPAT_SUPP	EXT2_FEATURE_COMPAT_EXT_ATTR
+#define EXT2_FEATURE_INCOMPAT_SUPP	(EXT2_FEATURE_INCOMPAT_FILETYPE| \
+					 EXT2_FEATURE_INCOMPAT_META_BG)
+#define EXT2_FEATURE_RO_COMPAT_SUPP	(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
+					 EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
+					 EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
+#define EXT2_FEATURE_RO_COMPAT_UNSUPPORTED	~EXT2_FEATURE_RO_COMPAT_SUPP
+#define EXT2_FEATURE_INCOMPAT_UNSUPPORTED	~EXT2_FEATURE_INCOMPAT_SUPP
+
+/*
+ * Default values for user and/or group using reserved blocks
+ */
+#define	EXT2_DEF_RESUID		0
+#define	EXT2_DEF_RESGID		0
+
+/*
+ * Default mount options
+ */
+#define EXT2_DEFM_DEBUG		0x0001
+#define EXT2_DEFM_BSDGROUPS	0x0002
+#define EXT2_DEFM_XATTR_USER	0x0004
+#define EXT2_DEFM_ACL		0x0008
+#define EXT2_DEFM_UID16		0x0010
+    /* Not used by ext2, but reserved for use by ext3 */
+#define EXT3_DEFM_JMODE		0x0060 
+#define EXT3_DEFM_JMODE_DATA	0x0020
+#define EXT3_DEFM_JMODE_ORDERED	0x0040
+#define EXT3_DEFM_JMODE_WBACK	0x0060
+
+/*
+ * Structure of a directory entry
+ */
+#define EXT2_NAME_LEN 255
+
+struct ext2_dir_entry {
+	__le32	inode;			/* Inode number */
+	__le16	rec_len;		/* Directory entry length */
+	__le16	name_len;		/* Name length */
+	char	name[EXT2_NAME_LEN];	/* File name */
+};
+
+/*
+ * The new version of the directory entry.  Since EXT2 structures are
+ * stored in intel byte order, and the name_len field could never be
+ * bigger than 255 chars, it's safe to reclaim the extra byte for the
+ * file_type field.
+ */
+struct ext2_dir_entry_2 {
+	__le32	inode;			/* Inode number */
+	__le16	rec_len;		/* Directory entry length */
+	__u8	name_len;		/* Name length */
+	__u8	file_type;
+	char	name[EXT2_NAME_LEN];	/* File name */
+};
+
+/*
+ * Ext2 directory file types.  Only the low 3 bits are used.  The
+ * other bits are reserved for now.
+ */
+enum {
+	EXT2_FT_UNKNOWN		= 0,
+	EXT2_FT_REG_FILE	= 1,
+	EXT2_FT_DIR		= 2,
+	EXT2_FT_CHRDEV		= 3,
+	EXT2_FT_BLKDEV		= 4,
+	EXT2_FT_FIFO		= 5,
+	EXT2_FT_SOCK		= 6,
+	EXT2_FT_SYMLINK		= 7,
+	EXT2_FT_MAX
+};
+
+/*
+ * EXT2_DIR_PAD defines the directory entries boundaries
+ *
+ * NOTE: It must be a multiple of 4
+ */
+#define EXT2_DIR_PAD		 	4
+#define EXT2_DIR_ROUND 			(EXT2_DIR_PAD - 1)
+#define EXT2_DIR_REC_LEN(name_len)	(((name_len) + 8 + EXT2_DIR_ROUND) & \
+					 ~EXT2_DIR_ROUND)
+#define EXT2_MAX_REC_LEN		((1<<16)-1)
+
+#endif	/* _LINUX_EXT2_FS_H */

+ 51 - 0
package/aboot/src/include/pal.h

@@ -0,0 +1,51 @@
+#ifndef __ALPHA_PAL_H
+#define __ALPHA_PAL_H
+
+/*
+ * Common PAL-code
+ */
+#define PAL_halt	  0
+#define PAL_cflush	  1
+#define PAL_draina	  2
+#define PAL_bpt		128
+#define PAL_bugchk	129
+#define PAL_chmk	131
+#define PAL_callsys	131
+#define PAL_imb		134
+#define PAL_rduniq	158
+#define PAL_wruniq	159
+#define PAL_gentrap	170
+#define PAL_nphalt	190
+
+/*
+ * VMS specific PAL-code
+ */
+#define PAL_swppal	10
+#define PAL_mfpr_vptb	41
+
+/*
+ * OSF specific PAL-code
+ */
+#define PAL_cserve	 9
+#define PAL_wripir	13
+#define PAL_rdmces	16
+#define PAL_wrmces	17
+#define PAL_wrfen	43
+#define PAL_wrvptptr	45
+#define PAL_jtopal	46
+#define PAL_swpctx	48
+#define PAL_wrval	49
+#define PAL_rdval	50
+#define PAL_tbi		51
+#define PAL_wrent	52
+#define PAL_swpipl	53
+#define PAL_rdps	54
+#define PAL_wrkgp	55
+#define PAL_wrusp	56
+#define PAL_wrperfmon	57
+#define PAL_rdusp	58
+#define PAL_whami	60
+#define PAL_retsys	61
+#define PAL_rti		63
+
+#endif /* __ALPHA_PAL_H */

+ 68 - 0
package/aboot/src/include/setjmp.h

@@ -0,0 +1,68 @@
+/*
+ * @COPYRIGHT@
+ * 
+ * x-kernel v3.2
+ * 
+ * Copyright (c) 1993,1991,1990  Arizona Board of Regents
+ * 
+ * @COPYRIGHT@
+ *
+ * $RCSfile: setjmp.h,v $
+ *
+ * HISTORY
+ * $Log: setjmp.h,v $
+ * Revision 1.1.1.1  2004/04/25 20:38:20  vorlon
+ * Initial import of upstream source
+ *
+ * Revision 1.1.1.1  2001/10/08 23:03:52  wgwoods
+ * initial import of CVS source from alphalinux.org, plus a couple bugfixes
+ *
+ * Revision 1.1.1.1  2000/05/03 03:58:22  dhd
+ * Initial import (from 0.7 release)
+ *
+ * Revision 1.1  1995/03/06  16:41:07  davidm
+ * Initial revision
+ *
+ * Revision 1.1  1994/10/07  00:47:11  davidm
+ * Initial revision
+ *
+ */
+#ifndef _setjmp_h
+#define _setjmp_h
+
+#define		JB_GP		0x00
+#define		JB_SP		0x08
+#define		JB_RA		0x10
+#define		JB_S0		0x18
+#define		JB_S1		0x20
+#define		JB_S2		0x28
+#define		JB_S3		0x30
+#define		JB_S4		0x38
+#define		JB_S5		0x40
+#define		JB_S6		0x48
+#define		JB_MAGIC	0x50
+# ifndef SCOUT_FPU_SUPPORT
+#  define JBLEN			(0x58 / 8)
+# else
+#  define	JB_F2		0x58
+#  define	JB_F3		0x60
+#  define	JB_F4		0x68
+#  define	JB_F5		0x70
+#  define	JB_F6		0x78
+#  define	JB_F7		0x80
+#  define	JB_F8		0x88
+#  define	JB_F9		0x90
+#  define 	JBLEN		(0x98 / 8)
+# endif /* SCOUT_FPU_SUPPORT */
+
+#define	JBMAGIC	0x2ceb1ade
+
+#ifndef LANGUAGE_ASSEMBLY
+
+typedef long	jmp_buf[JBLEN];
+
+extern void	_longjmp (jmp_buf, int);
+extern int	_setjmp (jmp_buf);
+
+#endif /* LANGUAGE_ASSEMBLY */
+#endif /* _setjmp_h */

+ 31 - 0
package/aboot/src/include/string.h

@@ -0,0 +1,31 @@
+/* 
+ * aboot/include/string.h 
+ * prototypes for the functions in lib/string.c.
+ * We used to use the definitions from linux/string.h but more recent
+ * kernels don't provide these to userspace code.
+ */
+
+#include <stddef.h>
+
+#include <linux/types.h>
+
+extern char * ___strtok;
+extern char * strcpy(char *,const char *);
+extern char * strncpy(char *,const char *, size_t);
+extern char * strcat(char *, const char *);
+extern char * strncat(char *, const char *, size_t);
+extern int strcmp(const char *,const char *);
+extern int strncmp(const char *,const char *,size_t);
+extern char * strchr(const char *,int);
+extern char * strrchr(const char *,int);
+extern size_t strlen(const char *);
+extern size_t strnlen(const char *, size_t);
+extern size_t strspn(const char *,const char *);
+extern char * strpbrk(const char * cs,const char * ct);
+extern char * strtok(char * s,const char * ct);
+extern void * memset(void * s, int c, size_t count);
+extern void bcopy(const void * src, void * dest, size_t count);
+extern void * memcpy(void * dest,const void *src,size_t count);
+extern void * memmove(void * dest,const void *src,size_t count);
+extern int memcmp(const void * cs,const void * ct,size_t count);
+extern void * memscan(void * addr, unsigned char c, size_t size);

+ 326 - 0
package/aboot/src/include/system.h

@@ -0,0 +1,326 @@
+#ifndef __ALPHA_SYSTEM_H
+#define __ALPHA_SYSTEM_H
+
+#include <asm/pal.h>
+#define PAGE_SHIFT	13
+#define PAGE_SIZE	(1UL << PAGE_SHIFT)
+#define PAGE_OFFSET	0xfffffc0000000000UL
+
+
+/*
+ * System defines.. Note that this is included both from .c and .S
+ * files, so it does only defines, not any C code.
+ */
+
+/*
+ * We leave one page for the initial stack page, and one page for
+ * the initial process structure. Also, the console eats 3 MB for
+ * the initial bootloader (one of which we can reclaim later).
+ */
+#define BOOT_PCB	0x20000000
+#define BOOT_ADDR	0x20000000
+/* Remove when official MILO sources have ELF support: */
+#define BOOT_SIZE	(16*1024)
+
+#ifdef CONFIG_ALPHA_LEGACY_START_ADDRESS
+#define KERNEL_START_PHYS	0x300000 /* Old bootloaders hardcoded this.  */
+#else
+#define KERNEL_START_PHYS	0x1000000 /* required: Wildfire/Titan/Marvel */
+#endif
+
+#define KERNEL_START	(PAGE_OFFSET+KERNEL_START_PHYS)
+#define SWAPPER_PGD	KERNEL_START
+#define INIT_STACK	(PAGE_OFFSET+KERNEL_START_PHYS+0x02000)
+#define EMPTY_PGT	(PAGE_OFFSET+KERNEL_START_PHYS+0x04000)
+#define EMPTY_PGE	(PAGE_OFFSET+KERNEL_START_PHYS+0x08000)
+#define ZERO_PGE	(PAGE_OFFSET+KERNEL_START_PHYS+0x0A000)
+
+#define START_ADDR	(PAGE_OFFSET+KERNEL_START_PHYS+0x10000)
+
+/*
+ * This is setup by the secondary bootstrap loader.  Because
+ * the zero page is zeroed out as soon as the vm system is
+ * initialized, we need to copy things out into a more permanent
+ * place.
+ */
+#define PARAM			ZERO_PGE
+#define COMMAND_LINE		((char*)(PARAM + 0x0000))
+#define INITRD_START		(*(unsigned long *) (PARAM+0x100))
+#define INITRD_SIZE		(*(unsigned long *) (PARAM+0x108))
+
+#ifndef __ASSEMBLY__
+#include <linux/kernel.h>
+
+/*
+ * This is the logout header that should be common to all platforms
+ * (assuming they are running OSF/1 PALcode, I guess).
+ */
+struct el_common {
+	unsigned int	size;		/* size in bytes of logout area */
+	unsigned int	sbz1	: 30;	/* should be zero */
+	unsigned int	err2	:  1;	/* second error */
+	unsigned int	retry	:  1;	/* retry flag */
+	unsigned int	proc_offset;	/* processor-specific offset */
+	unsigned int	sys_offset;	/* system-specific offset */
+	unsigned int	code;		/* machine check code */
+	unsigned int	frame_rev;	/* frame revision */
+};
+
+/* Machine Check Frame for uncorrectable errors (Large format)
+ *      --- This is used to log uncorrectable errors such as
+ *          double bit ECC errors.
+ *      --- These errors are detected by both processor and systems.
+ */
+struct el_common_EV5_uncorrectable_mcheck {
+        unsigned long   shadow[8];        /* Shadow reg. 8-14, 25           */
+        unsigned long   paltemp[24];      /* PAL TEMP REGS.                 */
+        unsigned long   exc_addr;         /* Address of excepting instruction*/
+        unsigned long   exc_sum;          /* Summary of arithmetic traps.   */
+        unsigned long   exc_mask;         /* Exception mask (from exc_sum). */
+        unsigned long   pal_base;         /* Base address for PALcode.      */
+        unsigned long   isr;              /* Interrupt Status Reg.          */
+        unsigned long   icsr;             /* CURRENT SETUP OF EV5 IBOX      */
+        unsigned long   ic_perr_stat;     /* I-CACHE Reg. <11> set Data parity
+                                                         <12> set TAG parity*/
+        unsigned long   dc_perr_stat;     /* D-CACHE error Reg. Bits set to 1:
+                                                     <2> Data error in bank 0
+                                                     <3> Data error in bank 1
+                                                     <4> Tag error in bank 0
+                                                     <5> Tag error in bank 1 */
+        unsigned long   va;               /* Effective VA of fault or miss. */
+        unsigned long   mm_stat;          /* Holds the reason for D-stream 
+                                             fault or D-cache parity errors */
+        unsigned long   sc_addr;          /* Address that was being accessed
+                                             when EV5 detected Secondary cache
+                                             failure.                 */
+        unsigned long   sc_stat;          /* Helps determine if the error was
+                                             TAG/Data parity(Secondary Cache)*/
+        unsigned long   bc_tag_addr;      /* Contents of EV5 BC_TAG_ADDR    */
+        unsigned long   ei_addr;          /* Physical address of any transfer
+                                             that is logged in EV5 EI_STAT */
+        unsigned long   fill_syndrome;    /* For correcting ECC errors.     */
+        unsigned long   ei_stat;          /* Helps identify reason of any 
+                                             processor uncorrectable error
+                                             at its external interface.     */
+        unsigned long   ld_lock;          /* Contents of EV5 LD_LOCK register*/
+};
+
+struct el_common_EV6_mcheck {
+	unsigned int FrameSize;		/* Bytes, including this field */
+	unsigned int FrameFlags;	/* <31> = Retry, <30> = Second Error */
+	unsigned int CpuOffset;		/* Offset to CPU-specific info */
+	unsigned int SystemOffset;	/* Offset to system-specific info */
+	unsigned int MCHK_Code;
+	unsigned int MCHK_Frame_Rev;
+	unsigned long I_STAT;		/* EV6 Internal Processor Registers */
+	unsigned long DC_STAT;		/* (See the 21264 Spec) */
+	unsigned long C_ADDR;
+	unsigned long DC1_SYNDROME;
+	unsigned long DC0_SYNDROME;
+	unsigned long C_STAT;
+	unsigned long C_STS;
+	unsigned long MM_STAT;
+	unsigned long EXC_ADDR;
+	unsigned long IER_CM;
+	unsigned long ISUM;
+	unsigned long RESERVED0;
+	unsigned long PAL_BASE;
+	unsigned long I_CTL;
+	unsigned long PCTX;
+};
+
+extern void halt(void) __attribute__((noreturn));
+#define __halt() __asm__ __volatile__ ("call_pal %0 #halt" : : "i" (PAL_halt))
+
+#define switch_to(P,N,L)						 \
+  do {									 \
+    (L) = alpha_switch_to(virt_to_phys(&task_thread_info(N)->pcb), (P)); \
+    check_mmu_context();						 \
+  } while (0)
+
+struct task_struct;
+extern struct task_struct *alpha_switch_to(unsigned long, struct task_struct*);
+
+/*
+ * On SMP systems, when the scheduler does migration-cost autodetection,
+ * it needs a way to flush as much of the CPU's caches as possible.
+ *
+ * TODO: fill this in!
+ */
+static inline void sched_cacheflush(void)
+{
+}
+
+#define imb() \
+__asm__ __volatile__ ("call_pal %0 #imb" : : "i" (PAL_imb) : "memory")
+
+#define draina() \
+__asm__ __volatile__ ("call_pal %0 #draina" : : "i" (PAL_draina) : "memory")
+
+enum implver_enum {
+	IMPLVER_EV4,
+	IMPLVER_EV5,
+	IMPLVER_EV6
+};
+
+#ifdef CONFIG_ALPHA_GENERIC
+#define implver()				\
+({ unsigned long __implver;			\
+   __asm__ ("implver %0" : "=r"(__implver));	\
+   (enum implver_enum) __implver; })
+#else
+/* Try to eliminate some dead code.  */
+#ifdef CONFIG_ALPHA_EV4
+#define implver() IMPLVER_EV4
+#endif
+#ifdef CONFIG_ALPHA_EV5
+#define implver() IMPLVER_EV5
+#endif
+#if defined(CONFIG_ALPHA_EV6)
+#define implver() IMPLVER_EV6
+#endif
+#endif
+
+enum amask_enum {
+	AMASK_BWX = (1UL << 0),
+	AMASK_FIX = (1UL << 1),
+	AMASK_CIX = (1UL << 2),
+	AMASK_MAX = (1UL << 8),
+	AMASK_PRECISE_TRAP = (1UL << 9),
+};
+
+#define amask(mask)						\
+({ unsigned long __amask, __input = (mask);			\
+   __asm__ ("amask %1,%0" : "=r"(__amask) : "rI"(__input));	\
+   __amask; })
+
+#define __CALL_PAL_R0(NAME, TYPE)				\
+static inline TYPE NAME(void)					\
+{								\
+	register TYPE __r0 __asm__("$0");			\
+	__asm__ __volatile__(					\
+		"call_pal %1 # " #NAME				\
+		:"=r" (__r0)					\
+		:"i" (PAL_ ## NAME)				\
+		:"$1", "$16", "$22", "$23", "$24", "$25");	\
+	return __r0;						\
+}
+
+#define __CALL_PAL_W1(NAME, TYPE0)				\
+static inline void NAME(TYPE0 arg0)				\
+{								\
+	register TYPE0 __r16 __asm__("$16") = arg0;		\
+	__asm__ __volatile__(					\
+		"call_pal %1 # "#NAME				\
+		: "=r"(__r16)					\
+		: "i"(PAL_ ## NAME), "0"(__r16)			\
+		: "$1", "$22", "$23", "$24", "$25");		\
+}
+
+#define __CALL_PAL_W2(NAME, TYPE0, TYPE1)			\
+static inline void NAME(TYPE0 arg0, TYPE1 arg1)			\
+{								\
+	register TYPE0 __r16 __asm__("$16") = arg0;		\
+	register TYPE1 __r17 __asm__("$17") = arg1;		\
+	__asm__ __volatile__(					\
+		"call_pal %2 # "#NAME				\
+		: "=r"(__r16), "=r"(__r17)			\
+		: "i"(PAL_ ## NAME), "0"(__r16), "1"(__r17)	\
+		: "$1", "$22", "$23", "$24", "$25");		\
+}
+
+#define __CALL_PAL_RW1(NAME, RTYPE, TYPE0)			\
+static inline RTYPE NAME(TYPE0 arg0)				\
+{								\
+	register RTYPE __r0 __asm__("$0");			\
+	register TYPE0 __r16 __asm__("$16") = arg0;		\
+	__asm__ __volatile__(					\
+		"call_pal %2 # "#NAME				\
+		: "=r"(__r16), "=r"(__r0)			\
+		: "i"(PAL_ ## NAME), "0"(__r16)			\
+		: "$1", "$22", "$23", "$24", "$25");		\
+	return __r0;						\
+}
+
+#define __CALL_PAL_RW2(NAME, RTYPE, TYPE0, TYPE1)		\
+static inline RTYPE NAME(TYPE0 arg0, TYPE1 arg1)		\
+{								\
+	register RTYPE __r0 __asm__("$0");			\
+	register TYPE0 __r16 __asm__("$16") = arg0;		\
+	register TYPE1 __r17 __asm__("$17") = arg1;		\
+	__asm__ __volatile__(					\
+		"call_pal %3 # "#NAME				\
+		: "=r"(__r16), "=r"(__r17), "=r"(__r0)		\
+		: "i"(PAL_ ## NAME), "0"(__r16), "1"(__r17)	\
+		: "$1", "$22", "$23", "$24", "$25");		\
+	return __r0;						\
+}
+
+__CALL_PAL_W1(cflush, unsigned long);
+__CALL_PAL_R0(rdmces, unsigned long);
+__CALL_PAL_R0(rdps, unsigned long);
+__CALL_PAL_R0(rdusp, unsigned long);
+__CALL_PAL_RW1(swpipl, unsigned long, unsigned long);
+__CALL_PAL_R0(whami, unsigned long);
+__CALL_PAL_W2(wrent, void*, unsigned long);
+__CALL_PAL_W1(wripir, unsigned long);
+__CALL_PAL_W1(wrkgp, unsigned long);
+__CALL_PAL_W1(wrmces, unsigned long);
+__CALL_PAL_RW2(wrperfmon, unsigned long, unsigned long, unsigned long);
+__CALL_PAL_W1(wrusp, unsigned long);
+__CALL_PAL_W1(wrvptptr, unsigned long);
+
+#define IPL_MIN		0
+#define IPL_SW0		1
+#define IPL_SW1		2
+#define IPL_DEV0	3
+#define IPL_DEV1	4
+#define IPL_TIMER	5
+#define IPL_PERF	6
+#define IPL_POWERFAIL	6
+#define IPL_MCHECK	7
+#define IPL_MAX		7
+
+#ifdef CONFIG_ALPHA_BROKEN_IRQ_MASK
+#undef IPL_MIN
+#define IPL_MIN		__min_ipl
+extern int __min_ipl;
+#endif
+
+#define getipl()		(rdps() & 7)
+#define setipl(ipl)		((void) swpipl(ipl))
+
+#define local_irq_disable()			do { setipl(IPL_MAX); barrier(); } while(0)
+#define local_irq_enable()			do { barrier(); setipl(IPL_MIN); } while(0)
+#define local_save_flags(flags)	((flags) = rdps())
+#define local_irq_save(flags)	do { (flags) = swpipl(IPL_MAX); barrier(); } while(0)
+#define local_irq_restore(flags)	do { barrier(); setipl(flags); barrier(); } while(0)
+
+#define irqs_disabled()	(getipl() == IPL_MAX)
+
+/*
+ * TB routines..
+ */
+#define __tbi(nr,arg,arg1...)					\
+({								\
+	register unsigned long __r16 __asm__("$16") = (nr);	\
+	register unsigned long __r17 __asm__("$17"); arg;	\
+	__asm__ __volatile__(					\
+		"call_pal %3 #__tbi"				\
+		:"=r" (__r16),"=r" (__r17)			\
+		:"0" (__r16),"i" (PAL_tbi) ,##arg1		\
+		:"$0", "$1", "$22", "$23", "$24", "$25");	\
+})
+
+#define tbi(x,y)	__tbi(x,__r17=(y),"1" (__r17))
+#define tbisi(x)	__tbi(1,__r17=(x),"1" (__r17))
+#define tbisd(x)	__tbi(2,__r17=(x),"1" (__r17))
+#define tbis(x)		__tbi(3,__r17=(x),"1" (__r17))
+#define tbiap()		__tbi(-1, /* no second argument */)
+#define tbia()		__tbi(-2, /* no second argument */)
+
+#endif /* __ASSEMBLY__ */
+
+#define arch_align_stack(x) (x)
+
+#endif

+ 691 - 0
package/aboot/src/include/ufs.h

@@ -0,0 +1,691 @@
+/*
+ * Copyright (c) 1982, 1986 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+/* 
+ * Mach Operating System
+ * Copyright (c) 1993 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * $Log: ufs.h,v $
+ * Revision 1.1.1.1  2004/04/25 20:38:21  vorlon
+ * Initial import of upstream source
+ *
+ * Revision 1.1.1.1  2001/10/08 23:03:52  wgwoods
+ * initial import of CVS source from alphalinux.org, plus a couple bugfixes
+ *
+ * Revision 1.1.1.1  2000/05/03 03:58:23  dhd
+ * Initial import (from 0.7 release)
+ *
+ * Revision 2.3  93/03/09  10:49:48  danner
+ * 	Make damn sure we get sys/types.h from the right place.
+ * 	[93/03/05            af]
+ * 
+ * Revision 2.2  93/02/05  08:01:43  danner
+ * 	Adapted for alpha.
+ * 	[93/02/04            af]
+ * 
+ * Revision 2.2  90/08/27  21:45:05  dbg
+ * 	Created.
+ * 	[90/07/16            dbg]
+ * 
+ */
+
+/*
+ * Common definitions for Berkeley Fast File System.
+ */
+#include <linux/types.h>
+
+#define DEV_BSIZE	512
+
+#ifndef NBBY
+#define	NBBY	8
+#endif
+
+/*
+ * The file system is made out of blocks of at most MAXBSIZE units,
+ * with smaller units (fragments) only in the last direct block.
+ * MAXBSIZE primarily determines the size of buffers in the buffer
+ * pool.  It may be made larger without any effect on existing
+ * file systems; however, making it smaller may make some file
+ * systems unmountable.
+ *
+ * Note that the disk devices are assumed to have DEV_BSIZE "sectors"
+ * and that fragments must be some multiple of this size.
+ */
+#define	MAXBSIZE	8192
+#define	MAXFRAG		8
+
+/*
+ * MAXPATHLEN defines the longest permissible path length
+ * after expanding symbolic links.
+ *
+ * MAXSYMLINKS defines the maximum number of symbolic links
+ * that may be expanded in a path name.  It should be set
+ * high enough to allow all legitimate uses, but halt infinite
+ * loops reasonably quickly.
+ */
+
+#define	MAXPATHLEN	1024
+#define	MAXSYMLINKS	8
+
+
+/*
+ * Error codes for file system errors.
+ */
+
+#define	FS_NOT_DIRECTORY	5000		/* not a directory */
+#define	FS_NO_ENTRY		5001		/* name not found */
+#define	FS_NAME_TOO_LONG	5002		/* name too long */
+#define	FS_SYMLINK_LOOP		5003		/* symbolic link loop */
+#define	FS_INVALID_FS		5004		/* bad file system */
+#define	FS_NOT_IN_FILE		5005		/* offset not in file */
+#define	FS_INVALID_PARAMETER	5006		/* bad parameter to
+						   a routine */
+/*
+ * Each disk drive contains some number of file systems.
+ * A file system consists of a number of cylinder groups.
+ * Each cylinder group has inodes and data.
+ *
+ * A file system is described by its super-block, which in turn
+ * describes the cylinder groups.  The super-block is critical
+ * data and is replicated in each cylinder group to protect against
+ * catastrophic loss.  This is done at `newfs' time and the critical
+ * super-block data does not change, so the copies need not be
+ * referenced further unless disaster strikes.
+ *
+ * For file system fs, the offsets of the various blocks of interest
+ * are given in the super block as:
+ *	[fs->fs_sblkno]		Super-block
+ *	[fs->fs_cblkno]		Cylinder group block
+ *	[fs->fs_iblkno]		Inode blocks
+ *	[fs->fs_dblkno]		Data blocks
+ * The beginning of cylinder group cg in fs, is given by
+ * the ``cgbase(fs, cg)'' macro.
+ *
+ * The first boot and super blocks are given in absolute disk addresses.
+ * The byte-offset forms are preferred, as they don't imply a sector size.
+ */
+#define BBSIZE		8192
+#define SBSIZE		8192
+#define	BBOFF		((off_t)(0))
+#define	SBOFF		((off_t)(BBOFF + BBSIZE))
+#define	BBLOCK		((__kernel_daddr_t)(0))
+#define	SBLOCK		((__kernel_daddr_t)(BBLOCK + BBSIZE / DEV_BSIZE))
+
+/*
+ * Addresses stored in inodes are capable of addressing fragments
+ * of `blocks'. File system blocks of at most size MAXBSIZE can 
+ * be optionally broken into 2, 4, or 8 pieces, each of which is
+ * addressable; these pieces may be DEV_BSIZE, or some multiple of
+ * a DEV_BSIZE unit.
+ *
+ * Large files consist of exclusively large data blocks.  To avoid
+ * undue wasted disk space, the last data block of a small file may be
+ * allocated as only as many fragments of a large block as are
+ * necessary.  The file system format retains only a single pointer
+ * to such a fragment, which is a piece of a single large block that
+ * has been divided.  The size of such a fragment is determinable from
+ * information in the inode, using the ``blksize(fs, ip, lbn)'' macro.
+ *
+ * The file system records space availability at the fragment level;
+ * to determine block availability, aligned fragments are examined.
+ *
+ * The root inode is the root of the file system.
+ * Inode 0 can't be used for normal purposes and
+ * historically bad blocks were linked to inode 1,
+ * thus the root inode is 2. (inode 1 is no longer used for
+ * this purpose, however numerous dump tapes make this
+ * assumption, so we are stuck with it)
+ */
+#define	ROOTINO		((__kernel_ino_t)2)	/* i number of all roots */
+
+/*
+ * MINBSIZE is the smallest allowable block size.
+ * In order to insure that it is possible to create files of size
+ * 2^32 with only two levels of indirection, MINBSIZE is set to 4096.
+ * MINBSIZE must be big enough to hold a cylinder group block,
+ * thus changes to (struct cg) must keep its size within MINBSIZE.
+ * Note that super blocks are always of size SBSIZE,
+ * and that both SBSIZE and MAXBSIZE must be >= MINBSIZE.
+ */
+#define MINBSIZE	4096
+
+/*
+ * The path name on which the file system is mounted is maintained
+ * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in 
+ * the super block for this name.
+ * The limit on the amount of summary information per file system
+ * is defined by MAXCSBUFS. It is currently parameterized for a
+ * maximum of two million cylinders.
+ */
+#define MAXMNTLEN 512
+#define MAXCSBUFS 32
+
+/*
+ * Per cylinder group information; summarized in blocks allocated
+ * from first cylinder group data blocks.  These blocks have to be
+ * read in from fs_csaddr (size fs_cssize) in addition to the
+ * super block.
+ *
+ * N.B. sizeof(struct csum) must be a power of two in order for
+ * the ``fs_cs'' macro to work (see below).
+ */
+struct csum {
+	int	cs_ndir;	/* number of directories */
+	int	cs_nbfree;	/* number of free blocks */
+	int	cs_nifree;	/* number of free inodes */
+	int	cs_nffree;	/* number of free frags */
+};
+
+typedef int ext_time_t;
+typedef struct {
+	unsigned int val[2];
+} quad;
+
+/*
+ * Super block for a file system.
+ */
+#define	FS_MAGIC	0x011954
+struct fs
+{
+	int	xxx1;			/* struct	fs *fs_link;*/
+	int	xxx2;			/* struct	fs *fs_rlink;*/
+	__kernel_daddr_t	fs_sblkno;		/* addr of super-block in filesys */
+	__kernel_daddr_t	fs_cblkno;		/* offset of cyl-block in filesys */
+	__kernel_daddr_t	fs_iblkno;		/* offset of inode-blocks in filesys */
+	__kernel_daddr_t	fs_dblkno;		/* offset of first data after cg */
+	int	fs_cgoffset;		/* cylinder group offset in cylinder */
+	int	fs_cgmask;		/* used to calc mod fs_ntrak */
+	ext_time_t fs_time;    		/* last time written */
+	int	fs_size;		/* number of blocks in fs */
+	int	fs_dsize;		/* number of data blocks in fs */
+	int	fs_ncg;			/* number of cylinder groups */
+	int	fs_bsize;		/* size of basic blocks in fs */
+	int	fs_fsize;		/* size of frag blocks in fs */
+	int	fs_frag;		/* number of frags in a block in fs */
+/* these are configuration parameters */
+	int	fs_minfree;		/* minimum percentage of free blocks */
+	int	fs_rotdelay;		/* num of ms for optimal next block */
+	int	fs_rps;			/* disk revolutions per second */
+/* these fields can be computed from the others */
+	int	fs_bmask;		/* ``blkoff'' calc of blk offsets */
+	int	fs_fmask;		/* ``fragoff'' calc of frag offsets */
+	int	fs_bshift;		/* ``lblkno'' calc of logical blkno */
+	int	fs_fshift;		/* ``numfrags'' calc number of frags */
+/* these are configuration parameters */
+	int	fs_maxcontig;		/* max number of contiguous blks */
+	int	fs_maxbpg;		/* max number of blks per cyl group */
+/* these fields can be computed from the others */
+	int	fs_fragshift;		/* block to frag shift */
+	int	fs_fsbtodb;		/* fsbtodb and dbtofsb shift constant */
+	int	fs_sbsize;		/* actual size of super block */
+	int	fs_csmask;		/* csum block offset */
+	int	fs_csshift;		/* csum block number */
+	int	fs_nindir;		/* value of NINDIR */
+	int	fs_inopb;		/* value of INOPB */
+	int	fs_nspf;		/* value of NSPF */
+/* yet another configuration parameter */
+	int	fs_optim;		/* optimization preference, see below */
+/* these fields are derived from the hardware */
+	int	fs_npsect;		/* # sectors/track including spares */
+	int	fs_interleave;		/* hardware sector interleave */
+	int	fs_trackskew;		/* sector 0 skew, per track */
+	int	fs_headswitch;		/* head switch time, usec */
+	int	fs_trkseek;		/* track-to-track seek, usec */
+/* sizes determined by number of cylinder groups and their sizes */
+	__kernel_daddr_t fs_csaddr;		/* blk addr of cyl grp summary area */
+	int	fs_cssize;		/* size of cyl grp summary area */
+	int	fs_cgsize;		/* cylinder group size */
+/* these fields are derived from the hardware */
+	int	fs_ntrak;		/* tracks per cylinder */
+	int	fs_nsect;		/* sectors per track */
+	int  	fs_spc;   		/* sectors per cylinder */
+/* this comes from the disk driver partitioning */
+	int	fs_ncyl;   		/* cylinders in file system */
+/* these fields can be computed from the others */
+	int	fs_cpg;			/* cylinders per group */
+	int	fs_ipg;			/* inodes per group */
+	int	fs_fpg;			/* blocks per group * fs_frag */
+/* this data must be re-computed after crashes */
+	struct	csum fs_cstotal;	/* cylinder summary information */
+/* these fields are cleared at mount time */
+	char   	fs_fmod;    		/* super block modified flag */
+	char   	fs_clean;    		/* file system is clean flag */
+	char   	fs_ronly;   		/* mounted read-only flag */
+	char   	fs_flags;   		/* currently unused flag */
+	char	fs_fsmnt[MAXMNTLEN];	/* name mounted on */
+/* these fields retain the current block allocation info */
+	int	fs_cgrotor;		/* last cg searched */
+#ifdef __alpha__
+	int	was_fs_csp[MAXCSBUFS];	/* unused on Alpha */
+#else
+	struct	csum *fs_csp[MAXCSBUFS];/* list of fs_cs info buffers */
+#endif
+	int	fs_cpc;			/* cyl per cycle in postbl */
+	short	fs_opostbl[16][8];	/* old rotation block list head */
+	int	fs_sparecon[56];	/* reserved for future constants */
+	quad	fs_qbmask;		/* ~fs_bmask - for use with quad size */
+	quad	fs_qfmask;		/* ~fs_fmask - for use with quad size */
+	int	fs_postblformat;	/* format of positional layout tables */
+	int	fs_nrpos;		/* number of rotaional positions */
+	int	fs_postbloff;		/* (short) rotation block list head */
+	int	fs_rotbloff;		/* (u_char) blocks for each rotation */
+	int	fs_magic;		/* magic number */
+	unsigned char	fs_space[1];		/* list of blocks for each rotation */
+/* actually longer */
+};
+/*
+ * Preference for optimization.
+ */
+#define FS_OPTTIME	0	/* minimize allocation time */
+#define FS_OPTSPACE	1	/* minimize disk fragmentation */
+
+/*
+ * Rotational layout table format types
+ */
+#define FS_42POSTBLFMT		-1	/* 4.2BSD rotational table format */
+#define FS_DYNAMICPOSTBLFMT	1	/* dynamic rotational table format */
+/*
+ * Macros for access to superblock array structures
+ */
+#define fs_postbl(fs, cylno) \
+    (((fs)->fs_postblformat == FS_42POSTBLFMT) \
+    ? ((fs)->fs_opostbl[cylno]) \
+    : ((short *)((char *)(fs) + (fs)->fs_postbloff) + (cylno) * (fs)->fs_nrpos))
+#define fs_rotbl(fs) \
+    (((fs)->fs_postblformat == FS_42POSTBLFMT) \
+    ? ((fs)->fs_space) \
+    : ((unsigned char *)((char *)(fs) + (fs)->fs_rotbloff)))
+
+/*
+ * Convert cylinder group to base address of its global summary info.
+ *
+ * N.B. This macro assumes that sizeof(struct csum) is a power of two.
+ */
+#define fs_cs(fs, indx) \
+	fs_csp[(indx) >> (fs)->fs_csshift][(indx) & ~(fs)->fs_csmask]
+
+/*
+ * Cylinder group block for a file system.
+ */
+#define	CG_MAGIC	0x090255
+struct	cg {
+	int	xxx1;			/* struct	cg *cg_link;*/
+	int	cg_magic;		/* magic number */
+	ext_time_t cg_time;		/* time last written */
+	int	cg_cgx;			/* we are the cgx'th cylinder group */
+	short	cg_ncyl;		/* number of cyl's this cg */
+	short	cg_niblk;		/* number of inode blocks this cg */
+	int	cg_ndblk;		/* number of data blocks this cg */
+	struct	csum cg_cs;		/* cylinder summary information */
+	int	cg_rotor;		/* position of last used block */
+	int	cg_frotor;		/* position of last used frag */
+	int	cg_irotor;		/* position of last used inode */
+	int	cg_frsum[MAXFRAG];	/* counts of available frags */
+	int	cg_btotoff;		/* (long) block totals per cylinder */
+	int	cg_boff;		/* (short) free block positions */
+	int	cg_iusedoff;		/* (char) used inode map */
+	int	cg_freeoff;		/* (u_char) free block map */
+	int	cg_nextfreeoff;		/* (u_char) next available space */
+	int	cg_sparecon[16];	/* reserved for future use */
+	unsigned char	cg_space[1];		/* space for cylinder group maps */
+/* actually longer */
+};
+/*
+ * Macros for access to cylinder group array structures
+ */
+#define cg_blktot(cgp) \
+    (((cgp)->cg_magic != CG_MAGIC) \
+    ? (((struct ocg *)(cgp))->cg_btot) \
+    : ((int *)((char *)(cgp) + (cgp)->cg_btotoff)))
+#define cg_blks(fs, cgp, cylno) \
+    (((cgp)->cg_magic != CG_MAGIC) \
+    ? (((struct ocg *)(cgp))->cg_b[cylno]) \
+    : ((short *)((char *)(cgp) + (cgp)->cg_boff) + (cylno) * (fs)->fs_nrpos))
+#define cg_inosused(cgp) \
+    (((cgp)->cg_magic != CG_MAGIC) \
+    ? (((struct ocg *)(cgp))->cg_iused) \
+    : ((char *)((char *)(cgp) + (cgp)->cg_iusedoff)))
+#define cg_blksfree(cgp) \
+    (((cgp)->cg_magic != CG_MAGIC) \
+    ? (((struct ocg *)(cgp))->cg_free) \
+    : ((unsigned char *)((char *)(cgp) + (cgp)->cg_freeoff)))
+#define cg_chkmagic(cgp) \
+    ((cgp)->cg_magic == CG_MAGIC || ((struct ocg *)(cgp))->cg_magic == CG_MAGIC)
+
+/*
+ * The following structure is defined
+ * for compatibility with old file systems.
+ */
+struct	ocg {
+	int	xxx1;			/* struct	ocg *cg_link;*/
+	int	xxx2;			/* struct	ocg *cg_rlink;*/
+	ext_time_t cg_time;		/* time last written */
+	int	cg_cgx;			/* we are the cgx'th cylinder group */
+	short	cg_ncyl;		/* number of cyl's this cg */
+	short	cg_niblk;		/* number of inode blocks this cg */
+	int	cg_ndblk;		/* number of data blocks this cg */
+	struct	csum cg_cs;		/* cylinder summary information */
+	int	cg_rotor;		/* position of last used block */
+	int	cg_frotor;		/* position of last used frag */
+	int	cg_irotor;		/* position of last used inode */
+	int	cg_frsum[8];		/* counts of available frags */
+	int	cg_btot[32];		/* block totals per cylinder */
+	short	cg_b[32][8];		/* positions of free blocks */
+	char	cg_iused[256];		/* used inode map */
+	int	cg_magic;		/* magic number */
+	unsigned char	cg_free[1];		/* free block map */
+/* actually longer */
+};
+
+/*
+ * Turn file system block numbers into disk block addresses.
+ * This maps file system blocks to device size blocks.
+ */
+#define fsbtodb(fs, b)	((b) << (fs)->fs_fsbtodb)
+#define	dbtofsb(fs, b)	((b) >> (fs)->fs_fsbtodb)
+
+/*
+ * Cylinder group macros to locate things in cylinder groups.
+ * They calc file system addresses of cylinder group data structures.
+ */
+#define	cgbase(fs, c)	((__kernel_daddr_t)((fs)->fs_fpg * (c)))
+#define cgstart(fs, c) \
+	(cgbase(fs, c) + (fs)->fs_cgoffset * ((c) & ~((fs)->fs_cgmask)))
+#define	cgsblock(fs, c)	(cgstart(fs, c) + (fs)->fs_sblkno)	/* super blk */
+#define	cgtod(fs, c)	(cgstart(fs, c) + (fs)->fs_cblkno)	/* cg block */
+#define	cgimin(fs, c)	(cgstart(fs, c) + (fs)->fs_iblkno)	/* inode blk */
+#define	cgdmin(fs, c)	(cgstart(fs, c) + (fs)->fs_dblkno)	/* 1st data */
+
+/*
+ * Macros for handling inode numbers:
+ *     inode number to file system block offset.
+ *     inode number to cylinder group number.
+ *     inode number to file system block address.
+ */
+#define	itoo(fs, x)	((x) % INOPB(fs))
+#define	itog(fs, x)	((x) / (fs)->fs_ipg)
+#define	itod(fs, x) \
+	((__kernel_daddr_t)(cgimin(fs, itog(fs, x)) + \
+	(blkstofrags((fs), (((x) % (fs)->fs_ipg) / INOPB(fs))))))
+
+/*
+ * Give cylinder group number for a file system block.
+ * Give cylinder group block number for a file system block.
+ */
+#define	dtog(fs, d)	((d) / (fs)->fs_fpg)
+#define	dtogd(fs, d)	((d) % (fs)->fs_fpg)
+
+/*
+ * Extract the bits for a block from a map.
+ * Compute the cylinder and rotational position of a cyl block addr.
+ */
+#define blkmap(fs, map, loc) \
+    (((map)[(loc) / NBBY] >> ((loc) % NBBY)) & (0xff >> (NBBY - (fs)->fs_frag)))
+#define cbtocylno(fs, bno) \
+    ((bno) * NSPF(fs) / (fs)->fs_spc)
+#define cbtorpos(fs, bno) \
+    (((bno) * NSPF(fs) % (fs)->fs_spc / (fs)->fs_nsect * (fs)->fs_trackskew + \
+     (bno) * NSPF(fs) % (fs)->fs_spc % (fs)->fs_nsect * (fs)->fs_interleave) % \
+     (fs)->fs_nsect * (fs)->fs_nrpos / (fs)->fs_npsect)
+
+/*
+ * The following macros optimize certain frequently calculated
+ * quantities by using shifts and masks in place of divisions
+ * modulos and multiplications.
+ */
+#define blkoff(fs, loc)		/* calculates (loc % fs->fs_bsize) */ \
+	((loc) & ~(fs)->fs_bmask)
+#define fragoff(fs, loc)	/* calculates (loc % fs->fs_fsize) */ \
+	((loc) & ~(fs)->fs_fmask)
+#define lblkno(fs, loc)		/* calculates (loc / fs->fs_bsize) */ \
+	((loc) >> (fs)->fs_bshift)
+#define numfrags(fs, loc)	/* calculates (loc / fs->fs_fsize) */ \
+	((loc) >> (fs)->fs_fshift)
+#define blkroundup(fs, size)	/* calculates roundup(size, fs->fs_bsize) */ \
+	(((size) + (fs)->fs_bsize - 1) & (fs)->fs_bmask)
+#define fragroundup(fs, size)	/* calculates roundup(size, fs->fs_fsize) */ \
+	(((size) + (fs)->fs_fsize - 1) & (fs)->fs_fmask)
+#define fragstoblks(fs, frags)	/* calculates (frags / fs->fs_frag) */ \
+	((frags) >> (fs)->fs_fragshift)
+#define blkstofrags(fs, blks)	/* calculates (blks * fs->fs_frag) */ \
+	((blks) << (fs)->fs_fragshift)
+#define fragnum(fs, fsb)	/* calculates (fsb % fs->fs_frag) */ \
+	((fsb) & ((fs)->fs_frag - 1))
+#define blknum(fs, fsb)		/* calculates rounddown(fsb, fs->fs_frag) */ \
+	((fsb) &~ ((fs)->fs_frag - 1))
+
+/*
+ * Determine the number of available frags given a
+ * percentage to hold in reserve
+ */
+#define freespace(fs, percentreserved) \
+	(blkstofrags((fs), (fs)->fs_cstotal.cs_nbfree) + \
+	(fs)->fs_cstotal.cs_nffree - ((fs)->fs_dsize * (percentreserved) / 100))
+
+/*
+ * Determining the size of a file block in the file system.
+ */
+#define blksize(fs, ip, lbn) \
+	(((lbn) >= NDADDR || (ip)->i_size >= ((lbn) + 1) << (fs)->fs_bshift) \
+	    ? (fs)->fs_bsize \
+	    : (fragroundup(fs, blkoff(fs, (ip)->i_size))))
+#define dblksize(fs, dip, lbn) \
+	(((lbn) >= NDADDR || (dip)->di_size >= ((lbn) + 1) << (fs)->fs_bshift) \
+	    ? (fs)->fs_bsize \
+	    : (fragroundup(fs, blkoff(fs, (dip)->di_size))))
+
+/*
+ * Number of disk sectors per block; assumes DEV_BSIZE byte sector size.
+ */
+#define	NSPB(fs)	((fs)->fs_nspf << (fs)->fs_fragshift)
+#define	NSPF(fs)	((fs)->fs_nspf)
+
+/*
+ * INOPB is the number of inodes in a secondary storage block.
+ */
+#define	INOPB(fs)	((fs)->fs_inopb)
+#define	INOPF(fs)	((fs)->fs_inopb >> (fs)->fs_fragshift)
+
+/*
+ * NINDIR is the number of indirects in a file system block.
+ */
+#define	NINDIR(fs)	((fs)->fs_nindir)
+
+/*
+ * Copyright (c) 1982, 1986, 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *	@(#)dir.h	7.6 (Berkeley) 5/9/89
+ */
+
+/*
+ * A directory consists of some number of blocks of DIRBLKSIZ
+ * bytes, where DIRBLKSIZ is chosen such that it can be transferred
+ * to disk in a single atomic operation (e.g. 512 bytes on most machines).
+ *
+ * Each DIRBLKSIZ byte block contains some number of directory entry
+ * structures, which are of variable length.  Each directory entry has
+ * a struct direct at the front of it, containing its inode number,
+ * the length of the entry, and the length of the name contained in
+ * the entry.  These are followed by the name padded to a 4 byte boundary
+ * with null bytes.  All names are guaranteed null terminated.
+ * The maximum length of a name in a directory is MAXNAMLEN.
+ *
+ * The macro DIRSIZ(dp) gives the amount of space required to represent
+ * a directory entry.  Free space in a directory is represented by
+ * entries which have dp->d_reclen > DIRSIZ(dp).  All DIRBLKSIZ bytes
+ * in a directory block are claimed by the directory entries.  This
+ * usually results in the last entry in a directory having a large
+ * dp->d_reclen.  When entries are deleted from a directory, the
+ * space is returned to the previous entry in the same directory
+ * block by increasing its dp->d_reclen.  If the first entry of
+ * a directory block is free, then its dp->d_ino is set to 0.
+ * Entries other than the first in a directory do not normally have
+ * dp->d_ino set to 0.
+ */
+#define DIRBLKSIZ	DEV_BSIZE
+#define	MAXNAMLEN	255
+
+struct	direct {
+	unsigned int	d_ino;			/* inode number of entry */
+	unsigned short	d_reclen;		/* length of this record */
+	unsigned short	d_namlen;		/* length of string in d_name */
+	char	d_name[MAXNAMLEN + 1];	/* name with length <= MAXNAMLEN */
+};
+
+/*
+ * The DIRSIZ macro gives the minimum record length which will hold
+ * the directory entry.  This requires the amount of space in struct direct
+ * without the d_name field, plus enough space for the name with a terminating
+ * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
+ */
+#undef DIRSIZ
+#define DIRSIZ(dp) \
+    ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
+
+/*
+ * The I node is the focus of all file activity in the BSD Fast File System.
+ * There is a unique inode allocated for each active file,
+ * each current directory, each mounted-on file, text file, and the root.
+ * An inode is 'named' by its dev/inumber pair. (iget/iget.c)
+ * Data in icommon is read in from permanent inode on volume.
+ */
+
+#define	NDADDR	12		/* direct addresses in inode */
+#define	NIADDR	3		/* indirect addresses in inode */
+
+#define	MAX_FASTLINK_SIZE	((NDADDR + NIADDR) * sizeof(__kernel_daddr_t))
+
+struct 	icommon {
+	unsigned short	ic_mode;	/*  0: mode and type of file */
+	short	ic_nlink;	/*  2: number of links to file */
+	unsigned short	ic_uid;		/*  4: owner's user id */
+	unsigned short	ic_gid;		/*  6: owner's group id */
+	long	ic_size;	/*  8: number of bytes in file */
+	ext_time_t ic_atime;	/* 16: time last accessed */
+	int	ic_atspare;
+	ext_time_t ic_mtime;	/* 24: time last modified */
+	int	ic_mtspare;
+	ext_time_t ic_ctime;	/* 32: last time inode changed */
+	int	ic_ctspare;
+	union {
+	    struct {
+		__kernel_daddr_t	Mb_db[NDADDR];	/* 40: disk block addresses */
+		__kernel_daddr_t	Mb_ib[NIADDR];	/* 88: indirect blocks */
+	    } ic_Mb;
+	    char	ic_Msymlink[MAX_FASTLINK_SIZE];
+					/* 40: symbolic link name */
+	} ic_Mun;
+#define	ic_db		ic_Mun.ic_Mb.Mb_db
+#define	ic_ib		ic_Mun.ic_Mb.Mb_ib
+#define	ic_symlink	ic_Mun.ic_Msymlink
+	int	ic_flags;	/* 100: status, currently unused */
+#define	IC_FASTLINK	0x0001		/* Symbolic link in inode */
+	int	ic_blocks;	/* 104: blocks actually held */
+	int	ic_gen;		/* 108: generation number */
+	int	ic_spare[4];	/* 112: reserved, currently unused */
+};
+
+#define	i_mode		i_ic.ic_mode
+#define	i_nlink		i_ic.ic_nlink
+#define	i_uid		i_ic.ic_uid
+#define	i_gid		i_ic.ic_gid
+#if	BYTE_MSF
+#define	i_size		i_ic.ic_size
+#else	/* BYTE_LSF */
+#define	i_size		i_ic.ic_size
+#endif
+#define	i_db		i_ic.ic_db
+#define	i_ib		i_ic.ic_ib
+#define	i_atime		i_ic.ic_atime
+#define	i_mtime		i_ic.ic_mtime
+#define	i_ctime		i_ic.ic_ctime
+#define i_blocks	i_ic.ic_blocks
+#define	i_rdev		i_ic.ic_db[0]
+#define	i_symlink	i_ic.ic_symlink
+#define i_flags		i_ic.ic_flags
+#define i_gen		i_ic.ic_gen
+
+/* modes */
+#define	IFMT		0170000		/* type of file */
+#define	IFCHR		0020000		/* character special */
+#define	IFDIR		0040000		/* directory */
+#define	IFBLK		0060000		/* block special */
+#define	IFREG		0100000		/* regular */
+#define	IFLNK		0120000		/* symbolic link */
+#define	IFSOCK		0140000		/* socket */
+
+#define	ISUID		04000		/* set user id on execution */
+#define	ISGID		02000		/* set group id on execution */
+#define	ISVTX		01000		/* save swapped text even after use */
+#define	IREAD		0400		/* read, write, execute permissions */
+#define	IWRITE		0200
+#define	IEXEC		0100
+
+/*
+ *	Same structure, but on disk.
+ */
+struct dinode {
+	union {
+	    struct icommon	di_com;
+	    char		di_char[128];
+	} di_un;
+};
+#define	di_ic	di_un.di_com
+
+struct dev_t {
+	int		handle;
+	unsigned int	first_block;
+	unsigned int	last_block;
+};
+
+typedef unsigned int recnum_t;
+

+ 24 - 0
package/aboot/src/include/utils.h

@@ -0,0 +1,24 @@
+#ifndef utils_h
+#define utils_h
+
+#include <stddef.h>
+
+#include "hwrpb.h"
+
+#ifdef TESTING
+#define pal_init()
+#else
+extern int		printf (const char *fmt, ...);
+extern struct pcb_struct *find_pa (unsigned long vptb, struct pcb_struct *pcb);
+extern void		pal_init (void);
+
+extern void *		malloc (size_t size);
+extern void		free (void *ptr);
+extern void		getline (char *buf, int maxlen);
+#endif
+
+extern int		check_memory(unsigned long, unsigned long);
+extern unsigned long	memory_end(void);
+extern unsigned long	free_mem_ptr;
+
+#endif /* utils_h */

+ 42 - 0
package/aboot/src/lib/Makefile

@@ -0,0 +1,42 @@
+ifndef ($(CC))
+CC		?= gcc
+endif
+
+override CPPFLAGS += -D__KERNEL__ -I../include
+override ASFLAGS += $(CPPFLAGS) -D__ASSEMBLY__ -traditional
+
+ifeq ($(TESTING),)
+ifeq ($(FOREIGN),"yes")
+override CFLAGS	+= -Os -Wall -fno-builtin
+else
+override CFLAGS	+= -Os -Wall -mno-fp-regs -fno-builtin
+endif
+else
+override CFLAGS	+= -Os -g3 -Wall
+endif
+
+ifeq ($(TESTING),)
+libaboot.a: vsprintf.o memcpy.o memset.o string.o _setjmp.o \
+	_longjmp.o isolib.o __divqu.o __remqu.o __divlu.o \
+	__remlu.o
+	ar cru $@ $?
+else
+libaboot.a: isolib.o
+	ar cru $@ $?
+endif
+
+clean:
+	rm -f libaboot.a *.o
+
+__divqu.o: divide.S
+	$(CC) -DDIV -c -o $@ divide.S
+
+__remqu.o: divide.S
+	$(CC) -DREM -c -o $@ divide.S
+
+__divlu.o: divide.S
+	$(CC) -DDIV -DINTSIZE -c -o $@ divide.S
+
+__remlu.o: divide.S
+	$(CC) -DREM -DINTSIZE -c -o $@ divide.S
+

+ 61 - 0
package/aboot/src/lib/_longjmp.S

@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1995	David Mosberger (davidm@cs.arizona.edu)
+ */
+#include <setjmp.h>
+#include "system.h"
+
+	.extern	printf
+
+	.globl	_longjmp
+	.ent	_longjmp
+
+_longjmp:
+	ldgp	$29, 0($27)
+
+	mov	$17, $0
+	lda	$1, JBMAGIC & 0xffff
+	ldah	$1, ((JBMAGIC >> 16) & 0xffff)($1)
+	cmoveq	$0, 1, $0		# ensure $0 != 0
+	
+	ldq	$2, JB_MAGIC($16)
+	subq	$1, $2, $1
+	ldq	$30, JB_SP($16)
+	bne	$1, bad_magic
+
+	ldq	 $9, JB_S0($16)
+	ldq	$10, JB_S1($16)
+	ldq	$11, JB_S2($16)
+	ldq	$12, JB_S3($16)
+	ldq	$13, JB_S4($16)
+	ldq	$14, JB_S5($16)
+	ldq	$15, JB_S6($16)
+	ldq	$29, JB_GP($16)
+	ldq	$26, JB_RA($16)
+#ifdef FPU
+	ldt	$f2, JB_F2($16)
+	ldt	$f3, JB_F3($16)
+	ldt	$f4, JB_F4($16)
+	ldt	$f5, JB_F5($16)
+	ldt	$f6, JB_F6($16)
+	ldt	$f7, JB_F7($16)
+	ldt	$f8, JB_F8($16)
+	ldt	$f9, JB_F9($16)
+#endif
+	ret	($26)
+
+	.data
+error_msg:
+#ifdef __osf__
+	.asciiz	"_longjmp: bad magic number"
+#else
+	.asciz	"_longjmp: bad magic number"
+#endif
+
+	.text
+bad_magic:
+	lda	$16, error_msg
+	lda	$27, printf
+	jsr	$27, printf
+	call_pal PAL_halt
+
+	.end _longjmp

+ 36 - 0
package/aboot/src/lib/_setjmp.S

@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 1995	David Mosberger (davidm@cs.arizona.edu)
+ */
+#include <setjmp.h>
+
+	.globl	_setjmp
+	.ent	_setjmp
+
+_setjmp:
+	stq	$29, JB_GP($16)
+	stq	$30, JB_SP($16)
+	stq	 $9, JB_S0($16)
+	stq	$10, JB_S1($16)
+	stq	$11, JB_S2($16)
+	stq	$12, JB_S3($16)
+	stq	$13, JB_S4($16)
+	stq	$14, JB_S5($16)
+	stq	$15, JB_S6($16)
+	stq	$26, JB_RA($16)
+#ifdef FPU
+	stt	$f2, JB_F2($16)
+	stt	$f3, JB_F3($16)
+	stt	$f4, JB_F4($16)
+	stt	$f5, JB_F5($16)
+	stt	$f6, JB_F6($16)
+	stt	$f7, JB_F7($16)
+	stt	$f8, JB_F8($16)
+	stt	$f9, JB_F9($16)
+#endif
+	lda	$1, JBMAGIC & 0xffff
+	ldah	$1, ((JBMAGIC >> 16) & 0xffff)($1)
+	stq	$1, JB_MAGIC($16)
+	clr	$0
+	ret	($26)
+
+	.end _setjmp

+ 160 - 0
package/aboot/src/lib/divide.S

@@ -0,0 +1,160 @@
+/*
+ * arch/alpha/lib/divide.S
+ *
+ * (C) 1995 Linus Torvalds
+ *
+ * Alpha division..
+ */
+
+/*
+ * The alpha chip doesn't provide hardware division, so we have to do it
+ * by hand.  The compiler expects the functions
+ *
+ *	__divqu: 64-bit unsigned long divide
+ *	__remqu: 64-bit unsigned long remainder
+ *	__divqs/__remqs: signed 64-bit
+ *	__divlu/__remlu: unsigned 32-bit
+ *	__divls/__remls: signed 32-bit
+ *
+ * These are not normal C functions: instead of the normal
+ * calling sequence, these expect their arguments in registers
+ * $24 and $25, and return the result in $27. Register $28 may
+ * be clobbered (assembly temporary), anything else must be saved. 
+ *
+ * In short: painful.
+ *
+ * This is a rather simple bit-at-a-time algorithm: it's very good
+ * at dividing random 64-bit numbers, but the more usual case where
+ * the divisor is small is handled better by the DEC algorithm
+ * using lookup tables. This uses much less memory, though, and is
+ * nicer on the cache.. Besides, I don't know the copyright status
+ * of the DEC code.
+ */
+
+/*
+ * My temporaries:
+ *	$0 - current bit
+ *	$1 - shifted divisor
+ *	$2 - modulus/quotient
+ *
+ *	$23 - return address
+ *	$24 - dividend
+ *	$25 - divisor
+ *
+ *	$27 - quotient/modulus
+ *	$28 - compare status
+ */
+
+#define halt .long 0
+
+/*
+ * Select function type and registers
+ */
+#define mask	$0
+#define divisor	$1
+#define compare $28
+
+#ifdef DIV
+#define func(x) __div##x
+#define modulus $2
+#define quotient $27
+#define GETSIGN(x) xor $24,$25,x
+#else
+#define func(x) __rem##x
+#define modulus $27
+#define quotient $2
+#define GETSIGN(x) bis $24,$24,x
+#endif
+
+/*
+ * For 32-bit operations, we need to extend to 64-bit
+ */
+#ifdef INTSIZE
+#define ufunction func(lu)
+#define sfunction func(l)
+#define LONGIFY(x) zapnot x,15,x
+#define SLONGIFY(x) addl x,0,x
+#else
+#define ufunction func(qu)
+#define sfunction func(q)
+#define LONGIFY(x)
+#define SLONGIFY(x)
+#endif
+
+.set noat
+.globl	ufunction
+.ent	ufunction
+ufunction:
+	subq	$30,32,$30
+	stq	$0, 0($30)
+	stq	$1, 8($30)
+	stq	$2,16($30)
+
+	bis	$25,$25,divisor
+	bis	$24,$24,modulus
+	bis	$31,$31,quotient
+	LONGIFY(divisor)
+	LONGIFY(modulus)
+	beq	divisor, 9f			/* div by zero */
+	bis	$31,1,mask
+
+	/* shift divisor left */
+1:	cmpult	divisor,modulus,compare
+	blt	divisor, 3f
+	addq	divisor,divisor,divisor
+	addq	mask,mask,mask
+	bne	compare,1b
+
+	/* ok, start to go right again.. */
+2:	srl	divisor,1,divisor
+	beq	mask,9f
+	srl	mask,1,mask
+3:	cmpule	divisor,modulus,compare
+	beq	compare,2b
+	addq	quotient,mask,quotient
+	beq	mask,9f
+	subq	modulus,divisor,modulus
+	br	2b
+
+9:	ldq	$0, 0($30)
+	ldq	$1, 8($30)
+	ldq	$2, 16($30)
+	addq	$30,32,$30
+	ret	$31,($23),1
+	.end	ufunction
+
+/*
+ * Uhh.. Ugly signed division. I'd rather not have it at all, but
+ * it's needed in some circumstances. There are different ways to
+ * handle this, really. This does:
+ * 	-a / b = a / -b = -(a / b)
+ *	-a % b = a % b
+ *	a % -b = -(a % b)
+ * which is probably not the best solution, but at least should
+ * have the property that (x/y)*y + (x%y) = x.
+ */
+.globl	sfunction
+.ent	sfunction
+sfunction:
+	bis	$24,$25,$28
+	SLONGIFY($28)
+	bge	$28,ufunction
+	subq	$30,32,$30
+	stq	$23,0($30)
+	stq	$24,8($30)
+	stq	$25,16($30)
+	subq	$31,$24,$28
+	cmovlt	$24,$28,$24	/* abs($24) */
+	subq	$31,$25,$28
+	cmovlt	$25,$28,$25	/* abs($25) */
+	bsr	$23,ufunction
+	ldq	$23,0($30)
+	ldq	$24,8($30)
+	ldq	$25,16($30)
+	addq	$30,32,$30
+	GETSIGN($28)
+	SLONGIFY($28)
+	bge	$28,1f
+	subq	$31,$27,$27
+1:	ret	$31,($23),1
+	.end	sfunction

+ 1590 - 0
package/aboot/src/lib/isolib.c

@@ -0,0 +1,1590 @@
+/* 
+ * This code is based on the ISO filesystem support in MILO (by
+ * Dave Rusling).
+ *
+ * This is a set of functions that provides minimal filesystem
+ * functionality to the Linux bootstrapper.  All we can do is
+ * open and read files... but that's all we need 8-)
+ */
+#include <linux/stat.h>
+#include <sys/types.h>
+
+#include "string.h"
+#include "iso.h"
+#include "isolib.h"
+#include "utils.h"
+
+/* iso9660 support code */
+
+#define MAX_OPEN_FILES 5
+
+static struct inode_table_entry {
+    struct iso_inode inode;
+    int inumber;
+    int free;
+    unsigned short old_mode;
+    unsigned size;
+    int nlink;
+    int mode;
+    void *start;
+} inode_table[MAX_OPEN_FILES];
+
+static unsigned long root_inode = 0;
+static struct isofs_super_block sb;
+static char data_block[1024];
+static char big_data_block[2048];
+
+#ifndef S_IRWXUGO
+# define S_IRWXUGO	(S_IRWXU|S_IRWXG|S_IRWXO)
+# define S_IXUGO	(S_IXUSR|S_IXGRP|S_IXOTH)
+# define S_IRUGO	(S_IRUSR|S_IRGRP|S_IROTH)
+#endif
+
+extern long iso_dev_read (void * buf, long offset, long size);
+
+static int parse_rock_ridge_inode(struct iso_directory_record * de,
+				  struct iso_inode * inode);
+static char *get_rock_ridge_symlink(struct iso_inode *inode);
+static int get_rock_ridge_filename(struct iso_directory_record * de,
+				   char * retname,
+				   struct iso_inode * inode);
+
+int
+isonum_711 (char * p)
+{
+	return (*p & 0xff);
+}
+
+
+int
+isonum_712 (char * p)
+{
+	int val;
+
+	val = *p;
+	if (val & 0x80)
+		val |= 0xffffff00;
+	return val;
+}
+
+
+int
+isonum_721 (char * p)
+{
+	return ((p[0] & 0xff) | ((p[1] & 0xff) << 8));
+}
+
+int
+isonum_722 (char * p)
+{
+	return (((p[0] & 0xff) << 8) | (p[1] & 0xff));
+}
+
+
+int
+isonum_723 (char * p)
+{
+	return isonum_721(p);
+}
+
+
+int
+isonum_731 (char * p)
+{
+	return ((p[0] & 0xff)
+		| ((p[1] & 0xff) << 8)
+		| ((p[2] & 0xff) << 16)
+		| ((p[3] & 0xff) << 24));
+}
+
+
+int
+isonum_732 (char * p)
+{
+	return (((p[0] & 0xff) << 24)
+		| ((p[1] & 0xff) << 16)
+		| ((p[2] & 0xff) << 8)
+		| (p[3] & 0xff));
+}
+
+
+int
+isonum_733 (char * p)
+{
+	return isonum_731(p);
+}
+
+
+static int
+iso_bmap (struct iso_inode *inode, int block)
+{
+	if (block < 0) {
+		printf("iso_bmap: block<0");
+		return 0;
+	}
+	return (inode->i_first_extent >> sb.s_blocksize_bits) + block;
+}
+
+static int
+iso_breadi (struct iso_inode *ip, long blkno, long nblks, char * buffer)
+{
+	long i_size, abs_blkno;
+
+	/* do some error checking */
+	if (!ip || !ip->i_first_extent)
+		return -1;
+
+	i_size = ((struct inode_table_entry *) ip)->size;
+	/* as in ext2.c - cons_read() doesn't really cope well with
+           EOF conditions - actually it should be fixed */
+	if ((blkno+nblks) * sb.s_blocksize > i_size)
+		nblks = ((i_size + sb.s_blocksize)
+			 / sb.s_blocksize) - blkno;
+
+	/* figure out which iso block number(s) we're being asked for */
+	abs_blkno = iso_bmap(ip, blkno);
+	if (!abs_blkno)
+		return -1;
+	/* now try and read them (easy since ISO files are continguous) */
+	return iso_dev_read(buffer, abs_blkno * sb.s_blocksize,
+			    nblks * sb.s_blocksize);
+}
+
+
+/*
+ * Release our hold on an inode.  Since this is a read-only application,
+ * don't worry about putting back any changes...
+ */
+static void
+iso_iput (struct iso_inode *ip)
+{
+	struct inode_table_entry *itp;
+
+	/* Find and free the inode table slot we used... */
+	itp = (struct inode_table_entry *) ip;
+
+	itp->inumber = 0;
+	itp->free = 1;
+}
+
+/*
+ * Read the specified inode from the disk and return it to the user.
+ * Returns NULL if the inode can't be read...
+ *
+ * Uses data_block
+ */
+static struct iso_inode *
+iso_iget (int ino)
+{
+	int i;
+	struct iso_inode *inode;
+	struct inode_table_entry *itp;
+	struct iso_directory_record * raw_inode;
+	unsigned char *pnt = NULL;
+	void *cpnt = NULL;
+	int high_sierra;
+	int block;
+
+#ifdef DEBUG_ISO
+	printf("iso_iget(ino=%d)\n", ino);
+#endif
+
+	/* find a free inode to play with */
+	inode = NULL;
+	itp = NULL;
+	for (i = 0; i < MAX_OPEN_FILES; i++) {
+		if (inode_table[i].free) {
+			itp = &(inode_table[i]);
+			inode = &(itp->inode);
+			break;
+		}
+	}
+	if ((inode == NULL) || (itp == NULL)) {
+		printf("iso9660 (iget): no free inodes\n");
+		return (NULL);
+	}
+
+	block = ino >> sb.s_blocksize_bits;
+	if (iso_dev_read(data_block, block * sb.s_blocksize, sb.s_blocksize)
+	    != sb.s_blocksize) {
+		printf("iso9660: unable to read i-node block");
+		return NULL;
+	}
+
+	pnt = ((unsigned char *) data_block + (ino & (sb.s_blocksize - 1)));
+	raw_inode = ((struct iso_directory_record *) pnt);
+	high_sierra = sb.s_high_sierra;
+
+	if ((ino & (sb.s_blocksize - 1)) + *pnt > sb.s_blocksize){
+		int frag1, offset;
+
+		offset = (ino & (sb.s_blocksize - 1));
+		frag1 = sb.s_blocksize - offset;
+		cpnt = big_data_block;
+		memcpy(cpnt, data_block + offset, frag1);
+		offset += *pnt - sb.s_blocksize; /* DUH! pnt would get
+                                                    wiped out by the
+                                                    iso_dev_read here. */
+		if (iso_dev_read(data_block, ++block * sb.s_blocksize,
+				 sb.s_blocksize)
+		    != sb.s_blocksize) {
+			printf("unable to read i-node block");
+			return NULL;
+		}
+		memcpy((char *)cpnt+frag1, data_block, offset);
+		pnt = ((unsigned char *) cpnt);
+		raw_inode = ((struct iso_directory_record *) pnt);
+	}
+
+	if (raw_inode->flags[-high_sierra] & 2) {
+		itp->mode = S_IRUGO | S_IXUGO | S_IFDIR;
+		itp->nlink = 1; /* Set to 1.  We know there are 2, but
+				   the find utility tries to optimize
+				   if it is 2, and it screws up.  It is
+				   easier to give 1 which tells find to
+				   do it the hard way. */
+	} else {
+		itp->mode = sb.s_mode; /* Everybody gets to read the file. */
+		itp->nlink = 1;
+		itp->mode |= S_IFREG;
+		/*
+		 * If there are no periods in the name, then set the
+		 * execute permission bit
+		 */
+		for(i=0; i< raw_inode->name_len[0]; i++)
+			if(raw_inode->name[i]=='.' || raw_inode->name[i]==';')
+				break;
+		if(i == raw_inode->name_len[0] || raw_inode->name[i] == ';') 
+			itp->mode |= S_IXUGO; /* execute permission */
+	}
+
+	itp->size = isonum_733 (raw_inode->size);
+
+	/* There are defective discs out there - we do this to protect
+	   ourselves.  A cdrom will never contain more than 700Mb */
+	if((itp->size < 0 || itp->size > 700000000) &&
+	   sb.s_cruft == 'n')
+	{
+		printf("Warning: defective cdrom.  "
+		       "Enabling \"cruft\" mount option.\n");
+		sb.s_cruft = 'y';
+	}
+
+	/*
+	 * Some dipshit decided to store some other bit of information
+	 * in the high byte of the file length.  Catch this and
+	 * holler.  WARNING: this will make it impossible for a file
+	 * to be > 16Mb on the CDROM!!!
+	 */
+	if(sb.s_cruft == 'y' && 
+	   itp->size & 0xff000000)
+	{
+		itp->size &= 0x00ffffff;
+	}
+
+	if (raw_inode->interleave[0]) {
+		printf("Interleaved files not (yet) supported.\n");
+		itp->size = 0;
+	}
+
+	/* I have no idea what file_unit_size is used for, so
+	   we will flag it for now */
+	if (raw_inode->file_unit_size[0] != 0){
+		printf("File unit size != 0 for ISO file (%d).\n", ino);
+	}
+
+	/* I have no idea what other flag bits are used for, so
+	   we will flag it for now */
+#ifdef DEBUG_ISO
+	if ((raw_inode->flags[-high_sierra] & ~2)!= 0){
+		printf("Unusual flag settings for ISO file (%d %x).\n",
+		       ino, raw_inode->flags[-high_sierra]);
+	}
+#endif
+
+	inode->i_first_extent = (isonum_733 (raw_inode->extent) + 
+				 isonum_711 (raw_inode->ext_attr_length))
+					 << sb.s_log_zone_size;
+
+	/* Now we check the Rock Ridge extensions for further info */
+
+	if (sb.s_rock) 
+		parse_rock_ridge_inode(raw_inode,inode);
+
+	/* Will be used for previous directory */
+	inode->i_backlink = 0xffffffff;
+	switch (sb.s_conversion) {
+	      case 'a':
+		inode->i_file_format = ISOFS_FILE_UNKNOWN; /* File type */
+		break;
+	      case 'b':
+		inode->i_file_format = ISOFS_FILE_BINARY; /* File type */
+		break;
+	      case 't':
+		inode->i_file_format = ISOFS_FILE_TEXT; /* File type */
+		break;
+	      case 'm':
+		inode->i_file_format = ISOFS_FILE_TEXT_M; /* File type */
+		break;
+	}
+
+	/* keep our inode table correct */
+	itp->free = 0;
+	itp->inumber = ino;
+
+	/* return a pointer to it */
+	return inode;
+}
+
+
+/*
+ * ok, we cannot use strncmp, as the name is not in our data space.
+ * Thus we'll have to use iso_match. No big problem. Match also makes
+ * some sanity tests.
+ *
+ * NOTE! unlike strncmp, iso_match returns 1 for success, 0 for failure.
+ */
+static int
+iso_match (int len, const char *name, const char *compare, int dlen)
+{
+	if (!compare)
+		return 0;
+
+#ifdef DEBUG_ISO
+	printf("iso_match: comparing %d chars of %s with %s\n",
+	       dlen, name, compare);
+#endif
+
+	/* check special "." and ".." files */
+	if (dlen == 1) {
+		/* "." */
+		if (compare[0] == 0) {
+			if (!len)
+				return 1;
+			compare = ".";
+		} else if (compare[0] == 1) {
+			compare = "..";
+			dlen = 2;
+		}
+	}
+	if (dlen != len)
+		return 0;
+	return !memcmp(name, compare, len);
+}
+
+/*
+ * Find an entry in the specified directory with the wanted name. It
+ * returns the cache buffer in which the entry was found, and the entry
+ * itself (as an inode number). It does NOT read the inode of the
+ * entry - you'll have to do that yourself if you want to.
+ *
+ * uses data_block
+ */
+static int
+iso_find_entry (struct iso_inode *dir, const char *name, int namelen,
+		unsigned long *ino, unsigned long *ino_back)
+{
+	unsigned long bufsize = sb.s_blocksize;
+	unsigned char bufbits = sb.s_blocksize_bits;
+	unsigned int block, f_pos, offset, inode_number = 0; /*shut up, gcc*/
+	void * cpnt = NULL;
+	unsigned int old_offset;
+	unsigned int backlink;
+	int dlen, match, i;
+	struct iso_directory_record * de;
+	char c;
+	struct inode_table_entry *itp = (struct inode_table_entry *) dir;
+
+	*ino = 0;
+	if (!dir) return -1;
+	
+	if (!(block = dir->i_first_extent)) return -1;
+  
+	f_pos = 0;
+	offset = 0;
+	block = iso_bmap(dir,f_pos >> bufbits);
+	if (!block) return -1;
+
+	if (iso_dev_read(data_block, block * sb.s_blocksize, sb.s_blocksize)
+	    != sb.s_blocksize) return -1;
+  
+	while (f_pos < itp->size) {
+		de = (struct iso_directory_record *) (data_block + offset);
+		backlink = itp->inumber;
+		inode_number = (block << bufbits) + (offset & (bufsize - 1));
+
+		/* If byte is zero, this is the end of file, or time to move to
+		   the next sector. Usually 2048 byte boundaries. */
+		
+		if (*((unsigned char *) de) == 0) {
+			offset = 0;
+
+			/* round f_pos up to the nearest blocksize */
+			f_pos = ((f_pos & ~(ISOFS_BLOCK_SIZE - 1))
+				 + ISOFS_BLOCK_SIZE);
+			block = iso_bmap(dir,f_pos>>bufbits);
+			if (!block) return -1;
+			if (iso_dev_read(data_block,
+					 block * sb.s_blocksize,
+					 sb.s_blocksize)
+				!= sb.s_blocksize) return -1;
+  			continue; /* Will kick out if past end of directory */
+		}
+
+		old_offset = offset;
+		offset += *((unsigned char *) de);
+		f_pos += *((unsigned char *) de);
+
+		/* Handle case where the directory entry spans two blocks.
+		   Usually 1024 byte boundaries */
+		if (offset >= bufsize) {
+		        unsigned int frag1;
+			frag1 = bufsize - old_offset;
+			cpnt = big_data_block;
+			memcpy(cpnt, data_block + old_offset, frag1);
+
+			de = (struct iso_directory_record *) cpnt;
+			offset = f_pos & (bufsize - 1);
+			block = iso_bmap(dir,f_pos>>bufbits);
+			if (!block) return -1;
+                        if (iso_dev_read(data_block,
+					 block * sb.s_blocksize,
+					 sb.s_blocksize)
+				!= sb.s_blocksize) return 0;
+			memcpy((char *)cpnt+frag1, data_block, offset);
+		}
+		
+		/* Handle the '.' case */
+		
+		if (de->name[0]==0 && de->name_len[0]==1) {
+		  inode_number = itp->inumber;
+		  backlink = 0;
+		}
+		
+		/* Handle the '..' case */
+
+		if (de->name[0]==1 && de->name_len[0]==1) {
+
+		  if((int) sb.s_firstdatazone != itp->inumber)
+  		    inode_number = (isonum_733(de->extent) + 
+			  	    isonum_711(de->ext_attr_length))
+				    << sb.s_log_zone_size;
+		  else
+		    inode_number = itp->inumber;
+		  backlink = 0;
+		}
+    
+		{
+		  /* should be sufficient, since get_rock_ridge_filename
+		   * truncates at 254 chars */
+		  char retname[256]; 
+		  dlen = get_rock_ridge_filename(de, retname, dir);
+		  if (dlen) {
+		    strcpy(de->name, retname);
+		  } else {
+		    dlen = isonum_711(de->name_len);
+		    if(sb.s_mapping == 'n') {
+		      for (i = 0; i < dlen; i++) {
+			c = de->name[i];
+			if (c >= 'A' && c <= 'Z') c |= 0x20;  /* lower case */
+			if (c == ';' && i == dlen-2
+			    && de->name[i+1] == '1') {
+			  dlen -= 2;
+			  break;
+			}
+			if (c == ';') c = '.';
+			de->name[i] = c;
+		      }
+		      /* This allows us to match with and without a trailing
+			 period.  */
+		      if(de->name[dlen-1] == '.' && namelen == dlen-1)
+			dlen--;
+		    }
+		  }
+		}
+		/*
+		 * Skip hidden or associated files unless unhide is set
+		 */
+		match = 0;
+		if(   !(de->flags[-sb.s_high_sierra] & 5)
+		   || sb.s_unhide == 'y' ) 
+		{
+		  match = iso_match(namelen, name, de->name, dlen);
+		}
+
+		if (cpnt) cpnt = NULL;
+
+		if (match) {
+		  if ((int) inode_number == -1) {
+		    /* Should never happen */
+		    printf("iso9660: error inode_number = -1\n");
+		    return -1;
+		  }
+
+		  *ino = inode_number;
+		  *ino_back = backlink;
+#ifdef DEBUG_ISO
+		  printf("iso_find_entry returning successfully (ino = %d)\n",
+			 inode_number);
+#endif
+		  return 0;
+		}
+	}
+#ifdef DEBUG_ISO
+		  printf("iso_find_entry returning unsuccessfully (ino = %d)\n",
+			 inode_number);
+#endif
+	return -1;
+}
+
+
+/*
+ *  Look up name in the current directory and return its corresponding
+ *  inode if it can be found.
+ *
+ */
+struct iso_inode *
+iso_lookup(struct iso_inode *dir, const char *name)
+{
+	struct inode_table_entry *itp = (struct inode_table_entry *) dir;
+	unsigned long ino, ino_back;
+	struct iso_inode *result = NULL;
+	int first, last;
+
+#ifdef DEBUG_ISO
+	printf("iso_lookup: %s\n", name);
+#endif
+
+	/* is the current inode a directory? */
+	if (!S_ISDIR(itp->mode)) {
+#ifdef DEBUG_ISO
+		printf("iso_lookup: inode %d not a directory\n", itp->inumber);
+#endif
+		iso_iput(dir);
+		return NULL;
+	}
+
+	/* work through the name finding each directory in turn */
+	ino = 0;
+	first = last = 0;
+	while (last < (int) strlen(name)) {
+		if (name[last] == '/') {
+			if (iso_find_entry(dir, &name[first], last - first, 
+					   &ino, &ino_back)) 
+				return NULL;
+			/* throw away the old directory inode, we
+			   don't need it anymore */
+			iso_iput(dir);
+
+			if (!(dir = iso_iget(ino))) 
+				return NULL;
+			first = last + 1;
+			last = first;
+		} else
+			last++;
+	}
+	{
+		int rv;
+		if ((rv = iso_find_entry(dir, &name[first], last - first, &ino, &ino_back))) {
+			iso_iput(dir);
+			return NULL;
+		}
+	}
+	if (!(result = iso_iget(ino))) {
+		iso_iput(dir);
+		return NULL;
+	}
+	/*
+	 * We need this backlink for the ".." entry unless the name
+	 * that we are looking up traversed a mount point (in which
+	 * case the inode may not even be on an iso9660 filesystem,
+	 * and writing to u.isofs_i would only cause memory
+	 * corruption).
+	 */
+	result->i_backlink = ino_back; 
+	
+	iso_iput(dir);
+	return result;
+}
+
+/* follow a symbolic link, returning the inode of the file it points to */
+static struct iso_inode *
+iso_follow_link(struct iso_inode *from, const char *basename) 
+{
+	struct inode_table_entry *itp = (struct inode_table_entry *)from;
+	struct iso_inode *root = iso_iget(root_inode);
+	/* HK: iso_iget expects an "int" but root_inode is "long" ?? */
+	struct iso_inode *result = NULL;
+	char *linkto;
+	
+#ifdef DEBUG_ISO
+	printf("iso_follow_link(%s): ",basename);
+#endif
+
+	if (!S_ISLNK(itp->mode)) /* Hey, that's not a link! */
+		return NULL;
+
+	if (!itp->size) 
+		return NULL;
+	
+	if (!(linkto = get_rock_ridge_symlink(from)))
+		return NULL;
+
+	linkto[itp->size]='\0';
+#ifdef DEBUG_ISO
+	printf("%s->%s\n",basename,linkto ? linkto : "[failed]");
+#endif
+	
+	/* Resolve relative links. */
+
+	if (linkto[0] !='/') {
+		char *end = strrchr(basename, '/');
+		if (end) {
+			char fullname[(end - basename + 1) + strlen(linkto) + 1];
+			strncpy(fullname, basename, end - basename + 1);
+			fullname[end - basename + 1] = '\0';
+			strcat(fullname, linkto);
+#ifdef DEBUG_ISO
+			printf("resolved to %s\n", fullname);
+#endif
+			result = iso_lookup(root,fullname);
+		} else {
+			/* Assume it's in the root */
+			result = iso_lookup(root,linkto);
+		}
+	} else {
+		result = iso_lookup(root,linkto);
+	}
+	free(linkto);
+	iso_iput(root);
+	return result;
+}
+
+/*
+ * look if the driver can tell the multi session redirection value
+ */
+static inline unsigned int
+iso_get_last_session (void)
+{
+#ifdef DEBUG_ISO 
+	printf("iso_get_last_session() called\n");
+#endif	
+	return 0;
+}
+
+
+int
+iso_read_super (void *data, int silent)
+{
+	static int first_time = 1;
+	int high_sierra;
+	unsigned int iso_blknum, vol_desc_start;
+	char rock = 'y';
+	int i;
+
+	struct iso_volume_descriptor *vdp;
+	struct hs_volume_descriptor *hdp;
+
+	struct iso_primary_descriptor *pri = NULL;
+	struct hs_primary_descriptor *h_pri = NULL;
+
+	struct iso_directory_record *rootp;
+
+	/* Initialize the inode table */
+	for (i = 0; i < MAX_OPEN_FILES; i++) {
+		inode_table[i].free = 1;
+		inode_table[i].inumber = 0;
+	}
+
+#ifdef DEBUG_ISO 
+	printf("iso_read_super() called\n");
+#endif	
+
+	/* set up the block size */
+	sb.s_blocksize = 1024;
+	sb.s_blocksize_bits = 10;
+
+	sb.s_high_sierra = high_sierra = 0; /* default is iso9660 */
+
+	vol_desc_start = iso_get_last_session();
+	
+	for (iso_blknum = vol_desc_start+16; iso_blknum < vol_desc_start+100; 
+	     iso_blknum++) {
+#ifdef DEBUG_ISO
+		printf("iso_read_super: iso_blknum=%d\n", iso_blknum);
+#endif
+		if (iso_dev_read(data_block, iso_blknum * 2048,
+				 sb.s_blocksize) != sb.s_blocksize)
+		{
+			printf("iso_read_super: bread failed, dev "
+			       "iso_blknum %d\n", iso_blknum);
+			return -1;
+		}
+		vdp = (struct iso_volume_descriptor *)data_block;
+		hdp = (struct hs_volume_descriptor *)data_block;
+
+		if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) {
+			if (isonum_711 (hdp->type) != ISO_VD_PRIMARY)
+				return -1;
+			if (isonum_711 (hdp->type) == ISO_VD_END)
+				return -1;
+
+			sb.s_high_sierra = 1;
+			high_sierra = 1;
+			rock = 'n';
+			h_pri = (struct hs_primary_descriptor *)vdp;
+			break;
+		}
+
+		if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) {
+			if (isonum_711 (vdp->type) != ISO_VD_PRIMARY)
+				return -1;
+			if (isonum_711 (vdp->type) == ISO_VD_END)
+				return -1;
+			
+			pri = (struct iso_primary_descriptor *)vdp;
+			break;
+		}
+	}
+	if(iso_blknum == vol_desc_start + 100) {
+		if (!silent)
+			printf("iso: Unable to identify CD-ROM format.\n");
+		return -1;
+	}
+	
+	if (high_sierra) {
+		rootp = (struct iso_directory_record *)
+			h_pri->root_directory_record;
+#if 0
+//See http://www.y-adagio.com/public/standards/iso_cdromr/sect_1.htm
+//Section 4.16 and 4.17 for explanation why this check is invalid
+		if (isonum_723 (h_pri->volume_set_size) != 1) {
+			printf("Multi-volume disks not (yet) supported.\n");
+			return -1;
+		};
+#endif
+		sb.s_nzones = isonum_733 (h_pri->volume_space_size);
+		sb.s_log_zone_size = 
+			isonum_723 (h_pri->logical_block_size);
+		sb.s_max_size = isonum_733(h_pri->volume_space_size);
+	} else {
+		rootp = (struct iso_directory_record *)
+			pri->root_directory_record;
+#if 0
+//See http://www.y-adagio.com/public/standards/iso_cdromr/sect_1.htm
+//Section 4.16 and 4.17 for explanation why this check is invalid
+		if (isonum_723 (pri->volume_set_size) != 1) {
+			printf("Multi-volume disks not (yet) supported.\n");
+			return -1;
+		}
+#endif
+		sb.s_nzones = isonum_733 (pri->volume_space_size);
+		sb.s_log_zone_size = isonum_723 (pri->logical_block_size);
+		sb.s_max_size = isonum_733(pri->volume_space_size);
+	}
+
+	sb.s_ninodes = 0; /* No way to figure this out easily */
+
+	/* RDE: convert log zone size to bit shift */
+
+	switch (sb.s_log_zone_size) {
+	      case  512: sb.s_log_zone_size =  9; break;
+	      case 1024: sb.s_log_zone_size = 10; break;
+	      case 2048: sb.s_log_zone_size = 11; break;
+
+	      default:
+		printf("Bad logical zone size %ld\n", sb.s_log_zone_size);
+		return -1;
+	}
+
+	/* RDE: data zone now byte offset! */
+
+	sb.s_firstdatazone = (isonum_733( rootp->extent) 
+					 << sb.s_log_zone_size);
+	/*
+	 * The CDROM is read-only, has no nodes (devices) on it, and
+	 * since all of the files appear to be owned by root, we
+	 * really do not want to allow suid.  (suid or devices will
+	 * not show up unless we have Rock Ridge extensions).
+	 */
+	if (first_time) {
+		first_time = 0;
+		printf("iso: Max size:%ld   Log zone size:%ld\n",
+		       sb.s_max_size, 1UL << sb.s_log_zone_size);
+		printf("iso: First datazone:%ld   Root inode number %d\n",
+		       sb.s_firstdatazone >> sb.s_log_zone_size,
+		       isonum_733 (rootp->extent) << sb.s_log_zone_size);
+		if (high_sierra)
+			printf("iso: Disc in High Sierra format.\n");
+	}
+
+	/* set up enough so that it can read an inode */
+
+	sb.s_mapping = 'n';
+	sb.s_rock = (rock == 'y' ? 1 : 0);
+	sb.s_conversion = 'b';
+	sb.s_cruft = 'n';
+	sb.s_unhide = 'n';
+	/*
+	 * It would be incredibly stupid to allow people to mark every file 
+	 * on the disk as suid, so we merely allow them to set the default 
+	 * permissions.
+	 */
+	sb.s_mode = S_IRUGO & 0777;
+
+	/* return successfully */
+	root_inode = isonum_733 (rootp->extent) << sb.s_log_zone_size;
+	/* HK: isonum_733 returns an "int" but root_inode is a long ? */
+	return 0;
+}
+
+
+int
+iso_bread (int fd, long blkno, long nblks, char * buffer)
+{
+	struct iso_inode *inode;
+
+	/* find the inode for this file */
+	inode = &inode_table[fd].inode;
+	return iso_breadi(inode, blkno, nblks, buffer); 
+}
+
+
+int
+iso_open (const char *filename)
+{
+	struct iso_inode *inode, *oldinode;
+	struct iso_inode *root;
+
+	/* get the root directory */
+	root = iso_iget(root_inode);
+/* HK: iso_iget expects an "int" but root_inode is "long" ?? */
+	if (!root) {
+		printf("iso9660: get root inode failed\n");
+		return -1;
+	}
+
+	/* lookup the file */
+	inode = iso_lookup(root, filename);
+
+#ifdef DEBUG_ISO
+	if (inode && S_ISLNK(((struct inode_table_entry *)inode)->mode)) {
+		printf("%s is a link (len %u)\n",filename,
+		       ((struct inode_table_entry *)inode)->size);
+	} else {
+		printf("%s is not a link\n",filename);
+	}
+#endif
+
+	while ((inode) && (S_ISLNK(((struct inode_table_entry *)inode)->mode))) {
+		oldinode = inode;
+		inode = iso_follow_link(oldinode, filename);
+		iso_iput(oldinode);
+	}
+	if (inode == NULL) 
+		return -1;
+	else {
+		struct inode_table_entry * itp =
+			(struct inode_table_entry *) inode;
+		return (itp - inode_table);
+	}
+}
+
+
+void
+iso_close (int fd)
+{
+	iso_iput(&inode_table[fd].inode);
+}
+
+
+long
+iso_map (int fd, long block)
+{
+	return iso_bmap(&inode_table[fd].inode, block) * sb.s_blocksize;
+}
+
+#include <linux/stat.h>
+int
+iso_fstat (int fd, struct stat * buf)
+{
+	struct inode_table_entry * ip = inode_table + fd;
+
+	if (fd >= MAX_OPEN_FILES)
+		return -1;
+
+	memset(buf, 0, sizeof(struct stat));
+	/* fill in relevant fields */
+	buf->st_ino   = ip->inumber;
+	buf->st_mode  = ip->mode;
+	buf->st_nlink = ip->nlink;
+	buf->st_size  = ip->size;
+	return 0;
+}
+
+/*
+ * NOTE: mixing calls to this and calls to any other function that reads from
+ * the filesystem will clobber the buffers and cause much wailing and gnashing
+ * of teeth.
+ *
+ * Sorry this function is so ugly. It was written as a way for me to
+ * learn how the ISO filesystem stuff works. 
+ * 
+ * Will Woods, 2/2001
+ *
+ * Uses data_block
+ */
+char *iso_readdir_i(int fd, int rewind) {
+    struct inode_table_entry *itp = &(inode_table[fd]);
+    struct iso_directory_record *dirent = 0;
+    unsigned int fraglen = 0, block, dirent_len, name_len = 0, oldoffset;
+    static unsigned int blockoffset = 0, diroffset = 0;
+    
+    if (!S_ISDIR(itp->mode)) {
+	printf("Not a directory\n");
+	return NULL;
+    }
+    
+    /* Initial read to this directory, get the first block */
+    if (rewind) {
+	blockoffset = diroffset = 0;
+	block = iso_bmap(&itp->inode,0); 
+#ifdef DEBUG_ISO
+	printf("fd #%d, inode %d, first_extent %d, block %u\n",
+	       fd,itp->inumber,itp->inode.i_first_extent,block);
+#endif
+	if (!block) return NULL;
+	
+	if (iso_dev_read(data_block, block * sb.s_blocksize, sb.s_blocksize) 
+	    != sb.s_blocksize) return NULL;
+    }
+
+    /* keep doing this until we get a filename or we fail */ 
+    while (!name_len) {
+	/* set up our dirent pointer into the block of data we've read */
+	dirent = (struct iso_directory_record *) (data_block + blockoffset);
+	dirent_len = isonum_711(dirent->length);
+#ifdef DEBUG_ISO
+	printf("diroffset=%u, blockoffset=%u, length=%u\n",
+	       diroffset,blockoffset,dirent_len);
+#endif
+    
+	/* End of directory listing or end of sector */
+	if (dirent_len == 0) { 
+	    /* round diroffset up to the nearest blocksize */
+	    diroffset = ((diroffset & ~(ISOFS_BLOCK_SIZE - 1))
+			 + ISOFS_BLOCK_SIZE);
+#ifdef DEBUG_ISO
+	    printf("dirent_len == 0. diroffset=%u, itp->size=%u. ",
+		   diroffset,itp->size);
+#endif
+	    if (diroffset >= itp->size) {
+#ifdef DEBUG_ISO
+		printf("End of directory.\n");
+#endif
+		return NULL;
+	    } else {
+#ifdef DEBUG_ISO
+		printf("End of sector. Need next block.\n");
+#endif
+		/* Get the next block. */
+		block = iso_bmap(&itp->inode, diroffset>>sb.s_blocksize_bits);
+		if (!block) return NULL;
+		if (iso_dev_read(data_block, block * sb.s_blocksize, sb.s_blocksize) 
+		    != sb.s_blocksize) return NULL;
+
+		/* set the offsets and the pointers properly */
+		blockoffset = 0;
+		dirent = (struct iso_directory_record *) data_block;
+		dirent_len = isonum_711(dirent->length);
+#ifdef DEBUG_ISO
+		printf("diroffset=%u, blockoffset=%u, length=%u\n",
+		       diroffset,blockoffset,dirent_len);
+#endif
+	    }
+	}
+
+	/* update the offsets for the next read */
+	oldoffset = blockoffset;
+	blockoffset += dirent_len;
+	diroffset += dirent_len;
+	
+	/* 
+	 * directory entry spans two blocks - 
+	 * get next block and glue the two halves together 
+	 */
+	if (blockoffset >= sb.s_blocksize) {
+	    fraglen = sb.s_blocksize - oldoffset; 
+#ifdef DEBUG_ISO
+	    printf("fragmented block: blockoffset = %u, fraglen = %u\n",
+		   blockoffset, fraglen);
+#endif
+	    /* copy the fragment at end of old block to front of new buffer */
+	    memcpy(big_data_block, data_block + oldoffset, fraglen);
+	    
+	    /* read the next block into the buffer after the old fragment */
+	    block = iso_bmap(&itp->inode, diroffset >> sb.s_blocksize_bits);
+	    if (!block) return NULL;
+	    if (iso_dev_read(big_data_block + fraglen, block * sb.s_blocksize, sb.s_blocksize) 
+		!= sb.s_blocksize) return NULL;
+#ifdef DEBUG_ISO
+	    printf("read %u bytes from offset %u\n",
+		   sb.s_blocksize, block * sb.s_blocksize);
+#endif
+	    
+	    blockoffset = 0;
+	    dirent = (struct iso_directory_record *) big_data_block;
+	}
+	
+	/* 
+	 * Everything's cool, let's get the filename. 
+	 * First we need to figure out the length. 
+	 */
+	name_len = isonum_711(dirent->name_len);
+#ifdef DEBUG_ISO
+	if (name_len==0) printf("dirent->name_len = 0, skipping.\n");
+#endif
+	
+	/* skip '.' and '..' */
+	if (name_len == 1) {
+	    if (dirent->name[0] == (char)0) name_len = 0;
+	    if (dirent->name[0] == (char)1) name_len = 0;
+	} 
+
+
+	if (sb.s_unhide == 'n') {
+	    /* sb.s_high_sierra is the offset for the position of the flags.
+	       this adjusts for differences between iso9660 and high sierra.
+	       
+	       if bit 0 (exists) or bit 2 (associated) are set, we ignore
+	       this record. */
+	    if (dirent->flags[-sb.s_high_sierra] & 5) name_len = 0;
+	}
+
+	/* if we have a real filename here.. */
+	if (name_len) {
+	    /* should be sufficient, since get_rock_ridge_filename truncates
+	       at 254 characters */
+	    char rrname[256]; 
+	    if ((name_len = get_rock_ridge_filename(dirent, rrname, &itp->inode))) {
+		rrname[name_len] = '\0';
+		/* it's okay if rrname is longer than dirent->name, because
+		   we're just overwriting parts of the now-useless dirent */
+		strcpy(dirent->name, rrname); 
+	    } else {
+	        int i;
+	        char c;
+		if (sb.s_mapping == 'n') { /* downcase the name */
+		    for (i = 0; i < name_len; i++) {
+			c = dirent->name[i];
+			
+                        /* lower case */ 
+			if ((c >= 'A') && (c <= 'Z')) c |= 0x20; 
+			
+			/* Drop trailing '.;1' */
+			if ((c == '.') && (i == name_len-3) && 
+			    (dirent->name[i+1] == ';') && 
+                            (dirent->name[i+2] == '1')) {
+			    name_len -= 3 ; break; 
+			}
+			
+			/* Drop trailing ';1' */
+			if ((c == ';') && (i == name_len-2) && 
+                            (dirent->name[i+1] == '1')) {
+			    name_len -= 2; break;
+			}
+			
+			/* convert ';' to '.' */
+			if (c == ';') 
+			    c = '.';
+			
+			dirent->name[i] = c;
+		    }
+		    dirent->name[name_len] = '\0';
+		}
+	    }
+	}
+	/* now that we're done using it, and it's smaller than a full block, 
+	 * copy big_data_block back into data_block */
+	if (fraglen) { 
+            int len = sb.s_blocksize - dirent_len;
+	    memcpy(data_block, big_data_block + dirent_len, len);
+#ifdef DEBUG_ISO
+	    printf("copied %u bytes of data back to data_block\n", len);
+#endif
+	    blockoffset = 0;
+	    fraglen = 0;
+	}
+    }
+    return dirent->name;
+}
+
+/********************************************************************** 
+ * 
+ * Rock Ridge functions and definitions, from the Linux kernel source.
+ * linux/fs/isofs/rock.c, (c) 1992, 1993 Eric Youngdale.
+ * 
+ **********************************************************************/
+
+#define SIG(A,B) ((A << 8) | B)
+
+/* This is a way of ensuring that we have something in the system
+   use fields that is compatible with Rock Ridge */
+#define CHECK_SP(FAIL)	       			\
+      if(rr->u.SP.magic[0] != 0xbe) FAIL;	\
+      if(rr->u.SP.magic[1] != 0xef) FAIL;
+
+/* We define a series of macros because each function must do exactly the
+   same thing in certain places.  We use the macros to ensure that everything
+   is done correctly */
+
+#define CONTINUE_DECLS \
+  int cont_extent = 0, cont_offset = 0, cont_size = 0;   \
+  void * buffer = 0
+
+#define CHECK_CE	       			\
+      {cont_extent = isonum_733(rr->u.CE.extent); \
+      cont_offset = isonum_733(rr->u.CE.offset); \
+      cont_size = isonum_733(rr->u.CE.size);}
+
+#define SETUP_ROCK_RIDGE(DE,CHR,LEN)	      		      	\
+  {LEN= sizeof(struct iso_directory_record) + DE->name_len[0];	\
+  if(LEN & 1) LEN++;						\
+  CHR = ((unsigned char *) DE) + LEN;				\
+  LEN = *((unsigned char *) DE) - LEN;}
+
+#define MAYBE_CONTINUE(LABEL) \
+  {if (buffer) free(buffer); \
+  if (cont_extent){ \
+    buffer = malloc(cont_size); \
+    if (!buffer) goto out; \
+    if (iso_dev_read(buffer, cont_extent * ISOFS_BLOCK_SIZE + cont_offset, cont_size) \
+	  == cont_size) { \
+        chr = (unsigned char *) buffer; \
+        len = cont_size; \
+        cont_extent = cont_size = cont_offset = 0; \
+        goto LABEL; \
+    }; \
+    printf("Unable to read rock-ridge attributes\n");    \
+  }}
+
+int get_rock_ridge_filename(struct iso_directory_record * de,
+			    char * retname,
+			    struct iso_inode * inode)
+{
+  int len;
+  unsigned char * chr;
+  int retnamlen = 0, truncate=0;
+  int cont_extent = 0, cont_offset = 0, cont_size = 0;
+  void *buffer = 0;
+
+  /* No rock ridge? well then... */
+  if (!sb.s_rock) return 0;
+  *retname = '\0';
+
+  len = sizeof(struct iso_directory_record) + isonum_711(de->name_len);
+  if (len & 1) len++;
+  chr = ((unsigned char *) de) + len;
+  len = *((unsigned char *) de) - len;
+  {
+    struct rock_ridge * rr;
+    int sig;
+    
+  repeat:
+    while (len > 1){ /* There may be one byte for padding somewhere */
+      rr = (struct rock_ridge *) chr;
+      if (rr->len == 0) break; /* Something got screwed up here */
+
+      sig = (chr[0] << 8) + chr[1];
+      chr += rr->len; 
+      len -= rr->len;
+
+      switch(sig){
+      case SIG('R','R'):
+	  if((rr->u.RR.flags[0] & RR_NM) == 0) goto out;
+	  break;
+      case SIG('S','P'):
+	  if (rr->u.SP.magic[0] != 0xbe ||
+	      rr->u.SP.magic[1] != 0xef)
+	      goto out;
+	  break;
+      case SIG('C','E'):
+	  cont_extent = isonum_733(rr->u.CE.extent);
+	  cont_offset = isonum_733(rr->u.CE.offset);
+	  cont_size = isonum_733(rr->u.CE.size);
+	  break;
+      case SIG('N','M'):
+	  if (truncate) break;
+        /*
+	 * If the flags are 2 or 4, this indicates '.' or '..'.
+	 * We don't want to do anything with this, because it
+	 * screws up the code that calls us.  We don't really
+	 * care anyways, since we can just use the non-RR
+	 * name.
+	 */
+	if (rr->u.NM.flags & 6) {
+	    break;
+	}
+
+	if (rr->u.NM.flags & ~1) {
+	  printf("Unsupported NM flag settings (%d)\n",rr->u.NM.flags);
+	  break;
+	};
+	if((strlen(retname) + rr->len - 5) >= 254) {
+	    int i = 254-strlen(retname);
+	    strncat(retname, rr->u.NM.name, i); 
+	    retnamlen += i;
+	    truncate = 1;
+	    break;
+	};
+	strncat(retname, rr->u.NM.name, rr->len - 5);
+	retnamlen += rr->len - 5;
+	break;
+      case SIG('R','E'):
+	  goto out;
+      default:
+	  break;
+      }
+    };
+  }
+  if (buffer) free(buffer);
+  if (cont_extent) { /* we had a continued record */
+      buffer = malloc(cont_size);
+      if (!buffer) goto out;
+      if (iso_dev_read(buffer, cont_extent * ISOFS_BLOCK_SIZE + cont_offset, cont_size) 
+	  != cont_size) goto out;
+      chr = buffer + cont_offset;
+      len = cont_size;
+      cont_extent = cont_size = cont_offset = 0;
+      goto repeat;
+  }
+  return retnamlen; /* If 0, this file did not have a NM field */
+ out:
+  if (buffer) free(buffer);
+  return 0;
+}
+
+static int parse_rock_ridge_inode(struct iso_directory_record * de,
+				  struct iso_inode * inode){
+  int len;
+  unsigned char *chr;
+  int symlink_len = 0;
+  struct inode_table_entry *itp = (struct inode_table_entry *) inode;
+  CONTINUE_DECLS;
+
+#ifdef DEBUG_ROCK
+  printf("parse_rock_ridge_inode(%u)\n",itp->inumber);
+#endif
+
+  if (!sb.s_rock) return 0;
+
+  SETUP_ROCK_RIDGE(de, chr, len);
+ repeat:
+  {
+    int sig;
+    /* struct iso_inode * reloc; */
+    struct rock_ridge * rr;
+    int rootflag;
+    
+    while (len > 1){ /* There may be one byte for padding somewhere */
+      rr = (struct rock_ridge *) chr;
+      if (rr->len == 0) goto out; /* Something got screwed up here */
+      sig = (chr[0] << 8) + chr[1];
+      chr += rr->len; 
+      len -= rr->len;
+      
+      switch(sig){
+      case SIG('R','R'):
+#ifdef DEBUG_ROCK
+  printf("RR ");
+#endif
+	if((rr->u.RR.flags[0] & 
+ 	    (RR_PX | RR_TF | RR_SL | RR_CL)) == 0) goto out;
+	break;
+      case SIG('S','P'):
+#ifdef DEBUG_ROCK
+  printf("SP ");
+#endif
+	CHECK_SP(goto out);
+	break;
+      case SIG('C','E'):
+#ifdef DEBUG_ROCK
+  printf("CE ");
+#endif
+	CHECK_CE;
+	break;
+      case SIG('E','R'):
+#ifdef DEBUG_ROCK
+	printf("ISO 9660 Extensions: ");
+	{ int p;
+	  for(p=0;p<rr->u.ER.len_id;p++) printf("%c",rr->u.ER.data[p]);
+	};
+	printf("\n");
+#endif
+	break;
+      case SIG('P','X'):
+#ifdef DEBUG_ROCK
+  printf("PX ");
+#endif
+	itp->mode  = isonum_733(rr->u.PX.mode);
+	itp->nlink = isonum_733(rr->u.PX.n_links);
+	/* Ignore uid and gid. We're only a simple bootloader, after all. */
+	break;
+      case SIG('P','N'):
+	/* Ignore device files. */
+	break;
+      case SIG('T','F'):
+        /* create/modify/access times are uninteresting to us. */
+	break;
+      case SIG('S','L'):
+#ifdef DEBUG_ROCK
+  printf("SL ");
+#endif
+	{int slen;
+	 struct SL_component * slp;
+	 struct SL_component * oldslp;
+	 slen = rr->len - 5;
+	 slp = &rr->u.SL.link;
+	 itp->size = symlink_len;
+	 while (slen > 1){
+	   rootflag = 0;
+	   switch(slp->flags &~1){
+	   case 0:
+	     itp->size += slp->len;
+	     break;
+	   case 2:
+	     itp->size += 1;
+	     break;
+	   case 4:
+	     itp->size += 2;
+	     break;
+	   case 8:
+	     rootflag = 1;
+	     itp->size += 1;
+	     break;
+	   default:
+	     printf("Symlink component flag not implemented\n");
+	   };
+	   slen -= slp->len + 2;
+	   oldslp = slp;
+	   slp = (struct SL_component *) (((char *) slp) + slp->len + 2);
+
+	   if(slen < 2) {
+	     if(    ((rr->u.SL.flags & 1) != 0) 
+		    && ((oldslp->flags & 1) == 0) ) itp->size += 1;
+	     break;
+	   }
+
+	   /*
+	    * If this component record isn't continued, then append a '/'.
+	    */
+	   if(   (!rootflag)
+		 && ((oldslp->flags & 1) == 0) ) itp->size += 1;
+	 }
+	}
+	symlink_len = itp->size;
+	break;
+      case SIG('R','E'):
+	printf("Attempt to read inode for relocated directory\n");
+	goto out;
+      case SIG('C','L'):
+#ifdef DEBUG_ROCK
+  printf("CL(!) ");
+#endif
+        /* I'm unsure as to the function of this signature.
+	   We'll ignore it and hope that everything will be OK.
+	*/
+#if 0
+#ifdef DEBUG
+	printf("RR CL (%x)\n",inode->i_ino);
+#endif
+	inode->inode.first_extent = isonum_733(rr->u.CL.location);
+	reloc = iso_iget(inode->i_sb,
+			 (inode->u.isofs_i.i_first_extent <<
+			  inode -> i_sb -> u.isofs_sb.s_log_zone_size));
+	if (!reloc)
+		goto out;
+	inode->mode = reloc->mode;
+	inode->nlink = reloc->nlink;
+	inode->size = reloc->size;
+	iso_iput(reloc);
+#endif /* 0 */
+	break;
+      default:
+	break;
+      }
+    };
+  }
+  MAYBE_CONTINUE(repeat);
+#ifdef DEBUG_ROCK
+  printf("\nparse_rock_ridge_inode(): ok\n");
+#endif
+  return 1;
+ out:
+  if(buffer) free(buffer);
+#ifdef DEBUG_ROCK
+  printf("\nparse_rock_ridge_inode(): failed\n");
+#endif
+  return 0;
+}
+
+/* Returns the name of the file that this inode is symlinked to.  This is
+   in malloc memory, so we have to free it when we're done */
+
+static char * get_rock_ridge_symlink(struct iso_inode *inode)
+{
+  int blocksize = ISOFS_BLOCK_SIZE;
+  int blockbits = ISOFS_BLOCK_BITS;
+  char * rpnt = NULL;
+  unsigned char * pnt;
+  struct iso_directory_record * raw_inode;
+  struct inode_table_entry *itp = (struct inode_table_entry *)inode;
+  CONTINUE_DECLS;
+  int block, blockoffset;
+  int sig;
+  int rootflag;
+  int len;
+  unsigned char * chr, * buf = NULL;
+  struct rock_ridge * rr;
+
+#ifdef DEBUG_ROCK
+  printf("get_rock_ridge_symlink(%u): link is %u bytes long\n",itp->inumber, itp->size);
+#endif
+  
+  if (!sb.s_rock) goto out;
+
+  block = itp->inumber >> blockbits;
+  blockoffset = itp->inumber & (blocksize - 1);
+
+  buf=malloc(blocksize);
+
+  if (iso_dev_read(buf, block << blockbits, blocksize) != blocksize)
+	  goto out_noread;
+
+  pnt = ((unsigned char *) buf) + blockoffset;
+  
+  raw_inode = ((struct iso_directory_record *) pnt);
+  
+  /*
+   * If we go past the end of the buffer, there is some sort of error.
+   */
+  if (blockoffset + *pnt > blocksize)
+	goto out_bad_span;
+  
+  /* Now test for possible Rock Ridge extensions which will override some of
+     these numbers in the inode structure. */
+  
+  SETUP_ROCK_RIDGE(raw_inode, chr, len);
+
+ repeat:
+  while (len > 1){ /* There may be one byte for padding somewhere */
+    rr = (struct rock_ridge *) chr;
+    if (rr->len == 0) goto out; /* Something got screwed up here */
+    sig = (chr[0] << 8) + chr[1];
+    chr += rr->len; 
+    len -= rr->len;
+    
+#ifdef DEBUG_ROCK
+    printf("%c%c ",chr[0],chr[1]);
+#endif
+    switch(sig){
+    case SIG('R','R'):
+      if((rr->u.RR.flags[0] & RR_SL) == 0) goto out;
+      break;
+    case SIG('S','P'):
+      CHECK_SP(goto out);
+      break;
+    case SIG('S','L'):
+      {int slen;
+       struct SL_component * oldslp;
+       struct SL_component * slp;
+       slen = rr->len - 5;
+       slp = &rr->u.SL.link;
+       while (slen > 1){
+	 if (!rpnt){
+	   rpnt = (char *) malloc (itp->size +1);
+	   if (!rpnt) goto out;
+	   *rpnt = 0;
+	 };
+	 rootflag = 0;
+	 switch(slp->flags &~1){
+	 case 0:
+	   strncat(rpnt,slp->text, slp->len);
+	   break;
+	 case 2:
+	   strcat(rpnt,".");
+	   break;
+	 case 4:
+	   strcat(rpnt,"..");
+	   break;
+	 case 8:
+	   rootflag = 1;
+	   strcat(rpnt,"/");
+	   break;
+	 default:
+#ifdef DEBUG_ROCK
+	   printf("Symlink component flag not implemented (%d)\n",slen);
+#endif
+	   break;
+	 };
+	 slen -= slp->len + 2;
+	 oldslp = slp;
+	 slp = (struct SL_component *) (((char *) slp) + slp->len + 2);
+
+	 if(slen < 2) {
+	   /*
+	    * If there is another SL record, and this component record
+	    * isn't continued, then add a slash.
+	    */
+	   if(    ((rr->u.SL.flags & 1) != 0) 
+	       && ((oldslp->flags & 1) == 0) ) strcat(rpnt,"/");
+	   break;
+	 }
+
+	 /*
+	  * If this component record isn't continued, then append a '/'.
+	  */
+	 if(   (!rootflag)
+	    && ((oldslp->flags & 1) == 0) ) strcat(rpnt,"/");
+
+       };
+       break;
+     case SIG('C','E'):
+       CHECK_CE; /* This tells is if there is a continuation record */
+       break;
+     default:
+       break;
+     }
+    };
+  };
+  MAYBE_CONTINUE(repeat);
+  
+ out_freebh:
+#ifdef DEBUG_ROCK
+  printf("\nget_rock_ridge_symlink() exiting\n");
+#endif
+        if (buf)
+		free(buf);
+	return rpnt;
+
+	/* error exit from macro */
+out:
+#ifdef DEBUG_ROCK
+	printf("abort");
+#endif
+	if(buffer)
+		free(buffer);
+	if(rpnt)
+		free(rpnt);
+	rpnt = NULL;
+	goto out_freebh;
+out_noread:
+	printf("unable to read block");
+	goto out_freebh;
+out_bad_span:
+	printf("symlink spans iso9660 blocks\n");
+	goto out_freebh;
+}
+
+
+

+ 23 - 0
package/aboot/src/lib/memcpy.c

@@ -0,0 +1,23 @@
+/*
+ *  aboot/lib/memcpy.c
+ *
+ *  Copyright (c) 1995  David Mosberger (davidm@cs.arizona.edu)
+ */
+#include <linux/types.h>
+#include <stddef.h>
+
+/*
+ * Booting is I/O bound so rather than a time-optimized, we want
+ * a space-optimized memcpy.  Not that the rest of the loader
+ * were particularly small, though...
+ */
+void *__memcpy(void *dest, const void *source, size_t n)
+{
+	char *dst = dest;
+	const char *src = source;
+
+	while (n--) {
+		*dst++ = *src++;
+	}
+	return dest;
+}

+ 28 - 0
package/aboot/src/lib/memset.c

@@ -0,0 +1,28 @@
+/*
+ *  aboot/lib/memset.c
+ *
+ *  Copyright (c) 1995  David Mosberger (davidm@cs.arizona.edu)
+ */
+#include <linux/types.h>
+#include <stddef.h>
+
+/*
+ * Booting is I/O bound so rather than a time-optimized, we want
+ * a space-optimized memcpy.  Not that the rest of the loader
+ * were particularly small, though...
+ */
+void *__memset(void *s, char c, size_t n)
+{
+	char *dst = s;
+
+	while (n--) {
+		*dst++ = c;
+	}
+	return s;
+}
+
+
+void *__constant_c_memset(void *dest, char c, size_t n)
+{
+	return __memset(dest, c, n);
+}

+ 252 - 0
package/aboot/src/lib/string.c

@@ -0,0 +1,252 @@
+/*
+ *  aboot/lib/string.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+/*
+ * stupid library routines.. The optimized versions should generally be found
+ * as inline code in <asm-xx/string.h>
+ *
+ * These are buggy as well..
+ */
+
+#include <stddef.h> 
+#include <linux/types.h>
+
+char * ___strtok = NULL;
+
+char * strcpy(char * dest,const char *src)
+{
+	char *tmp = dest;
+
+	while ((*dest++ = *src++) != '\0')
+		/* nothing */;
+	return tmp;
+}
+
+char * strncpy(char * dest,const char *src,size_t count)
+{
+	char *tmp = dest;
+
+	while (count-- && (*dest++ = *src++) != '\0')
+		/* nothing */;
+
+	return tmp;
+}
+
+char * strcat(char * dest, const char * src)
+{
+	char *tmp = dest;
+
+	while (*dest)
+		dest++;
+	while ((*dest++ = *src++) != '\0')
+		;
+
+	return tmp;
+}
+
+char * strncat(char *dest, const char *src, size_t count)
+{
+	char *tmp = dest;
+
+	if (count) {
+		while (*dest)
+			dest++;
+		while ((*dest++ = *src++)) {
+			if (--count == 0)
+				break;
+		}
+	}
+
+	return tmp;
+}
+
+int strcmp(const char * cs,const char * ct)
+{
+	register signed char __res;
+
+	while (1) {
+		if ((__res = *cs - *ct++) != 0 || !*cs++)
+			break;
+	}
+
+	return __res;
+}
+
+int strncmp(const char * cs,const char * ct,size_t count)
+{
+	register signed char __res = 0;
+
+	while (count) {
+		if ((__res = *cs - *ct++) != 0 || !*cs++)
+			break;
+		count--;
+	}
+
+	return __res;
+}
+
+char * strchr(const char * s,char c)
+{
+	for(; *s != c; ++s)
+		if (*s == '\0')
+			return NULL;
+	return (char *) s;
+}
+
+char * strrchr(const char * s,char c)
+{
+	const char * r = NULL;
+	while (*s++)
+		if (*s == c) r = s;
+	return (char *) r;
+}
+
+size_t strlen(const char * s)
+{
+	const char *sc;
+
+	for (sc = s; *sc != '\0'; ++sc)
+		/* nothing */;
+	return sc - s;
+}
+
+size_t strnlen(const char * s, size_t count)
+{
+	const char *sc;
+
+	for (sc = s; *sc != '\0' && count--; ++sc)
+		/* nothing */;
+	return sc - s;
+}
+
+size_t strspn(const char *s, const char *accept)
+{
+	const char *p;
+	const char *a;
+	size_t count = 0;
+
+	for (p = s; *p != '\0'; ++p) {
+		for (a = accept; *a != '\0'; ++a) {
+			if (*p == *a)
+				break;
+		}
+		if (*a == '\0')
+			return count;
+		++count;
+	}
+
+	return count;
+}
+
+char * strpbrk(const char * cs,const char * ct)
+{
+	const char *sc1,*sc2;
+
+	for( sc1 = cs; *sc1 != '\0'; ++sc1) {
+		for( sc2 = ct; *sc2 != '\0'; ++sc2) {
+			if (*sc1 == *sc2)
+				return (char *) sc1;
+		}
+	}
+	return NULL;
+}
+
+char * strtok(char * s,const char * ct)
+{
+	char *sbegin, *send;
+
+	sbegin  = s ? s : ___strtok;
+	if (!sbegin) {
+		return NULL;
+	}
+	sbegin += strspn(sbegin,ct);
+	if (*sbegin == '\0') {
+		___strtok = NULL;
+		return( NULL );
+	}
+	send = strpbrk( sbegin, ct);
+	if (send && *send != '\0')
+		*send++ = '\0';
+	___strtok = send;
+	return (sbegin);
+}
+
+void * memset(void * s, int c, size_t count)
+{
+	char *xs = (char *) s;
+
+	while (count--)
+		*xs++ = c;
+
+	return s;
+}
+
+char * bcopy(const char * src, char * dest, int count)
+{
+	char *tmp = dest;
+
+	while (count--)
+		*tmp++ = *src++;
+
+	return dest;
+}
+
+void * memcpy(void * dest,const void *src,size_t count)
+{
+	char *tmp = (char *) dest, *s = (char *) src;
+
+	while (count--)
+		*tmp++ = *s++;
+
+	return dest;
+}
+
+void * memmove(void * dest,const void *src,size_t count)
+{
+	char *tmp, *s;
+
+	if (dest <= src) {
+		tmp = (char *) dest;
+		s = (char *) src;
+		while (count--)
+			*tmp++ = *s++;
+		}
+	else {
+		tmp = (char *) dest + count;
+		s = (char *) src + count;
+		while (count--)
+			*--tmp = *--s;
+		}
+
+	return dest;
+}
+
+int memcmp(const void * cs,const void * ct,size_t count)
+{
+	const unsigned char *su1, *su2;
+	signed char res = 0;
+
+	for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
+		if ((res = *su1 - *su2) != 0)
+			break;
+	return res;
+}
+
+/*
+ * find the first occurrence of byte 'c', or 1 past the area if none
+ */
+void * memscan(void * addr, unsigned char c, size_t size)
+{
+	unsigned char * p = (unsigned char *) addr;
+
+	while (size) {
+		if (*p == c)
+			return (void *) p;
+		p++;
+		size--;
+	}
+  	return (void *) p;
+}

+ 317 - 0
package/aboot/src/lib/vsprintf.c

@@ -0,0 +1,317 @@
+/*
+ *  linux/lib/vsprintf.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
+/*
+ * Wirzenius wrote this portably, Torvalds fucked it up :-)
+ */
+
+#include <stdarg.h>
+#include <linux/types.h>
+#include "string.h"
+
+/* we use this so that we can do without the ctype library */
+#define is_digit(c)	((c) >= '0' && (c) <= '9')
+#define is_xdigit(c) \
+  (is_digit(c) || ((c) >= 'A' && (c) <= 'F') || ((c) >= 'a' && (c) <= 'f'))
+#define is_lower(c)	(((c) >= 'a') && ((c) <= 'z'))
+#define to_upper(c)	((c) + 'a' - 'A')
+
+unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base)
+{
+	unsigned long result = 0, value;
+
+	if (!base) {
+		base = 10;
+		if (*cp == '0') {
+			base = 8;
+			cp++;
+			if ((*cp == 'x') && is_xdigit(cp[1])) {
+				cp++;
+				base = 16;
+			}
+		}
+	}
+	while (is_xdigit(*cp)
+	       && (value =
+		   (is_digit(*cp)
+		    ? *cp - '0' : ((is_lower(*cp)
+				    ? to_upper(*cp) : *cp) - 'A' + 10)))
+		   < base)
+	{
+		result = result*base + value;
+		cp++;
+	}
+	if (endp)
+		*endp = (char *)cp;
+	return result;
+}
+
+
+static int skip_atoi(const char **s)
+{
+	int i=0;
+
+	while (is_digit(**s))
+		i = i*10 + *((*s)++) - '0';
+	return i;
+}
+
+#define ZEROPAD	1		/* pad with zero */
+#define SIGN	2		/* unsigned/signed long */
+#define PLUS	4		/* show plus */
+#define SPACE	8		/* space if plus */
+#define LEFT	16		/* left justified */
+#define SPECIAL	32		/* 0x */
+#define LARGE	64		/* use 'ABCDEF' instead of 'abcdef' */
+
+#define do_div(n,base) ({ \
+int __res; \
+__res = ((unsigned long) n) % (unsigned) base; \
+n = ((unsigned long) n) / (unsigned) base; \
+__res; })
+
+static char * number(char * str, long num, int base, int size, int precision
+	,int type)
+{
+	char c,sign,tmp[66];
+	const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
+	int i;
+
+	if (type & LARGE)
+		digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+	if (type & LEFT)
+		type &= ~ZEROPAD;
+	if (base < 2 || base > 36)
+		return 0;
+	c = (type & ZEROPAD) ? '0' : ' ';
+	sign = 0;
+	if (type & SIGN) {
+		if (num < 0) {
+			sign = '-';
+			num = -num;
+			size--;
+		} else if (type & PLUS) {
+			sign = '+';
+			size--;
+		} else if (type & SPACE) {
+			sign = ' ';
+			size--;
+		}
+	}
+	if (type & SPECIAL) {
+		if (base == 16)
+			size -= 2;
+		else if (base == 8)
+			size--;
+	}
+	i = 0;
+	if (num == 0)
+		tmp[i++]='0';
+	else while (num != 0)
+		tmp[i++] = digits[do_div(num,base)];
+	if (i > precision)
+		precision = i;
+	size -= precision;
+	if (!(type&(ZEROPAD+LEFT)))
+		while(size-->0)
+			*str++ = ' ';
+	if (sign)
+		*str++ = sign;
+	if (type & SPECIAL) {
+		if (base==8)
+			*str++ = '0';
+		else if (base==16) {
+			*str++ = '0';
+			*str++ = digits[33];
+		}
+	}
+	if (!(type & LEFT))
+		while (size-- > 0)
+			*str++ = c;
+	while (i < precision--)
+		*str++ = '0';
+	while (i-- > 0)
+		*str++ = tmp[i];
+	while (size-- > 0)
+		*str++ = ' ';
+	return str;
+}
+
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+	int len;
+	unsigned long num;
+	int base = 10;
+	int i;
+	char * str;
+	char *s;
+
+	int flags;		/* flags to number() */
+
+	int field_width = -1;	/* width of output field */
+	int precision = -1;		/* min. # of digits for integers; max
+				   number of chars for from string */
+	int qualifier = -1;		/* 'h', 'l', or 'L' for integer fields */
+
+	for (str=buf ; *fmt ; ++fmt) {
+		if (*fmt != '%') {
+			*str++ = *fmt;
+			continue;
+		}
+			
+		/* process flags */
+		flags = 0;
+		repeat:
+			++fmt;		/* this also skips first '%' */
+			switch (*fmt) {
+				case '-': flags |= LEFT; goto repeat;
+				case '+': flags |= PLUS; goto repeat;
+				case ' ': flags |= SPACE; goto repeat;
+				case '#': flags |= SPECIAL; goto repeat;
+				case '0': flags |= ZEROPAD; goto repeat;
+				}
+		
+		/* get field width */
+		field_width = -1;
+		if (is_digit(*fmt))
+			field_width = skip_atoi(&fmt);
+		else if (*fmt == '*') {
+			++fmt;
+			/* it's the next argument */
+			field_width = va_arg(args, int);
+			if (field_width < 0) {
+				field_width = -field_width;
+				flags |= LEFT;
+			}
+		}
+
+		/* get the precision */
+		precision = -1;
+		if (*fmt == '.') {
+			++fmt;	
+			if (is_digit(*fmt))
+				precision = skip_atoi(&fmt);
+			else if (*fmt == '*') {
+				++fmt;
+				/* it's the next argument */
+				precision = va_arg(args, int);
+			}
+			if (precision < 0)
+				precision = 0;
+		}
+
+		/* get the conversion qualifier */
+		qualifier = -1;
+		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
+			qualifier = *fmt;
+			++fmt;
+		}
+
+		/* default base */
+		base = 10;
+
+		switch (*fmt) {
+		case 'c':
+			if (!(flags & LEFT))
+				while (--field_width > 0)
+					*str++ = ' ';
+			*str++ = (unsigned char) va_arg(args, int);
+			while (--field_width > 0)
+				*str++ = ' ';
+			continue;
+
+		case 's':
+			s = va_arg(args, char *);
+			if (!s)
+				s = "<NULL>";
+
+			len = strnlen(s, precision);
+
+			if (!(flags & LEFT))
+				while (len < field_width--)
+					*str++ = ' ';
+			for (i = 0; i < len; ++i)
+				*str++ = *s++;
+			while (len < field_width--)
+				*str++ = ' ';
+			continue;
+
+		case 'p':
+			if (field_width == -1) {
+				field_width = 2*sizeof(void *);
+				flags |= ZEROPAD;
+			}
+			str = number(str,
+				(unsigned long) va_arg(args, void *), 16,
+				field_width, precision, flags);
+			continue;
+
+
+		case 'n':
+			if (qualifier == 'l') {
+				long * ip = va_arg(args, long *);
+				*ip = (str - buf);
+			} else {
+				int * ip = va_arg(args, int *);
+				*ip = (str - buf);
+			}
+			continue;
+
+		/* integer number formats - set up the flags and "break" */
+		case 'o':
+			base = 8;
+			break;
+
+		case 'X':
+			flags |= LARGE;
+		case 'x':
+			base = 16;
+			break;
+
+		case 'd':
+		case 'i':
+			flags |= SIGN;
+		case 'u':
+			break;
+
+		default:
+			if (*fmt != '%')
+				*str++ = '%';
+			if (*fmt)
+				*str++ = *fmt;
+			else
+				--fmt;
+			continue;
+		}
+		if (qualifier == 'l')
+			num = va_arg(args, unsigned long);
+		else if (qualifier == 'h')
+			if (flags & SIGN)
+				num = va_arg(args, int);
+			else
+				num = va_arg(args, unsigned int);
+		else if (flags & SIGN)
+			num = va_arg(args, int);
+		else
+			num = va_arg(args, unsigned int);
+		str = number(str, num, base, field_width, precision, flags);
+	}
+	*str = '\0';
+	return str-buf;
+}
+
+int sprintf(char * buf, const char *fmt, ...)
+{
+	va_list args;
+	int i;
+
+	va_start(args, fmt);
+	i=vsprintf(buf,fmt,args);
+	va_end(args);
+	return i;
+}
+

+ 146 - 0
package/aboot/src/net.c

@@ -0,0 +1,146 @@
+/*
+ * net.c
+ *
+ * This file is part of aboot, the SRM bootloader for Linux/Alpha
+ * Copyright (C) 1996 Dave Larson, and David Mosberger.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <asm/console.h>
+#include "system.h"
+
+#include "config.h"
+#include "cons.h"
+#include "aboot.h"
+#include "bootfs.h"
+#include "utils.h"
+#include "string.h"
+#include "netwrap.h"
+
+extern char boot_file[256];
+
+void
+dang (void)
+{
+	printf("aboot: oops, unimplemented net-bfs function called!\n");
+}
+
+extern char _end;
+static char *src = 0;
+static char *kern_src=0, *ird_src=0;
+static int  header_size=0, kern_size=0, ird_size=0;
+
+int
+net_bread (int fd, long blkno, long nblks, char * buf)
+{
+	int nbytes;
+
+#ifdef DEBUG
+	printf("net_bread: %p -> %p (%ld blocks at %ld)\n", src, buf,
+	       nblks, blkno);
+#endif
+	nbytes = bfs->blocksize * nblks;
+
+        memcpy(buf, src, nbytes);
+        src += nbytes;
+
+        return nbytes;
+}
+
+
+struct bootfs netfs = {
+	-1, 512,
+	(int (*)(long, long, long))	dang,	/* mount */
+	(int (*)(const char *))		dang,	/* open */
+	net_bread,				/* bread */
+	(void (*)(int fd))		dang,	/* close */
+	(const char* (*)(int, int))	dang,	/* readdir */
+	(int (*)(int, struct stat*))	dang,	/* fstat */
+};
+
+long
+read_initrd()
+{
+	int nblocks, nread;
+
+	/* put it as high up in memory as possible */
+	initrd_start = free_mem_ptr - align_pagesize(ird_size);
+	initrd_size = ird_size;
+	/* update free_mem_ptr so malloc() still works */
+	free_mem_ptr = initrd_start;
+#ifdef DEBUG
+	printf("memory_end %x %x\n", free_mem_ptr, initrd_start);
+#endif
+
+	nblocks = align_512(ird_size)/ 512;
+	printf("aboot: loading initrd (%d bytes/%d blocks) at %#lx\n",
+	        ird_size, nblocks, initrd_start);
+	nread = (*bfs->bread)(-1, 0, nblocks, (char*) initrd_start);
+	return 0;
+}
+
+
+
+long
+load_kernel (void)
+{
+	struct header *header;
+	bfs = &netfs;
+
+	header =  (struct header *)align_512( (unsigned long)&_end );
+	header_size = header->header_size;
+	kern_src = (char *)align_512((unsigned long)header + header_size);
+	kern_size = header->kern_size;
+	ird_src = (char *)align_512((unsigned long)kern_src + kern_size);
+	ird_size = header->ird_size;
+
+	if (!free_mem_ptr)
+		free_mem_ptr = memory_end();
+	free_mem_ptr = free_mem_ptr & ~(PAGE_SIZE-1);
+
+#ifdef DEBUG
+	printf("head %x %x kernel %x %x, initrd %x %x \n", header, header_size, kern_src, kern_size, ird_src, ird_size);
+#endif
+
+	if (ird_size) {
+		src = ird_src;
+		if (read_initrd() < 0) {
+			return -1;
+		}
+	}
+
+	strcpy(boot_file, "network");
+
+	//Move kernel to safe place before uncompression
+	src = (char*)free_mem_ptr - align_pagesize(kern_size);
+	free_mem_ptr = (unsigned long)src;
+	memcpy(src, kern_src, kern_size);
+
+	uncompress_kernel(-1);
+
+	memset((char*)bss_start, 0, bss_size);	        /* clear bss */
+
+	if (!kernel_args[0] && header->boot_arg[0]) { //have argument?
+		strncpy(kernel_args, header->boot_arg, header_size - sizeof(int)*3);
+	}
+
+	while (kernel_args[0] == 'i' && !kernel_args[1]) {
+	    printf("Enter kernel arguments:\n");
+	    printf("aboot> ");
+	    getline(kernel_args, sizeof(kernel_args));
+	    printf("\n");
+	}
+	return 0;
+}

+ 185 - 0
package/aboot/src/netabootwrap.c

@@ -0,0 +1,185 @@
+#include <sys/types.h>
+#include <asm/console.h>
+#include "system.h"
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include "netwrap.h"
+#include "bootloader.h"
+
+
+char *tfn="netboot.img", *kfn="vmlinux.gz", *ifn=NULL, *barg=NULL;
+char *progname;
+
+void print_usage(void )
+{
+	printf("Following shows options and default values or example value\n");
+	printf("%s -t netboot.img -k vmlinux.gz -i initrd.gz -a \"root=/dev/hda1 single\"\n", progname);
+	exit(1);
+}
+
+void open_file(char *fn, int *fd, int *sz)
+{
+	struct stat buf;
+
+	*fd = open(fn, O_RDONLY);
+	if (fd < 0) {
+		fprintf(stderr, "%s: Cannot open %s\n", progname, fn);
+		print_usage();
+		exit(1);
+	}
+
+	fstat(*fd, &buf);
+
+	if (buf.st_size <= 10*1024) {
+		fprintf(stderr, "%s:Is this a right file %s, size = %d\n", progname, fn, (int)buf.st_size);
+		print_usage();
+		exit(1);
+	}
+
+	*sz = buf.st_size;
+}
+
+void append_file(int tfd, int sfd)
+{
+	char buf[4096];
+	int  red;
+
+	while ((red=read(sfd, buf, 4096)))
+		write(tfd, buf, red);
+}
+
+int main(int argc, char **argv)
+{
+	int tfd=0, kfd=0, ifd=0, ksz=0, isz=0;
+	struct header hdr;
+	char *stmp;
+
+	progname=argv[0];
+
+	/*
+	 * Read switches.
+	 */
+	for (argc--, argv++; argc > 0; argc--, argv++) {
+		if (argv[0][0] != '-')
+			break;
+		switch (argv[0][1]) {
+
+		case 't':		    /* override target file name */
+			if (argv[0][2]) {
+				stmp = &(argv[0][2]);
+			} else {
+				argc--;
+				argv++;
+				stmp = argv[0];
+			}
+			if (!stmp) {
+				fprintf(stderr,
+				    "%s: missing file name for target\n",progname);
+				break;
+			}
+			tfn = stmp;
+			break;
+		case 'k':			/* override kernel name */
+			if (argv[0][2]) {
+				stmp = &(argv[0][2]);
+			} else {
+				argc--;
+				argv++;
+				stmp = argv[0];
+			}
+			if (!stmp) {
+				fprintf(stderr,
+					"%s: missing file name for kernel\n",progname);
+				break;
+			}
+			kfn = stmp;
+			break;
+		case 'i':			/* override file name for initrd */
+			if (argv[0][2]) {
+				stmp = &(argv[0][2]);
+			} else {
+				argc--;
+				argv++;
+				stmp = argv[0];
+			}
+			if (!stmp) {
+				fprintf(stderr,
+					"%s: missing file name for initial RAM-disk\n",progname);
+				break;
+			}
+			ifn = stmp;
+			break;
+		case 'a':			/* add kernel parameters */
+			if (argv[0][2]) {
+				stmp = &(argv[0][2]);
+			} else {
+				argc--;
+				argv++;
+				stmp = argv[0];
+			}
+			if (!stmp) {
+				fprintf(stderr,
+					"%s: No kernel parameters specified\n",progname);
+				break;
+			}
+			barg = stmp;
+			break;
+		default:
+			fprintf(stderr, "%s: unknown switch: -%c\n",
+					progname, argv[0][1]);
+			print_usage();
+			break;
+
+		} /* switch */
+	} /* for args */
+
+	open_file(kfn, &kfd, &ksz);
+
+	if (ifn)
+		open_file(ifn, &ifd, &isz);
+
+	printf("Target file name is %s\n", tfn);
+	unlink(tfn);
+	tfd = open(tfn, O_RDWR|O_CREAT, 0644);
+
+	write(tfd, bootloader, sizeof(bootloader));
+
+	hdr.header_size = sizeof(int)*3;
+	hdr.kern_size = ksz;
+	hdr.ird_size = isz;
+
+	if (barg) printf("With kernel arguments : %s \n", barg);
+	else printf("Without kernel argument\n");
+
+	if (barg) {
+		if (strlen(barg) >= 200) {
+			printf("Kernel argument-list is too long\n");
+			exit(1);
+		}
+		strncpy(hdr.boot_arg, barg, strlen(barg)+1);
+		hdr.header_size += strlen(barg)+1;
+	}
+
+	lseek(tfd, align_512(sizeof(bootloader)), SEEK_SET);
+	write(tfd, &hdr, hdr.header_size);
+
+	printf("Binding kernel %s\n", kfn);
+	lseek(tfd, align_512((unsigned long)lseek(tfd, 0, SEEK_CUR)), SEEK_SET);
+	append_file(tfd, kfd);
+
+	if (ifn) {
+		printf("Binding initrd %s\n", ifn);
+		lseek(tfd, align_512((unsigned long)lseek(tfd, 0, SEEK_CUR)), SEEK_SET);
+		append_file(tfd, ifd);
+	}
+
+	close(tfd);
+	printf("Done.\n");
+	return 0;
+}
+
+
+

+ 17 - 0
package/aboot/src/netwrap.h

@@ -0,0 +1,17 @@
+struct header {
+	int header_size;
+	int kern_size;
+	int ird_size; 
+	char boot_arg[200]; 
+} ;
+
+unsigned long align_pagesize(unsigned long v)
+{
+        return ((v + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1));
+}
+
+unsigned long align_512(unsigned long v)
+{
+        return ((v + 511) & ~511);
+}
+

+ 2 - 0
package/aboot/src/sdisklabel/.cvsignore

@@ -0,0 +1,2 @@
+sdisklabel
+swriteboot

+ 15 - 0
package/aboot/src/sdisklabel/Makefile

@@ -0,0 +1,15 @@
+ifndef ($(CC))
+CC 	?= gcc
+endif
+override CFLAGS += -g -O2 -I../include -Wall $(CPPFLAGS)
+
+all:	sdisklabel swriteboot
+
+sdisklabel: sdisklabel.o library.o
+	$(CC) $(LDFLAGS) $(CFLAGS) sdisklabel.o library.o -o sdisklabel
+
+swriteboot: swriteboot.o library.o
+	$(CC) $(LDFLAGS) $(CFLAGS) swriteboot.o library.o -o swriteboot
+
+clean:
+	rm -f sdisklabel swriteboot *.o

+ 105 - 0
package/aboot/src/sdisklabel/README

@@ -0,0 +1,105 @@
+These are sources and binaries for a Linux/Alpha boot file installer
+and disk partitioner. They're horrible, and should be destroyed.
+We're going to assume you don't have OSF/1, but want to use your hard
+drive. If you have OSF/1, what are you doing in here??!?!?!!?
+
+The program also assumes you have a SCSI disk with 512-byte sectors,
+tho it should work fine on an IDE drive as well.  All sizes are
+specified on the command line in sectors.
+
+There are 8 partitions in total, and are numbered from 0 to 7.
+Partitions have to be added sequentially, as this program won't let
+you leave empty partitions unlike many BSD disklabel programs.
+
+First off, if you have an invalid disk label (you've never run this
+program before) you get to do
+
+	sdisklabel /dev/sda zero
+
+(/dev/sda is the device you're partitioning, substitute as
+appropriate).
+
+This zeros out your disk label. Only do this if you really want to
+zero your disk label. It just does it; it doesn't ask, or warn, or
+anything.
+
+The program also probably printed out the size of your disk in K. If
+it was wrong, you now get to use the "size xxx" option along with the
+rest of these commands. The size isn't critical, it's just used to try
+and make sure you don't go past the end of the disk.
+
+Next, add your first partition. This *doesn't* start from 0, as you
+have to leave room for the boot loader and other stuff. 256K (or 512
+sectors) will be enough.
+
+Let's pretend that you want to make a 250000K partition starting
+from sector offset 512:
+
+	sdisklabel /dev/sda 0 512 500000 8 print
+
+The last number is the filesystem type, and is currently 8 for ext2fs
+filesystems. (A different number would be used to specify an OSF/1
+partition, for example).
+
+If all was successful, the program should print out the partition (the
+last keyword, "print", specifies that it should print the partition
+after modifying it with the previous command), and you should see
+something like
+----------------------------------------------------------------
+I think your disk is 528870K total size.
+If I'm wrong, override the size with the 'size num' option
+
+partition 0: type 8, starts sector 512, size 500000
+----------------------------------------------------------------
+
+We can then add the next partition, which would be partition 1.
+To add a second partition that is 200000K long, we'd run
+	sdisklabel /dev/sda 1 512256 400000 8 print
+And both partitions would then be printed out.
+
+If for some reason the size got determined incorrectly, we'd do
+instead
+
+	sdisklabel /dev/sda size 528870 0 512 400000 8 print
+
+The size option should come immediately after the device name, and the
+size is the total # of sectors on the drive.
+
+That wasn't too bad, was it? The program doesn't do enough error
+checking, but it should work OK if you don't try to abuse it.
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+Adding a bootstrap to the HD
+
+This isn't exactly trivial, and should be done immediately after
+setting up the partitions (but not before...). I can't be held
+responsible if the bootstrap writer wipes your drive-it does hardly
+any error checking, tho it tries to make sure that you're not going to
+wipe out any partitions before it starts writing.
+
+The program basically writes a raw binary image (*not* an a.out format file)
+to the disk starting from sector 2. This can be generated from an executable
+by using the arch/alpha/linux/tools/build program found in the kernel
+distribution, or the similar program in the aboot distributiion. So to
+install the bootloader in bootlx, assuming you've partitioned your disk (and
+left enough blank space between the start of the disk and the first
+partition to hold the bootloader):
+
+	swriteboot /dev/sda bootlx
+
+When using aboot, you can also append a kernel image by using
+        
+        swriteboot /dev/sda bootlx vmlinux.gz
+
+If you invoke swriteboot with the '-v' option, it will be a bit more
+verbose.
+
+If you have to partition your disk with a program that does not allow to
+leave a blank (unpartitiones) space at the beginning for the bootloader,
+create a partition of the desired size instead. swriteboot will complain
+that the desired boot area overlaps with that partition, so you must use
+
+        swriteboot -f# ...
+
+where # is the partition number to force overwriting this area.

+ 79 - 0
package/aboot/src/sdisklabel/library.c

@@ -0,0 +1,79 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <string.h>
+#include <unistd.h>
+#include <disklabel.h>
+#include "library.h"
+
+int read_disklabel(int fd,struct disklabel *d) {
+   if(lseek(fd,LABELOFFSET,SEEK_SET)<0) {
+      return -1;
+   }
+   if(read(fd,d,sizeof(*d))!=sizeof(*d)) {
+      return -1;
+   }
+   if(d->d_magic!=DISKLABELMAGIC || d->d_magic2!=DISKLABELMAGIC) {
+      fprintf(stderr,"Existing disk label is corrupt\n");
+      return -1;
+   }
+   return 0;
+}
+
+int dosumlabel(int fd,struct disklabel *d) {
+  u_int64_t buf[128];
+  int x;
+  u_int64_t sum=0;
+
+  if(lseek(fd,0,SEEK_SET)<0) {
+     return -1;
+  }
+  if(read(fd,buf,64*sizeof(u_int64_t))!=(64*sizeof(u_int64_t))) {
+     return -1;
+  }
+  memcpy(&buf[LABELOFFSET/sizeof(u_int64_t)],d,sizeof(*d));
+  for(x=0;x<63;x++) {
+    sum+=buf[x];
+  }
+  if(lseek(fd,63*sizeof(u_int64_t),SEEK_SET)<0) {
+     return -1;
+  }
+  if(write(fd,&sum,sizeof(sum))!=sizeof(sum)) {
+     return -1;
+  }
+  return 0;
+}
+
+static int does_overlap(int a1,int a2,int b1,int b2) {
+   if(a1>b1 && a1<b2) {
+      return 1;
+   }
+   if(a2>b1 && a2<b2) {
+      return 1;
+   }
+   if(b1>a1 && b1<a2) {
+      return 1;
+   }
+   if(b2>a1 && b2<a2) {
+      return 1;
+   }
+   return 0;
+}
+
+/*
+   returns the number of the partition overlapping with the area
+   from offset to endplace, while ignoring partitions in the bitset ignore.
+*/
+int overlaplabel(struct disklabel *d,int offset,int endplace,unsigned force) {
+   int x;
+
+   for(x=0;x<d->d_npartitions;x++) {
+      if((force & (1U << x)) == 0) {
+	 int part_offset=d->d_partitions[x].p_offset;
+	 int part_end=d->d_partitions[x].p_offset+d->d_partitions[x].p_size;
+	 if(part_end>0 && does_overlap(part_offset,part_end,offset,endplace)) 
+	    return x;
+      }
+   }
+   return -1;
+}
+

+ 8 - 0
package/aboot/src/sdisklabel/library.h

@@ -0,0 +1,8 @@
+#ifndef _LIBRARY_H
+#define _LIBRARY_H
+
+int read_disklabel(int fd,struct disklabel *d);
+int dosumlabel(int fd,struct disklabel *d);
+int overlaplabel(struct disklabel *d,int offset,int endplace, unsigned force);
+
+#endif

+ 241 - 0
package/aboot/src/sdisklabel/sdisklabel.c

@@ -0,0 +1,241 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <string.h>
+#include <unistd.h>
+#include <disklabel.h>
+#include <sys/ioctl.h>
+#include <linux/hdreg.h>
+#include "library.h"
+
+/* from linux/fs.h */
+#define BLKSSZGET  _IO(0x12,104)   /* get block device sector size */
+#define BLKGETSIZE _IO(0x12,96)    /* return device size */
+
+int label_modified=0;
+int force=0;
+
+int
+write_disklabel (int fd,struct disklabel *d)
+{
+	dosumlabel(fd,d);
+	if(lseek(fd,LABELOFFSET,SEEK_SET)<0) {
+		return -1;
+	}
+	if(write(fd,d,sizeof(*d))!=sizeof(*d)) {
+		return -1;
+	}
+	return 0;
+}
+
+void
+fixmagic (int fd,struct disklabel *d)
+{
+	d->d_magic=DISKLABELMAGIC;
+	d->d_magic2=DISKLABELMAGIC;
+	d->d_type=DTYPE_SCSI;
+	d->d_secsize=512;
+	strcpy(d->d_typename,"SCSI");
+}
+
+void
+zero_disklabel (int fd,struct disklabel *d)
+{
+	memset(d,0,sizeof(*d));
+	fixmagic(fd,d);
+	label_modified=1;
+}
+
+void
+print_disklabel(int fd,struct disklabel *d)
+{
+	int x;
+	for(x=0;x<d->d_npartitions;x++) {
+		printf("partition %d: type %d, starts sector %d, size %d\n",
+		       x, d->d_partitions[x].p_fstype,
+		       d->d_partitions[x].p_offset, d->d_partitions[x].p_size);
+	}
+}
+
+int total_disk_size, heads, sectors, cylinders;
+/* FIXME: use BLKSSZGET to get sector size. (depends on linux >=2.4) */
+int sector_size=512;
+
+#ifdef __linux__
+
+void
+set_disk_size (int fd)
+{
+	struct hd_geometry hd;
+	unsigned long blocks;
+	unsigned int sectors_per_block;
+	int r1, r2;
+	
+	sectors_per_block = sector_size / 512;
+	heads = sectors = cylinders = blocks = 0;
+
+	r1 = ioctl(fd,HDIO_GETGEO,&hd);
+
+	if (r1) {
+		perror("ioctl HDIO_GETGEO");
+	} else {
+		heads = hd.heads;
+		sectors = hd.sectors;
+		cylinders = hd.cylinders;
+		if (heads * sectors * cylinders == 0) { r1 = -1; }
+		/* fdisk says: "never use hd.cylinders - it is truncated" 
+		   if BLKGETSIZE works we'll calculate our own value for
+		   cylinders in a little bit, but for now, use it anyway */
+		total_disk_size=(heads*sectors*cylinders); /* in sectors */ 
+	}
+	
+	r2 = ioctl(fd,BLKGETSIZE, &blocks);
+
+	if (r2) {
+		perror("ioctl BLKGETSIZE");
+	}
+
+	if (r1 && r2) {
+		if (!total_disk_size) {
+			fprintf(stderr, "Unable to get disk size. Please specify it with the size [size_in_sectors] option.\n\n");
+		}
+		return;
+	}
+
+	if (r1 == 0 && r2 == 0) {
+		total_disk_size = blocks; /* sizes in sectors */
+		cylinders = blocks / (heads * sectors);
+		cylinders /= sectors_per_block;
+	} else if (r1 == 0) {
+		fprintf(stderr, "Unable to get disk geometry. Guessing number of sectors from disk size.\n");
+		cylinders = heads = 1;
+		sectors = blocks / sectors_per_block;
+	}
+	fprintf(stderr,"%d heads, %d sectors, %d cylinders %dK total size\n", 
+		heads, sectors, cylinders, total_disk_size/2);
+}
+#endif
+
+int
+set_partition (int fd,struct disklabel *d,int num,int offset,int size,int fstype)
+{
+	int endplace=offset+size;
+	int x;
+
+	if(endplace>total_disk_size) {
+		fprintf(stderr,"endplace is %d total_disk_size is %d\n",endplace,total_disk_size);
+		if (!force) return -1;
+		/* correct the discrepancy */
+		size = total_disk_size-offset;
+		endplace=total_disk_size;
+		fprintf(stderr,"Warning: changing endplace to %d and size to %d\n",endplace,size);
+	}
+
+	if(num>d->d_npartitions) {
+		fprintf(stderr,"Partition not consecutive! This would leave empty partitions.\nNext unset partition is %d.\n",d->d_npartitions);
+		if (!force) return -1;
+	}
+	x=overlaplabel(d,offset,endplace,1U<<num);
+	if(x!=-1)
+	  fprintf(stderr,"Warning: added partition %d overlaps with partition %d\n",num,x);
+	  
+	d->d_partitions[num].p_offset=offset;
+	d->d_partitions[num].p_size=size;
+	d->d_partitions[num].p_fstype=fstype;
+	if(num==d->d_npartitions) {
+		d->d_npartitions++;
+	}
+	label_modified=1;
+	return 0;
+}
+
+void
+usage (char *cmd_name)
+{
+	fprintf(stderr,"Usage: %s drive print\n",cmd_name);
+	fprintf(stderr,"       %s drive zero\n",cmd_name);
+	fprintf(stderr,"       %s drive partition_number offset_in_sectors size_in_sectors partition_type\n",cmd_name);
+	fprintf(stderr,"       %s drive sum\n",cmd_name);
+	fprintf(stderr,"       %s drive size size_in_sectors [other command]\n\n",cmd_name);
+	fprintf(stderr,"The print command may be placed before or after any other command.\n");
+	fprintf(stderr,"The size command is used to override the size of the disk, if the\nprogram isn't able to obtain this information for some reason.\n");
+	fprintf(stderr,"The partition type should be 8, unless you are creating\nlabels for OSF/1 partitions.\n");
+}
+
+
+int
+main (int argc,char **argv)
+{
+	struct disklabel d;
+	int fd,x;
+
+	if(argc < 3) {
+		usage(argv[0]);
+		exit(1);
+	}
+	fd=open(argv[1],O_RDWR);
+	if(fd<0) {
+		perror("couldn't open scsi disk");
+		exit(1);
+	}
+#ifdef __linux__
+	set_disk_size(fd);
+#endif
+	if(strcmp(argv[2],"zero")==0) {
+		zero_disklabel(fd,&d);
+	} else {
+		if(read_disklabel(fd,&d)) {
+			fprintf(stderr,"Error reading disklabel\n");
+			exit(1);
+		}
+	}
+	for(x=2;x<argc;) {
+		if(strcmp(argv[x],"size")==0 && ((x+1)<argc)) {
+			total_disk_size=atoi(argv[x+1]);
+			x+=2;
+		}
+		if(strcmp(argv[x],"sum")==0) {
+			dosumlabel(fd,&d);
+			x++;
+		}
+		else if(strcmp(argv[x],"zero")==0) {
+			zero_disklabel(fd,&d);
+			x++;
+		}
+		else if(strcmp(argv[x],"print")==0) {
+			print_disklabel(fd,&d);
+			x++;
+		}
+		else if(strcmp(argv[x],"force")==0) {
+		        force=1;
+			x++;
+		}
+		else {
+			if((argc-x)>3 && isdigit(argv[x][0]) && isdigit(argv[x+1][0]) && isdigit(argv[x+2][0]) && isdigit(argv[x+3][0])) {
+				int partnum=atoi(argv[x]);
+				int offset=atoi(argv[x+1]);
+				int size=atoi(argv[x+2]);
+				int fstype=atoi(argv[x+3]);
+				if(partnum<0 || partnum>7) {
+					fprintf(stderr,"Partition number %d out of range--partitions should be between 0 and 7\n",partnum);
+					exit(1);
+				}
+				if(set_partition(fd,&d,partnum,offset,size,fstype)) {
+					fprintf(stderr,"Set of partition failed\n");
+					exit(1);
+				}
+				x+=4;
+			} else {
+				fprintf(stderr,"Unrecognized option %s\n",argv[x]);
+				usage(argv[0]);
+				exit(1);
+			}
+		}
+	}
+	if(label_modified && write_disklabel(fd,&d)) {
+		fprintf(stderr,"Error writing disklabel\n");
+		exit(1);
+	}
+	return 0;
+}

+ 226 - 0
package/aboot/src/sdisklabel/swriteboot.c

@@ -0,0 +1,226 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "system.h"
+#include <disklabel.h>
+#include <config.h>
+#include "library.h"
+
+#define SECT_SIZE 512
+#define BOOT_SECTOR 2
+
+int read_configured_partition(int disk_fd, char* buf)
+{
+  u_int64_t bootsize, bootsect, bootpart = 0;
+  long *p = (long *) buf;
+  
+  if(lseek(disk_fd,60*8,SEEK_SET)<0) {
+    perror("lseek on disk");
+    exit(1);
+  }
+  /* Find old configuration */
+  read(disk_fd, &bootsize, sizeof(bootsize));
+  read(disk_fd, &bootsect, sizeof(bootsect));
+  if(lseek(disk_fd,SECT_SIZE*bootsect,SEEK_SET)<0)
+    return 0; /* probably random garbage in the boot block - not
+		 a fatal error */
+  read(disk_fd, buf, SECT_SIZE);
+  while ((char *)p < buf + SECT_SIZE)
+    if (*p++ == ABOOT_MAGIC)
+      bootpart = *p;
+  return bootpart;
+}
+
+int main(int argc, char **argv)
+{
+   u_int64_t bootsize,kernelsize=0;
+   u_int64_t bootsect=BOOT_SECTOR;
+   u_int64_t magicnum=0;
+   int disk_fd,file_fd,kernel_fd=0;
+   struct disklabel dlabel;
+   struct stat s;
+   int x;
+   char buf[2048];
+   int c;
+   int err=0, part, bootpart=0;
+   unsigned force_overlap=0;
+   int verbose=0;
+   extern int optind;
+   extern char *optarg;
+   char *bootfile=0, *device=0, *kernel=0;
+   
+   while ((c=getopt(argc,argv,"f:c:v?"))!=EOF)
+     switch(c)
+     {
+       case '?':
+         err=1;
+         break;
+       case 'f':
+	 part = atoi(optarg);
+	 if (part < 1 || part > 8) {
+	     fprintf(stderr, "%s: partition number must be in range 1-8\n",
+		     argv[0]);
+	     exit(1);
+	 }
+         force_overlap |= 1U << (part - 1);
+         break;
+       case 'c':
+	 bootpart = atoi(optarg);
+	 if (bootpart < 1 || bootpart > 8) {
+	     fprintf(stderr, "%s: partition number must be in range 1-8\n",
+		     argv[0]);
+	     exit(1);
+	 }
+	 break;
+       case 'v':
+         verbose=1;
+         break;
+       default:
+         err=1;
+         break;
+     }  
+
+  if(optind<argc)
+    device=argv[optind++];
+  if(optind<argc)
+    bootfile=argv[optind++];
+  if(optind<argc)
+    kernel=argv[optind++];
+    
+  if(!bootfile || !device || err)
+  {
+      fprintf(stderr, "Usage: %s [-f[1-8]] [-c[1-8]] [-v] disk bootfile [kernel]\n",
+	      argv[0]);
+      exit(1);
+   }
+  
+   disk_fd=open(device,O_RDWR);
+   file_fd=open(bootfile,O_RDONLY);
+   if(disk_fd<0) {
+      perror("open disk device");
+      exit(1);
+   }
+   if(file_fd<0) {
+      perror("open bootfile");
+      exit(1);
+   }
+   
+   if(kernel)
+   {
+     kernel_fd=open(kernel,O_RDONLY);
+     if (kernel_fd<0)
+     {
+       perror("open kernel");
+       exit(1);
+     }
+     else
+     {
+       if(fstat(kernel_fd,&s)) {
+         perror("fstat kernel");
+         exit(1);
+       }
+       kernelsize=(s.st_size+SECT_SIZE-1)/SECT_SIZE;
+     }
+   }
+   if(read_disklabel(disk_fd,&dlabel)) {
+      fprintf(stderr,"Couldn't get a valid disk label, exiting\n");
+      exit(1);
+   }
+   if(fstat(file_fd,&s)) {
+      perror("fstat bootfile");
+      exit(1);
+   }
+   bootsize=(s.st_size+SECT_SIZE-1)/SECT_SIZE;
+
+   if(-1 !=(x=overlaplabel(&dlabel,bootsect,bootsize+bootsect+kernelsize,force_overlap)))
+   {
+      fprintf(stderr,
+	      "error: bootcode overlaps with partition #%d. "
+	      "If you really want this, use -f%d\n",
+	      x + 1, x + 1);
+      exit(1);
+   }
+
+   if(!bootpart) {
+      bootpart = read_configured_partition(disk_fd, buf);
+      if (verbose) {
+	 if (bootpart) {
+	    printf("preserving boot partition %d\n", bootpart);
+	 } else {
+	    printf("could not find existing aboot, configuring for second partition\n");
+	 }
+      }
+   } else {
+      if (verbose) {
+	 printf("setting boot partition to %d\n", bootpart);
+      }
+   }
+   if(lseek(disk_fd,60*8,SEEK_SET)<0) {
+      perror("lseek on disk");
+      exit(1);
+   }
+   write(disk_fd,&bootsize,sizeof(bootsize));
+   write(disk_fd,&bootsect,sizeof(bootsect));
+   write(disk_fd,&magicnum,sizeof(magicnum));
+   if (verbose)
+   {
+     fprintf(stderr,"bootsize:%lu sectors\n",bootsize);
+     fprintf(stderr,"bootsect:%lu\n",bootsect);
+   }
+   if(lseek(disk_fd,SECT_SIZE*bootsect,SEEK_SET)<0) {
+      perror("lseek #3 on disk\n");
+      exit(1);
+   }
+   while((x=read(file_fd,buf,2048))>0) {
+      write(disk_fd,buf,x);
+   }
+   close(file_fd);
+   if (kernel_fd > 0 && kernelsize>0)
+   {
+     unsigned long len = 0;
+
+     if (verbose)
+       fprintf(stderr,"kernel:%lu sectors\n",kernelsize);
+#if 0
+     if(lseek(disk,BOOT_SIZE+BOOT_SECTOR*SECT_SIZE,SEEK_SET)<0) {
+       perror("lseek #4 on disk\n");
+       exit(1);
+     }
+#endif
+     while((x=read(kernel_fd,buf,2048))>0)
+     {
+       write(disk_fd,buf,x);
+       len += x;
+     }
+     close(kernel_fd);
+     if ((len+SECT_SIZE-1)/SECT_SIZE != kernelsize)
+       fprintf(stderr,"warning: kernel read %lu, should be %lu\n",(len+SECT_SIZE-1)/SECT_SIZE,kernelsize);
+   }
+   /* Now write the aboot partition config if we had one */
+   if (bootpart) {
+     long *p = (long *) buf;
+
+     if(lseek(disk_fd,SECT_SIZE*bootsect,SEEK_SET)<0) {
+       perror("lseek #5 on disk\n");
+       exit(1);
+     }
+     read(disk_fd, buf, SECT_SIZE);
+     while ((char *)p < buf + SECT_SIZE) {
+       if (*p++ == ABOOT_MAGIC) {
+	 *p = bootpart;
+       }
+     }
+     lseek(disk_fd,SECT_SIZE*bootsect,SEEK_SET);
+     write(disk_fd, buf, SECT_SIZE);
+   }
+   dosumlabel(disk_fd,&dlabel);
+   close(disk_fd);
+   if(verbose)
+     fprintf(stderr,"done!\n");
+   return 0;
+}

+ 349 - 0
package/aboot/src/srmbootfat/COPYING

@@ -0,0 +1,349 @@
+This software uses part of mtools-3.9.
+Mtools are Copyright (C) 1995 Alain Knaff.
+The rest is Copyright (C) 1998 Nikita Schmidt.
+
+ You may use, distribute and copy this program according to the terms of the
+GNU General Public License version 2 or later.
+
+ Alain Knaff
+----------------------------------------
+
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, 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
+
+	Appendix: 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., 675 Mass Ave, Cambridge, MA 02139, 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.

+ 24 - 0
package/aboot/src/srmbootfat/Makefile

@@ -0,0 +1,24 @@
+ifndef ($(CC))
+CC	= gcc
+endif
+override CFLAGS	+= -O2 -g -pipe -Wall
+#override LDFLAGS	+= -s
+SBINDIR	= ../bin
+
+all:	srmbootfat srmbootraw srmbootfat.1 srmbootraw.8
+
+srmbootfat: srmbootfat.c msdos.h
+	$(CC) $(CFLAGS) $(LDFLAGS) -o srmbootfat srmbootfat.c
+
+srmbootraw: srmbootraw.c
+	$(CC) $(CFLAGS) $(LDFLAGS) -o srmbootraw srmbootraw.c
+
+srmbootfat.1: srmbootfat.sgml
+	nsgmls srmbootfat.sgml | sgmlspl sgmlspl-specs/docbook2man-spec.pl
+
+srmbootraw.8: srmbootraw.sgml
+	nsgmls srmbootraw.sgml | sgmlspl sgmlspl-specs/docbook2man-spec.pl
+
+clean:
+	rm -f srmbootfat srmbootraw srmbootfat.1 srmbootraw.8 manpage.links manpage.log manpage.refs
+

+ 5 - 0
package/aboot/src/srmbootfat/README

@@ -0,0 +1,5 @@
+The contents of this diretory are taken from the milo source
+which can be found at http://milo.coresystems.de/source/milo-2.2-18.tar.bz2
+
+Additional patches to srmbootfat have been applied; also the man pages are
+improved in respect to the upstream version.

+ 160 - 0
package/aboot/src/srmbootfat/msdos.h

@@ -0,0 +1,160 @@
+#ifndef MTOOLS_MSDOS_H
+#define MTOOLS_MSDOS_H
+
+/*
+ * msdos common header file
+ */
+
+#define MAX_SECTOR	8192   		/* largest sector size */
+#define MDIR_SIZE	32		/* MSDOS directory entry size in bytes*/
+#define MAX_CLUSTER	8192		/* largest cluster size */
+#define MAX_PATH	128		/* largest MSDOS path length */
+#define MAX_DIR_SECS	64		/* largest directory (in sectors) */
+
+#define NEW		1
+#define OLD		0
+
+#define _WORD(x) ((unsigned char)(x)[0] + (((unsigned char)(x)[1]) << 8))
+#define _DWORD(x) (_WORD(x) + (_WORD((x)+2) << 16))
+
+#define DELMARK ((char) 0xe5)
+
+struct directory {
+	char name[8];			/*  0 file name */
+	char ext[3];			/*  8 file extension */
+	unsigned char attr;		/* 11 attribute byte */
+	unsigned char Case;		/* 12 case of short filename */
+	unsigned char ctime_ms;		/* 13 creation time, milliseconds (?) */
+	unsigned char ctime[2];		/* 14 creation time */
+	unsigned char cdate[2];		/* 16 creation date */
+	unsigned char adate[2];		/* 18 last access date */
+	unsigned char startHi[2];	/* 20 start cluster, Hi */
+	unsigned char time[2];		/* 22 time stamp */
+	unsigned char date[2];		/* 24 date stamp */
+	unsigned char start[2];		/* 26 starting cluster number */
+	unsigned char size[4];		/* 28 size of the file */
+};
+
+#define EXTCASE 0x10
+#define BASECASE 0x8
+
+#define MAX32 0xffffffff
+#define MAX_SIZE 0x7fffffff
+
+
+
+typedef struct InfoSector_t {
+	unsigned char signature0[4];
+	unsigned char filler[0x1e0];
+	unsigned char signature[4];
+	unsigned char count[4];
+	unsigned char pos[4];
+} InfoSector_t;
+
+#define INFOSECT_SIGNATURE0 0x41615252
+#define INFOSECT_SIGNATURE 0x61417272
+
+
+/* FAT32 specific info in the bootsector */
+typedef struct fat32_t {
+	unsigned char bigFat[4];	/* 36 nb of sectors per FAT */
+	unsigned char extFlags[2];     	/* 40 extension flags */
+	unsigned char fsVersion[2];	/* 42 ? */
+	unsigned char rootCluster[4];	/* 44 start cluster of root dir */
+	unsigned char infoSector[2];	/* 48 changeable global info */
+	unsigned char backupBoot[2];	/* 50 back up boot sector */
+	unsigned char reserved[6];	/* 52 ? */
+} fat32; /* ends at 58 */
+
+typedef struct oldboot_t {
+	unsigned char physdrive;	/* 36 physical drive ? */
+	unsigned char reserved;		/* 37 reserved */
+	unsigned char dos4;		/* 38 dos > 4.0 diskette */
+	unsigned char serial[4];       	/* 39 serial number */
+	char label[11];			/* 43 disk label */
+	char fat_type[8];		/* 54 FAT type */
+			
+	unsigned char res_2m;		/* 62 reserved by 2M */
+	unsigned char CheckSum;		/* 63 2M checksum (not used) */
+	unsigned char fmt_2mf;		/* 64 2MF format version */
+	unsigned char wt;		/* 65 1 if write track after format */
+	unsigned char rate_0;		/* 66 data transfer rate on track 0 */
+	unsigned char rate_any;		/* 67 data transfer rate on track<>0 */
+	unsigned char BootP[2];		/* 68 offset to boot program */
+	unsigned char Infp0[2];		/* 70 T1: information for track 0 */
+	unsigned char InfpX[2];		/* 72 T2: information for track<>0 */
+	unsigned char InfTm[2];		/* 74 T3: track sectors size table */
+	unsigned char DateF[2];		/* 76 Format date */
+	unsigned char TimeF[2];		/* 78 Format time */
+	unsigned char junk[1024 - 80];	/* 80 remaining data */
+} oldboot_t;
+
+struct bootsector {
+	unsigned char jump[3];		/* 0  Jump to boot code */
+	char banner[8];		       	/* 3  OEM name & version */
+	unsigned char secsiz[2];	/* 11 Bytes per sector hopefully 512 */
+	unsigned char clsiz;    	/* 13 Cluster size in sectors */
+	unsigned char nrsvsect[2];	/* 14 Number of reserved (boot) sectors */
+	unsigned char nfat;		/* 16 Number of FAT tables hopefully 2 */
+	unsigned char dirents[2];	/* 17 Number of directory slots */
+	unsigned char psect[2]; 	/* 19 Total sectors on disk */
+	unsigned char descr;		/* 21 Media descriptor=first byte of FAT */
+	unsigned char fatlen[2];	/* 22 Sectors in FAT */
+	unsigned char nsect[2];		/* 24 Sectors/track */
+	unsigned char nheads[2];	/* 26 Heads */
+	unsigned char nhs[4];		/* 28 number of hidden sectors */
+	unsigned char bigsect[4];	/* 32 big total sectors */
+
+	union {
+		struct fat32_t fat32;
+		struct oldboot_t old;
+	} ext;
+};
+
+extern struct OldDos_t {
+	unsigned int tracks;
+	unsigned int sectors;
+	unsigned int heads;
+	
+	unsigned int dir_len;
+	unsigned int cluster_size;
+	unsigned int fat_len;
+
+	unsigned int media;
+} old_dos[];
+
+#define FAT12 4085 /* max. number of clusters described by a 12 bit FAT */
+#define FAT16 65525
+
+#define MAX_SECT_PER_CLUSTER 64
+/* Experimentally, it turns out that DOS only accepts cluster sizes
+ * which are powers of two, and less than 128 sectors (else it gets a
+ * divide overflow) */
+
+
+#define FAT_SIZE(bits, sec_siz, clusters) \
+	((((clusters)+2) * ((bits)/4) - 1) / 2 / (sec_siz) + 1)
+
+#define NEEDED_FAT_SIZE(x) FAT_SIZE((x)->fat_bits, (x)->sector_size, \
+				    (x)->num_clus)
+
+/* disk size taken by FAT and clusters */
+#define DISK_SIZE(bits, sec_siz, clusters, n, cluster_size) \
+	((n) * FAT_SIZE(bits, sec_siz, clusters) + \
+	 (clusters) * (cluster_size))
+
+#define TOTAL_DISK_SIZE(bits, sec_siz, clusters, n, cluster_size) \
+	(DISK_SIZE(bits, sec_siz, clusters, n, cluster_size) + 2)
+/* approx. total disk size: assume 1 boot sector and one directory sector */
+
+extern const char *mversion;
+extern const char *mdate;
+
+
+
+int init(char drive, int mode);
+
+#define MT_READ 1
+#define MT_WRITE 2
+
+#endif

+ 246 - 0
package/aboot/src/srmbootfat/srmbootfat.c

@@ -0,0 +1,246 @@
+/*
+ *  SRMbootFAT - SRM boot block composer for FAT filesystems.
+ *  Copyright (C) 1998 Nikita Schmidt  <cetus@snowball.ucd.ie>
+ *  msdos.h is Copyright (C) 1995 Alain Knaff.
+ *
+ *  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.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <sys/types.h>
+
+#include "msdos.h"
+
+/* This should test for little-endianness, but why bother,
+   the whole thing is Alpha-specific anyway. */
+#ifdef __alpha__	/* Little endian */
+#define WORD(x)	 (*(u_int16_t *)(x))
+#define DWORD(x) (*(u_int32_t *)(x))
+#else			/* Big endian; in fact, generic stuff */
+#define WORD	 _WORD
+#define DWORD	 _DWORD
+#endif
+
+union full_bootsector {
+	struct bootsector dos;
+	struct {
+		unsigned char textlabel[64];
+		unsigned char disklabel[276];
+		unsigned char unused[140];
+		u_int64_t count, start, flags;
+		u_int64_t checksum;
+	} srm;
+	struct {
+		u_int64_t contents[63];
+		u_int64_t checksum;
+	} check;
+};
+
+#ifdef __alpha__	/* Should be test for little endian */
+unsigned int get_fat_entry (unsigned char *fat, int fatbits, unsigned entry)
+{
+	unsigned i, a, b;
+
+	/* No check for fat boundaries... */
+	switch (fatbits) {
+	    case 12:
+		i = ((entry *= 3) & 7) << 2;	/* Number of bits to shift */
+		a = ((u_int32_t *)fat)[entry >>= 3];
+		b = ((u_int32_t *)fat)[entry + 1];   /* May be outside FAT */
+		return ((a >> i) | (b << (32 - i))) & 0xFFF;
+	    case 16:
+		return ((u_int16_t *)fat)[entry];
+	}
+	fprintf (stderr, "Unknown FAT type - FAT-%d\n", fatbits);
+	exit (3);
+}
+#else
+// Portable Version from Falk Hueffner <falk.hueffner@student.uni-tuebingen.de>
+unsigned int get_fat_entry (unsigned char *fat, int fatbits, unsigned entry)
+{
+        unsigned i, a, b;
+
+        /* No check for fat boundaries... */
+        switch (fatbits) {
+            case 12:
+                i = ((entry *= 3) & 7) << 2;    /* Number of bits to shift */
+                entry >>= 3;
+                a = DWORD(fat + 4 * entry);
+                b = DWORD(fat + 4 * entry + 4);
+                return ((a >> i) | (b << (32 - i))) & 0xFFF;
+            case 16:
+                return WORD(fat + 2 * entry);
+        }
+        fprintf (stderr, "Unknown FAT type - FAT-%d\n", fatbits);
+        exit (3);
+}
+#endif
+
+int main (int argc, char *argv[])
+{
+	int f;
+	int i;
+	char *p;
+	union full_bootsector boot;
+	unsigned secsize;	/* Bytes per sector, hopefully 512 */
+	unsigned clusize;    	/* Cluster size in sectors */
+	unsigned fatstart;	/* Number of reserved (boot) sectors */
+	unsigned nfat;		/* Number of FAT tables, hopefully 2 */
+	unsigned dirents;	/* Number of directory slots */
+	unsigned psect; 	/* Total sectors on disk */
+	unsigned media;		/* Media descriptor=first byte of FAT */
+	unsigned fatsize;	/* Sectors in FAT */
+	unsigned fatbits;	/* FAT type (bits per entry) */
+	unsigned char *fat;
+	struct directory *rootdir;
+	unsigned start;		/* Starting cluster of the boot file */
+	unsigned size;		/* Boot file size */
+	unsigned fat_end;
+	unsigned j;
+	u_int64_t checksum;
+	char dosname[12];
+
+	if (argc != 3)
+		return printf ("Usage:  srmbootfat <filesystem image file> <boot file>\n"), 1;
+
+	if ((f = open (argv[1], O_RDWR)) < 0)
+		return perror (argv[1]), 2;
+
+	if (read (f, &boot, sizeof boot) != sizeof boot)
+		return fprintf (stderr, "Can't read boot sector from %s\n", argv[1]), 2;
+
+	secsize = _WORD (boot.dos.secsiz);
+	clusize = boot.dos.clsiz;
+	fatstart = WORD (boot.dos.nrsvsect);
+	nfat = boot.dos.nfat;
+	dirents = _WORD (boot.dos.dirents);
+	psect = _WORD (boot.dos.psect);
+	media = boot.dos.descr;
+	fatsize = WORD (boot.dos.fatlen);
+
+	if ((media & ~7) == 0xf8) {
+		i = media & 3;
+		clusize = old_dos[i].cluster_size;
+		fatstart = 1;
+		fatsize = old_dos[i].fat_len;
+		dirents = old_dos[i].dir_len * (512 / MDIR_SIZE);
+		nfat = 2;
+		fatbits = 12;
+	} else if (strncmp (boot.dos.ext.old.fat_type, "FAT12", 5) == 0)
+		fatbits = 12;
+	else if (strncmp (boot.dos.ext.old.fat_type, "FAT16", 5) == 0)
+		fatbits = 16;
+	else return fprintf (stderr, "%s: unrecognisable FAT type\n", argv[1]),
+			3;
+#ifdef DEBUG
+	printf ("%s: filesystem type is FAT-%d\n", argv[1], fatbits);
+#endif
+
+	if (secsize != 512)
+		return fprintf (stderr, "%s: sector size is %d; "
+				"unfortunately, this is not supported\n",
+				argv[1], secsize),
+			3;
+	if (nfat != 1 && nfat != 2)
+		fprintf (stderr,
+			"%s: warning: weird number of FAT tables (%d)\n",
+			argv[1], nfat);
+
+	fat = malloc (i = fatsize * secsize);
+	rootdir = malloc (dirents * MDIR_SIZE);
+	if (!fat || !rootdir)
+		return fprintf (stderr, "Not enough memory\n"), 2;
+	if (lseek (f, fatstart * secsize, SEEK_SET) == -1
+	 || read (f, fat, i) != i
+	 || lseek (f, (nfat - 1) * i, SEEK_CUR) == -1
+	 || read (f, rootdir, dirents * MDIR_SIZE) != dirents * MDIR_SIZE)
+		return perror (argv[1]), 2;
+
+	memset (dosname, ' ', sizeof dosname);
+	i = 0;
+	for (p = argv[2]; *p; p++)
+		if (*p == '.')
+			i = 8;
+		else if (i < sizeof dosname)
+			dosname[i++] = toupper (*p);
+
+	for (i = 0; i < dirents; i++)
+		if (memcmp (rootdir[i].name, dosname, 11) == 0
+		 && (rootdir[i].attr & (8 | 16)) == 0)
+			break;
+	if (i == dirents)
+		return fprintf (stderr,
+			"Can't find %s in the root directory in %s\n",
+			argv[2], argv[1]), 4;
+
+	start = WORD (rootdir[i].start);
+	size = DWORD (rootdir[i].size);
+
+	if (start * fatbits > fatsize * secsize * 8)
+		return fprintf (stderr,
+			"%s: first cluster (%u) is beyond the end of FAT",
+			argv[2], start), 3;
+
+	/* Fill in the bootstrap information */
+	size = (size + secsize - 1) / secsize;	/* Size is now in sectors */
+	boot.srm.start = (start - 2) * clusize + fatstart + nfat * fatsize
+		+ dirents / (512 / MDIR_SIZE);
+	boot.srm.count = size;
+	boot.srm.flags = 0;
+
+	/* Check that the image is contiguous */
+	i = 1;
+	fat_end = (1 << fatbits) - 9;	/* 0xFF7, 0xFFF7 or whatever */
+	while ((j = get_fat_entry (fat, fatbits, start)) < fat_end) {
+		if (j != start + 1)
+			return fprintf (stderr,
+				"Unfortunately, %s is not contiguous\n",
+				argv[2]), 4;
+		start = j;
+		i++;
+	}
+	if ((size + clusize - 1) / clusize != i)
+		return fprintf (stderr, "Inconsistency: file size contradicts "
+				"with the number of clusters allocated\n"), 3;
+
+	/* Put the checksum and write the boot sector. */
+	checksum = 0;
+	for (i = 0; i < 63; i++)
+		checksum += boot.check.contents[i];
+	boot.check.checksum = checksum;
+
+	printf ("Writing SRM boot block: starting sector %u, block count %u\n",
+		(unsigned)boot.srm.start, (unsigned)boot.srm.count);
+
+	if (lseek (f, 0, SEEK_SET) == -1
+	 || write (f, &boot, sizeof boot) != sizeof boot)
+		return perror (argv[2]), 2;
+
+	close (f);
+	return 0;
+}
+
+struct OldDos_t old_dos[]={
+	{   40,  9,  1, 4, 1, 2, 0xfc },
+	{   40,  9,  2, 7, 2, 2, 0xfd },
+	{   40,  8,  1, 4, 1, 1, 0xfe },
+	{   40,  8,  2, 7, 2, 1, 0xff },
+	{   80,  9,  2, 7, 2, 3, 0xf9 },
+	{   80, 15,  2,14, 1, 7, 0xf9 },
+	{   80, 18,  2,14, 1, 9, 0xf0 },
+	{   80, 36,  2,15, 2, 9, 0xf0 },
+	{    1,  8,  1, 1, 1, 1, 0xf0 }
+};

+ 85 - 0
package/aboot/src/srmbootfat/srmbootfat.sgml

@@ -0,0 +1,85 @@
+<!DOCTYPE RefEntry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+<refentry id="srmbootfat">
+
+<refmeta>
+<refentrytitle>srmbootfat</refentrytitle>
+<manvolnum>1</manvolnum>
+<refmiscinfo>srmbootfat</refmiscinfo>
+</refmeta>
+
+<refnamediv>
+<refname>srmbootfat</refname>
+<refpurpose>
+Linux/Alpha SRM boot block composer
+</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv>
+ <cmdsynopsis>
+   <command>srmbootfat</command> 
+        <arg choice="plain">filesystem_image</arg>
+        <arg choice="plain">boot_file</arg>
+   </cmdsynopsis>
+</refsynopsisdiv>
+
+<!--  <refsect1><title>COPYRIGHT</title>
+<para>
+</para>
+</refsect1> -->
+
+<refsect1><title>DESCRIPTIONS</title>
+<para>
+<indexterm><primary>srmbootfat</primary></indexterm>
+This tool is a quick hack and is not supposed to exist in its present
+state for long.
+</para>
+
+<para>
+<application>Srmbootfat</application> finds <filename>boot_file</filename>
+in the root directory of the <acronym>FAT</acronym> file system stored in file
+<filename>filesystem_image</filename>
+and makes it bootable by writing the appropriate SRM boot block into the
+file system image file.  This will work only on unpartitioned disks (such as
+floppies), because otherwise the boot block would need to be written into the
+partition table, which is outside the file system.  However, a hard drive
+containing a FAT file system would most probably be partitioned using the PC
+partition table, which SRM cannot boot from anyway.
+</para>
+
+<para>
+The bootloader (<filename>boot_file</filename>)
+must be contiguous, i.e. occupy consecutive blocks.
+</para>
+</refsect1>
+
+<refsect1><title>ARGUMENTS</title>
+<para>
+<variablelist>
+<varlistentry><term><filename>filesystem_image</filename></term>
+<listitem><para>
+The name of the file containing a FAT file system image, e.g.
+<filename>/dev/fd0</filename>.
+</para></listitem></varlistentry>
+<varlistentry><term><filename>boot_file</filename></term>
+<listitem><para>
+The file name of the bootloader.
+</para></listitem></varlistentry>
+</variablelist>
+</refsect1>
+
+<!-- <refsect1><title>BUGS</title>
+<para>
+</para>
+</refsect1> -->
+
+<refsect1><title>AUTHOR</title>
+<para>
+Nikita Schmidt <email>cetus@snowball.ucd.ie</email>
+</para>
+</refsect1>
+<refsect1><title>SEE ALSO</title>
+<para>
+<application>aboot</application>(8), <application>mke2fs</application>(8), <application>e2writeboot</application>(8)
+</para>
+</refsect1>
+</refentry>

+ 101 - 0
package/aboot/src/srmbootfat/srmbootraw.c

@@ -0,0 +1,101 @@
+/*
+ *  SRMbootraw - SRM boot block composer for raw boot partitions.
+ *  Copyright (C) 1998 Nikita Schmidt  <cetus@snowball.ucd.ie>
+ *
+ *  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.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/types.h>
+
+/* We assume little endiannes and possibly other Alpha properties as well. */
+#ifndef __alpha__
+#error This stuff must be compiled for Alpha.
+#endif
+
+#define BUFSIZE	65536
+
+union bootsector {
+	struct {
+		unsigned char textlabel[64];
+		unsigned char disklabel[276];
+		unsigned char unused[140];
+		u_int64_t count, start, flags;
+		u_int64_t checksum;
+	} srm;
+	struct {
+		u_int64_t contents[63];
+		u_int64_t checksum;
+	} check;
+};
+
+
+int main (int argc, char *argv[])
+{
+	int device, image;
+	int i;
+	union bootsector boot;
+	char *buf;
+	unsigned long size;
+	ssize_t len;
+	u_int64_t checksum;
+
+	if (argc != 3)
+		return printf ("Usage:  srmbootraw <boot device> <boot image>\n"), 1;
+
+	if ((device = open (argv[1], O_RDWR)) < 0)
+		return perror (argv[1]), 2;
+	if ((image = open (argv[2], O_RDONLY)) < 0)
+		return perror (argv[2]), 2;
+
+	/* Read in the old bootsector */
+	if (read (device, &boot, sizeof boot) != sizeof boot)
+		return fprintf (stderr, "Can't read boot sector from %s\n", argv[1]), 2;
+
+	if (!(buf = malloc (BUFSIZE)))
+		return fprintf (stderr, "Can't allocate memory for %s\n", argv[2]), 2;
+
+	/* Copy image onto the device */
+	size = 0;
+	while ((len = read (image, buf, BUFSIZE)) > 0)
+	{
+		if (write (device, buf, len) != len)
+			return fprintf (stderr, "Can't write to %s\n", argv[1]), 2;
+		size += len;
+	}
+	close (image);
+	if (len == -1)
+		return perror (argv[2]), 2;
+
+	/* Fill in the bootstrap information */
+	boot.srm.start = 1;
+	boot.srm.count = (size + 511) / 512;	/* Convert to sectors */
+	boot.srm.flags = 0;
+
+	/* Put the checksum and write the boot sector. */
+	checksum = 0;
+	for (i = 0; i < 63; i++)
+		checksum += boot.check.contents[i];
+	boot.check.checksum = checksum;
+
+	printf ("Writing SRM boot block: starting sector %u, block count %u\n",
+		(unsigned)boot.srm.start, (unsigned)boot.srm.count);
+
+	if (lseek (device, 0, SEEK_SET) == -1
+	 || write (device, &boot, sizeof boot) != sizeof boot)
+		return perror (argv[2]), 2;
+
+	close (device);
+	return 0;
+}

+ 84 - 0
package/aboot/src/srmbootfat/srmbootraw.sgml

@@ -0,0 +1,84 @@
+<!DOCTYPE RefEntry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+<refentry id="srmbootraw">
+
+<refmeta>
+<refentrytitle>srmbootraw</refentrytitle>
+<manvolnum>8</manvolnum>
+<refmiscinfo>srmbootraw</refmiscinfo>
+</refmeta>
+
+<refnamediv>
+<refname>srmbootraw</refname>
+<refpurpose>
+Linux/Alpha SRM boot block composer
+</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv>
+ <cmdsynopsis>
+   <command>srmbootraw</command> 
+        <arg choice="plain">boot_device</arg>
+        <arg choice="plain">boot_file</arg>
+   </cmdsynopsis>
+</refsynopsisdiv>
+
+<!--  <refsect1><title>COPYRIGHT</title>
+<para>
+</para>
+</refsect1> -->
+
+<refsect1><title>DESCRIPTIONS</title>
+<para>
+<indexterm><primary>srmbootraw</primary></indexterm>
+This tool is a quick hack and is not supposed to exist in its present
+state for long.
+</para>
+
+<para>
+<application>Srmbootraw</application> writes the image from
+<filename>boot_file</filename>
+preceded by the appropriate SRM boot block into the first blocks of
+<filename>boot_device</filename>, preserving the disklabel.
+It is intended to be used when you have a small raw
+partition at the beginning of your hard drive, dedicated for the bootloader.
+If you don't, <filename>srmbootraw</filename>
+will silently render your file system(s) unusable.
+</para>
+</refsect1>
+
+<refsect1><title>ARGUMENTS</title>
+<para>
+<variablelist>
+<varlistentry><term><filename>boot_device</filename></term>
+<listitem><para>
+The device you intend to boot from, e.g. <filename>/dev/sda</filename>.
+It must have enough room
+at the beginning to hold the boot block and the bootloader.
+</para></listitem></varlistentry>
+<varlistentry><term><filename>boot_file</filename></term>
+<listitem><para>
+The file name of the bootloader.
+</para></listitem></varlistentry>
+</variablelist>
+</refsect1>
+
+<!-- <refsect1><title>BUGS</title>
+<para>
+</para>
+</refsect1> -->
+
+<refsect1><title>AUTHOR</title>
+<para>
+Nikita Schmidt <email>cetus@snowball.ucd.ie</email>
+</para>
+</refsect1>
+<refsect1><title>SEE ALSO</title>
+<para>
+<application>aboot</application>(8), 
+<application>mke2fs</application>(8),
+<application>swriteboot</application>(8),
+<application>e2writeboot</application>(8),
+<application>srmbootfat</application>(1)
+</para>
+</refsect1>
+</refentry>

+ 5 - 0
package/aboot/src/tools/.cvsignore

@@ -0,0 +1,5 @@
+abootconf
+e2writeboot
+elfencap
+isomarkboot
+objstrip

+ 22 - 0
package/aboot/src/tools/Makefile

@@ -0,0 +1,22 @@
+ifndef ($(CC))
+CC	= gcc
+endif
+override CFLAGS		= -g -O2 -Wall -I. -I../include $(CPPFLAGS)
+override LDFLAGS	= -g
+override PGMS		+= e2writeboot abootconf elfencap objstrip
+
+EXEC_PREFIX = /usr
+
+all:	$(PGMS)
+
+install:	$(PGMS)
+	install -c -o root -g root -m 755 $(PGMS) $(EXEC_PREFIX)/bin
+
+clean:
+	rm -f *~ *.o *.a core $(PGMS)
+
+isomarkboot:	isomarkboot.o ../lib/isolib.o
+e2writeboot:	e2writeboot.o e2lib.o bio.o
+
+e2writeboot.o:	e2lib.h
+e2lib.o: e2lib.h

+ 125 - 0
package/aboot/src/tools/abootconf.c

@@ -0,0 +1,125 @@
+/*
+ * abootconf.c
+ *
+ * This file is part of aboot, the SRM bootloader for Linux/Alpha
+ * Copyright (C) 1996 Linus Torvalds, David Mosberger, and Michael Schwingen.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <sys/fcntl.h>
+
+#include <config.h>
+
+
+const char * prog_name;
+
+int
+main (int argc, char ** argv)
+{
+	unsigned long sector[512 / sizeof(unsigned long)];
+	off_t aboot_pos;
+	size_t nbytes;
+	long part = -1;
+	int disk, i;
+
+	prog_name = argv[0];
+
+	if (argc != 2 && argc != 3) {
+		fprintf(stderr, "usage: %s device [partition]\n", prog_name);
+		exit(1);
+	}
+
+	if (argc > 2) {
+	    errno = 0;
+	    part = strtol(argv[2], 0, 10);
+	    if (errno == ERANGE) {
+		fprintf(stderr, "%s: bad partition number %s\n",
+			prog_name, argv[2]);
+		exit(1);
+	    }
+	}
+
+	disk = open(argv[1], part < 0 ? O_RDONLY : O_RDWR);
+	if (disk < 0) {
+		perror(argv[1]);
+		exit(1);
+	}
+
+	nbytes = read(disk, sector, sizeof(sector));
+	if (nbytes != sizeof(sector)) {
+		if ((long) nbytes < 0) {
+			perror("read");
+		} else {
+			fprintf(stderr, "%s: short read\n", prog_name);
+		}
+		exit(1);
+	}
+
+	aboot_pos = sector[61] * 512;
+
+	if (lseek(disk, aboot_pos, SEEK_SET) != aboot_pos) {
+		perror("lseek");
+		exit(1);
+	}
+
+	nbytes = read(disk, sector, sizeof(sector));
+	if (nbytes != sizeof(sector)) {
+		if ((long) nbytes < 0) {
+			perror("read");
+		} else {
+			fprintf(stderr, "%s: short read\n", prog_name);
+		}
+		exit(1);
+	}
+
+	for (i = 0; i < (int) (sizeof(sector)/sizeof(sector[0])); ++i) {
+		if (sector[i] == ABOOT_MAGIC)
+			break;
+	}
+	if (i >= (int) (sizeof(sector)/sizeof(sector[0]))) {
+		fprintf(stderr, "%s: could not find aboot on disk %s\n",
+			prog_name, argv[1]);
+		exit(1);
+	}
+
+	if (part < 0) {
+	    printf("aboot.conf partition currently set to %ld\n",
+		   sector[i + 1]);
+	    exit(0);
+	}
+
+	if (lseek(disk, aboot_pos, SEEK_SET) != aboot_pos) {
+		perror("lseek");
+		exit(1);
+	}
+
+	sector[i + 1] = atoi(argv[2]);
+
+	nbytes = write(disk, sector, sizeof(sector));
+	if (nbytes != sizeof(sector)) {
+		if ((long) nbytes < 0) {
+			perror("write");
+		} else {
+			fprintf(stderr, "%s: short write\n", prog_name);
+		}
+		exit(1);
+	}
+	return 0;
+}

+ 178 - 0
package/aboot/src/tools/bio.c

@@ -0,0 +1,178 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* Buffered I/O functions.  By cacheing the most recently used blocks,
+ * we can cut WAAY down on disk traffic...
+ */
+
+static int	bio_fd = -1;
+static int	bio_counter = 0;
+static int	bio_blocksize = 0;
+
+struct bio_buf {
+    int		blkno;
+    int		last_access;
+    int		dirty;
+    char *	data;
+};
+
+#define NBUFS	32
+struct bio_buf	buflist[NBUFS];
+
+/* initialize the buffer cache.  Blow away anything that may
+ * have been previously cached...
+ */
+void
+binit(int fd, int blocksize)
+{
+    int		i;
+
+    bio_fd = fd;
+    bio_blocksize = blocksize;
+
+    for(i = 0; i < NBUFS; i++) {
+	buflist[i].blkno = 0;
+	if(buflist[i].data) {
+	    free(buflist[i].data);
+	}
+	buflist[i].data = 0;
+	buflist[i].last_access = 0;
+	buflist[i].dirty = 0;
+    }
+}
+
+/* Flush out any dirty blocks */
+void
+bflush(void)
+{
+    int		i;
+
+    for(i = 0; i < NBUFS; i++) {
+	if(buflist[i].dirty) {
+#ifdef BIO_DEBUG
+	    printf("bflush: writing block %d\n", buflist[i].blkno);
+#endif
+	    lseek(bio_fd, buflist[i].blkno * bio_blocksize, 0);
+	    write(bio_fd, buflist[i].data, bio_blocksize);
+	    buflist[i].dirty = 0;
+	}
+    }
+}
+
+/* Read a block.  */
+void
+bread(int blkno, void * blkbuf)
+{
+    int		i;
+    int		lowcount;
+    int		lowcount_buf;
+
+    /* First, see if the block is already in memory... */
+    for(i = 0; i < NBUFS; i++) {
+	if(buflist[i].blkno == blkno) {
+	    /* Got it!  Bump the access count and return. */
+	    buflist[i].last_access = ++bio_counter;
+#ifdef BIO_DEBUG
+	    printf("bread: buffer hit on block %d\n", blkno);
+#endif
+	    memcpy(blkbuf, buflist[i].data, bio_blocksize);
+	    return;
+	}
+    }
+
+    /* Not in memory; need to find a buffer and read it in. */
+    lowcount = buflist[0].last_access;
+    lowcount_buf = 0;
+    for(i = 1; i < NBUFS; i++) {
+	if(buflist[i].last_access < lowcount) {
+	    lowcount = buflist[i].last_access;
+	    lowcount_buf = i;
+	}
+    }
+
+    /* If the buffer is dirty, we need to write it out... */
+    if(buflist[lowcount_buf].dirty) {
+#ifdef BIO_DEBUG
+	printf("bread: recycling dirty buffer %d for block %d\n", 
+			lowcount_buf, buflist[lowcount_buf].blkno);
+#endif
+	lseek(bio_fd, buflist[lowcount_buf].blkno * bio_blocksize, 0);
+	write(bio_fd, buflist[lowcount_buf].data, bio_blocksize);
+	buflist[lowcount_buf].dirty = 0;
+    }
+
+#ifdef BIO_DEBUG
+    printf("bread: Using buffer %d for block %d\n", lowcount_buf, blkno);
+#endif
+
+    buflist[lowcount_buf].blkno = blkno;
+    if(!buflist[lowcount_buf].data) {
+	buflist[lowcount_buf].data = (char *)malloc(bio_blocksize);
+    }
+    lseek(bio_fd, blkno * bio_blocksize, 0);
+    if(read(bio_fd,buflist[lowcount_buf].data,bio_blocksize)!=bio_blocksize) {
+	perror("bread: I/O error");
+    }
+
+    buflist[lowcount_buf].last_access = ++bio_counter;
+    memcpy(blkbuf, buflist[lowcount_buf].data, bio_blocksize);
+}
+
+
+/* Write a block */
+void
+bwrite(int blkno, void * blkbuf)
+{
+    int		i;
+    int		lowcount;
+    int		lowcount_buf;
+
+    /* First, see if the block is already in memory... */
+    for(i = 0; i < NBUFS; i++) {
+	if(buflist[i].blkno == blkno) {
+	    /* Got it!  Bump the access count and return. */
+#ifdef BIO_DEBUG
+	    printf("bwrite: buffer hit on block %d\n", blkno);
+#endif
+	    buflist[i].last_access = ++bio_counter;
+	    memcpy(buflist[i].data, blkbuf, bio_blocksize);
+	    buflist[i].dirty = 1;
+	    return;
+	}
+    }
+
+    /* Not in memory; need to find a buffer and stuff it. */
+    lowcount = buflist[0].last_access;
+    lowcount_buf = 0;
+    for(i = 1; i < NBUFS; i++) {
+	if(buflist[i].last_access < lowcount) {
+	    lowcount = buflist[i].last_access;
+	    lowcount_buf = i;
+	}
+    }
+
+    /* If the buffer is dirty, we need to write it out... */
+    if(buflist[lowcount_buf].dirty) {
+#ifdef BIO_DEBUG
+	printf("bwrite: recycling dirty buffer %d for block %d\n", 
+			lowcount_buf, buflist[lowcount_buf].blkno);
+#endif
+	lseek(bio_fd, buflist[lowcount_buf].blkno * bio_blocksize, 0);
+	write(bio_fd, buflist[lowcount_buf].data, bio_blocksize);
+	buflist[lowcount_buf].dirty = 0;
+    }
+
+#ifdef BIO_DEBUG
+    printf("bwrite: Using buffer %d for block %d\n", lowcount_buf, blkno);
+#endif
+
+    buflist[lowcount_buf].blkno = blkno;
+    if(!buflist[lowcount_buf].data) {
+	buflist[lowcount_buf].data = (char *)malloc(bio_blocksize);
+    }
+    buflist[lowcount_buf].last_access = ++bio_counter;
+    memcpy(buflist[lowcount_buf].data, blkbuf, bio_blocksize);
+    buflist[lowcount_buf].dirty = 1;
+}

+ 4 - 0
package/aboot/src/tools/bio.h

@@ -0,0 +1,4 @@
+extern void	binit (int fd, int blocksize);
+extern void	bflush (void);
+extern void	bread (int blkno, void * blkbuf);
+extern void	bwrite (int blkno, void * blkbuf);

+ 1473 - 0
package/aboot/src/tools/e2lib.c

@@ -0,0 +1,1473 @@
+/* This is a library of functions that allow user-level programs to
+ * read and manipulate ext2 file systems.  For convenience sake,
+ * this library maintains a lot of state information in static
+ * variables; therefore,  it's not reentrant.  We don't care for
+ * our applications 8-)
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <bio.h>
+#include <e2lib.h>
+
+
+#define		MAX_OPEN_FILES		8 
+
+int				fd = -1; 
+struct ext2_super_block		sb;
+struct ext2_group_desc		*gds;
+int				ngroups = 0;
+int				blocksize;	/* Block size of this fs */
+int				directlim;	/* Maximum direct blkno */
+int				ind1lim;	/* Maximum single-indir blkno */
+int				ind2lim;	/* Maximum double-indir blkno */
+int				ptrs_per_blk;	/* ptrs/indirect block */
+char				filename[256];
+int				readonly;	/* Is this FS read-only? */
+int				verbose = 0;
+int				big_endian = 0;
+
+static void	ext2_ifree(int ino);
+static void	ext2_free_indirect(int indirect_blkno, int level);
+
+
+struct inode_table_entry {
+	struct	ext2_inode	inode;
+	int			inumber;
+	int			free;
+	unsigned short		old_mode;
+} inode_table[MAX_OPEN_FILES];
+
+/* Utility functions to byte-swap 16 and 32 bit quantities... */
+
+unsigned short
+swap16 (unsigned short s)
+{
+    return((unsigned short)( ((s << 8) & 0xff00) | ((s >> 8) & 0x00ff)));
+}
+
+unsigned int
+swap32 (unsigned int i)
+{
+    return((unsigned int)(
+                ((i << 24) & 0xff000000) |
+                ((i << 8) & 0x00ff0000) |
+                ((i >> 8) & 0x0000ff00) |
+                ((i >> 24) & 0x000000ff)) );
+}
+
+void
+ext2_swap_sb (struct ext2_super_block *sb)
+{
+    sb->s_inodes_count = swap32(sb->s_inodes_count);
+    sb->s_blocks_count = swap32(sb->s_blocks_count);
+    sb->s_r_blocks_count = swap32(sb->s_r_blocks_count);
+    sb->s_free_blocks_count = swap32(sb->s_free_blocks_count);
+    sb->s_free_inodes_count = swap32(sb->s_free_inodes_count);
+    sb->s_first_data_block = swap32(sb->s_first_data_block);
+    sb->s_log_block_size = swap32(sb->s_log_block_size);
+    sb->s_log_frag_size = swap32(sb->s_log_frag_size);
+    sb->s_blocks_per_group = swap32(sb->s_blocks_per_group);
+    sb->s_frags_per_group = swap32(sb->s_frags_per_group);
+    sb->s_inodes_per_group = swap32(sb->s_inodes_per_group);
+    sb->s_mtime = swap32(sb->s_mtime);
+    sb->s_wtime = swap32(sb->s_wtime);
+    sb->s_mnt_count = swap16(sb->s_mnt_count);
+    sb->s_max_mnt_count = swap16(sb->s_max_mnt_count);
+    sb->s_magic = swap16(sb->s_magic);
+    sb->s_state = swap16(sb->s_state);
+    sb->s_errors = swap16(sb->s_errors);
+    sb->s_pad = swap16(sb->s_pad);
+    sb->s_lastcheck = swap32(sb->s_lastcheck);
+    sb->s_checkinterval = swap32(sb->s_checkinterval);
+}
+
+void
+ext2_swap_gd (struct ext2_group_desc *gd)
+{
+	gd->bg_block_bitmap = swap32(gd->bg_block_bitmap);
+	gd->bg_inode_bitmap = swap32(gd->bg_inode_bitmap);
+	gd->bg_inode_table = swap32(gd->bg_inode_table);
+	gd->bg_free_blocks_count = swap16(gd->bg_free_blocks_count);
+	gd->bg_free_inodes_count = swap16(gd->bg_free_inodes_count);
+	gd->bg_used_dirs_count = swap16(gd->bg_used_dirs_count);
+	gd->bg_pad = swap16(gd->bg_pad);
+}
+
+void
+ext2_swap_inode (struct ext2_inode *ip)
+{
+    int		i;
+
+    ip->i_mode = swap16(ip->i_mode);
+    ip->i_uid = swap16(ip->i_uid);
+    ip->i_size = swap32(ip->i_size);
+    ip->i_atime = swap32(ip->i_atime);
+    ip->i_ctime = swap32(ip->i_ctime);
+    ip->i_mtime = swap32(ip->i_mtime);
+    ip->i_dtime = swap32(ip->i_dtime);
+    ip->i_gid = swap16(ip->i_gid);
+    ip->i_links_count = swap16(ip->i_links_count);
+    ip->i_blocks = swap32(ip->i_blocks);
+    ip->i_flags = swap32(ip->i_flags);
+    ip->i_reserved1 = swap32(ip->i_reserved1);
+    for(i = 0; i < EXT2_N_BLOCKS; i++) {
+	ip->i_block[i] = swap32(ip->i_block[i]);
+    }
+    ip->i_version = swap32(ip->i_version);
+    ip->i_file_acl = swap32(ip->i_file_acl);
+    ip->i_dir_acl = swap32(ip->i_dir_acl);
+    ip->i_faddr = swap32(ip->i_faddr);
+    ip->i_pad1 = swap16(ip->i_pad1);
+}
+
+
+
+/* Initialize an ext2 filesystem; this is sort-of the same idea as
+ * "mounting" it.  Read in the relevant control structures and 
+ * make them available to the user.  Returns 0 if successful, -1 on
+ * failure.
+ */
+int
+ext2_init (char * name, int access)
+{
+    int		i;
+
+    /* Initialize the inode table */
+    for(i = 0; i < MAX_OPEN_FILES; i++) {
+	inode_table[i].free = 1;
+	inode_table[i].inumber = 0;
+    }
+
+    if((access != O_RDONLY) && (access != O_RDWR)) {
+	fprintf(stderr, 
+		"ext2_init: Access must be O_RDONLY or O_RDWR, not %d\n",
+		access);
+	return(-1);
+    }
+
+    /* Open the device/file */
+    fd = open(name, access);
+    if(fd < 0) {
+	perror(filename);
+	return(-1);
+    }
+
+    if(access == O_RDONLY) {
+	readonly = 1;
+    }
+
+    /* Read in the first superblock */
+    lseek(fd, EXT2_MIN_BLOCK_SIZE, SEEK_SET);
+    if(read(fd, &sb, sizeof(sb)) != sizeof(sb)) {
+        perror("ext2 sb read");
+	close(fd);
+	return(-1);
+    }
+
+    if((sb.s_magic != EXT2_SUPER_MAGIC) && (sb.s_magic != EXT2_SUPER_BIGMAGIC)) {
+	fprintf(stderr, "ext2 bad magic 0x%x\n", sb.s_magic);
+	close(fd);
+	return(-1);
+    }
+
+    if(sb.s_magic == EXT2_SUPER_BIGMAGIC) {
+	big_endian = 1;
+
+	/* Byte-swap the fields in the superblock... */
+	ext2_swap_sb(&sb);
+    }
+
+    if(sb.s_first_data_block != 1) {
+	fprintf(stderr, 
+	    "Brain-damaged utils can't deal with a filesystem\nwhere s_first_data_block != 1.\nRe-initialize the filesystem\n");
+	close(fd);
+	return(-1);
+    }
+
+    ngroups = (sb.s_blocks_count+sb.s_blocks_per_group-1)/sb.s_blocks_per_group;
+    gds = (struct ext2_group_desc *)
+	      malloc((size_t)(ngroups * sizeof(struct ext2_group_desc)));
+
+    /* Read in the group descriptors (immediately follows superblock) */
+    if ((size_t) read(fd, gds, ngroups * sizeof(struct ext2_group_desc))
+	!= (ngroups * sizeof(struct ext2_group_desc)))
+    {
+	perror("ext2_init: group desc read error");
+	return(-1);
+    }
+
+    if(big_endian) {
+	for(i = 0; i < ngroups; i++) {
+	    ext2_swap_gd(&(gds[i]));
+	}
+    }
+
+    strcpy(filename, name);
+
+    /* Calculate direct/indirect block limits for this file system
+     * (blocksize dependent)
+     */
+    blocksize = EXT2_BLOCK_SIZE(&sb);
+    directlim = EXT2_NDIR_BLOCKS - 1;
+    ptrs_per_blk = blocksize/sizeof(unsigned int);
+    ind1lim = ptrs_per_blk + directlim;
+    ind2lim = (ptrs_per_blk * ptrs_per_blk) + directlim;
+
+    if(getenv("EXT2_VERBOSE")) {
+	verbose = 1;
+    }
+
+    binit(fd, blocksize);
+
+    if(verbose) {
+	printf("Initialized filesystem %s\n", filename);
+	printf("  %d blocks (%dKb), %d free (%dKb)\n", 
+		sb.s_blocks_count, (sb.s_blocks_count * blocksize)/1024,
+		sb.s_free_blocks_count, 
+		(sb.s_free_blocks_count * blocksize)/1024);
+	printf("  %d inodes,  %d free\n", 
+		sb.s_inodes_count, sb.s_free_inodes_count);
+	printf("  %d groups, %d blocks/group\n", 
+			ngroups, sb.s_blocks_per_group);
+    }
+
+    return(0);
+}
+
+int
+ext2_blocksize (void)
+{
+    return blocksize;
+}
+
+int
+ext2_total_blocks (void)
+{
+    return sb.s_blocks_count;
+}
+
+int
+ext2_free_blocks (void)
+{
+    return sb.s_free_blocks_count;
+}
+
+int
+ext2_total_inodes (void)
+{
+    return sb.s_inodes_count;
+}
+
+int
+ext2_free_inodes (void)
+{
+    return sb.s_free_inodes_count;
+}
+
+/* Call this when we're all done with the file system.  This will write
+ * back any superblock and group changes to the file system.
+ */
+void
+ext2_close (void)
+{
+    int		i;
+    int		errors = 0;
+    int		blocks_per_group = sb.s_blocks_per_group;
+
+    if(!readonly) {
+
+	if(big_endian) {
+	    ext2_swap_sb(&sb);
+	    for(i = 0; i < ngroups; i++) {
+		ext2_swap_gd(&(gds[i]));
+	    }
+	}
+
+	for(i = 0; i < ngroups; i++) {
+	    lseek(fd, ((i*blocks_per_group)+1)*blocksize, SEEK_SET);
+	    if(write(fd, &sb, sizeof(sb)) != sizeof(sb)) {
+		perror("sb write");
+		errors = 1;
+	    }
+
+	    if ((size_t) write(fd, gds, ngroups*sizeof(struct ext2_group_desc))
+		!= ngroups*sizeof(struct ext2_group_desc))
+	    {
+		perror("gds write");
+		errors = 1;
+	    }
+
+	    bflush();
+	}
+    }
+
+    close(fd);
+    if(errors) {
+	fprintf(stderr, "Errors encountered while updating %s\n", filename);
+	fprintf(stderr, "e2fsck is STRONGLY recommended!\n");
+    }
+}
+
+	
+
+/* Read the specified inode from the disk and return it to the user.
+ * Returns NULL if the inode can't be read...
+ */
+struct ext2_inode *
+ext2_iget (int ino)
+{
+    int				i;
+    struct ext2_inode *		ip = NULL;
+    struct inode_table_entry *	itp = NULL;
+    int				group;
+    int				blkoffset;
+    int				byteoffset;
+    char                        inobuf[EXT2_MAX_BLOCK_SIZE];
+
+    for(i = 0; i < MAX_OPEN_FILES; i++) {
+	if(inode_table[i].free) {
+	    itp = &(inode_table[i]);
+	    ip = &(itp->inode);
+	    break;
+	}
+    }
+    if(!ip) {
+	fprintf(stderr, "ext2_iget: no free inodes\n");
+	return(NULL);
+    }
+
+    group = ino / sb.s_inodes_per_group;
+    blkoffset = (gds[group].bg_inode_table * blocksize);
+    byteoffset = ((ino-1) % sb.s_inodes_per_group) * sizeof(struct ext2_inode);
+    blkoffset += ((byteoffset / blocksize) * blocksize);
+    byteoffset = (byteoffset % blocksize);
+    bread(blkoffset/blocksize, inobuf);
+
+    memcpy(ip, &(inobuf[byteoffset]), sizeof(struct ext2_inode));
+
+    if(big_endian) {
+	ext2_swap_inode(ip);
+    }
+
+    /* Yes, this is ugly, but it makes iput SOOO much easier 8-) */
+    itp->free = 0;
+    itp->inumber = ino;
+    itp->old_mode = ip->i_mode;
+
+    return(ip);
+}
+
+/* Put the specified inode back on the disk where it came from. */
+void
+ext2_iput (struct ext2_inode *ip)
+{
+    int				group;
+    int				blkoffset;
+    int				byteoffset;
+    int				ino;
+    struct inode_table_entry 	*itp;
+    char                        inobuf[EXT2_MAX_BLOCK_SIZE];
+    int				inode_mode;
+
+    itp = (struct inode_table_entry *)ip;
+    ino = itp->inumber;
+
+    if(ip->i_links_count == 0) {
+	ext2_ifree(itp->inumber);
+    }
+
+    itp->inumber = 0;
+
+    if(!readonly) {
+	group = ino / sb.s_inodes_per_group;
+	blkoffset = (gds[group].bg_inode_table * blocksize);
+	byteoffset = ((ino-1) % sb.s_inodes_per_group) * sizeof(struct ext2_inode);
+	blkoffset += (byteoffset / blocksize) * blocksize;
+	byteoffset = byteoffset % blocksize;
+
+	inode_mode = ip->i_mode;
+	bread(blkoffset/blocksize, inobuf);
+	if(big_endian) {
+	    ext2_swap_inode(ip);
+	}
+	memcpy(&(inobuf[byteoffset]), ip, sizeof(struct ext2_inode));
+	bwrite(blkoffset/blocksize, inobuf);
+
+	if(S_ISDIR(itp->old_mode) && !S_ISDIR(inode_mode)) {
+	    /* We deleted a directory */
+	    gds[group].bg_used_dirs_count--;
+	}
+	if(!S_ISDIR(itp->old_mode) && S_ISDIR(inode_mode)) {
+	    /* We created a directory */
+	    gds[group].bg_used_dirs_count++;
+	}
+    }
+
+    itp->free = 1;
+}
+
+#define BITS_PER_LONG	(8*sizeof(int))
+
+static int
+find_first_zero_bit (unsigned int * addr, unsigned size)
+{
+	unsigned lwsize;
+        unsigned int        *ap = (unsigned int *)addr;
+        unsigned int        mask;
+        unsigned int        longword, bit;
+	unsigned int	    lwval;
+
+	if (!size)
+		return 0;
+
+	/* Convert "size" to a whole number of longwords... */
+	lwsize = (size + BITS_PER_LONG - 1) >> 5;
+	for (longword = 0; longword < lwsize; longword++, ap++) {
+	    if(*ap != 0xffffffff) {
+		lwval = big_endian ? swap32(*ap) : *ap;
+
+		for (bit = 0, mask = 1; bit < BITS_PER_LONG; bit++, mask <<= 1)
+		{
+		    if ((lwval & mask) == 0) {
+			return (longword*BITS_PER_LONG) + bit;
+		    }
+		}
+	    }
+	}
+	return size;
+
+}
+
+static void
+set_bit (unsigned int *addr, int bitno)
+{
+    if(big_endian) {
+	int	lwval;
+	lwval = swap32(addr[bitno/BITS_PER_LONG]);
+	lwval |= (1 << (bitno % BITS_PER_LONG));
+	addr[bitno/BITS_PER_LONG] = swap32(lwval);
+    }
+    else {
+        addr[bitno / BITS_PER_LONG] |= (1 << (bitno % BITS_PER_LONG));
+    }
+}
+
+static void
+clear_bit (unsigned int *addr, int bitno)
+{
+    if(big_endian) {
+	int	lwval;
+	lwval = swap32(addr[bitno/BITS_PER_LONG]);
+	lwval &= ~((unsigned int)(1 << (bitno % BITS_PER_LONG)));
+	addr[bitno/BITS_PER_LONG] = swap32(lwval);
+    }
+    else {
+        addr[bitno / BITS_PER_LONG] &= 
+			~((unsigned int)(1 << (bitno % BITS_PER_LONG)));
+    }
+}
+
+
+/* Allocate a block from the file system.  Brain-damaged implementation;
+ * doesn't even TRY to do load-balancing among groups... just grabs the
+ * first block it can find...
+ */
+int
+ext2_balloc (void)
+{
+    unsigned int blk, blockmap[256];
+    int i;
+
+    if(readonly) {
+	fprintf(stderr, "ext2_balloc: readonly filesystem\n");
+	return(0);
+    }
+
+    for(i = 0; i < ngroups; i++) {
+	if(gds[i].bg_free_blocks_count > 0) {
+	    bread(gds[i].bg_block_bitmap, blockmap);
+	    blk = find_first_zero_bit(blockmap, sb.s_blocks_per_group);
+	    if (blk == 0 || blk == sb.s_blocks_per_group) {
+		fprintf(stderr, 
+			"group %d has %d blocks free but none in bitmap?\n",
+			i, gds[i].bg_free_blocks_count);
+		continue;
+	    }
+	    set_bit(blockmap, blk);
+	    bwrite(gds[i].bg_block_bitmap, blockmap);
+	    gds[i].bg_free_blocks_count--;
+	    sb.s_free_blocks_count--;
+	    blk = blk + (i*sb.s_blocks_per_group)+1;
+
+	    if(blk == 0) {
+		fprintf(stderr, "ext2_balloc: blk == 0?\n");
+	    }
+	    return(blk);
+	}
+    }
+
+    if(verbose) {
+	printf("ext2_balloc: can't find a free block\n");
+    }
+    return(0);
+}
+
+/* Deallocate a block */
+void
+ext2_bfree (int blk)
+{
+    int		i;
+    unsigned int	blockmap[256];
+
+    /* Find which group this block is in */
+    i = (blk-1) / sb.s_blocks_per_group;
+
+    /* Read the block map */
+    bread(gds[i].bg_block_bitmap, blockmap);
+
+    /* Clear the appropriate bit */
+    clear_bit(blockmap, (blk-1) % sb.s_blocks_per_group);
+
+    /* Write the block map back out */
+    bwrite(gds[i].bg_block_bitmap, blockmap);
+
+    /* Update free block counts. */
+    gds[i].bg_free_blocks_count++;
+    sb.s_free_blocks_count++;
+
+}
+
+/* Allocate a contiguous range of blocks.  This is used ONLY for
+ * initializing the bootstrapper.  It uses a simple-minded algorithm
+ * that works best on a clean or nearly clean file system...  we
+ * chunk through the bitmap a longword at a time.  Only if the whole
+ * longword indicates free blocks do we use it.  On a 32-bit system,
+ * this means we allocate blocks only in units of 32.
+ */
+int
+ext2_contiguous_balloc (int nblocks)
+{
+    int		i, j;
+    int		firstlong, lastlong;
+    int		longs_needed;
+    int		longs_per_group;
+    int		blk;
+    unsigned int	blockmap[256];
+
+    if(readonly) {
+	fprintf(stderr, "ext2_contiguous_balloc: readonly filesystem\n");
+	return(0);
+    }
+
+    /* Compute how many longwords we need to fulfill this request */
+    longs_needed = (nblocks + BITS_PER_LONG - 1) / BITS_PER_LONG;
+    longs_per_group = sb.s_blocks_per_group/BITS_PER_LONG;
+
+    for(i = 0; i < ngroups; i++) {
+	/* Don't even bother if this group doesn't have enough blocks! */
+	if(gds[i].bg_free_blocks_count >= nblocks) {
+
+	    /* Get the block map. */
+	    bread(gds[i].bg_block_bitmap, blockmap);
+
+	    /* Find a run of blocks */
+	    firstlong = 0;
+
+	    do {
+	        for(; firstlong < longs_per_group; firstlong++) {
+		    if(blockmap[firstlong] == 0) break;
+		}
+
+	        if(firstlong == longs_per_group) {
+		    /* No such thing in this group; try another! */
+		    break;
+	        }
+
+	        for(lastlong = firstlong; lastlong < longs_per_group; 
+							lastlong++) {
+		    if(blockmap[lastlong] != 0) break;
+	        }
+
+		if((lastlong-firstlong) < longs_needed) {
+		    firstlong = lastlong;
+		}
+	    } while((lastlong-firstlong) < longs_needed);
+
+	    /* If we got all the way through the block map, 
+	     * try another group.
+	     */
+	    if(firstlong == longs_per_group) {
+		continue;
+	    }
+
+	    /* If we get here, then we know that we have a run
+	     * that will fit our allocation.  Allocate the *actual*
+	     * blocks that we need!
+	     */
+	    blk = firstlong * BITS_PER_LONG;
+	    for(j = 0; j < nblocks; j++) {
+		set_bit(blockmap, blk+j);
+	    }
+	  
+	    bwrite(gds[i].bg_block_bitmap, blockmap);
+	    gds[i].bg_free_blocks_count -= nblocks;
+	    sb.s_free_blocks_count -= nblocks;
+	    blk = blk + (i*sb.s_blocks_per_group)+1;
+
+	    if(verbose) {
+		printf("ext2_contiguous_balloc: allocated %d blks @%d\n",
+			nblocks, blk);
+	    }
+	    return(blk);
+	}
+    }
+
+    if(verbose) {
+	printf("ext2_contiguous_balloc: can't find %d contiguous free blocks\n", nblocks);
+    }
+    return(0);
+}
+    
+
+/* Pre-allocate contiguous blocks to the specified inode.  Note that the 
+ * DATA blocks must be contiguous; indirect blocks can come from anywhere.
+ * This is for the benefit of the bootstrap loader.
+ * If successful, this routine returns the block number of the first 
+ * data block of the file.  Otherwise, it returns -1.
+ */
+int
+ext2_fill_contiguous (struct ext2_inode * ip, int nblocks)
+{
+    int		iblkno = 0;
+    int		firstblock;
+    int		i;
+    unsigned int *lp = NULL;
+    char	blkbuf[EXT2_MAX_BLOCK_SIZE];
+
+    /* For simplicity's sake, we only allow single indirection
+     * here.  We shouldn't need more than this anyway!
+     */
+    if(nblocks > ind1lim) {
+	fprintf(stderr, 
+	  "ext2_fill_contiguous: file size too big (%d); cannot exceed %d\n",
+	  nblocks, ind1lim);
+	return(-1);
+    }
+
+    /* First, try to allocate the data blocks */
+    firstblock = ext2_contiguous_balloc(nblocks);
+
+    if(firstblock == 0) {
+	fprintf(stderr, 
+          "ext2_fill_contiguous: Cannot allocate %d contiguous blocks\n", nblocks);
+	return(-1);
+    }
+
+    ip->i_blocks = nblocks * (blocksize/512);
+
+    /* If we need the indirect block, then allocate it now. */
+    if(nblocks > directlim) {
+        iblkno = ext2_balloc();
+	if(iblkno == 0) {
+	    /* Should rarely happen! */
+	    fprintf(stderr,
+		"ext2_fill_contiguous: cannot allocate indirect block\n");
+	    for(i = 0; i < nblocks; i++) {
+		ext2_bfree(i);
+	    }
+	    return(-1);
+	}
+	ip->i_blocks += (blocksize/512);
+        /* Point to indirect block buffer, in case we need it! */
+        lp = (unsigned int *)blkbuf;
+
+	for(i = 0; i < ptrs_per_blk; i++) {
+	    lp[i] = 0;
+	}
+
+	ip->i_block[EXT2_IND_BLOCK] = iblkno;
+    }
+
+    /* All set... let's roll! */
+    ip->i_size = nblocks * blocksize;
+
+    for(i = 0; i < nblocks; i++) {
+	if(i < EXT2_NDIR_BLOCKS) {
+	    ip->i_block[i] = firstblock+i;
+	}
+	else {
+	    *lp++ = big_endian ? swap32(firstblock+i) : firstblock+i;
+	}
+    }
+
+    /* Write back the indirect block if necessary... */
+    if(iblkno) {
+	bwrite(iblkno, blkbuf);
+    }
+
+    return(firstblock);
+}
+
+/* Write out a boot block for this file system.  The caller
+ * should have instantiated the block.
+ */
+void
+ext2_write_bootblock (char *bb)
+{
+    bwrite(0, bb);
+}
+
+
+/* Allocate an inode from the file system.  Brain-damaged implementation;
+ * doesn't even TRY to do load-balancing among groups... just grabs the
+ * first inode it can find...
+ */
+int
+ext2_ialloc (void)
+{
+    unsigned int inodemap[256];
+    int i, ino;
+
+    if(readonly) {
+	return(0);
+    }
+    for(i = 0; i < ngroups; i++) {
+	if(gds[i].bg_free_inodes_count > 4) {
+	    /* leave a few inodes in each group for slop... */
+	    bread(gds[i].bg_inode_bitmap, inodemap);
+
+	    ino = find_first_zero_bit(inodemap, sb.s_inodes_per_group);
+	    if (ino == 0 || (unsigned) ino == sb.s_inodes_per_group) {
+		fprintf(stderr, 
+			"group %d has %d inodes free but none in bitmap?\n",
+			i, gds[i].bg_free_inodes_count);
+		continue;
+	    }
+	    set_bit(inodemap, ino);
+	    bwrite(gds[i].bg_inode_bitmap, inodemap);
+	    gds[i].bg_free_inodes_count--;
+	    sb.s_free_inodes_count--;
+	    ino = ino + (i*sb.s_inodes_per_group) + 1;
+	    return ino;
+	}
+    }
+    return 0;
+}
+
+/* Deallocate an inode */
+static void
+ext2_ifree (int ino)
+{
+    int		i;
+    unsigned int	inodemap[256];
+
+    /* Find which group this inode is in */
+    i = (ino-1) / sb.s_inodes_per_group;
+
+    /* Read the inode map */
+    bread(gds[i].bg_inode_bitmap, inodemap);
+
+    /* Clear the appropriate bit */
+    clear_bit(inodemap, (ino-1) % sb.s_inodes_per_group);
+
+    /* Write the inode map back out */
+    bwrite(gds[i].bg_inode_bitmap, inodemap);
+
+    /* Update free inode counts. */
+    gds[i].bg_free_inodes_count++;
+    sb.s_free_inodes_count++;
+}
+
+/* Map a block offset into a file into an absolute block number.
+ * (traverse the indirect blocks if necessary).  Note: Double-indirect
+ * blocks allow us to map over 64Mb on a 1k file system.  Therefore, for
+ * our purposes, we will NOT bother with triple indirect blocks.
+ *
+ * The "allocate" argument is set if we want to *allocate* a block
+ * and we don't already have one allocated.
+ */
+int
+ext2_blkno (struct ext2_inode *ip, int blkoff, int allocate)
+{
+    unsigned int	*lp;
+    int			blkno;
+    int			iblkno;
+    int			diblkno;
+    char		blkbuf[EXT2_MAX_BLOCK_SIZE];
+
+    if(allocate && readonly) {
+	fprintf(stderr, "ext2_blkno: Cannot allocate on a readonly file system!\n");
+	return(0);
+    }
+
+    lp = (unsigned int *)blkbuf;
+
+    /* If it's a direct block, it's easy! */
+    if(blkoff <= directlim) {
+	if((ip->i_block[blkoff] == 0) && allocate) {
+	    ip->i_block[blkoff] = ext2_balloc();
+	    if(verbose) {
+		printf("Allocated data block %d\n", ip->i_block[blkoff]);
+	    }
+	    ip->i_blocks += (blocksize / 512);
+	}
+	return(ip->i_block[blkoff]);
+    }
+
+    /* Is it a single-indirect? */
+    if(blkoff <= ind1lim) {
+	iblkno = ip->i_block[EXT2_IND_BLOCK];
+	if((iblkno == 0) && allocate) {
+	    /* No indirect block and we need one, so we allocate
+	     * one, zero it, and write it out.
+	     */
+	    iblkno = ext2_balloc();
+	    if(iblkno == 0) {
+		return(0);
+	    }
+	    ip->i_block[EXT2_IND_BLOCK] = iblkno;
+	    if(verbose) {
+		printf("Allocated indirect block %d\n", iblkno);
+	    }
+	    ip->i_blocks += (blocksize / 512);
+	    memset(blkbuf, 0, blocksize);
+	    bwrite(iblkno, blkbuf);
+	}
+
+	if(iblkno == 0) {
+	    return(0);
+	}
+
+	/* Read the indirect block */
+	bread(iblkno, blkbuf);
+	
+	if(big_endian) {
+	    blkno = swap32(lp[blkoff-(directlim+1)]);
+	}
+	else {
+	    blkno = lp[blkoff-(directlim+1)];
+	}
+	if((blkno == 0) && allocate) {
+	    /* No block allocated but we need one. */
+	    if(big_endian) {
+		blkno = ext2_balloc();
+		lp[blkoff-(directlim+1)] = swap32(blkno);
+	    }
+	    else {
+	        blkno = lp[blkoff-(directlim+1)] = ext2_balloc();
+	    }
+	    if(blkno == 0) {
+		return(0);
+	    }
+	    ip->i_blocks += (blocksize / 512);
+	    if(verbose) {
+		printf("Allocated data block %d\n", blkno);
+	    }
+	    bwrite(iblkno, blkbuf);
+	}
+	return(blkno);
+    }
+
+    /* Is it a double-indirect? */
+    if(blkoff <= ind2lim) {
+	/* Find the double-indirect block */
+	diblkno = ip->i_block[EXT2_DIND_BLOCK];
+	if((diblkno == 0) && allocate) {
+	    /* No double-indirect block and we need one.  Allocate one,
+	     * fill it with zeros, and write it out.
+	     */
+	    diblkno = ext2_balloc();
+	    if(diblkno == 0) {
+		return(0);
+	    }
+	    ip->i_blocks += (blocksize / 512);
+	    if(verbose) {
+		printf("Allocated double-indirect block %d\n", diblkno);
+	    }
+	    memset(blkbuf, 0, blocksize);
+	    bwrite(diblkno, blkbuf);
+	    ip->i_block[EXT2_DIND_BLOCK] = diblkno;
+	}
+
+	if(diblkno == 0) {
+	    return(0);
+	}
+
+	/* Read in the double-indirect block */
+	bread(diblkno, blkbuf);
+
+	/* Find the single-indirect block pointer ... */
+	iblkno = lp[(blkoff - (ind1lim+1)) / ptrs_per_blk];
+	if(big_endian) {
+		iblkno = swap32(iblkno);
+	}
+
+	if((iblkno == 0) && allocate) {
+	    /* No indirect block and we need one, so we allocate
+	     * one, zero it, and write it out.
+	     */
+	    iblkno = ext2_balloc();
+	    if(iblkno == 0) {
+		return(0);
+	    }
+	    ip->i_blocks += (blocksize / 512);
+	    if(verbose) {
+		printf("Allocated single-indirect block %d\n", iblkno);
+	    }
+	    lp[(blkoff-(ind1lim+1)) / ptrs_per_blk] = big_endian ? swap32(iblkno) :  iblkno;
+	    bwrite(diblkno, blkbuf);
+
+	    memset(blkbuf, 0, blocksize);
+	    bwrite(iblkno, blkbuf);
+	}
+
+	if(iblkno == 0) {
+	    return(0);
+	}
+	    
+
+	/* Read the indirect block */
+	bread(iblkno, blkbuf);
+	
+	/* Find the block itself. */
+	blkno = lp[(blkoff-(ind1lim+1)) % ptrs_per_blk];
+	if(big_endian) {
+		blkno = swap32(blkno);
+	}
+	if((blkno == 0) && allocate) {
+	    /* No block allocated but we need one. */
+	    if(big_endian) {
+		blkno = ext2_balloc();
+		lp[(blkoff-(ind1lim+1)) % ptrs_per_blk] = swap32(blkno);
+	    }
+	    else {
+	        blkno = lp[(blkoff-(ind1lim+1)) % ptrs_per_blk] = ext2_balloc();
+	    }
+	    ip->i_blocks += (blocksize / 512);
+	    if(verbose) {
+		printf("Allocated data block %d\n", blkno);
+	    }
+	    bwrite(iblkno, blkbuf);
+	}
+	return(blkno);
+    }
+
+    if(blkoff > ind2lim) {
+	fprintf(stderr, "ext2_blkno: block number too large: %d\n", blkoff);
+	return(0);
+    }
+    return 0;
+}
+
+
+
+
+/* Read block number "blkno" from the specified file */
+void
+ext2_bread (struct ext2_inode *ip, int blkno, char * buffer)
+{
+    int		dev_blkno;
+
+    dev_blkno = ext2_blkno(ip, blkno, 0);
+    if(dev_blkno == 0) {
+	/* This is a "hole" */
+	memset(buffer, 0, blocksize);
+    }
+    else {
+	/* Read it for real */
+	bread(dev_blkno, buffer);
+    }
+}
+
+/* Write block number "blkno" to the specified file */
+void
+ext2_bwrite (struct ext2_inode *ip, int blkno, char * buffer)
+{
+    int		dev_blkno;
+
+    if(readonly) {
+	fprintf(stderr, "ext2_bwrite: Cannot write to a readonly filesystem!\n");
+	return;
+    }
+
+    dev_blkno = ext2_blkno(ip, blkno, 1);
+    if(dev_blkno == 0) {
+	fprintf(stderr, "%s: No space on ext2 device\n", filename);
+    }
+    else {
+	/* Write it for real */
+	bwrite(dev_blkno, buffer);
+    }
+}
+
+/* More convenient forms of ext2_bread/ext2_bwrite.  These allow arbitrary
+ * data alignment and buffer sizes...
+ */
+int
+ext2_seek_and_read (struct ext2_inode *ip, int offset, char *buffer, int count)
+{
+    int		blkno;
+    int		blkoffset;
+    int		bytesleft;
+    int		nread;
+    int		iosize;
+    char	*bufptr;
+    char	blkbuf[EXT2_MAX_BLOCK_SIZE];
+
+    bufptr = buffer;
+    bytesleft = count;
+    nread = 0;
+    blkno = offset / blocksize;
+    blkoffset = offset % blocksize;
+
+    while(bytesleft > 0) {
+	iosize = ((blocksize-blkoffset) > bytesleft) ? 
+				bytesleft : (blocksize-blkoffset);
+	if((blkoffset == 0) && (iosize == blocksize)) {
+	    ext2_bread(ip, blkno, bufptr);
+	}
+	else {
+	    ext2_bread(ip, blkno, blkbuf);
+	    memcpy(bufptr, blkbuf+blkoffset, iosize);
+	}
+   	bytesleft -= iosize;
+	bufptr += iosize;
+	nread += iosize;
+	blkno++;
+	blkoffset = 0;
+    }
+    return(nread);
+}
+
+int
+ext2_seek_and_write (struct ext2_inode *ip, int offset, char *buffer, int count)
+{
+    int		blkno;
+    int		blkoffset;
+    int		bytesleft;
+    int		nwritten;
+    int		iosize;
+    char	*bufptr;
+    char	blkbuf[EXT2_MAX_BLOCK_SIZE];
+
+    bufptr = buffer;
+    bytesleft = count;
+    nwritten = 0;
+    blkno = offset / blocksize;
+    blkoffset = offset % blocksize;
+
+    while(bytesleft > 0) {
+	iosize = ((blocksize-blkoffset) > bytesleft) ? 
+				bytesleft : (blocksize-blkoffset);
+	if((blkoffset == 0) && (iosize == blocksize)) {
+	    ext2_bwrite(ip, blkno, bufptr);
+	}
+	else {
+	    ext2_bread(ip, blkno, blkbuf);
+	    memcpy(blkbuf+blkoffset, bufptr, iosize);
+	    ext2_bwrite(ip, blkno, blkbuf);
+	}
+   	bytesleft -= iosize;
+	bufptr += iosize;
+	nwritten += iosize;
+	blkno++;
+	blkoffset = 0;
+    }
+    return(nwritten);
+}
+
+struct ext2_inode *
+ext2_namei (char *name)
+{
+    char 	namebuf[256];
+    char 	dirbuf[EXT2_MAX_BLOCK_SIZE];
+    char *	component;
+    struct ext2_inode *		dir_inode;
+    struct ext2_dir_entry *dp;
+    int		next_ino;
+
+    /* Squirrel away a copy of "namebuf" that we can molest */
+    strcpy(namebuf, name);
+
+    /* Start at the root... */
+    dir_inode = ext2_iget(EXT2_ROOT_INO);
+
+    component = strtok(namebuf, "/");
+    while(component) {
+	unsigned diroffset;
+	int component_length, blockoffset;
+
+	/* Search for the specified component in the current directory
+	 * inode.
+	 */
+
+	next_ino = -1;
+
+	component_length = strlen(component);
+	diroffset = 0;
+	while (diroffset < dir_inode->i_size) {
+	    blockoffset = 0;
+	    ext2_bread(dir_inode, diroffset / blocksize, dirbuf);
+	    while (blockoffset < blocksize) {
+		int namelen;
+
+	        dp = (struct ext2_dir_entry *)(dirbuf+blockoffset);
+		namelen = big_endian ? swap16(dp->name_len) : dp->name_len;
+		if((namelen == component_length) &&
+		   (strncmp(component, dp->name, component_length) == 0)) {
+			/* Found it! */
+			next_ino = big_endian ? swap32(dp->inode) : dp->inode;
+			break;
+		}
+		/* Go to next entry in this block */
+		blockoffset += (big_endian ? swap16(dp->rec_len) : dp->rec_len);
+	    }
+	    if(next_ino >= 0) {
+		break;
+	    }
+
+	    /* If we got here, then we didn't find the component.
+	     * Try the next block in this directory...
+	     */
+	    diroffset += blocksize;
+	}
+
+	/* At this point, we're done with this directory whether
+	 * we've succeeded or failed...
+	 */
+	ext2_iput(dir_inode);
+
+	/* If next_ino is negative, then we've failed (gone all the
+	 * way through without finding anything)
+	 */
+	if(next_ino < 0) {
+	    return(NULL);
+	}
+
+	/* Otherwise, we can get this inode and find the next
+	 * component string...
+	 */
+	dir_inode = ext2_iget(next_ino);
+	
+	component = strtok(NULL, "/");
+    }
+
+    /* If we get here, then we got through all the components.
+     * Whatever we got must match up with the last one.
+     */
+    return(dir_inode);
+}
+
+/* Create a new entry in the specified directory with the specified
+ * name/inumber pair.  This routine ASSUMES that the specified 
+ * entry does not already exist!  Therefore, we MUST use namei
+ * first to try and find the entry...
+ */
+
+void
+ext2_mknod (struct ext2_inode *dip, char * name, int ino)
+{
+    unsigned diroffset;
+    int blockoffset, namelen, new_reclen;
+    struct ext2_dir_entry *dp;
+    struct ext2_dir_entry *entry_dp;
+    char dirbuf[EXT2_MAX_BLOCK_SIZE];
+    int dp_inode, dp_reclen, dp_namelen;
+
+    namelen = strlen(name);
+
+    /* Look for an empty directory entry that can hold this
+     * item.
+     */
+    diroffset = 0;
+    entry_dp = NULL;
+    while (diroffset < dip->i_size) {
+	blockoffset = 0;
+	ext2_bread(dip, diroffset / blocksize, dirbuf);
+	while(blockoffset < blocksize) {
+
+	    dp = (struct ext2_dir_entry *)(dirbuf+blockoffset);
+	    dp_inode = big_endian ? swap32(dp->inode) : dp->inode;
+	    dp_reclen = big_endian ? swap16(dp->rec_len) : dp->rec_len;
+	    dp_namelen = big_endian ? swap16(dp->name_len) : dp->name_len;
+
+	    if((dp_inode == 0) && (dp_reclen >= EXT2_DIR_REC_LEN(namelen))) {
+		/* Found an *empty* entry that can hold this name. */
+		entry_dp = dp;
+		break;
+	    }
+
+	    /* If this entry is in use, see if it has space at the end
+	     * to hold the new entry anyway...
+	     */
+	    if((dp_inode != 0) && 
+		((dp_reclen - EXT2_DIR_REC_LEN(dp_namelen)) 
+					>= EXT2_DIR_REC_LEN(namelen))) {
+
+		new_reclen = dp_reclen - EXT2_DIR_REC_LEN(dp_namelen);
+
+		/* Chop the in-use entry down to size */
+		if(big_endian) {
+		    dp_reclen = EXT2_DIR_REC_LEN(swap16(dp->name_len));
+		}
+		else {
+		    dp_reclen = EXT2_DIR_REC_LEN(dp->name_len);
+		}
+		dp->rec_len = big_endian ? swap16(dp_reclen) : dp_reclen;
+		
+		/* Point entry_dp to the end of this entry */
+		entry_dp = (struct ext2_dir_entry *)((char*)dp + dp_reclen);
+
+		/* Set the record length for this entry */
+		entry_dp->rec_len = big_endian ? swap16(new_reclen) : new_reclen;
+
+		/* all set! */
+		break;
+	    }
+
+	    /* No luck yet... go to next entry in this block */
+	    blockoffset += dp_reclen;
+	}
+	if(entry_dp != NULL) {
+	    break;
+	}
+
+	/* If we got here, then we didn't find the component.
+	 * Try the next block in this directory...
+	 */
+	diroffset += blocksize;
+    }
+
+    /* By the time we get here, one of two things has happened:
+     *
+     *	If entry_dp is non-NULL, then entry_dp points to the 
+     *  place in dirbuf where the entry lives, and diroffset
+     *  is the directory offset of the beginning of dirbuf.
+     *
+     *  If entry_dp is NULL, then we couldn't find an entry,
+     *  so we need to add a block to the directory file for
+     *  this entry...
+     */
+    if(entry_dp) {
+	entry_dp->inode = big_endian ? swap32(ino) : ino;
+	entry_dp->name_len = big_endian ? swap16(namelen) : namelen;
+	strncpy(entry_dp->name, name, namelen);
+	ext2_bwrite(dip, diroffset/blocksize, dirbuf);
+    }
+    else {
+	entry_dp = (struct ext2_dir_entry *)dirbuf;
+	entry_dp->inode = big_endian ? swap32(ino) : ino;
+	entry_dp->name_len = big_endian ? swap16(namelen) : namelen;
+	strncpy(entry_dp->name, name, namelen);
+	entry_dp->rec_len = big_endian ? swap16(blocksize) : blocksize;
+	ext2_bwrite(dip, dip->i_size/blocksize, dirbuf);
+	dip->i_size += blocksize;
+    }
+}
+
+/* This is a close cousin to namei, only it *removes* the entry
+ * in addition to finding it.  This routine assumes that the specified
+ * entry has already been found...
+ */
+void
+ext2_remove_entry (char *name)
+{
+    char 	namebuf[256];
+    char 	dirbuf[EXT2_MAX_BLOCK_SIZE];
+    char *	component;
+    struct ext2_inode *		dir_inode;
+    struct ext2_dir_entry *dp;
+    int		next_ino;
+    int		dp_inode, dp_reclen, dp_namelen;
+
+    /* Squirrel away a copy of "namebuf" that we can molest */
+    strcpy(namebuf, name);
+
+    /* Start at the root... */
+    dir_inode = ext2_iget(EXT2_ROOT_INO);
+
+    component = strtok(namebuf, "/");
+    while(component) {
+	unsigned diroffset;
+	int blockoffset, component_length;
+	char *next_component;
+	struct ext2_dir_entry * pdp;
+
+	/* Search for the specified component in the current directory
+	 * inode.
+	 */
+
+	next_component = NULL;
+	pdp = NULL;
+	next_ino = -1;
+
+	component_length = strlen(component);
+	diroffset = 0;
+	while (diroffset < dir_inode->i_size) {
+	    blockoffset = 0;
+	    ext2_bread(dir_inode, diroffset / blocksize, dirbuf);
+	    while(blockoffset < blocksize) {
+	        dp = (struct ext2_dir_entry *)(dirbuf+blockoffset);
+		dp_inode = big_endian ? swap32(dp->inode) : dp->inode;
+		dp_reclen = big_endian ? swap16(dp->rec_len) : dp->rec_len;
+		dp_namelen = big_endian ? swap16(dp->name_len) : dp->name_len;
+
+		if((dp_namelen == component_length) &&
+		   (strncmp(component, dp->name, component_length) == 0)) {
+			/* Found it! */
+			next_component = strtok(NULL, "/");
+			if(next_component == NULL) {
+			    /* We've found the entry that needs to be
+			     * zapped.  If it's at the beginning of the
+			     * block, then zap it.  Otherwise, coalesce
+			     * it with the previous entry.
+			     */
+			    if(pdp) {
+				if(big_endian) {
+				    pdp->rec_len = 
+					swap16(swap16(pdp->rec_len)+dp_reclen);
+				}
+				else {
+				    pdp->rec_len += dp_reclen;
+				}
+			    }
+			    else {
+				dp->inode = 0;
+				dp->name_len = 0;
+			    }
+	    		    ext2_bwrite(dir_inode, diroffset / blocksize, dirbuf);
+			    return;
+			}
+			next_ino = dp_inode;
+			break;
+		}
+		/* Go to next entry in this block */
+		pdp = dp;
+		blockoffset += dp_reclen;
+	    }
+	    if(next_ino >= 0) {
+		break;
+	    }
+
+	    /* If we got here, then we didn't find the component.
+	     * Try the next block in this directory...
+	     */
+	    diroffset += blocksize;
+	}
+
+	/* At this point, we're done with this directory whether
+	 * we've succeeded or failed...
+	 */
+	ext2_iput(dir_inode);
+
+	/* If next_ino is negative, then we've failed (gone all the
+	 * way through without finding anything)
+	 */
+	if(next_ino < 0) {
+	    return;
+	}
+
+	/* Otherwise, we can get this inode and find the next
+	 * component string...
+	 */
+	dir_inode = ext2_iget(next_ino);
+	
+	component = next_component;
+    }
+
+    ext2_iput(dir_inode);
+}
+
+
+void
+ext2_truncate (struct ext2_inode *ip)
+{
+    int		i;
+
+    /* Deallocate all blocks associated with a particular file
+     * and set its size to zero.
+     */
+
+    /* Direct blocks */
+    for(i = 0; i < EXT2_NDIR_BLOCKS; i++) {
+	if(ip->i_block[i]) {
+	    ext2_bfree(ip->i_block[i]);
+	    ip->i_block[i] = 0;
+	}
+    }
+
+    /* First-level indirect blocks */
+    if(ip->i_block[EXT2_IND_BLOCK]) {
+	ext2_free_indirect(ip->i_block[EXT2_IND_BLOCK], 0);
+	ip->i_block[EXT2_IND_BLOCK] = 0;
+    }
+
+    /* Second-level indirect blocks */
+    if(ip->i_block[EXT2_DIND_BLOCK]) {
+	ext2_free_indirect(ip->i_block[EXT2_DIND_BLOCK], 1);
+	ip->i_block[EXT2_DIND_BLOCK] = 0;
+    }
+
+    /* Third-level indirect blocks */
+    if(ip->i_block[EXT2_TIND_BLOCK]) {
+        ext2_free_indirect(ip->i_block[EXT2_TIND_BLOCK], 2);
+        ip->i_block[EXT2_TIND_BLOCK] = 0;
+    }
+
+    ip->i_size = 0;
+}
+
+/* Recursive routine to free an indirect chain */
+static void
+ext2_free_indirect (int indirect_blkno, int level)
+{
+    int i, indirect_block[EXT2_MAX_BLOCK_SIZE/4];
+
+    /* Read the specified indirect block */
+    bread(indirect_blkno, indirect_block);
+
+    for(i = 0; i < ptrs_per_blk; i++) {
+	if(level == 0) {
+	    /* These are pointers to data blocks; just free them up */
+	    if(indirect_block[i]) {
+		if(big_endian) {
+	            ext2_bfree(swap32(indirect_block[i]));
+		}
+		else {
+	            ext2_bfree(indirect_block[i]);
+		}
+	        indirect_block[i] = 0;
+	    }
+	}
+	else {
+	    /* These are pointers to *indirect* blocks.  Go down the chain */
+	    if(indirect_block[i]) {
+		if(big_endian) {
+		    ext2_free_indirect(swap32(indirect_block[i]), level-1);
+		}
+		else {
+		    ext2_free_indirect(indirect_block[i], level-1);
+		}
+		indirect_block[i] = 0;
+	    }
+	}
+    }
+    ext2_bfree(indirect_blkno);
+}
+
+int
+ext2_get_inumber (struct ext2_inode *ip)
+{
+    struct inode_table_entry *itp;
+
+    itp = (struct inode_table_entry *)ip;
+    return(itp->inumber);
+}

+ 332 - 0
package/aboot/src/tools/e2lib.h

@@ -0,0 +1,332 @@
+#ifndef EXT2_LIB_H
+#define EXT2_LIB_H
+
+#include <fcntl.h>
+
+
+/* Definitions cribbed from ext2_fs.h, modified so's to be 64-bit clean
+ * when cross-compiling on Alpha
+ */
+
+/*
+ * The second extended filesystem constants/structures
+ */
+
+/*
+ * Define EXT2FS_DEBUG to produce debug messages
+ */
+#undef EXT2FS_DEBUG
+
+/*
+ * Define EXT2FS_DEBUG_CACHE to produce cache debug messages
+ */
+#undef EXT2FS_DEBUG_CACHE
+
+/*
+ * Define EXT2FS_CHECK_CACHE to add some checks to the name cache code
+ */
+#undef EXT2FS_CHECK_CACHE
+
+/*
+ * Define EXT2FS_PRE_02B_COMPAT to convert ext 2 fs prior to 0.2b
+ */
+#undef EXT2FS_PRE_02B_COMPAT
+
+/*
+ * Define DONT_USE_DCACHE to inhibit the directory cache
+ */
+#define DONT_USE_DCACHE
+
+/*
+ * Define EXT2_PREALLOCATE to preallocate data blocks for expanding files
+ */
+#define EXT2_PREALLOCATE
+
+/*
+ * The second extended file system version
+ */
+#define EXT2FS_DATE		"94/03/10"
+#define EXT2FS_VERSION		"0.5"
+
+
+/*
+ * Special inodes numbers
+ */
+#define	EXT2_BAD_INO		 1	/* Bad blocks inode */
+#define EXT2_ROOT_INO		 2	/* Root inode */
+#define EXT2_ACL_IDX_INO	 3	/* ACL inode */
+#define EXT2_ACL_DATA_INO	 4	/* ACL inode */
+#define EXT2_BOOT_LOADER_INO	 5	/* Boot loader inode */
+#define EXT2_UNDEL_DIR_INO	 6	/* Undelete directory inode */
+#define EXT2_FIRST_INO		11	/* First non reserved inode */
+
+/*
+ * The second extended file system magic number
+ */
+#define EXT2_PRE_02B_MAGIC	0xEF51
+#define EXT2_SUPER_MAGIC	0xEF53
+#define EXT2_SUPER_BIGMAGIC	0x53EF	/* Accessing on big-endian system... */
+
+/*
+ * Maximal count of links to a file
+ */
+#define EXT2_LINK_MAX		32000
+
+/*
+ * Macro-instructions used to manage several block sizes
+ */
+#define EXT2_MIN_BLOCK_SIZE		1024
+#define	EXT2_MAX_BLOCK_SIZE		4096
+#define EXT2_MIN_BLOCK_LOG_SIZE		  10
+# define EXT2_BLOCK_SIZE(s)		(EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
+#define EXT2_ACLE_PER_BLOCK(s)		(EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry))
+#define	EXT2_ADDR_PER_BLOCK(s)		(EXT2_BLOCK_SIZE(s) / sizeof (unsigned int))
+# define EXT2_BLOCK_SIZE_BITS(s)	((s)->s_log_block_size + 10)
+#define	EXT2_INODES_PER_BLOCK(s)	(EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_inode))
+
+/*
+ * Macro-instructions used to manage fragments
+ */
+#define EXT2_MIN_FRAG_SIZE		1024
+#define	EXT2_MAX_FRAG_SIZE		4096
+#define EXT2_MIN_FRAG_LOG_SIZE		  10
+# define EXT2_FRAG_SIZE(s)		(EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size)
+# define EXT2_FRAGS_PER_BLOCK(s)	(EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s))
+
+/*
+ * ACL structures
+ */
+struct ext2_acl_header	/* Header of Access Control Lists */
+{
+	unsigned int aclh_size;
+	unsigned int aclh_file_count;
+	unsigned int aclh_acle_count;
+	unsigned int aclh_first_acle;
+};
+
+struct ext2_acl_entry	/* Access Control List Entry */
+{
+	unsigned int  acle_size;
+	unsigned short acle_perms;	/* Access permissions */
+	unsigned short acle_type;	/* Type of entry */
+	unsigned short acle_tag;	/* User or group identity */
+	unsigned short acle_pad1;
+	unsigned int  acle_next;	/* Pointer on next entry for the */
+					/* same inode or on next free entry */
+};
+
+/*
+ * Structure of a blocks group descriptor
+ */
+struct ext2_old_group_desc
+{
+	unsigned int  bg_block_bitmap;		/* Blocks bitmap block */
+	unsigned int  bg_inode_bitmap;		/* Inodes bitmap block */
+	unsigned int  bg_inode_table;		/* Inodes table block */
+	unsigned short bg_free_blocks_count;	/* Free blocks count */
+	unsigned short bg_free_inodes_count;	/* Free inodes count */
+};
+
+struct ext2_group_desc
+{
+	unsigned int  bg_block_bitmap;		/* Blocks bitmap block */
+	unsigned int  bg_inode_bitmap;		/* Inodes bitmap block */
+	unsigned int  bg_inode_table;		/* Inodes table block */
+	unsigned short bg_free_blocks_count;	/* Free blocks count */
+	unsigned short bg_free_inodes_count;	/* Free inodes count */
+	unsigned short bg_used_dirs_count;	/* Directories count */
+	unsigned short bg_pad;
+	unsigned int  bg_reserved[3];
+};
+
+/*
+ * Macro-instructions used to manage group descriptors
+ */
+# define EXT2_BLOCKS_PER_GROUP(s)	((s)->s_blocks_per_group)
+# define EXT2_DESC_PER_BLOCK(s)		(EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
+# define EXT2_INODES_PER_GROUP(s)	((s)->s_inodes_per_group)
+
+/*
+ * Constants relative to the data blocks
+ */
+#define	EXT2_NDIR_BLOCKS		12
+#define	EXT2_IND_BLOCK			EXT2_NDIR_BLOCKS
+#define	EXT2_DIND_BLOCK			(EXT2_IND_BLOCK + 1)
+#define	EXT2_TIND_BLOCK			(EXT2_DIND_BLOCK + 1)
+#define	EXT2_N_BLOCKS			(EXT2_TIND_BLOCK + 1)
+
+/*
+ * Inode flags
+ */
+#define	EXT2_SECRM_FL			0x0001	/* Secure deletion */
+#define	EXT2_UNRM_FL			0x0002	/* Undelete */
+#define	EXT2_COMPR_FL			0x0004	/* Compress file */
+#define EXT2_SYNC_FL			0x0008	/* Synchronous updates */
+
+/*
+ * ioctl commands
+ */
+#define	EXT2_IOC_GETFLAGS		_IOR('f', 1, int)
+#define	EXT2_IOC_SETFLAGS		_IOW('f', 2, int)
+#define	EXT2_IOC_GETVERSION		_IOR('v', 1, int)
+#define	EXT2_IOC_SETVERSION		_IOW('v', 2, int)
+
+/*
+ * Structure of an inode on the disk
+ */
+struct ext2_inode {
+	unsigned short i_mode;		/* File mode */
+	unsigned short i_uid;		/* Owner Uid */
+	unsigned int  i_size;		/* Size in bytes */
+	unsigned int  i_atime;		/* Access time */
+	unsigned int  i_ctime;		/* Creation time */
+	unsigned int  i_mtime;		/* Modification time */
+	unsigned int  i_dtime;		/* Deletion Time */
+	unsigned short i_gid;		/* Group Id */
+	unsigned short i_links_count;	/* Links count */
+	unsigned int  i_blocks;	/* Blocks count */
+	unsigned int  i_flags;		/* File flags */
+	unsigned int  i_reserved1;
+	unsigned int  i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
+	unsigned int  i_version;	/* File version (for NFS) */
+	unsigned int  i_file_acl;	/* File ACL */
+	unsigned int  i_dir_acl;	/* Directory ACL */
+	unsigned int  i_faddr;		/* Fragment address */
+	unsigned char  i_frag;		/* Fragment number */
+	unsigned char  i_fsize;		/* Fragment size */
+	unsigned short i_pad1;
+	unsigned int  i_reserved2[2];
+};
+
+/*
+ * File system states
+ */
+#define	EXT2_VALID_FS			0x0001	/* Unmounted cleany */
+#define	EXT2_ERROR_FS			0x0002	/* Errors detected */
+
+/*
+ * Mount flags
+ */
+#define EXT2_MOUNT_CHECK_NORMAL		0x0001	/* Do some more checks */
+#define EXT2_MOUNT_CHECK_STRICT		0x0002	/* Do again more checks */
+#define EXT2_MOUNT_CHECK		(EXT2_MOUNT_CHECK_NORMAL | \
+					 EXT2_MOUNT_CHECK_STRICT)
+#define EXT2_MOUNT_GRPID		0x0004	/* Create files with directory's group */
+#define EXT2_MOUNT_DEBUG		0x0008	/* Some debugging messages */
+#define EXT2_MOUNT_ERRORS_CONT		0x0010	/* Continue on errors */
+#define EXT2_MOUNT_ERRORS_RO		0x0020	/* Remount fs ro on errors */
+#define EXT2_MOUNT_ERRORS_PANIC		0x0040	/* Panic on errors */
+
+#define clear_opt(o, opt)		o &= ~EXT2_MOUNT_##opt
+#define set_opt(o, opt)			o |= EXT2_MOUNT_##opt
+#define test_opt(sb, opt)		((sb)->u.ext2_sb.s_mount_opt & \
+					 EXT2_MOUNT_##opt)
+/*
+ * Maximal mount counts between two filesystem checks
+ */
+#define EXT2_DFL_MAX_MNT_COUNT		20	/* Allow 20 mounts */
+#define EXT2_DFL_CHECKINTERVAL		0	/* Don't use interval check */
+
+/*
+ * Behaviour when detecting errors
+ */
+#define EXT2_ERRORS_CONTINUE		1	/* Continue execution */
+#define EXT2_ERRORS_RO			2	/* Remount fs read-only */
+#define EXT2_ERRORS_PANIC		3	/* Panic */
+#define EXT2_ERRORS_DEFAULT		EXT2_ERRORS_CONTINUE
+
+/*
+ * Structure of the super block
+ */
+struct ext2_super_block {
+	unsigned int  s_inodes_count;	/* 0: Inodes count */
+	unsigned int  s_blocks_count;	/* 4: Blocks count */
+	unsigned int  s_r_blocks_count;/* 8: Reserved blocks count */
+	unsigned int  s_free_blocks_count;/* 12: Free blocks count */
+	unsigned int  s_free_inodes_count;/* 16: Free inodes count */
+	unsigned int  s_first_data_block;/* 20: First Data Block */
+	unsigned int  s_log_block_size;/* 24: Block size */
+	int           s_log_frag_size;	/* 28: Fragment size */
+	unsigned int  s_blocks_per_group;/* 32: # Blocks per group */
+	unsigned int  s_frags_per_group;/* 36: # Fragments per group */
+	unsigned int  s_inodes_per_group;/* 40: # Inodes per group */
+	unsigned int  s_mtime;		/* 44: Mount time */
+	unsigned int  s_wtime;		/* 48: Write time */
+	unsigned short s_mnt_count;	/* 52: Mount count */
+	short          s_max_mnt_count;	/* 54: Maximal mount count */
+	unsigned short s_magic;		/* 56: Magic signature */
+	unsigned short s_state;		/* 58: File system state */
+	unsigned short s_errors;	/* 60: Behaviour when detecting errors */
+	unsigned short s_pad;		/* 62: */
+	unsigned int  s_lastcheck;	/* 64: time of last check */
+	unsigned int  s_checkinterval;	/* 68: max. time between checks */
+	unsigned int  s_reserved[238];	/* 72: Padding to the end of the block */
+};
+
+/*
+ * Structure of a directory entry
+ */
+#define EXT2_NAME_LEN 255
+
+struct ext2_dir_entry {
+	unsigned int  inode;			/* Inode number */
+	unsigned short rec_len;			/* Directory entry length */
+	unsigned short name_len;		/* Name length */
+	char           name[EXT2_NAME_LEN];	/* File name */
+};
+
+/*
+ * EXT2_DIR_PAD defines the directory entries boundaries
+ *
+ * NOTE: It must be a multiple of 4
+ */
+#define EXT2_DIR_PAD		 	4
+#define EXT2_DIR_ROUND 			(EXT2_DIR_PAD - 1)
+#define EXT2_DIR_REC_LEN(name_len)	(((name_len) + 8 + EXT2_DIR_ROUND) & \
+					 ~EXT2_DIR_ROUND)
+
+
+/* These definitions are cribbed from other file system include files, so that
+ * we can take a stab at identifying non-ext2 file systems as well...
+ */
+/*
+ * minix super-block data on disk
+ */
+struct minix_super_block {
+        unsigned short s_ninodes;
+        unsigned short s_nzones;
+        unsigned short s_imap_blocks;
+        unsigned short s_zmap_blocks;
+        unsigned short s_firstdatazone;
+        unsigned short s_log_zone_size;
+        unsigned int s_max_size;
+        unsigned short s_magic;
+        unsigned short s_state;
+};
+
+#define MINIX_SUPER_MAGIC       0x137F          /* original minix fs */
+#define MINIX_SUPER_MAGIC2      0x138F          /* minix fs, 30 char names */
+#define NEW_MINIX_SUPER_MAGIC   0x2468          /* minix V2 - not implemented */
+
+extern int 			ext2_init(char * name, int access);
+extern void 			ext2_close();
+extern struct ext2_inode *	ext2_iget(int ino);
+extern void 			ext2_iput(struct ext2_inode *ip);
+extern int			ext2_balloc(void);
+extern int			ext2_ialloc(void);
+extern int			ext2_blocksize(void);
+extern int			ext2_blkno(struct ext2_inode *ip, int blkoff,
+					   int allocate);
+extern void			ext2_bread(struct ext2_inode *ip, int blkno,
+					   char * buffer);
+extern void			ext2_bwrite(struct ext2_inode *ip, int blkno,
+					    char * buffer);
+extern struct ext2_inode *	ext2_namei(char * name);
+extern void			ext2_truncate(struct ext2_inode *ip);
+extern void			ext2_mknod(struct ext2_inode *dip,
+					   char * name, int ino);
+extern int			ext2_fill_contiguous(struct ext2_inode * ip,
+						     int nblocks);
+extern void			ext2_write_bootblock(char *bb);
+
+#endif /* EXT2_LIB_H */

Some files were not shown because too many files changed in this diff