Initial revision

This commit is contained in:
Michael Brown
2005-03-08 18:53:11 +00:00
commit 3d6123e69a
373 changed files with 114041 additions and 0 deletions

48
src/util/catrom.pl Executable file
View File

@@ -0,0 +1,48 @@
#!/usr/bin/perl -w
use warnings;
use strict;
use bytes;
use constant MAX_ROM_LEN => 1024*1024;
use constant PCI_OFF => 0x18;
use constant INDICATOR_OFF => 0x15;
my $total_len = 0;
my @romfiles = @ARGV
or die "Usage: $0 rom-file-1 rom-file-2 ... > multi-rom-file\n";
while ( my $romfile = shift @romfiles ) {
my $last = @romfiles ? 0 : 1;
open ROM, "<$romfile" or die "Could not open $romfile: $!\n";
my $len = read ( ROM, my $romdata, MAX_ROM_LEN )
or die "Could not read $romfile: $!\n";
close ROM;
die "$romfile is not a ROM file\n"
unless substr ( $romdata, 0, 2 ) eq "\x55\xAA";
( my $checklen ) = unpack ( 'C', substr ( $romdata, 2, 1 ) );
$checklen *= 512;
die "$romfile has incorrect length field $checklen (should be $len)\n"
unless $len == $checklen;
( my $pci ) = unpack ( 'v', substr ( $romdata, PCI_OFF, 2 ) );
die "Invalid PCI offset field in $romfile\n"
if $pci >= $len;
die "No PCIR signature in $romfile\n"
unless substr ( $romdata, $pci, 4 ) eq "PCIR";
( my $indicator ) =
unpack ( 'C', substr ( $romdata, $pci + INDICATOR_OFF, 1 ) );
my $msg = sprintf ( "$romfile: indicator was %02x, ", $indicator );
$indicator &= ! ( 1 << 7 );
$indicator |= ( $last << 7 );
$msg .= sprintf ( "now %02x\n", $indicator );
substr ( $romdata, $pci + INDICATOR_OFF, 1 ) = pack ( 'C', $indicator );
warn $msg;
print $romdata;
}

114
src/util/disrom.pl Executable file
View File

@@ -0,0 +1,114 @@
#!/usr/bin/perl -w
#
# Program to display key information about a boot ROM
# including PCI and PnP structures
#
# GPL, Ken Yap 2001
#
use bytes;
sub getid ($)
{
my ($offset) = @_;
return '' if ($offset == 0 or $offset > $len);
my ($string) = unpack('Z32', substr($data, $offset, 32));
return ($string);
}
sub dispci
{
my ($pcidata) = substr($data, $pci, 0x18);
my ($dummy, $vendorid, $deviceid, $vpd, $pcilen, $pcirev,
$class1, $class2, $class3, $imglen, $coderev, $codetype,
$indicator) = unpack('a4v4C4v2C2', $pcidata);
$imglen *= 512;
my $vendorstr = sprintf('%#04x', $vendorid);
my $devicestr = sprintf('%#04x', $deviceid);
my $coderevstr = sprintf('%#04x', $coderev);
print <<EOF;
PCI structure:
Vital product data: $vpd
Vendor ID: $vendorstr
Device ID: $devicestr
Device base type: $class1
Device sub type: $class2
Device interface type: $class3
Image length: $imglen
Code revision: $coderevstr
Code type: $codetype
Indicator: $indicator
EOF
}
sub dispnp
{
my ($pnpdata) = substr($data, $pnp, 0x20);
my ($dummy1, $pnprev, $pnplen, $nextpnp, $dummy2,
$pnpcsum, $deviceid, $mfrid, $productid,
$class1, $class2, $class3, $indicator,
$bcv, $dv, $bev, $dummy, $sri) = unpack('a4C2vC2a4v2C4v5', $pnpdata);
print <<EOF;
PnP structure:
EOF
print 'Vendor: ', &getid($mfrid), "\n";
print 'Device: ', &getid($productid), "\n";
my $indicatorstr = sprintf('%#02x', $indicator);
my $bcvstr = sprintf('%#04x', $bcv);
my $dvstr = sprintf('%#04x', $dv);
my $bevstr = sprintf('%#04x', $bev);
my $sristr = sprintf('%#04x', $sri);
my $checksum = unpack('%8C*', $pnpdata);
print <<EOF;
Device base type: $class1
Device sub type: $class2
Device interface type: $class3
Device indicator: $indicatorstr
Boot connection vector: $bcvstr
Disconnect vector: $dvstr
Bootstrap entry vector: $bevstr
Static resource information vector: $sristr
Checksum: $checksum
EOF
}
sub pcipnp
{
($pci, $pnp) = unpack('v2', substr($data, 0x18, 4));
if ($pci >= $len or $pnp >= $len) {
print "$file: Not a PCI PnP ROM image\n";
return;
}
if (substr($data, $pci, 4) ne 'PCIR' or substr($data, $pnp, 4) ne '$PnP') {
print "$file: No PCI and PNP structures, not a PCI PNP ROM image\n";
return;
}
&dispci();
&dispnp();
}
$file = $#ARGV >= 0 ? $ARGV[0] : '-';
open(F, "$file") or die "$file: $!\n";
binmode(F);
# Handle up to 64kB ROM images
$len = read(F, $data, 64*1024);
close(F);
defined($len) or die "$file: $!\n";
substr($data, 0, 2) eq "\x55\xAA" or die "$file: Not a boot ROM image\n";
my ($codelen) = unpack('C', substr($data, 2, 1));
$codelen *= 512;
if ($codelen < $len) {
my $pad = $len - $codelen;
print "Image is $codelen bytes and has $pad bytes of padding following\n";
$data = substr($data, 0, $codelen);
} elsif ($codelen > $len) {
print "Image should be $codelen bytes but is truncated to $len bytes\n";}
&pcipnp();
($csum) = unpack('%8C*', $data);
print "ROM checksum: $csum \n";
exit(0);

