mirror of https://github.com/ipxe/ipxe.git
Initial revision
parent
75a5374d79
commit
1097cf8685
|
@ -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.
|
|
@ -0,0 +1,20 @@
|
|||
Unless specifically noted, a file is under the GPL. GPLed files are in
|
||||
general either from Linux or have been explicitly put under GPL by the
|
||||
authors. A few files are inherited from FreeBSD netboot and therefore
|
||||
can be used under BSD or GPL.
|
||||
|
||||
File Copyright status
|
||||
|
||||
core/misc.c BSD
|
||||
drivers/net/3c509.c BSD
|
||||
drivers/net/3c509.h BSD
|
||||
drivers/net/3c595.c BSD
|
||||
drivers/net/3c595.h BSD
|
||||
drivers/net/3c90x.c Open Source
|
||||
drivers/net/epic100.c None
|
||||
drivers/net/epic100.h None
|
||||
drivers/net/ns8390.c BSD
|
||||
drivers/net/ns8390.h BSD
|
||||
drivers/net/tulip.c BSD
|
||||
arch/i386/include/bits/string.h None
|
||||
util/lzhuf.c Open Source
|
|
@ -0,0 +1,28 @@
|
|||
If you don't want to install development tools, and have access to the
|
||||
Web, you can get ROM images made on demand from http://rom-o-matic.net/
|
||||
|
||||
The documentation tarballs should be extracted in the top directory (the
|
||||
one you are reading this INSTALL document from). A top directory called
|
||||
doc will be populated. This way the links from index.html will work
|
||||
properly.
|
||||
|
||||
More likely if you are unfamiliar with Etherboot you should read the
|
||||
documentation starting with index.html if you have a Web browser, or
|
||||
doc/text/userman.txt (after installing the documentation tarball) if you
|
||||
just have a plain text terminal.
|
||||
|
||||
Also read RELNOTES for any additional recent information.
|
||||
|
||||
Don't forget to check out the contrib/ directory which contains much
|
||||
contributed software and documentation. Please contact the authors of
|
||||
those packages directly for queries.
|
||||
|
||||
If you are booting FreeBSD, enable -DELF_IMAGE (and optionally
|
||||
-DAOUT_IMAGE) in Config. This should happen automatically now.
|
||||
|
||||
The index.html file is the same as the one on the Etherboot home page at
|
||||
the time the distribution was made. Therefore some of the local file:/
|
||||
links from the Distribution section may not work.
|
||||
|
||||
Etherboot was built using gcc 3.3.3 and binutils 2.15.91 from SuSE 9.2 but
|
||||
earlier 3.x versions will generally work.
|
|
@ -0,0 +1,43 @@
|
|||
Etherboot 5.4.0
|
||||
|
||||
PXE is now supported. You will also need to configure your server to
|
||||
provide a pxelinux.0 loader file, kernel and initrd images, and a
|
||||
pxelinux.cfg directory with a appropriate configuration spec files.
|
||||
|
||||
See the PXELINUX home page at:
|
||||
|
||||
http://syslinux.zytor.com/pxe.php
|
||||
|
||||
for more information.
|
||||
|
||||
There is no longer a default target for make. You must specify an
|
||||
argument to make. Help text is now provided to indicate possible make
|
||||
targets.
|
||||
|
||||
It should be possible to compile Etherboot with gcc >= 3.3.3, including
|
||||
gcc 3.4.x now that a couple of bugs have been tracked down. Please mail
|
||||
reports of success or failure to the etherboot-users list, together with
|
||||
the versions of gcc and binutils used.
|
||||
|
||||
gcc 2.x is not supported anymore. You need at least gcc 3.x to compile
|
||||
etherboot due to C99 constructs.
|
||||
|
||||
Removed etherboot(-pci)?.* rule because there are too many drivers and
|
||||
the image will no longer fit in memory. I don't want to choose a subset
|
||||
of drivers as everybody will have different preferences. So I'm going to
|
||||
piss off everybody equally by deleting the rule. Use the multiple driver
|
||||
rule (driver1--driver2--...) and select your own subset of drivers.
|
||||
|
||||
In order to create .iso and .liso images you will need to have the
|
||||
packages mtools-3.9.9 or later, and syslinux-2.08 or later installed on
|
||||
your system. These packages are available in various locations and
|
||||
formats. .liso images are like .iso but use floppy emulation. If you
|
||||
have a very old BIOS and .liso images don't work you may wish to try
|
||||
adding the -s option of syslinux as a last resort.
|
||||
|
||||
EMERGENCYDISKBOOT has been renamed EXIT_IF_NO_OFFER, which describes it
|
||||
better.
|
||||
|
||||
Menuing using DHCP options (mknbi/menu.c) has been removed.
|
||||
|
||||
.exe format can be generated by doesn't work so not publicised.
|
|
@ -0,0 +1,9 @@
|
|||
FILES = cromutil bromutil
|
||||
|
||||
INCLUDEDIR = /usr/include
|
||||
CFLAGS = -O2 -fomit-frame-pointer -Wall -I$(INCLUDEDIR)
|
||||
|
||||
all: $(FILES)
|
||||
|
||||
clean:
|
||||
rm -f $(FILES) *~ core
|
|
@ -0,0 +1,31 @@
|
|||
This utility was apparently writen by John Finlay and came to me
|
||||
via Richard Schroeder who got it from Greg Beeley. John, if you want
|
||||
to be credited with your full address or whatever in the Etherboot
|
||||
documentation, please contact me (Etherboot maintainer).
|
||||
|
||||
1/18/2000 Marty Connor (mdc@thinguin.org) added code for the 3C905C
|
||||
with AT49BV512 Flash memory, and created cromutil and bromutil to
|
||||
differentiate the versions. cromutil is for 3C905C and bromutil is
|
||||
for 3C905B.
|
||||
|
||||
Be careful. You can easily erase your Flash memory using these
|
||||
utilities. Make *sure* to back them up first using the "read"
|
||||
command. You must "erase" before using "prog" to program the chip with
|
||||
Etherboot code. This code comes with NO WARRANTY, and you take sole
|
||||
responsibility and liability for whatever it does. Read the
|
||||
"romutil.txt" file for more information on commands.
|
||||
|
||||
That being said, if you are programming a 3C905C-TXM (for example)
|
||||
you would do something like this:
|
||||
|
||||
$ cd etherboot-x.x.x/contrib
|
||||
$ tar -zxvf n3c905xutil.tar.gz
|
||||
$ cd n3c905xutil
|
||||
$ make
|
||||
# replace 0x6600 with whatever the IO Addr for your card is!!!!
|
||||
$ ./cromutil 0x6600 read > 905cbackup.bin
|
||||
$ ./cromutil 0x6600 erase
|
||||
$ ./cromutil 0x6600 prog < 3c90x.lzrom
|
||||
|
||||
You should now have an Etherboot-enabled 3c905C-TXM.
|
||||
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* readutil.c - perform various control ops on the 3c509b bios rom
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __i386__
|
||||
# error "This program can't compile or run on non-intel computers"
|
||||
#else
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <machine/cpufunc.h>
|
||||
|
||||
#define OUTB(data, port) outb(port, data)
|
||||
#define OUTW(data, port) outw(port, data)
|
||||
#define OUTL(data, port) outl(port, data)
|
||||
|
||||
#else
|
||||
|
||||
#include <sys/io.h>
|
||||
|
||||
#define OUTB(data, port) outb(data, port)
|
||||
#define OUTW(data, port) outw(data, port)
|
||||
#define OUTL(data, port) outl(data, port)
|
||||
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
unsigned int i, j, n;
|
||||
unsigned int ioaddr;
|
||||
unsigned long recvrstat;
|
||||
unsigned char buf[128];
|
||||
unsigned char b;
|
||||
|
||||
if (argc != 3) {
|
||||
printf("Usage: romid ioaddr [erase|protect|unprotect|id|read >file|prog <file]\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
/* get permissions for in/out{blw} */
|
||||
open("/dev/io",O_RDONLY,0);
|
||||
#else
|
||||
setuid(0); /* if we're setuid, do it really */
|
||||
if (iopl(3)) {
|
||||
perror("iopl()");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
sscanf(argv[1],"%x",&ioaddr);
|
||||
/* Set the register window to 3 for the 3c905b */
|
||||
OUTW(0x803, ioaddr+0xe);
|
||||
recvrstat = inl(ioaddr); /* save the receiver status */
|
||||
/* set the receiver type to MII so the full bios rom address space
|
||||
can be accessed */
|
||||
OUTL((recvrstat & 0xf00fffff)|0x00600000, ioaddr);
|
||||
|
||||
/* Set the register window to 0 for the 3c905b */
|
||||
OUTW(0x800, ioaddr+0xe);
|
||||
|
||||
if (strcmp(argv[2], "erase") == 0) {
|
||||
/* do the funky chicken to erase the rom contents */
|
||||
OUTL(0x5555, ioaddr+0x4);
|
||||
OUTB(0xaa, ioaddr+0x8);
|
||||
OUTL(0x2aaa, ioaddr+0x4);
|
||||
OUTB(0x55, ioaddr+0x8);
|
||||
OUTL(0x5555, ioaddr+0x4);
|
||||
OUTB(0x80, ioaddr+0x8);
|
||||
OUTL(0x5555, ioaddr+0x4);
|
||||
OUTB(0xaa, ioaddr+0x8);
|
||||
OUTL(0x2aaa, ioaddr+0x4);
|
||||
OUTB(0x55, ioaddr+0x8);
|
||||
OUTL(0x5555, ioaddr+0x4);
|
||||
OUTB(0x10, ioaddr+0x8);
|
||||
printf("Bios ROM at %04x has been erased\n", ioaddr);
|
||||
} else if (strcmp(argv[2], "protect") == 0) {
|
||||
OUTL(0x5555, ioaddr+0x4);
|
||||
OUTB(0xaa, ioaddr+0x8);
|
||||
OUTL(0x2aaa, ioaddr+0x4);
|
||||
OUTB(0x55, ioaddr+0x8);
|
||||
OUTL(0x5555, ioaddr+0x4);
|
||||
OUTB(0xa0, ioaddr+0x8);
|
||||
printf("Software Data Protection for Bios ROM at %04x has been enabled\n",
|
||||
ioaddr);
|
||||
} else if (strcmp(argv[2], "unprotect") == 0) {
|
||||
OUTL(0x5555, ioaddr+0x4);
|
||||
OUTB(0xaa, ioaddr+0x8);
|
||||
OUTL(0x2aaa, ioaddr+0x4);
|
||||
OUTB(0x55, ioaddr+0x8);
|
||||
OUTL(0x5555, ioaddr+0x4);
|
||||
OUTB(0x80, ioaddr+0x8);
|
||||
OUTL(0x5555, ioaddr+0x4);
|
||||
OUTB(0xaa, ioaddr+0x8);
|
||||
OUTL(0x2aaa, ioaddr+0x4);
|
||||
OUTB(0x55, ioaddr+0x8);
|
||||
OUTL(0x5555, ioaddr+0x4);
|
||||
OUTB(0x20, ioaddr+0x8);
|
||||
printf("Software Data Protection for Bios ROM at %04x has been disabled\n",
|
||||
ioaddr);
|
||||
} else if (strcmp(argv[2], "id") == 0) {
|
||||
OUTL(0x5555, ioaddr+0x4);
|
||||
OUTB(0xaa, ioaddr+0x8);
|
||||
OUTL(0x2aaa, ioaddr+0x4);
|
||||
OUTB(0x55, ioaddr+0x8);
|
||||
OUTL(0x5555, ioaddr+0x4);
|
||||
OUTB(0x90, ioaddr+0x8);
|
||||
/* 10ms delay needed */
|
||||
printf("Manufacturer ID - ");
|
||||
/* manuf. id */
|
||||
OUTL(0x0000, ioaddr+0x4);
|
||||
printf("%02x\n", inb(ioaddr+0x8));
|
||||
/* device id */
|
||||
OUTL(0x0001, ioaddr+0x4);
|
||||
printf("Device ID - %02x\n", inb(ioaddr+0x8));
|
||||
/* undo the funky chicken */
|
||||
OUTL(0x5555, ioaddr+0x4);
|
||||
OUTB(0xaa, ioaddr+0x8);
|
||||
OUTL(0x2aaa, ioaddr+0x4);
|
||||
OUTB(0x55, ioaddr+0x8);
|
||||
OUTL(0x5555, ioaddr+0x4);
|
||||
OUTB(0xf0, ioaddr+0x8);
|
||||
} else if (strcmp(argv[2], "read") == 0) {
|
||||
for (i = 0; i < 65536; i++) {
|
||||
OUTL(i, ioaddr+0x4);
|
||||
b = inb(ioaddr+0x8);
|
||||
write(1, &b, 1);
|
||||
}
|
||||
} else if (strcmp(argv[2], "prog") == 0) {
|
||||
/* program the rom in 128 bute chunks */
|
||||
for (i = 0, n = 0; i < 65536; i += n) {
|
||||
n = read(0, buf, 128);
|
||||
if (n == 0)
|
||||
break;
|
||||
if (n < 0) {
|
||||
perror("File Error");
|
||||
exit(-3);
|
||||
}
|
||||
/* disable SDP temporarily for programming a sector */
|
||||
OUTL(0x5555, ioaddr+0x4);
|
||||
OUTB(0xaa, ioaddr+0x8);
|
||||
OUTL(0x2aaa, ioaddr+0x4);
|
||||
OUTB(0x55, ioaddr+0x8);
|
||||
OUTL(0x5555, ioaddr+0x4);
|
||||
OUTB(0xa0, ioaddr+0x8);
|
||||
for (j = 0; j < n; j++) {
|
||||
OUTL(i+j, ioaddr+0x4);
|
||||
OUTB(buf[j], ioaddr+0x8);
|
||||
}
|
||||
/* wait for the programming of this sector to coomplete */
|
||||
while (inb(ioaddr+0x8) != buf[j-1])
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the register window to 3 for the 3c905b */
|
||||
OUTW(0x803, ioaddr+0xe);
|
||||
/* restore the receiver status */
|
||||
OUTL(recvrstat, ioaddr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* __i386__ */
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* 3c905cutil.c - perform various control ops on the 3C905C bios rom
|
||||
* which we assume to be an AT49BV512
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __i386__
|
||||
# error "This program can't compile or run on non-intel computers"
|
||||
#else
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/io.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
unsigned int ioaddr, i, n;
|
||||
unsigned char b;
|
||||
|
||||
setuid(0); /* if we're setuid, do it really */
|
||||
if (argc != 3) {
|
||||
printf("Usage: romid ioaddr [erase|id|read >file|prog <file]\n");
|
||||
exit(-1);
|
||||
}
|
||||
if (iopl(3)) {
|
||||
perror("iopl()");
|
||||
exit(1);
|
||||
}
|
||||
sscanf(argv[1],"%x",&ioaddr);
|
||||
|
||||
/* Set the register window to 0 for the 3C905C */
|
||||
outw(0x800, ioaddr+0xe);
|
||||
|
||||
if (strcmp(argv[2], "erase") == 0) {
|
||||
/* do the funky chicken to erase the rom contents */
|
||||
outl(0x5555, ioaddr+0x4);
|
||||
outb(0xaa, ioaddr+0x8);
|
||||
outl(0x2aaa, ioaddr+0x4);
|
||||
outb(0x55, ioaddr+0x8);
|
||||
outl(0x5555, ioaddr+0x4);
|
||||
outb(0x80, ioaddr+0x8);
|
||||
outl(0x5555, ioaddr+0x4);
|
||||
outb(0xaa, ioaddr+0x8);
|
||||
outl(0x2aaa, ioaddr+0x4);
|
||||
outb(0x55, ioaddr+0x8);
|
||||
outl(0x5555, ioaddr+0x4);
|
||||
outb(0x10, ioaddr+0x8);
|
||||
sleep (1);
|
||||
printf("Bios ROM at %04x has been erased\n", ioaddr);
|
||||
} else if (strcmp(argv[2], "id") == 0) {
|
||||
outl(0x5555, ioaddr+0x4);
|
||||
outb(0xaa, ioaddr+0x8);
|
||||
outl(0x2aaa, ioaddr+0x4);
|
||||
outb(0x55, ioaddr+0x8);
|
||||
outl(0x5555, ioaddr+0x4);
|
||||
outb(0x90, ioaddr+0x8);
|
||||
/* 10ms delay needed */
|
||||
printf("Manufacturer ID - ");
|
||||
/* manuf. id */
|
||||
outl(0x0000, ioaddr+0x4);
|
||||
printf("%02x\n", inb(ioaddr+0x8));
|
||||
/* device id */
|
||||
outl(0x0001, ioaddr+0x4);
|
||||
printf("Device ID - %02x\n", inb(ioaddr+0x8));
|
||||
/* undo the funky chicken */
|
||||
outl(0x5555, ioaddr+0x4);
|
||||
outb(0xaa, ioaddr+0x8);
|
||||
outl(0x2aaa, ioaddr+0x4);
|
||||
outb(0x55, ioaddr+0x8);
|
||||
outl(0x5555, ioaddr+0x4);
|
||||
outb(0xf0, ioaddr+0x8);
|
||||
} else if (strcmp(argv[2], "read") == 0) {
|
||||
for (i = 0; i < 65536; i++) {
|
||||
outl(i, ioaddr+0x4);
|
||||
b = inb(ioaddr+0x8);
|
||||
write(1, &b, 1);
|
||||
}
|
||||
} else if (strcmp(argv[2], "prog") == 0) {
|
||||
for (i = 0; i < 65536; i++) {
|
||||
n = read(0, &b, 1);
|
||||
if (n == 0)
|
||||
break;
|
||||
if (n < 0) {
|
||||
perror("File Error");
|
||||
exit(-3);
|
||||
}
|
||||
outl(0x5555, ioaddr+0x4);
|
||||
outb(0xaa, ioaddr+0x8);
|
||||
outl(0x2aaa, ioaddr+0x4);
|
||||
outb(0x55, ioaddr+0x8);
|
||||
outl(0x5555, ioaddr+0x4);
|
||||
outb(0xA0, ioaddr+0x8);
|
||||
outl(i, ioaddr+0x4);
|
||||
outb(b, ioaddr+0x8);
|
||||
while (inb(ioaddr+0x8) != b)
|
||||
;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* __i386__ */
|
|
@ -0,0 +1,36 @@
|
|||
I wrote the attached little util program to try out the basic approach
|
||||
and thought that you might find it useful as well as providing some
|
||||
simple testing. It isn't a final solution so the interface is rough. The
|
||||
program must be run as root on an Intel based machine.
|
||||
|
||||
The key point is that the IO address needs to be entered - I grab it
|
||||
from the dmesg output:
|
||||
|
||||
eth0: 3Com 3c905B Cyclone 100baseTx at 0xe400, 00:10:4b:d2:5e:0d, IRQ
|
||||
11
|
||||
|
||||
or "cat /proc/pci" to find the "I/O at XXXXXX" for your 3Com Card.
|
||||
|
||||
Some example commands are:
|
||||
|
||||
romutil 0xe400 erase - erases the ROM contents
|
||||
romutil 0xe400 protect - enables the Software Data Protection
|
||||
on the ROM [3c905B only]
|
||||
romutil 0xe400 unprotect - disables the Software Data Protection
|
||||
on the ROM [3c905B only]
|
||||
romutil 0xe400 id - displays the manufacturer and
|
||||
device IDs
|
||||
romutil 0xe400 read >file - writes the contents of the ROM to stdout
|
||||
romutil 0xe400 prog <file - writes the contents of the stdin into the
|
||||
ROM (<64k)
|
||||
|
||||
I tried reading and writing the ROM while doing large ftp transfers and
|
||||
experienced no problems. I didn't spend much time worrying about the
|
||||
possible race conditions. My system has lots of resources (450MHx P2,
|
||||
128MB RAM) so it might not provide the best test candidate.
|
||||
|
||||
Let me know what results you get if you try it out.
|
||||
|
||||
Thanks
|
||||
|
||||
John
|
|
@ -0,0 +1,537 @@
|
|||
#
|
||||
# Automatically generated make config: don't edit
|
||||
#
|
||||
CONFIG_X86=y
|
||||
CONFIG_ISA=y
|
||||
# CONFIG_SBUS is not set
|
||||
CONFIG_UID16=y
|
||||
|
||||
#
|
||||
# Code maturity level options
|
||||
#
|
||||
CONFIG_EXPERIMENTAL=y
|
||||
|
||||
#
|
||||
# Loadable module support
|
||||
#
|
||||
CONFIG_MODULES=y
|
||||
# CONFIG_MODVERSIONS is not set
|
||||
# CONFIG_KMOD is not set
|
||||
|
||||
#
|
||||
# Processor type and features
|
||||
#
|
||||
CONFIG_M386=y
|
||||
# CONFIG_M486 is not set
|
||||
# CONFIG_M586 is not set
|
||||
# CONFIG_M586TSC is not set
|
||||
# CONFIG_M586MMX is not set
|
||||
# CONFIG_M686 is not set
|
||||
# CONFIG_M686FXSR is not set
|
||||
# CONFIG_MPENTIUM4 is not set
|
||||
# CONFIG_MK6 is not set
|
||||
# CONFIG_MK7 is not set
|
||||
# CONFIG_MCRUSOE is not set
|
||||
# CONFIG_MWINCHIPC6 is not set
|
||||
# CONFIG_MWINCHIP2 is not set
|
||||
# CONFIG_MWINCHIP3D is not set
|
||||
# CONFIG_X86_CMPXCHG is not set
|
||||
CONFIG_X86_L1_CACHE_SHIFT=4
|
||||
# CONFIG_TOSHIBA is not set
|
||||
# CONFIG_MICROCODE is not set
|
||||
# CONFIG_X86_MSR is not set
|
||||
# CONFIG_X86_CPUID is not set
|
||||
CONFIG_NOHIGHMEM=y
|
||||
# CONFIG_HIGHMEM4G is not set
|
||||
# CONFIG_HIGHMEM64G is not set
|
||||
CONFIG_MATH_EMULATION=y
|
||||
CONFIG_MTRR=y
|
||||
# CONFIG_SMP is not set
|
||||
# CONFIG_X86_UP_IOAPIC is not set
|
||||
|
||||
#
|
||||
# General setup
|
||||
#
|
||||
CONFIG_NET=y
|
||||
# CONFIG_VISWS is not set
|
||||
CONFIG_PCI=y
|
||||
# CONFIG_PCI_GOBIOS is not set
|
||||
# CONFIG_PCI_GODIRECT is not set
|
||||
CONFIG_PCI_GOANY=y
|
||||
CONFIG_PCI_BIOS=y
|
||||
CONFIG_PCI_DIRECT=y
|
||||
# CONFIG_PCI_NAMES is not set
|
||||
CONFIG_EISA=y
|
||||
# CONFIG_MCA is not set
|
||||
CONFIG_HOTPLUG=y
|
||||
|
||||
#
|
||||
# PCMCIA/CardBus support
|
||||
#
|
||||
# CONFIG_PCMCIA is not set
|
||||
CONFIG_SYSVIPC=y
|
||||
# CONFIG_BSD_PROCESS_ACCT is not set
|
||||
CONFIG_SYSCTL=y
|
||||
CONFIG_KCORE_ELF=y
|
||||
# CONFIG_KCORE_AOUT is not set
|
||||
# CONFIG_BINFMT_AOUT is not set
|
||||
CONFIG_BINFMT_ELF=y
|
||||
CONFIG_BINFMT_MISC=m
|
||||
CONFIG_PM=y
|
||||
# CONFIG_ACPI is not set
|
||||
# CONFIG_APM is not set
|
||||
|
||||
#
|
||||
# Memory Technology Devices (MTD)
|
||||
#
|
||||
# CONFIG_MTD is not set
|
||||
|
||||
#
|
||||
# Parallel port support
|
||||
#
|
||||
CONFIG_PARPORT=y
|
||||
CONFIG_PARPORT_PC=y
|
||||
CONFIG_PARPORT_PC_FIFO=y
|
||||
# CONFIG_PARPORT_PC_SUPERIO is not set
|
||||
# CONFIG_PARPORT_AMIGA is not set
|
||||
# CONFIG_PARPORT_MFC3 is not set
|
||||
# CONFIG_PARPORT_ATARI is not set
|
||||
# CONFIG_PARPORT_SUNBPP is not set
|
||||
# CONFIG_PARPORT_OTHER is not set
|
||||
# CONFIG_PARPORT_1284 is not set
|
||||
|
||||
#
|
||||
# Plug and Play configuration
|
||||
#
|
||||
# CONFIG_PNP is not set
|
||||
|
||||
#
|
||||
# Block devices
|
||||
#
|
||||
CONFIG_BLK_DEV_FD=m
|
||||
# CONFIG_BLK_DEV_XD is not set
|
||||
# CONFIG_PARIDE is not set
|
||||
# CONFIG_BLK_CPQ_DA is not set
|
||||
# CONFIG_BLK_CPQ_CISS_DA is not set
|
||||
# CONFIG_BLK_DEV_DAC960 is not set
|
||||
# CONFIG_BLK_DEV_LOOP is not set
|
||||
# CONFIG_BLK_DEV_NBD is not set
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_BLK_DEV_RAM_SIZE=4096
|
||||
# CONFIG_BLK_DEV_INITRD is not set
|
||||
|
||||
#
|
||||
# Multi-device support (RAID and LVM)
|
||||
#
|
||||
# CONFIG_MD is not set
|
||||
|
||||
#
|
||||
# Networking options
|
||||
#
|
||||
# CONFIG_PACKET is not set
|
||||
# CONFIG_NETLINK is not set
|
||||
# CONFIG_NETFILTER is not set
|
||||
# CONFIG_FILTER is not set
|
||||
CONFIG_UNIX=y
|
||||
CONFIG_INET=y
|
||||
# CONFIG_IP_MULTICAST is not set
|
||||
# CONFIG_IP_ADVANCED_ROUTER is not set
|
||||
CONFIG_IP_PNP=y
|
||||
# CONFIG_IP_PNP_BOOTP is not set
|
||||
# CONFIG_IP_PNP_RARP is not set
|
||||
# CONFIG_NET_IPIP is not set
|
||||
# CONFIG_NET_IPGRE is not set
|
||||
# CONFIG_INET_ECN is not set
|
||||
# CONFIG_SYN_COOKIES is not set
|
||||
# CONFIG_IPV6 is not set
|
||||
# CONFIG_KHTTPD is not set
|
||||
# CONFIG_ATM is not set
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
# CONFIG_IPX is not set
|
||||
# CONFIG_ATALK is not set
|
||||
# CONFIG_DECNET is not set
|
||||
# CONFIG_BRIDGE is not set
|
||||
# CONFIG_X25 is not set
|
||||
# CONFIG_LAPB is not set
|
||||
# CONFIG_LLC is not set
|
||||
# CONFIG_NET_DIVERT is not set
|
||||
# CONFIG_ECONET is not set
|
||||
# CONFIG_WAN_ROUTER is not set
|
||||
# CONFIG_NET_FASTROUTE is not set
|
||||
# CONFIG_NET_HW_FLOWCONTROL is not set
|
||||
|
||||
#
|
||||
# QoS and/or fair queueing
|
||||
#
|
||||
# CONFIG_NET_SCHED is not set
|
||||
|
||||
#
|
||||
# Telephony Support
|
||||
#
|
||||
# CONFIG_PHONE is not set
|
||||
|
||||
#
|
||||
# ATA/IDE/MFM/RLL support
|
||||
#
|
||||
# CONFIG_IDE is not set
|
||||
# CONFIG_BLK_DEV_IDE_MODES is not set
|
||||
# CONFIG_BLK_DEV_HD is not set
|
||||
|
||||
#
|
||||
# SCSI support
|
||||
#
|
||||
# CONFIG_SCSI is not set
|
||||
|
||||
#
|
||||
# IEEE 1394 (FireWire) support
|
||||
#
|
||||
# CONFIG_IEEE1394 is not set
|
||||
|
||||
#
|
||||
# I2O device support
|
||||
#
|
||||
# CONFIG_I2O is not set
|
||||
|
||||
#
|
||||
# Network device support
|
||||
#
|
||||
CONFIG_NETDEVICES=y
|
||||
|
||||
#
|
||||
# ARCnet devices
|
||||
#
|
||||
# CONFIG_ARCNET is not set
|
||||
# CONFIG_DUMMY is not set
|
||||
# CONFIG_BONDING is not set
|
||||
# CONFIG_EQUALIZER is not set
|
||||
# CONFIG_TUN is not set
|
||||
# CONFIG_NET_SB1000 is not set
|
||||
|
||||
#
|
||||
# Ethernet (10 or 100Mbit)
|
||||
#
|
||||
CONFIG_NET_ETHERNET=y
|
||||
# CONFIG_NET_VENDOR_3COM is not set
|
||||
# CONFIG_LANCE is not set
|
||||
# CONFIG_NET_VENDOR_SMC is not set
|
||||
# CONFIG_NET_VENDOR_RACAL is not set
|
||||
# CONFIG_AT1700 is not set
|
||||
# CONFIG_DEPCA is not set
|
||||
# CONFIG_HP100 is not set
|
||||
CONFIG_NET_ISA=y
|
||||
# CONFIG_E2100 is not set
|
||||
# CONFIG_EEXPRESS is not set
|
||||
# CONFIG_EEXPRESS_PRO is not set
|
||||
# CONFIG_HPLAN_PLUS is not set
|
||||
# CONFIG_HPLAN is not set
|
||||
# CONFIG_ETH16I is not set
|
||||
CONFIG_NE2000=y
|
||||
# CONFIG_SK_G16 is not set
|
||||
# CONFIG_NET_PCI is not set
|
||||
# CONFIG_NET_POCKET is not set
|
||||
|
||||
#
|
||||
# Ethernet (1000 Mbit)
|
||||
#
|
||||
# CONFIG_ACENIC is not set
|
||||
# CONFIG_HAMACHI is not set
|
||||
# CONFIG_YELLOWFIN is not set
|
||||
# CONFIG_SK98LIN is not set
|
||||
# CONFIG_FDDI is not set
|
||||
# CONFIG_HIPPI is not set
|
||||
# CONFIG_PLIP is not set
|
||||
# CONFIG_PPP is not set
|
||||
# CONFIG_SLIP is not set
|
||||
|
||||
#
|
||||
# Wireless LAN (non-hamradio)
|
||||
#
|
||||
# CONFIG_NET_RADIO is not set
|
||||
|
||||
#
|
||||
# Token Ring devices
|
||||
#
|
||||
# CONFIG_TR is not set
|
||||
# CONFIG_NET_FC is not set
|
||||
# CONFIG_RCPCI is not set
|
||||
# CONFIG_SHAPER is not set
|
||||
|
||||
#
|
||||
# Wan interfaces
|
||||
#
|
||||
# CONFIG_WAN is not set
|
||||
|
||||
#
|
||||
# Amateur Radio support
|
||||
#
|
||||
# CONFIG_HAMRADIO is not set
|
||||
|
||||
#
|
||||
# IrDA (infrared) support
|
||||
#
|
||||
# CONFIG_IRDA is not set
|
||||
|
||||
#
|
||||
# ISDN subsystem
|
||||
#
|
||||
# CONFIG_ISDN is not set
|
||||
|
||||
#
|
||||
# Old CD-ROM drivers (not SCSI, not IDE)
|
||||
#
|
||||
# CONFIG_CD_NO_IDESCSI is not set
|
||||
|
||||
#
|
||||
# Input core support
|
||||
#
|
||||
# CONFIG_INPUT is not set
|
||||
|
||||
#
|
||||
# Character devices
|
||||
#
|
||||
CONFIG_VT=y
|
||||
CONFIG_VT_CONSOLE=y
|
||||
CONFIG_SERIAL=y
|
||||
# CONFIG_SERIAL_CONSOLE is not set
|
||||
# CONFIG_SERIAL_EXTENDED is not set
|
||||
# CONFIG_SERIAL_NONSTANDARD is not set
|
||||
CONFIG_UNIX98_PTYS=y
|
||||
CONFIG_UNIX98_PTY_COUNT=256
|
||||
CONFIG_PRINTER=m
|
||||
# CONFIG_LP_CONSOLE is not set
|
||||
# CONFIG_PPDEV is not set
|
||||
|
||||
#
|
||||
# I2C support
|
||||
#
|
||||
# CONFIG_I2C is not set
|
||||
|
||||
#
|
||||
# Mice
|
||||
#
|
||||
# CONFIG_BUSMOUSE is not set
|
||||
CONFIG_MOUSE=y
|
||||
CONFIG_PSMOUSE=y
|
||||
# CONFIG_82C710_MOUSE is not set
|
||||
# CONFIG_PC110_PAD is not set
|
||||
|
||||
#
|
||||
# Joysticks
|
||||
#
|
||||
|
||||
#
|
||||
# Game port support
|
||||
#
|
||||
|
||||
#
|
||||
# Gameport joysticks
|
||||
#
|
||||
|
||||
#
|
||||
# Serial port support
|
||||
#
|
||||
|
||||
#
|
||||
# Serial port joysticks
|
||||
#
|
||||
|
||||
#
|
||||
# Parallel port joysticks
|
||||
#
|
||||
# CONFIG_QIC02_TAPE is not set
|
||||
|
||||
#
|
||||
# Watchdog Cards
|
||||
#
|
||||
# CONFIG_WATCHDOG is not set
|
||||
# CONFIG_INTEL_RNG is not set
|
||||
# CONFIG_NVRAM is not set
|
||||
# CONFIG_RTC is not set
|
||||
# CONFIG_DTLK is not set
|
||||
# CONFIG_R3964 is not set
|
||||
# CONFIG_APPLICOM is not set
|
||||
|
||||
#
|
||||
# Ftape, the floppy tape device driver
|
||||
#
|
||||
# CONFIG_FTAPE is not set
|
||||
CONFIG_AGP=m
|
||||
CONFIG_AGP_INTEL=y
|
||||
CONFIG_AGP_I810=y
|
||||
CONFIG_AGP_VIA=y
|
||||
# CONFIG_AGP_AMD is not set
|
||||
# CONFIG_AGP_SIS is not set
|
||||
# CONFIG_AGP_ALI is not set
|
||||
# CONFIG_DRM is not set
|
||||
|
||||
#
|
||||
# Multimedia devices
|
||||
#
|
||||
# CONFIG_VIDEO_DEV is not set
|
||||
|
||||
#
|
||||
# File systems
|
||||
#
|
||||
# CONFIG_QUOTA is not set
|
||||
# CONFIG_AUTOFS_FS is not set
|
||||
# CONFIG_AUTOFS4_FS is not set
|
||||
# CONFIG_ADFS_FS is not set
|
||||
# CONFIG_AFFS_FS is not set
|
||||
# CONFIG_HFS_FS is not set
|
||||
# CONFIG_BFS_FS is not set
|
||||
CONFIG_FAT_FS=m
|
||||
CONFIG_MSDOS_FS=m
|
||||
# CONFIG_UMSDOS_FS is not set
|
||||
CONFIG_VFAT_FS=m
|
||||
# CONFIG_EFS_FS is not set
|
||||
CONFIG_JFFS_FS_VERBOSE=0
|
||||
# CONFIG_CRAMFS is not set
|
||||
# CONFIG_RAMFS is not set
|
||||
# CONFIG_ISO9660_FS is not set
|
||||
# CONFIG_MINIX_FS is not set
|
||||
# CONFIG_NTFS_FS is not set
|
||||
# CONFIG_HPFS_FS is not set
|
||||
CONFIG_PROC_FS=y
|
||||
CONFIG_DEVFS_FS=y
|
||||
CONFIG_DEVFS_MOUNT=y
|
||||
# CONFIG_DEVFS_DEBUG is not set
|
||||
# CONFIG_DEVPTS_FS is not set
|
||||
# CONFIG_QNX4FS_FS is not set
|
||||
# CONFIG_ROMFS_FS is not set
|
||||
CONFIG_EXT2_FS=y
|
||||
# CONFIG_SYSV_FS is not set
|
||||
# CONFIG_UDF_FS is not set
|
||||
# CONFIG_UFS_FS is not set
|
||||
|
||||
#
|
||||
# Network File Systems
|
||||
#
|
||||
# CONFIG_CODA_FS is not set
|
||||
CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V3=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
# CONFIG_NFSD is not set
|
||||
CONFIG_SUNRPC=y
|
||||
CONFIG_LOCKD=y
|
||||
CONFIG_LOCKD_V4=y
|
||||
# CONFIG_SMB_FS is not set
|
||||
# CONFIG_NCP_FS is not set
|
||||
|
||||
#
|
||||
# Partition Types
|
||||
#
|
||||
# CONFIG_PARTITION_ADVANCED is not set
|
||||
CONFIG_MSDOS_PARTITION=y
|
||||
# CONFIG_SMB_NLS is not set
|
||||
CONFIG_NLS=y
|
||||
|
||||
#
|
||||
# Native Language Support
|
||||
#
|
||||
CONFIG_NLS_DEFAULT="iso8859-1"
|
||||
# CONFIG_NLS_CODEPAGE_437 is not set
|
||||
# CONFIG_NLS_CODEPAGE_737 is not set
|
||||
# CONFIG_NLS_CODEPAGE_775 is not set
|
||||
# CONFIG_NLS_CODEPAGE_850 is not set
|
||||
# CONFIG_NLS_CODEPAGE_852 is not set
|
||||
# CONFIG_NLS_CODEPAGE_855 is not set
|
||||
# CONFIG_NLS_CODEPAGE_857 is not set
|
||||
# CONFIG_NLS_CODEPAGE_860 is not set
|
||||
# CONFIG_NLS_CODEPAGE_861 is not set
|
||||
# CONFIG_NLS_CODEPAGE_862 is not set
|
||||
# CONFIG_NLS_CODEPAGE_863 is not set
|
||||
# CONFIG_NLS_CODEPAGE_864 is not set
|
||||
# CONFIG_NLS_CODEPAGE_865 is not set
|
||||
# CONFIG_NLS_CODEPAGE_866 is not set
|
||||
# CONFIG_NLS_CODEPAGE_869 is not set
|
||||
# CONFIG_NLS_CODEPAGE_874 is not set
|
||||
# CONFIG_NLS_CODEPAGE_932 is not set
|
||||
# CONFIG_NLS_CODEPAGE_936 is not set
|
||||
# CONFIG_NLS_CODEPAGE_949 is not set
|
||||
# CONFIG_NLS_CODEPAGE_950 is not set
|
||||
CONFIG_NLS_ISO8859_1=m
|
||||
# CONFIG_NLS_ISO8859_2 is not set
|
||||
# CONFIG_NLS_ISO8859_3 is not set
|
||||
# CONFIG_NLS_ISO8859_4 is not set
|
||||
# CONFIG_NLS_ISO8859_5 is not set
|
||||
# CONFIG_NLS_ISO8859_6 is not set
|
||||
# CONFIG_NLS_ISO8859_7 is not set
|
||||
# CONFIG_NLS_ISO8859_8 is not set
|
||||
# CONFIG_NLS_ISO8859_9 is not set
|
||||
# CONFIG_NLS_ISO8859_14 is not set
|
||||
# CONFIG_NLS_ISO8859_15 is not set
|
||||
# CONFIG_NLS_KOI8_R is not set
|
||||
# CONFIG_NLS_UTF8 is not set
|
||||
|
||||
#
|
||||
# Console drivers
|
||||
#
|
||||
CONFIG_VGA_CONSOLE=y
|
||||
# CONFIG_VIDEO_SELECT is not set
|
||||
# CONFIG_MDA_CONSOLE is not set
|
||||
|
||||
#
|
||||
# Frame-buffer support
|
||||
#
|
||||
# CONFIG_FB is not set
|
||||
|
||||
#
|
||||
# Sound
|
||||
#
|
||||
CONFIG_SOUND=m
|
||||
# CONFIG_SOUND_CMPCI is not set
|
||||
# CONFIG_SOUND_EMU10K1 is not set
|
||||
# CONFIG_SOUND_FUSION is not set
|
||||
# CONFIG_SOUND_CS4281 is not set
|
||||
# CONFIG_SOUND_ES1370 is not set
|
||||
CONFIG_SOUND_ES1371=m
|
||||
# CONFIG_SOUND_ESSSOLO1 is not set
|
||||
# CONFIG_SOUND_MAESTRO is not set
|
||||
# CONFIG_SOUND_SONICVIBES is not set
|
||||
# CONFIG_SOUND_TRIDENT is not set
|
||||
# CONFIG_SOUND_MSNDCLAS is not set
|
||||
# CONFIG_SOUND_MSNDPIN is not set
|
||||
CONFIG_SOUND_VIA82CXXX=m
|
||||
CONFIG_SOUND_OSS=m
|
||||
# CONFIG_SOUND_TRACEINIT is not set
|
||||
# CONFIG_SOUND_DMAP is not set
|
||||
# CONFIG_SOUND_AD1816 is not set
|
||||
# CONFIG_SOUND_SGALAXY is not set
|
||||
# CONFIG_SOUND_ADLIB is not set
|
||||
# CONFIG_SOUND_ACI_MIXER is not set
|
||||
# CONFIG_SOUND_CS4232 is not set
|
||||
# CONFIG_SOUND_SSCAPE is not set
|
||||
# CONFIG_SOUND_GUS is not set
|
||||
# CONFIG_SOUND_ICH is not set
|
||||
# CONFIG_SOUND_VMIDI is not set
|
||||
# CONFIG_SOUND_TRIX is not set
|
||||
# CONFIG_SOUND_MSS is not set
|
||||
# CONFIG_SOUND_MPU401 is not set
|
||||
# CONFIG_SOUND_NM256 is not set
|
||||
# CONFIG_SOUND_MAD16 is not set
|
||||
# CONFIG_SOUND_PAS is not set
|
||||
# CONFIG_SOUND_PSS is not set
|
||||
CONFIG_SOUND_SB=m
|
||||
# CONFIG_SOUND_AWE32_SYNTH is not set
|
||||
# CONFIG_SOUND_WAVEFRONT is not set
|
||||
# CONFIG_SOUND_MAUI is not set
|
||||
CONFIG_SOUND_YM3812=m
|
||||
# CONFIG_SOUND_OPL3SA1 is not set
|
||||
# CONFIG_SOUND_OPL3SA2 is not set
|
||||
# CONFIG_SOUND_YMPCI is not set
|
||||
# CONFIG_SOUND_YMFPCI is not set
|
||||
# CONFIG_SOUND_UART6850 is not set
|
||||
# CONFIG_SOUND_AEDSP16 is not set
|
||||
|
||||
#
|
||||
# USB support
|
||||
#
|
||||
# CONFIG_USB is not set
|
||||
|
||||
#
|
||||
# Kernel hacking
|
||||
#
|
||||
# CONFIG_MAGIC_SYSRQ is not set
|
|
@ -0,0 +1,565 @@
|
|||
|
||||
|
||||
The Diskless Terminal running from NT server Mini-HOWTO
|
||||
Pavel Tkatchouk, ptkatcho@portal.ca
|
||||
v0.1, June 19th 1999
|
||||
|
||||
Table of Contents
|
||||
|
||||
1. Introduction.
|
||||
|
||||
1.1 What is it for?
|
||||
1.2 Do we need this HOWTO?
|
||||
1.3 A bit of History.
|
||||
|
||||
2. Project description.
|
||||
|
||||
2.1 Packaging.
|
||||
2.2 Image.
|
||||
2.2.1 Kernel.
|
||||
2.2.2 MRFS.
|
||||
2.2.3 Building MRFS.
|
||||
2.3 Remotefs.
|
||||
2.4 Booting sequence.
|
||||
2.4.1 BOOTP, TFTP.
|
||||
2.5 Bootprom.
|
||||
|
||||
3. Resources.
|
||||
|
||||
4. Copyright.
|
||||
|
||||
5. Feedback and credits.
|
||||
|
||||
|
||||
1. Introduction.
|
||||
|
||||
|
||||
1.1. What is it for?
|
||||
|
||||
This document describes how to build software distribution to run Java client on diskless
|
||||
terminal booted from Microsoft Windows 95/98/NT workstation. Package can also be easily
|
||||
modified to be used as Linux terminal or X Windows terminal's software. I found it also
|
||||
convenient for setup over the Ethernet of floppyless PS's, hard disk of which for some
|
||||
reason can not be accessed (sealed case under warranty, etc.).
|
||||
|
||||
|
||||
1.2. Do we need this HOWTO?
|
||||
|
||||
To be honest, I'm not sure. There are few excellent HOWTO's (see 3. Recources) that up until
|
||||
recently I considered quite sufficient to build what I've done two years ago. But since my
|
||||
project uses MS Windows as a file server vs. traditional NFS there were some know-how's
|
||||
involved which number of people wanted to see in some formal document.
|
||||
|
||||
|
||||
1.3. A bit of history.
|
||||
|
||||
My project at that time (1996) was to find OS/JVM that will allow to run Java application
|
||||
on hardware we manufacture. Hardware is practically generic x86 PC except it has no keyboard,
|
||||
hard drive, floppy drive, mouse, but touchscreen over LCD, plus some POS specific peripherals
|
||||
(badge reader, credit card reader, etc.). Due to cost consideration it had no any significant
|
||||
storage, so OS and Java client along with support binaries, libraries etc. had to be loaded
|
||||
remotely. Because our clients are exclusively Windows shops, Server had to be Windows as well.
|
||||
During evaluation of different commercial OS'es along with JVM's available it become apparent
|
||||
to my surprise that most promising solution was GPL one - Linux.
|
||||
|
||||
|
||||
2. Project description.
|
||||
|
||||
2.1. Packaging.
|
||||
|
||||
The whole distribution consists of remote file system (RemoteFS) residing on MS Windows
|
||||
server (NT Workstation, NT Server or Windows9x) and tagged bootable image.
|
||||
|
||||
|
||||
2.2. Image.
|
||||
|
||||
Image (~1.5MB) is generated by mknbi utility that comes with Etherboot package
|
||||
<http://etherboot.sourceforge.net>. It can include minimal root file system (MRFS)
|
||||
like in my case (since I had to boot client from MS Windows server and Linux kernel doesn't
|
||||
support SMBFS-Root, only NFS-Root. So I had to keep rootfs in the ramdisk). To generate
|
||||
image the following script can be used.
|
||||
|
||||
#!/bin/sh
|
||||
# mkrootnet: makes tagged netbootable image
|
||||
# This image includes kernel and minimal root filesystem
|
||||
# to do initial boot.
|
||||
#
|
||||
# Copyright (c) Pavel Tkatchouk 1996. All rights reserved.
|
||||
# Permission is granted for this material to be freely
|
||||
# used and distributed, provided the source is acknowledged.
|
||||
# No warranty of any kind is provided. You use this material
|
||||
# at your own risk.
|
||||
#
|
||||
DEVICEFILENAME="/tmp/file" # temporary file to be used as device
|
||||
FSBLOCKS=4096 # uncompressed filesystem size in K
|
||||
BOOTDISKDIR="/usr/BOOT/ROOTFS" # root filesystem model
|
||||
MOUNT="/mnt2" # temporary mount point
|
||||
ROOTFS="/tmp/rootfs" # root filesystem image
|
||||
ROOTFSGZ="/tmp/rootfs.gz" # compressed root filesystem image
|
||||
KERNEL="/usr/KERNELS/vmlinuz-nt" # kernel image
|
||||
KERNELTMP="/tmp/vmlinuz" # temporary copy of kernel image
|
||||
BOOTIMAGE="/tmp/img" # tagged image to be booted by client
|
||||
# if you want ramisk more than default 4096 set CMDLINE, don't forget to
|
||||
# adjust $FSBLOCKS
|
||||
# CMDLINE="ramdisk_size=8192" # parameters to pass to the kernel
|
||||
#
|
||||
echo "check:"
|
||||
echo "- if tftp server's download dir mounted to /mnt"
|
||||
echo "- loopback device is built-in or loaded"
|
||||
echo "\n press Enter when done"
|
||||
read tmp
|
||||
UPLOAD="/mnt/tmp" # tftp server's dir to upload bootimage
|
||||
echo -e "\nZeroing $DEVICEFILENAME of $FSBLOCKS k"
|
||||
echo "to be used as device for root filesystem model"
|
||||
dd if=/dev/zero of=$DEVICEFILENAME bs=1k count=$FSBLOCKS
|
||||
echo -e "\nMaking file system on $DEVICEFILENAME"
|
||||
mke2fs -m 0 $DEVICEFILENAME
|
||||
echo "Mounting $DEVICEFILENAME as a loopback device"
|
||||
mount -o loop -t ext2 $DEVICEFILENAME $MOUNT
|
||||
curdir=`pwd`
|
||||
cd $BOOTDISKDIR
|
||||
echo -e "Copying files from $BOOTDISKDIR to $DEVICEFILENAME, please wait"
|
||||
find . -print|cpio -pmd $MOUNT
|
||||
echo "Unmounting $MOUNT"
|
||||
umount $MOUNT
|
||||
cd $curdir
|
||||
echo "Copying $DEVICEFILENAME to $ROOTFS"
|
||||
dd if=$DEVICEFILENAME of=$ROOTFS bs=1k
|
||||
echo "Compressing $ROOTFS, it may take a while"
|
||||
echo "Please wait..."
|
||||
if [ -f $ROOTFSGZ ];then
|
||||
rm -f $ROOTFSGZ
|
||||
fi
|
||||
gzip -c $ROOTFS>$ROOTFSGZ
|
||||
rm -f $ROOTFS
|
||||
echo -e "\nCreating netbootable image"
|
||||
cp $KERNEL $KERNELTMP
|
||||
mknbi -d ram -i rom -r $ROOTFSGZ -k $KERNELTMP -a $CMDLINE -o $BOOTIMAGE
|
||||
echo "Uploading $BOOTIMAGE to $UPLOAD"
|
||||
cp $BOOTIMAGE $UPLOAD
|
||||
echo "Cleaning after ourselves"
|
||||
rm -f $KERNELTMP $DEVICEFILENAME $BOOTIMAGE
|
||||
echo "All done"
|
||||
|
||||
|
||||
In the above script actual image is generated by the following comand
|
||||
|
||||
#mknbi -d ram -i rom -r rootfs.gz -k vmlinuz-nt -o img
|
||||
|
||||
where:
|
||||
rootfs.gz - minimal root file system (MRFS);
|
||||
vmlinuz-nt - kernel;
|
||||
img - resulting image.
|
||||
|
||||
|
||||
Note:
|
||||
Default ramdisk size is 4096. It was enough for RedHat4.1 based minimal file system, but
|
||||
apparently not enough for 5.2 based. When this happens "end request:I/O error, dev 01:00 ..."
|
||||
error shows up. To fix that either use "mknbi -a ramdisk_size=8192" to pass parameter to the
|
||||
kernel (doesn't require kernel recompilation), or change /usr/src/linux/drivers/block/rd.c:
|
||||
int rd_size= from 4096 to 8192 or whatever and rebuild the kernel.
|
||||
|
||||
|
||||
2.2.1. Kernel.
|
||||
|
||||
Kernels 2.0.30 and 2.0.36 have been used by author, although nothing is preventing you from
|
||||
experimenting with others. Kernel should include ramdisk support. The following
|
||||
<link to .config> configuration has been used to build <link to binary (kernel 2.0.30)>.
|
||||
You may find some components unnecessary, just exclude them and rebuild.
|
||||
|
||||
Don't forget to change root device after you built the kernel (rdev vmlinuz /dev/rd).
|
||||
|
||||
Gotcha's: apparently smbfs is broken in 2.2.x kernels. Symptoms: remote share is mounted
|
||||
just fine but after a while fails with "smb_request: result = -32" errmsg. I've heard
|
||||
SuSe has fix for that.
|
||||
|
||||
2.2.2. MRFS.
|
||||
|
||||
Minimal root file system is required to get Linux up and running along with networking until
|
||||
it can mount remote file system to run X/Java from there. After image gets loaded from the
|
||||
server MRFS is decompressed into ramdisk. If you can afford a lot of ram on your terminal the
|
||||
entire remote file system can be moved to rootfs.gz. That will make your terminal more
|
||||
responsive.
|
||||
|
||||
|
||||
2.2.3. Building MRFS.
|
||||
|
||||
Some folks found it easier to start from scratch, others use known "minimal" Linux distributions
|
||||
(Linux Router, tomsrtbt, etc.), yet others prefer to start from "big" Linuces like I did. Every
|
||||
path has it's pro and contras.
|
||||
|
||||
Pruning standard distribution (RedHat, Debian, etc.) to your needs might be very time consuming.
|
||||
To ease that painful process I have used remotely booted diskless client with NFS-Root (see
|
||||
Etherboot's Readme, NFS-Root and NFS-Root-Client mini-HOWTO's, Diskless-HOWTO):
|
||||
|
||||
- setup minimal RedHat4.1 install (networked workstation, X, no development, mail, etc., ~117MB);
|
||||
- find . -print|cpio -pmd /usr/NFS/ROOTFS - copy entire fs tree to NFS exported dir;
|
||||
- mknod /usr/NFS/ROOTFS/dev/nfsroot b 0 255;
|
||||
- build vmlinuz-nfs kernel according to NFS-Howto (built-in bootp,rarp,NFS,NFS root,NIC
|
||||
driver,RAM disk);
|
||||
- rdev vmlinuz-nfs /dev/nfsroot - to set NFS root device;
|
||||
- build image for NFS-Root fs:
|
||||
#mknbi -d rom -i rom -k vmlinuz-nfs -o nfsImage;
|
||||
- boot client while monitoring NFS file requests (by Solaris snoop);
|
||||
- copy files from /usr/NFS/ROOTFS to /usr/BOOT/ROOTFS (MRFS model) according to snoop's
|
||||
filelist;
|
||||
- generate image by mkrootnet script (don't forget to point to the right kernel vmlinuz-nt).
|
||||
|
||||
The above trick not only allows to determine the sought files set but also debug boot process
|
||||
analyzing NFS messages. I found it convenient to put "read tmp" statements into init scripts
|
||||
for debugging. Tracking files up until issuing login gives you <link to rootfs.gz> MRFS (~1MB)
|
||||
that can be used to boot Linux from ROM (flash, eprom, DiskOnChip, SanDisk, etc.) as well. All
|
||||
the other files requested by client (during starting X, Java, Java client) were put into (link
|
||||
to remotefs.zip, ~9MB).
|
||||
|
||||
|
||||
To restore MRFS model on your PC from the above rootfs.gz:
|
||||
- #cd /tmp
|
||||
- #gunzip rootfs.gz
|
||||
- #mount -o loop -t ext2 /tmp/rootfs /mnt
|
||||
- #cd /mnt
|
||||
- #find . -print|cpio -pmd /usr/BOOT/ROOTFS
|
||||
- #umount /mnt
|
||||
|
||||
Note:
|
||||
|
||||
You will have to change attributes of some dirs, files (/etc/mtab, /etc/mtab~, /var/lock/subsys/*,
|
||||
/var/run/*, /dev/tty*, etc.) against standard. This is because with standard attribs diskless
|
||||
client refused to work. For example I had to change /dev/tty* ownerships to 99:99 from original
|
||||
0:0 or 0:5, to get rid of errmsg "INIT: Id "1" respawning too fast: disabled for 5 minutes".
|
||||
Being admin illiterate I just chmod them to 777 and chown to 99:99 to make life easier.
|
||||
THIS IS SERIOUS SECURITY VIOLATION!!! Using keyboardless terminal with no daemons running in
|
||||
my case reduces the risk, yet I would appreciate very much those more experienced who will help
|
||||
to restore the right attribs while keeping the distribution working.
|
||||
|
||||
Some "gotcha's" to watch for during MRFS building:
|
||||
- standard attributes/ownership of some files don't work;
|
||||
- rdev must be set (non-tagged image didn't work, so couldn't use config file to pass parrs
|
||||
to the kernel);
|
||||
- diskless client writes 99:99 ownership on generated files;
|
||||
- "password incorrect" for root, but any other OK and su OK too.
|
||||
|
||||
|
||||
2.3. RemoteFS.
|
||||
|
||||
Remotefs.zip file includes everything required by the system that can be located on
|
||||
remote file system, i.e after booting has been complete and remote file system mounted.
|
||||
In my case it is X Windows System and Java binaries, libraries etc. To use that file on
|
||||
MS Windows NT:
|
||||
- unzip remotefs.zip to some directory;
|
||||
- share this directory read-only as "usr" (or share as some other name and pass this name to
|
||||
the client through bootptab configuration file for BOOTP server;
|
||||
- create an account username=root, password=linux on NT (can be set in bootptab).
|
||||
|
||||
Note:
|
||||
There's no symbolic links on NTFS, so UNIX links must be replaced by copies on NTFS.
|
||||
To determine potential troublmakers one could use the following:
|
||||
- first copy required subset (according to snoop's intercept) from /usr/NFS/ROOTFS to
|
||||
/usr/BOOT/REMOTEFS;
|
||||
- mount some share from NTFS to /mnt;
|
||||
- /usr/BOOT/REMOTEFS#find . -print|cpio -pmd /mnt 2>links;
|
||||
In the links file you will find names to work with.
|
||||
|
||||
|
||||
2.4. Booting sequence.
|
||||
|
||||
Boot occurs in the following sequence:
|
||||
- bootprom sends bootp request,
|
||||
- bootp server responds with subnet mask, client's name, client's IP, TFTP server's IP,
|
||||
bootfile name and some optional parameters (like NT's username/password to use it's share,
|
||||
you could pass some other share name here as say T104="somedir");
|
||||
- bootprom downloads image from TFTP server;
|
||||
- kernel starts;
|
||||
- kernel decompresses MRFS in RAM;
|
||||
- system starts init using ramdisk root,
|
||||
- mounts remote file system from NT via SMBFS;
|
||||
- automatically logins;
|
||||
- starts xstart script located on remotefs (/usr/sbin) where you can start any of your
|
||||
programs, change parameters, etc. without rebuilding the image.
|
||||
|
||||
Below are some config/init sample files from <rootfs.gz>, <remotefs.zip>:
|
||||
|
||||
<bootptab, change to link>
|
||||
t1:sm=255.255.255.0:sa=192.168.33.150:bf=img:T100="pavelnt4":T101="root":T102="linux"
|
||||
touch1:hn=touch1:tc=t1:ha=00A0F00035CD:ip=192.168.33.127
|
||||
|
||||
</etc/fstab, change to link>:
|
||||
/dev/ram / ext2 defaults 1 1
|
||||
/proc /proc proc defaults 0 0
|
||||
|
||||
</etc/rc.d/rc.bootp, change to link later>:
|
||||
#!/bin/sh
|
||||
# Written to simply set the IP stuff up from the
|
||||
# bootpc data.
|
||||
# Last updated : Mon Mar 10 15:17:01 1997
|
||||
#
|
||||
# Variables
|
||||
|
||||
BOOTPC=/sbin/bootpc
|
||||
IFCONFIG=/sbin/ifconfig
|
||||
ROUTE=/sbin/route
|
||||
BINHOST=/bin/hostname
|
||||
DEV=eth0
|
||||
ASKSERVER="255.255.255.255"
|
||||
TW="--timeoutwait 320"
|
||||
RIF="--returniffail"
|
||||
RIFMESSAGE="Bootp failed -- disabling network."
|
||||
RCONF=/etc/resolv.conf
|
||||
EHOSTS=/etc/hosts
|
||||
LHOSTS=/etc/hosts.local
|
||||
TMPFILE=/tmp/bootp
|
||||
# Functions
|
||||
# Remove the networking by taking down the interface
|
||||
netdown() {
|
||||
${ROUTE} del default
|
||||
${IFCONFIG} ${DEV} down
|
||||
}
|
||||
## End of the functions
|
||||
|
||||
## Start of the actual work
|
||||
# Bring up minimal networking use 0.0.0.0 as our address as we don't
|
||||
# know it yet (Means "Me but I don't know my address or network")
|
||||
${IFCONFIG} ${DEV} up 0.0.0.0
|
||||
${ROUTE} add default dev ${DEV}
|
||||
|
||||
# Perform the bootp -- doesn't return unless it gets an answer
|
||||
if ${BOOTPC} --dev ${DEV} --server ${ASKSERVER} ${RIF} ${TW} > ${TMPFILE}
|
||||
then
|
||||
# Take down networking (use the 0.0.0.0 for as short a time as possible)
|
||||
netdown
|
||||
# Read in the values
|
||||
. ${TMPFILE}
|
||||
|
||||
# To use in mountsmb script later
|
||||
SMBSERVER=${T100}
|
||||
# And delete the temporary file
|
||||
# rm ${TMPFILE}
|
||||
else
|
||||
# Take down networking (use the 0.0.0.0 for as short a time as possible)
|
||||
netdown
|
||||
# give message and quit
|
||||
echo ${RIFMESSAGE}
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Start the loopback interface and add a route to it
|
||||
# It's already set by standard init?
|
||||
${IFCONFIG} lo 127.0.0.1
|
||||
${ROUTE} add -net 127.0.0.0
|
||||
|
||||
# Setup of IP stuff needs doing first
|
||||
#
|
||||
if [ -z "${NETMASK}" ] ; then
|
||||
# No netmask info, all this is guessed from the IP number
|
||||
# If this is wrong for your network FIX the bootpd to know
|
||||
# what it should send in the RFC1497 cookie! 11/02/94 JSP
|
||||
#
|
||||
${IFCONFIG} ${DEV} up ${IPADDR} broadcast ${BROADCAST}
|
||||
${ROUTE} -n add -net ${NETWORK} dev ${DEV}
|
||||
else
|
||||
# We will have NETMASK, BROADCAST, and NETWORK defined
|
||||
${IFCONFIG} ${DEV} up ${IPADDR} broadcast ${BROADCAST} netmask ${NETMASK}
|
||||
${ROUTE} -n add -net ${NETWORK} dev ${DEV}
|
||||
fi
|
||||
|
||||
# Set the hostname from what we got via bootp or reverse lookup
|
||||
|
||||
echo "127.0.0.1 loopback localhost">${EHOSTS}
|
||||
${BINHOST} "${HOSTNAME}"
|
||||
echo "${IPADDR} ${HOSTNAME}" >>${EHOSTS}
|
||||
echo "${SERVER} ${SMBSERVER}" >>${EHOSTS}
|
||||
|
||||
|
||||
</etc/rc.d/rc.local, change to link>:
|
||||
#!/bin/sh
|
||||
# This script will be executed *after* all the other init scripts.
|
||||
# You can put your own initialization stuff in here if you don't
|
||||
# want to do the full Sys V style init stuff.
|
||||
#
|
||||
# 07/02/97 Pavel Tkatchouk
|
||||
#
|
||||
echo "Start networking"
|
||||
insmod /lib/8390.o
|
||||
insmod /lib/ne.o io=0x300 irq=9
|
||||
echo "Install serial"
|
||||
insmod /lib/serial.o
|
||||
echo "Install touch"
|
||||
insmod /lib/touch.o
|
||||
echo "Install smbfs"
|
||||
insmod /lib/smbfs.o
|
||||
echo "Getting TCP/IP parameters from bootp server"
|
||||
echo "and start networking"
|
||||
/etc/rc.d/rc.bootp
|
||||
if [ -f /etc/squirrel-release ]; then
|
||||
R=$(cat /etc/squirrel-release)
|
||||
else
|
||||
R="release 0.02"
|
||||
fi
|
||||
echo "Mounting remote fs"
|
||||
/sbin/mountsmb
|
||||
echo "XYZ Inc. Diskless Linux $R"
|
||||
echo "Starting X and Java client without login"
|
||||
su -c /sbin/xstart root
|
||||
|
||||
|
||||
</usr/sbin/xstart, change to link>:
|
||||
#!/bin/bash
|
||||
#
|
||||
# Script to start X and Java client
|
||||
# 08/07/97 Pavel Tkatchouk
|
||||
#
|
||||
# Read bootps response first
|
||||
. /tmp/bootp
|
||||
# -s 0 to disable screen-saver
|
||||
/usr/X11R6/bin/X -s 0 &
|
||||
export DISPLAY=:0.0
|
||||
# /usr is share mounted from Windows workstation
|
||||
cd /usr/program/
|
||||
java SomeJavaApp
|
||||
|
||||
|
||||
</sbin/mountsmb, change to link>:
|
||||
#!/bin/bash
|
||||
# mountsmb: mounts remote filesystems from NT workstation
|
||||
# using Microsoft's SMB protocol
|
||||
#
|
||||
# Copyright (c) Pavel Tkatchouk 1997. All rights reserved.
|
||||
# Permission is granted for this material to be freely
|
||||
# used and distributed, provided the source is acknowledged.
|
||||
# No warranty of any kind is provided. You use this material
|
||||
# at your own risk.
|
||||
#
|
||||
# Last edit June 29 8:30 1997
|
||||
#
|
||||
MOUNTDIR="usr"
|
||||
SHRDIR="usr"
|
||||
BOOTPRES="/tmp/bootp"
|
||||
# Read botpc response
|
||||
. ${BOOTPRES}
|
||||
# Sharename from NT server, uncomment if you want to use
|
||||
# non-hardcoded "usr" but from bootptab
|
||||
#SHRDIR=${T104}
|
||||
SMBSRV="//${T100}"
|
||||
CLIENT="${HOSTNAME}"
|
||||
USER="${T101}"
|
||||
PASSWORD="${T102}"
|
||||
echo -e "\nMounting $SMBSRV/$SHRDIR to /$MOUNTDIR"
|
||||
smbmount $SMBSRV/$SHRDIR $MOUNTDIR -c $CLIENT -U $USER -P $PASSWORD
|
||||
echo -e "\nDone"
|
||||
|
||||
Gotcha's:
|
||||
Looks like smbmount client from smbfs package used to mount remote Windows shares to local
|
||||
Linux dirs in pre 2.2.x era isn't maintained anymore so you should use one coming with
|
||||
Samba package. Also binary smbmount won't work with 2.2.x, so you have to recompile with
|
||||
2.2.x headers following Samba's readme. Yet even that won't guarantee reliable work until
|
||||
somebody fixes kernel's smbfs module.
|
||||
|
||||
2.4.1. BOOTP, TFTP.
|
||||
|
||||
There are number of BOOTP, TFTP servers for Windows on the market. You could find them
|
||||
here:
|
||||
|
||||
- www.walusoft.co.uk (Walusoft's tftp);
|
||||
- ftp.coast.net/simtel/nt/internet/tftpds12.zip (Millwood AB's tftp);
|
||||
- ftp.cabletron.com/pub/snmp/bootftp/boottft2.zip (Cabletron's bootp/tftp combo);
|
||||
- www.tellurian.au.com (Tellurian's bootp, tftp, dhcp servers).
|
||||
- www.metainfo.com (Metainfo's DHCP server)
|
||||
- www.nts.com (Network Telesystems's DHCP server in IPserver package)
|
||||
|
||||
My choice was Tellurian's products - very reliable, simple to install, attractively priced
|
||||
(fully capable evaluation versions are available).
|
||||
|
||||
2.5. Bootprom.
|
||||
|
||||
Ken Yap's Etherboot <etherboot.sourceforge.net> will tell you everything about bootprom.
|
||||
Here I just want to mention that normally you would have to put bootprom's code into network
|
||||
adapter's PROM. But if your hardware like mine has BIOS programmed in flash you could
|
||||
re-program it to add bootprom (some BIOS requires special programmer to do that, others don't)
|
||||
as BIOS extension.
|
||||
|
||||
This is what I did to add ne.rom (bootprom generated by Etherboot's makerom for NE2000 clone)
|
||||
to AMI BIOS on my flash:
|
||||
|
||||
- read flash content by programmer into bios.bin binary file;
|
||||
- use one of available binary editors (say www.simtel.net/Win95/editors/hxp3005.zip to add
|
||||
ne.rom to bios.bin (and to edit ne.rom if necessary);
|
||||
- write new bios.bin back to flash.
|
||||
|
||||
Notes:
|
||||
- makerom generates bootprom for standard EPROM sizes (8k, 16k, 32k, etc.), so if you tight on
|
||||
space use -s flag to adjust size (or cut it manually to multiple of 512 bytes blocks, just
|
||||
don't forget to adjust extension's length which is coded in Byte 2 and checksum to 8 bits
|
||||
of zero;
|
||||
- valid absolute addresses for BIOS extensions are from 0xC8000 to 0xF4000 (check with
|
||||
motherboard's manufacturer how flash is mapped onto system memory space);
|
||||
- Byte 0 must be 0x55, Byte 1 must be 0xAA, Byte 2 must be extension's length in 512 bytes
|
||||
blocks;
|
||||
- extension BIOS has to start at a 2k boundary;
|
||||
|
||||
|
||||
3. Resources.
|
||||
|
||||
FAQ's:
|
||||
- tomsrtbt.FAQ (www.toms.net);
|
||||
|
||||
HOWTO's:
|
||||
- Paul Moody's miniHOWTO (www.linuxembedded.com/pmhowto.html)
|
||||
- Diskless;
|
||||
- Diskless-HOWTO;
|
||||
- NFS-Root;
|
||||
- NFS-Root-Client;
|
||||
- Bootdisk-HOWTO;
|
||||
- BootPrompt-HOWTO;
|
||||
- NCD-X-Terminal;
|
||||
- Remote-Boot;
|
||||
- Remote-X-Apps;
|
||||
|
||||
Web:
|
||||
- etherboot.sourceforge.net/
|
||||
- www.waste.org/~zanshin
|
||||
- www.tellurian.com.au.
|
||||
- www.toms.net
|
||||
- www.trinux.org
|
||||
- www.linux.org.uk/ELKS-Home
|
||||
- www.embedded.com
|
||||
- www.linuxembedded.com
|
||||
- www.thinlinux.org
|
||||
- www.linuxrouter.org
|
||||
- linux-mandrake.com
|
||||
- www.disklessworkstations.com
|
||||
|
||||
Newsgroups:
|
||||
- comp.arch.embedded
|
||||
|
||||
Lists:
|
||||
- netboot-owner@baghira.han.de
|
||||
- linux-embedded@waste.org
|
||||
|
||||
Magazines:
|
||||
- Circuit Cellar #100 - 105
|
||||
|
||||
|
||||
4. Copyright.
|
||||
|
||||
Copyright (c) Pavel Tkatchouk 1999.
|
||||
Permission is granted for this material to be freely used and distributed, provided the source
|
||||
is acknowledged. Copyright policy is GPL as published by the Free Software Foundation.
|
||||
|
||||
No warranty of any kind is provided. You use this material at your own risk.
|
||||
|
||||
|
||||
|
||||
5. Feedback and credits.
|
||||
|
||||
Since I am neither have a lot of Linux experience nor native English speaker, there would be
|
||||
errors in this document. I would accept any help with gratitude whether in form of proof-reading,
|
||||
techical corrections or otherwise. Please send your comments, suggestions and questions to Pavel
|
||||
Tkatchouk (ptkatcho@portal.ca)
|
||||
|
||||
I wish to thank Pierre Mondie who convinced me to start this document. I'm also very much in
|
||||
debt to all those who's work made this project possible:
|
||||
|
||||
Ken Yap <ken_yap@users.sourceforge.net> (Etherboot)
|
||||
David Newall <www.tellurian.com.au> (Bootpdnt/Ftpdnt)
|
||||
(to be continued)
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<title>Free TFTP / Syslog / NFS Servers for Windows</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h3 align="center">Free TFTP / Syslog / NFS Servers for Windows</h3>
|
||||
<div align="center"><center>
|
||||
|
||||
<address>
|
||||
Stefan Furtmayr (<a href="mailto:sf@paf.net">sf@paf.net</a>)
|
||||
</address>
|
||||
</center></div>
|
||||
|
||||
<p>Feel free to send me your comments about these programs or some additions.</p>
|
||||
|
||||
<p>Also have a look at the <a
|
||||
href="http://www.ltsp.org/contrib/diskless-windows-howto.htm">"Diskless Windows
|
||||
Cookbook "</a> in the <a href="http://www.ltsp.org/contrib/">LTSP Contrib Area</a>.</p>
|
||||
|
||||
<p><small>From this list I have only used the W2K-TFTP once for a customer with the <a
|
||||
href="http://support.3com.com/infodeli/tools/nic/mba.htm">3Com MBA Utility Disk</a>, while
|
||||
it can be used as well with <a href="http://etherboot.sourceforge.net">Etherboot</a>
|
||||
tagged images for other NIC brands.</small><br>
|
||||
<small>The solution used a netbooted DOS with MS Client 3.0 to easily restore disk images
|
||||
with <a href="http://www.ghost.com/">Symantec Ghost</a> (see <a
|
||||
href="http://appdeploy.com/tools/imaging.shtml">appdeploy.com</a> for similar tools).</small><br>
|
||||
<small>Sure there are several possibilities to do this with Linux but for cloning NT4/W2K
|
||||
the NTFS support is rather experimental and automatically changing the SID is another
|
||||
issue.</small></p>
|
||||
|
||||
<h4>TFTP Servers:</h4>
|
||||
|
||||
<p>In Autumn 2000 i tested some different TFTP servers and found out that most of them do
|
||||
not install/run as a service, especially under W2K.
|
||||
|
||||
<ul>
|
||||
<li>TFTP server included with Windows 2000 (remote installation services need to be
|
||||
installed)<br>
|
||||
The path for the images has to be specified via registry:<br>
|
||||
Q232115 - Changing the Drive or Volume on Which Remote Installation Images Reside:<br>
|
||||
<a href="http://support.microsoft.com/support/kb/articles/Q232/1/15.ASP">http://support.microsoft.com/support/kb/articles/Q232/1/15.ASP</a></li>
|
||||
<li>3CDaemon version 2.0 revision 10. Freeware. Integrated TFTP/FTP/Syslog Daemon for
|
||||
Windows 95/98/NT<br>
|
||||
<a href="ftp://ftp.3com.com/pub/utilbin/win32/3cdv2r10.zip">ftp://ftp.3com.com/pub/utilbin/win32/3cdv2r10.zip</a><br>
|
||||
- Windows 2000 Server: does not run as service!<br>
|
||||
- Windows NT Server 4.0: not tested</li>
|
||||
<li>The TFTP Server portion of 3CServer, altered to run as a system Service under Windows NT<br>
|
||||
<a href="ftp://ftp.3com.com/pub/utilbin/win32/3CTftpSvc.zip">ftp://ftp.3com.com/pub/utilbin/win32/3CTftpSvc.zip</a><br>
|
||||
- Windows 2000 Server: only working in debug mode, does not run as service!<br>
|
||||
- Windows NT Server 4.0: not tested</li>
|
||||
<li>Cisco TFTP Server v.1.1<br>
|
||||
<a href="http://www.cisco.com/pcgi-bin/tablebuild.pl/tftp">http://www.cisco.com/pcgi-bin/tablebuild.pl/tftp</a><br>
|
||||
Does not provide an option itself to install as service.</li>
|
||||
<li><a href="http://solarwinds.net/Tools/Free_Tools/TFTP_Server/">http://solarwinds.net/Tools/Free_Tools/TFTP_Server/</a><br>
|
||||
Does not provide an option itself to install as service.</li>
|
||||
</ul>
|
||||
|
||||
<p><em>Untested:</em></p>
|
||||
|
||||
<p>found on <a href="http://www.nonags.com/nonags/servd32.html">http://www.nonags.com/nonags/servd32.html</a><br>
|
||||
- <a href="http://www.klever.net/kin/pumpkin.html">http://www.klever.net/kin/pumpkin.html</a><br>
|
||||
- <a href="http://membres.tripod.fr/phjounin//P_tftpd32.htm">http://membres.tripod.fr/phjounin//P_tftpd32.htm</a></p>
|
||||
|
||||
<h4>Syslog Servers:</h4>
|
||||
|
||||
<ul>
|
||||
<li>3Com Software Library - Utilities for 32 bit Windows<br>
|
||||
<a href="http://support.3com.com/software/utilities_for_windows_32_bit.htm">http://support.3com.com/software/utilities_for_windows_32_bit.htm</a></li>
|
||||
<li><a href="http://www.netal.com/download.htm#SL4NT03">http://www.netal.com/download.htm#SL4NT03</a>
|
||||
(works as service) </li>
|
||||
</ul>
|
||||
|
||||
<h4>NFS Servers:</h4>
|
||||
|
||||
<ul>
|
||||
<li>War NFS Daemon: <a href="http://www.jgaa.com">http://www.jgaa.com</a> (untested)</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,40 @@
|
|||
Date: 11/9/2001 3:56 PM
|
||||
Received: 11/9/2001 4:05 PM
|
||||
From: Steve Tilden, stilden@sicom-sys.com
|
||||
|
||||
...
|
||||
|
||||
2) I have added conditional code to main.c from Etherboot 5.0.4 to add
|
||||
a new default boot option and I have included the modified main.c as an
|
||||
attachment to this message.
|
||||
|
||||
As I received Etherboot 5.0.4, in the Config file, if you select
|
||||
ASK_BOOT with a non zero time-out option, then you also get to set
|
||||
ANS_DEFAULT = ANS_NETWORK or ANS_DEFAULT = ANS_LOCAL to determine what
|
||||
will happen if the operator does not respond to the prompt. I have now
|
||||
added conditional code in main.c such that if you set ANS_DEFAULT =
|
||||
ANS_AUTO, the default answer will be set according to whether or not
|
||||
there is a hard disk in the system (as detected by the BIOS). If a hard
|
||||
disk is present, then if the operator does nothing, the system will boot
|
||||
from it. If a hard disk does not exist, then again if the operator does
|
||||
nothing, the system will boot via the network. Either way, for our
|
||||
particular environment, the operator has to do nothing to get it to boot
|
||||
correctly. Yet the operator can still override the default selection
|
||||
to, for example, allow a unit without a hard disk, to boot directly from
|
||||
a floppy rather than the network, or to allow a unit with a hard disk,
|
||||
to boot from the network.
|
||||
|
||||
I don't know it the code I have added might be correct for a future
|
||||
production version of Etherboot, but I thought I'd send it to you and
|
||||
let you get it into the system if you feel it might be appropriate.
|
||||
|
||||
Thanks,
|
||||
|
||||
Steve Tilden
|
||||
Sicom Systems Inc.
|
||||
stilden@sicom-sys.com
|
||||
|
||||
[Ed: On a compliant BIOS, it will actually boot the next device in the
|
||||
BIOS list if local is selected, either explicitly or by timeout, which
|
||||
may or may not be the hard disk, which is why it's less than general and
|
||||
not included in the distribution by default.]
|
|
@ -0,0 +1,55 @@
|
|||
--- main.c Mon Nov 5 18:58:30 2001
|
||||
+++ main.c.new Thu Nov 15 01:45:12 2001
|
||||
@@ -149,21 +151,49 @@
|
||||
static unsigned short ipchksum(unsigned short *ip, int len);
|
||||
static unsigned short udpchksum(struct iphdr *packet);
|
||||
|
||||
+
|
||||
+#if defined(ASK_BOOT) && ASK_BOOT > 0 && (ANS_DEFAULT == ANS_AUTO)
|
||||
+/*
|
||||
+ * Read Installed Hard Disk Count from BIOS memory at 0:0475
|
||||
+ */
|
||||
+static int hdsk_cnt(void)
|
||||
+{
|
||||
+ int retv;
|
||||
+ __asm__ __volatile__(
|
||||
+ "xorw %%ax,%%ax\n\t"
|
||||
+ "movb 0x475,%%al\n"
|
||||
+ : "=a" (retv)
|
||||
+ : /* no inputs */
|
||||
+ : "ax", "cc", "memory"
|
||||
+ );
|
||||
+ return(retv);
|
||||
+}
|
||||
+#endif /* ASK_BOOT && ANS_AUTO */
|
||||
+
|
||||
+
|
||||
static inline void ask_boot(void)
|
||||
{
|
||||
#if defined(ASK_BOOT) && ASK_BOOT > 0
|
||||
while(1) {
|
||||
- int c;
|
||||
+ int c, deflt;
|
||||
unsigned long time;
|
||||
+#if defined(ASK_BOOT) && ASK_BOOT > 0 && (ANS_DEFAULT == ANS_AUTO)
|
||||
+ if (hdsk_cnt() != 0)
|
||||
+ deflt = ANS_LOCAL;
|
||||
+ else
|
||||
+ deflt = ANS_NETWORK;
|
||||
+#else
|
||||
+ deflt = ANS_DEFAULT;
|
||||
+#endif
|
||||
printf(ASK_PROMPT);
|
||||
for (time = currticks() + ASK_BOOT*TICKS_PER_SEC; !iskey(); )
|
||||
if (currticks() > time) {
|
||||
- c = ANS_DEFAULT;
|
||||
+ c = deflt;
|
||||
goto done;
|
||||
}
|
||||
c = getchar();
|
||||
if ((c >= 'a') && (c <= 'z')) c &= 0x5F;
|
||||
- if (c == '\n') c = ANS_DEFAULT;
|
||||
+ if (c == '\n') c = deflt;
|
||||
done:
|
||||
if ((c >= ' ') && (c <= '~')) putchar(c);
|
||||
putchar('\n');
|
|
@ -0,0 +1,2 @@
|
|||
An Award BIOS ROM lister in Perl contributed by Eric W. Biederman
|
||||
<ebiederman@lnxi.com>.
|
|
@ -0,0 +1,341 @@
|
|||
#!/usr/bin/perl -w
|
||||
use strict;
|
||||
use FileHandle;
|
||||
use integer;
|
||||
|
||||
sub unsigned_little_endian_to_value
|
||||
{
|
||||
# Assumes the data is initially little endian
|
||||
my ($buffer) = @_;
|
||||
my $bytes = length($buffer);
|
||||
my $value = 0;
|
||||
my $i;
|
||||
for($i = $bytes -1; $i >= 0; $i--) {
|
||||
my $byte = unpack('C', substr($buffer, $i, 1));
|
||||
$value = ($value * 256) + $byte;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
sub decode_fixed_string
|
||||
{
|
||||
my ($data, $bytes) = @_;
|
||||
return $data;
|
||||
}
|
||||
|
||||
sub decode_pstring
|
||||
{
|
||||
my ($buf_ref, $offset_ref) = @_;
|
||||
# Decode a pascal string
|
||||
my $offset = ${$offset_ref};
|
||||
my $len = unpack('C',substr(${$buf_ref}, $offset, 1));
|
||||
my $data = substr(${$buf_ref}, $offset +1, $len);
|
||||
${$offset_ref} = $offset + $len +1;
|
||||
return $data;
|
||||
}
|
||||
|
||||
sub decode_cstring
|
||||
{
|
||||
# Decode a c string
|
||||
my ($buf_ref, $offset_ref) = @_;
|
||||
my ($data, $byte);
|
||||
my $index = ${$offset_ref};
|
||||
while(1) {
|
||||
$byte = substr(${$buf_ref}, $index, 1);
|
||||
if (!defined($byte) || ($byte eq "\0")) {
|
||||
last;
|
||||
}
|
||||
$data .= $byte;
|
||||
$index++;
|
||||
}
|
||||
${$offset_ref} = $index;
|
||||
return $data;
|
||||
}
|
||||
|
||||
sub type_size
|
||||
{
|
||||
my ($entry) = @_;
|
||||
my %type_length = (
|
||||
byte => 1,
|
||||
half => 2,
|
||||
word => 4,
|
||||
xword => 8,
|
||||
'fixed-string' => $entry->[2],
|
||||
pstring => 0,
|
||||
cstring => 0,
|
||||
);
|
||||
my $type = $entry->[0];
|
||||
if (!exists($type_length{$type})) {
|
||||
die "unknown type $type";
|
||||
}
|
||||
my $length = $type_length{$type};
|
||||
return $length;
|
||||
}
|
||||
|
||||
sub decode_fixed_type
|
||||
{
|
||||
my ($type, $data, $bytes) = @_;
|
||||
my %decoders = (
|
||||
'byte' => \&unsigned_little_endian_to_value,
|
||||
'half' => \&unsigned_little_endian_to_value,
|
||||
'word' => \&unsigned_little_endian_to_value,
|
||||
'xword' => \&unsigned_little_endian_to_value,
|
||||
'fixed-string' => \&decode_fixed_string,
|
||||
);
|
||||
my $decoder = $decoders{$type} or die "unknow fixed type $type";
|
||||
return $decoder->($data, $bytes);
|
||||
}
|
||||
|
||||
sub decode_variable_type
|
||||
{
|
||||
my ($type, $buf_ref, $offset_ref) = @_;
|
||||
my %decoders = (
|
||||
'pstring' => \&decode_pstring,
|
||||
'cstring' => \&decode_cstring,
|
||||
);
|
||||
my $decoder = $decoders{$type} or die "unknow variable type $type";
|
||||
return $decoder->($buf_ref, $offset_ref);
|
||||
}
|
||||
|
||||
sub decode_struct
|
||||
{
|
||||
my ($buf_ref, $offset, $layout) = @_;
|
||||
my $initial_offset = $offset;
|
||||
my ($entry, %results);
|
||||
foreach $entry (@$layout) {
|
||||
my ($type, $name) = @$entry;
|
||||
my $bytes = type_size($entry);
|
||||
if ($bytes > 0) {
|
||||
my $data = substr(${$buf_ref}, $offset, $bytes);
|
||||
$results{$name} = decode_fixed_type($type, $data, $bytes);
|
||||
$offset += $bytes;
|
||||
} else {
|
||||
$results{$name} = decode_variable_type($type, $buf_ref, \$offset);
|
||||
}
|
||||
}
|
||||
return (\%results, $offset - $initial_offset);
|
||||
}
|
||||
|
||||
sub print_big_hex
|
||||
{
|
||||
my ($min_digits, $value) = @_;
|
||||
my @digits;
|
||||
while($min_digits > 0 || ($value > 0)) {
|
||||
my $digit = $value%16;
|
||||
$value /= 16;
|
||||
unshift(@digits, $digit);
|
||||
$min_digits--;
|
||||
}
|
||||
my $digit;
|
||||
foreach $digit (@digits) {
|
||||
printf("%01x", $digit);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
my %lha_signatures = (
|
||||
'-com-' => 1,
|
||||
'-lhd-' => 1,
|
||||
'-lh0-' => 1,
|
||||
'-lh1-' => 1,
|
||||
'-lh2-' => 1,
|
||||
'-lh3-' => 1,
|
||||
'-lh4-' => 1,
|
||||
'-lh5-' => 1,
|
||||
'-lzs-' => 1,
|
||||
'-lz4-' => 1,
|
||||
'-lz5-' => 1,
|
||||
'-afx-' => 1,
|
||||
'-lzf-' => 1,
|
||||
);
|
||||
|
||||
my %lha_os = (
|
||||
'M' => 'MS-DOS',
|
||||
'2' => 'OS/2',
|
||||
'9' => 'OS9',
|
||||
'K' => 'OS/68K',
|
||||
'3' => 'OS/386',
|
||||
'H' => 'HUMAN',
|
||||
'U' => 'UNIX',
|
||||
'C' => 'CP/M',
|
||||
'F' => 'FLEX',
|
||||
'm' => 'Mac',
|
||||
'R' => 'Runser',
|
||||
'T' => 'TownOS',
|
||||
'X' => 'XOSK',
|
||||
'A' => 'Amiga',
|
||||
'a' => 'atari',
|
||||
' ' => 'Award ROM',
|
||||
);
|
||||
|
||||
|
||||
my @lha_level_1_header = (
|
||||
[ 'byte', 'header_size' ], # 1
|
||||
[ 'byte', 'header_sum', ], # 2
|
||||
[ 'fixed-string', 'method_id', 5 ], # 7
|
||||
[ 'word', 'skip_size', ], # 11
|
||||
[ 'word', 'original_size' ], # 15
|
||||
[ 'half', 'dos_time' ], # 17
|
||||
[ 'half', 'dos_date' ], # 19
|
||||
[ 'byte', 'fixed' ], # 20
|
||||
[ 'byte', 'level' ], # 21
|
||||
[ 'pstring', 'filename' ], # 22
|
||||
[ 'half', 'crc' ],
|
||||
[ 'fixed-string', 'os_id', 1 ],
|
||||
[ 'half', 'ext_size' ],
|
||||
);
|
||||
|
||||
# General lha_header
|
||||
my @lha_header = (
|
||||
[ 'byte', 'header_size' ],
|
||||
[ 'byte', 'header_sum', ],
|
||||
[ 'fixed-string', 'method_id', 5 ],
|
||||
[ 'word', 'skip_size', ],
|
||||
[ 'word', 'original_size' ],
|
||||
[ 'half', 'dos_time' ],
|
||||
[ 'half', 'dos_date' ],
|
||||
[ 'half', 'rom_addr' ],
|
||||
[ 'half', 'rom_flags' ],
|
||||
[ 'byte', 'fixed' ],
|
||||
[ 'byte', 'level' ],
|
||||
[ 'pstring', 'filename' ],
|
||||
[ 'half', 'crc' ],
|
||||
[ 'lha_os', 'os_id', 1 ],
|
||||
[ 'half', 'ext_size' ],
|
||||
[ 'byte', 'zero' ],
|
||||
[ 'byte', 'total_checksum' ],
|
||||
[ 'half', 'total_size' ],
|
||||
);
|
||||
|
||||
sub print_struct
|
||||
{
|
||||
my ($layout, $self) = @_;
|
||||
my $entry;
|
||||
my $width = 0;
|
||||
foreach $entry(@$layout) {
|
||||
my ($type, $name) = @$entry;
|
||||
if (length($name) > $width) {
|
||||
$width = length($name);
|
||||
}
|
||||
}
|
||||
foreach $entry (@$layout) {
|
||||
my ($type, $name) = @$entry;
|
||||
printf("%*s = ", $width, $name);
|
||||
my $value = $self->{$name};
|
||||
if (!defined($value)) {
|
||||
print "undefined";
|
||||
}
|
||||
elsif ($type eq "lha_os") {
|
||||
print "$lha_os{$value}";
|
||||
}
|
||||
elsif ($type =~ m/string/) {
|
||||
print "$value";
|
||||
}
|
||||
else {
|
||||
my $len = type_size($entry);
|
||||
print "0x";
|
||||
print_big_hex($len *2, $value);
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub checksum
|
||||
{
|
||||
my ($buf_ref, $offset, $length) = @_;
|
||||
my ($i, $sum);
|
||||
$sum = 0;
|
||||
for($i = 0; $i < $length; $i++) {
|
||||
my $byte = unpack('C', substr($$buf_ref, $offset + $i, 1));
|
||||
$sum = ($sum + $byte) %256;
|
||||
}
|
||||
return $sum;
|
||||
}
|
||||
|
||||
sub decode_lha_header
|
||||
{
|
||||
my ($buf_ref, $offset) = @_;
|
||||
my $level = unpack('C',substr(${$buf_ref}, $offset + 20, 1));
|
||||
|
||||
my %self;
|
||||
my ($struct, $bytes);
|
||||
if ($level == 1) {
|
||||
($struct, $bytes)
|
||||
= decode_struct($buf_ref, $offset, \@lha_level_1_header);
|
||||
%self = %$struct;
|
||||
if ($self{fixed} != 0x20) {
|
||||
die "bad fixed value";
|
||||
}
|
||||
$self{total_size} = $self{header_size} + 2 + $self{skip_size};
|
||||
if ($bytes != $self{header_size} +2) {
|
||||
die "$bytes != $self{header_size} +2";
|
||||
}
|
||||
my $checksum = checksum($buf_ref, $offset +2, $self{header_size});
|
||||
if ($checksum != $self{header_sum}) {
|
||||
printf("WARN: Header bytes checksum to %02lx\n",
|
||||
$checksum);
|
||||
}
|
||||
# If we are an award rom...
|
||||
if ($self{os_id} eq ' ') {
|
||||
@self{qw(zero total_checksum)} =
|
||||
unpack('CC', substr($$buf_ref,
|
||||
$offset + $self{total_size}, 2));
|
||||
if ($self{zero} != 0) {
|
||||
warn "Award ROM without trailing zero";
|
||||
}
|
||||
else {
|
||||
$self{total_size}++;
|
||||
}
|
||||
my $checksum =
|
||||
checksum($buf_ref, $offset, $self{total_size});
|
||||
if ($self{total_checksum} != $checksum) {
|
||||
printf("WARN: Image bytes checksum to %02lx\n",
|
||||
$checksum);
|
||||
}
|
||||
else {
|
||||
$self{total_size}++;
|
||||
}
|
||||
$self{rom_addr} = $self{dos_time};
|
||||
$self{rom_flags} = $self{dos_date};
|
||||
delete @self{qw(dos_time dos_date)};
|
||||
}
|
||||
}
|
||||
else {
|
||||
die "Unknown header type";
|
||||
}
|
||||
return \%self;
|
||||
}
|
||||
|
||||
sub main
|
||||
{
|
||||
my ($filename, $rom_length) = @_;
|
||||
my $fd = new FileHandle;
|
||||
if (!defined($rom_length)) {
|
||||
my ($dev, $ino, $mode, $nlink, $uid, $gid,$rdev,$size,
|
||||
$atime, $mtime, $ctime, $blksize, $blocks)
|
||||
= stat($filename);
|
||||
$rom_length = $size;
|
||||
}
|
||||
$fd->open("<$filename") or die "Cannot ope $filename";
|
||||
my $data;
|
||||
$fd->read($data, $rom_length);
|
||||
$fd->close();
|
||||
|
||||
my $i;
|
||||
for($i = 0; $i < $rom_length; $i++) {
|
||||
my $sig = substr($data, $i, 5);
|
||||
if (exists($lha_signatures{$sig})) {
|
||||
my $start = $i -2;
|
||||
my $header = decode_lha_header(\$data, $start);
|
||||
|
||||
my $length = $header->{total_size};
|
||||
print "AT: $start - @{[$start + $length -1]}, $length bytes\n";
|
||||
print_struct(\@lha_header, $header);
|
||||
print "\n";
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main(@ARGV);
|
|
@ -0,0 +1,475 @@
|
|||
#
|
||||
# Makefile for Etherboot
|
||||
#
|
||||
# Most of the time you should edit Config
|
||||
#
|
||||
# Common options:
|
||||
# VERSION=v - Set the version string
|
||||
#
|
||||
# NS8390 options:
|
||||
# -DINCLUDE_NE - Include NE1000/NE2000 support
|
||||
# -DNE_SCAN=list - Probe for NE base address using list of
|
||||
# comma separated hex addresses
|
||||
# -DINCLUDE_3C503 - Include 3c503 support
|
||||
# -DT503_SHMEM - Use 3c503 shared memory mode (off by default)
|
||||
# -DINCLUDE_WD - Include Western Digital/SMC support
|
||||
# -DWD_DEFAULT_MEM- Default memory location for WD/SMC cards
|
||||
# -DCOMPEX_RL2000_FIX
|
||||
#
|
||||
# If you have a Compex RL2000 PCI 32-bit (11F6:1401),
|
||||
# and the bootrom hangs in "Probing...[NE*000/PCI]",
|
||||
# try enabling this fix... it worked for me :).
|
||||
# In the first packet write somehow it somehow doesn't
|
||||
# get back the expected data so it is stuck in a loop.
|
||||
# I didn't bother to investigate what or why because it works
|
||||
# when I interrupt the loop if it takes more then COMPEX_RL2000_TRIES.
|
||||
# The code will notify if it does a abort.
|
||||
# SomniOne - somnione@gmx.net
|
||||
#
|
||||
# 3C509 option:
|
||||
# -DINCLUDE_3C509 - Include 3c509 support
|
||||
#
|
||||
# 3C90X options:
|
||||
# -DINCLUDE_3C90X - Include 3c90x support
|
||||
# -DCFG_3C90X_PRESERVE_XCVR - Reset the transceiver type to the value it
|
||||
# had initially just before the loaded code is started.
|
||||
# -DCFG_3C90X_XCVR - Hardcode the tranceiver type Etherboot uses.
|
||||
# -DCFG_3C90X_BOOTROM_FIX - If you have a 3c905B with buggy ROM
|
||||
# interface, setting this option might "fix" it. Use
|
||||
# with caution and read the docs in 3c90x.txt!
|
||||
#
|
||||
# See the documentation file 3c90x.txt for more details.
|
||||
#
|
||||
# CS89X0 (optional) options:
|
||||
# -DINCLUDE_CS89X0- Include CS89x0 support
|
||||
# -DCS_SCAN=list - Probe for CS89x0 base address using list of
|
||||
# comma separated hex addresses; increasing the
|
||||
# address by one (0x300 -> 0x301) will force a
|
||||
# more aggressive probing algorithm. This might
|
||||
# be neccessary after a soft-reset of the NIC.
|
||||
#
|
||||
# LANCE options:
|
||||
# -DINCLUDE_NE2100- Include NE2100 support
|
||||
# -DINCLUDE_NI6510- Include NI6510 support
|
||||
#
|
||||
# SK_G16 options:
|
||||
# -DINCLUDE_SK_G16- Include SK_G16 support
|
||||
#
|
||||
# I82586 options:
|
||||
# -DINCLUDE_3C507 - Include 3c507 support
|
||||
# -DINCLUDE_NI5210- Include NI5210 support
|
||||
# -DINCLUDE_EXOS205-Include EXOS205 support
|
||||
#
|
||||
# SMC9000 options:
|
||||
# -DINCLUDE_SMC9000 - Include SMC9000 driver
|
||||
# -DSMC9000_SCAN=list - List of I/O addresses to probe
|
||||
#
|
||||
# TIARA (Fujitsu Etherstar) options:
|
||||
# -DINCLUDE_TIARA - Include Tiara support
|
||||
#
|
||||
# NI5010 options:
|
||||
# -DINCLUDE_NI5010 - Include NI5010 support
|
||||
#
|
||||
# TULIP options:
|
||||
# -DINCLUDE_TULIP - Include Tulip support
|
||||
# -DUSE_INTERNAL_BUFFER - receuve and transmit buffers within program
|
||||
# space, not below 0x10000, in case that region is used
|
||||
#
|
||||
# RTL8139 options:
|
||||
# -DINCLUDE_RTL8139 - Include RTL8139 support
|
||||
# -DUSE_INTERNAL_BUFFER - 8 kB receive buffer within program space,
|
||||
# not at 0x10000 - 8kB, in case that region is used
|
||||
#
|
||||
|
||||
include Config
|
||||
|
||||
GCC= gcc
|
||||
CPP= gcc -E
|
||||
VERSION= 4.6.12
|
||||
CFLAGS16+= -DVERSION=\"$(VERSION)\" -DRELOC=$(RELOCADDR)
|
||||
CFLAGS32+= -DVERSION=\"$(VERSION)\" -DRELOC=$(RELOCADDR) $(OLDGAS)
|
||||
LCONFIG+= -DRELOC=$(RELOCADDR)
|
||||
|
||||
IDENT16= 'Etherboot/16 $(VERSION) (GPL) $(@F)'
|
||||
IDENT32= 'Etherboot/32 $(VERSION) (GPL) $(@F)'
|
||||
|
||||
# Find out if we're using binutils 2.9.1 which uses a different syntax in some
|
||||
# places (most prominently in the opcode prefix area).
|
||||
OLDGAS:= $(shell $(AS) --version | grep -q '2\.9\.1' && echo -DGAS291)
|
||||
|
||||
# Check the requested type of build (32, 16 or both families)
|
||||
ifeq ($(ETHERBOOT),16)
|
||||
BUILD_LIBS= $(BLIB16)
|
||||
BUILD_BINS= $(BINS16)
|
||||
endif
|
||||
ifeq ($(ETHERBOOT),32)
|
||||
BUILD_LIBS= $(BLIB32)
|
||||
BUILD_BINS= $(BINS32)
|
||||
endif
|
||||
ifeq ($(ETHERBOOT),both)
|
||||
BUILD_LIBS= $(BLIB16) $(BLIB32)
|
||||
BUILD_BINS= $(BINS16) $(BINS32)
|
||||
endif
|
||||
|
||||
3C503FLAGS= -DINCLUDE_3C503 # -DT503_SHMEM
|
||||
# Note that the suffix to MAKEROM_ is the (mixed case) basename of the ROM file
|
||||
MAKEROM_3c503= -3
|
||||
3C507FLAGS= -DINCLUDE_3C507
|
||||
3C509FLAGS= -DINCLUDE_3C509
|
||||
3C529FLAGS= -DINCLUDE_3C529
|
||||
3C595FLAGS= -DINCLUDE_3C595
|
||||
3C90XFLAGS= -DINCLUDE_3C90X
|
||||
CS89X0FLAGS= -DINCLUDE_CS89X0
|
||||
EEPROFLAGS= -DINCLUDE_EEPRO
|
||||
EEPRO100FLAGS= -DINCLUDE_EEPRO100
|
||||
EPIC100FLAGS= -DINCLUDE_EPIC100
|
||||
EXOS205FLAGS= -DINCLUDE_EXOS205
|
||||
LANCEFLAGS= -DINCLUDE_LANCE # Lance/PCI!
|
||||
NE2100FLAGS= -DINCLUDE_NE2100
|
||||
NEFLAGS= -DINCLUDE_NE -DNE_SCAN=0x300,0x280,0x320,0x340,0x380
|
||||
NS8390FLAGS= -DINCLUDE_NS8390 # NE2000/PCI!
|
||||
NI5010FLAGS= -DINCLUDE_NI5010
|
||||
NI5210FLAGS= -DINCLUDE_NI5210
|
||||
NI6510FLAGS= -DINCLUDE_NI6510
|
||||
RTL8139FLAGS= -DINCLUDE_RTL8139
|
||||
SK_G16FLAGS= -DINCLUDE_SK_G16
|
||||
SMC9000FLAGS= -DINCLUDE_SMC9000
|
||||
TIARAFLAGS= -DINCLUDE_TIARA
|
||||
DEPCAFLAGS= -DINCLUDE_DEPCA # -DDEPCA_MODEL=DEPCA -DDEPCA_RAM_BASE=0xd0000
|
||||
TULIPFLAGS= -DINCLUDE_TULIP
|
||||
OTULIPFLAGS= -DINCLUDE_OTULIP
|
||||
VIA_RHINEFLAGS= -DINCLUDE_VIA_RHINE
|
||||
WDFLAGS= -DINCLUDE_WD -DWD_DEFAULT_MEM=0xCC000
|
||||
W89C840FLAGS= -DINCLUDE_W89C840
|
||||
|
||||
# If you have not made any changes to the *.S files, AS86 need not be set.
|
||||
# (most people)
|
||||
# If you have made changes to the *.S files and you want to rebuild *loader.bin
|
||||
# and {floppy,com}load.bin and you have as86 from the ELKS Dev86 package (not
|
||||
# the one that normally comes with Linux) (not most people)
|
||||
#AS86= as86
|
||||
# If you have made changes to the *.S files and you want to rebuild *loader.bin
|
||||
# and {floppy,com}load.bin and you have nasm (not most people)
|
||||
#AS86= nasm
|
||||
|
||||
# if your as has trouble with the data32 directive, uncomment this
|
||||
# but note that the premade start*.o will be larger than necessary because it
|
||||
# contains some routines which may not be used
|
||||
#AS_PSEUDOS= n
|
||||
|
||||
SRCS= floppyload.S comload.S liloprefix.S loader.S start16.S start32.S serial.S startmpcc.S
|
||||
SRCS+= main.c pci.c osloader.c nfs.c misc.c ansiesc.c bootmenu.c config.c
|
||||
SRCS+= md5.c floppy.c
|
||||
|
||||
# ROM loaders: LZ version (prefix Z), PCI header version (prefix P)
|
||||
ifndef AS86
|
||||
RLOADER= rloader.bin.pre
|
||||
PRLOADER= prloader.bin.pre
|
||||
RZLOADER= rzloader.bin.pre
|
||||
PRZLOADER= przloader.bin.pre
|
||||
FLOPPYLOAD= floppyload.bin.pre
|
||||
COMLOAD= comload.bin.pre
|
||||
LILOPREFIX= liloprefix.bin.pre
|
||||
else
|
||||
RLOADER= bin/rloader.bin
|
||||
PRLOADER= bin/prloader.bin
|
||||
RZLOADER= bin/rzloader.bin
|
||||
PRZLOADER= bin/przloader.bin
|
||||
FLOPPYLOAD= bin/floppyload.bin
|
||||
COMLOAD= bin/comload.bin
|
||||
LILOPREFIX= bin/liloprefix.bin
|
||||
endif
|
||||
|
||||
ifeq ($(AS86),as86)
|
||||
LCPPFLAGS+= -DUSE_AS86
|
||||
LASFLAGS+= $(AS86FLAGS) -0
|
||||
LASBINARY:= -b
|
||||
endif
|
||||
ifeq ($(AS86),nasm)
|
||||
LCPPFLAGS+= -DUSE_NASM
|
||||
LASFLAGS+= $(NASMFLAGS) -fbin
|
||||
LASBINARY:= -o
|
||||
endif
|
||||
|
||||
ifeq ($(AS_PSEUDOS),n)
|
||||
START16= start16.o.pre
|
||||
START32= start32.o.pre
|
||||
else
|
||||
START16= bin16/start16.o
|
||||
START32= bin32/startmpcc.o
|
||||
endif
|
||||
|
||||
BOBJS16= bin16/main.o bin16/osloader.o bin16/misc.o bin16/bootmenu.o
|
||||
BOBJS16+= bin16/floppy.o bin16/timer.o
|
||||
BOBJS32= bin32/main.o bin32/osloader.o bin32/nfs.o bin32/misc.o
|
||||
BOBJS32+= bin32/ansiesc.o bin32/bootmenu.o bin32/md5.o bin32/floppy.o
|
||||
BOBJS32+= bin32/serial.o bin32/timer.o
|
||||
BLIB16= bin16/bootlib.a
|
||||
BLIB32= bin32/bootlib.a
|
||||
LIBS16= $(BLIB16) $(LIBC16)
|
||||
LIBS32= $(BLIB32) $(LIBC32) /usr/lib/gcc-lib/i386-redhat-linux/2.96/libgcc.a
|
||||
UTIL_LZHUF:= $(shell if [ -d ../contrib/compressor ]; then echo bin/lzhuf; fi)
|
||||
UTILS+= bin/makerom $(UTIL_LZHUF) bin/organon
|
||||
STDDEPS16= $(START16) $(BLIB16) $(UTILS)
|
||||
STDDEPS32= $(START32) $(BLIB32) $(UTILS)
|
||||
MAKEDEPS= Makefile Config Roms
|
||||
|
||||
CHECKSIZE= { read d1; read d1 d2 d3 size d4; [ $$size -gt $(ROMLIMIT) ] &&\
|
||||
{ $(RM) $@; echo "ERROR: code size exceeds limit!"; exit 1; }; exit 0; }
|
||||
|
||||
# Make sure that the relocation address is acceptable for all ROM sizes.
|
||||
# Setting it to 0x98000 leaves about 29kB of space for the Etherboot program.
|
||||
# The check is done based running 'size' on the binary, not ROM size, but
|
||||
# roughly this means a ROM of 16kB or a partially used ROM of 32kB,
|
||||
# remembering to compressed ROM images into account.
|
||||
# You may also set RELOCADDR to 0x88000 to avoid using 0x98000
|
||||
# because of other drivers (e.g. Disk On Chip). In that case, you may
|
||||
# only load 512kB of OS, or load in memory above 1MB.
|
||||
# Don't forget to choose an assembler because the loaders have to be rebuilt.
|
||||
ifndef RELOCADDR
|
||||
RELOCADDR=0x98000
|
||||
#RELOCADDR=0xe0000
|
||||
endif
|
||||
|
||||
# Evaluate ROMLIMIT only once - it is constant during the make run.
|
||||
# Note that the 3K safety margin below is for the 1K extended BIOS data area
|
||||
# and for the Etherboot runtime stack. Under normal situations, 2K of stack
|
||||
# are rarely needed. If you experience strange behaviour in functions that use
|
||||
# many local variables or that call functions that do, check for stack overrun!
|
||||
# Make sure that the normal case needs no perl interpreter - if someone uses a
|
||||
# different RELOCADDR, then he has perl installed anyways (the shell cannot
|
||||
# deal with hex numbers, as test/eval don't support non-decimal integers).
|
||||
ifeq ($(RELOCADDR),0x98000)
|
||||
ROMLIMIT=29696
|
||||
else
|
||||
ROMLIMIT:=$(shell perl -e 'print 0x10000 - 3072 - ($(RELOCADDR) & 0xFFFF), "\n";')
|
||||
endif
|
||||
|
||||
# Start of targets
|
||||
|
||||
all: $(UTILS) $(BUILD_LIBS) allbins
|
||||
|
||||
include Roms
|
||||
|
||||
# We need allbins because $(BINS16) and $(BINS32) are not defined until
|
||||
# the Makefile fragment "Roms" is read.
|
||||
|
||||
allbins: $(BUILD_BINS)
|
||||
|
||||
# Common files
|
||||
|
||||
$(BLIB16): $(BOBJS16)
|
||||
$(AR16) rv $@ $(BOBJS16)
|
||||
$(RANLIB16) $@
|
||||
|
||||
$(BLIB32): $(BOBJS32)
|
||||
$(AR32) rv $@ $(BOBJS32)
|
||||
$(RANLIB32) $@
|
||||
|
||||
bin16/main.o: main.c etherboot.h osdep.h nic.h
|
||||
bin32/main.o: main.c etherboot.h osdep.h nic.h
|
||||
|
||||
bin16/osloader.o: osloader.c etherboot.h osdep.h
|
||||
bin32/osloader.o: osloader.c etherboot.h osdep.h
|
||||
|
||||
# NFS currently makes no sense for Etherboot/16
|
||||
bin32/nfs.o: nfs.c etherboot.h osdep.h nic.h
|
||||
|
||||
bin16/misc.o: misc.c etherboot.h osdep.h
|
||||
bin32/misc.o: misc.c etherboot.h osdep.h
|
||||
|
||||
# ANSIESC is not supported for Etherboot/16
|
||||
bin32/ansiesc.o: ansiesc.c etherboot.h osdep.h
|
||||
|
||||
bin16/bootmenu.o: bootmenu.c etherboot.h osdep.h
|
||||
bin32/bootmenu.o: bootmenu.c etherboot.h osdep.h
|
||||
|
||||
# Password support is not available for Etherboot/16
|
||||
bin32/md5.o: md5.c etherboot.h osdep.h
|
||||
|
||||
bin16/floppy.o: floppy.c etherboot.h osdep.h
|
||||
bin32/floppy.o: floppy.c etherboot.h osdep.h
|
||||
|
||||
bin16/timer.o: timer.c timer.h etherboot.h osdep.h
|
||||
bin32/timer.o: timer.c timer.h etherboot.h osdep.h
|
||||
|
||||
bin32/inthw.o: inthw.c
|
||||
|
||||
# PCI support code (common to all PCI drivers)
|
||||
|
||||
bin32/pci.o: pci.c pci.h
|
||||
|
||||
# Do not add driver specific dependencies here unless it's something the
|
||||
# genrules.pl script *can't* deal with, i.e. if it is not C code.
|
||||
|
||||
# Prepended loaders
|
||||
|
||||
#ifndef AS86
|
||||
#$(RLOADER) $(RZLOADER) $(PRLOADER) $(PRZLOADER): $(MAKEDEPS)
|
||||
# @if [ $(RELOCADDR) != 0x98000 ]; then echo Non-standard RELOCADDR, must assemble $@; exit 1; fi
|
||||
# $(TOUCH) $@
|
||||
#else
|
||||
#bin/rloader.s: loader.S $(MAKEDEPS)
|
||||
# $(CPP) $(LCPPFLAGS) $(LCONFIG) -o $@ $<
|
||||
#
|
||||
#bin/rzloader.s: loader.S $(MAKEDEPS)
|
||||
# $(CPP) $(LCPPFLAGS) $(LCONFIG) -DZLOADER -o $@ $<
|
||||
#
|
||||
#bin/prloader.s: loader.S $(MAKEDEPS)
|
||||
# $(CPP) $(LCPPFLAGS) $(LCONFIG) -DPCI_PNP_HEADER -o $@ $<
|
||||
#
|
||||
#bin/przloader.s: loader.S $(MAKEDEPS)
|
||||
# $(CPP) $(LCPPFLAGS) $(LCONFIG) -DPCI_PNP_HEADER -DZLOADER -o $@ $<
|
||||
#endif
|
||||
|
||||
# Floppy loader
|
||||
|
||||
ifdef AS86
|
||||
bin/floppyload.s: floppyload.S $(MAKEDEPS)
|
||||
$(CPP) $(LCPPFLAGS) -o $@ $<
|
||||
endif
|
||||
|
||||
# COM loader
|
||||
|
||||
ifdef AS86
|
||||
bin/comload.s: comload.S $(MAKEDEPS)
|
||||
$(CPP) $(LCPPFLAGS) -o $@ $<
|
||||
endif
|
||||
|
||||
# LILO prefix:
|
||||
|
||||
ifdef AS86
|
||||
bin/liloprefix.s: liloprefix.S $(MAKEDEPS)
|
||||
$(CPP) $(LCPPFLAGS) -o $@ $<
|
||||
endif
|
||||
|
||||
# Utilities
|
||||
|
||||
bin/makerom: makerom.c
|
||||
$(GCC) -O2 -o $@ makerom.c
|
||||
|
||||
bin/organon: organon.c
|
||||
$(GCC) -o $@ organon.c
|
||||
|
||||
bin/lzhuf: ../contrib/compressor/lzhuf.c
|
||||
$(GCC) -O2 -DENCODE -DDECODE -DMAIN -DVERBOSE -o $@ $<
|
||||
|
||||
# Roms file
|
||||
|
||||
Roms: NIC genrules.pl
|
||||
@chmod +x genrules.pl
|
||||
./genrules.pl NIC > $@
|
||||
|
||||
# Pattern Rules
|
||||
|
||||
# general rules for compiling/assembling source files
|
||||
bin16/%.o: %.c $(MAKEDEPS)
|
||||
$(CC16) $(CFLAGS16) -o $@ -c $<
|
||||
|
||||
bin32/%.o: %.c $(MAKEDEPS)
|
||||
$(CC32) $(CFLAGS32) -o $@ -c $<
|
||||
|
||||
bin16/%.o: %.S $(MAKEDEPS)
|
||||
$(CC16) $(CFLAGS16) $(ASFLAGS16) -c -o $@ $<
|
||||
|
||||
bin32/%.o: %.S $(MAKEDEPS)
|
||||
$(CPP) $(CFLAGS32) $< | $(AS) $(ASFLAGS32) -o $@
|
||||
|
||||
# general rule for .bin (plain binary loader code), may be overridden
|
||||
ifdef AS86
|
||||
bin/%.bin: bin/%.s
|
||||
$(AS86) $(LASFLAGS) $(LASBINARY) $@ $<
|
||||
endif
|
||||
|
||||
# general rule for .huf (compressed binary code), may be overridden
|
||||
%.huf: %.img
|
||||
bin/lzhuf e $< $@
|
||||
|
||||
# general rules for normal/compressed ROM images, may be overridden
|
||||
bin16/%.rom: bin16/%.img $(RLOADER)
|
||||
cat $(RLOADER) $< > $@
|
||||
bin/makerom $(MAKEROM_$*) -i$(IDENT16) $@
|
||||
|
||||
bin32/%.rom: bin32/%.img $(RLOADER)
|
||||
cat $(RLOADER) $< > $@
|
||||
bin/makerom $(MAKEROM_$*) -i$(IDENT32) $@
|
||||
|
||||
bin16/%.lzrom: bin16/%.huf $(RZLOADER)
|
||||
cat $(RZLOADER) $< > $@
|
||||
bin/makerom $(MAKEROM_$*) -i$(IDENT16) $@
|
||||
|
||||
bin32/%.lzrom: bin32/%.huf $(RZLOADER)
|
||||
cat $(RZLOADER) $< > $@
|
||||
bin/makerom $(MAKEROM_$*) -i$(IDENT32) $@
|
||||
|
||||
# rules to write the .rom/.lzrom image onto a blank floppy
|
||||
# You must give the directory name, e.g. use bin32/rtl8139.lzfd0 as the target.
|
||||
%.fd0: %.rom $(FLOPPYLOAD)
|
||||
cat $(FLOPPYLOAD) $< > /dev/fd0
|
||||
|
||||
%.lzfd0: %.lzrom $(FLOPPYLOAD)
|
||||
cat $(FLOPPYLOAD) $< > /dev/fd0
|
||||
|
||||
# rules to generate a .com executable
|
||||
# You must give the directory name, e.g. use bin32/rtl8139.com as the target.
|
||||
%.com: %.lzrom $(COMLOAD)
|
||||
cat $(COMLOAD) $< > $@
|
||||
|
||||
# rules to make a floppy image (padding to fill an even number of cylinders).
|
||||
# VMware reports floppy image read errors if it cannot read ahead 36 sectors,
|
||||
# probably because the floppyload.S code reads up to that number of sectors in
|
||||
# a single request. Not that 18k matters much these days...
|
||||
# You must give the directory name, e.g. use bin32/rtl8139.fdimg as the target.
|
||||
%.fdimg: %.rom $(FLOPPYLOAD)
|
||||
cat $(FLOPPYLOAD) $< > $@.x
|
||||
dd if=$@.x of=$@ bs=36k conv=sync 2> /dev/null
|
||||
$(RM) $@.x
|
||||
|
||||
%.lzfdimg: %.lzrom $(FLOPPYLOAD)
|
||||
cat $(FLOPPYLOAD) $< > $@.x
|
||||
dd if=$@.x of=$@ bs=36k conv=sync 2> /dev/null
|
||||
$(RM) $@.x
|
||||
|
||||
# rules to make a LILO-bootable image
|
||||
%.lilo: %.rom $(LILOPREFIX)
|
||||
cat $(LILOPREFIX) $< /dev/zero | head -c 64k > $@
|
||||
|
||||
%.lzlilo: %.lzrom $(LILOPREFIX)
|
||||
cat $(LILOPREFIX) $< /dev/zero | head -c 64k > $@
|
||||
|
||||
# Housekeeping
|
||||
|
||||
# To make sure that this actually builds a start32.o.pre with all options set,
|
||||
# you have to make sure that -DFLOPPY -DANSIESC -DCONSOLE_DUAL are in CFLAGS32.
|
||||
precompiled: bin/rloader.bin bin/rzloader.bin bin/prloader.bin bin/przloader.bin bin/floppyload.bin bin/comload.bin bin16/start16.o bin32/start32.o bin/liloprefix.bin
|
||||
cp -p bin/rloader.bin rloader.bin.pre
|
||||
cp -p bin/rzloader.bin rzloader.bin.pre
|
||||
cp -p bin/prloader.bin prloader.bin.pre
|
||||
cp -p bin/przloader.bin przloader.bin.pre
|
||||
cp -p bin/floppyload.bin floppyload.bin.pre
|
||||
cp -p bin/comload.bin comload.bin.pre
|
||||
cp -p bin16/start16.o start16.o.pre
|
||||
cp -p bin32/start32.o start32.o.pre
|
||||
cp -p bin/liloprefix.bin liloprefix.bin.pre
|
||||
|
||||
clean:
|
||||
$(RM) $(UTILS) bin/*.s bin/*.bin
|
||||
$(RM) $(BLIB16) $(BLIB32)
|
||||
$(RM) bin16/*.o bin32/*.o bin16/*.tmp bin32/*.tmp
|
||||
$(RM) bin16/*.img bin32/*.img bin16/*.huf bin32/*.huf
|
||||
$(RM) bin16/*.rom bin32/*.rom bin16/*.lzrom bin32/*.lzrom
|
||||
$(RM) bin16/*.com bin32/*.com
|
||||
$(RM) bin16/*.fdimg bin32/*.fdimg bin16/*.lzfdimg bin32/*.lzfdimg
|
||||
$(RM) bin16/*.lilo bin32/*.lilo bin16/*.lzlilo bin32/*.lzlilo
|
||||
$(RM) bin32/*.hex
|
||||
$(RM) bin32/*.asm
|
||||
$(RM) bin32/*.map
|
||||
|
||||
tarball:
|
||||
(echo -n $(VERSION) ''; date -u +'%Y-%m-%d') > ../VERSION
|
||||
(cd ..; tar cf /tmp/mpccboot-$(VERSION).tar --exclude CVS mpccboot)
|
||||
bzip2 -9 < /tmp/mpccboot-$(VERSION).tar > /tmp/mpccboot-$(VERSION).tar.bz2
|
||||
gzip -9 < /tmp/mpccboot-$(VERSION).tar > /tmp/mpccboot-$(VERSION).tar.gz
|
||||
|
||||
version:
|
||||
@echo $(VERSION)
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,52 @@
|
|||
From: "Paolo Marini" <paolom@prisma-eng.it>
|
||||
Subject: Etherboot on bare metal
|
||||
Date: Tue, 10 Apr 2001 23:19:19 +0200
|
||||
Organization: Prisma Engineering srl
|
||||
|
||||
Hi Ken,
|
||||
I have ported Etherboot on an embedded, biosless platform and would like
|
||||
to contribute the code.
|
||||
|
||||
Essentially, the hardware I was running Etherboot is a Pentium based
|
||||
embedded system, with an Intel Chipset, *but* without serial, VGA,
|
||||
keyboard etc., only an 82559 Intel (custom) Ethernet controller (I debug
|
||||
it with the etheral Ethernet packet analyser and an emulator).
|
||||
|
||||
What I did was:
|
||||
|
||||
a.. integrate the init.s file within the firmware, with GDT
|
||||
(re)initialisation (a simple and single entry point taking control of
|
||||
the boot process)
|
||||
b.. provide some stupid BIOS stubs in order to let the OS boot and
|
||||
still belive that an INT10 call goes to the BIOS
|
||||
c.. provide some basic functions to Etherboot, like timer (I used the
|
||||
Pentium TSC internal counter)
|
||||
d.. hardwire in the code information about the RAM size
|
||||
The BIOS stubs are enough to boot Linux, pSOS and QNX with bootp. QNX is
|
||||
somewhat difficult to load, because the i82559 driver tries to find the
|
||||
component using the BIOS32 calls, so I had to patch it.
|
||||
|
||||
what i I got from the original firmware is the PCI initialisation and
|
||||
resource (I/O, interrupts, memory) allocation.
|
||||
|
||||
I send you what I changed, that is, the initialisation code and the
|
||||
misc.c file containing the timer, and the makefile (I don't remember
|
||||
exactly the options I used to compile all).
|
||||
|
||||
Of course, it is only a good starting point for anyone wanting to
|
||||
implement a bootp client on a biosless platform; some integration work
|
||||
still needs to be done.
|
||||
|
||||
Ciao
|
||||
Paolo
|
||||
|
||||
And in a subsequent email:
|
||||
|
||||
I worked with version 4.6.12, but the real modifications involve the
|
||||
init.S file, which I think is quite sstable between releases. I forgot
|
||||
to say that my entry point (symbol _start in init.s) assumes the
|
||||
processor is already in protected mode.
|
||||
|
||||
[The only difference between main.c and misc.c from those in Etherboot
|
||||
4.6.12 seems to be the deletion of eth_reset(). This may be of use to
|
||||
others trying to make these changes work on more recent releases. Ken]
|
|
@ -0,0 +1,351 @@
|
|||
/**************************************************************************
|
||||
MISC Support Routines
|
||||
**************************************************************************/
|
||||
|
||||
#include "etherboot.h"
|
||||
|
||||
/**************************************************************************
|
||||
SLEEP
|
||||
**************************************************************************/
|
||||
void sleep(int secs)
|
||||
{
|
||||
unsigned long tmo;
|
||||
|
||||
for (tmo = currticks()+secs*TICKS_PER_SEC; currticks() < tmo; )
|
||||
/* Nothing */;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
TWIDDLE
|
||||
**************************************************************************/
|
||||
void twiddle()
|
||||
{
|
||||
static unsigned long lastticks = 0;
|
||||
static int count=0;
|
||||
static const char tiddles[]="-\\|/";
|
||||
unsigned long ticks;
|
||||
if ((ticks = currticks()) == lastticks)
|
||||
return;
|
||||
lastticks = ticks;
|
||||
putchar(tiddles[(count++)&3]);
|
||||
putchar('\b');
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
STRCASECMP (not entirely correct, but this will do for our purposes)
|
||||
**************************************************************************/
|
||||
int strcasecmp(a,b)
|
||||
char *a, *b;
|
||||
{
|
||||
while (*a && *b && (*a & ~0x20) == (*b & ~0x20)) {a++; b++; }
|
||||
return((*a & ~0x20) - (*b & ~0x20));
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
PRINTF and friends
|
||||
|
||||
Formats:
|
||||
%[#]X - 4 bytes long (8 hex digits)
|
||||
%[#]x - 2 bytes int (4 hex digits)
|
||||
- optional # prefixes 0x
|
||||
%b - 1 byte int (2 hex digits)
|
||||
%d - decimal int
|
||||
%c - char
|
||||
%s - string
|
||||
%I - Internet address in x.x.x.x notation
|
||||
Note: width specification not supported
|
||||
**************************************************************************/
|
||||
static char *do_printf(char *buf, const char *fmt, const int *dp)
|
||||
{
|
||||
register char *p;
|
||||
int alt;
|
||||
char tmp[16];
|
||||
static const char hex[]="0123456789ABCDEF";
|
||||
|
||||
while (*fmt) {
|
||||
if (*fmt == '%') { /* switch() uses more space */
|
||||
alt = 0;
|
||||
fmt++;
|
||||
if (*fmt == '#') {
|
||||
alt = 1;
|
||||
fmt++;
|
||||
}
|
||||
if (*fmt == 'X') {
|
||||
const long *lp = (const long *)dp;
|
||||
register long h = *lp++;
|
||||
dp = (const int *)lp;
|
||||
if (alt) {
|
||||
*buf++ = '0';
|
||||
*buf++ = 'x';
|
||||
}
|
||||
*(buf++) = hex[(h>>28)& 0x0F];
|
||||
*(buf++) = hex[(h>>24)& 0x0F];
|
||||
*(buf++) = hex[(h>>20)& 0x0F];
|
||||
*(buf++) = hex[(h>>16)& 0x0F];
|
||||
*(buf++) = hex[(h>>12)& 0x0F];
|
||||
*(buf++) = hex[(h>>8)& 0x0F];
|
||||
*(buf++) = hex[(h>>4)& 0x0F];
|
||||
*(buf++) = hex[h& 0x0F];
|
||||
}
|
||||
if (*fmt == 'x') {
|
||||
register int h = *(dp++);
|
||||
if (alt) {
|
||||
*buf++ = '0';
|
||||
*buf++ = 'x';
|
||||
}
|
||||
*(buf++) = hex[(h>>12)& 0x0F];
|
||||
*(buf++) = hex[(h>>8)& 0x0F];
|
||||
*(buf++) = hex[(h>>4)& 0x0F];
|
||||
*(buf++) = hex[h& 0x0F];
|
||||
}
|
||||
if (*fmt == 'b') {
|
||||
register int h = *(dp++);
|
||||
*(buf++) = hex[(h>>4)& 0x0F];
|
||||
*(buf++) = hex[h& 0x0F];
|
||||
}
|
||||
if (*fmt == 'd') {
|
||||
register int dec = *(dp++);
|
||||
p = tmp;
|
||||
if (dec < 0) {
|
||||
*(buf++) = '-';
|
||||
dec = -dec;
|
||||
}
|
||||
do {
|
||||
*(p++) = '0' + (dec%10);
|
||||
dec = dec/10;
|
||||
} while(dec);
|
||||
while ((--p) >= tmp) *(buf++) = *p;
|
||||
}
|
||||
if (*fmt == 'I') {
|
||||
union {
|
||||
long l;
|
||||
unsigned char c[4];
|
||||
} u;
|
||||
const long *lp = (const long *)dp;
|
||||
u.l = *lp++;
|
||||
dp = (const int *)lp;
|
||||
buf = sprintf(buf,"%d.%d.%d.%d",
|
||||
u.c[0], u.c[1], u.c[2], u.c[3]);
|
||||
}
|
||||
if (*fmt == 'c')
|
||||
*(buf++) = *(dp++);
|
||||
if (*fmt == 's') {
|
||||
p = (char *)*dp++;
|
||||
while (*p) *(buf++) = *p++;
|
||||
}
|
||||
} else *(buf++) = *fmt;
|
||||
fmt++;
|
||||
}
|
||||
*buf = '\0';
|
||||
return(buf);
|
||||
}
|
||||
|
||||
char *sprintf(char *buf, const char *fmt, ...)
|
||||
{
|
||||
return do_printf(buf, fmt, ((const int *)&fmt)+1);
|
||||
}
|
||||
|
||||
void printf(const char *fmt, ...)
|
||||
{
|
||||
char buf[120], *p;
|
||||
|
||||
p = buf;
|
||||
do_printf(buf, fmt, ((const int *)&fmt)+1);
|
||||
while (*p) putchar(*p++);
|
||||
}
|
||||
|
||||
#ifdef IMAGE_MENU
|
||||
/**************************************************************************
|
||||
INET_ATON - Convert an ascii x.x.x.x to binary form
|
||||
**************************************************************************/
|
||||
int inet_aton(char *p, in_addr *i)
|
||||
{
|
||||
unsigned long ip = 0;
|
||||
int val;
|
||||
if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
|
||||
if (*p != '.') return(0);
|
||||
p++;
|
||||
ip = val;
|
||||
if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
|
||||
if (*p != '.') return(0);
|
||||
p++;
|
||||
ip = (ip << 8) | val;
|
||||
if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
|
||||
if (*p != '.') return(0);
|
||||
p++;
|
||||
ip = (ip << 8) | val;
|
||||
if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
|
||||
i->s_addr = htonl((ip << 8) | val);
|
||||
return(1);
|
||||
}
|
||||
|
||||
#endif /* IMAGE_MENU */
|
||||
|
||||
int getdec(char **ptr)
|
||||
{
|
||||
char *p = *ptr;
|
||||
int ret=0;
|
||||
if ((*p < '0') || (*p > '9')) return(-1);
|
||||
while ((*p >= '0') && (*p <= '9')) {
|
||||
ret = ret*10 + (*p - '0');
|
||||
p++;
|
||||
}
|
||||
*ptr = p;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
#define K_RDWR 0x60 /* keyboard data & cmds (read/write) */
|
||||
#define K_STATUS 0x64 /* keyboard status */
|
||||
#define K_CMD 0x64 /* keybd ctlr command (write-only) */
|
||||
|
||||
#define K_OBUF_FUL 0x01 /* output buffer full */
|
||||
#define K_IBUF_FUL 0x02 /* input buffer full */
|
||||
|
||||
#define KC_CMD_WIN 0xd0 /* read output port */
|
||||
#define KC_CMD_WOUT 0xd1 /* write output port */
|
||||
#define KB_SET_A20 0xdf /* enable A20,
|
||||
enable output buffer full interrupt
|
||||
enable data line
|
||||
disable clock line */
|
||||
#define KB_UNSET_A20 0xdd /* enable A20,
|
||||
enable output buffer full interrupt
|
||||
enable data line
|
||||
disable clock line */
|
||||
#ifndef IBM_L40
|
||||
static void empty_8042(void)
|
||||
{
|
||||
unsigned long time;
|
||||
char st;
|
||||
|
||||
time = currticks() + TICKS_PER_SEC; /* max wait of 1 second */
|
||||
while ((((st = inb(K_CMD)) & K_OBUF_FUL) ||
|
||||
(st & K_IBUF_FUL)) &&
|
||||
currticks() < time)
|
||||
inb(K_RDWR);
|
||||
}
|
||||
#endif IBM_L40
|
||||
|
||||
/*
|
||||
* Gate A20 for high memory
|
||||
*/
|
||||
void gateA20_set(void)
|
||||
{
|
||||
#ifdef IBM_L40
|
||||
outb(0x2, 0x92);
|
||||
#else /* IBM_L40 */
|
||||
empty_8042();
|
||||
outb(KC_CMD_WOUT, K_CMD);
|
||||
empty_8042();
|
||||
outb(KB_SET_A20, K_RDWR);
|
||||
empty_8042();
|
||||
#endif /* IBM_L40 */
|
||||
}
|
||||
|
||||
#ifdef TAGGED_IMAGE
|
||||
/*
|
||||
* Unset Gate A20 for high memory - some operating systems (mainly old 16 bit
|
||||
* ones) don't expect it to be set by the boot loader.
|
||||
*/
|
||||
void gateA20_unset(void)
|
||||
{
|
||||
#ifdef IBM_L40
|
||||
outb(0x0, 0x92);
|
||||
#else /* IBM_L40 */
|
||||
empty_8042();
|
||||
outb(KC_CMD_WOUT, K_CMD);
|
||||
empty_8042();
|
||||
outb(KB_UNSET_A20, K_RDWR);
|
||||
empty_8042();
|
||||
#endif /* IBM_L40 */
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ETHERBOOT32
|
||||
/* Serial console is only implemented in ETHERBOOT32 for now */
|
||||
void
|
||||
putchar(int c)
|
||||
{
|
||||
#ifndef ANSIESC
|
||||
if (c == '\n')
|
||||
putchar('\r');
|
||||
#endif
|
||||
|
||||
#ifdef CONSOLE_CRT
|
||||
#ifdef ANSIESC
|
||||
handleansi(c);
|
||||
#else
|
||||
putc(c);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CONSOLE_SERIAL
|
||||
#ifdef ANSIESC
|
||||
if (c == '\n')
|
||||
serial_putc('\r');
|
||||
#endif
|
||||
serial_putc(c);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
GETCHAR - Read the next character from the console WITHOUT ECHO
|
||||
**************************************************************************/
|
||||
int
|
||||
getchar(void)
|
||||
{
|
||||
int c = 256;
|
||||
|
||||
#if defined CONSOLE_CRT || defined CONSOLE_SERIAL
|
||||
do {
|
||||
#ifdef CONSOLE_CRT
|
||||
if (ischar())
|
||||
c = getc();
|
||||
#endif
|
||||
#ifdef CONSOLE_SERIAL
|
||||
if (serial_ischar())
|
||||
c = serial_getc();
|
||||
#endif
|
||||
} while (c==256);
|
||||
if (c == '\r')
|
||||
c = '\n';
|
||||
#endif
|
||||
return c;
|
||||
}
|
||||
|
||||
int
|
||||
iskey(void)
|
||||
{
|
||||
#ifdef CONSOLE_CRT
|
||||
if (ischar())
|
||||
return 1;
|
||||
#endif
|
||||
#ifdef CONSOLE_SERIAL
|
||||
if (serial_ischar())
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif /* ETHERBOOT32 */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
||||
|
||||
#include <asm/msr.h>
|
||||
|
||||
#define CPUCLOCK 166
|
||||
|
||||
unsigned long currticks(void)
|
||||
{
|
||||
register unsigned long l, h;
|
||||
long long unsigned p;
|
||||
long long unsigned hh,ll;
|
||||
|
||||
rdtsc(l, h);
|
||||
ll = l, hh = h;
|
||||
|
||||
p = (ll + hh * 0x100000000LL) * 182 / (CPUCLOCK * 100000LL);
|
||||
return (unsigned)p;
|
||||
}
|
||||
|
|
@ -0,0 +1,756 @@
|
|||
/* #defines because ljmp wants a number, probably gas bug */
|
||||
/* .equ KERN_CODE_SEG,_pmcs-_gdt */
|
||||
#define KERN_CODE_SEG 0x08
|
||||
.equ KERN_DATA_SEG,_pmds-_gdt
|
||||
/* .equ REAL_CODE_SEG,_rmcs-_gdt */
|
||||
#define REAL_CODE_SEG 0x18
|
||||
.equ REAL_DATA_SEG,_rmds-_gdt
|
||||
.equ CR0_PE,1
|
||||
|
||||
#ifdef GAS291
|
||||
#define DATA32 data32;
|
||||
#define ADDR32 addr32;
|
||||
#define LJMPI(x) ljmp x
|
||||
#else
|
||||
#define DATA32 data32
|
||||
#define ADDR32 addr32
|
||||
/* newer GAS295 require #define LJMPI(x) ljmp *x */
|
||||
#define LJMPI(x) ljmp x
|
||||
#endif
|
||||
|
||||
#define PIC1_VBS 0x08 /* PIC1 interrupts start at vector 64 */
|
||||
#define PIC2_VBS 0x70 /* PIC1 interrupts start at vector 112 */
|
||||
|
||||
/*
|
||||
* NOTE: if you write a subroutine that is called from C code (gcc/egcs),
|
||||
* then you only have to take care of %ebx, %esi, %edi and %ebp. These
|
||||
* registers must not be altered under any circumstance. All other registers
|
||||
* may be clobbered without any negative side effects. If you don't follow
|
||||
* this rule then you'll run into strange effects that only occur on some
|
||||
* gcc versions (because the register allocator may use different registers).
|
||||
*
|
||||
* All the data32 prefixes for the ljmp instructions are necessary, because
|
||||
* the assembler emits code with a relocation address of 0. This means that
|
||||
* all destinations are initially negative, which the assembler doesn't grok,
|
||||
* because for some reason negative numbers don't fit into 16 bits. The addr32
|
||||
* prefixes are there for the same reasons, because otherwise the memory
|
||||
* references are only 16 bit wide. Theoretically they are all superfluous.
|
||||
* One last note about prefixes: the data32 prefixes on all call _real_to_prot
|
||||
* instructions could be removed if the _real_to_prot function is changed to
|
||||
* deal correctly with 16 bit return addresses. I tried it, but failed.
|
||||
*/
|
||||
|
||||
/**************************************************************************
|
||||
START - Where all the fun begins....
|
||||
**************************************************************************/
|
||||
/* this must be the first thing in the file because we enter from the top */
|
||||
.global _start
|
||||
.code32
|
||||
_start:
|
||||
cli
|
||||
|
||||
/* load new IDT and GDT */
|
||||
lgdt gdtarg
|
||||
lidt Idt_Reg
|
||||
/* flush prefetch queue, and reload %cs:%eip */
|
||||
ljmp $KERN_CODE_SEG,$1f
|
||||
1:
|
||||
|
||||
/* reload other segment registers */
|
||||
movl $KERN_DATA_SEG,%eax
|
||||
movl %eax,%ds
|
||||
movl %eax,%es
|
||||
movl %eax,%ss
|
||||
movl $stktop,%esp
|
||||
|
||||
/* program the PITs in order to stop them */
|
||||
mov $0x30,%al
|
||||
out %al,$0x43
|
||||
out %al,$0x40
|
||||
mov $0x70,%al
|
||||
out %al,$0x43
|
||||
out %al,$0x41
|
||||
mov $0xf0,%al
|
||||
out %al,$0x43
|
||||
out %al,$0x42
|
||||
|
||||
call main
|
||||
/* fall through */
|
||||
|
||||
.globl exit
|
||||
exit:
|
||||
2:
|
||||
ljmp $KERN_CODE_SEG,$2b
|
||||
|
||||
/**************************************************************************
|
||||
MEMSIZE - Determine size of extended memory
|
||||
**************************************************************************/
|
||||
.globl memsize
|
||||
memsize:
|
||||
#if 0
|
||||
pushl %ebx
|
||||
pushl %esi
|
||||
pushl %edi
|
||||
call _prot_to_real
|
||||
.code16
|
||||
movw $0xe801,%ax
|
||||
stc
|
||||
int $0x15
|
||||
jc 1f
|
||||
andl $0xffff,%eax
|
||||
andl $0xffff,%ebx
|
||||
shll $6,%ebx
|
||||
addl %ebx,%eax
|
||||
jmp 2f
|
||||
1:
|
||||
movw $0x8800,%ax
|
||||
int $0x15
|
||||
andl $0xffff,%eax
|
||||
2:
|
||||
movl %eax,%esi
|
||||
DATA32 call _real_to_prot
|
||||
.code32
|
||||
movl %esi,%eax
|
||||
popl %edi
|
||||
popl %esi
|
||||
popl %ebx
|
||||
#else
|
||||
mov $32768,%eax
|
||||
#endif
|
||||
ret
|
||||
|
||||
/**************************************************************************
|
||||
XSTART - Transfer control to the kernel just loaded
|
||||
**************************************************************************/
|
||||
.code16
|
||||
|
||||
.globl _int08_handler
|
||||
_int08_handler:
|
||||
movb $0x20, %al
|
||||
outb %al, $0x20
|
||||
iret
|
||||
|
||||
.globl _int10_handler
|
||||
_int10_handler:
|
||||
cmp $0x3, %ah
|
||||
jnz _int10_04
|
||||
mov $0x0, %dx
|
||||
mov $0x0, %cx
|
||||
iret
|
||||
_int10_04:
|
||||
cmp $0x4, %ah
|
||||
jnz _int10_05
|
||||
mov $0x0, %ah
|
||||
iret
|
||||
_int10_05:
|
||||
cmp $0x5, %ah
|
||||
jnz _int10_08
|
||||
mov $0x0, %al
|
||||
iret
|
||||
_int10_08:
|
||||
cmp $0x8, %ah
|
||||
jnz _int10_0D
|
||||
mov $0x20, %al
|
||||
mov $0x7, %ah
|
||||
iret
|
||||
_int10_0D:
|
||||
cmp $0xD, %ah
|
||||
jnz _int10_0F
|
||||
mov $0x0, %al
|
||||
iret
|
||||
_int10_0F:
|
||||
cmp $0xF, %ah
|
||||
jnz _int10_XX
|
||||
mov $0xb, %al
|
||||
mov $80, %ah
|
||||
mov $0, %bh
|
||||
_int10_XX:
|
||||
iret
|
||||
|
||||
.globl _int11_handler
|
||||
_int11_handler:
|
||||
mov $0x22, %ax
|
||||
iret
|
||||
|
||||
.globl _int12_handler
|
||||
_int12_handler:
|
||||
mov $640, %ax
|
||||
iret
|
||||
|
||||
.globl _int13_handler
|
||||
_int13_handler:
|
||||
clc
|
||||
mov $0, %ah
|
||||
iret
|
||||
|
||||
.globl _int14_handler
|
||||
_int14_handler:
|
||||
iret
|
||||
|
||||
.globl _int15_handler
|
||||
_int15_handler:
|
||||
cmp $0xe801,%ax
|
||||
jz _int15_008
|
||||
cmp $0x0, %ah
|
||||
jz _int15_000
|
||||
cmp $0x1, %ah
|
||||
jz _int15_000
|
||||
cmp $0x2, %ah
|
||||
jz _int15_000
|
||||
cmp $0x3, %ah
|
||||
jz _int15_000
|
||||
cmp $0xf, %ah
|
||||
jz _int15_000
|
||||
cmp $0x21, %ah
|
||||
jz _int15_000
|
||||
cmp $0x40, %ah
|
||||
jz _int15_000
|
||||
cmp $0x41, %ah
|
||||
jz _int15_000
|
||||
cmp $0x42, %ah
|
||||
jz _int15_000
|
||||
cmp $0x43, %ah
|
||||
jz _int15_000
|
||||
cmp $0x44, %ah
|
||||
jz _int15_000
|
||||
cmp $0x80, %ah
|
||||
jz _int15_001
|
||||
cmp $0x81, %ah
|
||||
jz _int15_001
|
||||
cmp $0x82, %ah
|
||||
jz _int15_002
|
||||
cmp $0x83, %ah
|
||||
jz _int15_003
|
||||
cmp $0x84, %ah
|
||||
jz _int15_000
|
||||
cmp $0x85, %ah
|
||||
jz _int15_004
|
||||
cmp $0x86, %ah
|
||||
jz _int15_003
|
||||
cmp $0x87, %ah
|
||||
jz _int15_005
|
||||
cmp $0x88, %ah
|
||||
jz _int15_006
|
||||
cmp $0x89, %ah
|
||||
jz _int15_005
|
||||
cmp $0x90, %ah
|
||||
jz _int15_007
|
||||
cmp $0xc0, %ah
|
||||
jz _int15_000
|
||||
cmp $0xc1, %ah
|
||||
jz _int15_000
|
||||
cmp $0xc2, %ah
|
||||
jz _int15_000
|
||||
cmp $0xc3, %ah
|
||||
jz _int15_000
|
||||
cmp $0xc4, %ah
|
||||
jz _int15_000
|
||||
iret
|
||||
|
||||
_int15_000:
|
||||
mov $0x86, %ah
|
||||
stc
|
||||
iret
|
||||
|
||||
_int15_001:
|
||||
mov $0, %bx
|
||||
mov $0, %cx
|
||||
iret
|
||||
|
||||
_int15_002:
|
||||
mov $0, %bx
|
||||
iret
|
||||
|
||||
_int15_003:
|
||||
clc
|
||||
iret
|
||||
|
||||
_int15_004:
|
||||
mov $0, %al
|
||||
iret
|
||||
|
||||
_int15_005:
|
||||
mov $0, %ah
|
||||
clc
|
||||
cmp $0, %ah
|
||||
iret
|
||||
|
||||
_int15_006:
|
||||
mov $0xf000, %ax
|
||||
iret
|
||||
|
||||
_int15_007:
|
||||
stc
|
||||
iret
|
||||
|
||||
_int15_008:
|
||||
clc
|
||||
mov $1024, %dx /* dx -> extended memory size (in 64K chuncks) */
|
||||
mov $640, %cx /* cx -> conventional memory size (in 1 Kbytes chuncks) */
|
||||
iret
|
||||
|
||||
.globl _int16_handler
|
||||
_int16_handler:
|
||||
cmp $0x0, %ah
|
||||
jnz _int16_01
|
||||
mov $0x20, %al
|
||||
mov $0x39, %ah
|
||||
iret
|
||||
_int16_01:
|
||||
cmp $0x1, %ah
|
||||
jnz _int16_02
|
||||
iret
|
||||
_int16_02:
|
||||
cmp $0x2, %ah
|
||||
jnz _int16_05
|
||||
mov $0, %al
|
||||
iret
|
||||
_int16_05:
|
||||
cmp $0x5, %ah
|
||||
jnz _int16_10
|
||||
mov $0, %al
|
||||
iret
|
||||
_int16_10:
|
||||
cmp $0x10, %ah
|
||||
jnz _int16_11
|
||||
mov $0x20, %al
|
||||
mov $0x39, %ah
|
||||
iret
|
||||
_int16_11:
|
||||
cmp $0x11, %ah
|
||||
jnz _int16_12
|
||||
iret
|
||||
_int16_12:
|
||||
cmp $0x12, %ah
|
||||
jnz _int16_XX
|
||||
mov $0, %ax
|
||||
iret
|
||||
_int16_XX:
|
||||
iret
|
||||
|
||||
.globl _int17_handler
|
||||
_int17_handler:
|
||||
mov $0xd0, %ah
|
||||
iret
|
||||
|
||||
.globl _int19_handler
|
||||
_int19_handler:
|
||||
hlt
|
||||
iret
|
||||
|
||||
.globl _int1A_handler
|
||||
_int1A_handler:
|
||||
stc
|
||||
iret
|
||||
|
||||
.code32
|
||||
.globl xstart
|
||||
xstart:
|
||||
/* reprogram the PICs so that interrupt are masked */
|
||||
movb $0x11,%al /* ICW1 [ICW4 NEEDED, EDGE TRIGGERED]*/
|
||||
outb %al,$0x20
|
||||
movb $PIC1_VBS, %al
|
||||
outb %al,$0x21
|
||||
movb $0x4,%al
|
||||
outb %al,$0x21
|
||||
movb $0x1,%al
|
||||
outb %al,$0x21
|
||||
movb $0xff,%al
|
||||
outb %al,$0x21
|
||||
|
||||
movb $0x11,%al /* ICW1 [ICW4 NEEDED, EDGE TRIGGERED]*/
|
||||
outb %al,$0xa0
|
||||
movb $PIC2_VBS, %al
|
||||
outb %al,$0xa1
|
||||
movb $0x2,%al
|
||||
outb %al,$0xa1
|
||||
movb $0x1,%al
|
||||
outb %al,$0xa1
|
||||
movb $0xff,%al
|
||||
outb %al,$0xa1
|
||||
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
pushl %ebx
|
||||
pushl %esi
|
||||
pushl %edi
|
||||
movl 8(%ebp),%eax
|
||||
movl %eax,_execaddr
|
||||
movl 12(%ebp),%ebx
|
||||
movl 16(%ebp),%ecx /* bootp record (32bit pointer) */
|
||||
addl $28,%ecx /* ip, udp header */
|
||||
shll $12,%ecx
|
||||
shrw $12,%cx
|
||||
call _prot_to_real
|
||||
.code16
|
||||
/* MP: add int10 handler */
|
||||
push %eax
|
||||
push %ebx
|
||||
push %es
|
||||
mov $0,%ax
|
||||
mov %ax,%es
|
||||
mov %cs,%ax
|
||||
shl $16,%eax
|
||||
|
||||
ADDR32 mov $(_int08_handler-_start),%ax
|
||||
mov $0x20,%ebx
|
||||
mov %eax,%es:(%bx)
|
||||
|
||||
ADDR32 mov $(_int10_handler-_start),%ax
|
||||
mov $0x40,%ebx
|
||||
mov %eax,%es:(%bx)
|
||||
|
||||
ADDR32 mov $(_int11_handler-_start),%ax
|
||||
mov $0x44,%ebx
|
||||
mov %eax,%es:(%bx)
|
||||
|
||||
ADDR32 mov $(_int12_handler-_start),%ax
|
||||
mov $0x48,%ebx
|
||||
mov %eax,%es:(%bx)
|
||||
|
||||
ADDR32 mov $(_int13_handler-_start),%ax
|
||||
mov $0x4c,%ebx
|
||||
mov %eax,%es:(%bx)
|
||||
|
||||
ADDR32 mov $(_int14_handler-_start),%ax
|
||||
mov $0x50,%ebx
|
||||
mov %eax,%es:(%bx)
|
||||
|
||||
ADDR32 mov $(_int15_handler-_start),%ax
|
||||
mov $0x54,%ebx
|
||||
mov %eax,%es:(%bx)
|
||||
|
||||
ADDR32 mov $(_int16_handler-_start),%ax
|
||||
mov $0x58,%ebx
|
||||
mov %eax,%es:(%bx)
|
||||
|
||||
ADDR32 mov $(_int17_handler-_start),%ax
|
||||
mov $0x5c,%ebx
|
||||
mov %eax,%es:(%bx)
|
||||
|
||||
ADDR32 mov $(_int19_handler-_start),%ax
|
||||
mov $0x64,%ebx
|
||||
mov %eax,%es:(%bx)
|
||||
|
||||
ADDR32 mov $(_int1A_handler-_start),%ax
|
||||
mov $0x68,%ebx
|
||||
mov %eax,%es:(%bx)
|
||||
|
||||
pop %es
|
||||
pop %ebx
|
||||
pop %eax
|
||||
/* */
|
||||
pushl %ecx /* bootp record */
|
||||
pushl %ebx /* file header */
|
||||
movl $((RELOC<<12)+(1f-RELOC)),%eax
|
||||
pushl %eax
|
||||
ADDR32 LJMPI(_execaddr-_start)
|
||||
1:
|
||||
addw $8,%sp /* XXX or is this 10 in case of a 16bit "ret" */
|
||||
DATA32 call _real_to_prot
|
||||
.code32
|
||||
popl %edi
|
||||
popl %esi
|
||||
popl %ebx
|
||||
popl %ebp
|
||||
ret
|
||||
|
||||
_execaddr:
|
||||
.long 0
|
||||
|
||||
#ifdef IMAGE_MULTIBOOT
|
||||
/**************************************************************************
|
||||
XEND - Restart Etherboot from the beginning (from protected mode)
|
||||
**************************************************************************/
|
||||
|
||||
.globl xend
|
||||
xend:
|
||||
cs
|
||||
lidt idtarg_realmode-_start+RELOC
|
||||
cs
|
||||
lgdt gdtarg-_start+RELOC
|
||||
#ifdef GAS291
|
||||
ljmp $REAL_CODE_SEG,$1f-RELOC /* jump to a 16 bit segment */
|
||||
#else
|
||||
ljmp $REAL_CODE_SEG,$1f-_start /* jump to a 16 bit segment */
|
||||
#endif /* GAS291 */
|
||||
1:
|
||||
.code16
|
||||
movw $REAL_DATA_SEG,%ax
|
||||
movw %ax,%ds
|
||||
movw %ax,%ss
|
||||
movw %ax,%es
|
||||
|
||||
/* clear the PE bit of CR0 */
|
||||
movl %cr0,%eax
|
||||
andl $0!CR0_PE,%eax
|
||||
movl %eax,%cr0
|
||||
|
||||
/* make intersegment jmp to flush the processor pipeline
|
||||
* and reload %cs:%eip (to clear upper 16 bits of %eip).
|
||||
*/
|
||||
DATA32 ljmp $(RELOC)>>4,$2f-_start
|
||||
2:
|
||||
/* we are in real mode now
|
||||
* set up the real mode segment registers : %ds, %ss, %es
|
||||
*/
|
||||
movw %cs,%ax
|
||||
movw %ax,%ds
|
||||
movw %ax,%es
|
||||
movw %ax,%ss
|
||||
xorl %esp,%esp
|
||||
ADDR32 movw initsp-RELOC,%sp
|
||||
|
||||
movw $0,%ax
|
||||
movw %ax,%fs
|
||||
movw %ax,%gs
|
||||
|
||||
sti
|
||||
jmp _start
|
||||
|
||||
.code32
|
||||
#endif /* IMAGE_MULTIBOOT */
|
||||
|
||||
.global get_cs
|
||||
get_cs:
|
||||
xorl %eax,%eax
|
||||
movw %cs,%ax
|
||||
ret
|
||||
|
||||
.global get_ds
|
||||
get_ds:
|
||||
xorl %eax,%eax
|
||||
movw %ds,%ax
|
||||
ret
|
||||
|
||||
.global getsp
|
||||
getsp:
|
||||
movl %esp,%eax /* GET STACK POINTER */
|
||||
subl $4, %eax /* ACCOUNT FOR RETURN ADDRESS ON */
|
||||
ret
|
||||
|
||||
.global get_gdtbase
|
||||
get_gdtbase:
|
||||
sub $8,%esp /* ALLOCATE ROOM ON THE STACK */
|
||||
sgdt (%esp,1) /*STORE IGDT REGISTER ON STACK */
|
||||
mov 2(%esp),%eax /* READ GDT BASE ADDRESS */
|
||||
mov $KERN_DATA_SEG,%dx /* ASSUME UNIVERSAL DS. */
|
||||
add $8,%esp /* RESTORE STACK */
|
||||
ret /* DONE */
|
||||
|
||||
.global get_gdtsize
|
||||
get_gdtsize:
|
||||
sub $8,%esp /* ALLOCATE ROOM ON THE STACK */
|
||||
sgdt (%esp,1) /*STORE IGDT REGISTER ON STACK */
|
||||
xor %eax,%eax
|
||||
mov 2(%esp),%eax /* READ GDT BASE ADDRESS */
|
||||
mov (%ESP),%ax
|
||||
shr $3,%ax
|
||||
add $8,%esp /* RESTORE STACK */
|
||||
ret /* DONE */
|
||||
|
||||
.global get_idtbase
|
||||
get_idtbase:
|
||||
sub $8,%esp
|
||||
sidt (%esp,1) /* STORE IIDT REGISTER ON STACK */
|
||||
mov 2(%esp),%eax
|
||||
mov $KERN_DATA_SEG,%dx
|
||||
add $8,%esp
|
||||
ret
|
||||
|
||||
.global get_lw
|
||||
get_lw:
|
||||
xor %edx,%edx
|
||||
mov 8(%esp),%eax
|
||||
mov 4(%esp),%dx
|
||||
ret
|
||||
|
||||
/**************************************************************************
|
||||
SETJMP - Save stack context for non-local goto
|
||||
**************************************************************************/
|
||||
.globl setjmp
|
||||
setjmp:
|
||||
mov 4(%esp),%ecx
|
||||
mov 0(%esp),%edx
|
||||
mov %edx,0(%ecx)
|
||||
mov %ebx,4(%ecx)
|
||||
mov %esp,8(%ecx)
|
||||
mov %ebp,12(%ecx)
|
||||
mov %esi,16(%ecx)
|
||||
mov %edi,20(%ecx)
|
||||
mov %eax,24(%ecx)
|
||||
mov $0,%eax
|
||||
ret
|
||||
|
||||
/**************************************************************************
|
||||
LONGJMP - Non-local jump to a saved stack context
|
||||
**************************************************************************/
|
||||
.globl longjmp
|
||||
longjmp:
|
||||
mov 4(%esp),%edx
|
||||
mov 8(%esp),%eax
|
||||
mov 0(%edx),%ecx
|
||||
mov 4(%edx),%ebx
|
||||
mov 8(%edx),%esp
|
||||
mov 12(%edx),%ebp
|
||||
mov 16(%edx),%esi
|
||||
mov 20(%edx),%edi
|
||||
cmp $0,%eax
|
||||
jne 1f
|
||||
mov $1,%eax
|
||||
1: mov %ecx,0(%esp)
|
||||
ret
|
||||
|
||||
/**************************************************************************
|
||||
_REAL_TO_PROT - Go from REAL mode to Protected Mode
|
||||
**************************************************************************/
|
||||
.globl _real_to_prot
|
||||
_real_to_prot:
|
||||
.code16
|
||||
cli
|
||||
cs
|
||||
ADDR32 lgdt gdtarg-_start
|
||||
movl %cr0,%eax
|
||||
orl $CR0_PE,%eax
|
||||
movl %eax,%cr0 /* turn on protected mode */
|
||||
|
||||
/* flush prefetch queue, and reload %cs:%eip */
|
||||
DATA32 ljmp $KERN_CODE_SEG,$1f
|
||||
1:
|
||||
.code32
|
||||
/* reload other segment registers */
|
||||
movl $KERN_DATA_SEG,%eax
|
||||
movl %eax,%ds
|
||||
movl %eax,%es
|
||||
movl %eax,%ss
|
||||
addl $RELOC,%esp /* Fix up stack pointer */
|
||||
xorl %eax,%eax
|
||||
movl %eax,%fs
|
||||
movl %eax,%gs
|
||||
popl %eax /* Fix up return address */
|
||||
addl $RELOC,%eax
|
||||
pushl %eax
|
||||
ret
|
||||
|
||||
/**************************************************************************
|
||||
_PROT_TO_REAL - Go from Protected Mode to REAL Mode
|
||||
**************************************************************************/
|
||||
.globl _prot_to_real
|
||||
_prot_to_real:
|
||||
.code32
|
||||
popl %eax
|
||||
subl $RELOC,%eax /* Adjust return address */
|
||||
pushl %eax
|
||||
subl $RELOC,%esp /* Adjust stack pointer */
|
||||
#ifdef GAS291
|
||||
ljmp $REAL_CODE_SEG,$1f-RELOC /* jump to a 16 bit segment */
|
||||
#else
|
||||
ljmp $REAL_CODE_SEG,$1f-_start /* jump to a 16 bit segment */
|
||||
#endif /* GAS291 */
|
||||
1:
|
||||
.code16
|
||||
movw $REAL_DATA_SEG,%ax
|
||||
movw %ax,%ds
|
||||
movw %ax,%ss
|
||||
movw %ax,%es
|
||||
movw %ax,%fs
|
||||
movw %ax,%gs
|
||||
cli
|
||||
|
||||
/* clear the PE bit of CR0 */
|
||||
movl %cr0,%eax
|
||||
andl $0!CR0_PE,%eax
|
||||
movl %eax,%cr0
|
||||
|
||||
/* make intersegment jmp to flush the processor pipeline
|
||||
* and reload %cs:%eip (to clear upper 16 bits of %eip).
|
||||
*/
|
||||
DATA32 ljmp $(RELOC)>>4,$2f-_start
|
||||
2:
|
||||
/* we are in real mode now
|
||||
* set up the real mode segment registers : %ds, $ss, %es
|
||||
*/
|
||||
movw %cs,%ax
|
||||
movw %ax,%ds
|
||||
movw %ax,%es
|
||||
movw %ax,%ss
|
||||
#if 0
|
||||
sti
|
||||
#endif
|
||||
DATA32 ret /* There is a 32 bit return address on the stack */
|
||||
.code32
|
||||
|
||||
/**************************************************************************
|
||||
GLOBAL DESCRIPTOR TABLE
|
||||
**************************************************************************/
|
||||
.align 4
|
||||
Idt_Reg:
|
||||
.word 0x3ff
|
||||
.long 0
|
||||
|
||||
.align 4
|
||||
_gdt:
|
||||
gdtarg:
|
||||
Gdt_Table:
|
||||
.word 0x27 /* limit */
|
||||
.long _gdt /* addr */
|
||||
.word 0
|
||||
_pmcs:
|
||||
/* 32 bit protected mode code segment */
|
||||
.word 0xffff,0
|
||||
.byte 0,0x9f,0xcf,0
|
||||
|
||||
_pmds:
|
||||
/* 32 bit protected mode data segment */
|
||||
.word 0xffff,0
|
||||
.byte 0,0x93,0xcf,0
|
||||
|
||||
_rmcs:
|
||||
/* 16 bit real mode code segment */
|
||||
.word 0xffff,(RELOC&0xffff)
|
||||
.byte (RELOC>>16),0x9b,0x00,(RELOC>>24)
|
||||
|
||||
_rmds:
|
||||
/* 16 bit real mode data segment */
|
||||
.word 0xffff,(RELOC&0xffff)
|
||||
.byte (RELOC>>16),0x93,0x00,(RELOC>>24)
|
||||
|
||||
.align 4
|
||||
RUN_GDT: /* POINTER TO GDT IN RAM */
|
||||
.byte 0x7f,0 /* [BSP_GDT_NUM*8]-1 */
|
||||
.long Gdt_Table
|
||||
|
||||
.align 4
|
||||
|
||||
.section ".rodata"
|
||||
err_not386:
|
||||
.ascii "Etherboot/32 requires 386+"
|
||||
.byte 0x0d, 0x0a
|
||||
err_not386_end:
|
||||
|
||||
days: .long 0
|
||||
irq_num: .long
|
||||
|
||||
.data
|
||||
.align 4
|
||||
.org 2048
|
||||
.global stktop
|
||||
stktop:
|
||||
.long
|
||||
|
||||
.section ".armando"
|
||||
/* 1:::::::::2:::::::::3:::::::3 */
|
||||
/* 12345678901234567890123456789012345678 */
|
||||
/* v----+----v----+----v----+----v----+--- */
|
||||
|
||||
.global EtherbootString
|
||||
EtherbootString:
|
||||
.ascii "EtherBoot MPCC " /* fw identifier */
|
||||
|
||||
.byte 0, 0 /* mandatory hole */
|
||||
|
||||
.long _start /* entry point */
|
||||
.word 0
|
||||
.byte 'E' /* type */
|
||||
.byte 0 /* selector */
|
||||
.word 0 /* CRC */
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
CC=gcc
|
||||
CFLAGS=-Wall -O2
|
||||
|
||||
bin2intelhex:
|
||||
|
||||
|
||||
clean:
|
||||
rm -f bin2intelhex core *.o
|
|
@ -0,0 +1,148 @@
|
|||
/* name : bin2intelhex.c
|
||||
* from : Jean Marc Lacroix <jeanmarc.lacroix@free.fr>
|
||||
* date : 06/12/1997.
|
||||
* abstract : Y have rewrite this program from ????? with some modifications
|
||||
* to add :
|
||||
* - the Intel specification.
|
||||
* - correct a bug because my prom programmer don't understand the
|
||||
* initial format. Y suspect a bug in the calcul of the lrc
|
||||
* in the original program.
|
||||
* - correct the format of printf . In the original program, it was
|
||||
* %x, and it is in fact %X, because in the Intel Format, all the
|
||||
* char are in upper case.
|
||||
* - correct the lrc calculation.
|
||||
* usage:
|
||||
*-------
|
||||
* this program read the standard input and put to the standard output
|
||||
* the result of the conversion.
|
||||
* an example of use :
|
||||
* cat my_bin | bin2intelhex > my_bin.hex or.....
|
||||
* bin2intelhex < my_bin > my_bin.hex
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
* $Log$
|
||||
* Revision 1.1 2005/05/17 16:45:06 mcb30
|
||||
* Initial revision
|
||||
*
|
||||
* Revision 1.9 1997/12/14 05:14:54 install
|
||||
* - some documentation....
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Intel Hex format specifications
|
||||
|
||||
The 8-bit Intel Hex File Format is a printable ASCII format consisting of one
|
||||
or more data records followed by an end of file record. Each
|
||||
record consists of one line of information. Data records may appear in any
|
||||
order. Address and data values are represented as 2 or 4 hexadecimal
|
||||
digit values.
|
||||
|
||||
Record Format
|
||||
:LLAAAARRDDDD......DDDDCC
|
||||
|
||||
|
||||
LL
|
||||
AAAA
|
||||
RR
|
||||
DD
|
||||
CC
|
||||
Length field. Number of data bytes.
|
||||
Address field. Address of first byte.
|
||||
Record type field. 00 for data and 01 for end of record.
|
||||
Data field.
|
||||
Checksum field. One's complement of length, address, record type and data
|
||||
fields modulo 256.
|
||||
CC = LL + AAAA + RR + all DD = 0
|
||||
|
||||
Example:
|
||||
:06010000010203040506E4
|
||||
:00000001FF
|
||||
|
||||
The first line in the above example Intel Hex file is a data record addressed
|
||||
at location 100H with data values 1 to 6. The second line is the end
|
||||
of file record, so that the LL field is 0
|
||||
|
||||
*/
|
||||
|
||||
|
||||
typedef unsigned char t_u8;
|
||||
typedef unsigned short t_u16;
|
||||
/*
|
||||
* the choice for the total length (16) of a line, but the specification
|
||||
* can support an another value
|
||||
*/
|
||||
#define LL_MAX_LINE 16
|
||||
typedef struct
|
||||
{
|
||||
t_u8 intel_lg_data;
|
||||
t_u16 intel_adr;
|
||||
t_u8 intel_type;
|
||||
t_u8 intel_data [LL_MAX_LINE];
|
||||
t_u8 intel_lrc;
|
||||
} t_one_line;
|
||||
#define INTEL_DATA_TYPE 0
|
||||
#define EXIT_OK 0
|
||||
int main (const int argc, const char ** const argv)
|
||||
{
|
||||
t_one_line line;
|
||||
/*
|
||||
* init for the adress, please note that it is assume that the program begin at 0
|
||||
*/
|
||||
line.intel_adr = 0;
|
||||
line.intel_type = INTEL_DATA_TYPE;
|
||||
/*
|
||||
* read the data on the standard input
|
||||
*/
|
||||
while ((line.intel_lg_data = read (0, &line.intel_data [0] ,LL_MAX_LINE )) > 0)
|
||||
{
|
||||
t_u8 i;
|
||||
/*
|
||||
* and now for this line, calculate the lrc.
|
||||
*/
|
||||
line.intel_lrc = line.intel_lg_data;
|
||||
line.intel_lrc += ((line.intel_adr >> 8) & 0xff);
|
||||
line.intel_lrc += (line.intel_adr &0xff);
|
||||
line.intel_lrc += line.intel_type;
|
||||
/*
|
||||
* the structure is ready, print it to stdout in the
|
||||
* right format
|
||||
*/
|
||||
(void) printf (":%02X%04X%02X",
|
||||
line.intel_lg_data,
|
||||
line.intel_adr,
|
||||
line.intel_type);
|
||||
/*
|
||||
* edit all the data read
|
||||
*/
|
||||
for (i=0; i<line.intel_lg_data; i++)
|
||||
{
|
||||
(void) printf ("%02X",
|
||||
(line.intel_data [i] & 0xff));
|
||||
/*
|
||||
* add to the lrc the data print
|
||||
*/
|
||||
line.intel_lrc +=line.intel_data [i];
|
||||
}
|
||||
/*
|
||||
* edit the value of the lrc and new line for the next
|
||||
*/
|
||||
(void) printf ("%02X\n",
|
||||
(0x100 - line.intel_lrc) & 0xff);
|
||||
/*
|
||||
* prepare the new adress for the next line
|
||||
*/
|
||||
line.intel_adr+=line.intel_lg_data;
|
||||
}
|
||||
/*
|
||||
* print the last line with a length of 0 data, so that the lrc is easy to
|
||||
* calculate (ff+01 =0)
|
||||
*/
|
||||
printf (":00000001FF\n");
|
||||
exit (EXIT_OK);
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
|
||||
Quick and dirty program to make intel-hex from a binary.
|
||||
|
||||
Written by R.E.Wolff@BitWizard.nl
|
||||
This file is in the public domain
|
||||
|
||||
Typing started:
|
||||
|
||||
Mon Jun 16 00:24:15 MET DST 1997
|
||||
|
||||
programming stopped:
|
||||
|
||||
Mon Jun 16 00:31:27 MET DST 1997
|
||||
|
||||
debugging finished (2 bugs found):
|
||||
Mon Jun 16 00:32:52 MET DST 1997
|
||||
|
||||
---------------------------------------------------------
|
||||
|
||||
Doc written in timeout. Everything else in this file was done while
|
||||
the timer was running.
|
||||
|
||||
I promised "Mark Kopecki" that writing the bin-to-intel-hex
|
||||
converter would cost less than 15 minutes, and that it would be more
|
||||
trouble to find a converter on the net than to write the converter
|
||||
myself. I ended up spending over half an hour searching for
|
||||
spec/converter/docs because of unreachable hosts on the internet. I
|
||||
got a file with docs, after that it was 8 minutes.....
|
||||
|
||||
---------------------------------------------------------
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Intel Hex format:
|
||||
|
||||
ll aaaa tt dd....dd cc
|
||||
|
||||
ll = length
|
||||
aaaa = address
|
||||
tt = type
|
||||
dd....dd = data
|
||||
cc = checksum.
|
||||
*/
|
||||
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
unsigned char buf[32];
|
||||
int addr = 0;
|
||||
int n,i;
|
||||
|
||||
while ((n = read (0, buf+4, 16)) > 0) {
|
||||
buf[0] = n;
|
||||
buf[1] = addr >> 8;
|
||||
buf[2] = addr & 0xff;
|
||||
buf[3] = 0x00;
|
||||
buf[4+n] = 0x00;
|
||||
|
||||
for (i=0;i<4+n;i++)
|
||||
buf[4+n] -= buf[i];
|
||||
printf (":");
|
||||
for (i=0;i<= 4+n;i++)
|
||||
printf ("%02x", buf[i]);
|
||||
printf ("\n");
|
||||
addr += n;
|
||||
}
|
||||
printf (":0000000001ff\n");
|
||||
exit (0);
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
bochsout.txt
|
||||
parport.out
|
||||
ne2k-tx.log
|
||||
ne2k-txdump.txt
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
all : serial-console.1
|
||||
|
||||
%.1 : %
|
||||
pod2man $< > $@
|
||||
|
||||
clean :
|
||||
rm -f serial-console.1
|
|
@ -0,0 +1,121 @@
|
|||
Running Etherboot within Bochs
|
||||
==============================
|
||||
|
||||
Michael Brown <mbrown@fensystems.co.uk>
|
||||
Based on an idea suggested by H. Peter Anvin <hpa@zytor.com>.
|
||||
|
||||
$Id$
|
||||
|
||||
Bochs is a program that simulates a complete Intel x86 computer,
|
||||
including hardware. It can be used to test Etherboot. There is a
|
||||
special pseudo NIC ("pnic") implemented in Bochs, with a corresponding
|
||||
driver in Etherboot. (There is also an NE2000 ISA driver in Bochs,
|
||||
but it doesn't seem to quite work.)
|
||||
|
||||
To get bochs running is fairly simple:
|
||||
|
||||
1. Get the bochs source code:
|
||||
a) cvs -d:pserver:anonymous:@cvs.sourceforge.net:/cvsroot/bochs login
|
||||
b) cvs -d:pserver:anonymous:@cvs.sourceforge.net:/cvsroot/bochs co bochs
|
||||
|
||||
2. Configure bochs with
|
||||
./configure --enable-all-optimisations --enable-pci \
|
||||
--enable-ne2000 --enable-pnic
|
||||
Other potentially useful configure options:
|
||||
--prefix=/usr
|
||||
to force use of standard file locations
|
||||
--enable-debugger
|
||||
to enable the internal debugger
|
||||
|
||||
3. Build bochs:
|
||||
make
|
||||
|
||||
4. Configure Etherboot with CONFIG_PCI_DIRECT: add the line
|
||||
CFLAGS += -DCONFIG_PCI_DIRECT
|
||||
to the end of src/arch/i386/Config.
|
||||
|
||||
5. Build bin/pnic.zrom:
|
||||
make bin/pnic.zrom
|
||||
|
||||
6. Load the TUN/TAP kernel module:
|
||||
modprobe tun
|
||||
You should see the device /dev/net/tun is created automatically if
|
||||
you're using devfs, otherwise you may have to create it by hand with:
|
||||
mknod /dev/net/tun c 10 200
|
||||
|
||||
7. Grant yourself write access to /dev/net/tun:
|
||||
su -c 'chown <your user id> /dev/net/tun'
|
||||
The alternative to this is to run Bochs as root. Don't do that.
|
||||
|
||||
8. Add the following fragment to /etc/dhcpd.conf:
|
||||
subnet 10.254.254.0 netmask 255.255.255.252 {
|
||||
range dynamic-bootp 10.254.254.1 10.254.254.1;
|
||||
}
|
||||
You will also need to add in any of your usual declarations for
|
||||
Etherboot, e.g. 'filename "vmlinuz.ltsp";'. Note that this setup
|
||||
assumes that your DHCP server, TFTP server etc. all live on the
|
||||
machine you are using for running Bochs. If not, then you're on
|
||||
your own.
|
||||
|
||||
9. Change back to this directory and run bochs from your Bochs source tree:
|
||||
cd /path/to/Etherboot/contrib/bochs
|
||||
/path/to/bochs/source/tree/bochs
|
||||
|
||||
10. Select option 5 (Begin simulation). You will be prompted for your
|
||||
root password. This is required in order to configure the tun1
|
||||
network interface and to restart the DHCP server.
|
||||
|
||||
11. You should see Bochs start up and attempt to boot from the network,
|
||||
with a screen that looks like:
|
||||
|
||||
VGA BIOS - Version 2.40
|
||||
Copyright (C) 1990-2000 Elpin Systems, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Licensed for use with bochs, courtesy of MandrakeSoft.
|
||||
|
||||
For information on this or other VGA development products, contact
|
||||
Elpin Systems at: (800) 723-9038 or www.elpin.com
|
||||
|
||||
Bochs BIOS, 1 cpu, $Revision$ $Date$
|
||||
|
||||
|
||||
Etherboot 5.3.6 (GPL) http://etherboot.org Tagged ELF for [PNIC]
|
||||
Relocating _text from: [00091020,0009fb50) to [01ef14d0,01f00000)
|
||||
Boot from (N)etwork or (Q)uit?
|
||||
|
||||
Probing pci nic...
|
||||
[pnic] - Detected Bochs Pseudo NIC MAC FE:FD:00:00:00:01 (API v1.0) at 0xdc00
|
||||
Searching for server (DHCP)...
|
||||
..Me: 10.254.254.1, Server: 10.254.254.2
|
||||
Loading 10.254.254.2:/tftpboot/kernel
|
||||
|
||||
|
||||
|
||||
|
||||
Serial console
|
||||
==============
|
||||
|
||||
You can use the program "serial-console" to obtain a virtual serial
|
||||
console for Etherboot running within Bochs. Simply run
|
||||
"./serial-console" on a spare tty (e.g. a separate xterm window)
|
||||
before starting Bochs, and ensure that you have compiled Etherboot
|
||||
with appropriate settings such as
|
||||
CFLAGS+= -DCONSOLE_DUAL -DCOMCONSOLE=0x3F8 -DCONSPEED=9600
|
||||
|
||||
There is a manual page for "serial-console"; use
|
||||
"man ./serial-console.1" to view it.
|
||||
|
||||
|
||||
|
||||
TODO
|
||||
====
|
||||
|
||||
Packet forwarding/masquerading - document what must be set up.
|
||||
|
||||
Mention possibility of using RFB as the display device - in
|
||||
conjunction with the serial console, gives you a test facility that
|
||||
can be accessed remotely.
|
||||
|
||||
Mention use of BOCHSBP instruction (xchgw %bx,%bx) to avoid need to
|
||||
calculate breakpoints.
|
|
@ -0,0 +1,658 @@
|
|||
# You many now use double quotes around pathnames, in case
|
||||
# your pathname includes spaces.
|
||||
|
||||
#=======================================================================
|
||||
# CONFIG_INTERFACE
|
||||
#
|
||||
# The configuration interface is a series of menus or dialog boxes that
|
||||
# allows you to change all the settings that control Bochs's behavior.
|
||||
# There are two choices of configuration interface: a text mode version
|
||||
# called "textconfig" and a graphical version called "wx". The text
|
||||
# mode version uses stdin/stdout and is always compiled in. The graphical
|
||||
# version is only available when you use "--with-wx" on the configure
|
||||
# command. If you do not write a config_interface line, Bochs will
|
||||
# choose a default for you.
|
||||
#
|
||||
# NOTE: if you use the "wx" configuration interface, you must also use
|
||||
# the "wx" display library.
|
||||
#=======================================================================
|
||||
#config_interface: textconfig
|
||||
#config_interface: wx
|
||||
|
||||
#=======================================================================
|
||||
# DISPLAY_LIBRARY
|
||||
#
|
||||
# The display library is the code that displays the Bochs VGA screen. Bochs
|
||||
# has a selection of about 10 different display library implementations for
|
||||
# different platforms. If you run configure with multiple --with-* options,
|
||||
# the display_library command lets you choose which one you want to run with.
|
||||
# If you do not write a display_library line, Bochs will choose a default for
|
||||
# you.
|
||||
#
|
||||
# The choices are:
|
||||
# x use X windows interface, cross platform
|
||||
# win32 use native win32 libraries
|
||||
# carbon use Carbon library (for MacOS X)
|
||||
# beos use native BeOS libraries
|
||||
# macintosh use MacOS pre-10
|
||||
# amigaos use native AmigaOS libraries
|
||||
# sdl use SDL library, cross platform
|
||||
# svga use SVGALIB library for Linux, allows graphics without X11
|
||||
# term text only, uses curses/ncurses library, cross platform
|
||||
# rfb provides an interface to AT&T's VNC viewer, cross platform
|
||||
# wx use wxWindows library, cross platform
|
||||
# nogui no display at all
|
||||
#
|
||||
# NOTE: if you use the "wx" configuration interface, you must also use
|
||||
# the "wx" display library.
|
||||
#=======================================================================
|
||||
#display_library: amigaos
|
||||
#display_library: beos
|
||||
#display_library: carbon
|
||||
#display_library: macintosh
|
||||
#display_library: nogui
|
||||
#display_library: rfb
|
||||
#display_library: sdl
|
||||
#display_library: term
|
||||
#display_library: win32
|
||||
#display_library: wx
|
||||
#display_library: x
|
||||
|
||||
#=======================================================================
|
||||
# ROMIMAGE:
|
||||
# You now need to load a ROM BIOS into F0000-FFFFF. I've wiped
|
||||
# out most of the BIOS hooks, and replace them with real BIOS
|
||||
# support. Normally, you can use a precompiled BIOS in the bios/
|
||||
# directory, named BIOS-bochs-latest.
|
||||
#=======================================================================
|
||||
#romimage: bios/BIOS-bochs-970717a
|
||||
#romimage: file=bios/BIOS-bochs-latest, address=0xf0000
|
||||
romimage: file=$BXSHARE/BIOS-bochs-latest, address=0xf0000
|
||||
#romimage: file=bios/BIOS-bochs-2-processors, address=0xf0000
|
||||
#romimage: file=bios/BIOS-bochs-4-processors, address=0xf0000
|
||||
#romimage: file=bios/rombios.bin, address=0xf0000
|
||||
|
||||
#=======================================================================
|
||||
# MEGS
|
||||
# set this to the default number of Megabytes of memory you want
|
||||
# to emulate. You may also pass the '-megs xyz' option to bochs
|
||||
#
|
||||
# The default is 32MB, most OS's won't need more than that.
|
||||
#=======================================================================
|
||||
#megs: 256
|
||||
#megs: 128
|
||||
#megs: 64
|
||||
megs: 32
|
||||
#megs: 16
|
||||
#megs: 8
|
||||
|
||||
#=======================================================================
|
||||
# OPTROMIMAGE[1-4]:
|
||||
# You may now load up to 4 optional ROM images. Be sure to use a
|
||||
# read-only area, typically between C8000 and EFFFF. These optional
|
||||
# ROM images should not overwrite the rombios (located at
|
||||
# F0000-FFFFF) and the videobios (located at C0000-C7FFF).
|
||||
# Those ROM images will be initialized by the bios if they contain
|
||||
# the right signature (0x55AA).
|
||||
# It can also be a convenient way to upload some arbitary code/data
|
||||
# in the simulation, that can be retrieved by the boot loader
|
||||
#=======================================================================
|
||||
#optromimage1: file=optionalrom.bin, address=0xd0000
|
||||
#optromimage2: file=optionalrom.bin, address=0xd1000
|
||||
#optromimage3: file=optionalrom.bin, address=0xd2000
|
||||
#optromimage4: file=optionalrom.bin, address=0xd3000
|
||||
#optromimage1: file=../../src/bin/ne.zrom, address=0xd0000
|
||||
optromimage1: file=../../src/bin/pnic.zrom, address=0xd0000
|
||||
|
||||
#=======================================================================
|
||||
# VGAROMIMAGE
|
||||
# You now need to load a VGA ROM BIOS into C0000.
|
||||
#=======================================================================
|
||||
#vgaromimage: bios/VGABIOS-lgpl-latest
|
||||
#vgaromimage: bios/VGABIOS-elpin-2.40
|
||||
vgaromimage: $BXSHARE/VGABIOS-elpin-2.40
|
||||
|
||||
#=======================================================================
|
||||
# FLOPPYA:
|
||||
# Point this to pathname of floppy image file or device
|
||||
# This should be of a bootable floppy(image/device) if you're
|
||||
# booting from 'a'.
|
||||
#
|
||||
# You can set the initial status of the media to 'ejected' or 'inserted'.
|
||||
# floppya: 2_88=path, status=ejected (2.88M 3.5" floppy)
|
||||
# floppya: 1_44=path, status=inserted (1.44M 3.5" floppy)
|
||||
# floppya: 1_2=path, status=ejected (1.2M 5.25" floppy)
|
||||
# floppya: 720k=path, status=inserted (720K 3.5" floppy)
|
||||
# floppya: 360k=path, status=inserted (360K 5.25" floppy)
|
||||
#
|
||||
# The path should be the name of a disk image file. On unix, you can use
|
||||
# a raw device name such as /dev/fd0 on Linux. On WinNT and Win2k, use
|
||||
# drive letters such as a: or b: as the path. Raw floppy access is not
|
||||
# supported on Windows 95 and 98.
|
||||
#=======================================================================
|
||||
floppya: 1_44=/dev/fd0, status=inserted
|
||||
#floppya: file=../1.44, status=inserted
|
||||
#floppya: 1_44=/dev/fd0H1440, status=inserted
|
||||
#floppya: 1_2=../1_2, status=inserted
|
||||
#floppya: 1_44=a:, status=inserted
|
||||
#floppya: 1_44=a.img, status=inserted
|
||||
|
||||
#=======================================================================
|
||||
# FLOPPYB:
|
||||
# See FLOPPYA above for syntax
|
||||
#=======================================================================
|
||||
#floppyb: 1_44=b:, status=inserted
|
||||
floppyb: 1_44=b.img, status=inserted
|
||||
|
||||
#=======================================================================
|
||||
# ATA0, ATA1, ATA2, ATA3
|
||||
# ATA controller for hard disks and cdroms
|
||||
#
|
||||
# ata[0-3]: enabled=[0|1], ioaddr1=addr, ioaddr2=addr, irq=number
|
||||
#
|
||||
# These options enables up to 4 ata channels. For each channel
|
||||
# the two base io address and the irq must be specified.
|
||||
#
|
||||
# ata0 is enabled by default, with ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
|
||||
#
|
||||
# Examples:
|
||||
# ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
|
||||
# ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15
|
||||
# ata2: enabled=1, ioaddr1=0x1e8, ioaddr2=0x3e8, irq=11
|
||||
# ata3: enabled=1, ioaddr1=0x168, ioaddr2=0x368, irq=9
|
||||
#=======================================================================
|
||||
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
|
||||
ata1: enabled=0, ioaddr1=0x170, ioaddr2=0x370, irq=15
|
||||
ata2: enabled=0, ioaddr1=0x1e8, ioaddr2=0x3e8, irq=11
|
||||
ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x368, irq=9
|
||||
|
||||
#=======================================================================
|
||||
# ATA[0-3]-MASTER, ATA[0-3]-SLAVE
|
||||
#
|
||||
# This defines the type and characteristics of all attached ata devices:
|
||||
# type= type of attached device [disk|cdrom]
|
||||
# path= path of the image
|
||||
# cylinders= only valid for disks
|
||||
# heads= only valid for disks
|
||||
# spt= only valid for disks
|
||||
# status= only valid for cdroms [inserted|ejected]
|
||||
# biosdetect= type of biosdetection [none|auto], only for disks on ata0 [cmos]
|
||||
# translation=type of transation of the bios, only for disks [none|lba|large|rechs|auto]
|
||||
# model= string returned by identify device command
|
||||
#
|
||||
# Point this at a hard disk image file, cdrom iso file, or physical cdrom
|
||||
# device. To create a hard disk image, try running bximage. It will help you
|
||||
# choose the size and then suggest a line that works with it.
|
||||
#
|
||||
# In UNIX it may be possible to use a raw device as a Bochs hard disk,
|
||||
# but WE DON'T RECOMMEND IT. In Windows there is no easy way.
|
||||
#
|
||||
# In windows, the drive letter + colon notation should be used for cdroms.
|
||||
# Depending on versions of windows and drivers, you may only be able to
|
||||
# access the "first" cdrom in the system. On MacOSX, use path="drive"
|
||||
# to access the physical drive.
|
||||
#
|
||||
# The path, cylinders, heads, and spt are mandatory for type=disk
|
||||
# The path is mandatory for type=cdrom
|
||||
#
|
||||
# Default values are:
|
||||
# biosdetect=auto, translation=auto, model="Generic 1234"
|
||||
#
|
||||
# The biosdetect option has currently no effect on the bios
|
||||
#
|
||||
# Examples:
|
||||
# ata0-master: type=disk, path=10M.sample, cylinders=306, heads=4, spt=17
|
||||
# ata0-slave: type=disk, path=20M.sample, cylinders=615, heads=4, spt=17
|
||||
# ata1-master: type=disk, path=30M.sample, cylinders=615, heads=6, spt=17
|
||||
# ata1-slave: type=disk, path=46M.sample, cylinders=940, heads=6, spt=17
|
||||
# ata2-master: type=disk, path=62M.sample, cylinders=940, heads=8, spt=17
|
||||
# ata2-slave: type=disk, path=112M.sample, cylinders=900, heads=15, spt=17
|
||||
# ata3-master: type=disk, path=483M.sample, cylinders=1024, heads=15, spt=63
|
||||
# ata3-slave: type=cdrom, path=iso.sample, status=inserted
|
||||
#=======================================================================
|
||||
#ata0-master: type=disk, path="30M.sample", cylinders=615, heads=6, spt=17
|
||||
#ata0-slave: type=cdrom, path=D:, status=inserted
|
||||
#ata0-slave: type=cdrom, path=/dev/cdrom, status=inserted
|
||||
#ata0-slave: type=cdrom, path="drive", status=inserted
|
||||
|
||||
#=======================================================================
|
||||
#
|
||||
# The DISKC option is deprecated. Use ATA* options instead.
|
||||
#
|
||||
# DISKC: file=, cyl=, heads=, spt=
|
||||
# Point this at a hard disk image file. To create
|
||||
# a hard disk image, try running bximage. It will help you choose the
|
||||
# size and then suggest a diskc line that works with it.
|
||||
#
|
||||
# In UNIX it may be possible to use a raw device as a Bochs hard disk,
|
||||
# but WE DON'T RECOMMEND IT. In Windows there is no easy way.
|
||||
#
|
||||
# Examples:
|
||||
# diskc: file=10M.sample, cyl=306, heads=4, spt=17
|
||||
# diskc: file=20M.sample, cyl=615, heads=4, spt=17
|
||||
# diskc: file=30M.sample, cyl=615, heads=6, spt=17
|
||||
# diskc: file=46M.sample, cyl=940, heads=6, spt=17
|
||||
# diskc: file=62M.sample, cyl=940, heads=8, spt=17
|
||||
# diskc: file=112M.sample, cyl=900, heads=15, spt=17
|
||||
# diskc: file=483M.sample, cyl=1024, heads=15, spt=63
|
||||
#=======================================================================
|
||||
#diskc: file="30M.sample", cyl=615, heads=6, spt=17
|
||||
|
||||
#=======================================================================
|
||||
#
|
||||
# The DISKD option is deprecated. Use ATA* options instead.
|
||||
#
|
||||
# DISKD:
|
||||
# See DISKC above for syntax
|
||||
#
|
||||
# NOTE: diskd and cdromd must not be used together!
|
||||
#=======================================================================
|
||||
#diskd: file="diskd.img", cyl=615, heads=6, spt=17
|
||||
|
||||
#=======================================================================
|
||||
#
|
||||
# The CDROMD option is deprecated. Use ATA* options instead.
|
||||
#
|
||||
# CDROMD:
|
||||
#
|
||||
# cdromd: dev=/dev/cdrom, status=inserted
|
||||
# cdromd: dev=/dev/cdrom, status=ejected
|
||||
# cdromd: dev=e:, status=ejected
|
||||
#
|
||||
# In windows, the drive letter + colon notation should be used for cdroms.
|
||||
# Depending on versions of windows and drivers, you may only be able to
|
||||
# access the "first" cdrom in the system. On MacOSX, use path="drive"
|
||||
# to access the physical drive.
|
||||
#
|
||||
# NOTE: diskd and cdromd must not be used together!
|
||||
#=======================================================================
|
||||
#cdromd: dev=D:, status=inserted
|
||||
#cdromd: dev=/dev/cdrom, status=inserted
|
||||
#cdromd: dev="drive", status=inserted
|
||||
|
||||
#=======================================================================
|
||||
# NEWHARDDRIVESUPPORT: enabled=[0|1]
|
||||
# As of cvs version on 5/17/2001, newharddrivesupport is on by default.
|
||||
#=======================================================================
|
||||
#newharddrivesupport: enabled=1
|
||||
|
||||
#=======================================================================
|
||||
# BOOT:
|
||||
# This defines your boot drive.
|
||||
# You can either boot from 'floppy', 'disk' or 'cdrom'
|
||||
# legacy 'a' and 'c' are also supported
|
||||
# Examples:
|
||||
# boot: floppy
|
||||
# boot: disk
|
||||
# boot: cdrom
|
||||
# boot: c
|
||||
# boot: a
|
||||
#=======================================================================
|
||||
#boot: floppy
|
||||
#boot: disk
|
||||
|
||||
#=======================================================================
|
||||
# FLOPPY_BOOTSIG_CHECK: disabled=[0|1]
|
||||
# Enables or disables the 0xaa55 signature check on boot floppies
|
||||
# Defaults to disabled=0
|
||||
# Examples:
|
||||
# floppy_bootsig_check: disabled=0
|
||||
# floppy_bootsig_check: disabled=1
|
||||
#=======================================================================
|
||||
#floppy_bootsig_check: disabled=1
|
||||
floppy_bootsig_check: disabled=0
|
||||
|
||||
#=======================================================================
|
||||
# LOG:
|
||||
# Give the path of the log file you'd like Bochs debug and misc. verbage
|
||||
# to be written to. If you really don't want it, make it /dev/null. :^(
|
||||
#
|
||||
# Examples:
|
||||
# log: ./bochs.out
|
||||
# log: /dev/tty
|
||||
#=======================================================================
|
||||
#log: /dev/null
|
||||
log: bochsout.txt
|
||||
|
||||
#=======================================================================
|
||||
# LOGPREFIX:
|
||||
# This handles the format of the string prepended to each log line.
|
||||
# You may use those special tokens :
|
||||
# %t : 11 decimal digits timer tick
|
||||
# %i : 8 hexadecimal digits of cpu0 current eip
|
||||
# %e : 1 character event type ('i'nfo, 'd'ebug, 'p'anic, 'e'rror)
|
||||
# %d : 5 characters string of the device, between brackets
|
||||
#
|
||||
# Default : %t%e%d
|
||||
# Examples:
|
||||
# logprefix: %t-%e-@%i-%d
|
||||
# logprefix: %i%e%d
|
||||
#=======================================================================
|
||||
#logprefix: %t%e%d
|
||||
|
||||
#=======================================================================
|
||||
# LOG CONTROLS
|
||||
#
|
||||
# Bochs now has four severity levels for event logging.
|
||||
# panic: cannot proceed. If you choose to continue after a panic,
|
||||
# don't be surprised if you get strange behavior or crashes.
|
||||
# error: something went wrong, but it is probably safe to continue the
|
||||
# simulation.
|
||||
# info: interesting or useful messages.
|
||||
# debug: messages useful only when debugging the code. This may
|
||||
# spit out thousands per second.
|
||||
#
|
||||
# For events of each level, you can choose to crash, report, or ignore.
|
||||
# TODO: allow choice based on the facility: e.g. crash on panics from
|
||||
# everything except the cdrom, and only report those.
|
||||
#
|
||||
# If you are experiencing many panics, it can be helpful to change
|
||||
# the panic action to report instead of fatal. However, be aware
|
||||
# that anything executed after a panic is uncharted territory and can
|
||||
# cause bochs to become unstable. The panic is a "graceful exit," so
|
||||
# if you disable it you may get a spectacular disaster instead.
|
||||
#=======================================================================
|
||||
panic: action=ask
|
||||
error: action=report
|
||||
info: action=report
|
||||
debug: action=ignore
|
||||
|
||||
#=======================================================================
|
||||
# DEBUGGER_LOG:
|
||||
# Give the path of the log file you'd like Bochs to log debugger output.
|
||||
# If you really don't want it, make it /dev/null or '-'. :^(
|
||||
#
|
||||
# Examples:
|
||||
# debugger_log: ./debugger.out
|
||||
#=======================================================================
|
||||
#debugger_log: /dev/null
|
||||
#debugger_log: debugger.out
|
||||
debugger_log: -
|
||||
|
||||
#=======================================================================
|
||||
# com1:
|
||||
# This defines a serial (COM) port. You can specify a device to use as com1.
|
||||
# This can be a real serial line, or a pty. To use a pty (under X/Unix),
|
||||
# create two windows (xterms, usually). One of them will run bochs, and the
|
||||
# other will act as com1. Find out the tty the com1 window using the `tty'
|
||||
# command, and use that as the `dev' parameter. Then do `sleep 1000000' in
|
||||
# the com1 window to keep the shell from messing with things, and run bochs in
|
||||
# the other window. Serial I/O to com1 (port 0x3f8) will all go to the other
|
||||
# window.
|
||||
#=======================================================================
|
||||
#com1: enabled=1, dev=/dev/ttyp9
|
||||
#com1: enabled=1, dev=/tmp/serial.log
|
||||
|
||||
|
||||
#=======================================================================
|
||||
# PARPORT1:
|
||||
# This defines a parallel (printer) port. When turned on and an output file is
|
||||
# defined the emulated printer port sends characters printed by the guest OS
|
||||
# into the output file. On some platforms a device filename can be used to
|
||||
# send the data to the real parallel port (e.g. "/dev/lp0" on Linux, "lpt1" on
|
||||
# win32 platforms).
|
||||
#
|
||||
# Examples:
|
||||
# parport1: enabled=1, file="parport.out"
|
||||
# parport1: enabled=1, file="/dev/lp0"
|
||||
# parport1: enabled=0
|
||||
#=======================================================================
|
||||
parport1: enabled=1, file="parport.out"
|
||||
|
||||
#=======================================================================
|
||||
# SB16:
|
||||
# This defines the SB16 sound emulation. It can have several of the
|
||||
# following properties.
|
||||
# All properties are in the format sb16: property=value
|
||||
# midi: The filename is where the midi data is sent. This can be a
|
||||
# device or just a file if you want to record the midi data.
|
||||
# midimode:
|
||||
# 0=no data
|
||||
# 1=output to device (system dependent. midi denotes the device driver)
|
||||
# 2=SMF file output, including headers
|
||||
# 3=output the midi data stream to the file (no midi headers and no
|
||||
# delta times, just command and data bytes)
|
||||
# wave: This is the device/file where wave output is stored
|
||||
# wavemode:
|
||||
# 0=no data
|
||||
# 1=output to device (system dependent. wave denotes the device driver)
|
||||
# 2=VOC file output, incl. headers
|
||||
# 3=output the raw wave stream to the file
|
||||
# log: The file to write the sb16 emulator messages to.
|
||||
# loglevel:
|
||||
# 0=no log
|
||||
# 1=only midi program and bank changes
|
||||
# 2=severe errors
|
||||
# 3=all errors
|
||||
# 4=all errors plus all port accesses
|
||||
# 5=all errors and port accesses plus a lot of extra info
|
||||
# dmatimer:
|
||||
# microseconds per second for a DMA cycle. Make it smaller to fix
|
||||
# non-continous sound. 750000 is usually a good value. This needs a
|
||||
# reasonably correct setting for IPS.
|
||||
#
|
||||
# For an example look at the next line:
|
||||
#=======================================================================
|
||||
|
||||
#sb16: midimode=1, midi=/dev/midi00, wavemode=1, wave=/dev/dsp, loglevel=2, log=sb16.log, dmatimer=600000
|
||||
|
||||
#=======================================================================
|
||||
# VGA_UPDATE_INTERVAL:
|
||||
# Video memory is scanned for updates and screen updated every so many
|
||||
# virtual seconds. The default is 300000, about 3Hz. This is generally
|
||||
# plenty. Keep in mind that you must tweak the 'ips:' directive
|
||||
# to be as close to the number of emulated instructions-per-second
|
||||
# your workstation can do, for this to be accurate.
|
||||
#
|
||||
# Examples:
|
||||
# vga_update_interval: 250000
|
||||
#=======================================================================
|
||||
vga_update_interval: 300000
|
||||
|
||||
# using for Winstone '98 tests
|
||||
#vga_update_interval: 100000
|
||||
|
||||
#=======================================================================
|
||||
# KEYBOARD_SERIAL_DELAY:
|
||||
# Approximate time in microseconds that it takes one character to
|
||||
# be transfered from the keyboard to controller over the serial path.
|
||||
# Examples:
|
||||
# keyboard_serial_delay: 200
|
||||
#=======================================================================
|
||||
keyboard_serial_delay: 250
|
||||
|
||||
#=======================================================================
|
||||
# KEYBOARD_PASTE_DELAY:
|
||||
# Approximate time in microseconds between attempts to paste
|
||||
# characters to the keyboard controller. This leaves time for the
|
||||
# guest os to deal with the flow of characters. The ideal setting
|
||||
# depends on how your operating system processes characters. The
|
||||
# default of 100000 usec (.1 seconds) was chosen because it works
|
||||
# consistently in Windows.
|
||||
#
|
||||
# If your OS is losing characters during a paste, increase the paste
|
||||
# delay until it stops losing characters.
|
||||
#
|
||||
# Examples:
|
||||
# keyboard_paste_delay: 100000
|
||||
#=======================================================================
|
||||
keyboard_paste_delay: 100000
|
||||
|
||||
#=======================================================================
|
||||
# FLOPPY_COMMAND_DELAY:
|
||||
# Time in microseconds to wait before completing some floppy commands
|
||||
# such as read/write/seek/etc, which normally have a delay associated.
|
||||
# I had this hardwired to 50,000 before.
|
||||
#
|
||||
# Examples:
|
||||
# floppy_command_delay: 50000
|
||||
#=======================================================================
|
||||
floppy_command_delay: 500
|
||||
|
||||
#=======================================================================
|
||||
# IPS:
|
||||
# Emulated Instructions Per Second. This is the number of IPS that bochs
|
||||
# is capable of running on your machine. Read the note in config.h
|
||||
# on how to find this. Make sure to recompile after.
|
||||
#
|
||||
# IPS is used to calibrate many time-dependent events within the bochs
|
||||
# simulation. For example, changing IPS affects the frequency of VGA
|
||||
# updates, the duration of time before a key starts to autorepeat, and
|
||||
# the measurement of BogoMips and other benchmarks.
|
||||
#
|
||||
# Examples:
|
||||
# Machine Mips
|
||||
# ________________________________________________________________
|
||||
# 650Mhz Athlon K-7 with Linux 2.4.4/egcs-2.91.66 2 to 2.5 Mips
|
||||
# 400Mhz Pentium II with Linux 2.0.36/egcs-1.0.3 1 to 1.8 Mips
|
||||
# 166Mhz 64bit Sparc with Solaris 2.x approx 0.75 Mips
|
||||
# 200Mhz Pentium with Linux 2.x approx 0.5 Mips
|
||||
#
|
||||
#=======================================================================
|
||||
ips: 1000000
|
||||
|
||||
#=======================================================================
|
||||
# PIT:
|
||||
# The PIT is the programmable interval timer. It has an option that tries to
|
||||
# keep the PIT in sync with real time. This feature is still experimental,
|
||||
# but it may be useful if you want to prevent Bochs from running too fast, for
|
||||
# example a DOS video game. Be aware that with the realtime pit option, your
|
||||
# simulation will not be repeatable; this can a problem if you are debugging.
|
||||
#=======================================================================
|
||||
#pit: realtime=1
|
||||
|
||||
#=======================================================================
|
||||
# mouse: Not used in any of the GUI specific modules, but the option
|
||||
# bx_options.mouse_enabled is set to this value. The idea,
|
||||
# is that the GUI code should not generate mouse events when
|
||||
# not enabled. The hardware emualation itself is not disabled
|
||||
# by this. This is to facilitate deterministic runs of bochs.
|
||||
#
|
||||
# Examples:
|
||||
# mouse: enabled=1
|
||||
# mouse: enabled=0
|
||||
#
|
||||
# I wouldn't recommend enabling the mouse by default, unless you have a
|
||||
# really good reason to do so.
|
||||
#=======================================================================
|
||||
mouse: enabled=0
|
||||
|
||||
#=======================================================================
|
||||
# private_colormap: Request that the GUI create and use it's own
|
||||
# non-shared colormap. This colormap will be used
|
||||
# when in the bochs window. If not enabled, a
|
||||
# shared colormap scheme may be used. Not implemented
|
||||
# on all GUI's.
|
||||
#
|
||||
# Examples:
|
||||
# private_colormap: enabled=1
|
||||
# private_colormap: enabled=0
|
||||
#=======================================================================
|
||||
private_colormap: enabled=0
|
||||
|
||||
#=======================================================================
|
||||
# fullscreen: ONLY IMPLEMENTED ON AMIGA
|
||||
# Request that Bochs occupy the entire screen instead of a
|
||||
# window.
|
||||
#
|
||||
# Examples:
|
||||
# fullscreen: enabled=0
|
||||
# fullscreen: enabled=1
|
||||
#=======================================================================
|
||||
fullscreen: enabled=0
|
||||
screenmode: name="sample"
|
||||
|
||||
#=======================================================================
|
||||
# ne2k: NE2000 compatible ethernet adapter
|
||||
#
|
||||
# Examples:
|
||||
# ne2k: ioaddr=IOADDR, irq=IRQ, mac=MACADDR, ethmod=MODULE, ethdev=DEVICE, script=SCRIPT
|
||||
#
|
||||
# ioaddr, irq: You probably won't need to change ioaddr and irq, unless there
|
||||
# are IRQ conflicts.
|
||||
#
|
||||
# mac: The MAC address MUST NOT match the address of any machine on the net.
|
||||
# Also, the first byte must be an even number (bit 0 set means a multicast
|
||||
# address), and you cannot use ff:ff:ff:ff:ff:ff because that's the broadcast
|
||||
# address. For the ethertap module, you must use fe:fd:00:00:00:01. There may
|
||||
# be other restrictions too. To be safe, just use the b0:c4... address.
|
||||
#
|
||||
# ethdev: The ethdev value is the name of the network interface on your host
|
||||
# platform. On UNIX machines, you can get the name by running ifconfig. On
|
||||
# Windows machines, you must run niclist to get the name of the ethdev.
|
||||
# Niclist source code is in misc/niclist.c and it is included in Windows
|
||||
# binary releases.
|
||||
#
|
||||
# script: The script value is optionnal, and is the name of a script that
|
||||
# is executed after bochs initialize the network interface. You can use
|
||||
# this script to configure this network interface, or enable masquerading.
|
||||
# This is mainly useful for the tun/tap devices that only exist during
|
||||
# Bochs execution. The network interface name is supplied to the script
|
||||
# as first parameter
|
||||
#=======================================================================
|
||||
# ne2k: ioaddr=0x280, irq=9, mac=b0:c4:20:00:00:00, ethmod=fbsd, ethdev=xl0
|
||||
# ne2k: ioaddr=0x280, irq=9, mac=b0:c4:20:00:00:00, ethmod=linux, ethdev=eth0
|
||||
# ne2k: ioaddr=0x280, irq=9, mac=b0:c4:20:00:00:01, ethmod=win32, ethdev=MYCARD
|
||||
# ne2k: ioaddr=0x280, irq=9, mac=fe:fd:00:00:00:01, ethmod=tap, ethdev=tap0
|
||||
# ne2k: ioaddr=0x280, irq=9, mac=fe:fd:00:00:00:01, ethmod=tuntap, ethdev=tun0, script=./ifup.tun
|
||||
# ne2k: ioaddr=0x280, irq=9, mac=fe:fd:00:00:00:01, ethmod=tuntap, ethdev=tun0
|
||||
|
||||
# Pseudo NIC adaptor. The way bochs is structured at the moment means
|
||||
# that you need to enable ne2k support in order to compile in any of
|
||||
# the networking code.
|
||||
pnic: ioaddr=0xdc00, irq=11, mac=fe:fd:00:00:00:01, ethmod=tuntap, ethdev=tun1, script=./ifup.tun
|
||||
|
||||
#=======================================================================
|
||||
# KEYBOARD_MAPPING:
|
||||
# This enables a remap of a physical localized keyboard to a
|
||||
# virtualized us keyboard, as the PC architecture expects.
|
||||
# If enabled, the keymap file must be specified.
|
||||
#
|
||||
# Examples:
|
||||
# keyboard_mapping: enabled=1, map=gui/keymaps/x11-pc-de.map
|
||||
#=======================================================================
|
||||
keyboard_mapping: enabled=0, map=
|
||||
|
||||
#=======================================================================
|
||||
# KEYBOARD_TYPE:
|
||||
# Type of keyboard return by a "identify keyboard" command to the
|
||||
# keyboard controler. It must be one of "xt", "at" or "mf".
|
||||
# Defaults to "mf". It should be ok for almost everybody. A known
|
||||
# exception is french macs, that do have a "at"-like keyboard.
|
||||
#
|
||||
# Examples:
|
||||
# keyboard_type: mf
|
||||
#=======================================================================
|
||||
#keyboard_type: mf
|
||||
|
||||
#=======================================================================
|
||||
# USER_SHORTCUT:
|
||||
# This defines the keyboard shortcut to be sent when you press the "user"
|
||||
# button in the headerbar. The shortcut string can be a combination of
|
||||
# these key names: "alt", "ctrl", "del", "esc", "f1", "f4", "tab", "win".
|
||||
# Up to 3 keys can be pressed at a time.
|
||||
#
|
||||
# Example:
|
||||
# user_shortcut: keys=ctrlaltdel
|
||||
#=======================================================================
|
||||
user_shortcut: keys=ctrlaltdel
|
||||
|
||||
#=======================================================================
|
||||
# other stuff
|
||||
#=======================================================================
|
||||
magic_break: enabled=1
|
||||
|
||||
#load32bitOSImage: os=nullkernel, path=../kernel.img, iolog=../vga_io.log
|
||||
#load32bitOSImage: os=linux, path=../linux.img, iolog=../vga_io.log, initrd=../initrd.img
|
||||
i440fxsupport: enabled=1
|
||||
#time0: 938581955
|
||||
|
||||
#=======================================================================
|
||||
# for Macintosh, use the style of pathnames in the following
|
||||
# examples.
|
||||
#
|
||||
# vgaromimage: :bios:VGABIOS-elpin-2.20
|
||||
# romimage: file=:bios:BIOS-bochs-981222a, address=0xf0000
|
||||
# floppya: 1_44=[fd:], status=inserted
|
||||
#=======================================================================
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
#!/bin/sh
|
||||
|
||||
SCRIPT=$0
|
||||
INTERFACE=$1
|
||||
|
||||
if [ `id -u` != 0 ]; then
|
||||
echo ""
|
||||
echo "Enter root password for configuring network interface $INTERFACE"
|
||||
echo "(To avoid this prompt, make the script $SCRIPT setuid-root)"
|
||||
/bin/su -c "$SCRIPT $INTERFACE" || exit 1
|
||||
exit 0
|
||||
fi
|
||||
|
||||
/sbin/ifconfig $INTERFACE 10.254.254.2 netmask 255.255.255.252
|
||||
|
||||
# Force dhcpd to notice the new network interface
|
||||
if [ -x /etc/init.d/dhcpd ]; then
|
||||
/etc/init.d/dhcpd reload # Redhat
|
||||
elif [ -x /etc/init.d/dhcp ]; then
|
||||
/etc/init.d/dhcp restart # Debian
|
||||
fi
|
|
@ -0,0 +1,278 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
=head1 NAME
|
||||
|
||||
serial-console
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
serial-console [options]
|
||||
|
||||
Options:
|
||||
|
||||
-h,--help Display brief help message
|
||||
-v,--verbose Increase verbosity
|
||||
-q,--quiet Decrease verbosity
|
||||
-l,--log FILE Log output to file
|
||||
-r,--rcfile FILE Modify specified bochsrc file
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<serial-console> provides a virtual serial console for use with
|
||||
Bochs. Running C<serial-console> creates a pseudo-tty. The master
|
||||
side of this pty is made available to the user for interaction; the
|
||||
slave device is written to the Bochs configuration file
|
||||
(C<bochsrc.txt>) for use by a subsequent Bochs session.
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
=over 4
|
||||
|
||||
=item C<serial-console>
|
||||
|
||||
Create a virtual serial console for Bochs, modify C<bochsrc.txt>
|
||||
appropriately.
|
||||
|
||||
=item C<serial-console -r ../.bochsrc -l serial.log>
|
||||
|
||||
Create a virtual serial console for Bochs, modify C<../.bochsrc>
|
||||
appropriately, log output to C<serial.log>.
|
||||
|
||||
=back
|
||||
|
||||
=head1 INVOCATION
|
||||
|
||||
Before starting Bochs, run C<serial-console> in a different session
|
||||
(e.g. a different xterm window). When you subsequently start Bochs,
|
||||
anything that the emulated machine writes to its serial port will
|
||||
appear in the window running C<serial-console>, and anything typed in
|
||||
the C<serial-console> window will arrive on the emulated machine's
|
||||
serial port.
|
||||
|
||||
You do B<not> need to rerun C<serial-console> afresh for each Bochs
|
||||
session.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<-l,--log FILE>
|
||||
|
||||
Log all output (i.e. everything that is printed in the
|
||||
C<serial-console> window) to the specified file.
|
||||
|
||||
=item B<-r,--rcfile FILE>
|
||||
|
||||
Modify the specified bochsrc file. The file will be updated to
|
||||
contain the path to the slave side of the psuedo tty that we create.
|
||||
The original file will be restored when C<serial-console> exits. The
|
||||
default is to modify the file C<bochsrc.txt> in the current directory.
|
||||
|
||||
To avoid modifying any bochsrc file, use C<--norcfile>.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
use IO::Pty;
|
||||
use IO::Select;
|
||||
use File::Spec::Functions qw ( :ALL );
|
||||
use Getopt::Long;
|
||||
use Pod::Usage;
|
||||
use POSIX qw ( :termios_h );
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $o;
|
||||
my $restore_file = {};
|
||||
my $restore_termios;
|
||||
use constant BLOCKSIZE => 8192;
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Parse command line options into options hash ($o)
|
||||
#
|
||||
# $o = parse_opts();
|
||||
|
||||
sub parse_opts {
|
||||
# $o is the hash that will hold the options
|
||||
my $o = {
|
||||
verbosity => 1,
|
||||
rcfile => 'bochsrc.txt',
|
||||
};
|
||||
# Special handlers for some options
|
||||
my $opt_handlers = {
|
||||
verbose => sub { $o->{verbosity}++; },
|
||||
quiet => sub { $o->{verbosity}--; },
|
||||
help => sub { pod2usage(1); },
|
||||
norcfile => sub { delete $o->{rcfile}; },
|
||||
};
|
||||
# Merge handlers into main options hash (so that Getopt::Long can find them)
|
||||
$o->{$_} = $opt_handlers->{$_} foreach keys %$opt_handlers;
|
||||
# Option specifiers for Getopt::Long
|
||||
my @optspec = ( 'help|h|?',
|
||||
'quiet|q+',
|
||||
'verbose|v+',
|
||||
'log|l=s',
|
||||
'rcfile|r=s',
|
||||
'norcfile',
|
||||
);
|
||||
# Do option parsing
|
||||
Getopt::Long::Configure ( 'bundling' );
|
||||
pod2usage("Error parsing command-line options") unless GetOptions (
|
||||
$o, @optspec );
|
||||
# Clean up $o by removing the handlers
|
||||
delete $o->{$_} foreach keys %$opt_handlers;
|
||||
return $o;
|
||||
}
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Modify bochsrc file
|
||||
|
||||
sub patch_bochsrc {
|
||||
my $active = shift;
|
||||
my $pty = shift;
|
||||
|
||||
# Rename active file to backup file
|
||||
( my $vol, my $dir, my $file ) = splitpath ( $active );
|
||||
$file = '.'.$file.".serial-console";
|
||||
my $backup = catpath ( $vol, $dir, $file );
|
||||
rename $active, $backup
|
||||
or die "Could not back up $active to $backup: $!\n";
|
||||
|
||||
# Derive line to be inserted
|
||||
my $patch = "com1: enabled=1, dev=$pty\n";
|
||||
|
||||
# Modify file
|
||||
open my $old, "<$backup" or die "Could not open $backup: $!\n";
|
||||
open my $new, ">$active" or die "Could not open $active: $!\n";
|
||||
print $new <<"EOF";
|
||||
##################################################
|
||||
#
|
||||
# This file has been modified by serial-console.
|
||||
#
|
||||
# Do not modify this file; it will be erased when
|
||||
# serial-console (pid $$) exits and will be
|
||||
# replaced with the backup copy held in
|
||||
# $backup.
|
||||
#
|
||||
##################################################
|
||||
|
||||
|
||||
EOF
|
||||
my $patched;
|
||||
while ( my $line = <$old> ) {
|
||||
if ( $line =~ /^\s*\#?\s*com1:\s*\S/ ) {
|
||||
if ( ! $patched ) {
|
||||
$line = $patch;
|
||||
$patched = 1;
|
||||
} else {
|
||||
$line = '# '.$line unless $line =~ /^\s*\#/;
|
||||
}
|
||||
}
|
||||
print $new $line;
|
||||
}
|
||||
print $new $patch unless $patched;
|
||||
close $old;
|
||||
close $new;
|
||||
|
||||
return $backup;
|
||||
}
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Attach/detach message printing and terminal settings
|
||||
|
||||
sub bochs_attached {
|
||||
print STDERR "Bochs attached.\n\n\n"
|
||||
if $o->{verbosity} >= 1;
|
||||
}
|
||||
|
||||
sub bochs_detached {
|
||||
print STDERR "\n\nWaiting for bochs to attach...\n"
|
||||
if $o->{verbosity} >= 1;
|
||||
}
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Main program
|
||||
|
||||
$o = parse_opts();
|
||||
pod2usage(1) if @ARGV;
|
||||
|
||||
# Catch signals
|
||||
my $sigdie = sub { die "Exiting via signal\n"; };
|
||||
$SIG{INT} = $sigdie;
|
||||
|
||||
# Create Pty, close slave side
|
||||
my $pty = IO::Pty->new();
|
||||
$pty->close_slave();
|
||||
$pty->set_raw();
|
||||
print STDERR "Slave pty is ".$pty->ttyname."\n" if $o->{verbosity} >= 1;
|
||||
|
||||
# Open logfile
|
||||
my $log;
|
||||
if ( $o->{log} ) {
|
||||
open $log, ">$o->{log}" or die "Could not open $o->{log}: $!\n";
|
||||
}
|
||||
|
||||
# Set up terminal
|
||||
my $termios;
|
||||
if ( -t STDIN ) {
|
||||
$termios = POSIX::Termios->new;
|
||||
$restore_termios = POSIX::Termios->new;
|
||||
$termios->getattr ( fileno(STDIN) );
|
||||
$restore_termios->getattr ( fileno(STDIN) );
|
||||
$termios->setlflag ( $termios->getlflag &
|
||||
~(ICANON) & ~(ECHO) );
|
||||
$termios->setattr ( fileno(STDIN), TCSANOW );
|
||||
}
|
||||
|
||||
# Modify bochsrc file
|
||||
$restore_file = { $o->{rcfile} =>
|
||||
patch_bochsrc ( $o->{rcfile}, $pty->ttyname ) }
|
||||
if $o->{rcfile};
|
||||
|
||||
# Start character shunt
|
||||
my $attached = 1;
|
||||
my $select = IO::Select->new ( \*STDIN, $pty );
|
||||
while ( 1 ) {
|
||||
my %can_read = map { $_ => 1 }
|
||||
$select->can_read ( $attached ? undef : 1 );
|
||||
if ( $can_read{\*STDIN} ) {
|
||||
sysread ( STDIN, my $data, BLOCKSIZE )
|
||||
or die "Cannot read from STDIN: $!\n";
|
||||
$pty->syswrite ( $data );
|
||||
}
|
||||
if ( $can_read{$pty} ) {
|
||||
if ( $pty->sysread ( my $data, BLOCKSIZE ) ) {
|
||||
# Actual data available
|
||||
bochs_attached() if $attached == 0;
|
||||
$attached = 1;
|
||||
syswrite ( STDOUT, $data );
|
||||
$log->syswrite ( $data ) if $log;
|
||||
} else {
|
||||
# No data available but select() says we can read. This almost
|
||||
# certainly indicates that nothing is attached to the slave.
|
||||
bochs_detached() if $attached == 1;
|
||||
$attached = 0;
|
||||
sleep ( 1 );
|
||||
}
|
||||
} else {
|
||||
bochs_attached() if $attached == 0;
|
||||
$attached = 1;
|
||||
}
|
||||
}
|
||||
|
||||
END {
|
||||
# Restore bochsrc file if applicable
|
||||
if ( ( my $orig_file, my $backup_file ) = %$restore_file ) {
|
||||
unlink $orig_file;
|
||||
rename $backup_file, $orig_file;
|
||||
}
|
||||
# Restore terminal settings if applicable
|
||||
if ( $restore_termios ) {
|
||||
$restore_termios->setattr ( fileno(STDIN), TCSANOW );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,191 @@
|
|||
.\" Automatically generated by Pod::Man v1.34, Pod::Parser v1.13
|
||||
.\"
|
||||
.\" Standard preamble:
|
||||
.\" ========================================================================
|
||||
.de Sh \" Subsection heading
|
||||
.br
|
||||
.if t .Sp
|
||||
.ne 5
|
||||
.PP
|
||||
\fB\\$1\fR
|
||||
.PP
|
||||
..
|
||||
.de Sp \" Vertical space (when we can't use .PP)
|
||||
.if t .sp .5v
|
||||
.if n .sp
|
||||
..
|
||||
.de Vb \" Begin verbatim text
|
||||
.ft CW
|
||||
.nf
|
||||
.ne \\$1
|
||||
..
|
||||
.de Ve \" End verbatim text
|
||||
.ft R
|
||||
.fi
|
||||
..
|
||||
.\" Set up some character translations and predefined strings. \*(-- will
|
||||
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
|
||||
.\" double quote, and \*(R" will give a right double quote. | will give a
|
||||
.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to
|
||||
.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C'
|
||||
.\" expand to `' in nroff, nothing in troff, for use with C<>.
|
||||
.tr \(*W-|\(bv\*(Tr
|
||||
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
|
||||
.ie n \{\
|
||||
. ds -- \(*W-
|
||||
. ds PI pi
|
||||
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
|
||||
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
|
||||
. ds L" ""
|
||||
. ds R" ""
|
||||
. ds C` ""
|
||||
. ds C' ""
|
||||
'br\}
|
||||
.el\{\
|
||||
. ds -- \|\(em\|
|
||||
. ds PI \(*p
|
||||
. ds L" ``
|
||||
. ds R" ''
|
||||
'br\}
|
||||
.\"
|
||||
.\" If the F register is turned on, we'll generate index entries on stderr for
|
||||
.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index
|
||||
.\" entries marked with X<> in POD. Of course, you'll have to process the
|
||||
.\" output yourself in some meaningful fashion.
|
||||
.if \nF \{\
|
||||
. de IX
|
||||
. tm Index:\\$1\t\\n%\t"\\$2"
|
||||
..
|
||||
. nr % 0
|
||||
. rr F
|
||||
.\}
|
||||
.\"
|
||||
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
||||
.\" way too many mistakes in technical documents.
|
||||
.hy 0
|
||||
.if n .na
|
||||
.\"
|
||||
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
|
||||
.\" Fear. Run. Save yourself. No user-serviceable parts.
|
||||
. \" fudge factors for nroff and troff
|
||||
.if n \{\
|
||||
. ds #H 0
|
||||
. ds #V .8m
|
||||
. ds #F .3m
|
||||
. ds #[ \f1
|
||||
. ds #] \fP
|
||||
.\}
|
||||
.if t \{\
|
||||
. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
|
||||
. ds #V .6m
|
||||
. ds #F 0
|
||||
. ds #[ \&
|
||||
. ds #] \&
|
||||
.\}
|
||||
. \" simple accents for nroff and troff
|
||||
.if n \{\
|
||||
. ds ' \&
|
||||
. ds ` \&
|
||||
. ds ^ \&
|
||||
. ds , \&
|
||||
. ds ~ ~
|
||||
. ds /
|
||||
.\}
|
||||
.if t \{\
|
||||
. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
|
||||
. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
|
||||
. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
|
||||
. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
|
||||
. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
|
||||
. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
|
||||
.\}
|
||||
. \" troff and (daisy-wheel) nroff accents
|
||||
.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
|
||||
.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
|
||||
.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
|
||||
.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
|
||||
.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
|
||||
.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
|
||||
.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
|
||||
.ds ae a\h'-(\w'a'u*4/10)'e
|
||||
.ds Ae A\h'-(\w'A'u*4/10)'E
|
||||
. \" corrections for vroff
|
||||
.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
|
||||
.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
|
||||
. \" for low resolution devices (crt and lpr)
|
||||
.if \n(.H>23 .if \n(.V>19 \
|
||||
\{\
|
||||
. ds : e
|
||||
. ds 8 ss
|
||||
. ds o a
|
||||
. ds d- d\h'-1'\(ga
|
||||
. ds D- D\h'-1'\(hy
|
||||
. ds th \o'bp'
|
||||
. ds Th \o'LP'
|
||||
. ds ae ae
|
||||
. ds Ae AE
|
||||
.\}
|
||||
.rm #[ #] #H #V #F C
|
||||
.\" ========================================================================
|
||||
.\"
|
||||
.IX Title "SERIAL-CONSOLE 1"
|
||||
.TH SERIAL-CONSOLE 1 "2004-03-10" "perl v5.8.0" "User Contributed Perl Documentation"
|
||||
.SH "NAME"
|
||||
serial\-console
|
||||
.SH "SYNOPSIS"
|
||||
.IX Header "SYNOPSIS"
|
||||
serial-console [options]
|
||||
.PP
|
||||
Options:
|
||||
.PP
|
||||
.Vb 5
|
||||
\& -h,--help Display brief help message
|
||||
\& -v,--verbose Increase verbosity
|
||||
\& -q,--quiet Decrease verbosity
|
||||
\& -l,--log FILE Log output to file
|
||||
\& -r,--rcfile FILE Modify specified bochsrc file
|
||||
.Ve
|
||||
.SH "DESCRIPTION"
|
||||
.IX Header "DESCRIPTION"
|
||||
\&\f(CW\*(C`serial\-console\*(C'\fR provides a virtual serial console for use with
|
||||
Bochs. Running \f(CW\*(C`serial\-console\*(C'\fR creates a pseudo\-tty. The master
|
||||
side of this pty is made available to the user for interaction; the
|
||||
slave device is written to the Bochs configuration file
|
||||
(\f(CW\*(C`bochsrc.txt\*(C'\fR) for use by a subsequent Bochs session.
|
||||
.SH "EXAMPLES"
|
||||
.IX Header "EXAMPLES"
|
||||
.ie n .IP """serial\-console""" 4
|
||||
.el .IP "\f(CWserial\-console\fR" 4
|
||||
.IX Item "serial-console"
|
||||
Create a virtual serial console for Bochs, modify \f(CW\*(C`bochsrc.txt\*(C'\fR
|
||||
appropriately.
|
||||
.ie n .IP """serial\-console \-r ../.bochsrc \-l serial.log""" 4
|
||||
.el .IP "\f(CWserial\-console \-r ../.bochsrc \-l serial.log\fR" 4
|
||||
.IX Item "serial-console -r ../.bochsrc -l serial.log"
|
||||
Create a virtual serial console for Bochs, modify \f(CW\*(C`../.bochsrc\*(C'\fR
|
||||
appropriately, log output to \f(CW\*(C`serial.log\*(C'\fR.
|
||||
.SH "INVOCATION"
|
||||
.IX Header "INVOCATION"
|
||||
Before starting Bochs, run \f(CW\*(C`serial\-console\*(C'\fR in a different session
|
||||
(e.g. a different xterm window). When you subsequently start Bochs,
|
||||
anything that the emulated machine writes to its serial port will
|
||||
appear in the window running \f(CW\*(C`serial\-console\*(C'\fR, and anything typed in
|
||||
the \f(CW\*(C`serial\-console\*(C'\fR window will arrive on the emulated machine's
|
||||
serial port.
|
||||
.PP
|
||||
You do \fBnot\fR need to rerun \f(CW\*(C`serial\-console\*(C'\fR afresh for each Bochs
|
||||
session.
|
||||
.SH "OPTIONS"
|
||||
.IX Header "OPTIONS"
|
||||
.IP "\fB\-l,\-\-log \s-1FILE\s0\fR" 4
|
||||
.IX Item "-l,--log FILE"
|
||||
Log all output (i.e. everything that is printed in the
|
||||
\&\f(CW\*(C`serial\-console\*(C'\fR window) to the specified file.
|
||||
.IP "\fB\-r,\-\-rcfile \s-1FILE\s0\fR" 4
|
||||
.IX Item "-r,--rcfile FILE"
|
||||
Modify the specified bochsrc file. The file will be updated to
|
||||
contain the path to the slave side of the psuedo tty that we create.
|
||||
The original file will be restored when \f(CW\*(C`serial\-console\*(C'\fR exits. The
|
||||
default is to modify the file \f(CW\*(C`bochsrc.txt\*(C'\fR in the current directory.
|
||||
.Sp
|
||||
To avoid modifying any bochsrc file, use \f(CW\*(C`\-\-norcfile\*(C'\fR.
|
|
@ -0,0 +1,42 @@
|
|||
#!/usr/bin/perl -w
|
||||
#
|
||||
# Quick hack to convert /etc/bootptab to format required by ISC DHCPD
|
||||
# This only outputs the fixed hosts portion of the config file
|
||||
# You still have to provide the global options and the subnet scoping
|
||||
#
|
||||
# Turn $useipaddr on if you prefer to use IP addresses in the config file
|
||||
# I run DNS so I prefer domain names
|
||||
$useipaddr = 0;
|
||||
# This will be appended to get the FQDN unless the hostname is already FQDN
|
||||
$domainname = "ken.com.au";
|
||||
$tftpdir = "/tftpdir/";
|
||||
open(B, "/etc/bootptab") or die "/etc/bootptab: $!\n";
|
||||
while(<B>) {
|
||||
if (/^[^a-z]/) {
|
||||
$prevline = $_;
|
||||
next;
|
||||
}
|
||||
chomp($_);
|
||||
($hostname, @tags) = split(/:/, $_, 5);
|
||||
($fqdn = $hostname) .= ".$domainname" unless($hostname =~ /\./);
|
||||
($macaddr) = grep(/^ha=/, @tags);
|
||||
$macaddr =~ s/ha=//;
|
||||
$macaddr =~ s/(..)(..)(..)(..)(..)(..)/$1:$2:$3:$4:$5:$6/g;
|
||||
($ipaddr) = grep(/^ip=/, @tags);
|
||||
$ipaddr =~ s/ip=//;
|
||||
($bootfile) = grep(/^bf=/, @tags);
|
||||
$bootfile =~ s/bf=//;
|
||||
$bootfile = $tftpdir . $bootfile;
|
||||
# I have a comment line above most entries and I like to carry this over
|
||||
print $prevline if ($prevline =~ /^#/);
|
||||
$address = $useipaddr ? $ipaddr : $fqdn;
|
||||
print <<EOF
|
||||
host $hostname {
|
||||
hardware ethernet $macaddr;
|
||||
fixed-address $address;
|
||||
filename "$bootfile";
|
||||
}
|
||||
EOF
|
||||
;
|
||||
$prevline = $_;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
The compression code as implemented in "lzhuf.c" was taken from a BBS
|
||||
program written by Joachim Schurig <jschurig@zedat.fu-berlin.de>. He
|
||||
states that the code can be used freely for programs that are covered
|
||||
by a "freeware" license. This probably includes both BSD style
|
||||
licenses and the GPL.
|
||||
|
||||
The code in "loader.asm" is a reimplementation of the uncompressor. It
|
||||
has been written from scratch and is hereby placed under the
|
||||
conditions of the GNU General Public License (GPL). The algorithm is
|
||||
outlined in "algorithm.doc".
|
||||
|
||||
Thus, there are no copyright problems with using this code, but there
|
||||
still might be difficulties with software patents. These patents are
|
||||
not legal in most parts of the world, but if you live in a country
|
||||
that honors software patents then you should verify that using these
|
||||
algorithms is legally permitted. Unless you are absolutely sure, that
|
||||
there are no legal obstacles, you should use the code for educational
|
||||
purposes only (this assumes that your educational institution is
|
||||
exempted from patent laws). The author cannot be held responsible for
|
||||
using the program code in violation of applicable local laws.
|
||||
|
||||
If you are aware of patents that might affect the legality of using
|
||||
the code in some parts of the world, please let me know.
|
|
@ -0,0 +1,58 @@
|
|||
The compressor achieves an average compression rate of 60% of the
|
||||
original size which is on par with "gzip". It seems that you cannot do
|
||||
much better for compressing compiled binaries. This means that the
|
||||
break even point for using compressed images is reached, once the
|
||||
uncompressed size approaches 1.5kB. We can stuff more than 12kB into
|
||||
an 8kB EPROM and more than 25kB into an 16kB EPROM. As there is only
|
||||
32kB of RAM for both the uncompressed image and its BSS area, this
|
||||
means that 32kB EPROMs will hardly ever be required.
|
||||
|
||||
The compression algorithm uses a 4kB ring buffer for buffering the
|
||||
uncompressed data. Before compression starts, the ring buffer is
|
||||
filled with spaces (ASCII character 0x20). The algorithm tries to
|
||||
find repeated input sequences of a maximum length of 60 bytes. All
|
||||
256 different input bytes plus the 58 (60 minus a threshold of 2)
|
||||
possible repeat lengths form a set of 314 symbols. These symbols are
|
||||
adaptively Huffman encoded. The algorithm starts out with a Huffmann
|
||||
tree that assigns equal code lengths to each of the 314 symbols
|
||||
(slightly favoring the repeat symbols over symbols for regular input
|
||||
characters), but it will be changed whenever the frequency of any of
|
||||
the symbols changes. Frequency counts are kept in 16bit words until
|
||||
the total number of compressed codes totals 2^15. Then, all frequency
|
||||
counts will be halfed (rounding to the bigger number). For unrepeated
|
||||
characters (symbols 0..255) the Huffman code is written to the output
|
||||
stream. For repeated characters the Huffmann code, which denotes the
|
||||
length of the repeated character sequence, is written out and then the
|
||||
index in the ring buffer is computed. From this index, the algorithm
|
||||
computes the offset relative to the current index into the ring
|
||||
buffer. Thus, for typical input data, one would expect that short to
|
||||
medium range offsets are more frequent than extremely short or medium
|
||||
range to long range offsets. Thus the 12bit (for a 4kB buffer) offset
|
||||
value is statically Huffman encoded using a precomputed Huffman tree
|
||||
that favors those offset values that are deemed to be more
|
||||
frequent. The Huffman encoded offset is written to the output data
|
||||
stream, directly following the code that determines the length of
|
||||
repeated characters.
|
||||
|
||||
This algorithm, as implemented in the C example code, looks very good
|
||||
and its operating parameters are already well optimized. This also
|
||||
explains why it achieves compression ratios comparable with
|
||||
"gzip". Depending on the input data, it sometimes excells considerably
|
||||
beyond what "gzip -9" does, but this phenomenon does not appear to be
|
||||
typical. There are some flaws with the algorithm, such as the limited
|
||||
buffer sizes, the adaptive Huffman tree which takes very long to
|
||||
change, if the input characters experience a sudden change in
|
||||
distribution, and the static Huffman tree for encoding offsets into
|
||||
the buffer. The slow changes of the adaptive Huffman tree are
|
||||
partially counteracted by artifically keeping a 16bit precision for
|
||||
the frequency counts, but this does not come into play until 32kB of
|
||||
compressed data is output, so it does not have any impact on our use
|
||||
for "etherboot", because the BOOT Prom does not support uncompressed
|
||||
data of more then 32kB (c.f. doc/spec.doc).
|
||||
|
||||
Nonetheless, these problems do not seem to affect compression of
|
||||
compiled programs very much. Mixing object code with English text,
|
||||
would not work too well though, and the algorithm should be reset in
|
||||
between. Actually, we might gain a little improvement, if text and
|
||||
data segments were compressed individually, but I have not
|
||||
experimented with this option, yet.
|
|
@ -0,0 +1,14 @@
|
|||
/* Do not change these values unless you really know what you are doing;
|
||||
the pre-computed lookup tables rely on the buffer size being 4kB or
|
||||
smaller. The buffer size must be a power of two. The lookahead size has
|
||||
to fit into 6 bits. If you change any of these numbers, you will also
|
||||
have to adjust the decompressor accordingly.
|
||||
*/
|
||||
|
||||
#define BUFSZ 4096
|
||||
#define LOOKAHEAD 60
|
||||
#define THRESHOLD 2
|
||||
#define NCHAR (256+LOOKAHEAD-THRESHOLD)
|
||||
#define TABLESZ (NCHAR+NCHAR-1)
|
||||
#define NIL ((unsigned short)-1)
|
||||
|
|
@ -0,0 +1,764 @@
|
|||
/*
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
M. LZHuf Compression
|
||||
|
||||
This is the LZHuf compression algorithm as used in DPBOX and F6FBB.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
*/
|
||||
/**************************************************************
|
||||
lzhuf.c
|
||||
written by Haruyasu Yoshizaki 11/20/1988
|
||||
some minor changes 4/6/1989
|
||||
comments translated by Haruhiko Okumura 4/7/1989
|
||||
|
||||
minor beautifications and adjustments for compiling under Linux
|
||||
by Markus Gutschke <gutschk@math.uni-muenster.de>
|
||||
1997-01-27
|
||||
|
||||
Modifications to allow use as a filter by Ken Yap <ken_yap@users.sourceforge.net>.
|
||||
1997-07-01
|
||||
|
||||
Small mod to cope with running on big-endian machines
|
||||
by Jim Hague <jim.hague@acm.org)
|
||||
1998-02-06
|
||||
|
||||
Make compression statistics report shorter
|
||||
by Ken Yap <ken_yap@users.sourceforge.net>.
|
||||
2001-04-25
|
||||
**************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef VERBOSE
|
||||
#define Fprintf(x)
|
||||
#define wterr 0
|
||||
#else
|
||||
#define Fprintf(x) fprintf x
|
||||
#if defined(ENCODE) || defined(DECODE)
|
||||
static char wterr[] = "Can't write.";
|
||||
#ifdef ENCODE
|
||||
static unsigned long int codesize = 0;
|
||||
#endif
|
||||
static unsigned long int printcount = 0;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MAIN
|
||||
extern
|
||||
#endif
|
||||
FILE *infile, *outfile;
|
||||
|
||||
#if defined(ENCODE) || defined(DECODE)
|
||||
static unsigned long int textsize = 0;
|
||||
|
||||
static __inline__ void Error(char *message)
|
||||
{
|
||||
Fprintf((stderr, "\n%s\n", message));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* These will be a complete waste of time on a lo-endian */
|
||||
/* system, but it only gets done once so WTF. */
|
||||
static unsigned long i86ul_to_host(unsigned long ul)
|
||||
{
|
||||
unsigned long res = 0;
|
||||
int i;
|
||||
union
|
||||
{
|
||||
unsigned char c[4];
|
||||
unsigned long ul;
|
||||
} u;
|
||||
|
||||
u.ul = ul;
|
||||
for (i = 3; i >= 0; i--)
|
||||
res = (res << 8) + u.c[i];
|
||||
return res;
|
||||
}
|
||||
|
||||
static unsigned long host_to_i86ul(unsigned long ul)
|
||||
{
|
||||
int i;
|
||||
union
|
||||
{
|
||||
unsigned char c[4];
|
||||
unsigned long ul;
|
||||
} u;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
u.c[i] = ul & 0xff;
|
||||
ul >>= 8;
|
||||
}
|
||||
return u.ul;
|
||||
}
|
||||
#endif
|
||||
|
||||
/********** LZSS compression **********/
|
||||
|
||||
#define N 4096 /* buffer size */
|
||||
/* Attention: When using this file for f6fbb-type compressed data exchange,
|
||||
set N to 2048 ! (DL8HBS) */
|
||||
#define F 60 /* lookahead buffer size */
|
||||
#define THRESHOLD 2
|
||||
#define NIL N /* leaf of tree */
|
||||
|
||||
#if defined(ENCODE) || defined(DECODE)
|
||||
static unsigned char
|
||||
text_buf[N + F - 1];
|
||||
#endif
|
||||
|
||||
#ifdef ENCODE
|
||||
static int match_position, match_length,
|
||||
lson[N + 1], rson[N + 257], dad[N + 1];
|
||||
|
||||
static void InitTree(void) /* initialize trees */
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = N + 1; i <= N + 256; i++)
|
||||
rson[i] = NIL; /* root */
|
||||
for (i = 0; i < N; i++)
|
||||
dad[i] = NIL; /* node */
|
||||
}
|
||||
|
||||
static void InsertNode(int r) /* insert to tree */
|
||||
{
|
||||
int i, p, cmp;
|
||||
unsigned char *key;
|
||||
unsigned c;
|
||||
|
||||
cmp = 1;
|
||||
key = &text_buf[r];
|
||||
p = N + 1 + key[0];
|
||||
rson[r] = lson[r] = NIL;
|
||||
match_length = 0;
|
||||
for ( ; ; ) {
|
||||
if (cmp >= 0) {
|
||||
if (rson[p] != NIL)
|
||||
p = rson[p];
|
||||
else {
|
||||
rson[p] = r;
|
||||
dad[r] = p;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (lson[p] != NIL)
|
||||
p = lson[p];
|
||||
else {
|
||||
lson[p] = r;
|
||||
dad[r] = p;
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (i = 1; i < F; i++)
|
||||
if ((cmp = key[i] - text_buf[p + i]) != 0)
|
||||
break;
|
||||
if (i > THRESHOLD) {
|
||||
if (i > match_length) {
|
||||
match_position = ((r - p) & (N - 1)) - 1;
|
||||
if ((match_length = i) >= F)
|
||||
break;
|
||||
}
|
||||
if (i == match_length) {
|
||||
if ((c = ((r - p) & (N - 1)) - 1) < match_position) {
|
||||
match_position = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dad[r] = dad[p];
|
||||
lson[r] = lson[p];
|
||||
rson[r] = rson[p];
|
||||
dad[lson[p]] = r;
|
||||
dad[rson[p]] = r;
|
||||
if (rson[dad[p]] == p)
|
||||
rson[dad[p]] = r;
|
||||
else
|
||||
lson[dad[p]] = r;
|
||||
dad[p] = NIL; /* remove p */
|
||||
}
|
||||
|
||||
static void DeleteNode(int p) /* remove from tree */
|
||||
{
|
||||
int q;
|
||||
|
||||
if (dad[p] == NIL)
|
||||
return; /* not registered */
|
||||
if (rson[p] == NIL)
|
||||
q = lson[p];
|
||||
else
|
||||
if (lson[p] == NIL)
|
||||
q = rson[p];
|
||||
else {
|
||||
q = lson[p];
|
||||
if (rson[q] != NIL) {
|
||||
do {
|
||||
q = rson[q];
|
||||
} while (rson[q] != NIL);
|
||||
rson[dad[q]] = lson[q];
|
||||
dad[lson[q]] = dad[q];
|
||||
lson[q] = lson[p];
|
||||
dad[lson[p]] = q;
|
||||
}
|
||||
rson[q] = rson[p];
|
||||
dad[rson[p]] = q;
|
||||
}
|
||||
dad[q] = dad[p];
|
||||
if (rson[dad[p]] == p)
|
||||
rson[dad[p]] = q;
|
||||
else
|
||||
lson[dad[p]] = q;
|
||||
dad[p] = NIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Huffman coding */
|
||||
|
||||
#define N_CHAR (256 - THRESHOLD + F)
|
||||
/* kinds of characters (character code = 0..N_CHAR-1) */
|
||||
#define T (N_CHAR * 2 - 1) /* size of table */
|
||||
#define R (T - 1) /* position of root */
|
||||
#define MAX_FREQ 0x8000 /* updates tree when the */
|
||||
/* root frequency comes to this value. */
|
||||
typedef unsigned char uchar;
|
||||
|
||||
/* table for encoding and decoding the upper 6 bits of position */
|
||||
|
||||
/* for encoding */
|
||||
|
||||
#ifdef ENCODE
|
||||
static uchar p_len[64] = {
|
||||
0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06,
|
||||
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
|
||||
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
|
||||
};
|
||||
|
||||
static uchar p_code[64] = {
|
||||
0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68,
|
||||
0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C,
|
||||
0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC,
|
||||
0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE,
|
||||
0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE,
|
||||
0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
|
||||
0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef DECODE
|
||||
/* for decoding */
|
||||
static uchar d_code[256] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
||||
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
|
||||
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
||||
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
|
||||
0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
|
||||
0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
|
||||
0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
|
||||
0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
|
||||
0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
|
||||
0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
|
||||
0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
|
||||
0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
|
||||
0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
|
||||
0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
|
||||
0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,
|
||||
0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
|
||||
0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
|
||||
0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||||
0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
};
|
||||
|
||||
static uchar d_len[256] = {
|
||||
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
||||
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
||||
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
||||
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
|
||||
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
|
||||
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
|
||||
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
|
||||
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
|
||||
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
|
||||
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(ENCODE) || defined(DECODE)
|
||||
static unsigned freq[T + 1]; /* frequency table */
|
||||
|
||||
static int prnt[T + N_CHAR]; /* pointers to parent nodes, except for the */
|
||||
/* elements [T..T + N_CHAR - 1] which are used to get */
|
||||
/* the positions of leaves corresponding to the codes. */
|
||||
|
||||
static int son[T]; /* pointers to child nodes (son[], son[] + 1) */
|
||||
#endif
|
||||
|
||||
#ifdef DECODE
|
||||
static unsigned getbuf = 0;
|
||||
static uchar getlen = 0;
|
||||
|
||||
static int GetBit(void) /* get one bit */
|
||||
{
|
||||
int i;
|
||||
|
||||
while (getlen <= 8) {
|
||||
if ((i = getc(infile)) < 0) i = 0;
|
||||
getbuf |= i << (8 - getlen);
|
||||
getlen += 8;
|
||||
}
|
||||
i = getbuf;
|
||||
getbuf <<= 1;
|
||||
getlen--;
|
||||
return ((signed short)i < 0);
|
||||
}
|
||||
|
||||
static int GetByte(void) /* get one byte */
|
||||
{
|
||||
unsigned short i;
|
||||
|
||||
while (getlen <= 8) {
|
||||
if ((signed short)(i = getc(infile)) < 0) i = 0;
|
||||
getbuf |= i << (8 - getlen);
|
||||
getlen += 8;
|
||||
}
|
||||
i = getbuf;
|
||||
getbuf <<= 8;
|
||||
getlen -= 8;
|
||||
return i >> 8;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENCODE
|
||||
static unsigned putbuf = 0;
|
||||
static uchar putlen = 0;
|
||||
|
||||
static void Putcode(int l, unsigned c) /* output c bits of code */
|
||||
{
|
||||
putbuf |= c >> putlen;
|
||||
if ((putlen += l) >= 8) {
|
||||
if (putc(putbuf >> 8, outfile) == EOF) {
|
||||
Error(wterr);
|
||||
}
|
||||
if ((putlen -= 8) >= 8) {
|
||||
if (putc(putbuf, outfile) == EOF) {
|
||||
Error(wterr);
|
||||
}
|
||||
#ifdef VERBOSE
|
||||
codesize += 2;
|
||||
#endif
|
||||
putlen -= 8;
|
||||
putbuf = c << (l - putlen);
|
||||
} else {
|
||||
putbuf <<= 8;
|
||||
#ifdef VERBOSE
|
||||
codesize++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* initialization of tree */
|
||||
|
||||
#if defined(ENCODE) || defined(DECODE)
|
||||
static void StartHuff(void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < N_CHAR; i++) {
|
||||
freq[i] = 1;
|
||||
son[i] = i + T;
|
||||
prnt[i + T] = i;
|
||||
}
|
||||
i = 0; j = N_CHAR;
|
||||
while (j <= R) {
|
||||
freq[j] = freq[i] + freq[i + 1];
|
||||
son[j] = i;
|
||||
prnt[i] = prnt[i + 1] = j;
|
||||
i += 2; j++;
|
||||
}
|
||||
freq[T] = 0xffff;
|
||||
prnt[R] = 0;
|
||||
}
|
||||
|
||||
/* reconstruction of tree */
|
||||
|
||||
static void reconst(void)
|
||||
{
|
||||
int i, j, k;
|
||||
unsigned f, l;
|
||||
|
||||
/* collect leaf nodes in the first half of the table */
|
||||
/* and replace the freq by (freq + 1) / 2. */
|
||||
j = 0;
|
||||
for (i = 0; i < T; i++) {
|
||||
if (son[i] >= T) {
|
||||
freq[j] = (freq[i] + 1) / 2;
|
||||
son[j] = son[i];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
/* begin constructing tree by connecting sons */
|
||||
for (i = 0, j = N_CHAR; j < T; i += 2, j++) {
|
||||
k = i + 1;
|
||||
f = freq[j] = freq[i] + freq[k];
|
||||
for (k = j - 1; f < freq[k]; k--);
|
||||
k++;
|
||||
l = (j - k) * 2;
|
||||
memmove(&freq[k + 1], &freq[k], l);
|
||||
freq[k] = f;
|
||||
memmove(&son[k + 1], &son[k], l);
|
||||
son[k] = i;
|
||||
}
|
||||
/* connect prnt */
|
||||
for (i = 0; i < T; i++) {
|
||||
if ((k = son[i]) >= T) {
|
||||
prnt[k] = i;
|
||||
} else {
|
||||
prnt[k] = prnt[k + 1] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* increment frequency of given code by one, and update tree */
|
||||
|
||||
static void update(int c)
|
||||
{
|
||||
int i, j, k, l;
|
||||
|
||||
if (freq[R] == MAX_FREQ) {
|
||||
reconst();
|
||||
}
|
||||
c = prnt[c + T];
|
||||
do {
|
||||
k = ++freq[c];
|
||||
|
||||
/* if the order is disturbed, exchange nodes */
|
||||
if (k > freq[l = c + 1]) {
|
||||
while (k > freq[++l]);
|
||||
l--;
|
||||
freq[c] = freq[l];
|
||||
freq[l] = k;
|
||||
|
||||
i = son[c];
|
||||
prnt[i] = l;
|
||||
if (i < T) prnt[i + 1] = l;
|
||||
|
||||
j = son[l];
|
||||
son[l] = i;
|
||||
|
||||
prnt[j] = c;
|
||||
if (j < T) prnt[j + 1] = c;
|
||||
son[c] = j;
|
||||
|
||||
c = l;
|
||||
}
|
||||
} while ((c = prnt[c]) != 0); /* repeat up to root */
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENCODE
|
||||
#if 0
|
||||
static unsigned code, len;
|
||||
#endif
|
||||
|
||||
static void EncodeChar(unsigned c)
|
||||
{
|
||||
unsigned i;
|
||||
int j, k;
|
||||
|
||||
i = 0;
|
||||
j = 0;
|
||||
k = prnt[c + T];
|
||||
|
||||
/* travel from leaf to root */
|
||||
do {
|
||||
i >>= 1;
|
||||
|
||||
/* if node's address is odd-numbered, choose bigger brother node */
|
||||
if (k & 1) i += 0x8000;
|
||||
|
||||
j++;
|
||||
} while ((k = prnt[k]) != R);
|
||||
Putcode(j, i);
|
||||
#if 0
|
||||
code = i;
|
||||
len = j;
|
||||
#endif
|
||||
update(c);
|
||||
}
|
||||
|
||||
static void EncodePosition(unsigned c)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
/* output upper 6 bits by table lookup */
|
||||
i = c >> 6;
|
||||
Putcode(p_len[i], (unsigned)p_code[i] << 8);
|
||||
|
||||
/* output lower 6 bits verbatim */
|
||||
Putcode(6, (c & 0x3f) << 10);
|
||||
}
|
||||
|
||||
static void EncodeEnd(void)
|
||||
{
|
||||
if (putlen) {
|
||||
if (putc(putbuf >> 8, outfile) == EOF) {
|
||||
Error(wterr);
|
||||
}
|
||||
#ifdef VERBOSE
|
||||
codesize++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DECODE
|
||||
static int DecodeChar(void)
|
||||
{
|
||||
unsigned c;
|
||||
|
||||
c = son[R];
|
||||
|
||||
/* travel from root to leaf, */
|
||||
/* choosing the smaller child node (son[]) if the read bit is 0, */
|
||||
/* the bigger (son[]+1} if 1 */
|
||||
while (c < T) {
|
||||
c += GetBit();
|
||||
c = son[c];
|
||||
}
|
||||
c -= T;
|
||||
update(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
static int DecodePosition(void)
|
||||
{
|
||||
unsigned i, j, c;
|
||||
|
||||
/* recover upper 6 bits from table */
|
||||
i = GetByte();
|
||||
c = (unsigned)d_code[i] << 6;
|
||||
j = d_len[i];
|
||||
|
||||
/* read lower 6 bits verbatim */
|
||||
j -= 2;
|
||||
while (j--) {
|
||||
i = (i << 1) + GetBit();
|
||||
}
|
||||
return c | (i & 0x3f);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENCODE
|
||||
/* compression */
|
||||
|
||||
void Encode(void) /* compression */
|
||||
{
|
||||
int i, c, len, r, s, last_match_length;
|
||||
unsigned long tw;
|
||||
|
||||
fseek(infile, 0L, 2);
|
||||
textsize = ftell(infile);
|
||||
#ifdef VERBOSE
|
||||
if ((signed long)textsize < 0)
|
||||
Fprintf((stderr, "Errno: %d", errno));
|
||||
#endif
|
||||
tw = host_to_i86ul(textsize);
|
||||
if (fwrite(&tw, sizeof tw, 1, outfile) < 1)
|
||||
Error(wterr); /* output size of text */
|
||||
if (textsize == 0)
|
||||
return;
|
||||
rewind(infile);
|
||||
textsize = 0; /* rewind and re-read */
|
||||
StartHuff();
|
||||
InitTree();
|
||||
s = 0;
|
||||
r = N - F;
|
||||
for (i = s; i < r; i++)
|
||||
text_buf[i] = ' ';
|
||||
for (len = 0; len < F && (c = getc(infile)) != EOF; len++)
|
||||
text_buf[r + len] = c;
|
||||
textsize = len;
|
||||
for (i = 1; i <= F; i++)
|
||||
InsertNode(r - i);
|
||||
InsertNode(r);
|
||||
do {
|
||||
if (match_length > len)
|
||||
match_length = len;
|
||||
if (match_length <= THRESHOLD) {
|
||||
match_length = 1;
|
||||
EncodeChar(text_buf[r]);
|
||||
} else {
|
||||
EncodeChar(255 - THRESHOLD + match_length);
|
||||
EncodePosition(match_position);
|
||||
}
|
||||
last_match_length = match_length;
|
||||
for (i = 0; i < last_match_length &&
|
||||
(c = getc(infile)) != EOF; i++) {
|
||||
DeleteNode(s);
|
||||
text_buf[s] = c;
|
||||
if (s < F - 1)
|
||||
text_buf[s + N] = c;
|
||||
s = (s + 1) & (N - 1);
|
||||
r = (r + 1) & (N - 1);
|
||||
InsertNode(r);
|
||||
}
|
||||
if ((textsize += i) > printcount) {
|
||||
#if defined(VERBOSE) && defined(EXTRAVERBOSE)
|
||||
Fprintf((stderr, "%12ld\r", textsize));
|
||||
#endif
|
||||
printcount += 1024;
|
||||
}
|
||||
while (i++ < last_match_length) {
|
||||
DeleteNode(s);
|
||||
s = (s + 1) & (N - 1);
|
||||
r = (r + 1) & (N - 1);
|
||||
if (--len) InsertNode(r);
|
||||
}
|
||||
} while (len > 0);
|
||||
EncodeEnd();
|
||||
#ifdef LONG_REPORT
|
||||
Fprintf((stderr, "input size %ld bytes\n", codesize));
|
||||
Fprintf((stderr, "output size %ld bytes\n", textsize));
|
||||
Fprintf((stderr, "input/output %.3f\n", (double)codesize / textsize));
|
||||
#else
|
||||
Fprintf((stderr, "input/output = %ld/%ld = %.3f\n", codesize, textsize,
|
||||
(double)codesize / textsize));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DECODE
|
||||
void Decode(void) /* recover */
|
||||
{
|
||||
int i, j, k, r, c;
|
||||
unsigned long int count;
|
||||
unsigned long tw;
|
||||
|
||||
if (fread(&tw, sizeof tw, 1, infile) < 1)
|
||||
Error("Can't read"); /* read size of text */
|
||||
textsize = i86ul_to_host(tw);
|
||||
if (textsize == 0)
|
||||
return;
|
||||
StartHuff();
|
||||
for (i = 0; i < N - F; i++)
|
||||
text_buf[i] = ' ';
|
||||
r = N - F;
|
||||
for (count = 0; count < textsize; ) {
|
||||
c = DecodeChar();
|
||||
if (c < 256) {
|
||||
if (putc(c, outfile) == EOF) {
|
||||
Error(wterr);
|
||||
}
|
||||
text_buf[r++] = c;
|
||||
r &= (N - 1);
|
||||
count++;
|
||||
} else {
|
||||
i = (r - DecodePosition() - 1) & (N - 1);
|
||||
j = c - 255 + THRESHOLD;
|
||||
for (k = 0; k < j; k++) {
|
||||
c = text_buf[(i + k) & (N - 1)];
|
||||
if (putc(c, outfile) == EOF) {
|
||||
Error(wterr);
|
||||
}
|
||||
text_buf[r++] = c;
|
||||
r &= (N - 1);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count > printcount) {
|
||||
#if defined(VERBOSE) && defined(EXTRAVERBOSE)
|
||||
Fprintf((stderr, "%12ld\r", count));
|
||||
#endif
|
||||
printcount += 1024;
|
||||
}
|
||||
}
|
||||
Fprintf((stderr, "%12ld\n", count));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MAIN
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *s;
|
||||
FILE *f;
|
||||
int c;
|
||||
|
||||
if (argc == 2) {
|
||||
outfile = stdout;
|
||||
if ((f = tmpfile()) == NULL) {
|
||||
perror("tmpfile");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
while ((c = getchar()) != EOF)
|
||||
fputc(c, f);
|
||||
rewind(infile = f);
|
||||
}
|
||||
else if (argc != 4) {
|
||||
Fprintf((stderr, "'lzhuf e file1 file2' encodes file1 into file2.\n"
|
||||
"'lzhuf d file2 file1' decodes file2 into file1.\n"));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (argc == 4) {
|
||||
if ((s = argv[1], s[1] || strpbrk(s, "DEde") == NULL)
|
||||
|| (s = argv[2], (infile = fopen(s, "rb")) == NULL)
|
||||
|| (s = argv[3], (outfile = fopen(s, "wb")) == NULL)) {
|
||||
Fprintf((stderr, "??? %s\n", s));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
if (toupper(*argv[1]) == 'E')
|
||||
Encode();
|
||||
else
|
||||
Decode();
|
||||
fclose(infile);
|
||||
fclose(outfile);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,16 @@
|
|||
This is an example of using vendor tags in DHCPD config, supplied by
|
||||
Bernd Wiebelt.
|
||||
|
||||
|
||||
subnet 10.97.0.0 netmask 255.255.0.0 {
|
||||
range 10.97.0.2 10.97.0.254;
|
||||
option option-128 e4:45:74:68:0:0;
|
||||
option option-160 "default=193";
|
||||
option option-184 "HALLO";
|
||||
option option-192 "Linux:::linux.tagged:";
|
||||
option option-193 "DOS Bootdisk:::dosboot.tagged";
|
||||
option option-194 "RH61 Bootdisk:::boot.tagged";
|
||||
option option-195 "Local Disk:::/dev/hda:85b103482a20682da703aa388933a6d8";
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
From: Dax Kelson
|
||||
To: Etherboot users list
|
||||
Subject: [Etherboot-users] Example ISC DHCP v3 dhcpd.conf using conditional operations
|
||||
Date: Wed, 13 Jun 2001 20:22:21 -0600
|
||||
|
||||
Hopefully someone will find this useful. I spent a long time tracking
|
||||
down and figuring out all the pieces. To the powers that be, feel free to
|
||||
stick this in contrib if you like it.
|
||||
|
||||
Goal: Use the vendor-class-identifier and ISC DHCP v3 "match" option to
|
||||
conditionally send proper options only when the DHCP discover/request from
|
||||
etherboot comes in. We use static-MAC-to-IP mappings for classroom
|
||||
computers, and dynamic dhcp ranges for other clients (student laptops,
|
||||
etc).
|
||||
|
||||
I used Etherboot 5.0.1 and the patch (required) in this email:
|
||||
|
||||
http://www.geocrawler.com/lists/3/SourceForge/5299/0/5952625/
|
||||
|
||||
Furture versions of Etherboot will likely already have this patch
|
||||
included.
|
||||
|
||||
Dax Kelson
|
||||
Guru Labs
|
||||
|
||||
######### Begin ISC DHCP v3 dhcpd.conf #############
|
||||
|
||||
ddns-update-style ad-hoc;
|
||||
|
||||
# Global default, can be overridden
|
||||
filename "/exports/kickstart/class1-rh7.1.ks";
|
||||
|
||||
# Define options for Etherboot
|
||||
# There are more, these are just the ones I'm using
|
||||
option ebootmagic code 128 = string;
|
||||
option cmdline code 129 = string;
|
||||
option menudflts code 160 = string;
|
||||
option menuline1 code 192 = string;
|
||||
option menuline2 code 193 = string;
|
||||
option menuline3 code 194 = string;
|
||||
option menuline4 code 195 = string;
|
||||
option menuline5 code 196 = string;
|
||||
option menuline6 code 197 = string;
|
||||
option menuline7 code 198 = string;
|
||||
option menuline8 code 199 = string;
|
||||
option menuline9 code 200 = string;
|
||||
option menuline10 code 201 = string;
|
||||
option menuline11 code 202 = string;
|
||||
option menuline12 code 203 = string;
|
||||
option menuline13 code 204 = string;
|
||||
option menuline14 code 205 = string;
|
||||
option menuline15 code 206 = string;
|
||||
option menuline16 code 207 = string;
|
||||
option motdline1 code 184 = string;
|
||||
|
||||
class "Etherboot" {
|
||||
match if substring (option vendor-class-identifier, 0, 9) = "Etherboot";
|
||||
|
||||
option ebootmagic = E4:45:74:68:00:00;
|
||||
|
||||
# We don't use this here, because different menu items require
|
||||
# different cmdlines. In our ".nbi" files we specify the cmdlines
|
||||
|
||||
# option cmdline = "ks initrd=initrd.img lang= devfs=nomount";
|
||||
|
||||
option motdline1 = "Welcome to Guru Labs classroom";
|
||||
|
||||
option menudflts = "timeout=30:default=192";
|
||||
|
||||
option menuline1 = "Boot from Hard Drive (Default):::/dev/hda:::";
|
||||
option menuline2 = "Boot from Floppy:::/dev/fd0:::";
|
||||
option menuline3 = "Boot from CDROM::::::";
|
||||
option menuline4 = "Kickstart install Red Hat 7.1:::rh71-ks-etherboot.nbi:::";
|
||||
option menuline5 = "Red Hat 7.1 network rescue:::rh71-rescue-etherboot.nbi:::";
|
||||
option menuline6 = "Boot Win98SE startup floppy:::win98se-startupdisk.nbi:::";
|
||||
option menuline7 = "Jumpstart install Solaris 8 (not working yet):::/dev/hda:::";
|
||||
option menuline8 = "Install Windows 98 SE (not working yet):::/dev/hda:::";
|
||||
option menuline9 = "Install Windows 2000 (not working yet):::/dev/hda:::";
|
||||
option menuline10 = "Install FreeBSD 4.3 (not working yet):::/dev/hda:::";
|
||||
option menuline11 = "Install OpenBSD 2.9 (not working yet):::/dev/hda:::";
|
||||
|
||||
# This is a hidden menu item, it should be password protected too
|
||||
option menuline12 = "^[[3D^[[K^[[1A^M:::/dev/hda:::";
|
||||
|
||||
# We are using the menu, with different bootfiles. So we don't use this.
|
||||
# If you weren't using a menu, you could use this override the global
|
||||
# default "filename" setting.
|
||||
|
||||
# filename "rh71-ks-etherboot";
|
||||
|
||||
# Use the following if etherboot compiled with -DREQUIRE_VCI_ETHERBOOT
|
||||
|
||||
option vendor-encapsulated-options 3c:09:45:74:68:65:72:62:6f:6f:74:ff;
|
||||
|
||||
}
|
||||
|
||||
subnet 10.100.0.0 netmask 255.255.255.0 {
|
||||
authoritative;
|
||||
option routers 10.100.0.254;
|
||||
option subnet-mask 255.255.255.0;
|
||||
option domain-name "example.com";
|
||||
option domain-name-servers 10.100.0.254;
|
||||
option time-offset -7; # US/Mountain
|
||||
option ntp-servers 10.100.0.254;
|
||||
range dynamic-bootp 10.100.0.175 10.100.0.250;
|
||||
default-lease-time 21600;
|
||||
max-lease-time 43200;
|
||||
option netbios-name-servers 10.100.0.254;
|
||||
option netbios-node-type 2;
|
||||
use-host-decl-names on;
|
||||
next-server server1.example.com;
|
||||
|
||||
}
|
||||
|
||||
host station1 {
|
||||
hardware ethernet 00:01:03:de:57:e2;
|
||||
fixed-address 10.100.0.1;
|
||||
}
|
||||
host station2 {
|
||||
hardware ethernet 00:01:03:de:57:e7;
|
||||
fixed-address 10.100.0.2;
|
||||
}
|
||||
host station3 {
|
||||
hardware ethernet 00:01:03:de:57:b4;
|
||||
fixed-address 10.100.0.3;
|
||||
}
|
||||
host station4 {
|
||||
hardware ethernet 00:01:03:de:57:38;
|
||||
fixed-address 10.100.0.4;
|
||||
}
|
||||
host station5 {
|
||||
hardware ethernet 00:01:03:de:58:3d;
|
||||
fixed-address 10.100.0.5;
|
||||
}
|
||||
|
||||
#
|
||||
# Etc, etc
|
||||
#
|
||||
|
||||
############## End ISC DHCP v3 dhcpd.conf #############
|
|
@ -0,0 +1,884 @@
|
|||
From daniel@insu.com Thu Apr 27 14:14:55 2000
|
||||
Sender: root@iNsu.COM
|
||||
Message-ID: <39075669.FAEB20F2@insu.com>
|
||||
Date: Wed, 26 Apr 2000 16:49:45 -0400
|
||||
From: Daniel Shane <daniel@insu.com>
|
||||
X-Mailer: Mozilla 4.72 [en] (X11; U; Linux 2.2.14-5.0 i686)
|
||||
X-Accept-Language: en
|
||||
MIME-Version: 1.0
|
||||
Subject: Re: New feature added to etherboot
|
||||
References: <20000425170804.6677127D8A@Goffman.iNsu.COM>
|
||||
Content-Type: multipart/mixed;
|
||||
boundary="------------4734FDA0BF2F2FBDF8EB8DF6"
|
||||
|
||||
This is a multi-part message in MIME format.
|
||||
--------------4734FDA0BF2F2FBDF8EB8DF6
|
||||
Content-Type: text/plain; charset=us-ascii
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
Ok, here is a diff for etherboot 4.6.0 that adds identifiers.
|
||||
|
||||
To test this you need to use a class in the dhcpd.conf file and
|
||||
also send back a string in option 208.
|
||||
|
||||
These identifiers prevent a client from booting from other DHCP
|
||||
servers when you have more than 1 in your network.
|
||||
|
||||
In will also prevent any client, except the valid ones, to use this
|
||||
DHCP server.
|
||||
|
||||
Here is a subset of my dhcpd.conf :
|
||||
|
||||
option iNdiskless-state code 208 = text;
|
||||
|
||||
class "iNdiskless-boot" {
|
||||
match if substring(option iNdiskless-state,0,4) = "BOOT";
|
||||
}
|
||||
class "iNdiskless-setup" {
|
||||
match if substring(option iNdiskless-state,0,5) = "SETUP";
|
||||
}
|
||||
|
||||
subnet 10.4.1.0 netmask 255.255.255.0 {
|
||||
pool {
|
||||
allow members of "iNdiskless-boot";
|
||||
deny unknown clients;
|
||||
range 10.4.1.2 10.4.1.200;
|
||||
next-server 10.4.1.1;
|
||||
|
||||
# Identify ourselves to the etherboot/DHCP client
|
||||
option iNdiskless-state "BOOT";
|
||||
|
||||
host labo01 {
|
||||
hardware ethernet 00:80:c8:ec:04:1b;
|
||||
}
|
||||
host labo02 {
|
||||
hardware ethernet 00:4f:4c:04:45:d6;
|
||||
}
|
||||
host labo03 {
|
||||
hardware ethernet 00:50:ba:c8:db:d6;
|
||||
}
|
||||
}
|
||||
pool {
|
||||
allow members of "iNdiskless-setup";
|
||||
range 10.4.1.201 10.4.1.254;
|
||||
option iNdiskless-state "SETUP";
|
||||
|
||||
# send another kernel to setup the diskless workstation
|
||||
}
|
||||
}
|
||||
|
||||
Daniel Shane.
|
||||
--------------4734FDA0BF2F2FBDF8EB8DF6
|
||||
Content-Type: text/plain; charset=us-ascii;
|
||||
name="main.c.diff"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Content-Disposition: inline;
|
||||
filename="main.c.diff"
|
||||
|
||||
--- etherboot-4.6.0/src/main.c Tue Apr 25 08:30:01 2000
|
||||
+++ etherboot-4.5.6-new/src/main.c Wed Apr 26 16:17:09 2000
|
||||
@@ -42,6 +42,23 @@ char *motd[RFC1533_VENDOR_NUMOFMOTD];
|
||||
#ifdef IMAGE_FREEBSD
|
||||
int freebsd_howto = 0;
|
||||
#endif
|
||||
+
|
||||
+#ifdef SERVER_IDENT
|
||||
+#ifdef DEFAULT_SERVER_IDENT
|
||||
+char server_ident[9] = DEFAULT_SERVER_IDENT;
|
||||
+#else
|
||||
+char server_ident[9] = {};
|
||||
+#endif
|
||||
+#endif
|
||||
+
|
||||
+#ifdef CLIENT_IDENT
|
||||
+#ifdef DEFAULT_CLIENT_IDENT
|
||||
+char client_ident[9] = DEFAULT_CLIENT_IDENT;
|
||||
+#else
|
||||
+char client_ident[9] = {};
|
||||
+#endif
|
||||
+#endif
|
||||
+
|
||||
int vendorext_isvalid;
|
||||
char config_buffer[TFTP_MAX_PACKET+1]; /* +1 for null byte */
|
||||
unsigned long netmask;
|
||||
@@ -63,61 +80,85 @@ char rfc1533_cookie[5] = { RFC1533_CO
|
||||
char rfc1533_cookie[] = { RFC1533_COOKIE};
|
||||
char rfc1533_end[]={RFC1533_END };
|
||||
static const char dhcpdiscover[]={
|
||||
- RFC2132_MSG_TYPE,1,DHCPDISCOVER,
|
||||
- RFC2132_MAX_SIZE,2,2,64,
|
||||
- RFC2132_PARAM_LIST,4,RFC1533_NETMASK,RFC1533_GATEWAY,
|
||||
- RFC1533_HOSTNAME,RFC1533_EXTENSIONPATH
|
||||
- };
|
||||
-static const char dhcprequest []={
|
||||
- RFC2132_MSG_TYPE,1,DHCPREQUEST,
|
||||
- RFC2132_SRV_ID,4,0,0,0,0,
|
||||
- RFC2132_REQ_ADDR,4,0,0,0,0,
|
||||
- RFC2132_MAX_SIZE,2,2,64,
|
||||
- /* request parameters */
|
||||
- RFC2132_PARAM_LIST,
|
||||
-#ifdef IMAGE_FREEBSD
|
||||
- /* 4 standard + 4 vendortags + 8 motd + 16 menu items */
|
||||
- 4 + 4 + 8 + 16,
|
||||
+ RFC2132_MSG_TYPE,1,DHCPDISCOVER,
|
||||
+ RFC2132_MAX_SIZE,2,2,64,
|
||||
+#ifdef CLIENT_IDENT
|
||||
+ RFC1533_VENDOR_CLIENT_IDENT,8,0,0,0,0,0,0,0,0,
|
||||
+#endif
|
||||
+ RFC2132_PARAM_LIST,
|
||||
+#ifdef SERVER_IDENT
|
||||
+ 5,
|
||||
#else
|
||||
- /* 4 standard + 3 vendortags + 8 motd + 16 menu items */
|
||||
- 4 + 3 + 8 + 16,
|
||||
+ 4,
|
||||
#endif
|
||||
- /* Standard parameters */
|
||||
- RFC1533_NETMASK, RFC1533_GATEWAY,
|
||||
- RFC1533_HOSTNAME, RFC1533_EXTENSIONPATH,
|
||||
- /* Etherboot vendortags */
|
||||
- RFC1533_VENDOR_MAGIC,
|
||||
+#ifdef SERVER_IDENT
|
||||
+ RFC1533_VENDOR_SERVER_IDENT,
|
||||
+#endif
|
||||
+ RFC1533_NETMASK,
|
||||
+ RFC1533_GATEWAY,
|
||||
+ RFC1533_HOSTNAME,
|
||||
+ RFC1533_EXTENSIONPATH
|
||||
+};
|
||||
+static const char dhcprequest []={
|
||||
+ RFC2132_MSG_TYPE,1,DHCPREQUEST,
|
||||
+ RFC2132_SRV_ID,4,0,0,0,0,
|
||||
+ RFC2132_REQ_ADDR,4,0,0,0,0,
|
||||
+#ifdef CLIENT_IDENT
|
||||
+ RFC1533_VENDOR_CLIENT_IDENT,8,0,0,0,0,0,0,0,0,
|
||||
+#endif
|
||||
+ RFC2132_MAX_SIZE,2,2,64,
|
||||
+ /* request parameters */
|
||||
+ RFC2132_PARAM_LIST,
|
||||
+ /* 4 standard + 3 vendortags + 8 motd + 16 menu items */
|
||||
+ 4 +
|
||||
+ 3 +
|
||||
+#ifdef IMAGE_FREEBSD
|
||||
+ 1 + /* One more vendortags for VENDOR_HOWTO */
|
||||
+#endif
|
||||
+#ifdef SERVER_IDENT
|
||||
+ 1 + /* One more vendortags for VENDOR_SERVER_IDENT */
|
||||
+#endif
|
||||
+ 8 +
|
||||
+ 16,
|
||||
+ /* Standard parameters */
|
||||
+ RFC1533_NETMASK, RFC1533_GATEWAY,
|
||||
+ RFC1533_HOSTNAME, RFC1533_EXTENSIONPATH,
|
||||
+ /* Etherboot vendortags */
|
||||
+ RFC1533_VENDOR_MAGIC,
|
||||
#ifdef IMAGE_FREEBSD
|
||||
- RFC1533_VENDOR_HOWTO,
|
||||
+ RFC1533_VENDOR_HOWTO,
|
||||
#endif
|
||||
- RFC1533_VENDOR_MNUOPTS, RFC1533_VENDOR_SELECTION,
|
||||
- /* 8 MOTD entries */
|
||||
- RFC1533_VENDOR_MOTD,
|
||||
- RFC1533_VENDOR_MOTD+1,
|
||||
- RFC1533_VENDOR_MOTD+2,
|
||||
- RFC1533_VENDOR_MOTD+3,
|
||||
- RFC1533_VENDOR_MOTD+4,
|
||||
- RFC1533_VENDOR_MOTD+5,
|
||||
- RFC1533_VENDOR_MOTD+6,
|
||||
- RFC1533_VENDOR_MOTD+7,
|
||||
- /* 16 image entries */
|
||||
- RFC1533_VENDOR_IMG,
|
||||
- RFC1533_VENDOR_IMG+1,
|
||||
- RFC1533_VENDOR_IMG+2,
|
||||
- RFC1533_VENDOR_IMG+3,
|
||||
- RFC1533_VENDOR_IMG+4,
|
||||
- RFC1533_VENDOR_IMG+5,
|
||||
- RFC1533_VENDOR_IMG+6,
|
||||
- RFC1533_VENDOR_IMG+7,
|
||||
- RFC1533_VENDOR_IMG+8,
|
||||
- RFC1533_VENDOR_IMG+9,
|
||||
- RFC1533_VENDOR_IMG+10,
|
||||
- RFC1533_VENDOR_IMG+11,
|
||||
- RFC1533_VENDOR_IMG+12,
|
||||
- RFC1533_VENDOR_IMG+13,
|
||||
- RFC1533_VENDOR_IMG+14,
|
||||
- RFC1533_VENDOR_IMG+15,
|
||||
- };
|
||||
+#ifdef SERVER_IDENT
|
||||
+ RFC1533_VENDOR_SERVER_IDENT,
|
||||
+#endif
|
||||
+ RFC1533_VENDOR_MNUOPTS, RFC1533_VENDOR_SELECTION,
|
||||
+ /* 8 MOTD entries */
|
||||
+ RFC1533_VENDOR_MOTD,
|
||||
+ RFC1533_VENDOR_MOTD+1,
|
||||
+ RFC1533_VENDOR_MOTD+2,
|
||||
+ RFC1533_VENDOR_MOTD+3,
|
||||
+ RFC1533_VENDOR_MOTD+4,
|
||||
+ RFC1533_VENDOR_MOTD+5,
|
||||
+ RFC1533_VENDOR_MOTD+6,
|
||||
+ RFC1533_VENDOR_MOTD+7,
|
||||
+ /* 16 image entries */
|
||||
+ RFC1533_VENDOR_IMG,
|
||||
+ RFC1533_VENDOR_IMG+1,
|
||||
+ RFC1533_VENDOR_IMG+2,
|
||||
+ RFC1533_VENDOR_IMG+3,
|
||||
+ RFC1533_VENDOR_IMG+4,
|
||||
+ RFC1533_VENDOR_IMG+5,
|
||||
+ RFC1533_VENDOR_IMG+6,
|
||||
+ RFC1533_VENDOR_IMG+7,
|
||||
+ RFC1533_VENDOR_IMG+8,
|
||||
+ RFC1533_VENDOR_IMG+9,
|
||||
+ RFC1533_VENDOR_IMG+10,
|
||||
+ RFC1533_VENDOR_IMG+11,
|
||||
+ RFC1533_VENDOR_IMG+12,
|
||||
+ RFC1533_VENDOR_IMG+13,
|
||||
+ RFC1533_VENDOR_IMG+14,
|
||||
+ RFC1533_VENDOR_IMG+15,
|
||||
+};
|
||||
|
||||
#endif /* NO_DHCP_SUPPORT */
|
||||
static const char broadcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
@@ -176,6 +217,55 @@ done:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
+
|
||||
+#ifdef SHIFTED_IDENT_INPUT
|
||||
+ if (getshift() & 3)
|
||||
+ {
|
||||
+#endif
|
||||
+
|
||||
+#ifdef CLIENT_IDENT
|
||||
+# ifdef ASK_CLIENT_IDENT
|
||||
+ {
|
||||
+ char tmp_ident[9] = {};
|
||||
+# ifdef DEFAULT_CLIENT_IDENT
|
||||
+ printf("Enter the client identifier (8 char max.) default [%s] : ",client_ident);
|
||||
+# else
|
||||
+ printf("Enter the client identifier (8 char max.) : ");
|
||||
+# endif
|
||||
+ getstr(tmp_ident,8);
|
||||
+ if (strlen(tmp_ident) != 0)
|
||||
+ memcpy(client_ident,tmp_ident,8);
|
||||
+ else
|
||||
+ printf("%s",client_ident);
|
||||
+ putchar('\n');
|
||||
+ }
|
||||
+# endif
|
||||
+#endif
|
||||
+
|
||||
+#ifdef SERVER_IDENT
|
||||
+# ifdef ASK_SERVER_IDENT
|
||||
+ {
|
||||
+ char tmp_ident[9] = {};
|
||||
+# ifdef DEFAULT_SERVER_IDENT
|
||||
+ printf("Enter the server identifier (8 char max.) default [%s] : ",server_ident);
|
||||
+# else
|
||||
+ printf("Enter the server identifier (8 char max.) : ");
|
||||
+# endif
|
||||
+ getstr(tmp_ident,8);
|
||||
+ if (strlen(tmp_ident) != 0)
|
||||
+ memcpy(server_ident,tmp_ident,8);
|
||||
+ else
|
||||
+ printf("%s",server_ident);
|
||||
+ putchar('\n');
|
||||
+ }
|
||||
+# endif
|
||||
+#endif
|
||||
+
|
||||
+#ifdef SHIFTED_IDENT_INPUT
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
+ print_config();
|
||||
#if (TRY_FLOPPY_FIRST > 0) && defined(FLOPPY)
|
||||
disk_init();
|
||||
printf("Trying floppy");
|
||||
@@ -188,7 +278,7 @@ done:
|
||||
}
|
||||
printf("no floppy\n");
|
||||
#endif /* TRY_FLOPPY_FIRST && FLOPPY */
|
||||
- print_config();
|
||||
+ print_config();
|
||||
gateA20_set();
|
||||
#ifdef EMERGENCYDISKBOOT
|
||||
if (!eth_probe()) {
|
||||
@@ -663,6 +753,8 @@ BOOTP - Get my IP address and load infor
|
||||
int bootp()
|
||||
{
|
||||
int retry;
|
||||
+ int offset = 0;
|
||||
+
|
||||
#ifndef NO_DHCP_SUPPORT
|
||||
int retry1;
|
||||
#endif /* NO_DHCP_SUPPORT */
|
||||
@@ -680,11 +772,18 @@ int bootp()
|
||||
bp.bp_xid = xid = starttime = currticks();
|
||||
memcpy(bp.bp_hwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE);
|
||||
#ifdef NO_DHCP_SUPPORT
|
||||
- memcpy(bp.bp_vend, rfc1533_cookie, 5); /* request RFC-style options */
|
||||
+ memcpy(bp.bp_vend+offset, rfc1533_cookie, 5); /* request RFC-style options */
|
||||
+ offset += sizeof rfc1533_cookie;
|
||||
#else
|
||||
- memcpy(bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie); /* request RFC-style options */
|
||||
- memcpy(bp.bp_vend+sizeof rfc1533_cookie, dhcpdiscover, sizeof dhcpdiscover);
|
||||
- memcpy(bp.bp_vend+sizeof rfc1533_cookie +sizeof dhcpdiscover, rfc1533_end, sizeof rfc1533_end);
|
||||
+ memcpy(bp.bp_vend+offset, rfc1533_cookie, sizeof rfc1533_cookie); /* request RFC-style options */
|
||||
+ offset += sizeof rfc1533_cookie;
|
||||
+ memcpy(bp.bp_vend+offset, dhcpdiscover, sizeof dhcpdiscover);
|
||||
+ offset += sizeof dhcpdiscover;
|
||||
+#ifdef CLIENT_IDENT
|
||||
+ memcpy(bp.bp_vend+13, client_ident, strlen(client_ident));
|
||||
+#endif
|
||||
+ memcpy(bp.bp_vend+offset, rfc1533_end, sizeof rfc1533_end);
|
||||
+ offset += sizeof rfc1533_end;
|
||||
#endif /* NO_DHCP_SUPPORT */
|
||||
|
||||
for (retry = 0; retry < MAX_BOOTP_RETRIES; ) {
|
||||
@@ -715,19 +814,22 @@ int bootp()
|
||||
#else
|
||||
if (await_reply(AWAIT_BOOTP, 0, NULL, TIMEOUT)){
|
||||
if (dhcp_reply==DHCPOFFER){
|
||||
- dhcp_reply=0;
|
||||
- memcpy(bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);
|
||||
- memcpy(bp.bp_vend+sizeof rfc1533_cookie, dhcprequest, sizeof dhcprequest);
|
||||
- memcpy(bp.bp_vend+sizeof rfc1533_cookie +sizeof dhcprequest, rfc1533_end, sizeof rfc1533_end);
|
||||
- memcpy(bp.bp_vend+9, &dhcp_server, sizeof(in_addr));
|
||||
- memcpy(bp.bp_vend+15, &dhcp_addr, sizeof(in_addr));
|
||||
- for (retry1 = 0; retry1 < MAX_BOOTP_RETRIES;) {
|
||||
- udp_transmit(IP_BROADCAST, 0, BOOTP_SERVER,
|
||||
- sizeof(struct bootp_t), &bp);
|
||||
dhcp_reply=0;
|
||||
- if (await_reply(AWAIT_BOOTP, 0, NULL, TIMEOUT))
|
||||
- if (dhcp_reply==DHCPACK)
|
||||
- return(1);
|
||||
+ memcpy(bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);
|
||||
+ memcpy(bp.bp_vend+sizeof rfc1533_cookie, dhcprequest, sizeof dhcprequest);
|
||||
+ memcpy(bp.bp_vend+sizeof rfc1533_cookie +sizeof dhcprequest, rfc1533_end, sizeof rfc1533_end);
|
||||
+ memcpy(bp.bp_vend+9, &dhcp_server, sizeof(in_addr));
|
||||
+ memcpy(bp.bp_vend+15, &dhcp_addr, sizeof(in_addr));
|
||||
+#ifdef CLIENT_IDENT
|
||||
+ memcpy(bp.bp_vend+21, client_ident, strlen(client_ident));
|
||||
+#endif
|
||||
+ for (retry1 = 0; retry1 < MAX_BOOTP_RETRIES;) {
|
||||
+ udp_transmit(IP_BROADCAST, 0, BOOTP_SERVER,
|
||||
+ sizeof(struct bootp_t), &bp);
|
||||
+ dhcp_reply=0;
|
||||
+ if (await_reply(AWAIT_BOOTP, 0, NULL, TIMEOUT))
|
||||
+ if (dhcp_reply==DHCPACK)
|
||||
+ return(1);
|
||||
rfc951_sleep(++retry1);
|
||||
}
|
||||
} else
|
||||
@@ -750,6 +852,7 @@ AWAIT_REPLY - Wait until we get a respon
|
||||
**************************************************************************/
|
||||
int await_reply(int type, int ival, void *ptr, int timeout)
|
||||
{
|
||||
+ int result;
|
||||
unsigned long time;
|
||||
struct iphdr *ip;
|
||||
struct udphdr *udp;
|
||||
@@ -757,6 +860,7 @@ int await_reply(int type, int ival, void
|
||||
struct bootp_t *bootpreply;
|
||||
struct rpc_t *rpc;
|
||||
unsigned short ptype;
|
||||
+ unsigned int min_packetlen;
|
||||
|
||||
unsigned int protohdrlen = ETHER_HDR_SIZE + sizeof(struct iphdr) +
|
||||
sizeof(struct udphdr);
|
||||
@@ -766,35 +870,35 @@ int await_reply(int type, int ival, void
|
||||
* needs a negligible amount of time. */
|
||||
for (;;) {
|
||||
if (eth_poll()) { /* We have something! */
|
||||
- /* Check for ARP - No IP hdr */
|
||||
+ /* Check for ARP - No IP hdr */
|
||||
if (nic.packetlen >= ETHER_HDR_SIZE) {
|
||||
ptype = ((unsigned short) nic.packet[12]) << 8
|
||||
| ((unsigned short) nic.packet[13]);
|
||||
} else continue; /* what else could we do with it? */
|
||||
if ((nic.packetlen >= ETHER_HDR_SIZE +
|
||||
- sizeof(struct arprequest)) &&
|
||||
- (ptype == ARP) ) {
|
||||
+ sizeof(struct arprequest)) &&
|
||||
+ (ptype == ARP) ) {
|
||||
unsigned long tmp;
|
||||
-
|
||||
+
|
||||
arpreply = (struct arprequest *)
|
||||
&nic.packet[ETHER_HDR_SIZE];
|
||||
if ((arpreply->opcode == ntohs(ARP_REPLY)) &&
|
||||
- !memcmp(arpreply->sipaddr, ptr, sizeof(in_addr)) &&
|
||||
- (type == AWAIT_ARP)) {
|
||||
+ !memcmp(arpreply->sipaddr, ptr, sizeof(in_addr)) &&
|
||||
+ (type == AWAIT_ARP)) {
|
||||
memcpy(arptable[ival].node, arpreply->shwaddr, ETHER_ADDR_SIZE);
|
||||
return(1);
|
||||
}
|
||||
memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr));
|
||||
if ((arpreply->opcode == ntohs(ARP_REQUEST)) &&
|
||||
- (tmp == arptable[ARP_CLIENT].ipaddr.s_addr)) {
|
||||
+ (tmp == arptable[ARP_CLIENT].ipaddr.s_addr)) {
|
||||
arpreply->opcode = htons(ARP_REPLY);
|
||||
memcpy(arpreply->tipaddr, arpreply->sipaddr, sizeof(in_addr));
|
||||
memcpy(arpreply->thwaddr, arpreply->shwaddr, ETHER_ADDR_SIZE);
|
||||
memcpy(arpreply->sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr));
|
||||
memcpy(arpreply->shwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE);
|
||||
eth_transmit(arpreply->thwaddr, ARP,
|
||||
- sizeof(struct arprequest),
|
||||
- arpreply);
|
||||
+ sizeof(struct arprequest),
|
||||
+ arpreply);
|
||||
#ifdef MDEBUG
|
||||
memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr));
|
||||
printf("Sent ARP reply to: %I\n",tmp);
|
||||
@@ -802,20 +906,20 @@ int await_reply(int type, int ival, void
|
||||
}
|
||||
continue;
|
||||
}
|
||||
-
|
||||
+
|
||||
if (type == AWAIT_QDRAIN) {
|
||||
continue;
|
||||
}
|
||||
-
|
||||
- /* Check for RARP - No IP hdr */
|
||||
+
|
||||
+ /* Check for RARP - No IP hdr */
|
||||
if ((type == AWAIT_RARP) &&
|
||||
- (nic.packetlen >= ETHER_HDR_SIZE +
|
||||
- sizeof(struct arprequest)) &&
|
||||
- (ptype == RARP)) {
|
||||
+ (nic.packetlen >= ETHER_HDR_SIZE +
|
||||
+ sizeof(struct arprequest)) &&
|
||||
+ (ptype == RARP)) {
|
||||
arpreply = (struct arprequest *)
|
||||
&nic.packet[ETHER_HDR_SIZE];
|
||||
if ((arpreply->opcode == ntohs(RARP_REPLY)) &&
|
||||
- !memcmp(arpreply->thwaddr, ptr, ETHER_ADDR_SIZE)) {
|
||||
+ !memcmp(arpreply->thwaddr, ptr, ETHER_ADDR_SIZE)) {
|
||||
memcpy(arptable[ARP_SERVER].node, arpreply->shwaddr, ETHER_ADDR_SIZE);
|
||||
memcpy(& arptable[ARP_SERVER].ipaddr, arpreply->sipaddr, sizeof(in_addr));
|
||||
memcpy(& arptable[ARP_CLIENT].ipaddr, arpreply->tipaddr, sizeof(in_addr));
|
||||
@@ -823,64 +927,72 @@ int await_reply(int type, int ival, void
|
||||
}
|
||||
continue;
|
||||
}
|
||||
-
|
||||
- /* Anything else has IP header */
|
||||
+
|
||||
+ /* Anything else has IP header */
|
||||
if ((nic.packetlen < protohdrlen) ||
|
||||
- (ptype != IP) ) continue;
|
||||
+ (ptype != IP) ) continue;
|
||||
ip = (struct iphdr *)&nic.packet[ETHER_HDR_SIZE];
|
||||
if ((ip->verhdrlen != 0x45) ||
|
||||
- ipchksum((unsigned short *)ip, sizeof(struct iphdr)) ||
|
||||
- (ip->protocol != IP_UDP)) continue;
|
||||
+ ipchksum((unsigned short *)ip, sizeof(struct iphdr)) ||
|
||||
+ (ip->protocol != IP_UDP)) continue;
|
||||
udp = (struct udphdr *)&nic.packet[ETHER_HDR_SIZE +
|
||||
- sizeof(struct iphdr)];
|
||||
-
|
||||
- /* BOOTP ? */
|
||||
+ sizeof(struct iphdr)];
|
||||
+
|
||||
+ /* BOOTP ? */
|
||||
bootpreply = (struct bootp_t *)&nic.packet[ETHER_HDR_SIZE];
|
||||
- if ((type == AWAIT_BOOTP) &&
|
||||
- (nic.packetlen >= (ETHER_HDR_SIZE +
|
||||
-#ifdef NO_DHCP_SUPPORT
|
||||
- sizeof(struct bootp_t))) &&
|
||||
+#ifdef NO_DHCP_SUPPORT
|
||||
+ min_packetlen = ETHER_HDR_SIZE + sizeof(struct bootp_t);
|
||||
#else
|
||||
- sizeof(struct bootp_t))-DHCP_OPT_LEN) &&
|
||||
-#endif /* NO_DHCP_SUPPORT */
|
||||
- (ntohs(udp->dest) == BOOTP_CLIENT) &&
|
||||
- (bootpreply->bp_op == BOOTP_REPLY) &&
|
||||
- (bootpreply->bp_xid == xid)) {
|
||||
- arptable[ARP_CLIENT].ipaddr.s_addr =
|
||||
- bootpreply->bp_yiaddr.s_addr;
|
||||
+ min_packetlen = ETHER_HDR_SIZE + sizeof(struct bootp_t) - DHCP_OPT_LEN;
|
||||
+#endif
|
||||
+ if (
|
||||
+ (type == AWAIT_BOOTP) &&
|
||||
+ (nic.packetlen >= min_packetlen) &&
|
||||
+ (ntohs(udp->dest) == BOOTP_CLIENT) &&
|
||||
+ (bootpreply->bp_op == BOOTP_REPLY) &&
|
||||
+ (bootpreply->bp_xid == xid)
|
||||
+ ) {
|
||||
+ arptable[ARP_CLIENT].ipaddr.s_addr = bootpreply->bp_yiaddr.s_addr;
|
||||
#ifndef NO_DHCP_SUPPORT
|
||||
dhcp_addr.s_addr = bootpreply->bp_yiaddr.s_addr;
|
||||
#endif /* NO_DHCP_SUPPORT */
|
||||
netmask = default_netmask();
|
||||
- arptable[ARP_SERVER].ipaddr.s_addr =
|
||||
- bootpreply->bp_siaddr.s_addr;
|
||||
+ arptable[ARP_SERVER].ipaddr.s_addr = bootpreply->bp_siaddr.s_addr;
|
||||
memset(arptable[ARP_SERVER].node, 0, ETHER_ADDR_SIZE); /* Kill arp */
|
||||
- arptable[ARP_GATEWAY].ipaddr.s_addr =
|
||||
- bootpreply->bp_giaddr.s_addr;
|
||||
+ arptable[ARP_GATEWAY].ipaddr.s_addr = bootpreply->bp_giaddr.s_addr;
|
||||
memset(arptable[ARP_GATEWAY].node, 0, ETHER_ADDR_SIZE); /* Kill arp */
|
||||
if (bootpreply->bp_file[0]) {
|
||||
memcpy(kernel_buf, bootpreply->bp_file, 128);
|
||||
kernel = kernel_buf;
|
||||
}
|
||||
memcpy((char *)BOOTP_DATA_ADDR, (char *)bootpreply, sizeof(struct bootpd_t));
|
||||
- decode_rfc1533(BOOTP_DATA_ADDR->bootp_reply.bp_vend,
|
||||
-#ifdef NO_DHCP_SUPPORT
|
||||
- 0, BOOTP_VENDOR_LEN +
|
||||
- MAX_BOOTP_EXTLEN, 1);
|
||||
-#else
|
||||
- 0, DHCP_OPT_LEN, 1);
|
||||
-#endif /* NO_DHCP_SUPPORT */
|
||||
- return(1);
|
||||
+#ifdef NO_DHCP_SUPPORT
|
||||
+ if (decode_rfc1533(BOOTP_DATA_ADDR->bootp_reply.bp_vend,
|
||||
+ 0, BOOTP_VENDOR_LEN +
|
||||
+ MAX_BOOTP_EXTLEN, 1)) {
|
||||
+ return(1);
|
||||
+ }
|
||||
+ else {
|
||||
+ continue;
|
||||
+ }
|
||||
+#else
|
||||
+ if (decode_rfc1533(BOOTP_DATA_ADDR->bootp_reply.bp_vend,
|
||||
+ 0, DHCP_OPT_LEN, 1)) {
|
||||
+ return(1);
|
||||
+ }
|
||||
+ else {
|
||||
+ continue;
|
||||
+ }
|
||||
}
|
||||
-
|
||||
+#endif /* NO_DHCP_SUPPORT */
|
||||
#ifdef DOWNLOAD_PROTO_TFTP
|
||||
- /* TFTP ? */
|
||||
+ /* TFTP ? */
|
||||
if ((type == AWAIT_TFTP) &&
|
||||
- (ntohs(udp->dest) == ival)) return(1);
|
||||
+ (ntohs(udp->dest) == ival)) return(1);
|
||||
#endif /* DOWNLOAD_PROTO_TFTP */
|
||||
-
|
||||
+
|
||||
#ifdef DOWNLOAD_PROTO_NFS
|
||||
- /* RPC ? */
|
||||
+ /* RPC ? */
|
||||
rpc = (struct rpc_t *)&nic.packet[ETHER_HDR_SIZE];
|
||||
if ((type == AWAIT_RPC) &&
|
||||
(ntohs(udp->dest) == ival) &&
|
||||
@@ -889,19 +1001,19 @@ int await_reply(int type, int ival, void
|
||||
return (1);
|
||||
}
|
||||
#endif /* DOWNLOAD_PROTO_NFS */
|
||||
-
|
||||
+
|
||||
} else {
|
||||
- /* Check for abort key only if the Rx queue is empty -
|
||||
- * as long as we have something to process, don't
|
||||
- * assume that something failed. It is unlikely that
|
||||
- * we have no processing time left between packets. */
|
||||
+ /* Check for abort key only if the Rx queue is empty -
|
||||
+ * as long as we have something to process, don't
|
||||
+ * assume that something failed. It is unlikely that
|
||||
+ * we have no processing time left between packets. */
|
||||
if (iskey() && (getchar() == ESC))
|
||||
#ifdef EMERGENCYDISKBOOT
|
||||
exit(0);
|
||||
#else
|
||||
- longjmp(jmp_bootmenu,1);
|
||||
+ longjmp(jmp_bootmenu,1);
|
||||
#endif
|
||||
- /* Do the timeout after at least a full queue walk. */
|
||||
+ /* Do the timeout after at least a full queue walk. */
|
||||
if ((timeout == 0) || (currticks() > time)) {
|
||||
break;
|
||||
}
|
||||
@@ -914,13 +1026,15 @@ int await_reply(int type, int ival, void
|
||||
DECODE_RFC1533 - Decodes RFC1533 header
|
||||
**************************************************************************/
|
||||
int decode_rfc1533(p, block, len, eof)
|
||||
- register unsigned char *p;
|
||||
- int block, len, eof;
|
||||
+ register unsigned char *p;
|
||||
+ int block, len, eof;
|
||||
{
|
||||
static unsigned char *extdata = NULL, *extend = NULL;
|
||||
unsigned char *extpath = NULL;
|
||||
unsigned char *endp;
|
||||
-
|
||||
+#ifdef SERVER_IDENT
|
||||
+ char rcvd_server_ident[9] = {};
|
||||
+#endif
|
||||
if (block == 0) {
|
||||
#ifdef IMAGE_MENU
|
||||
memset(imagelist, 0, sizeof(imagelist));
|
||||
@@ -1002,11 +1116,16 @@ int decode_rfc1533(p, block, len, eof)
|
||||
}
|
||||
#endif
|
||||
#ifdef MOTD
|
||||
- else if (c >= RFC1533_VENDOR_MOTD &&
|
||||
+ else if (c >= RFC1533_VENDOR_MOTD &&
|
||||
c < RFC1533_VENDOR_MOTD +
|
||||
RFC1533_VENDOR_NUMOFMOTD)
|
||||
motd[c - RFC1533_VENDOR_MOTD] = p;
|
||||
#endif
|
||||
+#ifdef SERVER_IDENT
|
||||
+ else if (c == RFC1533_VENDOR_SERVER_IDENT) {
|
||||
+ memcpy(rcvd_server_ident,p+2,TAG_LEN(p));
|
||||
+ }
|
||||
+#endif
|
||||
else {
|
||||
#if 0
|
||||
unsigned char *q;
|
||||
@@ -1018,6 +1137,30 @@ int decode_rfc1533(p, block, len, eof)
|
||||
}
|
||||
p += TAG_LEN(p) + 2;
|
||||
}
|
||||
+#if defined(SERVER_IDENT) && defined(DBG_IDENT)
|
||||
+ if (strcasecmp(rcvd_server_ident,server_ident)) {
|
||||
+ char ip[16];
|
||||
+
|
||||
+ inet_ntoa(dhcp_server,ip);
|
||||
+ printf("[%s]: Option %d (%s), invalid response. Wanted (%s).\n",
|
||||
+ ip,
|
||||
+ RFC1533_VENDOR_SERVER_IDENT,
|
||||
+ rcvd_server_ident,
|
||||
+ server_ident);
|
||||
+ strcpy(rcvd_server_ident,"");
|
||||
+ return(0);
|
||||
+ }
|
||||
+ else {
|
||||
+ char ip[16];
|
||||
+
|
||||
+ inet_ntoa(dhcp_server,ip);
|
||||
+ printf("[%s]: Option %d (%s), valid response.\n",
|
||||
+ ip,
|
||||
+ RFC1533_VENDOR_SERVER_IDENT,
|
||||
+ rcvd_server_ident);
|
||||
+ strcpy(rcvd_server_ident,"");
|
||||
+ }
|
||||
+#endif
|
||||
extdata = extend = endp;
|
||||
if (block == 0 && extpath != NULL) {
|
||||
char fname[64];
|
||||
@@ -1103,3 +1246,4 @@ void cleanup(void)
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
||||
+
|
||||
|
||||
--------------4734FDA0BF2F2FBDF8EB8DF6
|
||||
Content-Type: text/plain; charset=us-ascii;
|
||||
name="misc.c.diff"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Content-Disposition: inline;
|
||||
filename="misc.c.diff"
|
||||
|
||||
--- etherboot-4.6.0/src/misc.c Tue Apr 25 08:30:25 2000
|
||||
+++ etherboot-4.5.6-new/src/misc.c Wed Apr 26 16:26:38 2000
|
||||
@@ -140,9 +140,11 @@ void printf(const char *fmt, ...)
|
||||
|
||||
#ifdef IMAGE_MENU
|
||||
/**************************************************************************
|
||||
-INET_ATON - Convert an ascii x.x.x.x to binary form
|
||||
+INET_NTOA - Convert an ascii x.x.x.x to binary form
|
||||
**************************************************************************/
|
||||
-int inet_aton(char *p, in_addr *i)
|
||||
+int inet_aton(p, i)
|
||||
+ char *p;
|
||||
+ in_addr *i;
|
||||
{
|
||||
unsigned long ip = 0;
|
||||
int val;
|
||||
@@ -165,7 +167,19 @@ int inet_aton(char *p, in_addr *i)
|
||||
|
||||
#endif /* IMAGE_MENU */
|
||||
|
||||
-int getdec(char **ptr)
|
||||
+#if defined(CLIENT_IDENT) || defined (SERVER_IDENT)
|
||||
+/**************************************************************************
|
||||
+INET_NTOA - Convert a binary form to an ascii x.x.x.x form
|
||||
+**************************************************************************/
|
||||
+char *inet_ntoa(in_addr i, char *p)
|
||||
+{
|
||||
+ sprintf(p,"%d.%d.%d.%d",i.s_addr>>24,i.s_addr<<8>>24,i.s_addr<<16>>24,i.s_addr<<24>>24);
|
||||
+ return p;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+int getdec(ptr)
|
||||
+ char **ptr;
|
||||
{
|
||||
char *p = *ptr;
|
||||
int ret=0;
|
||||
@@ -308,6 +322,45 @@ iskey(void)
|
||||
return 0;
|
||||
}
|
||||
#endif /* ETHERBOOT32 */
|
||||
+
|
||||
+/**************************************************************************
|
||||
+GETSTR - Read a string of size bytes from the keyboard
|
||||
+(without echoing the final return)
|
||||
+**************************************************************************/
|
||||
+void getstr(char *s, int size)
|
||||
+{
|
||||
+ int i=0;
|
||||
+ char c;
|
||||
+
|
||||
+ while(1) {
|
||||
+ c = getc();
|
||||
+
|
||||
+
|
||||
+ if (c == 13)
|
||||
+ {
|
||||
+ s[i]='\0';
|
||||
+ break;
|
||||
+ }
|
||||
+ else if (
|
||||
+ ((c >= 'a') && (c <='z')) ||
|
||||
+ ((c >= 'A') && (c <='Z')) ||
|
||||
+ ((c >= '0') && (c <='9'))
|
||||
+ ) {
|
||||
+ if (i==8) {
|
||||
+ putchar(8);
|
||||
+ putchar(s[i-1]=c);
|
||||
+ }
|
||||
+ else
|
||||
+ putchar(s[i++]=c);
|
||||
+ }
|
||||
+ else if ( c == 8 ) {
|
||||
+ if (i != 0) {
|
||||
+ --i;
|
||||
+ s[i]='\0';
|
||||
+ putchar(8);
|
||||
+ putchar(32);
|
||||
+ putchar(8);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
|
||||
--------------4734FDA0BF2F2FBDF8EB8DF6
|
||||
Content-Type: text/plain; charset=us-ascii;
|
||||
name="Config.diff"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Content-Disposition: inline;
|
||||
filename="Config.diff"
|
||||
|
||||
--- etherboot-4.6.0/src/Config Tue Apr 25 08:30:57 2000
|
||||
+++ etherboot-4.5.6-new/src/Config Wed Apr 26 15:55:57 2000
|
||||
@@ -59,6 +59,27 @@
|
||||
# may no longer be appropriate. You might need to set
|
||||
# MAX_ARP_RETRIES, MAX_BOOTP_RETRIES, MAX_TFTP_RETRIES
|
||||
# and MAX_RPC_RETRIES to a larger value.
|
||||
+# -DDEFAULT_CLIENT_IDENT
|
||||
+# The default client identifier that is sent to the
|
||||
+# DHCP server to identify itself.
|
||||
+# -DDEFAULT_SERVER_IDENT
|
||||
+# The expected response that the client will wait
|
||||
+# for when a DHCP server responds to the the initial
|
||||
+# client discovery.
|
||||
+# -DASK_CLIENT_IDENT
|
||||
+# -DASK_SERVER_IDENT
|
||||
+# If these are set, the boot process will include
|
||||
+# a question period where you can manualy specify
|
||||
+# the client and/or server identifiers.
|
||||
+# -DSHIFTED_IDENT_INPUT
|
||||
+# If this is set then the boot process will only
|
||||
+# ask for the identifiers if one of the shift keys
|
||||
+# is pressed. Else it will send the default identifiers
|
||||
+# automatically
|
||||
+# -DDBG_IDENT
|
||||
+# This will give show all the DHCP responses with
|
||||
+# their identifiers.
|
||||
+#
|
||||
#
|
||||
# Etherboot/32 only options:
|
||||
# -DAOUT_IMAGE - Add a.out kernel boot support (generic)
|
||||
@@ -147,6 +168,14 @@ CFLAGS32+= -DASK_BOOT=3 -DANS_DEFAULT=AN
|
||||
|
||||
# Change download protocol to NFS. Only available for Etherboot/32 for now.
|
||||
# CFLAGS32+= -DDOWNLOAD_PROTO_NFS
|
||||
+
|
||||
+# If you have more than one DHCP server you might want to
|
||||
+# enable these to be able to sort out which one you want to
|
||||
+# respond to.
|
||||
+CFLAGS32+= -DDEFAULT_CLIENT_IDENT=\"BOOT\" -DDEFAULT_SERVER_IDENT=\"BOOT\"
|
||||
+CFLAGS32+= -DASK_CLIENT_IDENT -DASK_SERVER_IDENT
|
||||
+CFLAGS32+= -DSHIFTED_IDENT_INPUT
|
||||
+CFLAGS32+= -DDBG_IDENT
|
||||
|
||||
# These flags affect the loader that is prepended to the Etherboot image
|
||||
LCONFIG+= -DMOVEROM
|
||||
|
||||
--------------4734FDA0BF2F2FBDF8EB8DF6
|
||||
Content-Type: text/plain; charset=us-ascii;
|
||||
name="etherboot.h.diff"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Content-Disposition: inline;
|
||||
filename="etherboot.h.diff"
|
||||
|
||||
--- etherboot-4.6.0/src/etherboot.h Tue Apr 25 08:30:55 2000
|
||||
+++ etherboot-4.5.6-new/src/etherboot.h Wed Apr 26 16:07:16 2000
|
||||
@@ -8,6 +8,14 @@ Author: Martin Renters
|
||||
|
||||
#include "osdep.h"
|
||||
|
||||
+#if (! defined(NO_DHCP_SUPPORT)) && (defined(ASK_CLIENT_IDENT) || defined(DEFAULT_CLIENT_IDENT))
|
||||
+# define CLIENT_IDENT
|
||||
+#endif
|
||||
+
|
||||
+#if (! defined(NO_DHCP_SUPPORT)) && (defined(ASK_SERVER_IDENT) || defined(DEFAULT_SERVER_IDENT))
|
||||
+# define SERVER_IDENT
|
||||
+#endif
|
||||
+
|
||||
/* These could be customised for different languages perhaps */
|
||||
#define ASK_PROMPT "Boot from (N)etwork or from (L)ocal? "
|
||||
#define ANS_NETWORK 'N'
|
||||
@@ -224,6 +232,12 @@ Author: Martin Renters
|
||||
#ifdef IMAGE_FREEBSD
|
||||
#define RFC1533_VENDOR_HOWTO 132
|
||||
#endif
|
||||
+#ifdef CLIENT_IDENT
|
||||
+#define RFC1533_VENDOR_CLIENT_IDENT 208
|
||||
+#endif
|
||||
+#ifdef SERVER_IDENT
|
||||
+#define RFC1533_VENDOR_SERVER_IDENT 208
|
||||
+#endif
|
||||
#define RFC1533_VENDOR_MNUOPTS 160
|
||||
#define RFC1533_VENDOR_SELECTION 176
|
||||
#define RFC1533_VENDOR_MOTD 184
|
||||
@@ -477,11 +491,13 @@ extern int getdec P((char **));
|
||||
extern void printf P((const char *, ...));
|
||||
extern char *sprintf P((char *, const char *, ...));
|
||||
extern int inet_aton P((char *p, in_addr *i));
|
||||
+extern char *inet_ntoa P((in_addr i, char *p));
|
||||
extern void gateA20_set P((void));
|
||||
extern void gateA20_unset P((void));
|
||||
extern void putchar P((int));
|
||||
extern int getchar P((void));
|
||||
extern int iskey P((void));
|
||||
+extern void getstr P((char *s, int size));
|
||||
|
||||
/* start*.S */
|
||||
extern int getc P((void));
|
||||
@@ -528,8 +544,10 @@ extern int hostnamelen;
|
||||
extern unsigned long netmask;
|
||||
extern int jmp_bootmenu[10];
|
||||
extern struct arptable_t arptable[MAX_ARP];
|
||||
-#ifdef IMAGE_MENU
|
||||
+#ifdef MOTD
|
||||
extern char *motd[RFC1533_VENDOR_NUMOFMOTD];
|
||||
+#endif
|
||||
+#ifdef IMAGE_MENU
|
||||
extern int menutmo,menudefault;
|
||||
extern unsigned char *defparams;
|
||||
extern int defparams_max;
|
||||
|
||||
--------------4734FDA0BF2F2FBDF8EB8DF6--
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
Date: Tue, 18 May 1999 15:45:55 +0200 (MEST)
|
||||
From: Erik Starback <erik@math.uu.se>
|
||||
To: netboot@baghira.han.de
|
||||
Subject: Netboot with Intel EEPRO100+ Management
|
||||
Message-ID: <Pine.LNX.3.96.990518154313.3875A-100000@anarchy.math.uu.se>
|
||||
MIME-Version: 1.0
|
||||
Content-Type: TEXT/PLAIN; charset=iso-8859-1
|
||||
Content-Transfer-Encoding: 8BIT
|
||||
Sender: owner-netboot@baghira.han.de
|
||||
Precedence: bulk
|
||||
Reply-To: netboot@baghira.han.de
|
||||
X-Moderator: netboot-owner@baghira.han.de
|
||||
X-UIDL: 6ca8453c19c46d622813e9be8ada9517
|
||||
Status: O
|
||||
X-Status:
|
||||
|
||||
Hello!
|
||||
|
||||
When Intel eepro100+ NIC disappeared from the market, I didn't know
|
||||
what to do. I didn't find any information if anyone has used the
|
||||
new eepro100+ Management Adapter to netboot linux.
|
||||
|
||||
I thought that the card should netboot with the same configuration as
|
||||
the old card when I read Donald Beckers comment:
|
||||
> The driver should "just work" with the '559. It's not supposed to be
|
||||
> substantially different than the '558. (I don't have a datasheet
|
||||
> or sample card to confirm this statement.)
|
||||
|
||||
The problem was now only to put the netboot-program to the built in
|
||||
flash memory on the NIC. With the old card I used a flash memory (Intel
|
||||
N28F020 [N28010 didn't work])) and the program FUTIL.EXE from Intel to
|
||||
flash it. FUTIL did't recognize the memory on the management card
|
||||
and did not work therefore.
|
||||
|
||||
I found the intel program FBOOT.EXE that was made to upgrade the built
|
||||
in Intel BOOT agent. I did: Boot dos from floppy, Run FBOOT (choose
|
||||
adapter), choose (u)pdate, choose Create restore image, rename the
|
||||
backup file (in my case 2743BE52.FLS [the eight last hex digits from
|
||||
the MAC address]), rename your netboot code (in my case netboot 0.8.1)
|
||||
to the backup files original name (in my case 2743BE52.FLS), run
|
||||
FBOOT, choose (r)estore.
|
||||
|
||||
Voila!
|
||||
|
||||
A shorter way (if you don't need the backup of the old Intel BOOT
|
||||
agent code) is of course: rename netboot file to [the eight last hex
|
||||
digits from the MAC address].FLS, run FBOOT, choose restore.
|
||||
|
||||
Caution: I think it is possible to make a NIC unusable if you have
|
||||
made the netboot (or etherboot) file with "wrong" parameters. A couple
|
||||
of month ago I did a etherboot boot file and put it on an old
|
||||
EEPRO100+ card. It worked fine, but it was impossible to boot local
|
||||
with it. So I could not boot dos and with FUTIL or FBOOT erase the
|
||||
flash memory! To erase the chip I had to take out the memory chip,
|
||||
boot dos and then put in the memory chip. This isn't possible when the
|
||||
memory chip is build in.
|
||||
|
||||
Links:
|
||||
<http://support.intel.com/support/landesk/configmgr/LSA1_193.HTM>
|
||||
FUTIL.EXE is a part of LSA1_193.ZIP
|
||||
|
||||
<http://support.intel.com/support/etherexpress/pro100/100pboot.htm>
|
||||
FBOOT.EXE is a part of 100pboot.exe
|
||||
|
||||
/Erik S
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
Erik Starbäck, System administrator E-mail address: erik@math.uu.se
|
||||
Uppsala University Telephone (o): +46 18 4713277
|
||||
Department of Mathematics Cellular phone: +46 70 4250260
|
||||
P. O. Box 480 Fax (o): +46 18 4713201
|
||||
SE-751 06 UPPSALA
|
||||
Sweden
|
|
@ -0,0 +1,149 @@
|
|||
Subject: Look Mom, no PROM burner! (eepro100b flashing instructions) :-)
|
||||
Date: Sun, 23 Jan 2000 01:53:08 -0500
|
||||
x-sender: mdc%thinguin.org@cdi.entity.com
|
||||
x-mailer: Claris Emailer 2.0v3, January 22, 1998
|
||||
From: Marty Connor <mdc@thinguin.org>
|
||||
To: "Netboot List" <netboot@baghira.han.de>
|
||||
Mime-Version: 1.0
|
||||
Content-Type: text/plain; charset="US-ASCII"
|
||||
Message-ID: <1263512144-341319205@entity.com>
|
||||
|
||||
Continuing the Etherboot World Domination theme, I noticed that there was
|
||||
a PCI ethernet card on my bookshelf that still contained the original
|
||||
vendor's code in its flash memory. The card virtually cried out to be
|
||||
flashed with Etherboot 4.4.1. :-)
|
||||
|
||||
After having figured out how to flash the 3C905C last week, and owing to
|
||||
the fact that the temperature here in Cambridge, Massachusetts (USA) has
|
||||
dropped well below freezing, I decided to explore the possibility of
|
||||
flashing the Intel eepro100b that was sitting on my bookcase.
|
||||
|
||||
After determining that it was unlikely that one could flash the chip in
|
||||
user mode under linux like the 3C509C, I turned to other options. (the
|
||||
reason is that the flash is memory mapped to a place that causes a core
|
||||
dump if accessed. i suppose one could to patch the kernel to flash the
|
||||
card, or add a linux device driver, but... :-)
|
||||
|
||||
By the way, If you are ever looking for Linux utilities for Ethernet
|
||||
cards, you may want to check out:
|
||||
|
||||
http://cesdis.gsfc.nasa.gov/linux/diag/
|
||||
|
||||
which is a treasure trove of tools for manipulating and testing Ethernet
|
||||
cards, all with source, courtesy of Donald Becker.
|
||||
|
||||
At this point, I felt it was time to make a virtual trip to the Intel
|
||||
site (http://www.intel.com/), and search for utilities that might work
|
||||
with the eepro100B. I found two candidates: FUTIL and FBOOT. I
|
||||
downloaded, decompressed, and transferred them to a DOS formatted floppy.
|
||||
Next I determined (after a few tries) that F8 will let me get to DOS
|
||||
instead of booting windows. (I tend to avoid Windows when I can).
|
||||
|
||||
I first tried FUTIL.EXE. No good. It told me it didn't recognize the
|
||||
flash on my eepro100B. how unfortunate. and I had such hopes :-)
|
||||
|
||||
Next I tested FBOOT.EXE (available at
|
||||
http://support.intel.com/support/network/adapter/pro100/100PBOOT.htm)
|
||||
This program did in fact recognize my eepro100b card.
|
||||
|
||||
The thing about FBOOT however, is that it thinks it only can load certain
|
||||
files. I of course needed to load an Etherboot image. It appeared to
|
||||
have no option for doing that. Things looked grim.
|
||||
|
||||
Then I noticed that FBOOT was kind enough to do the following dialog:
|
||||
|
||||
Select Option (U)pdate or (R)estore: U
|
||||
|
||||
I chose Update and it then offered to back up my flash rom for later
|
||||
restore:
|
||||
|
||||
Create Restore Image (Y)es or (N)o: Y
|
||||
|
||||
I chose "Y" and it proceeded to write a file of my flash memory, which
|
||||
contained the Intel code.
|
||||
|
||||
Writing FLASH image to file... 100%
|
||||
|
||||
It then erased the device:
|
||||
|
||||
Erasing FLASH Device... 100%
|
||||
|
||||
and then programmed it with fresh code (stored inside the program, no
|
||||
doubt):
|
||||
|
||||
Programming FLASH Device... 100%
|
||||
|
||||
So now I had a backup of the Intel boot code in a file strangely called:
|
||||
|
||||
2794FC60.FLS
|
||||
|
||||
Hmmmm, interesting name. The MAC address of the card is 09902794FC60.
|
||||
They just name the file with the last 4 octets of the MAC address and
|
||||
.FLS. The file is exactly 65536 bytes, which would make sense for a 64K
|
||||
Flash Memory device.
|
||||
|
||||
Then I got to thinking, I wonder how carefully the "restore" part of
|
||||
FBOOT looks at what it is loading? What if I took an Etherboot .rom
|
||||
file, padded it with 48K of 0xFFs and named it 2794FC60.FLS. What if I
|
||||
then told FBOOT.EXE to "restore" that?
|
||||
|
||||
Well, I guess by now, you know it worked :-)
|
||||
|
||||
The card came up with the delightful Etherboot banner, Did DHCP, tftp,
|
||||
and started a kernel.
|
||||
|
||||
The only unfortunate part is that you need to do this under DOS because
|
||||
you seem to need to be in real mode to program the card. Oh well,
|
||||
sacrifices have to be made :-)
|
||||
|
||||
So, in summary, to prepare Etherboot image for flashing into the Intel
|
||||
EEPRO100B card with FBOOT, you need to first make an eepro100.rom file,
|
||||
as usual.
|
||||
|
||||
Then, see how large it is, with an "ls -l eepro100.rom". the answer will
|
||||
probably be 16,384. You need to pad it with hex FFs to make it 64K for
|
||||
FBOOT. I used the following two lines to create the flash image file.
|
||||
|
||||
$ perl -e 'print "\xFF" x 49152' > 48kpad.bin
|
||||
$ cat eepro100.rom 48kpad.bin > 2794FC60.FLS
|
||||
|
||||
Next write it to a DOS Floppy:
|
||||
|
||||
$ mount -t msdos /dev/fd0 /mnt/floppy
|
||||
$ cp 2794FC60.FLS /mnt/floppy
|
||||
$ umount /mnt/floppy
|
||||
|
||||
Now you need to get to DOS. You could actually use a bootable DOS floppy
|
||||
with FBOOT.EXE and 2794FC60.FLS on it. I started a Windows box and hit
|
||||
F8 right before Windows started, and chose option 5, "Command Prompt
|
||||
Only", which gives you DOS. This program can't run in a DOS window under
|
||||
Windows or anything like that. You need to be in real DOS.
|
||||
|
||||
Next it's time to run FBOOT. It will detect your ethernet card(s), ask
|
||||
you which one you want to program, and let you choose it from a menu.
|
||||
|
||||
now the fun part:
|
||||
|
||||
Select Option (U)pdate or (R)estore: R
|
||||
Erasing FLASH Device... 100%
|
||||
Writing FLASH image from file... 100%
|
||||
|
||||
Time to reboot and let Etherboot take over.
|
||||
|
||||
So there you go, a way to make Intel EEPRO100Bs play nicely with
|
||||
Etherboot. Maybe we should put these instructions in the Etherboot
|
||||
contrib directory so people who have eepro100b cards will be able to
|
||||
avoid 3C905C envy :-)
|
||||
|
||||
I hope this helps a few people out.
|
||||
|
||||
Regards,
|
||||
|
||||
Marty
|
||||
|
||||
---
|
||||
Name: Martin D. Connor
|
||||
US Mail: Entity Cyber, Inc.; P.O. Box 391827; Cambridge, MA 02139; USA
|
||||
Voice: (617) 491-6935, Fax: (617) 491-7046
|
||||
Email: mdc@thinguin.org
|
||||
Web: http://www.thinguin.org/
|
|
@ -0,0 +1,57 @@
|
|||
Date: Sun, 23 Jan 2000 09:47:15 +0100 (MET)
|
||||
From: Erik Starbäck <erik@math.uu.se>
|
||||
To: Netboot List <netboot@baghira.han.de>
|
||||
Subject: Re: Look Mom, no PROM burner! (eepro100b flashing instructions) :-)
|
||||
In-Reply-To: <1263512144-341319205@entity.com>
|
||||
Message-ID: <Pine.LNX.3.96.1000123094505.28562A-100000@anarchy.math.uu.se>
|
||||
MIME-Version: 1.0
|
||||
Content-Type: TEXT/PLAIN; charset=iso-8859-1
|
||||
Content-Transfer-Encoding: 8BIT
|
||||
Sender: owner-netboot@baghira.han.de
|
||||
Precedence: bulk
|
||||
Reply-To: netboot@baghira.han.de
|
||||
X-Moderator: netboot-owner@baghira.han.de
|
||||
|
||||
|
||||
Hello!
|
||||
|
||||
In <http://www.han.de/~gero/netboot/archive/msg01718.html> I wrote what I
|
||||
did know about futil and fboot then. It is about the same as Martys
|
||||
instructions, but I have a few comments now.
|
||||
|
||||
> Then, see how large it is, with an "ls -l eepro100.rom". the answer will
|
||||
> probably be 16,384. You need to pad it with hex FFs to make it 64K for
|
||||
> FBOOT. I used the following two lines to create the flash image file.
|
||||
|
||||
> $ perl -e 'print "\xFF" x 49152' > 48kpad.bin
|
||||
> $ cat eepro100.rom 48kpad.bin > 2794FC60.FLS
|
||||
|
||||
It worked for me without any padding. When I burned a smaller image
|
||||
the program printed 50% instead of 100% and then it
|
||||
stopped. Everything worked anyway.
|
||||
|
||||
|
||||
I also did a brutal way of install etherboot or netboot on a
|
||||
EEPRO100+Mng without creating a file of type "2794FC60.FLS" for
|
||||
every card. It was necessary for me when I installed 70 clients...
|
||||
|
||||
I chopped the binary file fboot.exe (my version was 99811 bytes, I
|
||||
don't remember the version name) in three parts:
|
||||
|
||||
fboot1 30096 bytes
|
||||
fboot2 65536 bytes
|
||||
fboot3 4179 bytes
|
||||
|
||||
Then you cat put them together again, but with a different part 2 and
|
||||
save it as fbootown.exe and execute it. It worked for me anyway. Of
|
||||
course you have to use padding to get a 64k part instead of fboot2.
|
||||
|
||||
/Erik S
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
Erik Starbäck, System administrator E-mail address: erik@math.uu.se
|
||||
Uppsala University Telephone (o): +46 18 4713277
|
||||
Department of Mathematics Cellular phone: +46 70 4250260
|
||||
P. O. Box 480 Fax (o): +46 18 4713201
|
||||
SE-751 06 UPPSALA
|
||||
Sweden
|
|
@ -0,0 +1,29 @@
|
|||
CPPFLAGS = -x assembler-with-cpp
|
||||
AS86 = as86
|
||||
LD86 = ld86
|
||||
OBJDUMP = objdump
|
||||
|
||||
.SUFFIXES: .s86 .asm .aout .img
|
||||
|
||||
all: flashimg.img
|
||||
|
||||
clean:
|
||||
rm -rf *.o *.s86 *.aout *.img
|
||||
|
||||
realclean: clean
|
||||
rm -rf *.img
|
||||
|
||||
.asm.s86: $*.asm $*.inc
|
||||
$(CPP) $(CPPFLAGS) -o $@ $*.asm
|
||||
|
||||
.s86.img: $*.s86
|
||||
$(AS86) -0 -b $@ $*.s86
|
||||
|
||||
# .s86.o: $*.s86
|
||||
# $(AS86) -0 -a -o $@ $*.s86
|
||||
#
|
||||
# .o.aout: $*.o
|
||||
# $(LD86) -0 -s -o $@ $*.o
|
||||
#
|
||||
# .aout.img:
|
||||
# dd if=$*.aout of=$@ bs=32 skip=1
|
|
@ -0,0 +1,497 @@
|
|||
; Copyright (C) 1997 Markus Gutschke <gutschk@uni-muenster.de>
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or modify
|
||||
; it under the terms of the GNU General Public License as published by
|
||||
; the Free Software Foundation; either version 2 of the License, or
|
||||
; any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
; Prepend this image file to an arbitrary ROM image. The resulting binary
|
||||
; can be loaded from any BOOT-Prom that supports the "nbi" file format.
|
||||
; When started, the image will reprogram the flash EPROM on the FlashCard
|
||||
; ISA card. The flash EPROM has to be an AMD 29F010, and the programming
|
||||
; algorithm is the same as that suggested by AMD in the appropriate data
|
||||
; sheets.
|
||||
|
||||
|
||||
#define SEGLOW 0xC800 /* lower range for EPROM segment */
|
||||
#define SEGHIGH 0xE800 /* upper range for EPROM segment */
|
||||
#define AMD_ID 0x2001 /* flash EPROM ID, only support AMD */
|
||||
#define ERASE1_CMD 0x80 /* first cmd for erasing full chip */
|
||||
#define ERASE2_CMD 0x10 /* second cmd for erasing full chip */
|
||||
#define READID_CMD 0x90 /* cmd to read chip ID */
|
||||
#define PROG_CMD 0xA0 /* cmd to program a byte */
|
||||
#define RESET_CMD 0xF0 /* cmd to reset chip state machine */
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
|
||||
.text
|
||||
.org 0
|
||||
|
||||
; .globl _main
|
||||
_main: mov ax,#0x0FE0
|
||||
mov ds,ax
|
||||
mov ax,magic ; verify that we have been loaded by
|
||||
cmp ax,#0xE4E4 ; boot prom
|
||||
jnz lderr
|
||||
jmpi 0x200,0x0FE0 ; adjust code segment
|
||||
lderr: mov si,#loaderr
|
||||
cld
|
||||
lderrlp:seg cs
|
||||
lodsb ; loop over all characters of
|
||||
or al,al ; string
|
||||
jnz lderrnx
|
||||
xor ah,ah
|
||||
int 0x16 ; wait for keypress
|
||||
jmpi 0x0000,0xFFFF ; reboot!
|
||||
lderrnx:mov ah,#0x0E ; print it
|
||||
mov bl,#0x07
|
||||
xor bh,bh
|
||||
int 0x10
|
||||
jmp lderrlp
|
||||
|
||||
loaderr:.ascii "The flash EPROM utility has to be loaded from a BOOT-Prom"
|
||||
.byte 0xa,0xd
|
||||
.ascii "that knows about the 'nbi' file format!"
|
||||
.byte 0xa,0xd
|
||||
.ascii "Reboot to proceed..."
|
||||
.byte 0
|
||||
|
||||
.org 510
|
||||
.byte 0x55,0xAA
|
||||
|
||||
!----------------------------------------------------------------------------
|
||||
|
||||
start: mov ax,cs
|
||||
mov ds,ax
|
||||
mov ax,romdata ; verify that there is an Prom image
|
||||
cmp ax,#0xAA55 ; attached to the utility
|
||||
jnz resmag
|
||||
mov al,romdata+2
|
||||
or al,al ; non-zero size is required
|
||||
jnz magicok
|
||||
resmag: mov si,#badmagic ; print error message
|
||||
reset: call prnstr
|
||||
xor ah,ah
|
||||
int 0x16 ; wait for keypress
|
||||
jmpi 0x0000,0xFFFF ; reboot!
|
||||
magicok:mov di,#clrline1
|
||||
mov si,#welcome ; print welcome message
|
||||
inpnew: call prnstr
|
||||
inprest:xor bx,bx
|
||||
mov cl,#0xC ; expect 4 nibbles input data
|
||||
inploop:xor ah,ah
|
||||
int 0x16
|
||||
cmp al,#0x8 ; <Backspace>
|
||||
jnz inpnobs
|
||||
or bx,bx ; there has to be at least one input ch
|
||||
jz inperr
|
||||
mov si,#delchar ; wipe out char from screen
|
||||
call prnstr
|
||||
add cl,#4 ; compute bitmask for removing input
|
||||
mov ch,cl
|
||||
mov cl,#0xC
|
||||
sub cl,ch
|
||||
mov ax,#0xFFFF
|
||||
shr ax,cl
|
||||
not ax
|
||||
and bx,ax
|
||||
mov cl,ch
|
||||
inploop1:jmp inploop
|
||||
inpnobs:cmp al,#0x0D ; <Return>
|
||||
jnz inpnocr
|
||||
or bx,bx ; zero input -> autoprobing
|
||||
jz inpdone
|
||||
cmp cl,#-4 ; otherwise there have to be 4 nibbles
|
||||
jz inpdone
|
||||
inperr: mov al,#7 ; ring the console bell
|
||||
jmp inpecho
|
||||
inpnocr:cmp al,#0x15 ; <CTRL-U>
|
||||
jnz inpnokl
|
||||
mov si,di
|
||||
call prnstr ; clear entire input and restart
|
||||
jmp inprest
|
||||
inpnokl:cmp cl,#-4 ; cannot input more than 4 nibbles
|
||||
jz inperr
|
||||
cmp al,#0x30 ; '0'
|
||||
jb inperr
|
||||
ja inpdig
|
||||
or bx,bx ; leading '0' is not allowed
|
||||
jz inperr
|
||||
inpdig: cmp al,#0x39 ; '9'
|
||||
ja inpnodg
|
||||
mov ch,al
|
||||
sub al,#0x30
|
||||
inpnum: xor ah,ah ; compute new input value
|
||||
shl ax,cl
|
||||
add ax,bx
|
||||
test ax,#0x1FF ; test for 8kB boundary
|
||||
jnz inperr
|
||||
cmp ax,#SEGHIGH ; input has to be below E800
|
||||
jae inperr
|
||||
cmp ax,#SEGLOW ; and above/equal C800
|
||||
jae inpok
|
||||
cmp cl,#0xC ; if there is just one nibble, yet,
|
||||
jnz inperr ; then the lower limit ix C000
|
||||
cmp ax,#0xC000
|
||||
jb inperr
|
||||
inpok: mov bx,ax ; adjust bitmask
|
||||
sub cl,#4
|
||||
mov al,ch
|
||||
inpecho:call prnchr ; output new character
|
||||
jmp inploop1
|
||||
inpnodg:and al,#0xDF ; lower case -> upper case
|
||||
cmp al,#0x41 ; 'A'
|
||||
jb inperr
|
||||
cmp al,#0x46 ; 'F'
|
||||
ja inperr
|
||||
mov ch,al
|
||||
sub al,#0x37
|
||||
jmp inpnum
|
||||
inpdone:or bx,bx ; zero -> autoprobing
|
||||
jnz probe
|
||||
mov si,#automsg
|
||||
call prnstr
|
||||
mov cx,#0x10
|
||||
mov bx,#SEGHIGH ; scan from E800 to C800
|
||||
autoprb:sub bx,#0x0200 ; stepping down in 8kB increments
|
||||
mov di,bx
|
||||
call readid
|
||||
cmp ax,#AMD_ID
|
||||
jz prbfnd
|
||||
loop autoprb
|
||||
mov si,#failmsg
|
||||
nofnd: mov di,#clrline2
|
||||
jmp near inpnew ; failure -> ask user for new input
|
||||
probe: mov di,bx
|
||||
test bx,#0x07FF ; EPROM might have to be aligned to
|
||||
jz noalign ; 32kB boundary
|
||||
call readid
|
||||
cmp ax,#AMD_ID ; check for AMDs id
|
||||
jz prbfnd
|
||||
mov si,#alignmsg
|
||||
call prnstr
|
||||
and bx,#0xF800 ; enforce alignment of hardware addr
|
||||
noalign:call readid ; check for AMDs id
|
||||
cmp ax,#AMD_ID
|
||||
jz prbfnd
|
||||
mov si,#nofndmsg ; could not find any EPROM at speci-
|
||||
call prnstr ; fied location --- even tried
|
||||
mov si,#basemsg ; aligning to 32kB boundary
|
||||
jmp nofnd ; failure -> ask user for new input
|
||||
prbfnd: mov si,#fndmsg
|
||||
call prnstr ; we found a flash EPROM
|
||||
mov ax,bx
|
||||
call prnwrd
|
||||
mov si,#ersmsg
|
||||
call prnstr
|
||||
call erase ; erase old contents
|
||||
jnc ersdone
|
||||
mov si,#failresmsg ; failure -> reboot machine
|
||||
jmp near reset
|
||||
ersdone:mov si,#prg1msg ; tell user that we are about
|
||||
call prnstr ; to program the new data into
|
||||
mov ax,di ; the specified range
|
||||
call prnwrd
|
||||
mov si,#prg2msg
|
||||
call prnstr
|
||||
xor dh,dh
|
||||
mov dl,romdata+2
|
||||
shl dx,#1
|
||||
mov ah,dh
|
||||
mov cl,#4
|
||||
shl ah,cl
|
||||
xor al,al
|
||||
add ax,di
|
||||
call prnwrd
|
||||
mov al,#0x3A ; ':'
|
||||
call prnchr
|
||||
mov ah,dl
|
||||
xor al,al
|
||||
dec ax
|
||||
call prnwrd
|
||||
mov al,#0x20
|
||||
call prnchr
|
||||
mov dh,romdata+2 ; number of 512 byte blocks
|
||||
push ds
|
||||
mov ax,ds
|
||||
add ax,#romdata>>4 ; adjust segment descriptor, so that
|
||||
mov ds,ax ; we can handle images which are
|
||||
prgloop:mov cx,#0x200 ; larger than 64kB
|
||||
xor si,si
|
||||
xor bp,bp
|
||||
call program ; program 512 data bytes
|
||||
jc prgerr ; check error condition
|
||||
mov ax,ds
|
||||
add ax,#0x20 ; increment segment descriptors
|
||||
mov ds,ax
|
||||
add di,#0x20
|
||||
dec dh ; decrement counter
|
||||
jnz prgloop
|
||||
pop ds
|
||||
mov si,#donemsg ; success -> reboot
|
||||
prgdone:call prnstr
|
||||
mov si,#resetmsg
|
||||
jmp near reset
|
||||
prgerr: pop ds ; failure -> reboot
|
||||
mov si,#failresmsg
|
||||
jmp prgdone
|
||||
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
; READID -- read EPROM id number, base address is passed in BX
|
||||
; ======
|
||||
;
|
||||
; changes: AX, DL, ES
|
||||
|
||||
readid: mov dl,#RESET_CMD ; reset chip
|
||||
call sendop
|
||||
mov dl,#READID_CMD
|
||||
call sendop ; send READID command
|
||||
mov es,bx
|
||||
seg es
|
||||
mov ax,0x00 ; read manufacturer ID
|
||||
mov dl,#RESET_CMD
|
||||
jmp sendop ; reset chip
|
||||
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
; ERASE -- erase entire EPROM, base address is passed in BX
|
||||
; =====
|
||||
;
|
||||
; changes: AL, CX, DL, ES, CF
|
||||
|
||||
erase: mov dl,#ERASE1_CMD
|
||||
call sendop ; send ERASE1 command
|
||||
mov dl,#ERASE2_CMD
|
||||
call sendop ; send ERASE2 command
|
||||
xor bp,bp
|
||||
mov al,#0xFF
|
||||
push di
|
||||
mov di,bx
|
||||
call waitop ; wait until operation finished
|
||||
pop di
|
||||
jnc erfail
|
||||
mov dl,#RESET_CMD
|
||||
call sendop ; reset chip
|
||||
stc
|
||||
erfail: ret
|
||||
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
; PROGRAM -- write data block at DS:SI of length CX into EPROM at DI:BP
|
||||
; =======
|
||||
;
|
||||
; changes: AX, CX, DL, BP, ES, CF
|
||||
|
||||
program:mov dl,#PROG_CMD
|
||||
call sendop ; send programming command
|
||||
lodsb ; get next byte from buffer
|
||||
mov es,di
|
||||
seg es
|
||||
mov byte ptr [bp],al ; write next byte into flash EPROM
|
||||
call waitop ; wait until programming operation is
|
||||
jc progdn ; completed
|
||||
inc bp
|
||||
loop program ; continue with next byte
|
||||
clc ; return without error
|
||||
progdn: ret
|
||||
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
; SENDOP -- send command in DL to EPROM, base address is passed in BX
|
||||
; ======
|
||||
;
|
||||
; changes: ES
|
||||
|
||||
sendop: mov es,bx
|
||||
seg es
|
||||
mov byte ptr 0x5555,#0xAA ; write magic data bytes into
|
||||
jcxz so1 ; magic locations. This unlocks
|
||||
so1: jcxz so2 ; the flash EPROM. N.B. that the
|
||||
so2: seg es ; magic locations are mirrored
|
||||
mov byte ptr 0x2AAA,#0x55 ; every 32kB; the hardware address
|
||||
jcxz so3 ; might have to be adjusted to a
|
||||
so3: jcxz so4 ; 32kB boundary
|
||||
so4: seg es
|
||||
mov byte ptr 0x5555,dl
|
||||
ret
|
||||
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
; WAITOP -- wait for command to complete, address is passed in DI:BP
|
||||
; ======
|
||||
;
|
||||
; for details on the programming algorithm, c.f. http://www.amd.com
|
||||
;
|
||||
; changes: AX, DL, ES, CF
|
||||
|
||||
waitop: and al,#0x80 ; monitor bit 7
|
||||
mov es,di
|
||||
wait1: seg es ; read contents of EPROM cell that is
|
||||
mov ah,byte ptr [bp] ; being programmed
|
||||
mov dl,ah
|
||||
and ah,#0x80
|
||||
cmp al,ah ; bit 7 indicates sucess
|
||||
je waitok
|
||||
test dl,#0x20 ; bit 5 indicates timeout/error
|
||||
jz wait1 ; otherwise wait for cmd to complete
|
||||
seg es
|
||||
mov ah,byte ptr [bp] ; check error condition once again,
|
||||
and ah,#0x80 ; because bits 7 and 5 can change
|
||||
cmp al,ah ; simultaneously
|
||||
je waitok
|
||||
stc
|
||||
ret
|
||||
waitok: clc
|
||||
ret
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
; PRNSTR -- prints a string in DS:SI onto the console
|
||||
; ======
|
||||
;
|
||||
; changes: AL
|
||||
|
||||
prnstr: push si
|
||||
cld
|
||||
prns1: lodsb ; loop over all characters of
|
||||
or al,al ; string
|
||||
jz prns2
|
||||
call prnchr ; print character
|
||||
jmp prns1
|
||||
prns2: pop si
|
||||
ret
|
||||
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
; PRNWRD, PRNBYT, PRNNIB, PRNCHR -- prints hexadezimal values, or ASCII chars
|
||||
; ====== ====== ====== ======
|
||||
;
|
||||
; changes: AX
|
||||
|
||||
prnwrd: push ax
|
||||
mov al,ah
|
||||
call prnbyt ; print the upper byte
|
||||
pop ax
|
||||
prnbyt: push ax
|
||||
shr al,1 ; prepare upper nibble
|
||||
shr al,1
|
||||
shr al,1
|
||||
shr al,1
|
||||
call prnnib ; print it
|
||||
pop ax
|
||||
prnnib: and al,#0x0F ; prepare lower nibble
|
||||
add al,#0x30
|
||||
cmp al,#0x39 ; convert it into hex
|
||||
jle prnchr
|
||||
add al,#7
|
||||
prnchr: push bx
|
||||
mov ah,#0x0E ; print it
|
||||
mov bl,#0x07
|
||||
xor bh,bh
|
||||
int 0x10
|
||||
pop bx
|
||||
ret
|
||||
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
magic: .byte 0xE4,0xE4
|
||||
|
||||
badmagic:.byte 0xa,0xd
|
||||
.ascii "There does not appear to be a ROM image attached to the"
|
||||
.ascii "flash EPROM utility;"
|
||||
.byte 0xa,0xd
|
||||
resetmsg:.ascii "Reboot to proceed..."
|
||||
.byte 0
|
||||
|
||||
welcome:.byte 0xa,0xd
|
||||
.ascii "Flash EPROM programming utility V1.0"
|
||||
.byte 0xa,0xd
|
||||
.ascii "Copyright (c) 1997 by M. Gutschke <gutschk@uni-muenster.de>"
|
||||
.byte 0xa,0xd
|
||||
.ascii "==========================================================="
|
||||
.byte 0xa,0xd
|
||||
prompt: .byte 0xa,0xd
|
||||
.ascii "Enter base address for AMD29F010 flash EPROM on FlashCard or"
|
||||
.byte 0xa,0xd
|
||||
.ascii "press <RETURN> to start autoprobing; the base address has"
|
||||
.byte 0xa
|
||||
clrline1:.byte 0xd
|
||||
.ascii "to be in the range C800..E600: "
|
||||
.ascii " "
|
||||
.byte 0x8,0x8,0x8,0x8
|
||||
.byte 0
|
||||
|
||||
delchar:.byte 0x8,0x20,0x8
|
||||
.byte 0
|
||||
|
||||
automsg:.ascii "autoprobing... "
|
||||
.byte 0
|
||||
|
||||
failmsg:.ascii "failed!"
|
||||
basemsg:.byte 0xa
|
||||
clrline2:.byte 0xd
|
||||
.ascii "Enter base address: "
|
||||
.ascii " "
|
||||
.byte 0x8,0x8,0x8,0x8
|
||||
.byte 0
|
||||
|
||||
fndmsg: .byte 0xa,0xd
|
||||
.ascii "Found flash EPROM at: "
|
||||
.byte 0
|
||||
|
||||
alignmsg:.byte 0xa,0xd
|
||||
.ascii "FlashCard requires the hardware address to be aligned to a"
|
||||
.byte 0xa,0xd
|
||||
.ascii "32kB boundary; automatically adjusting..."
|
||||
.byte 0
|
||||
|
||||
nofndmsg:.byte 0xa,0xd
|
||||
.ascii "No AMD29F010 flash EPROM found"
|
||||
.byte 0
|
||||
|
||||
ersmsg: .byte 0xa,0xd
|
||||
.ascii "Erasing old contents... "
|
||||
.byte 0
|
||||
|
||||
prg1msg:.ascii "done"
|
||||
.byte 0xa,0xd
|
||||
.ascii "Programming from "
|
||||
.byte 0
|
||||
|
||||
prg2msg:.ascii ":0000 to "
|
||||
.byte 0
|
||||
|
||||
donemsg:.ascii "done!"
|
||||
.byte 0xa,0xd
|
||||
.byte 0
|
||||
|
||||
failresmsg:
|
||||
.ascii "failed!"
|
||||
.byte 0xa,0xd
|
||||
.byte 0
|
||||
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
.align 16
|
||||
.org *-1
|
||||
.byte 0x00
|
||||
romdata:
|
Binary file not shown.
|
@ -0,0 +1,15 @@
|
|||
# Use nasm or as86
|
||||
ASM=nasm
|
||||
# ASM=as86
|
||||
|
||||
hdload.bin: hdload.S
|
||||
ifeq ($(ASM),as86)
|
||||
gcc $(CFLAGS) -DUSE_AS86 -E -traditional -o hdload.s hdload.S
|
||||
as86 -0 -b hdload.bin hdload.s
|
||||
else
|
||||
gcc $(CFLAGS) -DUSE_NASM -E -traditional -o hdload.s hdload.S
|
||||
nasm -f bin hdload.s -o hdload.bin
|
||||
endif
|
||||
|
||||
clean:
|
||||
$(RM) -f hdload.s hdload.bin
|
|
@ -0,0 +1,162 @@
|
|||
#if !defined(USE_NASM) && !defined(USE_AS86)
|
||||
#define USE_AS86
|
||||
#endif
|
||||
|
||||
#ifdef USE_AS86
|
||||
#define CON(x) *x
|
||||
#define BCON(x) *x
|
||||
#define WCON(x) *x
|
||||
#define LOC(x) x
|
||||
#define BLOC(x) byte ptr x
|
||||
#define WLOC(x) word ptr x
|
||||
#define JMP(x) jmp x
|
||||
#define STRDECL(s) .ascii s
|
||||
#define SEGCS seg cs
|
||||
#define SEGES seg es
|
||||
#define ALIGN(x) .align x
|
||||
#define SPACE(x) .space x
|
||||
#endif
|
||||
|
||||
#ifdef USE_NASM
|
||||
#define CON(x) x
|
||||
#define BCON(x) byte x
|
||||
#define WCON(x) word x
|
||||
#define LOC(x) [x]
|
||||
#define BLOC(x) byte [x]
|
||||
#define WLOC(x) word [x]
|
||||
#define JMP(x) jmp short x
|
||||
#define STRDECL(s) db s
|
||||
#define SEGCS cs
|
||||
#define SEGES es
|
||||
#define ALIGN(x) align x, db 0
|
||||
#define SPACE(x) times x db 0
|
||||
#endif
|
||||
|
||||
ROMLOAD equ 0x5000
|
||||
|
||||
start:
|
||||
cli
|
||||
xor ax, ax
|
||||
mov ss, ax
|
||||
mov sp, CON(0x7C00)
|
||||
mov si, sp
|
||||
mov es, ax
|
||||
mov ds, ax
|
||||
sti
|
||||
cld
|
||||
mov di, CON(0x600)
|
||||
mov cx, CON(0x100)
|
||||
rep
|
||||
movsw
|
||||
db 0xEA
|
||||
dw jump
|
||||
dw 0
|
||||
jump:
|
||||
mov si, CON(Hlaska)
|
||||
call print
|
||||
|
||||
; rozmery prvniho HD
|
||||
mov ah, CON(8)
|
||||
mov dl, CON(0x80)
|
||||
int 0x13
|
||||
jc chyba
|
||||
; dh - H, cx - CS
|
||||
|
||||
; prvi stopa obsahuje bootrom, tak ji natahneme do RAM
|
||||
mov ah, CON(2)
|
||||
mov al, cl
|
||||
and al, CON(0x3F)
|
||||
dec al
|
||||
mov dx, CON(0x80)
|
||||
mov cx, CON(2)
|
||||
mov bx, CON(ROMLOAD)
|
||||
mov es, bx
|
||||
xor bx, bx
|
||||
int 0x13
|
||||
jc chyba
|
||||
|
||||
; hromada kodu podle zdrojaku netboot
|
||||
xor di, di
|
||||
mov es, di
|
||||
mov di, CON(0x380)
|
||||
push di
|
||||
mov cx, CON(10)
|
||||
cld
|
||||
rep
|
||||
stosw
|
||||
pop di
|
||||
#ifdef USE_AS86
|
||||
mov word ptr [ di ], CON(0x5a5a)
|
||||
mov byte ptr [ di + 2 ], CON(0x50)
|
||||
mov word ptr [ di + 0x10 ], CON(0xFFFF)
|
||||
mov word ptr [ di + 0x12 ], CON(0xFFFF)
|
||||
#endif
|
||||
#ifdef USE_NASM
|
||||
mov word [ di ], CON(0x5a5a)
|
||||
mov byte [ di + 2 ], CON(0x50)
|
||||
mov word [ di + 10h ], CON(0xFFFF)
|
||||
mov word [ di + 12h ], CON(0xFFFF)
|
||||
#endif
|
||||
|
||||
; navratova adresa, kdyby nezabrala ROM
|
||||
SEGCS
|
||||
mov WLOC(OfsErr), CON(RomErr)
|
||||
push cs
|
||||
push WCON(chyba)
|
||||
mov ax, CON(ROMLOAD)
|
||||
mov es, ax
|
||||
push es
|
||||
; kouzelny jump....
|
||||
SEGES
|
||||
mov si, [ 0x1a ]
|
||||
SEGES
|
||||
#ifdef USE_AS86
|
||||
push word ptr [ si + 0x1a ] ; ...do bootrom v RAM
|
||||
#endif
|
||||
#ifdef USE_NASM
|
||||
push word [ si + 0x1a ] ; ...do bootrom v RAM
|
||||
#endif
|
||||
retf
|
||||
|
||||
chyba:
|
||||
SEGCS
|
||||
mov si, LOC(OfsErr)
|
||||
call print
|
||||
mov si, CON(CRLF)
|
||||
call print
|
||||
JMP(chyba)
|
||||
|
||||
print:
|
||||
lodsb
|
||||
cmp al,CON(0)
|
||||
je navrat
|
||||
push si
|
||||
mov bx,CON(7)
|
||||
mov ah,CON(0x0E)
|
||||
int 0x10
|
||||
pop si
|
||||
JMP(print)
|
||||
|
||||
navrat:
|
||||
ret
|
||||
|
||||
Hlaska: db 13, 10
|
||||
STRDECL('HD Net Loader v1.0 (c) poli 1999')
|
||||
db 13, 10, 0
|
||||
CRLF: db 13, 10, 0
|
||||
OfsErr: dw Error
|
||||
Error: STRDECL('Error load from HD !')
|
||||
db 0
|
||||
RomErr: STRDECL('ROM Error !')
|
||||
db 0
|
||||
|
||||
mbrend:
|
||||
ret
|
||||
|
||||
#ifdef USE_AS86
|
||||
org 510
|
||||
#endif
|
||||
#ifdef USE_NASM
|
||||
times 510-($-$$) db 0
|
||||
#endif
|
||||
dw 0xAA55
|
|
@ -0,0 +1,175 @@
|
|||
From netboot-owner@baghira.han.de Thu Sep 16 12:08:44 1999
|
||||
Return-Path: <netboot-owner@baghira.han.de>
|
||||
Received: (from factotum@localhost)
|
||||
by baghira.han.de (8.9.3/8.9.3) id NAA23838
|
||||
for netboot-outgoing; Wed, 15 Sep 1999 13:12:44 +0200
|
||||
X-Authentication-Warning: baghira.han.de: factotum set sender to owner-netboot using -f
|
||||
Received: from hathi.han.de (root@hathi.han.de [192.109.225.1])
|
||||
by baghira.han.de (8.9.3/8.9.3) with ESMTP id NAA23785
|
||||
for <netboot@baghira.han.de>; Wed, 15 Sep 1999 13:11:02 +0200
|
||||
Received: from vsb.cz (root@decsys.vsb.cz [158.196.149.9])
|
||||
by hathi.han.de (8.9.3/8.9.3) with ESMTP id NAA04707
|
||||
for <netboot@baghira.han.de>; Wed, 15 Sep 1999 13:11:00 +0200
|
||||
Received: from nwfei1.vsb.cz (nwfei1.vsb.cz [158.196.146.13])
|
||||
by vsb.cz (8.9.3/8.9.1) with ESMTP id NAA22363
|
||||
for <netboot@baghira.han.de>; Wed, 15 Sep 1999 13:10:52 +0200 (MET DST)
|
||||
Received: from FEI1/SpoolDir by nwfei1.vsb.cz (Mercury 1.44);
|
||||
15 Sep 99 13:10:50 +0100
|
||||
Received: from SpoolDir by FEI1 (Mercury 1.44); 15 Sep 99 13:10:27 +0100
|
||||
Received: from pcd403z.vsb.cz (158.196.146.9) by nwfei1.vsb.cz (Mercury 1.44) with ESMTP;
|
||||
15 Sep 99 13:10:25 +0100
|
||||
Received: from oli10 by pcd403z.vsb.cz with local-esmtp (Exim 2.05 #1 (Debian))
|
||||
id 11RCxI-0000oT-00; Wed, 15 Sep 1999 13:10:28 +0200
|
||||
Date: Wed, 15 Sep 1999 13:10:28 +0200 (CEST)
|
||||
From: Petr Olivka <Petr.Olivka@vsb.cz>
|
||||
To: netboot@baghira.han.de
|
||||
Subject: netboot image on hard disk - it is easy
|
||||
In-Reply-To: <37DF4BD4.E8FFF8FC@gsmbox.com>
|
||||
Message-ID: <Pine.LNX.4.10.9909151247430.2936-100000@pcd403z.vsb.cz>
|
||||
MIME-Version: 1.0
|
||||
Content-Type: TEXT/PLAIN; charset=US-ASCII
|
||||
Sender: owner-netboot@baghira.han.de
|
||||
Precedence: bulk
|
||||
Reply-To: netboot@baghira.han.de
|
||||
X-Moderator: netboot-owner@baghira.han.de
|
||||
|
||||
It is good joke, at this moment I have only simple version of MBR to load
|
||||
image from HD, but only from track 0. HD have to have enough sectors per
|
||||
track for rom image.
|
||||
And small program in turbo-pascal to download image to HD.
|
||||
|
||||
below is assembler code for MBR. Is writen for tasm and tlink.
|
||||
If you have 512 bytes binary file with MBR code, then concat it with
|
||||
rom-image and download to hda. BUT NOT DIRECTLY !!!! You have to copy
|
||||
partition table ( and NT signature ) to MBR and then download. BUT ONLY tO
|
||||
TRACK 0.
|
||||
|
||||
Everything in your own risk.
|
||||
|
||||
If I will have some free time, I will write some code directly to netboot.
|
||||
|
||||
poli
|
||||
|
||||
.model large, pascal
|
||||
|
||||
.code
|
||||
.386
|
||||
public mbrasm, mbrend
|
||||
|
||||
ROMLOAD equ 5000h
|
||||
|
||||
org 600h
|
||||
|
||||
mbrasm proc
|
||||
|
||||
cli
|
||||
xor ax, ax
|
||||
mov ss, ax
|
||||
mov sp, 7C00h
|
||||
mov si, sp
|
||||
mov es, ax
|
||||
mov ds, ax
|
||||
sti
|
||||
cld
|
||||
mov di, 600h
|
||||
mov cx, 100h
|
||||
rep movsw
|
||||
db 0EAh
|
||||
dw offset @@jump
|
||||
dw 0
|
||||
@@jump:
|
||||
mov si, offset Hlaska
|
||||
call @@print
|
||||
|
||||
; rozmery prvniho HD
|
||||
mov ah, 8
|
||||
mov dl, 80h
|
||||
int 13h
|
||||
jc @@chyba
|
||||
; dh - H, cx - CS
|
||||
|
||||
; prvi stopa obsahuje bootrom, tak ji natahneme do RAM
|
||||
mov ah, 2
|
||||
mov al, cl
|
||||
and al, 3Fh
|
||||
dec al
|
||||
mov dx, 80h
|
||||
mov cx, 2
|
||||
mov bx, ROMLOAD
|
||||
mov es, bx
|
||||
xor bx, bx
|
||||
int 13h
|
||||
jc @@chyba
|
||||
|
||||
; hromada kodu podle zdrojaku netboot
|
||||
xor di, di
|
||||
mov es, di
|
||||
mov di, 380h
|
||||
push di
|
||||
mov cx, 10
|
||||
cld
|
||||
rep stosw
|
||||
pop di
|
||||
mov word ptr [ di ], 5a5ah
|
||||
mov byte ptr [ di + 2 ], 50h
|
||||
mov word ptr [ di + 10h ], 0FFFFh
|
||||
mov word ptr [ di + 12h ], 0FFFFh
|
||||
|
||||
; navratova adresa, kdyby nezabrala ROM
|
||||
mov OfsErr, offset RomErr
|
||||
push cs
|
||||
push offset @@chyba
|
||||
|
||||
mov ax, ROMLOAD
|
||||
mov es, ax
|
||||
push es
|
||||
; kouzelny jump....
|
||||
mov si, es:[ 1ah ]
|
||||
push word ptr es:[ si + 1ah ] ; ...do bootrom v RAM
|
||||
retf
|
||||
|
||||
@@chyba:
|
||||
mov si, OfsErr
|
||||
call @@print
|
||||
mov si, offset CRLF
|
||||
call @@print
|
||||
jmp @@chyba
|
||||
|
||||
@@print:
|
||||
lodsb
|
||||
cmp al,0
|
||||
je @@navrat
|
||||
push si
|
||||
mov bx,7
|
||||
mov ah,0Eh
|
||||
int 10h
|
||||
pop si
|
||||
jmp @@print
|
||||
|
||||
@@navrat:
|
||||
retn
|
||||
|
||||
Hlaska db 13, 10, 'HD Net Loader v1.0 (c) poli 1999', 13, 10, 0
|
||||
CRLF db 13, 10, 0
|
||||
OfsErr dw offset Error
|
||||
Error db 'Error load from HD !', 0
|
||||
RomErr db 'ROM Error !', 0
|
||||
|
||||
mbrasm endp
|
||||
|
||||
mbrend proc
|
||||
ret
|
||||
mbrend endp
|
||||
|
||||
org 800h - 2
|
||||
dw 0AA55h
|
||||
|
||||
end
|
||||
|
||||
===========================================================================
|
||||
This Mail was sent to netboot mailing list by:
|
||||
Petr Olivka <Petr.Olivka@vsb.cz>
|
||||
To get help about this list, send a mail with 'help' as the only string in
|
||||
it's body to majordomo@baghira.han.de. If you have problems with this list,
|
||||
send a mail to netboot-owner@baghira.han.de.
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
mkinitrd-net ChangeLog
|
||||
|
||||
Last Modified: Fri Jul 26 23:08:28 2002
|
||||
|
||||
$Log$
|
||||
Revision 1.1 2005/05/17 16:45:02 mcb30
|
||||
Initial revision
|
||||
|
||||
Revision 1.1 2002/11/06 06:31:06 ken_yap
|
||||
Contributed by Michael Brown.
|
||||
|
||||
Revision 1.10 2002/07/26 23:09:13 mcb30
|
||||
Support for new binary etherboot.nic-dev-id structure
|
||||
Added --kernel option patch from Stew Benedict at MandrakeSoft
|
||||
Only try to use sudo if we are not already root
|
||||
|
||||
Revision 1.9 2002/06/05 13:31:50 mcb30
|
||||
Modifications to allow DHCP, TFTP and NFS servers to be separate machines.
|
||||
|
||||
Revision 1.8 2002/05/30 11:41:18 mcb30
|
||||
/tftpboot symlinked to /var/lib/tftpboot
|
||||
Has ability to be quiet if "quiet" specified on kernel cmdline
|
||||
|
||||
Revision 1.7 2002/05/26 11:15:04 mcb30
|
||||
PCI-ID auto-mapping via dhcpd.conf.etherboot-pcimap.include
|
||||
|
||||
Revision 1.6 2002/05/24 02:05:11 mcb30
|
||||
Bugfixes, migrated /tftpboot to /var/lib/tftpboot
|
||||
|
||||
Revision 1.5 2002/05/23 21:29:58 mcb30
|
||||
Now includes dhcpd.conf.etherboot.include
|
||||
Automatically scans for all network modules in the pcimap file
|
||||
|
||||
Revision 1.4 2002/05/08 09:04:31 mcb30
|
||||
Bugfixes: tmpdir selection, linuxrc typos, ifconfig peculiarities
|
||||
|
||||
Revision 1.3 2002/05/04 21:44:13 mcb30
|
||||
During %make, LIBDIR must be set for mknbi
|
||||
Added %post scriptlet since %trigger seems not to be being triggered...
|
||||
|
||||
Revision 1.2 2002/05/04 21:20:32 mcb30
|
||||
Added extra sources instead of requiring "make" to download them
|
||||
|
||||
Revision 1.1 2002/05/04 13:19:40 mcb30
|
||||
First attempt at an RPM package
|
||||
|
|
@ -0,0 +1,187 @@
|
|||
UCLIBC_VERSION = 0.9.11
|
||||
UCLIBC = uClibc-$(UCLIBC_VERSION)
|
||||
$(UCLIBC)_SOURCE = http://www.uclibc.org/downloads/$(UCLIBC).tar.bz2
|
||||
UCLIBC_INSTALL = $(CURDIR)/uClibc
|
||||
|
||||
UDHCP_VERSION = 0.9.7
|
||||
UDHCP = udhcp-$(UDHCP_VERSION)
|
||||
$(UDHCP)_SOURCE = http://udhcp.busybox.net/source/$(UDHCP).tar.gz
|
||||
|
||||
BUSYBOX_VERSION = 0.60.3
|
||||
BUSYBOX = busybox-$(BUSYBOX_VERSION)
|
||||
$(BUSYBOX)_SOURCE = http://www.busybox.net/downloads/$(BUSYBOX).tar.bz2
|
||||
|
||||
LINUX_WLAN_VERSION = 0.1.13
|
||||
LINUX_WLAN = linux-wlan-ng-$(LINUX_WLAN_VERSION)
|
||||
$(LINUX_WLAN)_SOURCE = ftp://ftp.linux-wlan.org/pub/linux-wlan-ng/$(LINUX_WLAN).tar.gz
|
||||
|
||||
MKNBI_VERSION = 1.2
|
||||
MKNBI = mknbi-$(MKNBI_VERSION)
|
||||
$(MKNBI)_SOURCE = http://belnet.dl.sourceforge.net/sourceforge/etherboot/$(MKNBI).tar.gz
|
||||
|
||||
export PATH := $(UCLIBC_INSTALL)/bin:$(PATH)
|
||||
|
||||
all : utils initrd-skel mknbi mknbi-linux
|
||||
# Run "make tftpboot/initrd-kernel_module.img" to generate a suitable initrd
|
||||
# Run "make tftpboot/boot-kernel_module.nbi" to generate a suitable NBI
|
||||
# Run "make all-nbi" to generate a complete set of NBIs
|
||||
|
||||
%.tar.bz2 :
|
||||
[ -d $* ] || wget $($*_SOURCE)
|
||||
[ -f $*.t*gz ] && ( gunzip $*.t*gz ; bzip2 -9 $*.tar ) || true
|
||||
|
||||
UTILS = udhcpc busybox wlanctl
|
||||
|
||||
utils : $(UTILS)
|
||||
|
||||
clean : partlyclean
|
||||
rm -rf uClibc
|
||||
rm -rf $(UCLIBC)
|
||||
rm -rf tftpboot/*
|
||||
|
||||
partlyclean :
|
||||
rm -rf $(UDHCP)
|
||||
rm -rf $(BUSYBOX)
|
||||
rm -rf $(LINUX_WLAN)
|
||||
rm -rf $(MKNBI)
|
||||
rm -rf initrd-skel
|
||||
rm -f *.img *.ird *.nbi insert-modules
|
||||
rm -f $(UTILS) mknbi-linux
|
||||
rm -f *.uClibc *.busybox *.udhcpc *.wlanctl
|
||||
|
||||
.PHONY : all utils clean partlyclean
|
||||
|
||||
uClibc : $(UCLIBC)
|
||||
rm -rf $@
|
||||
$(MAKE) -C $(UCLIBC) install
|
||||
|
||||
$(UCLIBC) : $(UCLIBC).tar.bz2
|
||||
[ -d $@ ] || tar xvjf $<
|
||||
[ -f $(UCLIBC)/Config ] || perl -pe 's/^(INCLUDE_RPC).*/$$1 = true/ ;' \
|
||||
-e 's{^(DEVEL_PREFIX).*}{$$1 = $(UCLIBC_INSTALL)} ;' \
|
||||
-e 's{^(SHARED_LIB_LOADER_PATH).*}{$$1 = /lib} ;' \
|
||||
$(UCLIBC)/extra/Configs/Config.i386 > $(UCLIBC)/Config
|
||||
# Stripping out spurious CVS directories (screws up local cvs update)
|
||||
rm -rf `find $(UCLIBC) -name CVS`
|
||||
$(MAKE) -C $(UCLIBC)
|
||||
install -m 644 $(UCLIBC)/COPYING.LIB COPYING.uClibc
|
||||
|
||||
udhcpc : $(UDHCP)
|
||||
install -m 755 -s $(UDHCP)/$@ $@
|
||||
|
||||
$(UDHCP) : $(UDHCP).tar.bz2 uClibc
|
||||
[ -d $@ ] || tar xvjf $<
|
||||
if [ ! -f $@/.script.c.patch ]; then \
|
||||
patch -d $@ -b -z .orig < script.c.patch ; \
|
||||
touch $@/.script.c.patch ; \
|
||||
fi
|
||||
$(MAKE) LDFLAGS+=-static -C $(UDHCP)
|
||||
install -m 644 $(UDHCP)/AUTHORS AUTHORS.udhcpc
|
||||
install -m 644 $(UDHCP)/COPYING COPYING.udhcpc
|
||||
|
||||
busybox : $(BUSYBOX)
|
||||
install -m 755 -s $(BUSYBOX)/$@ $@
|
||||
|
||||
$(BUSYBOX) : $(BUSYBOX).tar.bz2 uClibc
|
||||
[ -d $@ ] || tar xvjf $<
|
||||
perl -pi.orig -e \
|
||||
's/^.*(#define BB_(FEATURE_NFSMOUNT|INSMOD|PIVOT_ROOT|IFCONFIG|ROUTE)).*/$$1/' \
|
||||
$(BUSYBOX)/Config.h
|
||||
perl -pi.orig -e \
|
||||
's/^(DOSTATIC).*$$/$$1 = true/' \
|
||||
$(BUSYBOX)/Makefile
|
||||
$(MAKE) -C $(BUSYBOX)
|
||||
install -m 644 $(BUSYBOX)/AUTHORS AUTHORS.busybox
|
||||
install -m 644 $(BUSYBOX)/LICENSE LICENSE.busybox
|
||||
|
||||
wlanctl : $(LINUX_WLAN)
|
||||
install -m 755 -s $(LINUX_WLAN)/src/wlanctl/$@ $@
|
||||
|
||||
$(LINUX_WLAN) : $(LINUX_WLAN).tar.bz2 uClibc linux-wlan.cfg
|
||||
[ -d $@ ] || tar xvjf $<
|
||||
cd $(LINUX_WLAN) ; ./Configure -d ../linux-wlan.cfg
|
||||
perl -pi.orig -e \
|
||||
's/(-o wlanctl)/-static $$1/' \
|
||||
$(LINUX_WLAN)/src/wlanctl/Makefile
|
||||
$(MAKE) -C $(LINUX_WLAN)/src/wlanctl
|
||||
install -m 644 $(LINUX_WLAN)/COPYING COPYING.wlanctl
|
||||
install -m 644 $(LINUX_WLAN)/LICENSE LICENSE.wlanctl
|
||||
install -m 644 $(LINUX_WLAN)/THANKS THANKS.wlanctl
|
||||
|
||||
mknbi-linux : $(MKNBI)
|
||||
|
||||
mknbi : $(MKNBI)
|
||||
|
||||
$(MKNBI) : $(MKNBI).tar.bz2
|
||||
[ -d $@ ] || tar xvjf $<
|
||||
if [ ! -f $@/.mknbi-encap.patch ]; then \
|
||||
patch -d $@ -b -z .orig < mknbi-encap.patch ; \
|
||||
touch $@/.mknbi-encap.patch ; \
|
||||
fi
|
||||
make -C $(MKNBI) LIBDIR=`pwd`/$(MKNBI) mknbi
|
||||
install -m 755 $(MKNBI)/mknbi mknbi-linux
|
||||
make -C $(MKNBI) clean
|
||||
make -C $(MKNBI)
|
||||
|
||||
initrd-skel : $(UTILS) linuxrc udhcpc-post include-modules
|
||||
rm -rf $@
|
||||
mkdir -p $@
|
||||
mkdir -p $@/dev
|
||||
mkdir -p $@/etc
|
||||
mkdir -p $@/bin
|
||||
mkdir -p $@/lib
|
||||
mkdir -p $@/lib/modules
|
||||
mkdir -p $@/proc
|
||||
mkdir -p $@/sysroot
|
||||
ln -s bin $@/sbin
|
||||
install -m 755 busybox $@/bin/
|
||||
install -m 755 udhcpc $@/bin/
|
||||
install -m 755 wlanctl $@/bin/
|
||||
ln -s busybox $@/bin/sh
|
||||
ln -s busybox $@/bin/echo
|
||||
ln -s busybox $@/bin/mknod
|
||||
ln -s busybox $@/bin/chmod
|
||||
ln -s busybox $@/bin/insmod
|
||||
ln -s busybox $@/bin/ifconfig
|
||||
ln -s busybox $@/bin/route
|
||||
ln -s busybox $@/bin/mount
|
||||
ln -s busybox $@/bin/pivot_root
|
||||
ln -s busybox $@/bin/umount
|
||||
ln -s busybox $@/bin/[
|
||||
ln -s busybox $@/bin/sleep
|
||||
ln -s busybox $@/bin/grep
|
||||
|
||||
install -m 755 linuxrc $@/linuxrc
|
||||
install -m 755 udhcpc-post $@/bin/udhcpc-post
|
||||
|
||||
tftpboot/initrd-%.img : initrd-skel
|
||||
./mkinitrd-net -l `echo $* | tr . " "`
|
||||
|
||||
tftpboot/boot-%.nbi : tftpboot/initrd-%.img mknbi-linux
|
||||
./mknbi-linux --format=nbi --target=linux /boot/vmlinuz $< > $@
|
||||
sudo cp $@ $(tftpbootdir)
|
||||
|
||||
all-nbi : all
|
||||
./mknbi-set -l -v
|
||||
ls tftpboot
|
||||
|
||||
prefix = /usr
|
||||
sysconfdir = /etc
|
||||
bindir = $(prefix)/bin
|
||||
libdir = $(prefix)/lib
|
||||
mandir = $(prefix)/share/man
|
||||
docdir = $(prefix)/share/doc
|
||||
tftpbootdir = /var/lib/tftpboot
|
||||
initrdskeldir = $(prefix)/lib/mkinitrd-net/initrd-skel
|
||||
|
||||
install :
|
||||
mkdir -p $(libdir)/mknbi
|
||||
mkdir -p $(bindir)
|
||||
mkdir -p $(sysconfdir)
|
||||
mkdir -p $(tftpbootdir)
|
||||
mkdir -p $(initrdskeldir)
|
||||
install -m 755 mkinitrd-net include-modules mknbi-set $(bindir)/
|
||||
cp -a initrd-skel/* $(initrdskeldir)/
|
||||
install -m 644 mknbi-set.conf dhcpd.conf.etherboot.include $(sysconfdir)
|
||||
make -C $(MKNBI) INSTPREFIX=$(prefix) MANDIR=$(mandir)/man1 \
|
||||
DOCDIR=$(docdir)/$(MKNBI) install
|
|
@ -0,0 +1,15 @@
|
|||
initrd/ChangeLog
|
||||
initrd/Makefile
|
||||
initrd/Manifest
|
||||
initrd/README
|
||||
initrd/dhcpd.conf.etherboot.include
|
||||
initrd/include-modules
|
||||
initrd/linux-wlan.cfg
|
||||
initrd/linuxrc
|
||||
initrd/mkinitrd-net
|
||||
initrd/mkinitrd-net.spec
|
||||
initrd/mknbi-encap.patch
|
||||
initrd/mknbi-set
|
||||
initrd/mknbi-set.conf
|
||||
initrd/script.c.patch
|
||||
initrd/udhcpc-post
|
|
@ -0,0 +1,37 @@
|
|||
README for mkinitrd-net
|
||||
|
||||
mkinitrd-net enables you to use your distribution's stock kernel for
|
||||
diskless workstations, without having to compile in support for the
|
||||
relevant network card(s). It creates an initial ramdisk image containing
|
||||
the required network-card kernel modules and bootstrap scripts to load the
|
||||
module, obtain an IP address via DHCP and mount the root filesystem via
|
||||
NFS.
|
||||
|
||||
mkinitrd-net also generates a dhcpd.conf file fragment that can be used to
|
||||
automate the process of mapping NBI files to clients, based on the PCI IDs
|
||||
of their network cards. Etherboot will send the PCI ID of the network
|
||||
card to the DHCP server in the etherboot-encapsulated-options field
|
||||
(Etherboot 5.0.7 and newer) and the DHCP server can use this to identify
|
||||
the correct NBI to point the client towards.
|
||||
|
||||
The end result is that:
|
||||
|
||||
a) You can avoid the hassle of compiling custom kernels for diskless
|
||||
workstations.
|
||||
|
||||
b) Diskless workstations will automatically download the correct
|
||||
kernel+initrd.
|
||||
|
||||
c) You have an easier life! :-)
|
||||
|
||||
|
||||
|
||||
mkinitrd-net is Copyright Fen Systems Ltd. 2001. mkinitrd-net itself is
|
||||
licensed under the GNU GPL. It incorporates code from the uClibc,
|
||||
busybox, udhcpc and Etherboot projects, each of which has its own licence
|
||||
terms. Standard disclaimers apply.
|
||||
|
||||
The copy of mkinitrd-net in the Etherboot contribs is not the
|
||||
authoritative copy of mkinitrd-net; please do not make modifications to
|
||||
this copy. Patches should be sent to Michael Brown
|
||||
<mbrown@fensystems.co.uk>.
|
|
@ -0,0 +1,207 @@
|
|||
# dhcpd.conf include file for Etherboot
|
||||
#
|
||||
# Include this file from your /etc/dhcpd.conf
|
||||
# $Id$
|
||||
|
||||
# Definition of Etherboot options
|
||||
# (taken from vendortags.html)
|
||||
|
||||
# We use an encapsulated option space to avoid polluting the site-local DHCP option space
|
||||
#
|
||||
option space etherboot;
|
||||
option etherboot-encapsulated-options code 150 = encapsulate etherboot;
|
||||
|
||||
# Definition of option codes within the etherboot-encapsulated-options space
|
||||
#
|
||||
option etherboot.extensions-path code 18 = string;
|
||||
option etherboot.magic code 128 = string;
|
||||
option etherboot.kernel-cmdline code 129 = string;
|
||||
option etherboot.menu-opts code 160 = string;
|
||||
option etherboot.nic-dev-id code 175 = string;
|
||||
option etherboot.menu-selection code 176 = unsigned integer 8;
|
||||
option etherboot.motd-1 code 184 = string;
|
||||
option etherboot.motd-2 code 185 = string;
|
||||
option etherboot.motd-3 code 186 = string;
|
||||
option etherboot.motd-4 code 187 = string;
|
||||
option etherboot.motd-5 code 188 = string;
|
||||
option etherboot.motd-6 code 189 = string;
|
||||
option etherboot.motd-7 code 190 = string;
|
||||
option etherboot.motd-8 code 191 = string;
|
||||
option etherboot.image-1 code 192 = string;
|
||||
option etherboot.image-2 code 193 = string;
|
||||
option etherboot.image-3 code 194 = string;
|
||||
option etherboot.image-4 code 195 = string;
|
||||
option etherboot.image-5 code 196 = string;
|
||||
option etherboot.image-6 code 197 = string;
|
||||
option etherboot.image-7 code 198 = string;
|
||||
option etherboot.image-8 code 199 = string;
|
||||
option etherboot.image-9 code 200 = string;
|
||||
option etherboot.image-10 code 201 = string;
|
||||
option etherboot.image-11 code 202 = string;
|
||||
option etherboot.image-12 code 203 = string;
|
||||
option etherboot.image-13 code 204 = string;
|
||||
option etherboot.image-14 code 205 = string;
|
||||
option etherboot.image-15 code 206 = string;
|
||||
option etherboot.image-16 code 207 = string;
|
||||
option etherboot.kmod code 254 = string;
|
||||
|
||||
# Legacy support for Etherboot options as site-local options (i.e. non-encapsulated)
|
||||
# Note: options defined after the switch to encapsulated options should not be defined here
|
||||
#
|
||||
option legacy-etherboot-magic code 128 = string;
|
||||
option legacy-etherboot-kernel-cmdline code 129 = string;
|
||||
option legacy-etherboot-menu-opts code 160 = string;
|
||||
option legacy-etherboot-menu-selection code 176 = unsigned integer 8;
|
||||
option legacy-etherboot-motd-1 code 184 = string;
|
||||
option legacy-etherboot-motd-2 code 185 = string;
|
||||
option legacy-etherboot-motd-3 code 186 = string;
|
||||
option legacy-etherboot-motd-4 code 187 = string;
|
||||
option legacy-etherboot-motd-5 code 188 = string;
|
||||
option legacy-etherboot-motd-6 code 189 = string;
|
||||
option legacy-etherboot-motd-7 code 190 = string;
|
||||
option legacy-etherboot-motd-8 code 191 = string;
|
||||
option legacy-etherboot-image-1 code 192 = string;
|
||||
option legacy-etherboot-image-2 code 193 = string;
|
||||
option legacy-etherboot-image-3 code 194 = string;
|
||||
option legacy-etherboot-image-4 code 195 = string;
|
||||
option legacy-etherboot-image-5 code 196 = string;
|
||||
option legacy-etherboot-image-6 code 197 = string;
|
||||
option legacy-etherboot-image-7 code 198 = string;
|
||||
option legacy-etherboot-image-8 code 199 = string;
|
||||
option legacy-etherboot-image-9 code 200 = string;
|
||||
option legacy-etherboot-image-10 code 201 = string;
|
||||
option legacy-etherboot-image-11 code 202 = string;
|
||||
option legacy-etherboot-image-12 code 203 = string;
|
||||
option legacy-etherboot-image-13 code 204 = string;
|
||||
option legacy-etherboot-image-14 code 205 = string;
|
||||
option legacy-etherboot-image-15 code 206 = string;
|
||||
option legacy-etherboot-image-16 code 207 = string;
|
||||
|
||||
# Apply Etherboot options only for Etherboot clients
|
||||
#
|
||||
if substring ( option vendor-class-identifier, 0, 9 ) = "Etherboot" {
|
||||
|
||||
# We must specify this value for etherboot-magic, or Etherboot will
|
||||
# ignore all other options.
|
||||
#
|
||||
option etherboot.magic E4:45:74:68:00:00;
|
||||
|
||||
# Bootfile name: derive from etherboot.kmod (calculated below)
|
||||
# Use boot.nbi if no NIC_DEV_ID option present
|
||||
# (i.e. if etherboot.kmod doesn't get set)
|
||||
# Also pass filename back in filename field
|
||||
#
|
||||
option bootfile-name = pick-first-value ( concat ( "boot-",
|
||||
config-option etherboot.kmod,
|
||||
".nbi" ),
|
||||
"boot.nbi" ) ;
|
||||
filename = config-option bootfile-name;
|
||||
|
||||
# "Sensible" default values for some options
|
||||
|
||||
# Mount devfs (will probably be needed for a network-boot)
|
||||
option etherboot.kernel-cmdline " devfs=mount";
|
||||
|
||||
# Info message (includes client IP address, MAC address, hardware ID string,
|
||||
# server IP address and name of boot file)
|
||||
option etherboot.motd-4 = concat ( "Using Etherboot to boot ",
|
||||
binary-to-ascii ( 10, 8, ".", leased-address ),
|
||||
" [",
|
||||
binary-to-ascii ( 16, 8, ":", suffix ( hardware, 6 ) ),
|
||||
"] [",
|
||||
pick-first-value ( option etherboot.nic-dev-id, "unknown card" ),
|
||||
"]", 0d:0a, " from ",
|
||||
binary-to-ascii ( 10, 8, ".", option dhcp-server-identifier ),
|
||||
" with file ",
|
||||
config-option tftp-server-name,
|
||||
":",
|
||||
config-option bootfile-name,
|
||||
" [",
|
||||
pick-first-value ( config-option etherboot.kmod, "unknown module" ),
|
||||
"]", 0d:0a );
|
||||
|
||||
# Legacy site-local option support
|
||||
# If client does not include an etherboot-encapsulated-options field in its DHCPREQUEST, then
|
||||
# it will not understand etherboot-encapsulated-options in the DHCPACK and so we must send
|
||||
# back the options as site-local options (i.e. not encapsulated).
|
||||
# Note: we need do this only for options that existed prior to the switch to encapsulation.
|
||||
#
|
||||
if not exists etherboot-encapsulated-options {
|
||||
option legacy-etherboot-magic = config-option etherboot.magic;
|
||||
option legacy-etherboot-kernel-cmdline = config-option etherboot.kernel-cmdline;
|
||||
option legacy-etherboot-menu-opts = config-option etherboot.menu-opts;
|
||||
option legacy-etherboot-menu-selection = config-option etherboot.menu-selection;
|
||||
option legacy-etherboot-motd-1 = config-option etherboot.motd-1;
|
||||
option legacy-etherboot-motd-2 = config-option etherboot.motd-2;
|
||||
option legacy-etherboot-motd-3 = config-option etherboot.motd-3;
|
||||
option legacy-etherboot-motd-4 = config-option etherboot.motd-4;
|
||||
option legacy-etherboot-motd-5 = config-option etherboot.motd-5;
|
||||
option legacy-etherboot-motd-6 = config-option etherboot.motd-6;
|
||||
option legacy-etherboot-motd-7 = config-option etherboot.motd-7;
|
||||
option legacy-etherboot-motd-8 = config-option etherboot.motd-8;
|
||||
option legacy-etherboot-image-1 = config-option etherboot.image-1;
|
||||
option legacy-etherboot-image-2 = config-option etherboot.image-2;
|
||||
option legacy-etherboot-image-3 = config-option etherboot.image-3;
|
||||
option legacy-etherboot-image-4 = config-option etherboot.image-4;
|
||||
option legacy-etherboot-image-5 = config-option etherboot.image-5;
|
||||
option legacy-etherboot-image-6 = config-option etherboot.image-6;
|
||||
option legacy-etherboot-image-7 = config-option etherboot.image-7;
|
||||
option legacy-etherboot-image-8 = config-option etherboot.image-8;
|
||||
option legacy-etherboot-image-9 = config-option etherboot.image-9;
|
||||
option legacy-etherboot-image-10 = config-option etherboot.image-10;
|
||||
option legacy-etherboot-image-11 = config-option etherboot.image-11;
|
||||
option legacy-etherboot-image-12 = config-option etherboot.image-12;
|
||||
option legacy-etherboot-image-13 = config-option etherboot.image-13;
|
||||
option legacy-etherboot-image-14 = config-option etherboot.image-14;
|
||||
option legacy-etherboot-image-15 = config-option etherboot.image-15;
|
||||
option legacy-etherboot-image-16 = config-option etherboot.image-16;
|
||||
}
|
||||
}
|
||||
|
||||
# Some options should be set for both Etherboot and the udhcpc client
|
||||
#
|
||||
if ( ( substring ( option vendor-class-identifier, 0, 9 ) = "Etherboot" )
|
||||
or ( substring ( option vendor-class-identifier, 0, 5 ) = "udhcp" ) ) {
|
||||
|
||||
# TFTP server defaults to DHCP server and is specified in both
|
||||
# next-server field and tftp-server-name option field
|
||||
#
|
||||
option tftp-server-name = binary-to-ascii ( 10, 8, ".", config-option dhcp-server-identifier );
|
||||
server-name = config-option tftp-server-name;
|
||||
next-server = config-option dhcp-server-identifier;
|
||||
|
||||
# Root path defaults to root of TFTP server
|
||||
option root-path = concat ( config-option tftp-server-name, ":/" );
|
||||
|
||||
# A fallback hostname, generated from the IP address
|
||||
option host-name = concat ( "client_", binary-to-ascii ( 10, 8, "_", leased-address ) );
|
||||
}
|
||||
|
||||
# Force some items onto parameter request list for udhcp
|
||||
#
|
||||
if substring ( option vendor-class-identifier, 0, 5 ) = "udhcp" {
|
||||
# Forcibly add root-path to list
|
||||
option dhcp-parameter-request-list = concat ( option dhcp-parameter-request-list, 11 );
|
||||
}
|
||||
|
||||
# Etherboot sends a string to identify the NIC in etherboot.nic-dev-id.
|
||||
# For PCI NICs, this string is of the form "PCI:vvvv:dddd" where vvvv is the
|
||||
# vendor identifier and dddd the device identifier, in lower-case ASCII hex.
|
||||
# For ISA NICs, the format of the string is "ISA:..." where ... is not yet
|
||||
# decided upon.
|
||||
#
|
||||
# We use the identifier to select the NBI image that will be specified via
|
||||
# the "bootfile-name" option.
|
||||
#
|
||||
# PCI NICs - use PCI vendor and device IDs
|
||||
# Listed in file generated by mknbi-set
|
||||
#
|
||||
include "/etc/dhcpd.conf.etherboot-pcimap.include";
|
||||
|
||||
# ISA NICs
|
||||
#
|
||||
if substring ( option vendor-class-identifier, 0, 9 ) = "Etherboot" {
|
||||
if exists etherboot.nic-dev-id {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
#!/usr/bin/perl -w
|
||||
#
|
||||
# Retrieve modules required for an initrd image
|
||||
# $Id$
|
||||
|
||||
unless ( @ARGV ) {
|
||||
die "Syntax: $0 [ -d target_directory ] module_1 module_2 module_3\n"
|
||||
}
|
||||
|
||||
# Parse command line arguments
|
||||
my @requested_modules = ();
|
||||
my $target_dir = "";
|
||||
my $kernel_ver;
|
||||
my $quiet;
|
||||
chomp ( my $current_kernel_ver = `uname -r` );
|
||||
while ( $_ = shift ) {
|
||||
if ( /-d/ ) { $target_dir = shift }
|
||||
elsif ( /-k/ ) { $kernel_ver = shift }
|
||||
elsif ( /-q/ ) { $quiet = 1 }
|
||||
else { push @requested_modules, $_ };
|
||||
}
|
||||
|
||||
# Create target directory if required
|
||||
if ( $target_dir ) {
|
||||
print STDERR "Target directory is $target_dir\n" unless $quiet;
|
||||
system ( "mkdir -p $target_dir" );
|
||||
chdir $target_dir;
|
||||
}
|
||||
|
||||
# Use modprobe -nav to retrieve locations of modules and their dependencies
|
||||
print STDERR "Requested modules ". join (' ', @requested_modules)."\n" unless $quiet;
|
||||
my @modules_dups;
|
||||
foreach my $module ( @requested_modules ) {
|
||||
my @module_list = map { /^\S+\s+(.*)$/ ; $1 } `/sbin/modprobe -nva $module`;
|
||||
die "Cannot find any modules matching $module\n" unless @module_list;
|
||||
push @modules_dups, @module_list;
|
||||
}
|
||||
|
||||
# Remove duplicates from list
|
||||
my %module_basenames = ();
|
||||
my @modules = ();
|
||||
foreach my $module ( @modules_dups ) {
|
||||
# Ugly hack : assume that dependencies are independent of kernel version
|
||||
# This seems to be necessary because we can't run modprobe and specify
|
||||
# an alternate modules.dep file; it refuses to understand lines of the
|
||||
# form "depfile=XXX" as documented in modules.conf(5)
|
||||
$module =~ s/$current_kernel_ver/$kernel_ver/ if $kernel_ver;
|
||||
push @modules, $module unless $module_basenames{$module};
|
||||
( my $basename ) = ( $module =~ /([^\/]+)\.o/ );
|
||||
$module_basenames{$module} = $basename;
|
||||
}
|
||||
|
||||
# Process module list
|
||||
print "#!/bin/sh\n";
|
||||
foreach my $module ( @modules ) {
|
||||
my $basename = $module_basenames{$module};
|
||||
# Report via stdout
|
||||
print STDERR "Using module $basename from $module\n" unless $quiet;
|
||||
# Copy uncompressed module to current directory
|
||||
system ("gunzip -c $module > $basename.o");
|
||||
# Print insmod line to stdout
|
||||
print "insmod $basename\n";
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
# Dummy config file for building only wlanctl
|
||||
# $Id$
|
||||
|
||||
PRISM2_PLX=n
|
||||
PRISM2_PCMCIA=n
|
||||
PRISM2_PCI=n
|
||||
PRISM2_USB=n
|
|
@ -0,0 +1,76 @@
|
|||
#!/bin/sh
|
||||
# $Id$
|
||||
|
||||
PATH=/sbin:/bin
|
||||
|
||||
echo Busybox /linuxrc starting
|
||||
|
||||
echo Mounting /proc filesystem
|
||||
mount -t proc none /proc
|
||||
|
||||
echo=echo
|
||||
if grep '\bquiet\b' /proc/cmdline > /dev/null; then
|
||||
echo=true
|
||||
quiet=1
|
||||
fi
|
||||
|
||||
$echo Creating root device
|
||||
mknod /dev/root b 1 0 2>/dev/null
|
||||
chmod 700 /dev/root
|
||||
echo 0x100 > /proc/sys/kernel/real-root-dev
|
||||
|
||||
$echo Inserting modules
|
||||
if [ -z "$quiet" ]; then
|
||||
/bin/insert-modules
|
||||
else
|
||||
/bin/insert-modules >/dev/null
|
||||
fi
|
||||
|
||||
$echo Bringing up loopback interface
|
||||
ifconfig lo 127.0.0.1 up
|
||||
route add -net 127.0.0.0 netmask 255.0.0.0 lo
|
||||
|
||||
# Hack required for prism2 cards
|
||||
# It is not yet possible to use iwconfig to configure these cards,
|
||||
# so we need wlanctl.
|
||||
if ifconfig wlan0 down 2> /dev/null; then
|
||||
$echo Setting up wireless link
|
||||
wlanctl wlan0 lnxreq_ifstate ifstate=enable
|
||||
wlanctl wlan0 lnxreq_autojoin ssid= authtype=opensystem
|
||||
fi
|
||||
|
||||
$echo Obtaining IP address via DHCP
|
||||
$echo Trying to obtain IP address via wired link [eth0]
|
||||
if udhcpc -i eth0 -f -n -q -s /bin/udhcpc-post; then
|
||||
$echo Successfully obtained IP address via wired link [eth0]
|
||||
else
|
||||
$echo Failed to obtain IP address via wired link [eth0]
|
||||
$echo Trying to obtain IP address via wireless link [wlan0]
|
||||
udhcpc -i wlan0 -f -n -q -s /bin/udhcpc-post
|
||||
fi
|
||||
|
||||
if [ -d /sysroot/initrd ]; then
|
||||
$echo Unmounting /proc prior to pivot_root
|
||||
umount /proc
|
||||
|
||||
$echo Pivoting root to /sysroot
|
||||
pivot_root /sysroot /sysroot/initrd
|
||||
cd /
|
||||
|
||||
$echo Remounting devfs at correct place
|
||||
mount -t devfs none /dev
|
||||
|
||||
$echo Releasing locks on old devfs
|
||||
exec 0</dev/null
|
||||
exec 1>/dev/console
|
||||
exec 2>/dev/console
|
||||
|
||||
$echo Unmounting old devfs
|
||||
umount /initrd/dev
|
||||
else
|
||||
# Failed to mount root: report error and hang
|
||||
echo FATAL ERROR: Failed to mount root filesystem
|
||||
echo Press Alt-SysRq-B or hit the reset switch to reboot
|
||||
while : ; do sleep 6000 ; done
|
||||
fi
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# $Id$
|
||||
# initrd builder for network booting
|
||||
|
||||
# Utility function to determine whether or not a filesystem is usable for
|
||||
# loopback mounts. Lifted verbatim from Erik Troan's mkinitrd script.
|
||||
#
|
||||
is_good_fs() {
|
||||
local parttype= tmpname=
|
||||
local dir=$1
|
||||
[[ -d $dir ]] || return 1
|
||||
[[ -w $dir ]] || return 1
|
||||
[[ $dir == */ ]] && dir=${dir%/}
|
||||
parttype=$(awk "{if (\$2 == \""$dir"\") print \$3 }" /proc/mounts)
|
||||
|
||||
while tmpname=${dir%/*} && [[ -z $parttype ]];do
|
||||
[[ -z $tmpname ]] && tmpname=/
|
||||
parttype=$(awk "{if (\$2 == \""$tmpname"\") print \$3 }" /proc/mounts)
|
||||
dir=$tmpname
|
||||
done
|
||||
|
||||
case $parttype in
|
||||
nfs|tmpfs) return 1;;
|
||||
*) return 0;
|
||||
esac
|
||||
}
|
||||
|
||||
# Find a suitable temporary directory (i.e. not tmpfs or nfs)
|
||||
if is_good_fs $TMPDIR; then
|
||||
tmpdir=$TMPDIR
|
||||
elif is_good_fs /tmp; then
|
||||
tmpdir=/tmp
|
||||
elif is_good_fs /var/tmp; then
|
||||
tmpdir=/var/tmp
|
||||
elif is_good_fs /root/tmp; then
|
||||
tmpdir=/root/tmp
|
||||
else
|
||||
echo "Cannot use a tmp directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Default settings (some can be overridden by command-line options)
|
||||
include_modules=include-modules
|
||||
initrd_skel=/usr/lib/mkinitrd-net/initrd-skel
|
||||
kernel_ver=`uname -r`
|
||||
use_sudo=y
|
||||
keep=n
|
||||
output_dir=/var/lib/tftpboot
|
||||
make_link=y
|
||||
quiet=
|
||||
|
||||
# No need to use sudo if we are root
|
||||
if [ $UID -eq 0 ]; then
|
||||
use_sudo=n
|
||||
fi
|
||||
|
||||
USAGE="Usage: $0 [-k|--kernel <kernel_ver>] [-n|--nolink] [-q|--quiet] [-l|--local] [--nosudo] [--keep] [--help] module_list ..."
|
||||
|
||||
# Parse command-line options
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-l|--local)
|
||||
shift
|
||||
use_local=y ;;
|
||||
-k|--kernel)
|
||||
shift
|
||||
kernel_ver=$1
|
||||
shift ;;
|
||||
--nosudo) shift ; use_sudo=n ;;
|
||||
--keep) shift ; keep=y ;;
|
||||
--n|--nolink)
|
||||
shift ; make_link=n ;;
|
||||
-q|--quiet) shift ; quiet=-q ;;
|
||||
--help) shift ; do_help=y ;;
|
||||
--) shift ; break ;;
|
||||
-*) echo "${0}: ${1}: invalid option" >&2
|
||||
echo $USAGE >& 2
|
||||
exit 2 ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Build list of requested modules
|
||||
modules="$*"
|
||||
requested_modules="$modules"
|
||||
modules="$modules nfs" # Always require nfs for nfs mount
|
||||
modules="$modules af_packet" # Always require af_packet for udhcpc
|
||||
|
||||
# --help => Print help message
|
||||
if [ "$do_help" == "y" ]; then
|
||||
echo $USAGE
|
||||
echo " -k, --kernel Specify kernel version"
|
||||
echo " -n, --nolink Do not create a matching symbolic link"
|
||||
echo " -l, --local Run locally from CVS (for developers only)"
|
||||
echo " --nosudo Do not use sudo (i.e. must run as root instead)"
|
||||
echo " --keep Keep temporary files instead of deleting them"
|
||||
exit 0;
|
||||
fi
|
||||
|
||||
# --local => we are running directly from CVS, rather than
|
||||
# from an installed copy, so use local files and directories
|
||||
if [ "$use_local" == "y" ]; then
|
||||
include_modules=./include-modules
|
||||
initrd_skel=initrd-skel
|
||||
output_dir=tftpboot
|
||||
fi
|
||||
|
||||
# If use_sudo is set, check that sudo exists
|
||||
sudo=/usr/bin/sudo
|
||||
if [ "$use_sudo" == "y" ]; then
|
||||
if [ ! -x $sudo ]; then
|
||||
use_sudo=n
|
||||
echo "WARNING: --nosudo not specified but $sudo not found"
|
||||
fi
|
||||
fi
|
||||
if [ "$use_sudo" == "n" ]; then
|
||||
sudo=
|
||||
fi
|
||||
|
||||
# Create temporary working files
|
||||
initrd=`mktemp -d ${tmpdir}/initrd.XXXXXX`
|
||||
initrdimg=`mktemp ${tmpdir}/initrd.img.XXXXXX`
|
||||
initrdmnt=`mktemp -d ${tmpdir}/initrd.mnt.XXXXXX`
|
||||
|
||||
# Copy skeleton into temporary area
|
||||
cp -a $initrd_skel/* $initrd/
|
||||
mkdir -p $initrd/lib/modules/$kernel_ver
|
||||
$include_modules $quiet -k $kernel_ver -d $initrd/lib/modules/$kernel_ver $modules > $initrd/bin/insert-modules || exit 1
|
||||
chmod 755 $initrd/bin/insert-modules
|
||||
|
||||
# Create empty ext2fs image file
|
||||
dd if=/dev/zero bs=1k of=$initrdimg count=$((`du -sk $initrd | cut -f1` * 7 / 6)) 2> /dev/null
|
||||
/sbin/mke2fs -q -F $initrdimg 2> /dev/null
|
||||
|
||||
# Mount image file, copy files on, create /dev entries, display free space, umount
|
||||
$sudo mount -o loop $initrdimg $initrdmnt
|
||||
cp -a $initrd/* $initrdmnt/
|
||||
$sudo mknod $initrdmnt/dev/console c 5 1
|
||||
$sudo mknod $initrdmnt/dev/null c 1 3
|
||||
$sudo mknod $initrdmnt/dev/ram b 1 1
|
||||
$sudo mknod $initrdmnt/dev/systty c 4 0
|
||||
for i in 1 2 3 4; do $sudo mknod $initrdmnt/dev/tty$i c 4 $i; done
|
||||
if [ "$quiet" == "n" ]; then
|
||||
df -h $initrdmnt
|
||||
fi
|
||||
$sudo umount $initrdmnt
|
||||
|
||||
# Create output file
|
||||
initrd_suffix=`echo $requested_modules | tr " " .`
|
||||
gzip -9 -n -c $initrdimg > $output_dir/initrd-$initrd_suffix.$kernel_ver.img
|
||||
|
||||
# Create symlink
|
||||
if [ "$make_link" == "y" ]; then
|
||||
link=$output_dir/initrd-$initrd_suffix.img
|
||||
[ -L $link ] && rm -f $link
|
||||
ln -s initrd-$initrd_suffix.$kernel_ver.img $link
|
||||
fi
|
||||
|
||||
# Remove temporary files
|
||||
if [ "$keep" == "n" ]; then
|
||||
rm -rf $initrd
|
||||
rm -f $initrdimg
|
||||
rmdir $initrdmnt
|
||||
fi
|
|
@ -0,0 +1,112 @@
|
|||
%define name mkinitrd-net
|
||||
%define version 1.10
|
||||
%define release 1fs
|
||||
|
||||
Summary: Network-booting initrd builder
|
||||
Name: %{name}
|
||||
Version: %{version}
|
||||
Release: %{release}
|
||||
Source0: %{name}-%{version}.tar.bz2
|
||||
Source1: http://belnet.dl.sourceforge.net/sourceforge/etherboot/mknbi-1.2.tar.bz2
|
||||
Source2: http://www.busybox.net/downloads/busybox-0.60.3.tar.bz2
|
||||
Source3: http://www.uclibc.org/downloads/uClibc-0.9.11.tar.bz2
|
||||
Source4: ftp://ftp.linux-wlan.org/pub/linux-wlan-ng/linux-wlan-ng-0.1.13.tar.bz2
|
||||
Source5: http://udhcp.busybox.net/source/udhcp-0.9.7.tar.bz2
|
||||
Copyright: GPL/LGPL/MPL
|
||||
Group: System/Kernel and hardware
|
||||
BuildRoot: %{_tmppath}/%{name}-buildroot
|
||||
Prefix: %{_prefix}
|
||||
Requires: tftp-server
|
||||
|
||||
%description
|
||||
mkinitrd-net allows you to build initial ramdisk images (initrds) suitable
|
||||
for use with Etherboot and other network-booting software. This package
|
||||
contains two main utilities: mkinitrd-net (to build an initrd containing a
|
||||
specified set of network-card modules) and mknbi (to generate
|
||||
Etherboot-usable NBI images from a given kernel and initrd). It also
|
||||
contains a helper script mknbi-set which will maintain sets of initrds to
|
||||
match all your currently-installed kernels.
|
||||
|
||||
mkinitrd-net uses code from the uClibc, busybox, udhcp and Etherboot
|
||||
projects.
|
||||
|
||||
%prep
|
||||
%setup -n initrd -a1 -a2 -a3 -a4 -a5
|
||||
|
||||
%build
|
||||
%make LIBDIR=%{_libdir}/mknbi
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
%makeinstall tftpbootdir=$RPM_BUILD_ROOT%{_localstatedir}/tftpboot
|
||||
touch $RPM_BUILD_ROOT%{_sysconfdir}/dhcpd.conf.etherboot-pcimap.include
|
||||
ln -s %{_localstatedir}/tftpboot $RPM_BUILD_ROOT/tftpboot
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%post
|
||||
%{_bindir}/mknbi-set
|
||||
|
||||
%triggerin -- kernel kernel-smp kernel-secure kernel-enterprise
|
||||
%{_bindir}/mknbi-set
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
%config(noreplace) %{_sysconfdir}/mknbi-set.conf
|
||||
%config(noreplace) %{_sysconfdir}/dhcpd.conf.etherboot.include
|
||||
%ghost %{_sysconfdir}/dhcpd.conf.etherboot-pcimap.include
|
||||
%{_bindir}/mknbi-*
|
||||
%{_bindir}/mkelf-*
|
||||
%{_bindir}/dis*
|
||||
%{_bindir}/mkinitrd-net
|
||||
%{_bindir}/include-modules
|
||||
%{_libdir}/mknbi
|
||||
%{_libdir}/mkinitrd-net
|
||||
%{_mandir}/man*/*
|
||||
/tftpboot
|
||||
%{_localstatedir}/tftpboot
|
||||
%doc README
|
||||
%doc AUTHORS.busybox LICENSE.busybox
|
||||
%doc AUTHORS.udhcpc COPYING.udhcpc
|
||||
%doc COPYING.wlanctl LICENSE.wlanctl THANKS.wlanctl
|
||||
%doc COPYING.uClibc
|
||||
%docdir %{_docdir}/mknbi*
|
||||
%{_docdir}/mknbi*
|
||||
|
||||
%changelog
|
||||
* Fri Jul 26 2002 Michael Brown <mbrown@fensystems.co.uk> 1.10-1fs
|
||||
- Support for new binary etherboot.nic-dev-id structure
|
||||
- Added --kernel option patch from Stew Benedict at MandrakeSoft
|
||||
- Only try to use sudo if we are not already root
|
||||
|
||||
* Wed Jun 05 2002 Michael Brown <mbrown@fensystems.co.uk> 1.9-1fs
|
||||
- Modifications to allow DHCP, TFTP and NFS servers to be separate machines.
|
||||
|
||||
* Thu May 30 2002 Michael Brown <mbrown@fensystems.co.uk> 1.8-1fs
|
||||
- /tftpboot symlinked to /var/lib/tftpboot
|
||||
- Has ability to be quiet if "quiet" specified on kernel cmdline
|
||||
|
||||
* Sun May 26 2002 Michael Brown <mbrown@fensystems.co.uk> 1.7-1fs
|
||||
- PCI-ID auto-mapping via dhcpd.conf.etherboot-pcimap.include
|
||||
|
||||
* Fri May 24 2002 Michael Brown <mbrown@fensystems.co.uk> 1.6-1fs
|
||||
- Bugfixes, migrated /tftpboot to /var/lib/tftpboot
|
||||
|
||||
* Thu May 23 2002 Michael Brown <mbrown@fensystems.co.uk> 1.5-1fs
|
||||
- Now includes dhcpd.conf.etherboot.include
|
||||
- Automatically scans for all network modules in the pcimap file
|
||||
|
||||
* Wed May 08 2002 Michael Brown <mbrown@fensystems.co.uk> 1.4-1fs
|
||||
- Bugfixes: tmpdir selection, linuxrc typos, ifconfig peculiarities
|
||||
|
||||
* Sat May 04 2002 Michael Brown <mbrown@fensystems.co.uk> 1.3-1fs
|
||||
- During %make, LIBDIR must be set for mknbi
|
||||
- Added %post scriptlet since %trigger seems not to be being triggered...
|
||||
|
||||
* Sat May 04 2002 Michael Brown <mbrown@fensystems.co.uk> 1.2-1fs
|
||||
- Added extra sources instead of requiring "make" to download them
|
||||
|
||||
* Sat May 04 2002 Michael Brown <mbrown@fensystems.co.uk> 1.1-1fs
|
||||
- First attempt at an RPM package
|
||||
|
|
@ -0,0 +1,200 @@
|
|||
#!/usr/bin/perl -w
|
||||
#
|
||||
# $Id$
|
||||
# Maintains set of NBIs based on currently-installed kernels
|
||||
# Network card module sets are taken from /etc/mknbi-set.conf
|
||||
|
||||
use strict;
|
||||
use vars qw($verbosity);
|
||||
|
||||
use constant EB_PCI_DEVICE => 1;
|
||||
|
||||
# Utility function: calculate output id given a kernel file name and
|
||||
# space-separated list of modules
|
||||
sub calc_output_id ($$) {
|
||||
my $kernel = shift;
|
||||
my $moduleset = shift;
|
||||
my $kernel_ver = "";
|
||||
( $kernel_ver ) = ( $kernel =~ /vmlinuz-(.*)$/ );
|
||||
( my $output_id = "$moduleset".( $kernel_ver ? ".$kernel_ver" : "" ) ) =~ tr/,/./;
|
||||
return ( $kernel_ver, $output_id );
|
||||
}
|
||||
|
||||
# Utility function: read modules.pcimap-style file
|
||||
# Add modules to modulesets hash, write out dhcpd.conf fragment
|
||||
sub read_config_file ($$$$) {
|
||||
my $configfile = shift;
|
||||
my $modulesets = shift;
|
||||
my $dhcpfh = shift;
|
||||
my $alwaysuse = shift;
|
||||
|
||||
print "Scanning through $configfile for network modules...\n" if $verbosity >= 1;
|
||||
open CF, $configfile or die "Could not open $configfile: $!\n";
|
||||
chomp ( my $tempmodule = `mktemp /tmp/mknbi-set.XXXXXX` );
|
||||
chomp ( my $cwd = `pwd` ); chdir '/'; # Modprobe searches the current directory...
|
||||
print $dhcpfh " \# Generated from $configfile\n";
|
||||
while (<CF>) {
|
||||
chomp;
|
||||
next if /^[\#;]/ or /^\s*$/;
|
||||
( my $module, undef, my $vendor, my $device ) = /^(\S+)(\s+(\S+)\s+(\S+))?/ ;
|
||||
$modulesets->{$module} = 1 if $alwaysuse;
|
||||
if ( ! exists $modulesets->{$module} ) {
|
||||
# Check to see if module is a network module
|
||||
# Only do this the first time we encounter a module
|
||||
my @modulepaths = `/sbin/modprobe -l $module.o*` ;
|
||||
chomp ( my $modulepath = $modulepaths[0] );
|
||||
if ( $modulepath ) {
|
||||
if ( $modulepath =~ /.o.gz$/ ) {
|
||||
system ( "zcat $modulepath > $tempmodule" );
|
||||
} else {
|
||||
system ( "cp $modulepath $tempmodule" );
|
||||
}
|
||||
$modulesets->{$module} = 0;
|
||||
foreach ( `nm $tempmodule` ) {
|
||||
chomp;
|
||||
$modulesets->{$module} = 1 if /(ether|wlan)/ ;
|
||||
}
|
||||
unlink $tempmodule;
|
||||
} else {
|
||||
print STDERR "Cannot locate module $module specified in $configfile\n";
|
||||
}
|
||||
}
|
||||
if ( $modulesets->{$module} ) {
|
||||
if ( $vendor ) {
|
||||
print "$module ($vendor,$device) listed in $configfile\n" if $verbosity >= 2;
|
||||
printf $dhcpfh ( " if option etherboot.nic-dev-id = %02x:%02x:%02x:%02x:%02x { option etherboot.kmod \"%s\"; }\n",
|
||||
EB_PCI_DEVICE,
|
||||
( hex($vendor) >> 8 ) & 0xff, hex($vendor) & 0xff,
|
||||
( hex($device) >> 8 ) & 0xff, hex($device) & 0xff,
|
||||
$module );
|
||||
} else {
|
||||
print "$module (without PCI IDs) listed in $configfile\n" if $verbosity >= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
close CF;
|
||||
print $dhcpfh "\n";
|
||||
chdir $cwd;
|
||||
}
|
||||
|
||||
my $conffile = '/etc/mknbi-set.conf';
|
||||
my $mkinitrd_net = 'mkinitrd-net';
|
||||
my $mknbi = 'mknbi-linux';
|
||||
my $output_dir = '/var/lib/tftpboot';
|
||||
my $dhcpfile = '/etc/dhcpd.conf.etherboot-pcimap.include';
|
||||
my $use_local;
|
||||
our $verbosity = 1;
|
||||
my $modulesets = {};
|
||||
my $kernel = '';
|
||||
my @kernels = ();
|
||||
|
||||
my $usage="Usage: $0 [-l|--local] [-q] [-v] [-r|--refresh module[,module...]] [--help]";
|
||||
|
||||
# Parse command-line options
|
||||
while ( $_ = shift ) {
|
||||
if ( /-l|--local/ ) {
|
||||
$conffile = 'mknbi-set.conf';
|
||||
$mkinitrd_net = './mkinitrd-net';
|
||||
$mknbi = './mknbi-linux --format=nbi --target=linux';
|
||||
$output_dir = 'tftpboot';
|
||||
$dhcpfile = 'tftpboot/dhcpd.conf.etherboot-pcimap.include';
|
||||
$use_local = 1;
|
||||
} elsif ( /-r|--refresh/ ) {
|
||||
my $moduleset = shift;
|
||||
$modulesets->{$moduleset} = 1;
|
||||
} elsif ( /-k|--kernel/ ) {
|
||||
$kernel = shift;
|
||||
} elsif ( /-v|--verbose/ ) {
|
||||
$verbosity++;
|
||||
} elsif ( /-q|--quiet/ ) {
|
||||
$verbosity--;
|
||||
} elsif ( /--help/ ) {
|
||||
die "$usage\n".
|
||||
" -k, --kernel Build NBIs for a particular kernel\n".
|
||||
" -l, --local Run locally from CVS (for developers only)\n".
|
||||
" -r, --refresh Refresh NBI for a particular module\n".
|
||||
" -v, --verbose Be more verbose\n".
|
||||
" -q, --quiet Be less verbose\n";
|
||||
} else {
|
||||
die "$usage\n";
|
||||
}
|
||||
}
|
||||
|
||||
# Get set of current kernels
|
||||
if ($kernel) {
|
||||
@kernels = ( $kernel );
|
||||
} else {
|
||||
@kernels = glob('/boot/vmlinuz*');
|
||||
}
|
||||
die "Could not find any kernels in /boot\n" unless @kernels;
|
||||
|
||||
# If modules have been specified via --refresh, do not scan for modules or rewrite the
|
||||
# dhcpd.conf fragment file
|
||||
unless ( %$modulesets ) {
|
||||
# Write dhcpd.conf fragment file
|
||||
open my $dhcpfh, ">$dhcpfile" or die "Could not open $dhcpfile for writing: $!\n";
|
||||
print $dhcpfh "# Etherboot PCI ID -> Linux kernel module mapping file\n";
|
||||
print $dhcpfh "# Generated by mknbi-set on ".(scalar localtime)."\n";
|
||||
print $dhcpfh "#\n";
|
||||
print $dhcpfh "if substring ( option vendor-class-identifier, 0, 9 ) = \"Etherboot\" {\n";
|
||||
print $dhcpfh " if exists etherboot.nic-dev-id {\n";
|
||||
print $dhcpfh " \# Legacy nic-dev-id mechanism: there are some DLink DFE538 cards in circulation that\n";
|
||||
print $dhcpfh " \# predated the change to the new nic-dev-id binary structure\n";
|
||||
print $dhcpfh " if option etherboot.nic-dev-id = \"PCI:1186:1300\" { option etherboot.kmod \"8139too\"; }\n";
|
||||
print $dhcpfh "\n";
|
||||
|
||||
# Get set of network modules to build NBIs for
|
||||
# Read explicitly-specified module sets from $conffile
|
||||
read_config_file($conffile, $modulesets, $dhcpfh, 1);
|
||||
# Obtain list of all network modules from pcimap file
|
||||
my $pcimap;
|
||||
foreach ( `/sbin/modprobe -c` ) {
|
||||
$pcimap = $1 if /^pcimap.*?=(.*)$/;
|
||||
}
|
||||
if ( $pcimap ) {
|
||||
read_config_file($pcimap, $modulesets, $dhcpfh, 0);
|
||||
} else {
|
||||
print STDERR "Could not identify pcimap file\n";
|
||||
}
|
||||
# Finish off dhcpd.conf fragment file
|
||||
print $dhcpfh " }\n}\n";
|
||||
close $dhcpfh;
|
||||
}
|
||||
|
||||
# Build initrd and nbi for each kernel-moduleset combination
|
||||
foreach my $moduleset ( sort keys %$modulesets ) {
|
||||
next unless $modulesets->{$moduleset}; # Ignore if value is 0
|
||||
print "Building NBIs for module set $moduleset\n" if $verbosity >= 1;
|
||||
foreach my $kernel ( @kernels ) {
|
||||
( my $kernel_ver, my $output_id ) = calc_output_id ( $kernel, $moduleset );
|
||||
if ( -l $kernel ) {
|
||||
# Symbolic link; create matching symlink
|
||||
my $real_kernel = readlink ( $kernel );
|
||||
( my $real_kernel_ver, my $real_output_id ) = calc_output_id ( $real_kernel, $moduleset );
|
||||
print "Symlinking $output_id to $real_output_id\n" if $verbosity >= 2;
|
||||
my $initrd_file = "$output_dir/initrd-$output_id.img";
|
||||
unlink ( $initrd_file ) if -l $initrd_file;
|
||||
system ( "ln -s initrd-$real_output_id.img $initrd_file" ) == 0 or print STDERR "Could not symlink $initrd_file to initrd-$real_output_id.img: $!\n";
|
||||
my $nbi_file = "$output_dir/boot-$output_id.nbi";
|
||||
unlink ( $nbi_file ) if -l $nbi_file;
|
||||
system ( "ln -s boot-$real_output_id.nbi $nbi_file" ) == 0 or print STDERR "Could not symlink $nbi_file to boot-$real_output_id.nbi: $!\n";
|
||||
} else {
|
||||
# Real file: create initrd and nbi
|
||||
print "Creating initrd and nbi for $output_id\n" if $verbosity >= 2;
|
||||
( my $moduleset_spaces = $moduleset ) =~ tr/,/ /;
|
||||
my $initrd_cmd = "$mkinitrd_net --nolink ".
|
||||
( $use_local ? "--local " : "" ).
|
||||
( $kernel_ver ? "--kernel $kernel_ver " : "" ).
|
||||
( $verbosity >= 2 ? "" : "-q " ).
|
||||
$moduleset_spaces;
|
||||
print "$initrd_cmd\n" if $verbosity >= 3;
|
||||
if ( system ( $initrd_cmd ) == 0 ) {
|
||||
my $mknbi_cmd = "$mknbi $kernel $output_dir/initrd-$output_id.img > $output_dir/boot-$output_id.nbi";
|
||||
print "$mknbi_cmd\n" if $verbosity >= 3;
|
||||
system ( $mknbi_cmd ) == 0 or print STDERR "mknbi failed: $!\n";
|
||||
} else {
|
||||
print STDERR "$initrd_cmd failed: $!\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
# This file specifies the network cards for which NBI images should be built
|
||||
# Each line contains a list of kernel modules to be used, separated by commas
|
||||
# You can optionally specify PCI vendor and device IDs that should be automatically
|
||||
# mapped to this module.
|
||||
#
|
||||
# The format is similar to modutils' modules.pcimap file.
|
||||
#
|
||||
# Examples:
|
||||
# RTL8139-based ethernet card
|
||||
; 8139too
|
||||
# RTL8139-based ethernet card with PCI IDs vendor=0x1186, device=0x1300
|
||||
; 8139too 0x1186 0x1300
|
||||
# RTL8139 and Prism2_pci in same image
|
||||
; 8139too,prism2_pci
|
||||
|
||||
# Some modules do not include the MODULE_DEVICE_TABLE macro, and so end up not
|
||||
# being listed in the pcimap file. These modules are included here to force
|
||||
# the creation of corresponding initrds.
|
||||
prism2_pci 0x1260 0x3873
|
||||
prism2_plx 0x1638 0x1100
|
||||
prism2_plx 0x16ab 0x1101
|
||||
prism2_plx 0x16ab 0x1102
|
||||
prism2_plx 0x1385 0x4100
|
||||
prism2_plx 0x15e8 0x0130
|
||||
prism2_plx 0x16ec 0x3685
|
||||
prism2_plx 0x16ab 0x1102
|
||||
prism2_plx 0x15e8 0x0131
|
|
@ -0,0 +1,11 @@
|
|||
--- script.c.orig Tue Apr 2 23:49:33 2002
|
||||
+++ script.c Wed Jun 5 14:17:22 2002
|
||||
@@ -179,7 +179,7 @@
|
||||
}
|
||||
if (packet->siaddr) {
|
||||
envp[j] = malloc(sizeof("siaddr=255.255.255.255"));
|
||||
- sprintip(envp[j++], "siaddr=", (unsigned char *) &packet->yiaddr);
|
||||
+ sprintip(envp[j++], "siaddr=", (unsigned char *) &packet->siaddr);
|
||||
}
|
||||
if (!(over & FILE_FIELD) && packet->file[0]) {
|
||||
/* watch out for invalid packets */
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/sh
|
||||
# $Id$
|
||||
|
||||
if [ "$1" = "deconfig" ]; then
|
||||
ifconfig $interface 0.0.0.0 up
|
||||
else if [ "$1" = "bound" ] ; then
|
||||
echo UDHCPC: I am $ip [$hostname], booting from $serverid
|
||||
[ -n "$hostname" ] && echo $hostname > /proc/sys/kernel/hostname
|
||||
[ -n "$broadcast" ] && BROADCAST="broadcast $broadcast"
|
||||
[ -n "$subnet" ] && NETMASK="netmask $subnet"
|
||||
ifconfig $interface $ip $BROADCAST $NETMASK
|
||||
route add default gw $router dev $interface
|
||||
echo -n > /etc/resolv.conf
|
||||
for i in $dns; do
|
||||
echo nameserver $i >> /etc/resolv.conf
|
||||
done
|
||||
[ -n "$siaddr" ] || siaddr=$serverid
|
||||
[ -n "$rootpath" ] || rootpath=$siaddr:/
|
||||
echo Mounting root filesystem $rootpath at /sysroot
|
||||
echo If this appears to hang, check that the server of $rootpath is able to
|
||||
echo reverse-map my IP address $ip to obtain my hostname $hostname
|
||||
mount -t nfs -o nolock,rsize=8192,wsize=8192 $rootpath /sysroot
|
||||
fi
|
||||
fi
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
Xref: news.nsw.CSIRO.AU comp.os.linux.announce:2827
|
||||
Path: news.nsw.CSIRO.AU!metro!metro!munnari.OZ.AU!news.ecn.uoknor.edu!news.wildstar.net!news.ececs.uc.edu!newsrelay.netins.net!newsfeed.dacom.co.kr!arclight.uoregon.edu!feed1.news.erols.com!howland.erols.net!newsfeed.internetmci.com!in3.uu.net!liw.clinet.fi!usenet
|
||||
From: schoebel@informatik.uni-stuttgart.de (Thomas Schoebel-Theuer)
|
||||
Newsgroups: comp.os.linux.announce
|
||||
Subject: linux-2.0.21-transname - Patch for easier pool administration
|
||||
Followup-To: comp.os.linux.misc
|
||||
Date: 30 Oct 1996 10:53:38 GMT
|
||||
Organization: Informatik, Uni Stuttgart, Germany
|
||||
Lines: 76
|
||||
Approved: linux-announce@news.ornl.gov (Lars Wirzenius)
|
||||
Message-ID: <pgpmoose.199610301253.4416@liw>
|
||||
NNTP-Posting-Host: liw
|
||||
X-Auth: PGPMoose V1.1 PGP comp.os.linux.announce
|
||||
iQBVAwUBMnczrjiesvPHtqnBAQEO6gH/WRtFpTPyVtwi0cFVPZ1Xhn8cvfb6i3mk
|
||||
LQY2kgpAPquP2TeXYWb5Ta3HxqK15pR1AgaEy5BmPS6+66ixZFvKRQ==
|
||||
=hhea
|
||||
|
||||
-----BEGIN PGP SIGNED MESSAGE-----
|
||||
|
||||
linux-2.0.21-transname.patch enables diskless clients, X-terminals etc to
|
||||
mount the *root filesystem* of the server. This makes administration of
|
||||
large pools *a lot* easier.
|
||||
|
||||
Currently different diskless clients must have their root "/" on different
|
||||
directories on the server, beause each client has _some_ different
|
||||
configuration files. However, most administration files (typically about 99%)
|
||||
have the same contents on the clients and on the server, but have to be
|
||||
(and maintained separately) just because of the 1% differences.
|
||||
|
||||
This duplication causes very large efforts in practice, since at least
|
||||
the /etc directory has to be duplicated for every client. Even in /etc
|
||||
many files are identical, for example sendmail.cf, initrc scripts and
|
||||
others. Maintaining a large pool means to ensure coherence amoung the
|
||||
duplicates. Classical methods like symlinks are unconvenient
|
||||
for this task because they have to be valid in the view of mounted
|
||||
filesystems at the client, not at the server.
|
||||
|
||||
linux-2.0-transname.patch overcomes this problem by allowing filenames
|
||||
to be context-dependend. For example, if you have a file "/etc/config"
|
||||
that should differ on the hosts "myserver" and "myclient", you just
|
||||
create two different files named "/etc/config#host=myserver#" and
|
||||
"/etc/config#host=myclient#". On host "myserver", the file
|
||||
"/etc/config#host=myserver#" will appear as if it were hardlinked to
|
||||
file "/etc/config" (without the #...=...# suffix). On host "myclient",
|
||||
the corresponding other file will appear as "/etc/config". So you
|
||||
can access the right file contents under the same name, depending
|
||||
on which host you are.
|
||||
|
||||
As a result, you may use different contexts for e.g. /etc/fstab, but
|
||||
have one shared /etc/passwd for all pool machines. So you don't need
|
||||
yp or NYS any more.
|
||||
|
||||
The kernel patch was developped for and is used at our Linux pool at the
|
||||
University of Stuttgart with good results. Maintainance of the pool is
|
||||
at a minimum, and adding new clients is a child's play. No worry with
|
||||
keeping up mail configurations, newly installed tools, changed /etc/services,
|
||||
/etc/shells, /etc/resolv.conf and many, many others. In contrast to a
|
||||
sophisticated symlink solution, adding a new file to the /etc directory
|
||||
is seen immediately by all clients. I never had less trouble with
|
||||
administration before.
|
||||
|
||||
I just uploaded the patch to
|
||||
ftp://ftp.lmh.ox.ac.uk
|
||||
where it should appear in /pub/linux-kernel-patch-archive/
|
||||
and also to
|
||||
ftp://sunsite.unc.edu/pub/Linux/Incoming/
|
||||
where it should be moved to /pub/Linux/kernel/patches/misc/ soon.
|
||||
|
||||
More details can be found in the README there, and also in the
|
||||
configure-help.
|
||||
|
||||
Enjoy,
|
||||
|
||||
- -- Thomas
|
||||
|
||||
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: 2.6.3i
|
||||
Charset: noconv
|
||||
|
||||
iQCVAwUBMnczhYQRll5MupLRAQHzuwP9HGYa4I3bZpt22Y3oQIwEKZGfvnaS5AaD
|
||||
fVG8wOQ/T7Nrant9JtTktsTVlxGVlYVnziRY4c0ew2qExapK9FqY/ItN0NJXy5aT
|
||||
a4eSkn86rp6Un7m90RK1xVY5AyVAq49Rdw2StGxr7uj+davnmg3Np+U0MiAILq91
|
||||
52jKGaR3fvc=
|
||||
=LSD6
|
||||
-----END PGP SIGNATURE-----
|
||||
|
||||
--
|
||||
This article has been digitally signed by the moderator, using PGP.
|
||||
http://www.iki.fi/liw/lars-public-key.asc has PGP key for validating signature.
|
||||
Send submissions for comp.os.linux.announce to: linux-announce@news.ornl.gov
|
||||
PLEASE remember a short description of the software and the LOCATION.
|
||||
This group is archived at http://www.iki.fi/liw/linux/cola.html
|
|
@ -0,0 +1,24 @@
|
|||
diff -Naur linux.orig/drivers/net/3c503.c linux/drivers/net/3c503.c
|
||||
--- linux.orig/drivers/net/3c503.c Thu Feb 19 23:14:04 1998
|
||||
+++ linux/drivers/net/3c503.c Thu Feb 19 23:16:24 1998
|
||||
@@ -179,7 +179,8 @@
|
||||
for both the old and new 3Com prefix */
|
||||
outb(ECNTRL_SAPROM|ECNTRL_THIN, ioaddr + 0x406);
|
||||
vendor_id = inb(ioaddr)*0x10000 + inb(ioaddr + 1)*0x100 + inb(ioaddr + 2);
|
||||
- if ((vendor_id != OLD_3COM_ID) && (vendor_id != NEW_3COM_ID)) {
|
||||
+ if ((vendor_id != OLD_3COM_ID) && (vendor_id != NEW_3COM_ID) &&
|
||||
+ (vendor_id != BULL_3COM_ID)) {
|
||||
/* Restore the register we frobbed. */
|
||||
outb(saved_406, ioaddr + 0x406);
|
||||
return ENODEV;
|
||||
diff -Naur linux.orig/drivers/net/3c503.h linux/drivers/net/3c503.h
|
||||
--- linux.orig/drivers/net/3c503.h Thu Feb 19 23:14:05 1998
|
||||
+++ linux/drivers/net/3c503.h Mon Feb 16 11:41:56 1998
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#define OLD_3COM_ID 0x02608c
|
||||
#define NEW_3COM_ID 0x0020af
|
||||
+#define BULL_3COM_ID 0x000062
|
||||
|
||||
/* Shared memory management parameters. NB: The 8 bit cards have only
|
||||
one bank (MB1) which serves both Tx and Rx packet space. The 16bit
|
|
@ -0,0 +1,7 @@
|
|||
As part of determining whether a 3c503 is present, the Linux driver
|
||||
examines the first 3 bytes of the ethernet address (the vendor ID)
|
||||
to see if it corresponds to a known 3Com vendor ID.
|
||||
|
||||
The Bull discless 386 workstation I have (don't laugh) has an
|
||||
unknown vendor ID 0x000062. This trivial patch adds it to those
|
||||
known to the driver.
|
|
@ -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.
|
|
@ -0,0 +1,8 @@
|
|||
CC=gcc
|
||||
CFLAGS=-Wall -O2
|
||||
|
||||
mini-slamd: mini-slamd.c
|
||||
$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f mini-slamd
|
|
@ -0,0 +1,521 @@
|
|||
/*
|
||||
* mini-slamd
|
||||
* (c) 2002 Eric Biederman
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/in.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
/*
|
||||
* To specify the default interface for multicast packets use:
|
||||
* route add -net 224.0.0.0 netmask 240.0.0.0 dev eth1
|
||||
* This server is stupid and does not override the default.
|
||||
*/
|
||||
|
||||
/* Sever states.
|
||||
*
|
||||
* Waiting for clients.
|
||||
* Sending data to clients.
|
||||
* Pinging clients for data.
|
||||
*
|
||||
*/
|
||||
#define SLAM_PORT 10000
|
||||
#define SLAM_MULTICAST_IP ((239<<24)|(255<<16)|(1<<8)|(1<<0))
|
||||
#define SLAM_MULTICAST_PORT 10000
|
||||
#define SLAM_MULTICAST_TTL 1
|
||||
#define SLAM_MULTICAST_LOOPBACK 1
|
||||
#define SLAM_MAX_CLIENTS 10
|
||||
|
||||
#define SLAM_PING_TIMEOUT 100 /* ms */
|
||||
|
||||
/*** Packets Formats ***
|
||||
* Data Packet:
|
||||
* transaction
|
||||
* total bytes
|
||||
* block size
|
||||
* packet #
|
||||
* data
|
||||
*
|
||||
* Status Request Packet
|
||||
* transaction
|
||||
* total bytes
|
||||
* block packets
|
||||
*
|
||||
* Status Packet
|
||||
* received packets
|
||||
* requested packets
|
||||
* received packets
|
||||
* requested packets
|
||||
* ...
|
||||
* received packets
|
||||
* requested packtes
|
||||
* 0
|
||||
*/
|
||||
|
||||
#define MAX_HDR (7 + 7 + 7) /* transaction, total size, block size */
|
||||
#define MIN_HDR (1 + 1 + 1) /* transaction, total size, block size */
|
||||
|
||||
#define MAX_DATA_HDR (MAX_HDR + 7) /* header, packet # */
|
||||
#define MIN_DATA_HDR (MAX_HDR + 1) /* header, packet # */
|
||||
|
||||
/* ETH_MAX_MTU 1500 - sizeof(iphdr) 20 - sizeof(udphdr) 8 = 1472 */
|
||||
#define SLAM_MAX_NACK (1500 - (20 + 8))
|
||||
/* ETH_MAX_MTU 1500 - sizeof(iphdr) 20 - sizeof(udphdr) 8 - MAX_HDR = 1451 */
|
||||
#define SLAM_BLOCK_SIZE (1500 - (20 + 8 + MAX_HDR))
|
||||
|
||||
|
||||
/* Define how many debug messages you want
|
||||
* 1 - sparse but useful
|
||||
* 2 - everything
|
||||
*/
|
||||
#ifndef DEBUG
|
||||
#define DEBUG 0
|
||||
#endif
|
||||
|
||||
static int slam_encode(
|
||||
unsigned char **ptr, unsigned char *end, unsigned long value)
|
||||
{
|
||||
unsigned char *data = *ptr;
|
||||
int bytes;
|
||||
bytes = sizeof(value);
|
||||
while ((bytes > 0) && ((0xff & (value >> ((bytes -1)<<3))) == 0)) {
|
||||
bytes--;
|
||||
}
|
||||
if (bytes <= 0) {
|
||||
bytes = 1;
|
||||
}
|
||||
if (data + bytes >= end) {
|
||||
return -1;
|
||||
}
|
||||
if ((0xe0 & (value >> ((bytes -1)<<3))) == 0) {
|
||||
/* packed together */
|
||||
*data = (bytes << 5) | (value >> ((bytes -1)<<3));
|
||||
} else {
|
||||
bytes++;
|
||||
*data = (bytes << 5);
|
||||
}
|
||||
bytes--;
|
||||
data++;
|
||||
while(bytes) {
|
||||
*(data++) = 0xff & (value >> ((bytes -1)<<3));
|
||||
bytes--;
|
||||
}
|
||||
*ptr = data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long slam_decode(unsigned char **ptr, unsigned char *end, int *err)
|
||||
{
|
||||
unsigned long value;
|
||||
unsigned bytes;
|
||||
if (*ptr >= end) {
|
||||
*err = -1;
|
||||
}
|
||||
bytes = ((**ptr) >> 5) & 7;
|
||||
if ((bytes == 0) || (bytes > sizeof(unsigned long))) {
|
||||
*err = -1;
|
||||
return 0;
|
||||
}
|
||||
if ((*ptr) + bytes >= end) {
|
||||
*err = -1;
|
||||
}
|
||||
value = (**ptr) & 0x1f;
|
||||
bytes--;
|
||||
(*ptr)++;
|
||||
while(bytes) {
|
||||
value <<= 8;
|
||||
value |= **ptr;
|
||||
(*ptr)++;
|
||||
bytes--;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
static struct sockaddr_in client[SLAM_MAX_CLIENTS];
|
||||
static int clients;
|
||||
|
||||
|
||||
void del_client(struct sockaddr_in *old)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < clients; i++) {
|
||||
if ((client[i].sin_family == old->sin_family) &&
|
||||
(client[i].sin_addr.s_addr == old->sin_addr.s_addr) &&
|
||||
(client[i].sin_port == old->sin_port)) {
|
||||
memmove(&client[i], &client[i+1],
|
||||
(clients - (i+1))*sizeof(client[0]));
|
||||
clients--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void add_client(struct sockaddr_in *new)
|
||||
{
|
||||
del_client(new);
|
||||
if (clients >= SLAM_MAX_CLIENTS)
|
||||
return;
|
||||
memcpy(&client[clients], new, sizeof(*new));
|
||||
clients++;
|
||||
}
|
||||
|
||||
void push_client(struct sockaddr_in *new)
|
||||
{
|
||||
del_client(new);
|
||||
if (clients >= SLAM_MAX_CLIENTS) {
|
||||
clients--;
|
||||
}
|
||||
memmove(&client[1], &client[0], clients*sizeof(*new));
|
||||
memcpy(&client[0], new, sizeof(*new));
|
||||
clients++;
|
||||
}
|
||||
|
||||
|
||||
void next_client(struct sockaddr_in *next)
|
||||
{
|
||||
/* Find the next client we want to ping next */
|
||||
if (!clients) {
|
||||
next->sin_family = AF_UNSPEC;
|
||||
return;
|
||||
}
|
||||
/* Return the first client */
|
||||
memcpy(next, &client[0], sizeof(*next));
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *filename;
|
||||
uint8_t nack_packet[SLAM_MAX_NACK];
|
||||
int nack_len;
|
||||
uint8_t request_packet[MAX_HDR];
|
||||
int request_len;
|
||||
uint8_t data_packet[MAX_DATA_HDR + SLAM_BLOCK_SIZE];
|
||||
int data_len;
|
||||
uint8_t *ptr, *end;
|
||||
struct sockaddr_in master_client;
|
||||
struct sockaddr_in sa_src;
|
||||
struct sockaddr_in sa_mcast;
|
||||
uint8_t mcast_ttl;
|
||||
uint8_t mcast_loop;
|
||||
int sockfd, filefd;
|
||||
int result;
|
||||
struct pollfd fds[1];
|
||||
int state;
|
||||
#define STATE_PINGING 1
|
||||
#define STATE_WAITING 2
|
||||
#define STATE_RECEIVING 3
|
||||
#define STATE_TRANSMITTING 4
|
||||
off_t size;
|
||||
struct stat st;
|
||||
uint64_t transaction;
|
||||
unsigned long packet;
|
||||
unsigned long packet_count;
|
||||
unsigned slam_port, slam_multicast_port;
|
||||
struct in_addr slam_multicast_ip;
|
||||
|
||||
slam_port = SLAM_PORT;
|
||||
slam_multicast_port = SLAM_MULTICAST_PORT;
|
||||
slam_multicast_ip.s_addr = htonl(SLAM_MULTICAST_IP);
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Bad argument count\n");
|
||||
fprintf(stderr, "Usage: mini-slamd filename\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
filename = argv[1];
|
||||
filefd = -1;
|
||||
size = 0;
|
||||
transaction = 0;
|
||||
|
||||
/* Setup the udp socket */
|
||||
sockfd = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (sockfd < 0) {
|
||||
fprintf(stderr, "Cannot create socket\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
memset(&sa_src, 0, sizeof(sa_src));
|
||||
sa_src.sin_family = AF_INET;
|
||||
sa_src.sin_port = htons(slam_port);
|
||||
sa_src.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
result = bind(sockfd, &sa_src, sizeof(sa_src));
|
||||
if (result < 0) {
|
||||
fprintf(stderr, "Cannot bind socket to port %d\n",
|
||||
ntohs(sa_src.sin_port));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Setup the multicast transmission address */
|
||||
memset(&sa_mcast, 0, sizeof(sa_mcast));
|
||||
sa_mcast.sin_family = AF_INET;
|
||||
sa_mcast.sin_port = htons(slam_multicast_port);
|
||||
sa_mcast.sin_addr.s_addr = slam_multicast_ip.s_addr;
|
||||
if (!IN_MULTICAST(ntohl(sa_mcast.sin_addr.s_addr))) {
|
||||
fprintf(stderr, "Not a multicast ip\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Set the multicast ttl */
|
||||
mcast_ttl = SLAM_MULTICAST_TTL;
|
||||
setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL,
|
||||
&mcast_ttl, sizeof(mcast_ttl));
|
||||
|
||||
/* Set the multicast loopback status */
|
||||
mcast_loop = SLAM_MULTICAST_LOOPBACK;
|
||||
setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &mcast_loop, sizeof(mcast_loop));
|
||||
|
||||
|
||||
state = STATE_WAITING;
|
||||
packet = 0;
|
||||
packet_count = 0;
|
||||
fds[0].fd = sockfd;
|
||||
fds[0].events = POLLIN;
|
||||
fds[0].revents = 0;
|
||||
for(;;) {
|
||||
switch(state) {
|
||||
case STATE_PINGING:
|
||||
state = STATE_WAITING;
|
||||
next_client(&master_client);
|
||||
if (master_client.sin_family == AF_UNSPEC) {
|
||||
break;
|
||||
}
|
||||
#if DEBUG
|
||||
printf("Pinging %s:%d\n",
|
||||
inet_ntoa(master_client.sin_addr),
|
||||
ntohs(master_client.sin_port));
|
||||
fflush(stdout);
|
||||
#endif
|
||||
|
||||
/* Prepare the request packet, it is all header */
|
||||
ptr = request_packet;
|
||||
end = &request_packet[sizeof(request_packet) -1];
|
||||
slam_encode(&ptr, end, transaction);
|
||||
slam_encode(&ptr, end, size);
|
||||
slam_encode(&ptr, end, SLAM_BLOCK_SIZE);
|
||||
request_len = ptr - request_packet;
|
||||
|
||||
result = sendto(sockfd, request_packet, request_len, 0,
|
||||
&master_client, sizeof(master_client));
|
||||
/* Forget the client I just asked, when the reply
|
||||
* comes in we will remember it again.
|
||||
*/
|
||||
del_client(&master_client);
|
||||
break;
|
||||
case STATE_WAITING:
|
||||
{
|
||||
int timeout;
|
||||
int from_len;
|
||||
timeout = -1;
|
||||
if (master_client.sin_family != AF_UNSPEC) {
|
||||
timeout = SLAM_PING_TIMEOUT;
|
||||
}
|
||||
result = poll(fds, sizeof(fds)/sizeof(fds[0]), timeout);
|
||||
if (result == 0) {
|
||||
/* On a timeout try the next client */
|
||||
state = STATE_PINGING;
|
||||
break;
|
||||
}
|
||||
if (result > 0) {
|
||||
from_len = sizeof(master_client);
|
||||
result = recvfrom(sockfd,
|
||||
nack_packet, sizeof(nack_packet), 0,
|
||||
&master_client, &from_len);
|
||||
if (result < 0)
|
||||
break;
|
||||
nack_len = result;
|
||||
#if DEBUG
|
||||
printf("Received Nack from %s:%d\n",
|
||||
inet_ntoa(master_client.sin_addr),
|
||||
ntohs(master_client.sin_port));
|
||||
fflush(stdout);
|
||||
#endif
|
||||
#if DEBUG
|
||||
{
|
||||
ptr = nack_packet;
|
||||
end = ptr + result;
|
||||
packet = 0;
|
||||
result = 0;
|
||||
while(ptr < end) {
|
||||
packet += slam_decode(&ptr, end, &result);
|
||||
if (result < 0) break;
|
||||
packet_count = slam_decode(&ptr, end, &result);
|
||||
if (result < 0) break;
|
||||
printf("%d-%d ",
|
||||
packet, packet + packet_count -1);
|
||||
}
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
#endif
|
||||
/* Forget this client temporarily.
|
||||
* If the packet appears good they will be
|
||||
* readded.
|
||||
*/
|
||||
del_client(&master_client);
|
||||
ptr = nack_packet;
|
||||
end = ptr + nack_len;
|
||||
result = 0;
|
||||
packet = slam_decode(&ptr, end, &result);
|
||||
if (result < 0)
|
||||
break;
|
||||
packet_count = slam_decode(&ptr, end, &result);
|
||||
if (result < 0)
|
||||
break;
|
||||
/* We appear to have a good packet, keep
|
||||
* this client.
|
||||
*/
|
||||
push_client(&master_client);
|
||||
|
||||
/* Reopen the file to transmit */
|
||||
if (filefd != -1) {
|
||||
close(filefd);
|
||||
}
|
||||
filefd = open(filename, O_RDONLY);
|
||||
if (filefd < 0) {
|
||||
fprintf(stderr, "Cannot open %s: %s\n",
|
||||
filename, strerror(errno));
|
||||
break;
|
||||
}
|
||||
size = lseek(filefd, 0, SEEK_END);
|
||||
if (size < 0) {
|
||||
fprintf(stderr, "Seek failed on %s: %s\n",
|
||||
filename, strerror(errno));
|
||||
break;
|
||||
}
|
||||
result = fstat(filefd, &st);
|
||||
if (result < 0) {
|
||||
fprintf(stderr, "Stat failed on %s: %s\n",
|
||||
filename, strerror(errno));
|
||||
break;
|
||||
}
|
||||
transaction = st.st_mtime;
|
||||
|
||||
state = STATE_TRANSMITTING;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case STATE_RECEIVING:
|
||||
/* Now clear the queue of received packets */
|
||||
{
|
||||
struct sockaddr_in from;
|
||||
int from_len;
|
||||
uint8_t dummy_packet[SLAM_MAX_NACK];
|
||||
state = STATE_TRANSMITTING;
|
||||
result = poll(fds, sizeof(fds)/sizeof(fds[0]), 0);
|
||||
if (result < 1)
|
||||
break;
|
||||
from_len = sizeof(from);
|
||||
result = recvfrom(sockfd,
|
||||
dummy_packet, sizeof(dummy_packet), 0,
|
||||
&from, &from_len);
|
||||
if (result <= 0)
|
||||
break;
|
||||
#if DEBUG
|
||||
printf("Received Nack from %s:%d\n",
|
||||
inet_ntoa(from.sin_addr),
|
||||
ntohs(from.sin_port));
|
||||
fflush(stdout);
|
||||
#endif
|
||||
/* Receive packets until I don't get any more */
|
||||
state = STATE_RECEIVING;
|
||||
/* Process a packet */
|
||||
if (dummy_packet[0] == '\0') {
|
||||
/* If the first byte is null it is a disconnect
|
||||
* packet.
|
||||
*/
|
||||
del_client(&from);
|
||||
}
|
||||
else {
|
||||
/* Otherwise attempt to add the client. */
|
||||
add_client(&from);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case STATE_TRANSMITTING:
|
||||
{
|
||||
off_t off;
|
||||
off_t offset;
|
||||
ssize_t bytes;
|
||||
uint8_t *ptr2, *end2;
|
||||
|
||||
/* After I transmit a packet check for packets to receive. */
|
||||
state = STATE_RECEIVING;
|
||||
|
||||
/* Find the packet to transmit */
|
||||
offset = packet * SLAM_BLOCK_SIZE;
|
||||
|
||||
/* Seek to the desired packet */
|
||||
off = lseek(filefd, offset, SEEK_SET);
|
||||
if ((off < 0) || (off != offset)) {
|
||||
fprintf(stderr, "Seek failed on %s:%s\n",
|
||||
filename, strerror(errno));
|
||||
break;
|
||||
}
|
||||
/* Encode the packet header */
|
||||
ptr2 = data_packet;
|
||||
end2 = data_packet + sizeof(data_packet);
|
||||
slam_encode(&ptr2, end2, transaction);
|
||||
slam_encode(&ptr2, end2, size);
|
||||
slam_encode(&ptr2, end2, SLAM_BLOCK_SIZE);
|
||||
slam_encode(&ptr2, end2, packet);
|
||||
data_len = ptr2 - data_packet;
|
||||
|
||||
/* Read in the data */
|
||||
bytes = read(filefd, &data_packet[data_len],
|
||||
SLAM_BLOCK_SIZE);
|
||||
if (bytes <= 0) {
|
||||
fprintf(stderr, "Read failed on %s:%s\n",
|
||||
filename, strerror(errno));
|
||||
break;
|
||||
}
|
||||
data_len += bytes;
|
||||
/* Write out the data */
|
||||
result = sendto(sockfd, data_packet, data_len, 0,
|
||||
&sa_mcast, sizeof(sa_mcast));
|
||||
if (result != data_len) {
|
||||
fprintf(stderr, "Send failed %s\n",
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
#if DEBUG > 1
|
||||
printf("Transmitted: %d\n", packet);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
/* Compute the next packet */
|
||||
packet++;
|
||||
packet_count--;
|
||||
if (packet_count == 0) {
|
||||
packet += slam_decode(&ptr, end, &result);
|
||||
if (result >= 0)
|
||||
packet_count = slam_decode(&ptr, end, &result);
|
||||
if (result < 0) {
|
||||
/* When a transmission is done close the file,
|
||||
* so it may be updated. And then ping then start
|
||||
* pinging clients to get the transmission started
|
||||
* again.
|
||||
*/
|
||||
state = STATE_PINGING;
|
||||
close(filefd);
|
||||
filefd = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
# Makefile for the mkQNXnbi filter
|
||||
|
||||
all: mkQNXnbi
|
||||
|
||||
mkQNXnbi: mkQNXnbi.o
|
||||
|
||||
mkQNXnbi.o: mkQNXnbi.c
|
||||
|
||||
clean:
|
||||
rm -f mkQNXnbi *.o
|
|
@ -0,0 +1,36 @@
|
|||
mkQNXnbi is a quick hack to generate tagged images from QNX boot images.
|
||||
|
||||
To boot a QNX client with Etherboot you have to consider the following:
|
||||
1. You MUST have another QNX box running in the network to provide the
|
||||
root filesystem and the license info to the client. QNX cannot use
|
||||
e.g. NFS for its root filesystem, as it needs to load a valid license
|
||||
from a file on the root fs before being able to start TCP/IP. This
|
||||
would lead to a chicken-and-egg problem.
|
||||
2. The Net task normally determines the size of its internal tables from
|
||||
the actual number of licensed nodes. Since this information is not
|
||||
available at boot time when booting from the network, you will have
|
||||
to set the max. number of nodes as well as a valid netmap entry for
|
||||
the node providing the root filesystem as an option to Net in the
|
||||
build file.
|
||||
See examples/ws.etherboot and fill in the <blanks>.
|
||||
3. The client does not need a TCP/IP license in order to boot.
|
||||
4. You can use the boot-server OS of your choice. If you choose to use
|
||||
QNX as boot server, the server of course needs a TCP/IP run-time
|
||||
license. In this case you have the option of creating the boot image
|
||||
on-the-fly and use the macro $(netmap) instead of a hard-coded MAC
|
||||
address.
|
||||
See examples/ws.etherboot.on-the-fly and fill in the <blanks>.
|
||||
A template bootptab for the QNX bootp server is placed in the
|
||||
examples directory.
|
||||
5. mkQNXnbi expects the QNX image to be supplied on stdin and generates
|
||||
the tagged image to stdout. This can be overridden on the command line
|
||||
using the options -i <input-file> and -o <output-file>.
|
||||
|
||||
mkQNXnbi can be compiled using e.g. Linux/gcc or on QNX using Watcom C
|
||||
(or gcc, if you have it - see http://w3c.teaser.fr/~jcmichot/)
|
||||
|
||||
Bug-reports to <al@alarsen.net>
|
||||
|
||||
2002-01-25
|
||||
Anders Larsen
|
||||
<al@alarsen.net>
|
|
@ -0,0 +1,29 @@
|
|||
# /etc/bootptab: database for QNX bootp server (/etc/bootpd)
|
||||
|
||||
# First, we define a global entry which specifies the stuff every host uses.
|
||||
global:\
|
||||
:hd=/boot:\
|
||||
:ht=ethernet:\
|
||||
:sm=<your netmask here>:\
|
||||
:bf=|cd /boot; buildqnx -b 0x10000 build/<your build-file here> | mkQNXnbi:\
|
||||
:hn:
|
||||
|
||||
# node 2 uses the default build-file
|
||||
node2:\
|
||||
:tc=global:\
|
||||
:ha=<your MAC here>:\
|
||||
:ip=<your IP address here>:
|
||||
|
||||
# node 3 uses its own build-file
|
||||
node3:\
|
||||
:tc=global:\
|
||||
:ha=<your MAC here>:\
|
||||
:ip=<your IP address here>:\
|
||||
:bf=|cd /boot; buildqnx -b 0x10000 build/<your build-file here> | mkQNXnbi:
|
||||
|
||||
# node 4 uses a pre-built boot image
|
||||
node3:\
|
||||
:tc=global:\
|
||||
:ha=<your MAC here>:\
|
||||
:ip=<your IP address here>:\
|
||||
:bf=images/<your image-file here>:
|
|
@ -0,0 +1,22 @@
|
|||
# /boot/build/ws.etherboot
|
||||
|
||||
sys/boot
|
||||
$ boot -v
|
||||
|
||||
sys/Proc32
|
||||
$ Proc32 -l <target node number>
|
||||
|
||||
sys/Slib32
|
||||
$ Slib32
|
||||
|
||||
sys/Slib16
|
||||
$ Slib16
|
||||
|
||||
/bin/Net
|
||||
$ Net -n <highest QNX node number in network> -m "<node number of boot server> 1 <MAC of boot server node here>"
|
||||
|
||||
/bin/Net.<network driver>
|
||||
$ Net.<network driver>
|
||||
|
||||
/bin/sinit
|
||||
$ sinit -r //<node number of boot server>/ TERM=<your terminal emulation {QNX|qansi}>
|
|
@ -0,0 +1,22 @@
|
|||
# /boot/build/ws.etherboot.on-the-fly
|
||||
|
||||
sys/boot
|
||||
$ boot -v
|
||||
|
||||
sys/Proc32
|
||||
$ Proc32 -l $(lnode)
|
||||
|
||||
sys/Slib32
|
||||
$ Slib32
|
||||
|
||||
sys/Slib16
|
||||
$ Slib16
|
||||
|
||||
/bin/Net
|
||||
$ Net -n <highest QNX node number in network> -m $(netmap)
|
||||
|
||||
/bin/Net.<network driver>
|
||||
$ Net.<network driver>
|
||||
|
||||
/bin/sinit
|
||||
$ sinit -r //$(bnode)/ TERM=<your terminal emulation {QNX|qansi}>
|
|
@ -0,0 +1,196 @@
|
|||
//*****************************************************************************
|
||||
//
|
||||
// Purpose: Make a boot-image for EtherBoot
|
||||
//
|
||||
//
|
||||
// Compiler: This source can be compiled with gcc and Watcom C
|
||||
//
|
||||
//
|
||||
// Note: The QNX boot image can be build with any reasonable
|
||||
// start address, e.g. 0x1000 (default) or 0x10000
|
||||
// (widespread Boot-Rom address)
|
||||
//
|
||||
//
|
||||
// Author: Anders Larsen
|
||||
//
|
||||
//
|
||||
// Copyright: (C) 1999 by
|
||||
//
|
||||
// Anders Larsen
|
||||
// systems engineer
|
||||
// Gutleuthausstr. 3
|
||||
// D-69469 Weinheim
|
||||
// Germany
|
||||
// phone: +49-6201-961717
|
||||
// fax: +49-6201-961718
|
||||
// e-mail: al@alarsen.net
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Change Log:
|
||||
// V0.2: Sun 1999-12-13 Anders Larsen <al@alarsen.net>
|
||||
//*****************************************************************************
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
// max. size of QNX OS boot image is 512K
|
||||
#define MAXSIZE (512*1024)
|
||||
|
||||
typedef unsigned short ushort_t;
|
||||
typedef unsigned long ulong_t;
|
||||
|
||||
|
||||
// global header of tagged image:
|
||||
struct initial_t
|
||||
{
|
||||
ulong_t magic;
|
||||
ulong_t length;
|
||||
ulong_t location;
|
||||
ulong_t start;
|
||||
};
|
||||
|
||||
|
||||
// header of each image:
|
||||
struct header_t
|
||||
{
|
||||
ulong_t flags;
|
||||
ulong_t loadaddr;
|
||||
ulong_t imgsize;
|
||||
ulong_t memsize;
|
||||
};
|
||||
|
||||
|
||||
// global header of the QNX EtherBoot image:
|
||||
struct qnx_loader_t
|
||||
{
|
||||
struct initial_t setup;
|
||||
struct header_t qnx;
|
||||
};
|
||||
|
||||
|
||||
// global header:
|
||||
union
|
||||
{
|
||||
struct qnx_loader_t h;
|
||||
char filler[512];
|
||||
} header;
|
||||
|
||||
|
||||
char buffer[MAXSIZE];
|
||||
|
||||
|
||||
int usage( char* const* argv )
|
||||
{
|
||||
fprintf( stderr, "%s - make a tagged boot image for EtherBoot\n", *argv );
|
||||
fprintf( stderr, "\nuse:\n" );
|
||||
fprintf( stderr, "%s [ -<option> ]*\n", *argv );
|
||||
fprintf( stderr, "\noptions:\n" );
|
||||
fprintf( stderr, " i <input file> : QNX boot file (default: stdin)\n" );
|
||||
fprintf( stderr, " o <output file> : tagged image file (default: stdout)\n" );
|
||||
fprintf( stderr, " v : be verbose\n" );
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
#ifdef __USAGE
|
||||
%C - make a tagged boot image for EtherBoot
|
||||
|
||||
use:
|
||||
%C [ -<option> ]*
|
||||
|
||||
options:
|
||||
i <input file> : QNX boot file (default: stdin)
|
||||
o <output file> : tagged image file (default: stdout)
|
||||
v : be verbose
|
||||
#endif
|
||||
|
||||
|
||||
int main( int argc, char* const* argv )
|
||||
{
|
||||
int ch, l;
|
||||
int verbose = 0;
|
||||
|
||||
while ( ( ch = getopt( argc, argv, "hi:o:v" ) ) != EOF )
|
||||
switch ( ch )
|
||||
{
|
||||
case 'i':
|
||||
if ( !freopen( optarg, "r", stdin ) )
|
||||
{
|
||||
perror( "can't open input file" );
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
if ( !freopen( optarg, "w", stdout ) )
|
||||
{
|
||||
perror( "can't create output file" );
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
default:
|
||||
return usage( argv );
|
||||
}
|
||||
if ( optind != argc )
|
||||
return usage( argv );
|
||||
|
||||
memset( &header, 0, sizeof header );
|
||||
header.h.setup.magic = 0x1b031336; // magic number
|
||||
header.h.setup.length = 4;
|
||||
header.h.setup.location = 0x93e00000; // just below the EtherBoot rom
|
||||
header.h.setup.start = 0; // filled in dynamically
|
||||
header.h.qnx.flags = 0x04000004; // single image only
|
||||
header.h.qnx.loadaddr = 0; // filled in dynamically
|
||||
header.h.qnx.imgsize = 0; // filled in dynamically
|
||||
header.h.qnx.memsize = 0; // filled in dynamically
|
||||
|
||||
// read the QNX image from stdin:
|
||||
for ( ; ( l = fread( buffer + header.h.qnx.imgsize, 1, 1024, stdin ) ) > 0;
|
||||
header.h.qnx.imgsize += l
|
||||
)
|
||||
;
|
||||
header.h.qnx.memsize = header.h.qnx.imgsize;
|
||||
|
||||
// fill in the real load-address of the QNX boot image:
|
||||
header.h.setup.start = *(ushort_t*)&buffer[10] << 16;
|
||||
header.h.qnx.loadaddr = *(ushort_t*)&buffer[10] << 4;
|
||||
|
||||
// write the tagged image file to stdout:
|
||||
fwrite( &header, 1, 512, stdout );
|
||||
fwrite( buffer, 1, header.h.qnx.imgsize, stdout );
|
||||
|
||||
if ( verbose )
|
||||
{
|
||||
// print diagnostic information:
|
||||
fprintf( stderr, "QNX image size: %d bytes (%dK), load addr: 0x%05X\n",
|
||||
header.h.qnx.imgsize,
|
||||
header.h.qnx.imgsize / 1024,
|
||||
header.h.qnx.loadaddr
|
||||
);
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# floppyfw initfile
|
||||
#
|
||||
# nicked from:
|
||||
# hal91's initfile (/linuxrc), the bootup script of the system
|
||||
#
|
||||
|
||||
VERSION=2.1.6
|
||||
|
||||
load_fsmod () {
|
||||
case $1 in
|
||||
/dev/hd*)
|
||||
insmod ide-cd
|
||||
insmod cdrom
|
||||
;;
|
||||
esac
|
||||
case $2 in
|
||||
vfat)
|
||||
echo vfat support is builtin
|
||||
;;
|
||||
iso9660)
|
||||
insmod isofs
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
#
|
||||
/bin/busybox echo "Booting floppyfw"
|
||||
|
||||
PATH="/bin:/sbin:/usr/bin:/usr/sbin"
|
||||
#PATH="/bin"
|
||||
TERM=linux
|
||||
ignoreeof=10
|
||||
no_exit_on_failed_exec=yes
|
||||
export PATH TERM ignoreeof
|
||||
umask 022
|
||||
|
||||
/bin/busybox echo "mounting: proc"
|
||||
/bin/busybox mount -t proc /proc /proc
|
||||
|
||||
/bin/busybox echo "Generating links. (Thanks to busybox.lineo.com)"
|
||||
/bin/busybox --install -s
|
||||
|
||||
echo "Generated"
|
||||
|
||||
# Modified by Gem, based on coyote distro, changes by Ken Yap
|
||||
ROOTDEV=`sed -e 's/$/ /' -e 's/.*root=\([^ ]*\) .*/\1/' -e 's/,/ /g' -e 's:/dev/nfs:/dev/fd0:' /proc/cmdline`
|
||||
set -- $ROOTDEV
|
||||
# Backward compatibility with a single device argument
|
||||
if [ $# -eq 1 ]
|
||||
then
|
||||
set -- $1 vfat
|
||||
fi
|
||||
while [ "$1" -a "$2" ]
|
||||
do
|
||||
echo "attempting to mount $1 ($2)"
|
||||
load_fsmod $1 $2
|
||||
if mount -t $2 $1 /mnt/tmp
|
||||
then
|
||||
echo "mounted $1 on /mnt/tmp"
|
||||
break
|
||||
fi
|
||||
shift; shift
|
||||
done
|
||||
|
||||
[ -f /mnt/tmp/floppyfw/floppyfw.ini ] && cat /mnt/tmp/floppyfw/floppyfw.ini \
|
||||
| tr -d '\015' >/floppyfw.ini
|
||||
|
||||
[ -f /floppyfw.ini ] && chmod 777 /floppyfw.ini
|
||||
[ -f /floppyfw.ini ] && exec /floppyfw.ini
|
||||
|
||||
echo
|
||||
echo "** floppyfw.ini failed.. starting a shell"
|
||||
echo
|
||||
exec sh
|
|
@ -0,0 +1,43 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
sub status_system ($$) {
|
||||
my ($command, $message) = @_;
|
||||
|
||||
$status = system($command);
|
||||
$status <<= 8;
|
||||
if ($status < 0) {
|
||||
print STDERR "$!\n";
|
||||
}
|
||||
if ($status != 0) {
|
||||
print STDERR "$message\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub extendinitrd ($$) {
|
||||
my ($initrd, $nblocks) = @_;
|
||||
|
||||
if ($nblocks <= 1440) {
|
||||
print STDERR "nblocks must be >= 1440\n";
|
||||
return (1);
|
||||
}
|
||||
(undef, $type, undef, $fnlen, undef) = split(' ', `file $initrd`, 5);
|
||||
print "$type $fnlen\n";
|
||||
if ($type ne 'Minix' || $fnlen != 30) {
|
||||
die "Can only handle Minix initrds with 30 char filenames\n";
|
||||
return (1);
|
||||
}
|
||||
status_system("dd if=/dev/zero of=newinitrd bs=1k count=$nblocks", "Cannot create new initrd\n");
|
||||
status_system("mkfs.minix -n 30 newinitrd $nblocks", "Cannot mkfs.minix new initrd\n");
|
||||
mkdir("initrd.from") || print STDERR "Cannot make temp mount point initrd.from\n";
|
||||
mkdir("initrd.to") || print STDERR "Cannot make temp mount point initrd.to\n";
|
||||
status_system("mount -o ro,loop $initrd initrd.from", "Cannot mount $initrd on initrd.from");
|
||||
status_system("mount -o loop newinitrd initrd.to", "Cannot mount newinitrd on initrd.to");
|
||||
status_system("cp -a initrd.from/* initrd.to/", "Cannot copy initrd to newinitrd");
|
||||
status_system("umount initrd.from", "Cannot umount initrd.from");
|
||||
status_system("umount initrd.to", "Cannot umount initrd.to");
|
||||
rmdir("initrd.from") || print STDERR "Cannot remove temp mount point initrd.from\n";
|
||||
rmdir("initrd.to") || print STDERR "Cannot remove temp mount point initrd.to\n";
|
||||
return (0);
|
||||
}
|
||||
|
||||
1;
|
|
@ -0,0 +1,69 @@
|
|||
This is a quick and dirty script to convert a floppyfw floppy
|
||||
(http://www.zelow.no/floppyfw/) to a tagged image for booting with
|
||||
Etherboot (http://etherboot.sourceforge.net/). The advantages of network
|
||||
booting include: it's much faster loading from the network than from a
|
||||
floppy disk, you can boot from any size floppy, and you are not limited
|
||||
to the maximum of 1.44 MB of the physical floppy. If you have enough RAM
|
||||
and use a virtual floppy to build the initial boot image, you can put as
|
||||
much on it as will fit the ramdisk.
|
||||
|
||||
See further down under -nonet if you want to boot from HD or CDROM.
|
||||
|
||||
This program requires mtools, tar, bzip2, loopback mount in the kernel,
|
||||
and root privileges to execute. Hope you have them.
|
||||
|
||||
This script works for any of the releases for which a subdirectory of
|
||||
that name is provided, but it should not be too hard to make it work for
|
||||
other releases, all that is done here is to substitute some scripts for
|
||||
the distributed ones.
|
||||
|
||||
First of all you should make the floppy work the way you want before
|
||||
converting it to a tagged image. This involves editing the various
|
||||
config files on the floppy. Instructions on this are distributed from
|
||||
the floppyfw web page mentioned above.
|
||||
|
||||
Edit the $tftpdir assignment for the directory where you put your tagged
|
||||
images. Edit the $libdir assignment and the use lib directive near the
|
||||
top if you decide to put this package somewhere other than
|
||||
/usr/local/lib/mkffwnb/. Adjust the instructions below as necessary.
|
||||
|
||||
Copy everything to $libdir.
|
||||
|
||||
mkdir -p /usr/local/lib/mkffwnb/
|
||||
cp -a . /usr/local/lib/mkffwnb/
|
||||
|
||||
Make a link from /usr/local/lib/mkffwnb/mkffwnb.pl to
|
||||
/usr/local/bin/mkffwnb so that it's in your path.
|
||||
|
||||
ln -s /usr/local/lib/mkffwnb/mkffwnb.pl /usr/local/bin/mkffwnb
|
||||
|
||||
Then run it as:
|
||||
|
||||
mkffwnb
|
||||
|
||||
You can also provide a floppy drive as an argument, e.g.
|
||||
|
||||
mkffwnb x:
|
||||
|
||||
where x: could be mapped to a disk file. This allows you to build an
|
||||
image without a real floppy drive. Remember that for virtual drives root
|
||||
must have the mapping for the drive in question in ~root/.mtoolsrc.
|
||||
|
||||
You can use the option --localtime=/etc/localtime to specify that the
|
||||
file /etc/localtime is to be copied to /etc/localtime on the initrd.
|
||||
Instead of /etc/localtime, you can use any of the timezone files under
|
||||
/usr/share/zoneinfo/, it's just that /etc/localtime will usually be the
|
||||
correct one for your timezone.
|
||||
|
||||
If you use the option -nonet, it leaves the intermediate files in
|
||||
$tempdir, /tmp/mkffwnb by default. This is useful if you want the
|
||||
vmlinuz and initrd.gz files for use with LILO or isolinux to boot from
|
||||
HD or CDROM. Actually you can also use these with a floppy, it loads
|
||||
faster if you fold all the scripts and modules into the initrd ahead
|
||||
of time.
|
||||
|
||||
mkffwnb has to be run as root because it uses loopback mounts and also
|
||||
because the files inside the initrd are owned by root.
|
||||
|
||||
Ken Yap
|
||||
2003-04-20
|
|
@ -0,0 +1,226 @@
|
|||
#!/usr/bin/perl -w
|
||||
#
|
||||
# Perl script to make a bootable image from a floppyfw floppy
|
||||
# The basic idea is to unpack and replace or convert all
|
||||
# the necessary config files into the initrd
|
||||
# and then make a bootable image out of it
|
||||
#
|
||||
# The --format= option overrides the default of nbi or elf hardcoded
|
||||
# in the source. Valid arguments are nbi or elf.
|
||||
#
|
||||
# The --output= options specifies an output file instead of stdout
|
||||
# The --nonet option specifies that a netbootable image is not to
|
||||
# be built but the vmlinuz and initrd.gz files left behind in $tempdir
|
||||
# The --localtime=f option specifies a timezone file that's to be
|
||||
# copied to /etc/localtime in the initrd, allowing a different timezone.
|
||||
# The --ffw29 option is intended for 2.9.x and above and extends
|
||||
# the size of the initrd by making a bigger one and copying the original over.
|
||||
#
|
||||
# The first non-option argument is taken to be the letter of a floppy to
|
||||
# convert, e.g. a:, b: or even x: where x: is mapped to a file using
|
||||
# mtools mapping in $HOME/.mtoolsrc. See the mtools documentation.
|
||||
# Thus you can work on a floppy image in a disk file and only write
|
||||
# to a floppy with dd or cp when you need to test the image.
|
||||
|
||||
use Getopt::Long;
|
||||
|
||||
use lib '/usr/local/lib/mkffwnb/';
|
||||
use Extendinitrd;
|
||||
|
||||
use strict;
|
||||
|
||||
use vars qw($testing $verbose $localtime $nonet $format $ffw29 $imagefile
|
||||
$floppy $libdir $tftpdir $output $tempdir $tempmount);
|
||||
|
||||
sub findversion () {
|
||||
my ($version) = grep(/FloppyFW/, `mtype $imagefile ${floppy}floppyfw.msg`);
|
||||
return '' unless defined($version) and $version ne '';
|
||||
chomp($version);
|
||||
$version =~ s/.*FloppyFW (\d+\.\d+\.\d+(\.\d+)?).*/$1/;
|
||||
return ($version);
|
||||
}
|
||||
|
||||
sub getappendargs () {
|
||||
my ($append) = join(' ', grep(/^\s*(append\s|console=)/, `mtype $imagefile ${floppy}syslinux.cfg`));
|
||||
chomp ($append);
|
||||
my @args = split(/\s+/, $append);
|
||||
my @result = ();
|
||||
foreach $_ (@args) {
|
||||
next if (/^$/ or /^append/ or /^initrd=/);
|
||||
next if (!$ffw29 and /^root=/);
|
||||
push (@result, $_);
|
||||
}
|
||||
return (join(' ', @result));
|
||||
}
|
||||
|
||||
# Copy whole floppy to the current directory
|
||||
# m preserves timestamps, n overwrites without warning and / means recursive
|
||||
sub mcopy ($) {
|
||||
my ($tempdir) = @_;
|
||||
|
||||
print "mcopy $imagefile -mn/ ${floppy}* $tempdir\n";
|
||||
my $status = system("mcopy -mn/ $imagefile ${floppy}* $tempdir");
|
||||
return ($status / 256);
|
||||
}
|
||||
|
||||
# Gunzip file, -f forces overwriting of uncompressed file
|
||||
sub gunzip ($) {
|
||||
my ($file) = @_;
|
||||
|
||||
print "Gunzipping $file\n" if ($verbose);
|
||||
my $status = system('gunzip', '-f', $file);
|
||||
return ($status / 256);
|
||||
}
|
||||
|
||||
# Gzip file, -f forces overwriting of compressed file
|
||||
sub gzip ($) {
|
||||
my ($file) = @_;
|
||||
|
||||
print "Gzipping $file\n" if ($verbose);
|
||||
my $status = system('gzip', '-9', '-f', $file);
|
||||
return ($status / 256);
|
||||
}
|
||||
|
||||
sub loopbackmount ($$) {
|
||||
my ($file, $point) = @_;
|
||||
|
||||
print "Mounting $file on $point loopback\n" if ($verbose);
|
||||
my $status = system('mount', '-o', 'loop', $file, $point);
|
||||
return ($testing ? 0 : $status / 256);
|
||||
}
|
||||
|
||||
sub loopbackumount ($) {
|
||||
my ($point) = @_;
|
||||
|
||||
print "Umounting $point\n" if ($verbose);
|
||||
my $status = system('umount', $point);
|
||||
return ($testing ? 0 : $status / 256);
|
||||
}
|
||||
|
||||
# Convert DOS CR-NL to Unix NL. $dst has implied prefix of $tempmount
|
||||
# Use @output for temporary storage in case we write back to the same file
|
||||
sub dostounix ($$) {
|
||||
my ($src, $dst) = @_;
|
||||
my @output = ();
|
||||
|
||||
$dst = "$tempmount/$dst";
|
||||
print "Converting $src to $dst\n" if ($verbose);
|
||||
unless (open(S, $src)) {
|
||||
print "$src: $!\n";
|
||||
return (0);
|
||||
}
|
||||
while (<S>) {
|
||||
chomp;
|
||||
tr /\015//d;
|
||||
push(@output, $_);
|
||||
}
|
||||
close(S);
|
||||
open(D, ">$dst") or return;
|
||||
for $_ (@output) {
|
||||
print D "$_\n";
|
||||
}
|
||||
close(D);
|
||||
chmod(0755, $dst);
|
||||
return (1);
|
||||
}
|
||||
|
||||
sub bunzip2untar ($$) {
|
||||
my ($file, $dir) = @_;
|
||||
|
||||
print "Unpacking $file into $dir\n" if ($verbose);
|
||||
system("bunzip2 < $file | (cd $dir; tar xf -)");
|
||||
}
|
||||
|
||||
$testing = $< != 0;
|
||||
$verbose = 1;
|
||||
$format = '';
|
||||
$imagefile = '';
|
||||
GetOptions('output=s' => \$output,
|
||||
'nonet!' => \$nonet,
|
||||
'localtime=s' => \$localtime,
|
||||
'format=s' => \$format,
|
||||
'ffw29!' => \$ffw29,
|
||||
'ffw30!' => \$ffw29,
|
||||
'i=s' => \$imagefile);
|
||||
if (defined($output) and $output !~ m(^/)) {
|
||||
my $d = `pwd`;
|
||||
chomp($d);
|
||||
$output = "$d/$output";
|
||||
}
|
||||
if ($imagefile) {
|
||||
$imagefile = "-i $imagefile";
|
||||
}
|
||||
$libdir = '/usr/local/lib/mkffwnb';
|
||||
$tftpdir = '/usr/local/var/tftpboot';
|
||||
# default can also be 'elf'
|
||||
$format = 'nbi' if ($format ne 'elf' and $format ne 'nbi');
|
||||
$floppy = $#ARGV >= 0 ? $ARGV[0] : 'a:';
|
||||
print <<EOF;
|
||||
This program requires mtools, tar, bzip2, loopback mount in the kernel,
|
||||
and root privileges to execute. Hope you have them.
|
||||
EOF
|
||||
my $version = &findversion();
|
||||
$version ne '' or die "Cannot determine version\n";
|
||||
print "Version $version\n";
|
||||
my $append = &getappendargs();
|
||||
$append = "--append='$append'" if $append ne '';
|
||||
print "$append\n";
|
||||
$libdir .= '/' . $version;
|
||||
-d $libdir or die "Cannot find files for $version\n";
|
||||
$tempdir = $nonet ? '/tmp/mkffwnb' : "/tmp/mkffwnb$$";
|
||||
$tempmount = 'tmpmount';
|
||||
mkdir($tempdir, 0755);
|
||||
print "Copying files off floppy, please be patient...\n";
|
||||
&mcopy($tempdir) == 0 or die "Mcopy failed, diskette problem?\n";
|
||||
chdir($tempdir);
|
||||
&gunzip('initrd.gz') == 0 or die "Gunzip of initrd.gz failed\n";
|
||||
if ($ffw29) {
|
||||
extendinitrd("initrd", 5760);
|
||||
system("mv newinitrd initrd");
|
||||
}
|
||||
mkdir($tempmount, 0755);
|
||||
&loopbackmount('initrd', $tempmount) == 0 or die "Loopback mount failed\n";
|
||||
&dostounix("$libdir/linuxrc", "linuxrc") if (-r "$libdir/linuxrc");
|
||||
unless (&dostounix("$libdir/floppyfw.ini", "floppyfw.ini")) {
|
||||
&dostounix("floppyfw/floppyfw.ini", $ffw29 ? "etc/floppyfw.ini" : "floppyfw.ini");
|
||||
}
|
||||
&dostounix("config", $ffw29 ? "etc/config.prelogin" : "etc/config");
|
||||
for my $i (glob('*.bz2 floppyfw/add.bz2 modules/*.bz2 packages/*.bz2')) {
|
||||
&bunzip2untar($i, $tempmount);
|
||||
}
|
||||
for my $i (glob('packages/*.ini')) {
|
||||
my $file = $i;
|
||||
$file =~ s:packages/::;
|
||||
&dostounix($i, "etc/$file");
|
||||
}
|
||||
&dostounix("hosts", "etc/hosts");
|
||||
&dostounix("modules.lst", "etc/modules.lst");
|
||||
&dostounix("network.ini", "etc/network.init");
|
||||
&dostounix("firewall.ini", "etc/firewall.init");
|
||||
&dostounix("syslog.cfg", "etc/syslog.conf");
|
||||
&dostounix("packages/timeinfo", "etc/localtime");
|
||||
system("cp -p licenses/* $tempmount/licenses/");
|
||||
# This conditional code is for 1.1.2 and below
|
||||
unless (glob('modules/*.bz2')) {
|
||||
print "Copying additional modules\n" if ($verbose);
|
||||
system("cp -p modules/* $tempmount/lib/modules/");
|
||||
}
|
||||
# If a timezone file has been specified, copy that onto initrd
|
||||
if (defined($localtime)) {
|
||||
if (-r $localtime) {
|
||||
print "Copying $localtime to $tempmount/etc/localtime\n";
|
||||
system("cp -p $localtime $tempmount/etc/localtime");
|
||||
} else {
|
||||
print "$localtime: $!\n";
|
||||
}
|
||||
}
|
||||
&loopbackumount($tempmount) == 0 or die "Loopback umount failed\n";
|
||||
&gzip('initrd') == 0 or die "Gzip of initrd failed\n";
|
||||
if ($nonet) {
|
||||
print "Floppyfw directory in $tempdir\n";
|
||||
} else {
|
||||
print "Calling mk$format-linux to make the netbootable image\n" if ($verbose);
|
||||
$output = "$tftpdir/floppyfw-$version.nb" if (!defined($output));
|
||||
system("mk$format-linux $append --output=$output vmlinuz initrd.gz");
|
||||
system("rm -fr $tempdir");
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
This is a quick and dirty Perl program to make a netbootable
|
||||
image from a Linux Router floppy. It was tested with a Coyote Linux
|
||||
(http://www.coyotelinux.com) floppy which is based on LRP. You need tar,
|
||||
mtools, mknbi-1.0, and of course, perl, to run this script.
|
|
@ -0,0 +1,191 @@
|
|||
#!/usr/bin/perl -w
|
||||
#
|
||||
# A program to make a netbootable image from a LRP firewall floppy
|
||||
#
|
||||
# Tested on a Dachstein Linux floppy image available from
|
||||
# http://lrp1.steinkuehler.net/ or via http://leaf.sourceforge.net/
|
||||
|
||||
# The most recent version of this script and a companion HowTo is available at
|
||||
# http://members.optushome.com.au/graybeard/linux/netboot.html
|
||||
#
|
||||
# Modified from the mklrpnb file found in the contrib/mklrpnb directory of the
|
||||
# Etherboot source at http://etherboot.sourceforge.net/
|
||||
#
|
||||
# Modifications by Glenn McK <graybeard@users.sourceforge.net>
|
||||
# $Id$
|
||||
#####################################
|
||||
|
||||
# this entry will need changing
|
||||
$image = "/home/graybeard/etherboot/dachstein-v1.0.2-1680.bin";
|
||||
|
||||
# these can remain, but change them if desired
|
||||
#
|
||||
# the next argument defaults to firewall if no other name is passed via the
|
||||
# command line, this will be the directory where distribution will be expanded
|
||||
# under $base and also the directory in /tftpboot for lrp.nb
|
||||
|
||||
my $uniqdir = shift || 'firewall';
|
||||
|
||||
$mntdir = "/mnt/floppy"; # where the above image file can be mounted
|
||||
$tftpbase = "/tftpboot";
|
||||
$tftpboot = "$tftpbase/$uniqdir"; # where the netboot images will be available
|
||||
$base = "/usr/src/LRP";
|
||||
$dachorg = "$base/dach-org-$uniqdir"; # a copy required to make the distribution
|
||||
$dachnew = "$base/lrp-$uniqdir"; # the base files for the new distribution
|
||||
$packages = "$dachnew/var/lib/lrpkg"; # list to allow lrcfg to display Packages
|
||||
|
||||
# everything below should be okay
|
||||
######################################
|
||||
|
||||
if ( !-e $image ) {
|
||||
print
|
||||
"\n\tA valid LRP file and directory are required\n\tdownload one then edit $0\n\n";
|
||||
exit 1;
|
||||
}
|
||||
if ( !-d $base ) {
|
||||
mkdir( $base, 0700 );
|
||||
}
|
||||
|
||||
if ( !-d $dachorg ) {
|
||||
mkdir( $dachorg, 0700 );
|
||||
}
|
||||
|
||||
if ( !-d $dachnew ) {
|
||||
mkdir( $dachnew, 0700 );
|
||||
`umount $mntdir`;
|
||||
`mount -o ro,loop $image $mntdir`;
|
||||
|
||||
`cp -vr $mntdir/* $dachorg/`;
|
||||
|
||||
@cfg = `cat $mntdir/syslinux.cfg`;
|
||||
|
||||
unless ( defined(@cfg) ) {
|
||||
print "Cannot find syslinux.cfg on $mntdir\n";
|
||||
exit 1;
|
||||
}
|
||||
print "cfg = @cfg\n";
|
||||
($append) = grep( /append/, @cfg ); # find the append= line
|
||||
print "append = \n$append\n";
|
||||
chomp($append); # remove trailing newline
|
||||
$append =~ s/append=//; # remove the append= at beginning
|
||||
print "strip append = \n$append\n\n";
|
||||
@args = split ( / /, $append ); # split into arguments at whitespace
|
||||
($root) = grep( /^initrd=/, @args ); # find the initrd= argument
|
||||
$root =~ s/^initrd=//; # remove the initrd= at beginning
|
||||
$root =~ s/\.lrp$//; # cleanup for paclages list
|
||||
print "strip initrd = \n$root\n\n";
|
||||
($lrp) = grep( /^LRP=/, @args ); # find the LRP= argument
|
||||
$lrp =~ s/^LRP=//; # remove the LRP= at beginning
|
||||
print "strip LRP =\n$lrp\n\n";
|
||||
@lrp = split ( /,/, $lrp ); # split into filenames at ,
|
||||
unshift ( @lrp, $root ); # prepend the root LRP filename
|
||||
@pack = @lrp;
|
||||
print "LRP =\n@lrp\n\n";
|
||||
$append = '';
|
||||
|
||||
foreach $i (@args) { # rebuild the append string
|
||||
next if ( $i =~ /^initrd=/ ); # minus the unneeded parameters
|
||||
next if ( $i =~ /^LRP=/ );
|
||||
next if ( $i =~ /^boot=/ );
|
||||
next if ( $i =~ /^PKGPATH=/ );
|
||||
print "$i = i\n";
|
||||
$append .= "$i ";
|
||||
}
|
||||
|
||||
print "final append = \n$append\n";
|
||||
|
||||
chdir($dachnew) or die "$dachnew: $!\n";
|
||||
foreach $i (@lrp) {
|
||||
$i .= '.lrp' if $i !~ /\.lrp$/;
|
||||
print "\n\n\nUnpacking $i\n";
|
||||
system("ln -svf $dachorg/$i ${dachorg}/${i}.tar.gz");
|
||||
chmod 0600, "$dachorg/$i";
|
||||
system("cat $mntdir/$i | tar zxvf -");
|
||||
}
|
||||
|
||||
# create file for lrcfg to display packages
|
||||
open( PACKAGES, ">$packages/packages" )
|
||||
|| print "unable to modify $packages:$!\n";
|
||||
foreach $line (@pack) {
|
||||
print PACKAGES "$line\n";
|
||||
}
|
||||
close PACKAGES;
|
||||
|
||||
# prevent previous file from being overwritten during installation
|
||||
# and also mess with some values in /linuxrc to hide non errors
|
||||
open( LINUXRC, "$packages/root.linuxrc" );
|
||||
@text = <LINUXRC>;
|
||||
close LINUXRC;
|
||||
open( LINUXRC, ">$packages/root.linuxrc" );
|
||||
foreach $line (@text) {
|
||||
$line =~ s/PFX\/packages/PFX\/packages-old \
|
||||
\t\t\t\t# packages changed to packages-old for netboot setup/;
|
||||
$line =~
|
||||
s/^rc=1/# rc=1 changed to rc=0 to suppress error messages for netboot setup \
|
||||
rc=0/;
|
||||
$line =~
|
||||
s/echo -n \" \(nf\!\)\"/#echo -n \" \(nf\!\)\" changed to reflect ToDo list \
|
||||
\t\t\techo -n \" netboot setup - No backups possible from this machine - ToFix ?"/;
|
||||
print LINUXRC $line;
|
||||
}
|
||||
close LINUXRC;
|
||||
|
||||
# swap interfaces around in network config file
|
||||
# eth1 is the new external eth0 is OUR internal server access
|
||||
open( NETWORK, "$dachnew/etc/network.conf" )
|
||||
|| print "Unable to modify NETWORK:$!\n";
|
||||
@text = <NETWORK>;
|
||||
close NETWORK;
|
||||
open( NETWORK, ">$dachnew/etc/network.conf" )
|
||||
|| print "Unable to modify NETWORK:$!\n";
|
||||
foreach $line (@text) {
|
||||
$line =~ s/eth0/eth00/;
|
||||
$line =~ s/eth1/eth0/;
|
||||
$line =~ s/eth00/eth1/;
|
||||
print NETWORK $line;
|
||||
}
|
||||
close NETWORK;
|
||||
|
||||
`echo $append > $dachorg/appendstr`;
|
||||
|
||||
`umount /mnt/floppy`;
|
||||
print "\nThe files have been extracted to $dachnew\n";
|
||||
system("ls -al $dachnew");
|
||||
}
|
||||
else {
|
||||
print "\n\n\t$image \n \thas already been extracted to $dachnew \
|
||||
\tNow skipping to the next step where the netboot file\
|
||||
\twill be created.\n";
|
||||
|
||||
$append = `cat $dachorg/appendstr`;
|
||||
print "\nThe new append string will be...\n$append\n";
|
||||
|
||||
chdir($dachnew);
|
||||
if ( !-d $tftpbase ) {
|
||||
mkdir( $tftpbase, 0710 );
|
||||
system("chgrp nobody $tftpbase");
|
||||
}
|
||||
|
||||
unlink($tftpboot);
|
||||
|
||||
# these permissions really need changing to something secure
|
||||
mkdir( $tftpboot, 0710 );
|
||||
system("chgrp nobody $tftpboot");
|
||||
print "\tRepacking to $tftpboot/lrp.lrp\n";
|
||||
system("tar zcf $tftpboot/lrp.lrp *");
|
||||
print "\tExtracting kernel image from $dachorg\n";
|
||||
system("cat $dachorg/linux > $tftpboot/lrp.ker");
|
||||
print "\tCreating netboot image $tftpboot/lrp.nb\n";
|
||||
system(
|
||||
"mknbi-linux --append='$append' --output=$tftpboot/lrp.nb $tftpboot/lrp.ker $tftpboot/lrp.lrp"
|
||||
);
|
||||
chmod 0604, "$tftpboot/lrp.nb", "$tftpboot/lrp.ker", "$tftpboot/lrp.lrp";
|
||||
print "\nThese netboot files are in $tftpboot\n";
|
||||
system("ls -al $tftpboot");
|
||||
print "\n The owner and permissions for $tftpboot \
|
||||
and files should be checked for security. The above\
|
||||
permissions assume that tftp is running chroot (nobody)
|
||||
drwx--r--- root:nobody /tftpboot\n\n";
|
||||
}
|
||||
|
||||
exit 0;
|
|
@ -0,0 +1,45 @@
|
|||
#!/usr/bin/perl -w
|
||||
#
|
||||
# A program to make a netbootable image from a LRP firewall floppy
|
||||
# Tested on a Coyote Linux floppy
|
||||
#
|
||||
@cfg = `mtype a:syslinux.cfg`;
|
||||
unless (defined(@cfg)) {
|
||||
print "Cannot find syslinux.cfg on floppy\n";
|
||||
exit 1;
|
||||
}
|
||||
($append) = grep(/^append/, @cfg); # find the append= line
|
||||
chomp($append); # remove trailing newline
|
||||
$append =~ s/append=//; # remove the append= at beginning
|
||||
@args = split(/ /, $append); # split into arguments at whitespace
|
||||
($root) = grep(/^initrd=/, @args); # find the initrd= argument
|
||||
$root =~ s/^initrd=//; # remove the initrd= at beginning
|
||||
($lrp) = grep(/^LRP=/, @args); # find the LRP= argument
|
||||
$lrp =~ s/^LRP=//; # remove the LRP= at beginning
|
||||
@lrp = split(/,/, $lrp); # split into filenames at ,
|
||||
unshift(@lrp, $root); # prepend the root LRP filename
|
||||
$append = '';
|
||||
foreach $i (@args) { # rebuild the append string
|
||||
next if ($i =~ /^initrd=/); # minus the unneeded parameters
|
||||
next if ($i =~ /^LRP=/);
|
||||
next if ($i =~ /^boot=/);
|
||||
$append .= "$i ";
|
||||
}
|
||||
# print "$append\n";
|
||||
$tempdir = "/tmp/lrp$$";
|
||||
mkdir($tempdir, 0777) or die "$tempdir: $!\n";
|
||||
chdir($tempdir) or die "$tempdir: $!\n";
|
||||
foreach $i (@lrp) {
|
||||
$i .= '.lrp' if $i !~ /\.lrp$/;
|
||||
print "Unpacking $i\n";
|
||||
system("mtype a:$i | tar zxvf -");
|
||||
}
|
||||
print "Repacking to /tmp/lrp.lrp\n";
|
||||
system("tar zcf /tmp/lrp.lrp *");
|
||||
chdir('/tmp') or die "/tmp: $!\n";
|
||||
system("rm -fr $tempdir");
|
||||
print "Extracting kernel image from floppy\n";
|
||||
system("mtype a:linux > /tmp/lrp.ker");
|
||||
print "Creating netboot image in /tmp/lrp.nb\n";
|
||||
system("mkelf-linux --append='$append' --output=/tmp/lrp.nb /tmp/lrp.ker /tmp/lrp.lrp");
|
||||
exit 0;
|
|
@ -0,0 +1,97 @@
|
|||
#!/usr/bin/perl -w
|
||||
#
|
||||
# Quick Perl program to decode and display details about
|
||||
# tagged images created by mknbi, and then mount the contained
|
||||
# DOS filesystem using a loop-back mount
|
||||
#
|
||||
# Martin Atkins, November 1998
|
||||
# by hacking disnbi by
|
||||
# Ken Yap, September 1998
|
||||
#
|
||||
#
|
||||
|
||||
sub getvendordata {
|
||||
my ($flags) = @_;
|
||||
|
||||
my $vendordata = '';
|
||||
my $vendorlen = ($flags & 0xff) >> 4;
|
||||
if ($vendorlen > 0) {
|
||||
$vendorlen *= 4;
|
||||
$vendordata = unpack("A$vendorlen", substr($imageheader, $curoffset));
|
||||
$curoffset += $vendorlen;
|
||||
}
|
||||
return ($vendordata);
|
||||
}
|
||||
|
||||
sub decodesegmentflags {
|
||||
my ($flags) = @_;
|
||||
|
||||
$flags >>= 24;
|
||||
$flags &= 0x3;
|
||||
($flags == 0) and $type = "Absolute";
|
||||
($flags == 1) and $type = "Follows last segment";
|
||||
($flags == 2) and $type = "Below end of memory";
|
||||
($flags == 3) and $type = "Below last segment loaded";
|
||||
return ($type);
|
||||
}
|
||||
|
||||
sub onesegment
|
||||
{
|
||||
my ($segnum) = @_;
|
||||
my ($type, $vendordata);
|
||||
|
||||
my ($flags, $loadaddr, $imagelen, $memlength) = unpack("V4", substr($imageheader, $curoffset));
|
||||
$curoffset += 16;
|
||||
print "Segment number $segnum\n";
|
||||
printf "Load address:\t\t%08x\n", $loadaddr;
|
||||
printf "Image length:\t\t%d\n", $imagelen;
|
||||
printf "Memory length:\t\t%d\n", $memlength;
|
||||
$type = &decodesegmentflags($flags);
|
||||
printf "Position:\t\t$type\n";
|
||||
printf "Vendor tag:\t\t%d\n", ($flags >> 8) & 0xff;
|
||||
if (($vendordata = &getvendordata($flags)) ne '') {
|
||||
print "Vendor data:\t\t", $vendordata, "\n";
|
||||
}
|
||||
print "\n";
|
||||
push (@seglengths, $imagelen);
|
||||
return (($flags >> 26) & 1);
|
||||
}
|
||||
|
||||
@seglengths = ();
|
||||
$#ARGV == 1 or die "Usage: mntnbi tagged-image-file dir\n";
|
||||
$imagefile= $ARGV[0];
|
||||
open(I, $ARGV[0]) or die "$imagefile: $!\n";
|
||||
(defined($status = sysread(I, $imageheader, 512)) and $status == 512)
|
||||
or die "$imagefile: Cannot read header\n";
|
||||
$headerrecord = substr($imageheader, 0, 16);
|
||||
($magic, $flags, $bx, $ds, $ip, $cs) = unpack("a4Vv4", $headerrecord);
|
||||
$magic eq "\x36\x13\x03\x1B" or die "$imagefile: Not a tagged image file\n";
|
||||
$curoffset = 16;
|
||||
|
||||
# Now decode the header
|
||||
|
||||
printf "Header location:\t%04x:%04x\n", $ds, $bx;
|
||||
printf "Start address:\t\t%04x:%04x\n", $cs, $ip;
|
||||
printf "Flags:\n";
|
||||
print "Return to loader after execution (extension)\n" if (($flags >> 8) & 1);
|
||||
if (($vendordata = &getvendordata($flags)) ne '') {
|
||||
print "Vendor data:\t\t", $vendordata, "\n";
|
||||
}
|
||||
print "\n";
|
||||
|
||||
# Now decode each segment record
|
||||
|
||||
$segnum = 1;
|
||||
do {
|
||||
$lastrecord = &onesegment($segnum);
|
||||
++$segnum;
|
||||
} while (!$lastrecord);
|
||||
|
||||
if ($#seglengths != 1) {
|
||||
die "This is not a DOS image $#seglengths\n";
|
||||
}
|
||||
$offset = 512 + $seglengths[0];
|
||||
print "mounting filesystem at offset $offset in $ARGV[0] on $ARGV[1]\n";
|
||||
$rc = system "mount $ARGV[0] $ARGV[1] -t msdos -o loop,offset=$offset";
|
||||
print "Done\n" if ($rc == 0);
|
||||
exit(0);
|
|
@ -0,0 +1,2 @@
|
|||
For more information please check
|
||||
http://nfs-swap.dot-heine.de
|
|
@ -0,0 +1,10 @@
|
|||
# Comment out the second command and uncomment the first command
|
||||
# below if you don't want to use libwrap (hosts.{allow,deny} access control)
|
||||
|
||||
# If you don't have it in /var/log/subsys, uncomment and define
|
||||
#CFLAGS+=-DLOCKFILE_DIR=\"/var/log\"
|
||||
LIBWRAP=-lwrap
|
||||
|
||||
p910nd: p910nd.c
|
||||
# $(CC) -Wall $(CFLAGS) -o $@ p910nd.c
|
||||
$(CC) -Wall $(CFLAGS) -DUSE_LIBWRAP -o $@ p910nd.c $(LIBWRAP)
|
|
@ -0,0 +1,9 @@
|
|||
#!/usr/bin/perl
|
||||
while (1)
|
||||
{
|
||||
exit 0 if read(STDIN,$c,1) == 0;
|
||||
last if ($cl eq "\031" && $c eq "\001");
|
||||
$cl = $c;
|
||||
}
|
||||
kill 'STOP',$$;
|
||||
exit 0
|
|
@ -0,0 +1,58 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
# edit this to the printer hostname
|
||||
$them = 'ken';
|
||||
$port = 9101;
|
||||
|
||||
open(STDIN, "$ARGV[0]") if $#ARGV >= 0;
|
||||
|
||||
use Socket;
|
||||
#use Sys::Hostname;
|
||||
|
||||
#$hostname = hostname;
|
||||
|
||||
($name, $aliases, $proto) = getprotobyname('tcp');
|
||||
($name, $aliases, $port) = getservbyname($port, 'tcp')
|
||||
unless $port =~ /^\d+$/;
|
||||
|
||||
#$thisaddr = inet_aton($hostname);
|
||||
#defined($thisaddr) or &errexit("inet_aton: cannot resolve $hostname\n");
|
||||
|
||||
$thataddr = inet_aton($them);
|
||||
defined($thataddr) or &errexit("inet_aton: cannot resolve $them\n");
|
||||
|
||||
socket(S, PF_INET, SOCK_STREAM, $proto) or &errexit("socket: $!\n");
|
||||
|
||||
#$this = sockaddr_in(0, $thisaddr);
|
||||
#bind(S, $this) || &errexit("bind: $!\n");
|
||||
|
||||
$that = sockaddr_in($port, $thataddr);
|
||||
connect(S, $that) || &errexit("connect: $!\n");
|
||||
|
||||
select(S); $| = 1; select(STDOUT);
|
||||
|
||||
$buffer = '';
|
||||
while (1)
|
||||
{
|
||||
$rin = '';
|
||||
vec($rin, fileno(S), 1) = 1;
|
||||
$nfound = select($rout=$rin, $wout=$rin, undef, undef);
|
||||
if (vec($rout, fileno(S), 1)) {
|
||||
print STDERR "$buffer\n" if
|
||||
defined($nread = sysread(S, $buffer, 8192));
|
||||
}
|
||||
if (vec($wout, fileno(S), 1)) {
|
||||
$nread = read(STDIN, $buffer, 8192);
|
||||
last if $nread == 0;
|
||||
&errexit("write: $!\n") unless
|
||||
defined($written = syswrite(S,$buffer,$nread));
|
||||
}
|
||||
}
|
||||
close(S);
|
||||
exit 0;
|
||||
|
||||
sub errexit
|
||||
{
|
||||
print STDERR @_;
|
||||
exit 2;
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
.TH P910ND 8 "1 August 2004"
|
||||
.SH NAME
|
||||
p910nd \- port 9100+n printer daemon
|
||||
.SH SYNOPSIS
|
||||
.B p910nd
|
||||
[\fB-f device\fR]
|
||||
[\fB-i bindaddr\fR]
|
||||
[\fB-bv\fR]
|
||||
[\fB0|1|2\fR]
|
||||
.SH DESCRIPTION
|
||||
.I p910nd
|
||||
is a small daemon that copies any data received on the port
|
||||
it is listening on to the corresponding printer port.
|
||||
It is primarily intended for diskless Linux hosts running as printer drivers
|
||||
but there is no reason why it could not be used on diskful hosts.
|
||||
Port 9100 is copied to /dev/lp0, 9101 to /dev/lp1 and 9102 to /dev/lp2.
|
||||
The default is port 9100 to /dev/lp0.
|
||||
.LP
|
||||
The \fB-f\fR option can be used to specify a different printer device,
|
||||
e.g. /dev/usblp0.
|
||||
.LP
|
||||
The \fB-i\fR option can be used to specify binding to one address instead
|
||||
of all interfaces which is the default.
|
||||
.LP
|
||||
The \fB-b\fR option turns on bidirectional copying.
|
||||
.LP
|
||||
The \fB-v\fR option shows the version number.
|
||||
.SH INSTALLATION
|
||||
.I p910nd
|
||||
can be run as a standalone daemon or from inetd.
|
||||
It will automatically detect if it is running under inetd.
|
||||
.LP
|
||||
A sample SysVinit script,
|
||||
.IR p910nd.sh ,
|
||||
is provided for operation as a daemon.
|
||||
.I p910nd
|
||||
will change its name under ps to match the printer port, i.e.
|
||||
.I p9100d, p9101d
|
||||
and
|
||||
.IR p9102d .
|
||||
.LP
|
||||
When running under inetd, the
|
||||
.I /etc/inetd.conf
|
||||
entry should look something like this (with tcpwrappers protection):
|
||||
.sp
|
||||
.nf
|
||||
p9101 stream tcp nowait root /usr/sbin/tcpd /sbin/p910nd
|
||||
.fi
|
||||
.sp
|
||||
Don't forget to add an entry in
|
||||
.I /etc/services
|
||||
for the corresponding port.
|
||||
.LP
|
||||
If operating with lprng, use the host%port syntax for the
|
||||
printer device to send jobs to it.
|
||||
.LP
|
||||
If operating with CUPS, this is supported as the AppSocket
|
||||
protocol, also known as the JetDirect (probably TM) protocol.
|
||||
.LP
|
||||
If operating with classic Berkeley lpd, a sample client,
|
||||
.IR client.pl ,
|
||||
is provided.
|
||||
This should be installed as the ifilter (if=) in /etc/printcap.
|
||||
.I banner.pl
|
||||
should be installed as the ofilter (of=) in /etc/printcap.
|
||||
It may be necessary to create a dummy spool file for lpd (lp=).
|
||||
This file will be opened but not written to.
|
||||
The corresponding C versions are left as an exercise for the reader.
|
||||
.LP
|
||||
When running under inetd, more than one instance could be started.
|
||||
To avoid problems with multiple instances attempting to access the
|
||||
printer at the same time, make sure that only one client is active
|
||||
at any one time. This can be done by designating one host as the
|
||||
spooler and sending all jobs to this host. You will probably
|
||||
need to set up an intermediate queue anyway to provide print job filtering.
|
||||
.LP
|
||||
If compiled with USE_LIBWRAP and linked with -lwrap, it uses the libwrap
|
||||
library (tcpwrappers). Access control can be done with /etc/hosts.allow
|
||||
and /etc/hosts.deny. The service name is p910nd.
|
||||
.SH DIAGNOSTICS
|
||||
.I p910nd
|
||||
logs error messages to syslog.
|
||||
.SH "SEE ALSO"
|
||||
printcap(5), hosts_access(5)
|
||||
.SH FILES
|
||||
/var/run/p9100d.pid, /var/lock/subsys/p9100d, /etc/hosts.allow, /etc/hosts.deny
|
||||
.SH COPYRIGHT
|
||||
.I p910nd
|
||||
is under the GNU Public License
|
||||
.SH AUTHOR
|
||||
Ken Yap (ken_yap@users.sourceforge.net)
|
||||
.SH DATE
|
||||
Version 0.8 October 2004
|
|
@ -0,0 +1,420 @@
|
|||
/*
|
||||
* Port 9100+n daemon
|
||||
* Accepts a connection from port 9100+n and copy stream to
|
||||
* /dev/lpn, where n = 0,1,2.
|
||||
*
|
||||
* Run standalone as: p910nd [0|1|2]
|
||||
*
|
||||
* Run under inetd as:
|
||||
* p910n stream tcp nowait root /usr/sbin/tcpd p910nd [0|1|2]
|
||||
* where p910n is an /etc/services entry for
|
||||
* port 9100, 9101 or 9102 as the case may be.
|
||||
* root can be replaced by any uid with rw permission on /dev/lpn
|
||||
*
|
||||
* Port 9100+n will then be passively opened
|
||||
* n defaults to 0
|
||||
*
|
||||
* Version 0.8
|
||||
* Allow specifying address to bind to
|
||||
*
|
||||
* Version 0.7
|
||||
* Bidirectional data transfer
|
||||
*
|
||||
* Version 0.6
|
||||
* Arne Bernin fixed some cast warnings, corrected the version number
|
||||
* and added a -v option to print the version.
|
||||
*
|
||||
* Version 0.5
|
||||
* -DUSE_LIBWRAP and -lwrap enables hosts_access (tcpwrappers) checking.
|
||||
*
|
||||
* Version 0.4
|
||||
* Ken Yap (ken_yap@users.sourceforge.net), April 2001
|
||||
* Placed under GPL.
|
||||
*
|
||||
* Added -f switch to specify device which overrides /dev/lpn.
|
||||
* But number is still required get distinct ports and locks.
|
||||
*
|
||||
* Added locking so that two invocations of the daemon under inetd
|
||||
* don't try to open the printer at the same time. This can happen
|
||||
* even if there is one host running clients because the previous
|
||||
* client can exit after it has sent all data but the printer has not
|
||||
* finished printing and inetd starts up a new daemon when the next
|
||||
* request comes in too soon.
|
||||
*
|
||||
* Various things could be Linux specific. I don't
|
||||
* think there is much demand for this program outside of PCs,
|
||||
* but if you port it to other distributions or platforms,
|
||||
* I'd be happy to receive your patches.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <getopt.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <syslog.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#ifdef USE_LIBWRAP
|
||||
#include "tcpd.h"
|
||||
int allow_severity, deny_severity;
|
||||
extern int hosts_ctl(char *daemon, char *client_name,
|
||||
char *client_addr, char *client_user);
|
||||
#endif
|
||||
|
||||
#define BASEPORT 9100
|
||||
#define PIDFILE "/var/run/p910%cd.pid"
|
||||
#ifdef LOCKFILE_DIR
|
||||
#define LOCKFILE LOCKFILE_DIR "/p910%cd"
|
||||
#else
|
||||
#define LOCKFILE "/var/lock/subsys/p910%cd"
|
||||
#endif
|
||||
#define PRINTERFILE "/dev/lp%c"
|
||||
#define LOGOPTS LOG_ERR
|
||||
|
||||
static char *progname;
|
||||
static char version[] = "p910nd Version 0.8";
|
||||
static int lockfd = -1;
|
||||
static char *device = 0;
|
||||
static int bidir = 0;
|
||||
static char *bindaddr = 0;
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [-f device] [-i bindaddr] [-bv] [0|1|2]\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void show_version (void)
|
||||
{
|
||||
fprintf(stdout, "%s \n", version);
|
||||
}
|
||||
|
||||
FILE *open_printer(int lpnumber)
|
||||
{
|
||||
FILE *f;
|
||||
char lpname[sizeof(PRINTERFILE)];
|
||||
|
||||
#ifdef TESTING
|
||||
(void)snprintf(lpname, sizeof(lpname), "/dev/tty");
|
||||
#else
|
||||
(void)snprintf(lpname, sizeof(lpname), PRINTERFILE, lpnumber);
|
||||
#endif
|
||||
if (device == 0)
|
||||
device = lpname;
|
||||
if ((f = fopen(device, bidir ? "w+" : "w")) == NULL)
|
||||
{
|
||||
syslog(LOGOPTS, "%s: %m\n", device);
|
||||
exit(1);
|
||||
}
|
||||
return (f);
|
||||
}
|
||||
|
||||
int get_lock(int lpnumber)
|
||||
{
|
||||
char lockname[sizeof(LOCKFILE)];
|
||||
struct flock lplock;
|
||||
|
||||
(void)snprintf(lockname, sizeof(lockname), LOCKFILE, lpnumber);
|
||||
if ((lockfd = open(lockname, O_CREAT|O_RDWR)) < 0)
|
||||
{
|
||||
syslog(LOGOPTS, "%s: %m\n", lockname);
|
||||
return (0);
|
||||
}
|
||||
memset(&lplock, 0, sizeof(lplock));
|
||||
lplock.l_type = F_WRLCK;
|
||||
lplock.l_pid = getpid();
|
||||
if (fcntl(lockfd, F_SETLKW, &lplock) < 0)
|
||||
{
|
||||
syslog(LOGOPTS, "%s: %m\n", lockname);
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
void free_lock(void)
|
||||
{
|
||||
if (lockfd >= 0)
|
||||
(void)close(lockfd);
|
||||
}
|
||||
|
||||
/* Copy network socket to FILE f until EOS */
|
||||
int copy_stream(int fd, FILE *f)
|
||||
{
|
||||
int nread;
|
||||
char buffer[8192];
|
||||
|
||||
if (bidir) {
|
||||
FILE *nf;
|
||||
|
||||
if ((nf = fdopen(fd, "w")) == NULL) {
|
||||
syslog(LOGOPTS, "fdopen: %m\n");
|
||||
}
|
||||
for (;;) {
|
||||
fd_set readfds;
|
||||
int result;
|
||||
int maxfd = fileno(f) > fd ? fileno(f) : fd;
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(fileno(f), &readfds);
|
||||
FD_SET(fd, &readfds);
|
||||
result = select(maxfd + 1, &readfds, 0, 0, 0);
|
||||
if (result < 0)
|
||||
return (result);
|
||||
if (result == 0)
|
||||
continue;
|
||||
if (FD_ISSET(fd, &readfds)) {
|
||||
nread = read(fd, buffer, sizeof(buffer));
|
||||
if (nread <= 0)
|
||||
break;
|
||||
(void)fwrite(buffer, sizeof(char), nread, f);
|
||||
}
|
||||
if (FD_ISSET(fileno(f), &readfds)) {
|
||||
nread = read(fileno(f), buffer, sizeof(buffer));
|
||||
if (nread > 0 && nf != NULL) {
|
||||
(void)fwrite(buffer, sizeof(char), nread, nf);
|
||||
(void)fflush(nf);
|
||||
}
|
||||
}
|
||||
}
|
||||
(void)fflush(f);
|
||||
(void)fclose(nf);
|
||||
return (0);
|
||||
} else {
|
||||
while ((nread = read(fd, buffer, sizeof(buffer))) > 0)
|
||||
(void)fwrite(buffer, sizeof(char), nread, f);
|
||||
(void)fflush(f);
|
||||
return (nread);
|
||||
}
|
||||
}
|
||||
|
||||
void one_job(int lpnumber)
|
||||
{
|
||||
FILE *f;
|
||||
struct sockaddr_in client;
|
||||
socklen_t clientlen = sizeof(client);
|
||||
|
||||
if (getpeername(0, (struct sockaddr*) &client, &clientlen) >= 0)
|
||||
syslog(LOGOPTS, "Connection from %s port %hu\n",
|
||||
inet_ntoa(client.sin_addr),
|
||||
ntohs(client.sin_port));
|
||||
if (get_lock(lpnumber) == 0)
|
||||
return;
|
||||
f = open_printer(lpnumber);
|
||||
if (copy_stream(0, f) < 0)
|
||||
syslog(LOGOPTS, "copy_stream: %m\n");
|
||||
fclose(f);
|
||||
free_lock();
|
||||
}
|
||||
|
||||
void server(int lpnumber)
|
||||
{
|
||||
struct rlimit resourcelimit;
|
||||
#ifdef USE_GETPROTOBYNAME
|
||||
struct protoent *proto;
|
||||
#endif
|
||||
int netfd, fd, one = 1;
|
||||
socklen_t clientlen;
|
||||
struct sockaddr_in netaddr, client;
|
||||
char pidfilename[sizeof(PIDFILE)];
|
||||
FILE *f;
|
||||
int ipret;
|
||||
|
||||
#ifndef TESTING
|
||||
switch (fork())
|
||||
{
|
||||
case -1:
|
||||
syslog(LOGOPTS, "fork: %m\n");
|
||||
exit (1);
|
||||
case 0: /* child */
|
||||
break;
|
||||
default: /* parent */
|
||||
exit(0);
|
||||
}
|
||||
/* Now in child process */
|
||||
resourcelimit.rlim_max = 0;
|
||||
if (getrlimit(RLIMIT_NOFILE, &resourcelimit) < 0)
|
||||
{
|
||||
syslog(LOGOPTS, "getrlimit: %m\n");
|
||||
exit(1);
|
||||
}
|
||||
for (fd = 0; fd < resourcelimit.rlim_max; ++fd)
|
||||
(void)close(fd);
|
||||
if (setsid() < 0)
|
||||
{
|
||||
syslog(LOGOPTS, "setsid: %m\n");
|
||||
exit(1);
|
||||
}
|
||||
(void)chdir("/");
|
||||
(void)umask(022);
|
||||
fd = open("/dev/null", O_RDWR); /* stdin */
|
||||
(void)dup(fd); /* stdout */
|
||||
(void)dup(fd); /* stderr */
|
||||
(void)snprintf(pidfilename, sizeof(pidfilename), PIDFILE, lpnumber);
|
||||
if ((f = fopen(pidfilename, "w")) == NULL)
|
||||
{
|
||||
syslog(LOGOPTS, "%s: %m\n", pidfilename);
|
||||
exit(1);
|
||||
}
|
||||
(void)fprintf(f, "%d\n", getpid());
|
||||
(void)fclose(f);
|
||||
if (get_lock(lpnumber) == 0)
|
||||
exit(1);
|
||||
#endif
|
||||
f = open_printer(lpnumber);
|
||||
#ifdef USE_GETPROTOBYNAME
|
||||
if ((proto = getprotobyname("tcp")) == NULL)
|
||||
{
|
||||
syslog(LOGOPTS, "Cannot find protocol for TCP!\n");
|
||||
exit(1);
|
||||
}
|
||||
if ((netfd = socket(AF_INET, SOCK_STREAM, proto->p_proto)) < 0)
|
||||
#else
|
||||
if ((netfd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0)
|
||||
#endif
|
||||
{
|
||||
syslog(LOGOPTS, "socket: %m\n");
|
||||
exit(1);
|
||||
}
|
||||
if (setsockopt(netfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0)
|
||||
{
|
||||
syslog(LOGOPTS, "setsocketopt: %m\n");
|
||||
exit(1);
|
||||
}
|
||||
netaddr.sin_port = htons(BASEPORT + lpnumber - '0');
|
||||
if (bindaddr == 0) {
|
||||
netaddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
} else {
|
||||
ipret = inet_pton(AF_INET, bindaddr, &netaddr.sin_addr.s_addr);
|
||||
if (ipret < 0) {
|
||||
syslog(LOGOPTS, "inet_pton: %m\n");
|
||||
exit(1);
|
||||
} else if (ipret == 0) {
|
||||
syslog(LOGOPTS, "inet_pton: invalid bind IP address\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
memset(netaddr.sin_zero, 0, sizeof(netaddr.sin_zero));
|
||||
if (bind(netfd, (struct sockaddr*) &netaddr, sizeof(netaddr)) < 0)
|
||||
{
|
||||
syslog(LOGOPTS, "bind: %m\n");
|
||||
exit(1);
|
||||
}
|
||||
if (listen(netfd, 5) < 0)
|
||||
{
|
||||
syslog(LOGOPTS, "listen: %m\n");
|
||||
exit(1);
|
||||
}
|
||||
clientlen = sizeof(client);
|
||||
memset(&client, 0, sizeof(client));
|
||||
while ((fd = accept(netfd, (struct sockaddr*) &client, &clientlen)) >= 0)
|
||||
{
|
||||
#ifdef USE_LIBWRAP
|
||||
if (hosts_ctl("p910nd", STRING_UNKNOWN,
|
||||
inet_ntoa(client.sin_addr), STRING_UNKNOWN) == 0) {
|
||||
syslog(LOGOPTS, "Connection from %s port %hd rejected\n",
|
||||
inet_ntoa(client.sin_addr),
|
||||
ntohs(client.sin_port));
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
syslog(LOGOPTS, "Connection from %s port %hd accepted\n",
|
||||
inet_ntoa(client.sin_addr),
|
||||
ntohs(client.sin_port));
|
||||
/*write(fd, "Printing", 8);*/
|
||||
if (copy_stream(fd, f) < 0)
|
||||
syslog(LOGOPTS, "copy_stream: %m\n");
|
||||
(void)close(fd);
|
||||
}
|
||||
syslog(LOGOPTS, "accept: %m\n");
|
||||
free_lock();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int is_standalone(void)
|
||||
{
|
||||
struct sockaddr_in bind_addr;
|
||||
socklen_t ba_len;
|
||||
|
||||
/*
|
||||
* Check to see if a socket was passed to us from inetd.
|
||||
*
|
||||
* Use getsockname() to determine if descriptor 0 is indeed a socket
|
||||
* (and thus we are probably a child of inetd) or if it is instead
|
||||
* something else and we are running standalone.
|
||||
*/
|
||||
ba_len = sizeof(bind_addr);
|
||||
if (getsockname(0, (struct sockaddr*) &bind_addr, &ba_len) == 0)
|
||||
return (0); /* under inetd */
|
||||
if (errno != ENOTSOCK) /* strange... */
|
||||
syslog(LOGOPTS, "getsockname: %m\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int c, lpnumber;
|
||||
char *p;
|
||||
|
||||
if (argc <= 0) /* in case not provided in inetd.conf */
|
||||
progname = "p910nd";
|
||||
else
|
||||
{
|
||||
progname = argv[0];
|
||||
if ((p = strrchr(progname, '/')) != 0)
|
||||
progname = p + 1;
|
||||
}
|
||||
lpnumber = '0';
|
||||
while ((c = getopt(argc, argv, "bi:f:v")) != EOF)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'b':
|
||||
bidir = 1;
|
||||
break;
|
||||
case 'f':
|
||||
device = optarg;
|
||||
break;
|
||||
case 'i':
|
||||
bindaddr = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
show_version();
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
if (argc > 0)
|
||||
{
|
||||
if (isdigit(argv[0][0]))
|
||||
lpnumber = argv[0][0];
|
||||
}
|
||||
/* change the n in argv[0] to match the port so ps will show that */
|
||||
if ((p = strstr(progname, "p910n")) != NULL)
|
||||
p[4] = lpnumber;
|
||||
|
||||
/* We used to pass (LOG_PERROR|LOG_PID|LOG_LPR|LOG_ERR) to syslog, but
|
||||
* syslog ignored the LOG_PID and LOG_PERROR option. I.e. the intention
|
||||
* was to add both options but the effect was to have neither.
|
||||
* I disagree with the intention to add PERROR. --Stef */
|
||||
openlog (p, LOG_PID, LOG_LPR);
|
||||
if (is_standalone())
|
||||
server(lpnumber);
|
||||
else
|
||||
one_job(lpnumber);
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# p910nd.sh This shell script takes care of starting and stopping
|
||||
# p910nd (port 9100+n printer daemon)
|
||||
# This script only controls the one on port 9101.
|
||||
# You can start others if you wish.
|
||||
#
|
||||
|
||||
# Todo: Make it fully LSB
|
||||
|
||||
# See how we were called.
|
||||
case "$1" in
|
||||
start)
|
||||
# Start daemons.
|
||||
echo -n "Starting p910nd: "
|
||||
# default port is 1 so it will appear as p9101d on a ps
|
||||
start_daemon p910nd
|
||||
echo
|
||||
;;
|
||||
stop)
|
||||
# Stop daemons.
|
||||
echo -n "Shutting down p910nd: "
|
||||
killproc p9101d
|
||||
echo
|
||||
rm -f /var/run/p9101.pid
|
||||
;;
|
||||
status)
|
||||
status p9101d
|
||||
;;
|
||||
restart)
|
||||
$0 stop
|
||||
$0 start
|
||||
;;
|
||||
*)
|
||||
echo "Usage: p910nd {start|stop|restart|status}"
|
||||
exit 1
|
||||
esac
|
||||
|
||||
exit 0
|
|
@ -0,0 +1,67 @@
|
|||
CPPFLAGS =
|
||||
LDLIBS =
|
||||
CFLAGS = -pipe -g -O2 -Wall
|
||||
LDFLAGS = -pipe
|
||||
CC = gcc
|
||||
LD = gcc
|
||||
# Some "black" magic to determine optimal compiler flags for target
|
||||
# architecture
|
||||
TARGET_ARCH:= $(shell if [ \! -r .compile-options ] ; then ( \
|
||||
cpu=`grep cpu /proc/cpuinfo 2>&1 |head -1| \
|
||||
cut -d : -f 2-| sed -e 's/ //g'`; \
|
||||
if [ x"$$cpu" = x"" ] ; then \
|
||||
echo -fno-strength-reduce; \
|
||||
else if [ "$$cpu" = "386" ] ; then \
|
||||
echo -m386 -fno-strength-reduce; \
|
||||
else if [ "$$cpu" = "486" ] ; then \
|
||||
echo -m486 -fno-strength-reduce; \
|
||||
else if [ "$$cpu" = "Alpha" ] ; then \
|
||||
echo -fno-strength-reduce; \
|
||||
else echo main\(\)\{\} >.compile-options.c; \
|
||||
if gcc -mpentium -o .compile-options.o -c \
|
||||
.compile-options.c &>/dev/null; then \
|
||||
echo -mpentium -fstrength-reduce; \
|
||||
else if gcc -m486 -malign-functions=2 -malign-jumps=2 \
|
||||
-malign-loops=2 -o .compile-options.o -c \
|
||||
.compile-options.c &>/dev/null; then \
|
||||
echo -n -m486 -malign-functions=2 -malign-jumps=2; \
|
||||
echo ' '-malign-loops=2 -fno-strength-reduce; \
|
||||
else echo -m486; \
|
||||
fi;fi;fi;fi;fi;fi) > .compile-options; \
|
||||
rm -f .compile-options.c .compile-options.o; \
|
||||
fi; cat .compile-options)
|
||||
ASFLAGS = $(TARGET_ARCH)
|
||||
|
||||
OBJS = ppmtoansi.o
|
||||
|
||||
##############################################################################
|
||||
|
||||
ifeq (.depend,$(wildcard .depend))
|
||||
all: ppmtoansi
|
||||
include .depend
|
||||
else
|
||||
all: depend
|
||||
@$(MAKE) all
|
||||
endif
|
||||
|
||||
##############################################################################
|
||||
|
||||
ppmtoansi: $(OBJS)
|
||||
|
||||
##############################################################################
|
||||
|
||||
clean:
|
||||
$(RM) *~ *.o *.dvi *.log *.aux *yacc.tab.[ch] *yacc.output *lex.[co] \
|
||||
*.dat .depend .tmp_depend .compile-options*
|
||||
strip ppmtoansi >&/dev/null || true
|
||||
|
||||
distclean: clean
|
||||
$(RM) -rf ppmtoansi
|
||||
|
||||
##############################################################################
|
||||
|
||||
depend:
|
||||
for i in *.c;do $(CPP) $(CPPFLAGS) -MM $$i;done >.tmp_depend
|
||||
mv .tmp_depend .depend
|
||||
|
||||
##############################################################################
|
|
@ -0,0 +1 @@
|
|||
[9;;1- [15;;1- [18;;5-Ûl[9;1;3-$€[13;1;3-$€[17;1;1-À[9;2;1- [12;2;1- [15;2;1- [17;2;1-À[9;3;1- [15;3;1- [18;3;5-Ûl[9;4;1- [15;4;1- [23;4;1-À[9;5;1- [15;5;1- [23;5;1-À[9;6;1- [15;6;1- [18;6;5-Ûl[8;8;4-I [14;8;4-m°[19;8;5-¶Ú[8;9;1-@[12;9;2-L[18;9;2-¬[8;10;1-@[11;10;1-`[13;10;1-@[18;10;1- [20;10;1-`[8;11;1-@[11;11;1-`[13;11;1-@[19;11;5-¶Ú[8;12;1-@[11;12;1-`[13;12;1-@[20;12;1-`[24;12;1- [8;13;1-@[12;13;2-L[18;13;2-l[24;13;1- [8;14;4-I [14;14;4-m°[19;14;5-¶Ú
|
|
@ -0,0 +1,51 @@
|
|||
P3
|
||||
17 16
|
||||
65535
|
||||
0 0 0 65535 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 65535 0 0 0 0 0 0 0 0 0 65535 65535 0 65535 65535
|
||||
0 65535 65535 0 65535 65535 0 65535 65535 0 0 0 0 0 0
|
||||
0 0 0 65535 0 0 65535 0 0 65535 0 0 0 0 0 65535 0 0
|
||||
65535 0 0 65535 0 0 0 0 0 0 65535 65535 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 65535 0 0 0 0 0 0 0 0 65535 0 0 0 0 0
|
||||
0 0 0 65535 0 0 0 0 0 0 65535 65535 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 65535 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 65535 0 0 0 0 0 0 0 0 0 65535 65535 0 65535 65535
|
||||
0 65535 65535 0 65535 65535 0 65535 65535 0 0 0 0 0 0
|
||||
0 0 0 65535 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 65535 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 65535 65535 0 0 0
|
||||
0 0 0 65535 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 65535 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 65535 65535 0 0 0
|
||||
0 0 0 65535 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 65535 0 0 0 0 0 0 0 0 0 65535 65535 0 65535 65535
|
||||
0 65535 65535 0 65535 65535 0 65535 65535 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 65535 0 0 65535 0 0 65535 0 0 65535 0 0 0 0 0 0 0
|
||||
65535 65535 0 65535 65535 0 65535 65535 0 65535 65535 0 0 0 0 65535 0 65535
|
||||
65535 0 65535 65535 0 65535 65535 0 65535 65535 0 65535 0 0 0
|
||||
0 65535 0 0 0 0 0 0 0 0 0 0 0 65535 0 65535 65535 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 65535 0 65535 65535 65535 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 65535 0 0 0 0 0 0 0 65535 65535 0 0 0 0 0 65535 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 65535 0 65535 0 0 0
|
||||
65535 65535 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 65535 0 0 0 0 0 0 0 65535 65535 0 0 0 0 0 65535 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 65535 0 65535
|
||||
65535 0 65535 65535 0 65535 65535 0 65535 65535 0 65535 0 0 0
|
||||
0 65535 0 0 0 0 0 0 0 65535 65535 0 0 0 0 0 65535 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
65535 65535 0 0 0 0 0 0 0 0 0 0 65535 0 65535
|
||||
0 65535 0 0 0 0 0 0 0 0 0 0 0 65535 0 65535 65535 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 65535 65535 0 65535 65535 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 65535 0 65535
|
||||
0 65535 0 0 65535 0 0 65535 0 0 65535 0 0 0 0 0 0 0
|
||||
65535 65535 0 65535 65535 0 65535 65535 0 65535 65535 0 0 0 0 65535 0 65535
|
||||
65535 0 65535 65535 0 65535 65535 0 65535 65535 0 65535 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
|
@ -0,0 +1,29 @@
|
|||
/* XPM */
|
||||
static char *noname[] = {
|
||||
/* width height ncolors chars_per_pixel */
|
||||
"17 16 6 1",
|
||||
/* colors */
|
||||
"` c #000000",
|
||||
"a c #00FFFF",
|
||||
"b c #00FF00",
|
||||
"c c #FF00FF",
|
||||
"d c #FF0000",
|
||||
"e c #FFFF00",
|
||||
/* pixels */
|
||||
"`d`````d``aaaaa``",
|
||||
"`ddd`ddd`a```````",
|
||||
"`d``d``d`a```````",
|
||||
"`d`````d``aaaaa``",
|
||||
"`d`````d```````a`",
|
||||
"`d`````d```````a`",
|
||||
"`d`````d``aaaaa``",
|
||||
"`````````````````",
|
||||
"bbbb``eeee`ccccc`",
|
||||
"b```be````ce`````",
|
||||
"b``e`b````c`e````",
|
||||
"b``e`b`````ccccc`",
|
||||
"b``e`b``````e```c",
|
||||
"b```be````ee````c",
|
||||
"bbbb``eeee`ccccc`",
|
||||
"`````````````````"
|
||||
};
|
Binary file not shown.
|
@ -0,0 +1,99 @@
|
|||
P3
|
||||
32 16
|
||||
65535
|
||||
0 0 0 0 0 0 0 65535 65535 0 0 0 0 0 0 0 65535 65535
|
||||
0 0 0 0 0 0 0 65535 65535 0 0 0 0 0 0 0 65535 65535
|
||||
0 0 0 0 0 0 0 65535 65535 0 0 0 0 0 0 0 65535 65535
|
||||
0 0 0 0 0 0 0 65535 65535 0 0 0 0 0 0 0 65535 65535
|
||||
0 0 0 0 0 0 0 65535 65535 0 0 0 0 0 0 0 65535 65535
|
||||
0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 65535 65535 0 0 0 0 0 0 0 65535 65535
|
||||
0 0 0 0 0 0 0 65535 65535 0 0 0 0 0 0 0 65535 65535
|
||||
0 0 0 0 0 0 0 65535 65535 0 0 0 0 0 0 0 65535 65535
|
||||
0 0 0 0 0 0 0 65535 65535 0 0 0 0 0 0 0 65535 65535
|
||||
0 0 0 0 0 0 0 65535 65535 0 0 0 0 0 0 0 65535 65535
|
||||
0 0 0 0 0 0
|
||||
65535 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0 0
|
||||
65535 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0 0
|
||||
65535 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0 0
|
||||
65535 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0 0
|
||||
65535 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0 0
|
||||
65535 0 0 65535 0 0
|
||||
65535 0 0 0 0 0 0 0 0 0 65535 0 0 65535 0 0 65535 0
|
||||
0 65535 0 0 0 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0
|
||||
0 0 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0 0 0 0
|
||||
0 65535 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0 0 0 0
|
||||
0 65535 0 0 65535 0 0 65535 0 0 65535 0 0 0 0 0 0 0
|
||||
0 0 0 65535 0 0
|
||||
65535 0 0 0 0 0 0 0 0 0 65535 0 0 65535 0 0 65535 0
|
||||
0 65535 0 0 0 0 0 65535 0 0 0 0 0 0 0 0 65535 0
|
||||
0 0 0 0 65535 0 0 0 0 0 0 0 0 65535 0 0 0 0
|
||||
0 0 0 0 0 0 0 65535 0 0 0 0 0 0 0 0 0 0
|
||||
0 65535 0 0 65535 0 0 65535 0 0 65535 0 0 0 0 0 0 0
|
||||
0 0 0 65535 0 0
|
||||
65535 0 0 0 0 0 0 0 0 0 65535 0 0 0 0 0 0 0
|
||||
0 65535 0 0 0 0 0 65535 0 0 0 0 0 0 0 0 65535 0
|
||||
0 0 0 0 65535 0 0 0 0 0 0 0 0 65535 0 0 0 0
|
||||
0 0 0 0 0 0 0 65535 0 0 0 0 0 0 0 0 0 0
|
||||
0 65535 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 65535 0 0
|
||||
0 0 0 65535 0 0 0 0 0 0 65535 0 0 65535 0 0 65535 0
|
||||
0 65535 0 0 0 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0
|
||||
0 0 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0 0 0 0
|
||||
0 0 0 0 0 0 0 65535 0 0 0 0 0 0 0 0 0 0
|
||||
0 65535 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 65535 0 0
|
||||
0 0 0 0 0 0 65535 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 65535 0 0
|
||||
0 0 0 65535 0 0 0 0 0 0 65535 0 0 65535 0 0 65535 0
|
||||
0 65535 0 0 65535 0 0 0 0 0 65535 0 0 65535 0 0 65535 0
|
||||
0 65535 0 0 0 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0
|
||||
0 65535 0 0 0 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 65535 0 0
|
||||
65535 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 65535 0
|
||||
0 0 0 0 0 0 0 0 0 0 65535 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 65535 0 0 0 0
|
||||
0 0 0 0 0 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 65535 0 0
|
||||
65535 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 65535 0
|
||||
0 0 0 0 0 0 0 0 0 0 65535 0 0 65535 0 0 65535 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 65535 0 0 0 0
|
||||
0 0 0 0 0 0 0 65535 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 65535 0 0
|
||||
65535 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 65535 0
|
||||
0 0 0 0 0 0 0 0 0 0 65535 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 65535 0 0 0 0
|
||||
0 0 0 0 0 0 0 65535 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 65535 0 0
|
||||
65535 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0 0
|
||||
65535 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0 0
|
||||
65535 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0 0
|
||||
65535 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0 0
|
||||
65535 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0 0 65535 0 0
|
||||
65535 0 0 65535 0 0
|
||||
0 0 0 0 0 0 0 65535 65535 0 0 0 0 0 0 0 65535 65535
|
||||
0 0 0 0 0 0 0 65535 65535 0 0 0 0 0 0 0 65535 65535
|
||||
0 0 0 0 0 0 0 65535 65535 0 0 0 0 0 0 0 65535 65535
|
||||
0 0 0 0 0 0 0 65535 65535 0 0 0 0 0 0 0 65535 65535
|
||||
0 0 0 0 0 0 0 65535 65535 0 0 0 0 0 0 0 65535 65535
|
||||
0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 65535 65535 0 0 0 0 0 0 0 65535 65535
|
||||
0 0 0 0 0 0 0 65535 65535 0 0 0 0 0 0 0 65535 65535
|
||||
0 0 0 0 0 0 0 65535 65535 0 0 0 0 0 0 0 65535 65535
|
||||
0 0 0 0 0 0 0 65535 65535 0 0 0 0 0 0 0 65535 65535
|
||||
0 0 0 0 0 0 0 65535 65535 0 0 0 0 0 0 0 65535 65535
|
||||
0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0
|
|
@ -0,0 +1,27 @@
|
|||
/* XPM */
|
||||
static char *noname[] = {
|
||||
/* width height ncolors chars_per_pixel */
|
||||
"32 16 4 1",
|
||||
/* colors */
|
||||
"` c #000000",
|
||||
"a c #00FFFF",
|
||||
"b c #00FF00",
|
||||
"c c #FF0000",
|
||||
/* pixels */
|
||||
"``a``a``a``a``a``a``a``a``a``a``",
|
||||
"``a``a``a``a``a``a``a``a``a``a``",
|
||||
"cccccccccccccccccccccccccccccccc",
|
||||
"c``bbbb`bbbb`bbbb`bbbbb`bbbb```c",
|
||||
"c``bbbb`b``b`b``b```b```bbbb```c",
|
||||
"c``b``b`b``b`b``b```b```b``````c",
|
||||
"`c`bbbb`bbbb`bbbb```b```b``````c",
|
||||
"``c````````````````````````````c",
|
||||
"`c`bbbbb`bbbb`bbbbb`bbbb```````c",
|
||||
"c````b```b``````b```bbbb```````c",
|
||||
"c````b```bbb````b```b``````````c",
|
||||
"c````b```b``````b```b``````````c",
|
||||
"cccccccccccccccccccccccccccccccc",
|
||||
"``a``a``a``a``a``a``a``a``a``a``",
|
||||
"``a``a``a``a``a``a``a``a``a``a``",
|
||||
"````````````````````````````````"
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
[11;;2-l[11;1;2-l[17;1;1-`[11;2;2-l[16;2;2-l[11;3;2-l[15;3;3-m€[11;4;2-l[14;4;4-m°[11;5;2-l[14;5;4-m°[11;6;4-m°[16;6;2-l[11;7;4-m°[16;7;2-l[11;8;3-m€[16;8;2-l[11;9;2-l[16;9;2-l[11;10;1-`[16;10;2-l[16;11;2-l[13;12;2-l[16;12;2-l[19;12;2-l[14;13;6-m¶À[15;14;4-m°[16;15;2-l
|
|
@ -0,0 +1,35 @@
|
|||
P3
|
||||
10 16
|
||||
65535
|
||||
65535 65535 0 65535 65535 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0
|
||||
65535 65535 0 65535 65535 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
65535 65535 0 0 0 0 0 0 0 0 0 0
|
||||
65535 65535 0 65535 65535 0 0 0 0 0 0 0 0 0 0 65535 65535 0
|
||||
65535 65535 0 0 0 0 0 0 0 0 0 0
|
||||
65535 65535 0 65535 65535 0 0 0 0 0 0 0 65535 65535 0 65535 65535 0
|
||||
65535 65535 0 0 0 0 0 0 0 0 0 0
|
||||
65535 65535 0 65535 65535 0 0 0 0 65535 65535 0 65535 65535 0 65535 65535 0
|
||||
65535 65535 0 0 0 0 0 0 0 0 0 0
|
||||
65535 65535 0 65535 65535 0 0 0 0 65535 65535 0 65535 65535 0 65535 65535 0
|
||||
65535 65535 0 0 0 0 0 0 0 0 0 0
|
||||
65535 65535 0 65535 65535 0 65535 65535 0 65535 65535 0 0 0 0 65535 65535 0
|
||||
65535 65535 0 0 0 0 0 0 0 0 0 0
|
||||
65535 65535 0 65535 65535 0 65535 65535 0 65535 65535 0 0 0 0 65535 65535 0
|
||||
65535 65535 0 0 0 0 0 0 0 0 0 0
|
||||
65535 65535 0 65535 65535 0 65535 65535 0 0 0 0 0 0 0 65535 65535 0
|
||||
65535 65535 0 0 0 0 0 0 0 0 0 0
|
||||
65535 65535 0 65535 65535 0 0 0 0 0 0 0 0 0 0 65535 65535 0
|
||||
65535 65535 0 0 0 0 0 0 0 0 0 0
|
||||
65535 65535 0 0 0 0 0 0 0 0 0 0 0 0 0 65535 65535 0
|
||||
65535 65535 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 65535 65535 0
|
||||
65535 65535 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 65535 65535 0 65535 65535 0 0 0 0 65535 65535 0
|
||||
65535 65535 0 0 0 0 65535 65535 0 65535 65535 0
|
||||
0 0 0 0 0 0 0 0 0 65535 65535 0 65535 65535 0 65535 65535 0
|
||||
65535 65535 0 65535 65535 0 65535 65535 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 65535 65535 0 65535 65535 0
|
||||
65535 65535 0 65535 65535 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 65535 65535 0
|
||||
65535 65535 0 0 0 0 0 0 0 0 0 0
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue