diff options
Diffstat (limited to 'package')
108 files changed, 21826 insertions, 0 deletions
diff --git a/package/aboot/Makefile b/package/aboot/Makefile new file mode 100644 index 000000000..e49a773ea --- /dev/null +++ b/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 diff --git a/package/aboot/src/COPYING b/package/aboot/src/COPYING new file mode 100644 index 000000000..a43ea2126 --- /dev/null +++ b/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. diff --git a/package/aboot/src/ChangeLog b/package/aboot/src/ChangeLog new file mode 100644 index 000000000..c46c6fc08 --- /dev/null +++ b/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> diff --git a/package/aboot/src/ChangeLog.cvs b/package/aboot/src/ChangeLog.cvs new file mode 100644 index 000000000..88c7b450b --- /dev/null +++ b/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) + diff --git a/package/aboot/src/INSTALL b/package/aboot/src/INSTALL new file mode 100644 index 000000000..107940de2 --- /dev/null +++ b/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 diff --git a/package/aboot/src/Makefile b/package/aboot/src/Makefile new file mode 100644 index 000000000..12450e735 --- /dev/null +++ b/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: diff --git a/package/aboot/src/README b/package/aboot/src/README new file mode 100644 index 000000000..b5d3f0a2c --- /dev/null +++ b/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. + diff --git a/package/aboot/src/TODO b/package/aboot/src/TODO new file mode 100644 index 000000000..74a99d261 --- /dev/null +++ b/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. diff --git a/package/aboot/src/aboot.c b/package/aboot/src/aboot.c new file mode 100644 index 000000000..90614a72c --- /dev/null +++ b/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 */ diff --git a/package/aboot/src/aboot.conf b/package/aboot/src/aboot.conf new file mode 100644 index 000000000..02114138e --- /dev/null +++ b/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 +- diff --git a/package/aboot/src/aboot.lds b/package/aboot/src/aboot.lds new file mode 100644 index 000000000..415ab80e5 --- /dev/null +++ b/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) } +} diff --git a/package/aboot/src/b2c.c b/package/aboot/src/b2c.c new file mode 100644 index 000000000..0b9318540 --- /dev/null +++ b/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; + +} + + + diff --git a/package/aboot/src/cons.c b/package/aboot/src/cons.c new file mode 100644 index 000000000..3de796b3a --- /dev/null +++ b/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(); +} diff --git a/package/aboot/src/disk.c b/package/aboot/src/disk.c new file mode 100644 index 000000000..fd9af8f6a --- /dev/null +++ b/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; +} diff --git a/package/aboot/src/doc/faq/.cvsignore b/package/aboot/src/doc/faq/.cvsignore new file mode 100644 index 000000000..2d19fc766 --- /dev/null +++ b/package/aboot/src/doc/faq/.cvsignore @@ -0,0 +1 @@ +*.html diff --git a/package/aboot/src/doc/faq/Makefile b/package/aboot/src/doc/faq/Makefile new file mode 100644 index 000000000..fc38ddba4 --- /dev/null +++ b/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 diff --git a/package/aboot/src/doc/faq/SRM-HOWTO.sgml b/package/aboot/src/doc/faq/SRM-HOWTO.sgml new file mode 100644 index 000000000..8093647d4 --- /dev/null +++ b/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 +'>>>' prompt, like this: +<FOOTNOTE> + +<Para> +On multiprocessor machines, you +will see 'P00>>' instead, or possibly some other number depending on +which processor SRM is running. +</Para> + +</FOOTNOTE> + + +<Screen> +>>> boot dva0 -fi linux.gz -fl "root=/dev/fd0 load_ramdisk=1" +</Screen> + +</Para> + +<Para> +Unix commands will be shown with the '#' 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>' command prompt, like +this: + +<Screen> +aboot> 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_type</Literal> environment +variable in SRM to "OpenVMS" or "Unix", like this: + +<Screen> +>>> 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_type</Literal> to +"OpenVMS". Conversely, to return to ARC/AlphaBIOS, you can set +<Literal remap="tt">os_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> +>>> 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_dev</varname>, +<varname>boot_file</varname>, <varname>boot_flags</varname>, and +<varname>auto_action</varname>, all of which are cold non-volatile. +</Para> + +<Para> +To set environment variables, use the <command>set</command> command, like this: + +<Screen> +>>> 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_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_file</varname> variable contains the filename to be +loaded by the secondary bootloader, while <varname>boot_flags</varname> +contains any extra flags. <varname>auto_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_SIZE</varname> bytes starting at disk offset +<varname>BOOT_SIZE</varname><Literal remap="tt">+512</Literal> +(also in bytes). The constants +<varname>START_SIZE</varname> and <varname>BOOT_SIZE</varname> +are defined in +<filename>linux/include/asm-alpha/system.h</filename>. +<varname>START_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_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_SIZE</varname> and 16KB for +<varname>BOOT_SIZE</varname>. Note +that if you want to boot from a 1.44MB floppy disk, you have to reduce +<varname>START_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 >/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 ‐ 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_DEV</varname>, +<varname>BOOT_OSFILE</varname> and +<varname>BOOT_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_dev</varname> variable (among others), this variable is +read only +and needs to be changed via the <varname>bootdef_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> +>>> 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 +>[<Emphasis>n</Emphasis>/]<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> +>>> boot dka600 -file 2/vmlinux.gz +</Screen> + +</Para> + +<Para> +Or to boot from floppy drive 0, you'd enter: + +<Screen> +>>> 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_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_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> +>>> boot dka0 -fl i +aboot> ? + h, ? Display this message + q Halt the system and return to SRM + p 1-8 Look in partition <num> for configuration/kernel + l List pre-configured kernels + d <dir> List directory <dir> in current filesystem + b <file> <args> Boot kernel in <file> (- for raw boot) + with arguments <args> + 0-9 Boot pre-configuration 0-9 (list with 'l') +aboot> 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> +>>> 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_protocol (DE500 cards) or eia0_protocol (Intel cards) variable to bootp. + +<Screen> +>>> 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> +>>> 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> +>>> 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> +>>> 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\> 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> +>>> 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> +>>> 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> +>>> 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_dev and boot_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> diff --git a/package/aboot/src/doc/man/Makefile b/package/aboot/src/doc/man/Makefile new file mode 100644 index 000000000..4ccdd4c0d --- /dev/null +++ b/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 + diff --git a/package/aboot/src/doc/man/README b/package/aboot/src/doc/man/README new file mode 100644 index 000000000..f2af31271 --- /dev/null +++ b/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 diff --git a/package/aboot/src/doc/man/aboot.8 b/package/aboot/src/doc/man/aboot.8 new file mode 100644 index 000000000..5aa86a568 --- /dev/null +++ b/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 diff --git a/package/aboot/src/doc/man/aboot.conf.5 b/package/aboot/src/doc/man/aboot.conf.5 new file mode 100644 index 000000000..b3cb49393 --- /dev/null +++ b/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 diff --git a/package/aboot/src/doc/man/aboot.conf.sgml b/package/aboot/src/doc/man/aboot.conf.sgml new file mode 100644 index 000000000..f29813e7f --- /dev/null +++ b/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> diff --git a/package/aboot/src/doc/man/aboot.sgml b/package/aboot/src/doc/man/aboot.sgml new file mode 100644 index 000000000..d54d3ad8c --- /dev/null +++ b/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> diff --git a/package/aboot/src/doc/man/abootconf.8 b/package/aboot/src/doc/man/abootconf.8 new file mode 100644 index 000000000..cb0f00624 --- /dev/null +++ b/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 diff --git a/package/aboot/src/doc/man/abootconf.sgml b/package/aboot/src/doc/man/abootconf.sgml new file mode 100644 index 000000000..5281cd323 --- /dev/null +++ b/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> diff --git a/package/aboot/src/doc/man/de/Makefile b/package/aboot/src/doc/man/de/Makefile new file mode 100644 index 000000000..22ef583a1 --- /dev/null +++ b/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 diff --git a/package/aboot/src/doc/man/de/aboot.conf.sgml b/package/aboot/src/doc/man/de/aboot.conf.sgml new file mode 100644 index 000000000..5702c70db --- /dev/null +++ b/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> diff --git a/package/aboot/src/doc/man/de/aboot.sgml b/package/aboot/src/doc/man/de/aboot.sgml new file mode 100644 index 000000000..49fa124e6 --- /dev/null +++ b/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> diff --git a/package/aboot/src/doc/man/de/abootconf.sgml b/package/aboot/src/doc/man/de/abootconf.sgml new file mode 100644 index 000000000..21cbe5ebf --- /dev/null +++ b/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> diff --git a/package/aboot/src/doc/man/de/docbook2man-de-spec.pl b/package/aboot/src/doc/man/de/docbook2man-de-spec.pl new file mode 100644 index 000000000..2eed9015e --- /dev/null +++ b/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>', \¶_start); +sgml('</PARA>', \¶_end); +sgml('<SIMPARA>', \¶_start); +sgml('</SIMPARA>', \¶_end); + +# Nothing special, except maybe FIXME set nobreak. +sgml('<INFORMALEXAMPLE>', \¶_start); +sgml('</INFORMALEXAMPLE>', \¶_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>', \¶_end); + +# Same with sidebar. +sgml('<SIDEBAR>', sub { $separator = ''; man_output "\n.SS "}); +sgml('</SIDEBAR>', \¶_end); + +sgml('<FORMALPARA>', sub { $separator = ''; man_output "\n.SS "}); +sgml('</FORMALPARA>', \¶_end); + +sgml('<FIGURE>', sub { $separator = ''; man_output "\n.SS "}); +sgml('</FIGURE>', \¶_end); + + + +# NO title. # L10N +sgml('<HIGHLIGHTS>', sub { $separator = ''; man_output "\n.SS HIGHLIGHTS\n"}); +sgml('</HIGHLIGHTS>', \¶_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; + diff --git a/package/aboot/src/doc/man/de/e2writeboot.8 b/package/aboot/src/doc/man/de/e2writeboot.8 new file mode 100644 index 000000000..1c6b786dd --- /dev/null +++ b/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 diff --git a/package/aboot/src/doc/man/de/isomarkboot.sgml b/package/aboot/src/doc/man/de/isomarkboot.sgml new file mode 100644 index 000000000..7155bcb82 --- /dev/null +++ b/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> diff --git a/package/aboot/src/doc/man/de/netabootwrap.sgml b/package/aboot/src/doc/man/de/netabootwrap.sgml new file mode 100644 index 000000000..9ef857674 --- /dev/null +++ b/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> diff --git a/package/aboot/src/doc/man/de/sdisklabel.sgml b/package/aboot/src/doc/man/de/sdisklabel.sgml new file mode 100644 index 000000000..e1dbbd67a --- /dev/null +++ b/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> diff --git a/package/aboot/src/doc/man/de/srmbootfat.sgml b/package/aboot/src/doc/man/de/srmbootfat.sgml new file mode 100644 index 000000000..5711983b9 --- /dev/null +++ b/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> diff --git a/package/aboot/src/doc/man/de/srmbootraw.sgml b/package/aboot/src/doc/man/de/srmbootraw.sgml new file mode 100644 index 000000000..465401ecd --- /dev/null +++ b/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> diff --git a/package/aboot/src/doc/man/de/swriteboot.8 b/package/aboot/src/doc/man/de/swriteboot.8 new file mode 100644 index 000000000..69e25e2f9 --- /dev/null +++ b/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 diff --git a/package/aboot/src/doc/man/e2writeboot.8 b/package/aboot/src/doc/man/e2writeboot.8 new file mode 100644 index 000000000..520b9ca90 --- /dev/null +++ b/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 diff --git a/package/aboot/src/doc/man/isomarkboot.8 b/package/aboot/src/doc/man/isomarkboot.8 new file mode 100644 index 000000000..9d1100c30 --- /dev/null +++ b/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) diff --git a/package/aboot/src/doc/man/isomarkboot.sgml b/package/aboot/src/doc/man/isomarkboot.sgml new file mode 100644 index 000000000..a6e394b2b --- /dev/null +++ b/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> diff --git a/package/aboot/src/doc/man/netabootwrap.sgml b/package/aboot/src/doc/man/netabootwrap.sgml new file mode 100644 index 000000000..4e96ae8f2 --- /dev/null +++ b/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> diff --git a/package/aboot/src/doc/man/sdisklabel.8 b/package/aboot/src/doc/man/sdisklabel.8 new file mode 100644 index 000000000..dc2775c70 --- /dev/null +++ b/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) diff --git a/package/aboot/src/doc/man/sdisklabel.copyright b/package/aboot/src/doc/man/sdisklabel.copyright new file mode 100644 index 000000000..382d0a446 --- /dev/null +++ b/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 diff --git a/package/aboot/src/doc/man/sdisklabel.sgml b/package/aboot/src/doc/man/sdisklabel.sgml new file mode 100644 index 000000000..959219ff2 --- /dev/null +++ b/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> diff --git a/package/aboot/src/doc/man/swriteboot.8 b/package/aboot/src/doc/man/swriteboot.8 new file mode 100644 index 000000000..485c0f4a7 --- /dev/null +++ b/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 diff --git a/package/aboot/src/fs/dummy.c b/package/aboot/src/fs/dummy.c new file mode 100644 index 000000000..82d73d441 --- /dev/null +++ b/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) +{ +} diff --git a/package/aboot/src/fs/ext2.c b/package/aboot/src/fs/ext2.c new file mode 100644 index 000000000..b8cdefd13 --- /dev/null +++ b/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 +}; diff --git a/package/aboot/src/fs/iso.c b/package/aboot/src/fs/iso.c new file mode 100644 index 000000000..764993c05 --- /dev/null +++ b/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 +}; diff --git a/package/aboot/src/fs/ufs.c b/package/aboot/src/fs/ufs.c new file mode 100644 index 000000000..4cda3ceee --- /dev/null +++ b/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 +}; diff --git a/package/aboot/src/head.S b/package/aboot/src/head.S new file mode 100644 index 000000000..0e624e0da --- /dev/null +++ b/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 diff --git a/package/aboot/src/include/aboot.h b/package/aboot/src/include/aboot.h new file mode 100644 index 000000000..cbec653f8 --- /dev/null +++ b/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 */ diff --git a/package/aboot/src/include/bootfs.h b/package/aboot/src/include/bootfs.h new file mode 100644 index 000000000..cf41e16b4 --- /dev/null +++ b/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 */ diff --git a/package/aboot/src/include/config.h b/package/aboot/src/include/config.h new file mode 100644 index 000000000..28def9270 --- /dev/null +++ b/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 */ diff --git a/package/aboot/src/include/cons.h b/package/aboot/src/include/cons.h new file mode 100644 index 000000000..a9784246a --- /dev/null +++ b/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 */ diff --git a/package/aboot/src/include/disklabel.h b/package/aboot/src/include/disklabel.h new file mode 100644 index 000000000..3d0c2d129 --- /dev/null +++ b/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__ */ diff --git a/package/aboot/src/include/hwrpb.h b/package/aboot/src/include/hwrpb.h new file mode 100644 index 000000000..8e8f871af --- /dev/null +++ b/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 */ diff --git a/package/aboot/src/include/iso.h b/package/aboot/src/include/iso.h new file mode 100644 index 000000000..507bce2ee --- /dev/null +++ b/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 diff --git a/package/aboot/src/include/isolib.h b/package/aboot/src/include/isolib.h new file mode 100644 index 000000000..392327ab7 --- /dev/null +++ b/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 */ + + diff --git a/package/aboot/src/include/linux/ext2_fs.h b/package/aboot/src/include/linux/ext2_fs.h new file mode 100644 index 000000000..ce1b719e8 --- /dev/null +++ b/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 */ diff --git a/package/aboot/src/include/pal.h b/package/aboot/src/include/pal.h new file mode 100644 index 000000000..9b4ba0d6f --- /dev/null +++ b/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 */ diff --git a/package/aboot/src/include/setjmp.h b/package/aboot/src/include/setjmp.h new file mode 100644 index 000000000..57ad490da --- /dev/null +++ b/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 */ diff --git a/package/aboot/src/include/string.h b/package/aboot/src/include/string.h new file mode 100644 index 000000000..3aa65e7c8 --- /dev/null +++ b/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); diff --git a/package/aboot/src/include/system.h b/package/aboot/src/include/system.h new file mode 100644 index 000000000..0ab839a19 --- /dev/null +++ b/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 diff --git a/package/aboot/src/include/ufs.h b/package/aboot/src/include/ufs.h new file mode 100644 index 000000000..2629632fb --- /dev/null +++ b/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; + diff --git a/package/aboot/src/include/utils.h b/package/aboot/src/include/utils.h new file mode 100644 index 000000000..cda1d8600 --- /dev/null +++ b/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 */ diff --git a/package/aboot/src/lib/Makefile b/package/aboot/src/lib/Makefile new file mode 100644 index 000000000..bd6d3c543 --- /dev/null +++ b/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 + diff --git a/package/aboot/src/lib/_longjmp.S b/package/aboot/src/lib/_longjmp.S new file mode 100644 index 000000000..19b27a33c --- /dev/null +++ b/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 diff --git a/package/aboot/src/lib/_setjmp.S b/package/aboot/src/lib/_setjmp.S new file mode 100644 index 000000000..98d6366bb --- /dev/null +++ b/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 diff --git a/package/aboot/src/lib/divide.S b/package/aboot/src/lib/divide.S new file mode 100644 index 000000000..36668ab59 --- /dev/null +++ b/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 diff --git a/package/aboot/src/lib/isolib.c b/package/aboot/src/lib/isolib.c new file mode 100644 index 000000000..f0d186e30 --- /dev/null +++ b/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; +} + + + diff --git a/package/aboot/src/lib/memcpy.c b/package/aboot/src/lib/memcpy.c new file mode 100644 index 000000000..38fd642ab --- /dev/null +++ b/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; +} diff --git a/package/aboot/src/lib/memset.c b/package/aboot/src/lib/memset.c new file mode 100644 index 000000000..01ebe6758 --- /dev/null +++ b/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); +} diff --git a/package/aboot/src/lib/string.c b/package/aboot/src/lib/string.c new file mode 100644 index 000000000..7b6130b11 --- /dev/null +++ b/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; +} diff --git a/package/aboot/src/lib/vsprintf.c b/package/aboot/src/lib/vsprintf.c new file mode 100644 index 000000000..d6d256c73 --- /dev/null +++ b/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; +} + diff --git a/package/aboot/src/net.c b/package/aboot/src/net.c new file mode 100644 index 000000000..c753db314 --- /dev/null +++ b/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; +} diff --git a/package/aboot/src/netabootwrap.c b/package/aboot/src/netabootwrap.c new file mode 100644 index 000000000..aa49b43fd --- /dev/null +++ b/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; +} + + + diff --git a/package/aboot/src/netwrap.h b/package/aboot/src/netwrap.h new file mode 100644 index 000000000..20c9e4612 --- /dev/null +++ b/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); +} + diff --git a/package/aboot/src/sdisklabel/.cvsignore b/package/aboot/src/sdisklabel/.cvsignore new file mode 100644 index 000000000..2ffbe5c05 --- /dev/null +++ b/package/aboot/src/sdisklabel/.cvsignore @@ -0,0 +1,2 @@ +sdisklabel +swriteboot diff --git a/package/aboot/src/sdisklabel/Makefile b/package/aboot/src/sdisklabel/Makefile new file mode 100644 index 000000000..045fd3920 --- /dev/null +++ b/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 diff --git a/package/aboot/src/sdisklabel/README b/package/aboot/src/sdisklabel/README new file mode 100644 index 000000000..45b4636d0 --- /dev/null +++ b/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. diff --git a/package/aboot/src/sdisklabel/library.c b/package/aboot/src/sdisklabel/library.c new file mode 100644 index 000000000..7c9b198fd --- /dev/null +++ b/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; +} + diff --git a/package/aboot/src/sdisklabel/library.h b/package/aboot/src/sdisklabel/library.h new file mode 100644 index 000000000..cdb023df2 --- /dev/null +++ b/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 diff --git a/package/aboot/src/sdisklabel/sdisklabel.c b/package/aboot/src/sdisklabel/sdisklabel.c new file mode 100644 index 000000000..bc7b42a74 --- /dev/null +++ b/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; +} diff --git a/package/aboot/src/sdisklabel/swriteboot.c b/package/aboot/src/sdisklabel/swriteboot.c new file mode 100644 index 000000000..8c93d4402 --- /dev/null +++ b/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; +} diff --git a/package/aboot/src/srmbootfat/COPYING b/package/aboot/src/srmbootfat/COPYING new file mode 100644 index 000000000..a58e4228d --- /dev/null +++ b/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. diff --git a/package/aboot/src/srmbootfat/Makefile b/package/aboot/src/srmbootfat/Makefile new file mode 100644 index 000000000..27808ea2e --- /dev/null +++ b/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 + diff --git a/package/aboot/src/srmbootfat/README b/package/aboot/src/srmbootfat/README new file mode 100644 index 000000000..80ff41887 --- /dev/null +++ b/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. diff --git a/package/aboot/src/srmbootfat/msdos.h b/package/aboot/src/srmbootfat/msdos.h new file mode 100644 index 000000000..60b3ca29a --- /dev/null +++ b/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 diff --git a/package/aboot/src/srmbootfat/srmbootfat.c b/package/aboot/src/srmbootfat/srmbootfat.c new file mode 100644 index 000000000..71380ded5 --- /dev/null +++ b/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 } +}; diff --git a/package/aboot/src/srmbootfat/srmbootfat.sgml b/package/aboot/src/srmbootfat/srmbootfat.sgml new file mode 100644 index 000000000..33d5f4d8f --- /dev/null +++ b/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> diff --git a/package/aboot/src/srmbootfat/srmbootraw.c b/package/aboot/src/srmbootfat/srmbootraw.c new file mode 100644 index 000000000..3bba2d577 --- /dev/null +++ b/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; +} diff --git a/package/aboot/src/srmbootfat/srmbootraw.sgml b/package/aboot/src/srmbootfat/srmbootraw.sgml new file mode 100644 index 000000000..6490854ce --- /dev/null +++ b/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> diff --git a/package/aboot/src/tools/.cvsignore b/package/aboot/src/tools/.cvsignore new file mode 100644 index 000000000..2197455e0 --- /dev/null +++ b/package/aboot/src/tools/.cvsignore @@ -0,0 +1,5 @@ +abootconf +e2writeboot +elfencap +isomarkboot +objstrip diff --git a/package/aboot/src/tools/Makefile b/package/aboot/src/tools/Makefile new file mode 100644 index 000000000..740b9cb9d --- /dev/null +++ b/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 diff --git a/package/aboot/src/tools/abootconf.c b/package/aboot/src/tools/abootconf.c new file mode 100644 index 000000000..0d0ae075c --- /dev/null +++ b/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; +} diff --git a/package/aboot/src/tools/bio.c b/package/aboot/src/tools/bio.c new file mode 100644 index 000000000..c82161e62 --- /dev/null +++ b/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; +} diff --git a/package/aboot/src/tools/bio.h b/package/aboot/src/tools/bio.h new file mode 100644 index 000000000..398590360 --- /dev/null +++ b/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); diff --git a/package/aboot/src/tools/e2lib.c b/package/aboot/src/tools/e2lib.c new file mode 100644 index 000000000..56e4b66ef --- /dev/null +++ b/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); +} diff --git a/package/aboot/src/tools/e2lib.h b/package/aboot/src/tools/e2lib.h new file mode 100644 index 000000000..7c94ce270 --- /dev/null +++ b/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 */ diff --git a/package/aboot/src/tools/e2writeboot.c b/package/aboot/src/tools/e2writeboot.c new file mode 100644 index 000000000..58cbec1b7 --- /dev/null +++ b/package/aboot/src/tools/e2writeboot.c @@ -0,0 +1,254 @@ +/* Program to write a primary bootstrap file to a LINUX ext2 + * file system. + * + * Usage: e2writeboot fs-image bootfile + * + * It is assumed that the "bootfile" is a COFF executable with text, + * data, and bss contiguous. + */ + +#include <grp.h> +#include <pwd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include <sys/stat.h> + +#include <e2lib.h> + +#if defined(__linux__) +# include <sys/types.h> +#elif defined(__alpha__) && defined(__osf1__) + typedef unsigned long u_int64_t; +#elif defined(__GNUC__) + typedef unsigned long long u_int64_t; +#endif + +struct boot_block { + u_int64_t vax_code[17]; + u_int64_t reserved[43]; + u_int64_t count; + u_int64_t lbn; + u_int64_t flags; + u_int64_t chk_sum; +}; + +#define CONSOLE_BLOCK_SIZE 512 + +extern int big_endian; +extern unsigned short swap16(); +extern unsigned int swap32(); + + +int +main(int argc, char ** argv) +{ + char fsname[512]; + char iobuf[1024]; + char namebuf[EXT2_NAME_LEN+1]; + struct ext2_inode * ip; + int filesize; + int infile; + int blkno; + int bootstrap_size; + int i; + int bs_start; + char *bsbuf; + int blocksize; + struct boot_block *bbp; + u_int64_t *lbp, checksum; + struct stat st; + + if (argc != 3) { + printf("Usage: %s ext2-fs input-file\n", argv[0]); + exit(1); + } + + strcpy(fsname, argv[1]); + strcpy(namebuf, "/linuxboot"); + + + /* "Open" the file system */ + if (ext2_init(fsname, O_RDWR) < 0) { + exit(1); + } + + /* Open the input file */ + infile = open(argv[2], 0); + if (infile < 0) { + perror(argv[2]); + ext2_close(); + exit(1); + } + + /* Figure out just how much data the input file is going + * to require us to put out. (text+data+bss). + */ + if (fstat(infile, &st) == -1) { + perror("fstat"); + ext2_close(); + exit(1); + } + blocksize = ext2_blocksize(); + bootstrap_size = st.st_size; + printf("bootstrap_size: %d -> ", bootstrap_size); + bootstrap_size += blocksize-1; + bootstrap_size &= ~(blocksize-1); + printf("%d\n", bootstrap_size); + + /* Allocate a buffer to hold the entire bootstrap, then read + * in the text+data segments. + */ + bsbuf = (char *)malloc(bootstrap_size); + memset(bsbuf, 0, bootstrap_size); + read(infile, bsbuf, bootstrap_size); + close(infile); + + /* Get the inode for the file we want to create */ + ip = ext2_namei(namebuf); + if(ip) { + /* This file exists. Make sure it's a regular file, then + * truncate it. + */ + if(!S_ISREG(ip->i_mode)) { + printf("%s: Not a regular file. Must remove it first.\n", namebuf); + ext2_iput(ip); + ext2_close(); + exit(1); + } + + printf("Using existing file %s\n", namebuf); + ext2_truncate(ip); + } + else { + /* Doesn't exist. Must get the parent directory's inode. */ + char dirname[EXT2_NAME_LEN+1]; + char filename[EXT2_NAME_LEN+1]; + struct ext2_inode *dip; + int inumber; + char *cp; + int i; + + strcpy(dirname, namebuf); + cp = strrchr(dirname, '/'); + if(cp) { + *cp = '\0'; + strcpy(filename, cp+1); + } + else { + strcpy(filename, dirname); + strcpy(dirname, "/"); + } + + dip = ext2_namei(dirname); + if(!dip) { + printf("Directory %s does not exist\n", dirname); + ext2_close(); + exit(1); + } + + printf("Creating new file %s in directory %s\n", filename, dirname); + + /* Get an inode for the file */ + inumber = ext2_ialloc(); + ip = ext2_iget(inumber); + + if(!ip) { + printf("PANIC! ip == NULL\n"); + exit(1); + } + + /* Create the directory entry */ + ext2_mknod(dip, filename, inumber); + + /* We're done with the directory for now... */ + ext2_iput(dip); + + /* Set certain fields in the inode (we're not going to get + * fancy here... just choose a safe set of defaults...) + */ + ip->i_mode = 0550 | S_IFREG; /* Regular file, r-xr-x--- */ + ip->i_uid = 0; /* Owned by root */ + ip->i_gid = 0; /* Group is system */ + ip->i_size = 0; + ip->i_atime = ip->i_ctime = ip->i_mtime = time(0); + ip->i_dtime = 0; + ip->i_links_count = 1; + ip->i_blocks = 0; + ip->i_flags = 0; /* Nothing special */ + for(i = 0; i < EXT2_N_BLOCKS; i++) { + ip->i_block[i] = 0; + } + ip->i_version = 0; + ip->i_file_acl = 0; + ip->i_frag = 0; + ip->i_fsize = 0; + ip->i_reserved1 = ip->i_pad1 = ip->i_reserved2[0] = 0; + + } + + /* At this point we have an inode for an empty regular file. + * Fill it up! + */ + + bs_start = ext2_fill_contiguous(ip, bootstrap_size/blocksize); + if(bs_start <= 0) { + printf("Cannot allocate blocks for %s... goodbye!\n", argv[2]); + ext2_close(); + exit(1); + } + + /* Write what we've got out to the file */ + filesize = bootstrap_size; + blkno = 0; + while(filesize > 0) { + ext2_bwrite(ip, blkno, bsbuf+(blkno*blocksize)); + blkno++; + filesize -= blocksize; + } + + ip->i_size = bootstrap_size; + ip->i_mtime = time(0); + + + /* Prepare and write out a bootblock */ + memset(iobuf, 0, blocksize); + bbp = (struct boot_block *)iobuf; + + bbp->count = bootstrap_size / CONSOLE_BLOCK_SIZE; + bbp->lbn = (bs_start * blocksize) / CONSOLE_BLOCK_SIZE; + bbp->flags = 0; + + /* Compute the checksum */ + checksum = 0; + lbp = (u_int64_t*) bbp; + for (i = 0; i < CONSOLE_BLOCK_SIZE/8; ++i) { + checksum += lbp[i]; + } + bbp->chk_sum = checksum; + + if(big_endian) { + /* Need to flip the bootblock fields so they come out + * right on disk... + */ + bbp->count = (((u_int64_t) swap32(bbp->count & 0xffffffff) << 32) + | swap32(bbp->count >> 32)); + bbp->lbn = (((u_int64_t) swap32(bbp->lbn & 0xffffffff) << 32) + | swap32(bbp->lbn >> 32)); + bbp->flags = (((u_int64_t) swap32(bbp->flags & 0xffffffff) << 32) + | swap32(bbp->flags >> 32)); + bbp->chk_sum = (((u_int64_t) swap32(bbp->chk_sum & 0xffffffff) << 32) + | swap32(bbp->chk_sum >> 32)); + } + + ext2_write_bootblock((char *) bbp); + + ext2_iput(ip); + ext2_close(); + + printf("%d bytes written to %s\n", bootstrap_size, namebuf); + return 0; +} diff --git a/package/aboot/src/tools/elfencap.c b/package/aboot/src/tools/elfencap.c new file mode 100644 index 000000000..3e5f4b4b9 --- /dev/null +++ b/package/aboot/src/tools/elfencap.c @@ -0,0 +1,61 @@ +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include <sys/stat.h> + +#include <linux/elf.h> + + +int +main (int argc, char ** argv) +{ + int ifd; + ssize_t n; + char buf[8192]; + struct stat st; + struct { + struct elf64_hdr ehdr; + struct elf64_phdr phdr; + } h; + + ifd = open(argv[1], O_RDONLY); + if (ifd < 0) { + perror(argv[1]); + return 1; + } + + if (fstat(ifd, &st) < 0) { + perror(argv[1]); + return 1; + } + + memset(&h, 0, sizeof(h)); + + h.ehdr.e_ident[0] = 0x7f; + strcpy(h.ehdr.e_ident + 1, "ELF"); + h.ehdr.e_ident[EI_CLASS] = ELFCLASS64; + h.ehdr.e_ident[EI_DATA] = ELFDATA2LSB; + h.ehdr.e_ident[EI_VERSION] = EV_CURRENT; + h.ehdr.e_type = ET_EXEC; + h.ehdr.e_machine = EM_ALPHA; + h.ehdr.e_version = EV_CURRENT; + h.ehdr.e_entry = 0xfffffc0000310000; + h.ehdr.e_phnum = 1; + h.ehdr.e_phoff = (char *) &h.phdr - (char *) &h; + h.phdr.p_vaddr = 0xfffffc0000310000; + h.phdr.p_offset = sizeof(h); + h.phdr.p_filesz = st.st_size; + h.phdr.p_memsz = h.phdr.p_filesz; + + write(1, &h, sizeof(h)); + + while ((n = read(ifd, buf, sizeof(buf))) > 0) { + if (write(1, buf, n) != n) { + perror("short write"); + return 1; + } + } + return 0; +} diff --git a/package/aboot/src/tools/isomarkboot.c b/package/aboot/src/tools/isomarkboot.c new file mode 100644 index 000000000..ba01009fa --- /dev/null +++ b/package/aboot/src/tools/isomarkboot.c @@ -0,0 +1,239 @@ +/* + * isomarkboot.c + * + * This file is part of aboot, the SRM bootloader for Linux/Alpha + * Copyright (C) 1996 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. + */ +/* + * Making an ISO9660 filesystem bootable is straight-forward since all + * files are contiguous. + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <asm/fcntl.h> + +#include <config.h> +#include <isolib.h> +#include <iso.h> + +const char * prog_name; + +static int disk; + +void +__memcpy (void * dest, const void * src, size_t n) +{ + memcpy (dest, src, n); +} + +long +iso_dev_read (void * buf, long offset, long size) +{ + if (lseek(disk, offset, SEEK_SET) != offset) { + perror("lseek"); + return -1; + } + return read(disk, buf, size); +} + +/* Write a 64-bit quantity out into memory in LITTLE ENDIAN order */ +static void write_64 (unsigned char* out, unsigned long long in) +{ + out[0] = in & 0xFF; + out[1] = (in >> 8) & 0xFF; + out[2] = (in >> 16) & 0xFF; + out[3] = (in >> 24) & 0xFF; + out[4] = (in >> 32) & 0xFF; + out[5] = (in >> 40) & 0xFF; + out[6] = (in >> 48) & 0xFF; + out[7] = (in >> 56) & 0xFF; +} + +/* Read in a 64-bit LITTLE ENDIAN quantity */ +static unsigned long long read_64 (unsigned char *in) +{ + unsigned long long result = 0; + + result |= (unsigned long long) in[0]; + result |= (unsigned long long) in[1] << 8; + result |= (unsigned long long) in[2] << 16; + result |= (unsigned long long) in[3] << 24; + result |= (unsigned long long) in[4] << 32; + result |= (unsigned long long) in[5] << 40; + result |= (unsigned long long) in[6] << 48; + result |= (unsigned long long) in[7] << 56; + + return result; +} + +int +main (int argc, char ** argv) +{ + u_int64_t sector[512 / 8], sum; + struct iso_primary_descriptor vol_desc; + size_t nbytes, aboot_size; + off_t aboot_pos; + int i, aboot_fd; + int rootbin_fd; + off_t rootbin_pos; + char root_start[100]; + + prog_name = argv[0]; + + if (argc < 3 || argc > 4) { + fprintf(stderr, "usage: %s filesys path [root.bin]\n", prog_name); + exit(1); + } + disk = open(argv[1], O_RDWR); + if (disk < 0) { + perror(argv[1]); + exit(1); + } + + if (iso_read_super (0, 0) < 0) { + fprintf(stderr, "%s: cannot mount\n", argv[1]); + exit(1); + } + + aboot_fd = iso_open(argv[2]); + if (aboot_fd < 0) { + fprintf(stderr, "%s: file not found\n", argv[2]); + exit(1); + } + + { + struct stat buf; + iso_fstat(aboot_fd, &buf); + aboot_size = buf.st_size; + } + + aboot_pos = iso_map (aboot_fd, 0); + + printf("%s: %s is at offset %ld and is %lu bytes long\n", + prog_name, argv[2], aboot_pos, aboot_size); + + if (lseek(disk, 0, SEEK_SET) != 0) { + perror("lseek"); + return -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); + } + + strcpy((char *) sector, "Linux/Alpha aboot for ISO filesystem."); + write_64 ((unsigned char *) §or[60], aboot_size / 512);/* sector count */ + write_64 ((unsigned char *) §or[61], aboot_pos / 512); /* starting LBM */ + write_64 ((unsigned char *) §or[62], 0); /* flags */ + + /* update checksum: */ + sum = 0; + for (i = 0; i < 63; i++) + sum += read_64 ((unsigned char *) §or[i]); + + write_64 ((unsigned char *) §or[63], sum); + + if (lseek(disk, 0, SEEK_SET) != 0) { + perror("lseek"); + return -1; + } + + 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); + } + + if (argc < 4) + return 0; + + rootbin_fd = iso_open(argv[3]); + if (rootbin_fd < 0) { + fprintf(stderr, "%s: file not found\n", argv[3]); + exit(1); + } + + rootbin_pos = iso_map (rootbin_fd, 0); + iso_close(rootbin_fd); + + { + struct stat buf; + iso_fstat(rootbin_fd, &buf); + printf("%s: %s is at offset %ld and is %lu bytes long\n", + prog_name, argv[3], rootbin_pos, buf.st_size); + } + + + if (lseek(disk, 16*2048, SEEK_SET) != 16*2048) { + perror("lseek"); + return -1; + } + nbytes = read(disk, &vol_desc, sizeof(vol_desc)); + if (nbytes != sizeof(vol_desc)) { + if ((long) nbytes < 0) { + perror("read"); + } else { + fprintf(stderr, "%s: short read\n", prog_name); + } + exit(1); + } + + if (strncmp (vol_desc.id, ISO_STANDARD_ID, sizeof vol_desc.id) != 0) { + fprintf(stderr,"first volume descriptor has not an ISO_STANDARD_ID!!\n"); + exit(1); + } + if (isonum_711 (vol_desc.type) != ISO_VD_PRIMARY) { + fprintf(stderr,"first volume descriptor is not a primary one!!\n"); + exit(1); + } + if (rootbin_pos & 2047) { + fprintf(stderr,"erreur:rootbin_pos=%ld is not at a isoblock boundary\n",rootbin_pos); + exit(1); + } + sprintf(root_start,"ROOT START=%ld ",rootbin_pos/2048); + printf("writing %s in application_data of first volume descriptor\n", root_start); + memcpy(vol_desc.application_data,root_start,strlen(root_start)); + if (lseek(disk, 16*2048, SEEK_SET) != 16*2048) { + perror("lseek"); + return -1; + } + + nbytes = write(disk, &vol_desc, sizeof(vol_desc)); + if (nbytes != sizeof(vol_desc)) { + if ((long) nbytes < 0) { + perror("write"); + } else { + fprintf(stderr, "%s: short write\n", prog_name); + } + exit(1); + } + + return 0; +} diff --git a/package/aboot/src/tools/objstrip.c b/package/aboot/src/tools/objstrip.c new file mode 100644 index 000000000..19612644b --- /dev/null +++ b/package/aboot/src/tools/objstrip.c @@ -0,0 +1,260 @@ +/* + * arch/alpha/boot/tools/objstrip.c + * + * Strip the object file headers/trailers from an executable (ELF). + * + * Copyright (C) 1996 David Mosberger-Tang. + */ +/* + * Converts an ELF object file into a bootable file. The + * object file must be a OMAGIC file (i.e., data and bss follow immediatly + * behind the text). See DEC "Assembly Language Programmer's Guide" + * documentation for details. The SRM boot process is documented in + * the Alpha AXP Architecture Reference Manual, Second Edition by + * Richard L. Sites and Richard T. Witek. + */ +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> + +#include <sys/fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include <a.out.h> +#include <linux/coff.h> +#include <linux/param.h> +#include <string.h> + +#ifdef __ELF__ +# include <linux/elf.h> +# include <linux/version.h> +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) +# define elf_check_arch(x) ((x)->e_machine == EM_ALPHA) +# endif +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +# define aboot_elf_check_arch(e) elf_check_arch(e) +# else +# define aboot_elf_check_arch(e) elf_check_arch(e->e_machine) +# endif +#endif + +/* bootfile size must be multiple of BLOCK_SIZE: */ +#define BLOCK_SIZE 512 + +const char * prog_name; + + +void +usage (void) +{ + fprintf(stderr, + "usage: %s [-v] -p file primary\n" + " %s [-vb] file [secondary]\n", prog_name, prog_name); + exit(1); +} + + +int +main (int argc, char *argv[]) +{ + size_t nwritten, tocopy, n, mem_size, fil_size, pad = 0; + int fd, ofd, i, j, verbose = 0, primary = 0; + char buf[8192], *inname; + struct exec * aout; /* includes file & aout header */ + long offset; +#ifdef __ELF__ + struct elf64_hdr *elf; + struct elf64_phdr *elf_phdr; /* program header */ + unsigned long long e_entry; +#endif + + prog_name = argv[0]; + + for (i = 1; i < argc && argv[i][0] == '-'; ++i) { + for (j = 1; argv[i][j]; ++j) { + switch (argv[i][j]) { + case 'v': + verbose = ~verbose; + break; + + case 'b': + pad = BLOCK_SIZE; + break; + + case 'p': + primary = 1; /* make primary bootblock */ + break; + } + } + } + + if (i >= argc) { + usage(); + } + inname = argv[i++]; + + fd = open(inname, O_RDONLY); + if (fd == -1) { + perror("open"); + exit(1); + } + + ofd = 1; + if (i < argc) { + ofd = open(argv[i++], O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (fd == -1) { + perror("open"); + exit(1); + } + } + + if (primary) { + /* generate bootblock for primary loader */ + + unsigned long bb[64], sum = 0; + struct stat st; + off_t size; + int i; + + if (ofd == 1) { + usage(); + } + + if (fstat(fd, &st) == -1) { + perror("fstat"); + exit(1); + } + + size = (st.st_size + BLOCK_SIZE - 1) & ~(BLOCK_SIZE - 1); + memset(bb, 0, sizeof(bb)); + strcpy((char *) bb, "Linux SRM bootblock"); + bb[60] = size / BLOCK_SIZE; /* count */ + bb[61] = 1; /* starting sector # */ + bb[62] = 0; /* flags---must be 0 */ + for (i = 0; i < 63; ++i) { + sum += bb[i]; + } + bb[63] = sum; + if (write(ofd, bb, sizeof(bb)) != sizeof(bb)) { + perror("boot-block write"); + exit(1); + } + printf("%lu\n", size); + return 0; + } + + /* read and inspect exec header: */ + + if (read(fd, buf, sizeof(buf)) < 0) { + perror("read"); + exit(1); + } + +#ifdef __ELF__ + elf = (struct elf64_hdr *) buf; + + if (elf->e_ident[0] == 0x7f && strncmp(elf->e_ident + 1, "ELF", 3) == 0) { + if (elf->e_type != ET_EXEC) { + fprintf(stderr, "%s: %s is not an ELF executable\n", + prog_name, inname); + exit(1); + } + if (!aboot_elf_check_arch(elf)) { + fprintf(stderr, "%s: is not for this processor (e_machine=%d)\n", + prog_name, elf->e_machine); + exit(1); + } + if (elf->e_phnum != 1) { + fprintf(stderr, + "%s: %d program headers (forgot to link with -N?)\n", + prog_name, elf->e_phnum); + } + + e_entry = elf->e_entry; + + lseek(fd, elf->e_phoff, SEEK_SET); + if (read(fd, buf, sizeof(*elf_phdr)) != sizeof(*elf_phdr)) { + perror("read"); + exit(1); + } + + elf_phdr = (struct elf64_phdr *) buf; + offset = elf_phdr->p_offset; + mem_size = elf_phdr->p_memsz; + fil_size = elf_phdr->p_filesz; + + /* work around ELF bug: */ + if (elf_phdr->p_vaddr < e_entry) { + unsigned long delta = e_entry - elf_phdr->p_vaddr; + offset += delta; + mem_size -= delta; + fil_size -= delta; + elf_phdr->p_vaddr += delta; + } + + if (verbose) { + fprintf(stderr, "%s: extracting %#016lx-%#016lx (at %lx)\n", + prog_name, (long) elf_phdr->p_vaddr, + elf_phdr->p_vaddr + fil_size, offset); + } + } +#endif + + if (lseek(fd, offset, SEEK_SET) != offset) { + perror("lseek"); + exit(1); + } + + if (verbose) { + fprintf(stderr, "%s: copying %lu byte from %s\n", + prog_name, (unsigned long) fil_size, inname); + } + + tocopy = fil_size; + while (tocopy > 0) { + n = tocopy; + if (n > sizeof(buf)) { + n = sizeof(buf); + } + tocopy -= n; + if ((size_t) read(fd, buf, n) != n) { + perror("read"); + exit(1); + } + do { + nwritten = write(ofd, buf, n); + if ((ssize_t) nwritten == -1) { + perror("write"); + exit(1); + } + n -= nwritten; + } while (n > 0); + } + + if (pad) { + mem_size = ((mem_size + pad - 1) / pad) * pad; + } + + tocopy = mem_size - fil_size; + if (tocopy > 0) { + fprintf(stderr, + "%s: zero-filling bss and aligning to %lu with %lu bytes\n", + prog_name, pad, (unsigned long) tocopy); + + memset(buf, 0x00, sizeof(buf)); + do { + n = tocopy; + if (n > sizeof(buf)) { + n = sizeof(buf); + } + nwritten = write(ofd, buf, n); + if ((ssize_t) nwritten == -1) { + perror("write"); + exit(1); + } + tocopy -= nwritten; + } while (tocopy > 0); + } + return 0; +} diff --git a/package/aboot/src/utils.c b/package/aboot/src/utils.c new file mode 100644 index 000000000..e2f559c30 --- /dev/null +++ b/package/aboot/src/utils.c @@ -0,0 +1,292 @@ +#include <linux/kernel.h> + +#include "hwrpb.h" +#include <linux/version.h> +#include "system.h" + +#include "string.h" + +#include <stdarg.h> +#include <errno.h> + +#include "aboot.h" +#include "cons.h" + +unsigned long free_mem_ptr = 0; + + +int printf(const char *fmt, ...) +{ + static char buf[1024]; + va_list args; + long len, num_lf; + char *src, *dst; + + va_start(args, fmt); + len = vsprintf(buf, fmt, args); + va_end(args); + + /* count number of linefeeds in string: */ + + num_lf = 0; + for (src = buf; *src; ++src) { + if (*src == '\n') { + ++num_lf; + } + } + + if (num_lf) { + /* expand each linefeed into carriage-return/linefeed: */ + for (dst = src + num_lf; src >= buf; ) { + if (*src == '\n') { + *dst-- = '\r'; + } + *dst-- = *src--; + } + } + return cons_puts(buf, len + num_lf); +} + + +/* + * Find a physical address of a virtual object.. + * + * This is easy using the virtual page table address. + */ +struct pcb_struct *find_pa(unsigned long *vptb, struct pcb_struct *pcb) +{ + unsigned long address = (unsigned long) pcb; + unsigned long result; + + result = vptb[address >> 13]; + result >>= 32; + result <<= 13; + result |= address & 0x1fff; + return (struct pcb_struct *) result; +} + +/* + * This function moves into OSF/1 pal-code, and has a temporary + * PCB for that. The kernel proper should replace this PCB with + * the real one as soon as possible. + * + * The page table muckery in here depends on the fact that the boot + * code has the L1 page table identity-map itself in the second PTE + * in the L1 page table. Thus the L1-page is virtually addressable + * itself (through three levels) at virtual address 0x200802000. + * + * As we don't want it there anyway, we also move the L1 self-map + * up as high as we can, so that the last entry in the L1 page table + * maps the page tables. + * + * As a result, the OSF/1 pal-code will instead use a virtual page table + * map located at 0xffffffe00000000. + */ +#define pcb_va ((struct pcb_struct *) 0x20000000) +#define old_vptb (0x0000000200000000UL) +#define new_vptb (0xfffffffe00000000UL) +void pal_init(void) +{ + unsigned long i, rev, sum; + unsigned long *L1, *l; + struct percpu_struct * percpu; + struct pcb_struct * pcb_pa; + + /* Find the level 1 page table and duplicate it in high memory */ + L1 = (unsigned long *) 0x200802000UL; /* (1<<33 | 1<<23 | 1<<13) */ + L1[1023] = L1[1]; + + percpu = (struct percpu_struct *) (INIT_HWRPB->processor_offset + + (unsigned long) INIT_HWRPB), + pcb_va->ksp = 0; + pcb_va->usp = 0; + pcb_va->ptbr = L1[1] >> 32; + pcb_va->asn = 0; + pcb_va->pcc = 0; + pcb_va->unique = 0; + pcb_va->flags = 1; + pcb_pa = find_pa((unsigned long *) old_vptb, pcb_va); + printf("aboot: switching to OSF/1 PALcode"); + /* + * a0 = 2 (OSF) + * a1 = return address, but we give the asm the virtual addr of the PCB + * a2 = physical addr of PCB + * a3 = new virtual page table pointer + * a4 = KSP (but we give it 0, asm sets it) + */ + i = switch_to_osf_pal( + 2, + pcb_va, + pcb_pa, + new_vptb, + 0); + if (i) { + printf("---failed, code %ld\n", i); + halt(); + } + rev = percpu->pal_revision = percpu->palcode_avail[2]; + + INIT_HWRPB->vptb = new_vptb; + + /* update checksum: */ + sum = 0; + for (l = (unsigned long *) INIT_HWRPB; l < (unsigned long *) &INIT_HWRPB->chksum; ++l) + sum += *l; + INIT_HWRPB->chksum = sum; + + printf(" version %ld.%ld\n", (rev >> 8) & 0xff, rev & 0xff); + /* remove the old virtual page-table mapping */ + L1[1] = 0; + tbia(); +} + +int check_memory(unsigned long start, unsigned long size) +{ + unsigned long phys_start, start_pfn, end_pfn; + struct memclust_struct *cluster; + struct memdesc_struct *memdesc; + int i; + + /* + * Get the physical address start. + * If 43-bit superpage is being used (VA<63:41> = 0x7ffffe) + * then the "correct" translation across all implementations is to + * sign extend the VA from bit 40. Othewise, assume it's already a + * physical address. + */ + phys_start = start; + if (((long)phys_start >> 41) == -2) + phys_start = (long)((start) << (64-41)) >> (64-41); + start_pfn = phys_start >> PAGE_SHIFT; + end_pfn = (phys_start + size - 1) >> PAGE_SHIFT; + + memdesc = (struct memdesc_struct *) + (INIT_HWRPB->mddt_offset + (unsigned long) INIT_HWRPB); + for (cluster = memdesc->cluster, i = 0; + i < memdesc->numclusters; + i++, cluster++) { + if ((cluster->start_pfn > end_pfn) || + ((cluster->start_pfn + cluster->numpages) <= start_pfn)) + continue; /* no overlap */ + + /* + * This cluster overlaps the memory we're checking, check + * the usage: + * bit 0 is console/PAL reserved + * bit 1 is non-volatile + * If either is set, it's a problem, return -EBUSY + */ + if (cluster->usage & 3) + return -EBUSY; /* reserved */ + + /* + * It's not reserved, take it out of what we're checking + */ + if (cluster->start_pfn <= end_pfn) + end_pfn = cluster->start_pfn - 1; + if ((cluster->start_pfn + cluster->numpages) > start_pfn) + start_pfn = cluster->start_pfn + cluster->numpages; + + if (end_pfn < start_pfn) + return 0; /* all found, ok */ + } + + /* no conflict, but not all memory found */ + return -ENOMEM; +} + +unsigned long memory_end(void) +{ + int i; + unsigned long high = 0; + struct memclust_struct *cluster; + struct memdesc_struct *memdesc; + + memdesc = (struct memdesc_struct *) + (INIT_HWRPB->mddt_offset + (unsigned long) INIT_HWRPB); + cluster = memdesc->cluster; + for (i = memdesc->numclusters; i > 0; i--, cluster++) { + unsigned long tmp; + + if (cluster->usage != 0) { + /* this is a PAL or NVRAM cluster (not for the OS) */ + continue; + } + + tmp = (cluster->start_pfn + cluster->numpages) << page_shift; + if (tmp > high) { + high = tmp; + } + } + return page_offset + high; +} + + +static void error(char *x) +{ + printf("%s\n", x); + _longjmp(jump_buffer, 1); +} + + +void unzip_error(char *x) +{ + printf("\nunzip: "); + error(x); +} + + +void *malloc(size_t size) +{ + if (!free_mem_ptr) { + free_mem_ptr = memory_end(); + } + + free_mem_ptr = (free_mem_ptr - size) & ~(sizeof(long) - 1); + if ((char*) free_mem_ptr <= dest_addr + INIT_HWRPB->pagesize) { + error("\nout of memory"); + } + return (void*) free_mem_ptr; +} + + +void free(void *where) +{ + /* don't care */ +} + + +void +getline (char *buf, int maxlen) +{ + int len=0; + char c; + + do { + c = cons_getchar(); + switch (c) { + case 0: + case 10: + case 13: + break; + case 8: + case 127: + if (len > 0) { + --len; + cons_putchar(8); + cons_putchar(' '); + cons_putchar(8); + } + break; + + default: + if (len < maxlen-1 && c >= ' ') { + buf[len] = c; + len++; + cons_putchar(c); + } + break; + } + } while (c != 13 && c != 10); + buf[len] = 0; +} diff --git a/package/aboot/src/zip/gzip.h b/package/aboot/src/zip/gzip.h new file mode 100644 index 000000000..89340c73b --- /dev/null +++ b/package/aboot/src/zip/gzip.h @@ -0,0 +1,96 @@ +/* gzip.h -- common declarations for all gzip modules + * Copyright (C) 1992-1993 Jean-loup Gailly. + * This is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License, see the file COPYING. + */ +#ifndef GZIP_H +#define GZIP_H + +#include "string.h" + +#define memzero(s, n) memset ((s), 0, (n)) + +/* Return codes from gzip */ +#define OK 0 +#define ERROR 1 +#define WARNING 2 + +/* Compression methods (see algorithm.doc) */ +#define STORED 0 +#define COMPRESSED 1 +#define PACKED 2 +/* + * methods 3 to 7 reserved + */ +#define DEFLATED 8 + +extern unsigned long bytes_out; /* # of uncompressed bytes */ +extern int method; /* compression method */ + +#define INBUFSIZ 0x20000 /* input buffer size */ +#define WSIZE 0x8000 /* window size--must be a power of two, and */ + /* at least 32K for zip's deflate method */ + +unsigned char *inbuf; /* input buffer */ +unsigned char *window; /* sliding window and suffix table (unlzw) */ + +extern unsigned insize; /* valid bytes in inbuf */ +extern unsigned inptr; /* index of next byte to be processed in inbuf */ +extern unsigned outcnt; /* bytes in output buffer */ + +#define GZIP_MAGIC "\037\213" /* Magic header for gzip files, 1F 8B */ +#define OLD_GZIP_MAGIC "\037\236" /* Magic header for gzip 0.5 = freeze 1.x */ +#define PKZIP_MAGIC "PK\003\004" /* Magic header for pkzip files */ +#define PACK_MAGIC "\037\036" /* Magic header for packed files */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ +#define RESERVED 0xC0 /* bit 6,7: reserved */ + +/* internal file attribute */ +#define UNKNOWN (-1) +#define BINARY 0 +#define ASCII 1 + + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST (WSIZE-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + +#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) +#define put_char(c) {window[outcnt++]=(unsigned char)(c); if (outcnt==WSIZE)\ + flush_window();} + +/* Macros for getting two-byte and four-byte header values */ +#define SH(p) ((unsigned short)(unsigned char)((p)[0]) | ((unsigned short)(unsigned char)((p)[1]) << 8)) +#define LG(p) ((unsigned long)(SH(p)) | ((unsigned long)(SH((p)+2)) << 16)) + +/* in unzip.c */ +extern void unzip (int in, int out); + +/* in misc.c: */ +extern unsigned long updcrc (unsigned char *s, unsigned n); +extern void clear_bufs (void); +extern int fill_inbuf (void); +extern void flush_window (void); +extern void unzip_error (char *m); + +/* in inflate.c */ +extern int inflate (void); + +#endif /* GZIP_H */ diff --git a/package/aboot/src/zip/inflate.c b/package/aboot/src/zip/inflate.c new file mode 100644 index 000000000..bed8596c7 --- /dev/null +++ b/package/aboot/src/zip/inflate.c @@ -0,0 +1,827 @@ +/* + * inflate.c -- Not copyrighted 1992 by Mark Adler + * version c10p1, 10 January 1993 + */ +/* + * Adapted for booting Linux by Hannu Savolainen 1993 + * based on gzip-1.0.3 + */ + +#include "gzip.h" +#define slide window + +#include <linux/types.h> + +extern void *malloc(size_t size); +extern void free(void *ptr); + +#if 0 +#define DEBG(x) {register long sp asm("30"); \ + printf("%s (sp=%lx)\n", x, sp);} +#define DEBG1(x) {register long sp asm("30"); \ + printf(" %s (sp=%lx)\n", x, sp);} +#else +#define DEBG(x) +#define DEBG1(x) +#endif + + +struct huft { + unsigned char e; /* number of extra bits or operation */ + unsigned char b; /* number of bits in this code or subcode */ + union { + unsigned short n; /* literal, length base, or distance base */ + struct huft *t; /* pointer to next level of table */ + } v; +}; + + +/* Function prototypes */ +int huft_build (unsigned *, unsigned, unsigned, unsigned short *, + unsigned short *, struct huft **, int *); +int huft_free (struct huft *); +int inflate_codes (struct huft *, struct huft *, int, int); +int inflate_stored (void); +int inflate_fixed (void); +int inflate_dynamic (void); +int inflate_block (int *); +int inflate (void); + + +#define wp outcnt +#define flush_output(w) (wp=(w),flush_window()) + +/* Tables for deflate from PKZIP's appnote.txt. */ +static unsigned border[] = { + /* Order of the bit length code lengths */ + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 +}; + +static unsigned short cplens[] = { + /* Copy lengths for literal codes 257..285 */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 +}; + +/* note: see note #13 above about the 258 in this list. */ +static unsigned short cplext[] = { + /* Extra bits for literal codes 257..285 */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99 /* 99==invalid */ +}; + +static unsigned short cpdist[] = { + /* Copy offsets for distance codes 0..29 */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577 +}; + +static unsigned short cpdext[] = { + /* Extra bits for distance codes */ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13 +}; + + +unsigned long bb; /* bit buffer */ +unsigned bk; /* bits in bit buffer */ + +unsigned short mask_bits[] = { + 0x0000, + 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff +}; + +#define NEXTBYTE() (unsigned char)get_byte() +#define NEEDBITS(n) {while(k<(n)){b|=((unsigned long)NEXTBYTE())<<k;k+=8;}} +#define DUMPBITS(n) {b>>=(n);k-=(n);} + +int lbits = 9; /* bits in base literal/length lookup table */ +int dbits = 6; /* bits in base distance lookup table */ + + +/* + * If BMAX needs to be larger than 16, then h and x[] should be + * unsigned long. + */ +#define BMAX 16 /* maximum bit length of any code (16 for explode) */ +#define N_MAX 288 /* maximum number of codes in any set */ + + +unsigned hufts; /* track memory usage */ + + +/* + * Given a list of code lengths and a maximum table size, make a set + * of tables to decode that set of codes. Return zero on success, one + * if the given code set is incomplete (the tables are still built in + * this case), two if the input is invalid (all zero length codes or + * an oversubscribed set of lengths), and three if not enough + * memory. + */ +int +huft_build(b, n, s, d, e, t, m) +unsigned *b; /* code lengths in bits (all assumed <= BMAX) */ +unsigned n; /* number of codes (assumed <= N_MAX) */ +unsigned s; /* number of simple-valued codes (0..s-1) */ +unsigned short *d; /* list of base values for non-simple codes */ +unsigned short *e; /* list of extra bits for non-simple codes */ +struct huft **t; /* result: starting table */ +int *m; /* maximum lookup bits, returns actual */ +{ + unsigned a; /* counter for codes of length k */ + unsigned c[BMAX+1]; /* bit length count table */ + unsigned f; /* i repeats in table every f entries */ + int g; /* maximum code length */ + int h; /* table level */ + register unsigned i; /* counter, current code */ + register unsigned j; /* counter */ + register int k; /* number of bits in current code */ + int l; /* bits per table (returned in m) */ + register unsigned *p; /* pointer into c[], b[], or v[] */ + register struct huft *q; /* points to current table */ + struct huft r; /* table entry for structure assignment */ + struct huft *u[BMAX]; /* table stack */ + unsigned v[N_MAX]; /* values in order of bit length */ + register int w; /* bits before this table == (l * h) */ + unsigned x[BMAX+1]; /* bit offsets, then code stack */ + unsigned *xp; /* pointer into x */ + int y; /* number of dummy codes added */ + unsigned z; /* number of entries in current table */ + +DEBG("huft1 "); + + /* Generate counts for each bit length */ + memzero(c, sizeof(c)); + p = b; i = n; + do { + c[*p++]++; /* assume all entries <= BMAX */ + } while (--i); + if (c[0] == n) /* null input--all zero length codes */ + { + *t = (struct huft *)NULL; + *m = 0; + return 0; + } + +DEBG("huft2 "); + + /* Find minimum and maximum length, bound *m by those */ + l = *m; + for (j = 1; j <= BMAX; j++) + if (c[j]) + break; + k = j; /* minimum code length */ + if ((unsigned)l < j) + l = j; + for (i = BMAX; i; i--) + if (c[i]) + break; + g = i; /* maximum code length */ + if ((unsigned)l > i) + l = i; + *m = l; + +DEBG("huft3 "); + + /* Adjust last length count to fill out codes, if needed */ + for (y = 1 << j; j < i; j++, y <<= 1) + if ((y -= c[j]) < 0) + return 2; /* bad input: more codes than bits */ + if ((y -= c[i]) < 0) + return 2; + c[i] += y; + +DEBG("huft4 "); + + /* Generate starting offsets into the value table for each length */ + x[1] = j = 0; + p = c + 1; xp = x + 2; + while (--i) { /* note that i == g from above */ + *xp++ = (j += *p++); + } + +DEBG("huft5 "); + + /* Make a table of values in order of bit lengths */ + p = b; i = 0; + do { + if ((j = *p++) != 0) + v[x[j]++] = i; + } while (++i < n); + +DEBG("h6 "); + + /* Generate the Huffman codes and for each, make the table entries */ + x[0] = i = 0; /* first Huffman code is zero */ + p = v; /* grab values in bit order */ + h = -1; /* no tables yet--level -1 */ + w = -l; /* bits decoded == (l * h) */ + u[0] = (struct huft *)NULL; /* just to keep compilers happy */ + q = (struct huft *)NULL; /* ditto */ + z = 0; /* ditto */ +DEBG("h6a "); + + /* go through the bit lengths (k already is bits in shortest code) */ + for (; k <= g; k++) + { +DEBG("h6b "); + a = c[k]; + while (a--) + { +DEBG("h6b1 "); + /* here i is the Huffman code of length k bits for value *p */ + /* make tables up to required level */ + while (k > w + l) + { +DEBG1("1 "); + h++; + w += l; /* previous table always l bits */ + + /* compute minimum size table less than or equal to l bits */ + z = (z = g - w) > (unsigned)l ? l : z; /* upper limit on table size */ + if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ + { /* too few codes for k-w bit table */ +DEBG1("2 "); + f -= a + 1; /* deduct codes from patterns left */ + xp = c + k; + while (++j < z) /* try smaller tables up to z bits */ + { + if ((f <<= 1) <= *++xp) + break; /* enough codes to use up j bits */ + f -= *xp; /* else deduct codes from patterns */ + } + } +DEBG1("3 "); + z = 1 << j; /* table entries for j-bit table */ + + /* allocate and link in new table */ + q = (struct huft *)malloc((z + 1)*sizeof(struct huft)); +DEBG1("4 "); + hufts += z + 1; /* track memory usage */ + *t = q + 1; /* link to list for huft_free() */ + *(t = &(q->v.t)) = (struct huft *)NULL; + u[h] = ++q; /* table starts after link */ + +DEBG1("5 "); + /* connect to last table, if there is one */ + if (h) + { + x[h] = i; /* save pattern for backing up */ + r.b = (unsigned char)l; /* bits to dump before this table */ + r.e = (unsigned char)(16 + j); /* bits in this table */ + r.v.t = q; /* pointer to this table */ + j = i >> (w - l); /* (get around Turbo C bug) */ + u[h-1][j] = r; /* connect to last table */ + } +DEBG1("6 "); + } +DEBG("h6c "); + + /* set up table entry in r */ + r.b = (unsigned char)(k - w); + if (p >= v + n) + r.e = 99; /* out of values--invalid code */ + else if (*p < s) + { + r.e = (unsigned char)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */ + r.v.n = *p++; /* simple code is just the value */ + } + else + { + r.e = (unsigned char)e[*p - s]; /* non-simple--look up in lists */ + r.v.n = d[*p++ - s]; + } +DEBG("h6d "); + + /* fill code-like entries with r */ + f = 1 << (k - w); + for (j = i >> w; j < z; j += f) + q[j] = r; + + /* backwards increment the k-bit code i */ + for (j = 1 << (k - 1); i & j; j >>= 1) + i ^= j; + i ^= j; + + /* backup over finished tables */ + while ((i & ((1 << w) - 1)) != x[h]) + { + h--; /* don't need to update q */ + w -= l; + } +DEBG("h6e "); + } +DEBG("h6f "); + } + +DEBG("huft7 "); + + /* Return true (1) if we were given an incomplete table */ + return y != 0 && g != 1; +} + + + +int huft_free(t) +struct huft *t; /* table to free */ +/* Free the malloc'ed tables built by huft_build(), which makes a linked + list of the tables it made, with the links in a dummy first entry of + each table. */ +{ + register struct huft *p, *q; + + + /* Go through linked list, freeing from the malloced (t[-1]) address. */ + p = t; + while (p != (struct huft *)NULL) + { + q = (--p)->v.t; + free(p); + p = q; + } + return 0; +} + + +int inflate_codes(tl, td, bl, bd) +struct huft *tl, *td; /* literal/length and distance decoder tables */ +int bl, bd; /* number of bits decoded by tl[] and td[] */ +/* inflate (decompress) the codes in a deflated (compressed) block. + Return an error code or zero if it all goes ok. */ +{ + register unsigned e; /* table entry flag/number of extra bits */ + unsigned n, d; /* length and index for copy */ + unsigned w; /* current window position */ + struct huft *t; /* pointer to table entry */ + unsigned ml, md; /* masks for bl and bd bits */ + register unsigned long b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + + /* make local copies of globals */ + b = bb; /* initialize bit buffer */ + k = bk; + w = wp; /* initialize window position */ + + /* inflate the coded data */ + ml = mask_bits[bl]; /* precompute masks for speed */ + md = mask_bits[bd]; + for (;;) /* do until end of block */ + { + NEEDBITS((unsigned)bl) + if ((e = (t = tl + ((unsigned)b & ml))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + if (e == 16) /* then it's a literal */ + { + slide[w++] = (unsigned char)t->v.n; + if (w == WSIZE) + { + flush_output(w); + w = 0; + } + } + else /* it's an EOB or a length */ + { + /* exit if end of block */ + if (e == 15) + break; + + /* get length of block to copy */ + NEEDBITS(e) + n = t->v.n + ((unsigned)b & mask_bits[e]); + DUMPBITS(e); + + /* decode distance of block to copy */ + NEEDBITS((unsigned)bd) + if ((e = (t = td + ((unsigned)b & md))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + NEEDBITS(e) + d = w - t->v.n - ((unsigned)b & mask_bits[e]); + DUMPBITS(e) + + /* do the copy */ + do { + n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e); +#if !defined(NOMEMCPY) && !defined(DEBUG) + if (w - d >= e) /* (this test assumes unsigned comparison) */ + { + memcpy(slide + w, slide + d, e); + w += e; + d += e; + } + else /* do it slow to avoid memcpy() overlap */ +#endif /* !NOMEMCPY */ + do { + slide[w++] = slide[d++]; + } while (--e); + if (w == WSIZE) + { + flush_output(w); + w = 0; + } + } while (n); + } + } + + + /* restore the globals from the locals */ + wp = w; /* restore global window pointer */ + bb = b; /* restore global bit buffer */ + bk = k; + + /* done */ + return 0; +} + + + +int inflate_stored() +/* "decompress" an inflated type 0 (stored) block. */ +{ + unsigned n; /* number of bytes in block */ + unsigned w; /* current window position */ + register unsigned long b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + +DEBG("<stor"); + + /* make local copies of globals */ + b = bb; /* initialize bit buffer */ + k = bk; + w = wp; /* initialize window position */ + + + /* go to byte boundary */ + n = k & 7; + DUMPBITS(n); + + + /* get the length and its complement */ + NEEDBITS(16) + n = ((unsigned)b & 0xffff); + DUMPBITS(16) + NEEDBITS(16) + if (n != (unsigned)((~b) & 0xffff)) + return 1; /* error in compressed data */ + DUMPBITS(16) + + + /* read and output the compressed data */ + while (n--) + { + NEEDBITS(8) + slide[w++] = (unsigned char)b; + if (w == WSIZE) + { + flush_output(w); + w = 0; + } + DUMPBITS(8) + } + + + /* restore the globals from the locals */ + wp = w; /* restore global window pointer */ + bb = b; /* restore global bit buffer */ + bk = k; + + DEBG(">"); + return 0; +} + + + +int inflate_fixed() +/* decompress an inflated type 1 (fixed Huffman codes) block. We should + either replace this with a custom decoder, or at least precompute the + Huffman tables. */ +{ + int i; /* temporary variable */ + struct huft *tl; /* literal/length code table */ + struct huft *td; /* distance code table */ + int bl; /* lookup bits for tl */ + int bd; /* lookup bits for td */ + unsigned l[288]; /* length list for huft_build */ + +DEBG("<fix"); + + /* set up literal table */ + for (i = 0; i < 144; i++) + l[i] = 8; + for (; i < 256; i++) + l[i] = 9; + for (; i < 280; i++) + l[i] = 7; + for (; i < 288; i++) /* make a complete, but wrong code set */ + l[i] = 8; + bl = 7; + if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl)) != 0) + return i; + + + /* set up distance table */ + for (i = 0; i < 30; i++) /* make an incomplete code set */ + l[i] = 5; + bd = 5; + if ((i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd)) > 1) + { + huft_free(tl); + + DEBG(">"); + return i; + } + + + /* decompress until an end-of-block code */ + if (inflate_codes(tl, td, bl, bd)) + return 1; + + + /* free the decoding tables, return */ + huft_free(tl); + huft_free(td); + return 0; +} + + + +int inflate_dynamic() +/* decompress an inflated type 2 (dynamic Huffman codes) block. */ +{ + int i; /* temporary variables */ + unsigned j; + unsigned l; /* last length */ + unsigned m; /* mask for bit lengths table */ + unsigned n; /* number of lengths to get */ + struct huft *tl; /* literal/length code table */ + struct huft *td; /* distance code table */ + int bl; /* lookup bits for tl */ + int bd; /* lookup bits for td */ + unsigned nb; /* number of bit length codes */ + unsigned nl; /* number of literal/length codes */ + unsigned nd; /* number of distance codes */ +#ifdef PKZIP_BUG_WORKAROUND + unsigned ll[288+32]; /* literal/length and distance code lengths */ +#else + unsigned ll[286+30]; /* literal/length and distance code lengths */ +#endif + register unsigned long b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + +DEBG("<dyn"); + + /* make local bit buffer */ + b = bb; + k = bk; + + + /* read in table lengths */ + NEEDBITS(5) + nl = 257 + ((unsigned)b & 0x1f); /* number of literal/length codes */ + DUMPBITS(5) + NEEDBITS(5) + nd = 1 + ((unsigned)b & 0x1f); /* number of distance codes */ + DUMPBITS(5) + NEEDBITS(4) + nb = 4 + ((unsigned)b & 0xf); /* number of bit length codes */ + DUMPBITS(4) +#ifdef PKZIP_BUG_WORKAROUND + if (nl > 288 || nd > 32) +#else + if (nl > 286 || nd > 30) +#endif + return 1; /* bad lengths */ + +DEBG("dyn1 "); + + /* read in bit-length-code lengths */ + for (j = 0; j < nb; j++) + { + NEEDBITS(3) + ll[border[j]] = (unsigned)b & 7; + DUMPBITS(3) + } + for (; j < 19; j++) + ll[border[j]] = 0; + +DEBG("dyn2 "); + + /* build decoding table for trees--single level, 7 bit lookup */ + bl = 7; + if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0) + { + if (i == 1) + huft_free(tl); + return i; /* incomplete code set */ + } + +DEBG("dyn3 "); + + /* read in literal and distance code lengths */ + n = nl + nd; + m = mask_bits[bl]; + i = l = 0; + while ((unsigned)i < n) + { + NEEDBITS((unsigned)bl) + j = (td = tl + ((unsigned)b & m))->b; + DUMPBITS(j) + j = td->v.n; + if (j < 16) /* length of code in bits (0..15) */ + ll[i++] = l = j; /* save last length in l */ + else if (j == 16) /* repeat last length 3 to 6 times */ + { + NEEDBITS(2) + j = 3 + ((unsigned)b & 3); + DUMPBITS(2) + if ((unsigned)i + j > n) + return 1; + while (j--) + ll[i++] = l; + } + else if (j == 17) /* 3 to 10 zero length codes */ + { + NEEDBITS(3) + j = 3 + ((unsigned)b & 7); + DUMPBITS(3) + if ((unsigned)i + j > n) + return 1; + while (j--) + ll[i++] = 0; + l = 0; + } + else /* j == 18: 11 to 138 zero length codes */ + { + NEEDBITS(7) + j = 11 + ((unsigned)b & 0x7f); + DUMPBITS(7) + if ((unsigned)i + j > n) + return 1; + while (j--) + ll[i++] = 0; + l = 0; + } + } + +DEBG("dyn4 "); + + /* free decoding table for trees */ + huft_free(tl); + +DEBG("dyn5 "); + + /* restore the global bit buffer */ + bb = b; + bk = k; + +DEBG("dyn5a "); + + /* build the decoding tables for literal/length and distance codes */ + bl = lbits; + if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0) + { +DEBG("dyn5b "); + if (i == 1) { + unzip_error("incomplete literal tree"); + huft_free(tl); + } + return i; /* incomplete code set */ + } +DEBG("dyn5c "); + bd = dbits; + if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0) + { +DEBG("dyn5d "); + if (i == 1) { + unzip_error("incomplete distance tree"); +#ifdef PKZIP_BUG_WORKAROUND + i = 0; + } +#else + huft_free(td); + } + huft_free(tl); + return i; /* incomplete code set */ +#endif + } + +DEBG("dyn6 "); + + /* decompress until an end-of-block code */ + if (inflate_codes(tl, td, bl, bd)) + return 1; + +DEBG("dyn7 "); + + /* free the decoding tables, return */ + huft_free(tl); + huft_free(td); + +DEBG(">"); + return 0; +} + + + +int inflate_block(e) +int *e; /* last block flag */ +/* decompress an inflated block */ +{ + unsigned t; /* block type */ + register unsigned long b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + DEBG("<blk"); + + /* make local bit buffer */ + b = bb; + k = bk; + + + /* read in last block bit */ + NEEDBITS(1) + *e = (int)b & 1; + DUMPBITS(1) + + + /* read in block type */ + NEEDBITS(2) + t = (unsigned)b & 3; + DUMPBITS(2) + + + /* restore the global bit buffer */ + bb = b; + bk = k; + + /* inflate that block type */ + if (t == 2) + return inflate_dynamic(); + if (t == 0) + return inflate_stored(); + if (t == 1) + return inflate_fixed(); + + DEBG(">"); + + /* bad block type */ + return 2; +} + + + +int inflate() +/* decompress an inflated entry */ +{ + int e; /* last block flag */ + int r; /* result code */ + unsigned h; /* maximum struct huft's malloc'ed */ + + + /* initialize window, bit buffer */ + wp = 0; + bk = 0; + bb = 0; + + + /* decompress until the last block */ + h = 0; + do { + hufts = 0; + if ((r = inflate_block(&e)) != 0) + return r; + if (hufts > h) + h = hufts; + } while (!e); + + /* Undo too much lookahead. The next read will be byte aligned so we + * can discard unused bits in the last meaningful byte. + */ + while (bk >= 8) { + bk -= 8; + inptr--; + } + + /* flush out slide */ + flush_output(wp); + + /* return success */ + return 0; +} diff --git a/package/aboot/src/zip/misc.c b/package/aboot/src/zip/misc.c new file mode 100644 index 000000000..ce5c339c2 --- /dev/null +++ b/package/aboot/src/zip/misc.c @@ -0,0 +1,316 @@ +/* + * misc.c + * + * This is a collection of several routines from gzip-1.0.3 + * adapted for Linux. + * + * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 + * puts by Nick Holloway 1993 + * + * Adapted to Linux/Alpha boot by David Mosberger (davidm@cs.arizona.edu). + */ +#include <linux/kernel.h> + +#include <stddef.h> +typedef __kernel_ssize_t ssize_t; + +#include "aboot.h" +#include "bootfs.h" +#include "setjmp.h" +#include "utils.h" +#include "gzip.h" + + +unsigned char *inbuf; +unsigned char *window; +unsigned outcnt; +unsigned insize; +unsigned inptr; +unsigned long bytes_out; +int method; + +static int block_number = 0; +static unsigned long crc_32_tab[256]; +static int input_fd = -1; +static int chunk; /* current segment */ +size_t file_offset; + +void +makecrc(void) +{ + /* Not copyrighted 1990 Mark Adler */ + unsigned long c; /* crc shift register */ + unsigned long e; /* polynomial exclusive-or pattern */ + int i; /* counter for all possible eight bit values */ + int k; /* byte being shifted into crc apparatus */ + + /* terms of polynomial defining this crc (except x^32): */ + static int p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* Make exclusive-or pattern from polynomial */ + e = 0; + for (i = 0; i < (int) (sizeof(p)/sizeof(int)); i++) + e |= 1L << (31 - p[i]); + + crc_32_tab[0] = 0; + + for (i = 1; i < 256; i++) { + c = 0; + for (k = i | 256; k != 1; k >>= 1) { + c = c & 1 ? (c >> 1) ^ e : c >> 1; + if (k & 1) + c ^= e; + } + crc_32_tab[i] = c; + } +} + + +/* + * Run a set of bytes through the crc shift register. If s is a NULL + * pointer, then initialize the crc shift register contents instead. + * Return the current crc in either case. + * + * Input: + * S pointer to bytes to pump through. + * N number of bytes in S[]. + */ +unsigned long +updcrc(unsigned char *s, unsigned n) +{ + register unsigned long c; + static unsigned long crc = 0xffffffffUL; /* shift register contents */ + + if (!s) { + c = 0xffffffffL; + } else { + c = crc; + while (n--) { + c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8); + } + } + crc = c; + return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */ +} + + +/* + * Clear input and output buffers + */ +void +clear_bufs(void) +{ + outcnt = 0; + insize = inptr = 0; + block_number = 0; + bytes_out = 0; + chunk = 0; + file_offset = 0; +} + + +/* + * Check the magic number of the input file and update ofname if an + * original name was given and to_stdout is not set. + * Return the compression method, -1 for error, -2 for warning. + * Set inptr to the offset of the next byte to be processed. + * This function may be called repeatedly for an input file consisting + * of several contiguous gzip'ed members. + * IN assertions: there is at least one remaining compressed member. + * If the member is a zip file, it must be the only one. + */ +static int +get_method(void) +{ + unsigned char flags; + char magic[2]; /* magic header */ + + magic[0] = get_byte(); + magic[1] = get_byte(); + + method = -1; /* unknown yet */ + if (memcmp(magic, GZIP_MAGIC, 2) == 0 + || memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) { + + method = get_byte(); + flags = get_byte(); + if ((flags & ENCRYPTED) != 0) + unzip_error("input is encrypted"); + if ((flags & CONTINUATION) != 0) + unzip_error("multi part input"); + if ((flags & RESERVED) != 0) + unzip_error("input has invalid flags"); + get_byte(); /* skip over timestamp */ + get_byte(); + get_byte(); + get_byte(); + + get_byte(); /* skip extra flags */ + get_byte(); /* skip OS type */ + + if ((flags & EXTRA_FIELD) != 0) { + unsigned len = get_byte(); + len |= get_byte() << 8; + while (len--) get_byte(); + } + + /* Get original file name if it was truncated */ + if ((flags & ORIG_NAME) != 0) { + /* skip name */ + while (get_byte() != 0) /* null */ ; + } + + /* Discard file comment if any */ + if ((flags & COMMENT) != 0) { + while (get_byte() != 0) /* null */ ; + } + } else { + unzip_error("unknown compression method"); + } + return method; +} + +/* + * Fill the input buffer and return the first byte in it. This is called + * only when the buffer is empty and at least one byte is really needed. + */ +int +fill_inbuf(void) +{ + long nblocks, nread; + + if (INBUFSIZ % bfs->blocksize != 0) { + printf("INBUFSIZ (%d) is not multiple of block-size (%d)\n", + INBUFSIZ, bfs->blocksize); + unzip_error("bad block-size"); + } + + if (block_number < 0) { + unzip_error("attempted to read past eof"); + } + + nblocks = INBUFSIZ / bfs->blocksize; + nread = (*bfs->bread)(input_fd, block_number, nblocks, inbuf); +#ifdef DEBUG + printf("read %ld blocks of %d, got %ld\n", nblocks, bfs->blocksize, + nread); +#endif + if (nread != nblocks * bfs->blocksize) { + if (nread < nblocks * bfs->blocksize) { + /* this is the EOF */ +#ifdef DEBUG + printf("at EOF\n"); +#endif + insize = nblocks * bfs->blocksize; + block_number = -1; + } else { + printf("Read returned %ld instead of %ld bytes\n", + nread, nblocks * bfs->blocksize); + unzip_error("read error"); + } + } else { + block_number += nblocks; + insize = INBUFSIZ; + } + inptr = 1; + return inbuf[0]; +} + + +/* + * Write the output window window[0..outcnt-1] holding uncompressed + * data and update crc. + */ +void +flush_window(void) +{ + if (!outcnt) { + return; + } + + updcrc(window, outcnt); + + if (!bytes_out) /* first block - look for headers */ + if (first_block(window, outcnt) < 0) + unzip_error("invalid exec header"); /* does a longjmp() */ + + bytes_out += outcnt; + while (chunk < nchunks) { + /* position within the current segment */ + ssize_t chunk_offset = file_offset - chunks[chunk].offset; + unsigned char *dest = (char *) chunks[chunk].addr + chunk_offset; + ssize_t to_copy; + unsigned char *src = window; + + /* window overlaps beginning of current segment */ + if (chunk_offset < 0) { + src = window - chunk_offset; + dest = (unsigned char *) chunks[chunk].addr; + } + if (src - window >= outcnt) { + file_offset += outcnt; + break; /* next window */ + } + + /* print a vanity message */ + if (chunk_offset == 0) + printf("aboot: segment %d, %ld bytes at %#lx\n", + chunk, chunks[chunk].size, + chunks[chunk].addr); + + to_copy = chunks[chunk].offset + chunks[chunk].size + - file_offset; + if (to_copy > outcnt) + to_copy = outcnt; +#ifdef DEBUG + printf("copying %ld bytes from offset %#lx " + "(segment %d) to %p\n", + to_copy, file_offset, chunk, dest); +#endif +#ifndef TESTING + memcpy(dest, src, to_copy); +#endif + file_offset += to_copy; + + if (to_copy < outcnt) { +#ifdef DEBUG + printf("new segment or EOF\n"); +#endif + outcnt -= to_copy; + chunk++; + } else + break; /* done this window */ + } +} + + +/* + * We have to be careful with the memory-layout during uncompression. + * The stack we're currently executing on lies somewhere between the + * end of this program (given by _end) and lastfree. However, as I + * understand it, there is no guarantee that the stack occupies the + * lowest page-frame following the page-frames occupied by this code. + * + * Thus, we are stuck allocating memory towards decreasing addresses, + * starting with lastfree. Unfortunately, to know the size of the + * kernel-code, we need to uncompress the image and we have a circular + * dependency. To make the long story short: we put a limit on + * the maximum kernel size at MAX_KERNEL_SIZE and allocate dynamic + * memory starting at (lastfree << ALPHA_PG_SHIFT) - MAX_KERNEL_SIZE. + */ +int +uncompress_kernel(int fd) +{ + input_fd = fd; + + inbuf = (unsigned char*) malloc(INBUFSIZ); + window = (unsigned char*) malloc(WSIZE); + + clear_bufs(); + makecrc(); + + method = get_method(); + unzip(0, 0); + + return 1; +} diff --git a/package/aboot/src/zip/unzip.c b/package/aboot/src/zip/unzip.c new file mode 100644 index 000000000..81813da5d --- /dev/null +++ b/package/aboot/src/zip/unzip.c @@ -0,0 +1,139 @@ +/* unzip.c -- decompress files in gzip or pkzip format. + * Copyright (C) 1992-1993 Jean-loup Gailly + * + * Adapted for Linux booting by Hannu Savolainen 1993 + * + * This is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License, see the file COPYING. + * + * The code in this file is derived from the file funzip.c written + * and put in the public domain by Mark Adler. + */ + +/* + * This version can extract files in gzip or pkzip format. For the + * latter, only the first entry is extracted, and it has to be either + * deflated or stored. + */ + +#include "gzip.h" + +/* PKZIP header definitions */ +#define LOCSIG 0x04034b50L /* four-byte lead-in (lsb first) */ +#define LOCFLG 6 /* offset of bit flag */ +#define CRPFLG 1 /* bit for encrypted entry */ +#define EXTFLG 8 /* bit for extended local header */ +#define LOCHOW 8 /* offset of compression method */ +#define LOCTIM 10 /* file mod time (for decryption) */ +#define LOCCRC 14 /* offset of crc */ +#define LOCSIZ 18 /* offset of compressed size */ +#define LOCLEN 22 /* offset of uncompressed length */ +#define LOCFIL 26 /* offset of file name field length */ +#define LOCEXT 28 /* offset of extra field length */ +#define LOCHDR 30 /* size of local header, including sig */ +#define EXTHDR 16 /* size of extended local header, inc sig */ + + +/* Globals */ + +int pkzip = 0; /* set for a pkzip file */ +int extended = 0; /* set if extended local header */ + +/* + * Unzip in to out. This routine works on both gzip and pkzip files. + * + * IN assertions: the buffer inbuf contains already the beginning of + * the compressed data, from offsets inptr to insize-1 included. + * The magic header has already been checked. The output buffer is cleared. + */ +void unzip(in, out) + int in, out; /* input and output file descriptors */ +{ + unsigned long orig_crc = 0; /* original crc */ + unsigned long orig_len = 0; /* original uncompressed length */ + int n; + unsigned char buf[EXTHDR]; /* extended local header */ + + /* ifd = in; + ofd = out; */ + + updcrc(NULL, 0); /* initialize crc */ + + if (pkzip && !extended) { /* crc and length at the end otherwise */ + orig_crc = LG(inbuf + LOCCRC); + orig_len = LG(inbuf + LOCLEN); + } + + /* Decompress */ + if (method == DEFLATED) { + + int res = inflate(); + + if (res == 3) { + unzip_error("out of memory"); + } else if (res != 0) { + unzip_error("invalid compressed format"); + } + + } else if (pkzip && method == STORED) { + register unsigned long n = LG(inbuf + LOCLEN); + + if (n != LG(inbuf + LOCSIZ)) { + unzip_error("length mismatch"); + } + while (n--) { + unsigned char c = get_byte(); + put_char(c); + } + } else { + unzip_error("internal error, invalid method"); + } + + /* Get the crc and original length */ +#ifdef DEBUG + printf("getting CRC and length\n"); +#endif + if (!pkzip) { + /* crc32 (see algorithm.doc) + * uncompressed input size modulo 2^32 + */ + for (n = 0; n < 8; n++) { + buf[n] = get_byte(); /* may cause an error if EOF */ +#ifdef DEBUG + printf("nonext: doing CRC, get_byte (ptr %d) returned %d\n", + inptr, buf[n]); +#endif + } + orig_crc = LG(buf); + orig_len = LG(buf+4); + + } else if (extended) { /* If extended header, check it */ + /* signature - 4bytes: 0x50 0x4b 0x07 0x08 + * CRC-32 value + * compressed size 4-bytes + * uncompressed size 4-bytes + */ + for (n = 0; n < EXTHDR; n++) { + buf[n] = get_byte(); /* may cause an error if EOF */ +#ifdef DEBUG + printf("ext: doing CRC, get_byte returned %d\n", buf[n]); +#endif + } + orig_crc = LG(buf+4); + orig_len = LG(buf+12); + } + + /* Validate decompression */ + if (orig_crc != updcrc(buf, 0)) { + unzip_error("crc error"); + } + if (orig_len != bytes_out) { + unzip_error("length error"); + } + + /* Check if there are more entries in a pkzip file */ + if (pkzip && inptr + 4 < insize && LG(inbuf+inptr) == LOCSIG) { + unzip_error("zip file has more than one entry"); + } + extended = pkzip = 0; /* for next file */ +} |