56
src/util/geniso Executable file
View File

@@ -0,0 +1,56 @@
#!/bin/bash
#
# Generate a isolinux ISO boot image
#
# geniso foo.iso foo.zlilo
#
# the ISO image is the first argument so that a list of .zlilo images
# to include can be specified
#
case $# in
0|1)
echo Usage: $0 foo.iso foo.zlilo ...
exit 1
;;
esac
# This should be the default location of the isolinux.bin file
isolinux_bin=${ISOLINUX_BIN:-util/isolinux.bin}
if [ ! -r $isolinux_bin ]
then
echo $0: $isolinux_bin not found, please install, or set ISOLINUX_BIN in arch/i386/config correctly
exit 1
fi
out=$1
shift
dir=bin/iso.dir
mkdir -p $dir
cfg=$dir/isolinux.cfg
cp -p $isolinux_bin $dir
cat > $cfg <<EOF
# These default options can be changed in the geniso script
SAY Etherboot ISO boot image generated by geniso
TIMEOUT 30
EOF
first=
for f
do
if [ ! -r $f ]
then
echo $f does not exist, skipping 1>&2
continue
fi
b=$(basename $f)
g=${b%.zlilo}
g=${g//[^a-z0-9]}.zli
case "$first" in
"")
echo DEFAULT $g
;;
esac
first=$g
echo LABEL $b
echo "" KERNEL $g
cp -p $f $dir/$g
done >> $cfg
mkisofs -l -o $out -c boot.cat -b isolinux.bin -no-emul-boot -boot-load-size 4 -boot-info-table $dir
rm -fr $dir

85
src/util/genliso Executable file
View File

@@ -0,0 +1,85 @@
#!/bin/bash
#
# Generate a legacy floppy emulation ISO boot image
#
# genliso foo.liso foo.zlilo
#
# the ISO image is the first argument so that a list of .zlilo images
# to include can be specified
#
case $0 in
*genliso)
;;
*genfdimg)
genfdimg=1
;;
esac
case $# in
0|1)
echo Usage: $0 foo.liso foo.zlilo ...
exit 1
;;
esac
case "`mtools -V`" in
Mtools\ version\ 3.9.9*|Mtools\ version\ 4.*)
;;
*)
echo Mtools version 3.9.9 or later is required
exit 1
;;
esac
out=$1
shift
dir=bin/liso.dir
mkdir -p $dir
case "$genfdimg" in
1)
img=$out
;;
*)
img=$dir/boot.img
;;
esac
mformat -f 1440 -C -i $img ::
cfg=bin/syslinux.cfg
cat > $cfg <<EOF
# These default options can be changed in the genliso script
SAY Etherboot ISO boot image generated by genliso
TIMEOUT 30
EOF
first=
for f
do
if [ ! -r $f ]
then
echo $f does not exist, skipping 1>&2
continue
fi
# shorten name for 8.3 filesystem
b=$(basename $f)
g=${b%.zlilo}
g=${g//[^a-z0-9]}
g=${g:0:8}.zli
case "$first" in
"")
echo DEFAULT $g
;;
esac
first=$g
echo LABEL $b
echo "" KERNEL $g
mcopy -m -i $img $f ::$g
done >> $cfg
mcopy -i $img $cfg ::syslinux.cfg
if ! syslinux $img
then
exit 1
fi
case "$genfdimg" in
1)
;;
*)
mkisofs -o $out -c boot.cat -b boot.img $dir
;;
esac
rm -fr $dir

