david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

Initial revision

This commit is contained in:
Michael Brown 2005-05-17 16:44:57 +00:00
parent 75a5374d79
commit 1097cf8685
164 changed files with 24592 additions and 0 deletions

339
COPYING Normal file
View File

@ -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.

20
Copyrights Normal file
View File

@ -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

28
INSTALL Normal file
View File

@ -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.

2863
LOG Normal file

File diff suppressed because it is too large Load Diff

43
RELNOTES Normal file
View File

@ -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.

1
VERSION Normal file
View File

@ -0,0 +1 @@
5.4.0 2005-04-01

View File

@ -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

31
contrib/3c90xutil/README Normal file
View File

@ -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.

View File

@ -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__ */

View File

@ -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__ */

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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">&quot;Diskless Windows
Cookbook &quot;</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>

40
contrib/auto-default/mail Normal file
View File

@ -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.]

View File

@ -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');

View File

@ -0,0 +1,2 @@
An Award BIOS ROM lister in Perl contributed by Eric W. Biederman
<ebiederman@lnxi.com>.

View File

@ -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);

475
contrib/baremetal/Makefile Normal file
View File

@ -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)

1119
contrib/baremetal/main.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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]

351
contrib/baremetal/misc.c Normal file
View File

@ -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;
}

View File

@ -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 */

View File

@ -0,0 +1,9 @@
CC=gcc
CFLAGS=-Wall -O2
bin2intelhex:
clean:
rm -f bin2intelhex core *.o

View File

@ -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);
}

View File

@ -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);
}

5
contrib/bochs/.cvsignore Normal file
View File

@ -0,0 +1,5 @@
bochsout.txt
parport.out
ne2k-tx.log
ne2k-txdump.txt

7
contrib/bochs/Makefile Normal file
View File

@ -0,0 +1,7 @@
all : serial-console.1
%.1 : %
pod2man $< > $@
clean :
rm -f serial-console.1

121
contrib/bochs/README Normal file
View File

@ -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.

658
contrib/bochs/bochsrc.txt Normal file
View File

@ -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
#=======================================================================

21
contrib/bochs/ifup.tun Executable file
View File

@ -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

278
contrib/bochs/serial-console Executable file
View File

@ -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 );
}
}

View File

@ -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.

View File

@ -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 = $_;
}

View File

@ -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.

View File

@ -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.

View File

@ -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)

764
contrib/compressor/lzhuf.c Normal file
View File

@ -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

View File

@ -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";
}

View File

@ -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 #############

884
contrib/dhcpid/dhcpid.txt Normal file
View File

@ -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--

View File

@ -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

View File

@ -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/

View File

@ -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

29
contrib/flashimg/Makefile Normal file
View File

@ -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

View File

@ -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.

15
contrib/hdload/Makefile Normal file
View File

@ -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

162
contrib/hdload/hdload.S Normal file
View File

@ -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

175
contrib/hdload/petr.msg Normal file
View File

@ -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.

46
contrib/initrd/ChangeLog Normal file
View File

@ -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

187
contrib/initrd/Makefile Normal file
View File

@ -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

15
contrib/initrd/Manifest Normal file
View File

@ -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

37
contrib/initrd/README Normal file
View File

@ -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>.

View File

@ -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 {
}
}

63
contrib/initrd/include-modules Executable file
View File

@ -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";
}

View File

@ -0,0 +1,7 @@
# Dummy config file for building only wlanctl
# $Id$
PRISM2_PLX=n
PRISM2_PCMCIA=n
PRISM2_PCI=n
PRISM2_USB=n

76
contrib/initrd/linuxrc Normal file
View File

@ -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

165
contrib/initrd/mkinitrd-net Executable file
View File

@ -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

View File

@ -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

200
contrib/initrd/mknbi-set Executable file
View File

@ -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";
}
}
}
}

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

339
contrib/mini-slamd/COPYING Normal file
View File

@ -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.

View File

@ -0,0 +1,8 @@
CC=gcc
CFLAGS=-Wall -O2
mini-slamd: mini-slamd.c
$(CC) $(CFLAGS) -o $@ $<
clean:
rm -f mini-slamd

View File

@ -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;
}

10
contrib/mkQNXnbi/Makefile Normal file
View File

@ -0,0 +1,10 @@
# Makefile for the mkQNXnbi filter
all: mkQNXnbi
mkQNXnbi: mkQNXnbi.o
mkQNXnbi.o: mkQNXnbi.c
clean:
rm -f mkQNXnbi *.o

36
contrib/mkQNXnbi/README Normal file
View File

@ -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>

View File

@ -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>:

View File

@ -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}>

View File

@ -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}>

196
contrib/mkQNXnbi/mkQNXnbi.c Normal file
View File

@ -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;
}

76
contrib/mkffwnb/2.0.10/linuxrc Executable file
View File

@ -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

View File

@ -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;

69
contrib/mkffwnb/README Normal file
View File

@ -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

226
contrib/mkffwnb/mkffwnb.pl Executable file
View File

@ -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");
}

View File

@ -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.

View File

@ -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;

45
contrib/mklrpnb/mklrpnb Executable file
View File

@ -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;

97
contrib/mntnbi/mntnbi.pl Executable file
View File

@ -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);

2
contrib/nfs-swap/README Normal file
View File

@ -0,0 +1,2 @@
For more information please check
http://nfs-swap.dot-heine.de

View File

@ -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)

9
contrib/p910nd-0.8/banner.pl Executable file
View File

@ -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

58
contrib/p910nd-0.8/client.pl Executable file
View File

@ -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;
}

View File

@ -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

420
contrib/p910nd-0.8/p910nd.c Normal file
View File

@ -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);
}

39
contrib/p910nd-0.8/p910nd.sh Executable file
View File

@ -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

View File

@ -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
##############################################################################

View File

@ -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-¶Ú

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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``",
"````````````````````````````````"
};

View File

@ -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

View File

@ -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