135
src/util/get-pci-ids Executable file
View File

@@ -0,0 +1,135 @@
#! /usr/bin/perl -w
# get-pci-ids: extract pci vendor/device ids from linux net drivers
# Copyright (C) 2003 Georg Baum <gbaum@users.sf.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# Known bugs/limitations:
# - Does not recognize all drivers because some require special cflags.
# Fails also on some drivers that do belong to other architectures
# than the one of the machine this script is running on.
# This is currently not so important because all drivers that have an
# Etherboot counterpart are recognized.
use strict;
use File::Basename "dirname";
use POSIX "uname";
# Where to find the kernel sources
my $kernel_src = "/usr/src/linux";
if($#ARGV >= 0) {
$kernel_src = shift;
}
# Sanity checks
if($#ARGV >= 0) {
print STDERR "Too many arguments.\n";
print STDERR "Usage: get-pci-ids [path to kernel sources]\n";
print STDERR " /usr/src/linux is assumed if no path is given.\n";
exit 1;
}
unless(-f "$kernel_src/include/linux/version.h") {
print STDERR "Could not find $kernel_src/include/linux/version.h.\n";
print STDERR "$kernel_src is probably no Linux kernel source tree.\n";
exit 1;
}
# Flags that are needed to preprocess the drivers.
# Some drivers need optimization
my $cflags="-D__KERNEL__ -I$kernel_src/include -I$kernel_src/net/inet -O2";
# The C preprocessor. It needs to spit out the preprocessed source on stdout.
my $cpp="gcc -E";
# List of drivers. We parse every .c file. It does not harm if it does not contain a driver.
my @drivers = split /\s+/, `find $kernel_src/drivers/net -name '*.c' | sort`;
# Kernel version
my $version = `grep UTS_RELEASE $kernel_src/include/linux/version.h`;
chomp $version;
$version =~ s/\s*#define\s+UTS_RELEASE\s+"(\S+)".*$/$1/g;
# Architecture
my @uname = uname();
# Print header
print "# PCI vendor/device ids extracted from Linux $version on $uname[4] at " . gmtime() . "\n";
my $driver;
# Process the drivers
foreach $driver (@drivers) {
# Preprocess to expand macros
my $command = "$cpp $cflags -I" . dirname($driver) . " $driver";
open DRIVER, "$command |" or die "Could not execute\n\"$command\".\n";
# Extract the pci_device_id structure
my $found = 0;
my $line = "";
my @lines;
while(<DRIVER>) {
if(/^\s*static\s+struct\s+pci_device_id/) {
# This file contains a driver. Print the name.
$driver =~ s!$kernel_src/drivers/net/!!g;
print "\n$driver\n";
$found = 1;
next;
}
if($found == 1){
if(/\};/ or /{\s*0\s*,?\s*}/) {
# End of struct
$found = 0;
} else {
chomp;
if(/\}\s*,?\s*\n?$/) {
# This line contains a full entry or the last part of it.
$_ = $line . $_;
$line = "";
s/[,\{\};\(\)]//g; # Strip punctuation
s/^\s+//g; # Eat whitespace at beginning of line
tr[A-Z][a-z]; # Convert to lowercase
# Push the vendor and device id to @lines if this line is not empty.
# We ignore everything else that might be there
my ($vendor_id, $device_id, $remainder) = split /\W+/, $_, 3;
push @lines, "$vendor_id $device_id\n" if($vendor_id && $device_id);
} else {
# This line does contain a partial entry. Remember it.
$line .= "$_ ";
}
}
}
}
close DRIVER; # No "or die", because $cpp fails on some files
# Now print out the sorted values
@lines = sort @lines;
my $lastline = "";
foreach(@lines) {
# Print each vendor/device id combination only once.
# Some drivers (e.g. e100) do contain subfamilies
print if($_ ne $lastline);
$lastline = $_;
}
}

764
src/util/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

40
src/util/makelilo.pl Executable file
View File

@@ -0,0 +1,40 @@
#!/usr/bin/perl -w
use constant SYSSIZE_LOC => 500; # bytes from beginning of boot block
use constant MINSIZE => 32768;
use strict;
use bytes;
$#ARGV >= 1 or die "Usage: $0 liloprefix file ...\n";
open(L, "$ARGV[0]") or die "$ARGV[0]: $!\n";
undef($/);
my $liloprefix = <L>;
close(L);
length($liloprefix) >= 512 or die "LILO prefix too short\n";
shift(@ARGV);
my $totalsize = 0;
for my $file (@ARGV) {
next if (! -f $file or ! -r $file);
$totalsize += -s $file;
}
my $pad = 0;
if ($totalsize < MINSIZE) {
$pad = MINSIZE - $totalsize;
$totalsize = MINSIZE;
}
print STDERR "LILO payload is $totalsize bytes\n";
$totalsize += 16;
$totalsize >>= 4;
substr($liloprefix, SYSSIZE_LOC, 2) = pack('v', $totalsize);
print $liloprefix;
for my $file (@ARGV) {
next unless open(I, "$file");
undef($/);
my $data = <I>;
print $data;
close(I);
}
print "\x0" x $pad;
exit(0);

226
src/util/makerom.pl Executable file
View File

@@ -0,0 +1,226 @@
#!/usr/bin/perl -w
use Getopt::Std;
use constant MINROMSIZE => 8192;
use constant MAXROMSIZE => 262144;
use constant PCI_PTR_LOC => 0x18; # from beginning of ROM
use constant PCI_HDR_SIZE => 0x18;
use constant PNP_PTR_LOC => 0x1a; # from beginning of ROM
use constant PNP_HDR_SIZE => 0x20;
use constant PNP_CHKSUM_OFF => 0x9; # bytes from beginning of PnP header
use constant PNP_DEVICE_OFF => 0x10; # bytes from beginning of PnP header
use constant PCI_VEND_ID_OFF => 0x4; # bytes from beginning of PCI header
use constant PCI_DEV_ID_OFF => 0x6; # bytes from beginning of PCI header
use constant PCI_SIZE_OFF => 0x10; # bytes from beginning of PCI header
use constant UNDI_PTR_LOC => 0x16; # from beginning of ROM
use constant UNDI_HDR_SIZE => 0x16;
use constant UNDI_CHKSUM_OFF => 0x05;
use strict;
use vars qw(%opts);
use bytes;
sub getromsize ($) {
my ($romref) = @_;
my $i;
print STDERR "BIOS extension ROM Image did not start with 0x55 0xAA\n"
if (substr($$romref, 0, 2) ne "\x55\xaa");
my $size = ord(substr($$romref, 2, 1)) * 512;
for ($i = MINROMSIZE; $i < MAXROMSIZE and $i < $size; $i *= 2) { }
print STDERR "$size is a strange size for a boot ROM\n"
if ($size > 0 and $i > $size);
return ($size);
}
sub addident ($) {
my ($romref) = @_;
return (0) unless (my $s = $opts{'i'});
# include the terminating NUL byte too
$s .= "\x00";
my $len = length($s);
# Put the identifier in only if the space is blank
my $pos = length($$romref) - $len - 2;
return (0) if (substr($$romref, $pos, $len) ne ("\xFF" x $len));
substr($$romref, $pos, $len) = $s;
return ($pos);
}
sub pcipnpheaders ($$) {
my ($romref, $identoffset) = @_;
my ($pci_hdr_offset, $pnp_hdr_offset);
$pci_hdr_offset = unpack('v', substr($$romref, PCI_PTR_LOC, 2));
$pnp_hdr_offset = unpack('v', substr($$romref, PNP_PTR_LOC, 2));
# Sanity checks
if ($pci_hdr_offset < PCI_PTR_LOC + 2
or $pci_hdr_offset > length($$romref) - PCI_HDR_SIZE
or $pnp_hdr_offset < PNP_PTR_LOC + 2
or $pnp_hdr_offset > length($$romref) - PNP_HDR_SIZE
or substr($$romref, $pci_hdr_offset, 4) ne 'PCIR'
or substr($$romref, $pnp_hdr_offset, 4) ne '$PnP') {
$pci_hdr_offset = $pnp_hdr_offset = 0;
} else {
printf "PCI header at %#x and PnP header at %#x\n",
$pci_hdr_offset, $pnp_hdr_offset;
}
if ($pci_hdr_offset > 0) {
my ($pci_vendor_id, $pci_device_id);
# if no -p option, just report what's there
if (!defined($opts{'p'})) {
$pci_vendor_id = unpack('v', substr($$romref, $pci_hdr_offset+PCI_VEND_ID_OFF, 2));
$pci_device_id = unpack('v', substr($$romref, $pci_hdr_offset+PCI_DEV_ID_OFF, 2));
printf "PCI Vendor ID %#x Device ID %#x\n",
$pci_vendor_id, $pci_device_id;
} else {
substr($$romref, $pci_hdr_offset + PCI_SIZE_OFF, 2)
= pack('v', length($$romref) / 512);
($pci_vendor_id, $pci_device_id) = split(/,/, $opts{'p'});
substr($$romref, $pci_hdr_offset+PCI_VEND_ID_OFF, 2)
= pack('v', oct($pci_vendor_id)) if ($pci_vendor_id);
substr($$romref, $pci_hdr_offset+PCI_DEV_ID_OFF, 2)
= pack('v', oct($pci_device_id)) if ($pci_device_id);
}
}
if ($pnp_hdr_offset > 0 and defined($identoffset)) {
# Point to device id string at end of ROM image
substr($$romref, $pnp_hdr_offset+PNP_DEVICE_OFF, 2)
= pack('v', $identoffset);
substr($$romref, $pnp_hdr_offset+PNP_CHKSUM_OFF, 1) = "\x00";
my $sum = unpack('%8C*', substr($$romref, $pnp_hdr_offset,
PNP_HDR_SIZE));
substr($$romref, $pnp_hdr_offset+PNP_CHKSUM_OFF, 1) = chr(256 - $sum);
}
}
sub undiheaders ($) {
my ($romref) = @_;
my ($undi_hdr_offset);
$undi_hdr_offset = unpack('v', substr($$romref, UNDI_PTR_LOC, 2));
# Sanity checks
if ($undi_hdr_offset < UNDI_PTR_LOC + 2
or $undi_hdr_offset > length($$romref) - UNDI_HDR_SIZE
or substr($$romref, $undi_hdr_offset, 4) ne 'UNDI') {
$undi_hdr_offset = 0;
} else {
printf "UNDI header at %#x\n", $undi_hdr_offset;
}
if ($undi_hdr_offset > 0) {
substr($$romref, $undi_hdr_offset+UNDI_CHKSUM_OFF, 1) = "\x00";
my $sum = unpack('%8C*', substr($$romref, $undi_hdr_offset,
UNDI_HDR_SIZE));
substr($$romref, $undi_hdr_offset+UNDI_CHKSUM_OFF, 1) = chr(256 - $sum);
}
}
sub writerom ($$) {
my ($filename, $romref) = @_;
open(R, ">$filename") or die "$filename: $!\n";
print R $$romref;
close(R);
}
sub checksum ($) {
my ($romref) = @_;
substr($$romref, 5, 1) = "\x00";
my $sum = unpack('%8C*', $$romref);
substr($$romref, 5, 1) = chr(256 - $sum);
# Double check
$sum = unpack('%8C*', $$romref);
if ($sum != 0) {
print "Checksum fails\n"
} elsif ($opts{'v'}) {
print "Checksum ok\n";
}
}
sub makerom () {
my ($rom, $romsize);
getopts('3xi:p:s:v', \%opts);
$ARGV[0] or die "Usage: $0 [-s romsize] [-i ident] [-p vendorid,deviceid] [-x] [-3] rom-file\n";
open(R, $ARGV[0]) or die "$ARGV[0]: $!\n";
# Read in the whole ROM in one gulp
my $filesize = read(R, $rom, MAXROMSIZE+1);
close(R);
defined($filesize) and $filesize >= 3 or die "Cannot get first 3 bytes of file\n";
print "$filesize bytes read\n" if $opts{'v'};
# If PXE image, just fill the length field and write it out
if ($opts{'x'}) {
substr($rom, 2, 1) = chr((length($rom) + 511) / 512);
&writerom($ARGV[0], \$rom);
return;
}
# Size specified with -s overrides value in 3rd byte in image
# -s 0 means round up to next 512 byte block
if (defined($opts{'s'})) {
if (($romsize = oct($opts{'s'})) <= 0) {
# NB: This roundup trick only works on powers of 2
$romsize = ($filesize + 511) & ~511
}
} else {
$romsize = &getromsize(\$rom);
# 0 put there by *loader.S means makerom should pick the size
if ($romsize == 0) {
# Shrink romsize down to the smallest power of two that will do
for ($romsize = MAXROMSIZE;
$romsize > MINROMSIZE and $romsize >= 2*$filesize;
$romsize /= 2) { }
}
}
if ($filesize > $romsize) {
print STDERR "ROM size of $romsize not big enough for data, ";
# NB: This roundup trick only works on powers of 2
$romsize = ($filesize + 511) & ~511;
print "will use $romsize instead\n"
}
# Pad with 0xFF to $romsize
$rom .= "\xFF" x ($romsize - length($rom));
if ($romsize >= 128 * 1024) {
print "Warning: ROM size exceeds extension BIOS limit\n";
}
substr($rom, 2, 1) = chr(($romsize / 512) % 256);
print "ROM size is $romsize\n" if $opts{'v'};
my $identoffset = &addident(\$rom);
&pcipnpheaders(\$rom, $identoffset);
&undiheaders(\$rom);
# 3c503 requires last two bytes to be 0x80
substr($rom, MINROMSIZE-2, 2) = "\x80\x80"
if ($opts{'3'} and $romsize == MINROMSIZE);
&checksum(\$rom);
&writerom($ARGV[0], \$rom);
}
sub modrom () {
my ($rom);
getopts('p:v', \%opts);
$ARGV[0] or die "Usage: $0 [-p vendorid,deviceid] rom-file\n";
open(R, $ARGV[0]) or die "$ARGV[0]: $!\n";
# Read in the whole ROM in one gulp
my $filesize = read(R, $rom, MAXROMSIZE+1);
close(R);
defined($filesize) and $filesize >= 3 or die "Cannot get first 3 bytes of file\n";
print "$filesize bytes read\n" if $opts{'v'};
&pcipnpheaders(\$rom);
&undiheaders(\$rom);
&checksum(\$rom);
&writerom($ARGV[0], \$rom);
}
# Main routine. See how we were called and behave accordingly
if ($0 =~ m:modrom(\.pl)?$:) {
&modrom();
} else {
&makerom();
}
exit(0);

226
src/util/modrom.pl Executable file
View File

@@ -0,0 +1,226 @@
#!/usr/bin/perl -w
use Getopt::Std;
use constant MINROMSIZE => 8192;
use constant MAXROMSIZE => 262144;
use constant PCI_PTR_LOC => 0x18; # from beginning of ROM
use constant PCI_HDR_SIZE => 0x18;
use constant PNP_PTR_LOC => 0x1a; # from beginning of ROM
use constant PNP_HDR_SIZE => 0x20;
use constant PNP_CHKSUM_OFF => 0x9; # bytes from beginning of PnP header
use constant PNP_DEVICE_OFF => 0x10; # bytes from beginning of PnP header
use constant PCI_VEND_ID_OFF => 0x4; # bytes from beginning of PCI header
use constant PCI_DEV_ID_OFF => 0x6; # bytes from beginning of PCI header
use constant PCI_SIZE_OFF => 0x10; # bytes from beginning of PCI header
use constant UNDI_PTR_LOC => 0x16; # from beginning of ROM
use constant UNDI_HDR_SIZE => 0x16;
use constant UNDI_CHKSUM_OFF => 0x05;
use strict;
use vars qw(%opts);
use bytes;
sub getromsize ($) {
my ($romref) = @_;
my $i;
print STDERR "BIOS extension ROM Image did not start with 0x55 0xAA\n"
if (substr($$romref, 0, 2) ne "\x55\xaa");
my $size = ord(substr($$romref, 2, 1)) * 512;
for ($i = MINROMSIZE; $i < MAXROMSIZE and $i < $size; $i *= 2) { }
print STDERR "$size is a strange size for a boot ROM\n"
if ($size > 0 and $i > $size);
return ($size);
}
sub addident ($) {
my ($romref) = @_;
return (0) unless (my $s = $opts{'i'});
# include the terminating NUL byte too
$s .= "\x00";
my $len = length($s);
# Put the identifier in only if the space is blank
my $pos = length($$romref) - $len - 2;
return (0) if (substr($$romref, $pos, $len) ne ("\xFF" x $len));
substr($$romref, $pos, $len) = $s;
return ($pos);
}
sub pcipnpheaders ($$) {
my ($romref, $identoffset) = @_;
my ($pci_hdr_offset, $pnp_hdr_offset);
$pci_hdr_offset = unpack('v', substr($$romref, PCI_PTR_LOC, 2));
$pnp_hdr_offset = unpack('v', substr($$romref, PNP_PTR_LOC, 2));
# Sanity checks
if ($pci_hdr_offset < PCI_PTR_LOC + 2
or $pci_hdr_offset > length($$romref) - PCI_HDR_SIZE
or $pnp_hdr_offset < PNP_PTR_LOC + 2
or $pnp_hdr_offset > length($$romref) - PNP_HDR_SIZE
or substr($$romref, $pci_hdr_offset, 4) ne 'PCIR'
or substr($$romref, $pnp_hdr_offset, 4) ne '$PnP') {
$pci_hdr_offset = $pnp_hdr_offset = 0;
} else {
printf "PCI header at %#x and PnP header at %#x\n",
$pci_hdr_offset, $pnp_hdr_offset;
}
if ($pci_hdr_offset > 0) {
my ($pci_vendor_id, $pci_device_id);
# if no -p option, just report what's there
if (!defined($opts{'p'})) {
$pci_vendor_id = unpack('v', substr($$romref, $pci_hdr_offset+PCI_VEND_ID_OFF, 2));
$pci_device_id = unpack('v', substr($$romref, $pci_hdr_offset+PCI_DEV_ID_OFF, 2));
printf "PCI Vendor ID %#x Device ID %#x\n",
$pci_vendor_id, $pci_device_id;
} else {
substr($$romref, $pci_hdr_offset + PCI_SIZE_OFF, 2)
= pack('v', length($$romref) / 512);
($pci_vendor_id, $pci_device_id) = split(/,/, $opts{'p'});
substr($$romref, $pci_hdr_offset+PCI_VEND_ID_OFF, 2)
= pack('v', oct($pci_vendor_id)) if ($pci_vendor_id);
substr($$romref, $pci_hdr_offset+PCI_DEV_ID_OFF, 2)
= pack('v', oct($pci_device_id)) if ($pci_device_id);
}
}
if ($pnp_hdr_offset > 0 and defined($identoffset)) {
# Point to device id string at end of ROM image
substr($$romref, $pnp_hdr_offset+PNP_DEVICE_OFF, 2)
= pack('v', $identoffset);
substr($$romref, $pnp_hdr_offset+PNP_CHKSUM_OFF, 1) = "\x00";
my $sum = unpack('%8C*', substr($$romref, $pnp_hdr_offset,
PNP_HDR_SIZE));
substr($$romref, $pnp_hdr_offset+PNP_CHKSUM_OFF, 1) = chr(256 - $sum);
}
}
sub undiheaders ($) {
my ($romref) = @_;
my ($undi_hdr_offset);
$undi_hdr_offset = unpack('v', substr($$romref, UNDI_PTR_LOC, 2));
# Sanity checks
if ($undi_hdr_offset < UNDI_PTR_LOC + 2
or $undi_hdr_offset > length($$romref) - UNDI_HDR_SIZE
or substr($$romref, $undi_hdr_offset, 4) ne 'UNDI') {
$undi_hdr_offset = 0;
} else {
printf "UNDI header at %#x\n", $undi_hdr_offset;
}
if ($undi_hdr_offset > 0) {
substr($$romref, $undi_hdr_offset+UNDI_CHKSUM_OFF, 1) = "\x00";
my $sum = unpack('%8C*', substr($$romref, $undi_hdr_offset,
UNDI_HDR_SIZE));
substr($$romref, $undi_hdr_offset+UNDI_CHKSUM_OFF, 1) = chr(256 - $sum);
}
}
sub writerom ($$) {
my ($filename, $romref) = @_;
open(R, ">$filename") or die "$filename: $!\n";
print R $$romref;
close(R);
}
sub checksum ($) {
my ($romref) = @_;
substr($$romref, 5, 1) = "\x00";
my $sum = unpack('%8C*', $$romref);
substr($$romref, 5, 1) = chr(256 - $sum);
# Double check
$sum = unpack('%8C*', $$romref);
if ($sum != 0) {
print "Checksum fails\n"
} elsif ($opts{'v'}) {
print "Checksum ok\n";
}
}
sub makerom () {
my ($rom, $romsize);
getopts('3xi:p:s:v', \%opts);
$ARGV[0] or die "Usage: $0 [-s romsize] [-i ident] [-p vendorid,deviceid] [-x] [-3] rom-file\n";
open(R, $ARGV[0]) or die "$ARGV[0]: $!\n";
# Read in the whole ROM in one gulp
my $filesize = read(R, $rom, MAXROMSIZE+1);
close(R);
defined($filesize) and $filesize >= 3 or die "Cannot get first 3 bytes of file\n";
print "$filesize bytes read\n" if $opts{'v'};
# If PXE image, just fill the length field and write it out
if ($opts{'x'}) {
substr($rom, 2, 1) = chr((length($rom) + 511) / 512);
&writerom($ARGV[0], \$rom);
return;
}
# Size specified with -s overrides value in 3rd byte in image
# -s 0 means round up to next 512 byte block
if (defined($opts{'s'})) {
if (($romsize = oct($opts{'s'})) <= 0) {
# NB: This roundup trick only works on powers of 2
$romsize = ($filesize + 511) & ~511
}
} else {
$romsize = &getromsize(\$rom);
# 0 put there by *loader.S means makerom should pick the size
if ($romsize == 0) {
# Shrink romsize down to the smallest power of two that will do
for ($romsize = MAXROMSIZE;
$romsize > MINROMSIZE and $romsize >= 2*$filesize;
$romsize /= 2) { }
}
}
if ($filesize > $romsize) {
print STDERR "ROM size of $romsize not big enough for data, ";
# NB: This roundup trick only works on powers of 2
$romsize = ($filesize + 511) & ~511;
print "will use $romsize instead\n"
}
# Pad with 0xFF to $romsize
$rom .= "\xFF" x ($romsize - length($rom));
if ($romsize >= 128 * 1024) {
print "Warning: ROM size exceeds extension BIOS limit\n";
}
substr($rom, 2, 1) = chr(($romsize / 512) % 256);
print "ROM size is $romsize\n" if $opts{'v'};
my $identoffset = &addident(\$rom);
&pcipnpheaders(\$rom, $identoffset);
&undiheaders(\$rom);
# 3c503 requires last two bytes to be 0x80
substr($rom, MINROMSIZE-2, 2) = "\x80\x80"
if ($opts{'3'} and $romsize == MINROMSIZE);
&checksum(\$rom);
&writerom($ARGV[0], \$rom);
}
sub modrom () {
my ($rom);
getopts('p:v', \%opts);
$ARGV[0] or die "Usage: $0 [-p vendorid,deviceid] rom-file\n";
open(R, $ARGV[0]) or die "$ARGV[0]: $!\n";
# Read in the whole ROM in one gulp
my $filesize = read(R, $rom, MAXROMSIZE+1);
close(R);
defined($filesize) and $filesize >= 3 or die "Cannot get first 3 bytes of file\n";
print "$filesize bytes read\n" if $opts{'v'};
&pcipnpheaders(\$rom);
&undiheaders(\$rom);
&checksum(\$rom);
&writerom($ARGV[0], \$rom);
}
# Main routine. See how we were called and behave accordingly
if ($0 =~ m:modrom(\.pl)?$:) {
&modrom();
} else {
&makerom();
}
exit(0);

1501
src/util/nrv2b.c Normal file

File diff suppressed because it is too large Load Diff

49
src/util/swapdevids.pl Executable file
View File

@@ -0,0 +1,49 @@
#!/usr/bin/perl -w
#
# Program to reverse the device identifier IDs in the PCIR and PnP
# structures in a ROM for old non-compliant BIOSes
#
# GPL, Ken Yap 2001
#
use bytes;
use IO::Seekable;
sub swaplocs ($$$)
{
my ($dataref, $loc1, $loc2) = @_;
my ($t);
$t = substr($$dataref, $loc1, 1);
substr($$dataref, $loc1, 1) = substr($$dataref, $loc2, 1);
substr($$dataref, $loc2, 1) = $t;
}
sub printdevids ($$)
{
my ($dataref, $loc) = @_;
return (sprintf "%02x %02x %02x", unpack('C3', substr($$dataref, $loc, 3)));
}
$#ARGV >= 0 or die "Usage: $0 romimage\n";
$file = $ARGV[0];
open(F, "+<$file") or die "$file: $!\n";
binmode(F);
# Handle up to 64kB ROM images
$len = read(F, $data, 64*1024);
defined($len) or die "$file: $!\n";
substr($data, 0, 2) eq "\x55\xAA" or die "$file: Not a boot ROM image\n";
($pci, $pnp) = unpack('v2', substr($data, 0x18, 4));
($pci < $len and $pnp < $len) or die "$file: Not a PCI PnP ROM image\n";
(substr($data, $pci, 4) eq 'PCIR' and substr($data, $pnp, 4) eq '$PnP')
or die "$file: No PCI and PNP structures, not a PCI PNP ROM image\n";
&swaplocs(\$data, $pci+13, $pci+15);
&swaplocs(\$data, $pnp+18, $pnp+20);
seek(F, 0, SEEK_SET) or die "$file: Cannot seek to beginning\n";
print F $data;
close(F);
print "PCI devids now: ", &printdevids(\$data, $pci+13), "\n";
print "PnP devids now: ", &printdevids(\$data, $pnp+18), "\n";
exit(0);

8
src/util/zfilelen.pl Executable file
View File

@@ -0,0 +1,8 @@
#!/usr/bin/perl -w
use bytes;
local $/;
$_ = <>;
print length($_);
exit;