Files
Amberelle Mason ac30ff9032 Initial import
Initial import of SunOS 4.1.1 and TME 0.8
2023-05-01 12:16:40 -04:00

410 lines
11 KiB
Perl

#! /usr/bin/perl -w
# $Id: tme-sun-idprom.pl,v 1.2 2003/07/29 18:21:31 fredette Exp $
# machine/sun/sun-idprom.pl - dumps and makes Sun IDPROM contents:
# Copyright (c) 2003 Matt Fredette
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by Matt Fredette.
# 4. The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# mapping from machine name to Sun code name:
@machine_codename =
( '2/120', 'sun2 Multibus',
'2/170', 'sun2 Multibus',
'2/50', 'sun2 VME',
'2/130', 'sun2 VME',
'2/160', 'sun2 VME',
'3/75', 'Carrera',
'3/140', 'Carrera',
'3/150', 'Carrera',
'3/160', 'Carrera',
'3/180', 'Carrera',
'3/50', 'Model 25',
'3/260', 'Sirius',
'3/280', 'Sirius',
'3/110', 'Prism',
'3/60', 'Ferrari',
'3/E', 'Sun3E',
'4/260', 'Sunrise',
'4/280', 'Sunrise',
'4/110', 'Cobra',
'4/150', 'Cobra',
'4/330', 'Stingray',
'4/310', 'Stingray',
'4/350', 'Stingray',
'4/360', 'Stingray',
'4/370', 'Stingray',
'4/380', 'Stingray',
'4/390', 'Stingray',
'4/470', 'Sunray',
'4/490', 'Sunray',
'386i/MB1', 'Roadrunner-MB1',
'386i/150', 'Roadrunner',
'386i/250', 'Roadrunner',
'3/460', 'Pegasus',
'3/470', 'Pegasus',
'3/480', 'Pegasus',
'3/80', 'Hydra',
'*SPARCStation 1', 'Campus',
'SS1', 'Campus',
'4/60', 'Campus',
'*SPARCstation IPC', 'Phoenix',
'IPC', 'Phoenix',
'4/40', 'Phoenix',
'*SPARCStation 1+', 'Campus B',
'SS1+', 'Campus B',
'4/65', 'Campus B',
'*SPARCstation SLC', 'Off-Campus',
'SLC', 'Off-Campus',
'4/20', 'Off-Campus',
'*SPARCStation 2', 'Calvin',
'SS2', 'Calvin',
'4/75', 'Calvin',
'*SPARCstation ELC', 'Node Warrior',
'ELC', 'Node Warrior',
'4/25', 'Node Warrior',
'*SPARCstation IPX', 'Hobbes',
'IPX', 'Hobbes',
'4/50', 'Hobbes',
'*SPARCengine 1', 'Polaris',
'4/E', 'Polaris',
'4/600', 'Galaxy',
'4/630', 'Galaxy',
'4/670', 'Galaxy',
'4/690', 'Galaxy',
'*SPARCstation 10', 'Campus-2',
'SS10', 'Campus-2',
'*SPARCstation 20', 'Kodiak',
'SS20', 'Kodiak',
'*SPARCclassic X', 'Hamlet',
'Classic X', 'Hamlet',
'4/10', 'Hamlet',
'*SPARCClassic', 'Sunergy',
'4/15', 'Sunergy',
'classic', 'Sunergy',
'4/30', 'Sunergy',
'SPARCstation LX', 'Sunergy',
'LX', 'Sunergy',
'Voyager', 'Gypsy',
'SS5', 'Aurora',
'SS4', 'Perigee',
);
%machine_codename = @machine_codename;
# mapping from Sun code name to IDPROM machine type byte:
@codename_machtype =
( 'sun2 Multibus', 0x01,
'sun2 VME', 0x02,
'Carrera', 0x11,
'Model 25', 0x12,
'Sirius', 0x13,
'Prism', 0x14,
'Ferrari', 0x17,
'Sun3E', 0x18,
'Sunrise', 0x21,
'Cobra', 0x22,
'Stingray', 0x23,
'Sunray', 0x24,
'Roadrunner', 0x31,
'Roadrunner-MB1', 0x3a,
'Pegasus', 0x41,
'Hydra', 0x42,
'Campus', 0x51,
'Phoenix', 0x52,
'Campus B', 0x53,
'Off-Campus', 0x54,
'Calvin', 0x55,
'Node Warrior', 0x56,
'Hobbes', 0x57,
'Polaris', 0x61,
'Galaxy', 0x71,
'Campus-2', 0x72,
'Kodiak', 0x72,
'Sunergy', 0x80,
'Gypsy', 0x80,
'Aurora', 0x80,
'Perigee', 0x80,
);
%codename_machtype = @codename_machtype;
# mapping from Sun code name to sometime during the
# shipping/availability period, if known, for those machines that
# shipped with a real manufacture date in the IDPROM:
%codename_shipping =
( 'sun2 Multibus', 457370182,
'Carrera', 587239630,
'Ferrari', 564526348,
);
# if our standard input is not a terminal, assume we're checking an IDPROM there:
unless (-t STDIN) {
# read in the IDPROM:
$size = sysread(STDIN, $idprom, 32);
if ($size != 32) {
print STDERR "fatal: IDPROM has wrong size ($size), must be exactly 32\n";
exit(1);
}
# unpack the IDPROM:
($format,
$machtype,
$ether0,
$ether1,
$ether2,
$ether3,
$ether4,
$ether5,
$date,
$serial_and_cksum) =
(unpack("C C C6 N N", $idprom));
$serial = ($serial_and_cksum >> 8);
# check the format:
if ($format != 1) {
print "warning: IDPROM has invalid format byte ($format), must be 1\n";
}
# check the checksum, which only covers the first 16 bytes:
@bytes = (unpack("C16", $idprom));
$cksum_old = pop(@bytes);
$cksum_new = 0;
foreach $byte (@bytes) {
$cksum_new ^= $byte;
}
if ($cksum_new != $cksum_old) {
print "warning: IDPROM has bad cksum ";
print sprintf("(0x%02x)", $cksum_old);
print ", should be ";
print sprintf("0x%02x", $cksum_new);
print "\n";
}
# turn the machine type into a set of code names and machines:
@codenames = ();
@machines = ();
for ($i = 0; $i < @codename_machtype; $i += 2) {
if ($codename_machtype[$i + 1] == $machtype) {
$codename = $codename_machtype[$i + 0];
push (@codenames, $codename);
@codename_machines = ();
for ($j = 0; $j < @machine_codename; $j += 2) {
if ($machine_codename[$j + 1] eq $codename) {
$machine = $machine_codename[$j + 0];
if ($machine =~ /^\*(.*)$/) {
push (@codename_machines, $1);
last;
}
else {
push(@codename_machines, $machine);
}
}
}
if (@codename_machines > 2) {
$codename_machines[$#codename_machines] = "or ".$codename_machines[$#codename_machines];
$codename_machines = join(", ", @codename_machines);
}
elsif (@codename_machines == 2) {
$codename_machines = join(" or ", @codename_machines);
}
else {
$codename_machines = $codename_machines[0];
}
push(@machines, $codename_machines);
}
}
# display a PROM-like banner:
if (@codenames == 0) {
print "warning: IDPROM has unknown machine type ";
print sprintf("(0x%02x)", $machtype);
print "\n";
}
elsif (@codenames == 1) {
$codename = $codenames[0];
$machines = $machines[0];
if ($machines =~ /^\d+i?\//
|| $machines =~ / or /) {
print "Sun Workstation, Model ";
}
print $machines;
print " (codename \"$codename\")" unless ($codename =~ /^sun2/);
print "\n";
}
else {
print "Sun Workstation, Model ";
for ($i = 0; $i < @codenames; $i++) {
$codename = $codenames[$i];
$machines[$i] .= " (codename \"$codename\")"
unless ($codename =~ /^sun2/);
}
print join((@codenames == 2 ? " or " : ", or "), @machines);
print "\n";
}
print "Serial \#$serial, Ethernet address";
$sep = ' ';
foreach $byte ($ether0, $ether1, $ether2, $ether3, $ether4, $ether5) {
print $sep.sprintf("%x", $byte);
$sep = ':';
}
print "\n";
print "Manufacture date ".gmtime($date)."\n";
}
# otherwise, we're generating a new IDPROM:
else {
# check our command line:
$usage = 0;
# the machine or code name:
if (@ARGV == 0) {
print STDERR "missing machine name\n";
$usage = 1;
}
else {
$name = shift(@ARGV);
if (defined($codename_machtype{$name})) {
$codename = $name;
}
else {
# this should be a machine name:
$codename = $machine_codename{$name};
if (!defined($codename)) {
$codename = $machine_codename{"*$name"};
}
if (!defined($codename)) {
print STDERR "unknown machine name '$name'\n";
$usage = 1;
}
}
}
# the Ethernet address:
if (@ARGV == 0) {
print STDERR "missing Ethernet address\n";
$usage = 1;
}
else {
$ether = shift(@ARGV);
@ether = split(/:/, $ether);
unless ($ether =~ /^[0-9a-fA-F:]+/
&& @ether == 6) {
print STDERR "bad Ethernet address '$ether'\n";
$usage = 1;
}
}
# the optional serial number:
if (@ARGV > 0) {
$serial = shift(@ARGV);
unless ($serial =~ /^\d+$/) {
print STDERR "bad serial number '$serial'\n";
$usage = 1;
}
}
else {
$serial = 1 + int(rand(100000));
}
# standard output must not be a terminal:
if (-t STDOUT) {
print STDERR "standard output must not be a terminal\n";
$usage = 1;
}
# any other arguments are unexpected:
if (@ARGV > 0) {
print STDERR "unexpected argument '$ARGV[0]'\n";
$usage = 1;
}
if ($usage) {
print STDERR "usage: $0 MACHINE ETHERNET [ SERIAL ] > IDPROM\n";
print STDERR " $0 < IDPROM\n";
exit(1);
}
# start the IDPROM:
$idprom = "";
# add in the format byte:
$idprom .= pack("C", 1);
# add in the machine type:
$machtype = $codename_machtype{$codename};
if (!defined($machtype)) {
die "internal error - machtype byte for codename $codename missing\n";
}
$idprom .= pack("C", $machtype);
# add in the ethernet address:
foreach $byte (@ether) {
$byte = hex($byte);
$idprom .= pack("C", $byte);
}
if ($ether[0] != 0x08
|| $ether[1] != 0x00
|| $ether[2] != 0x20) {
print STDERR "warning: Ethernet address $ether doesn't begin with Sun's OUI 8:0:20\n";
}
# add in a date, if possible:
$date = $codename_shipping{$codename};
if (defined($date)) {
# smear the date within 30 days of the known date:
$date += (int(rand(60)) - 30) * (24 * 60 * 60);
}
else {
$date = 0;
}
$idprom .= pack("N", $date);
# add in the serial number:
$idprom .= substr(pack("N", $serial), 1);
# calculate the checksum:
@bytes = (unpack("C*", $idprom));
$cksum_new = 0;
foreach $byte (@bytes) {
$cksum_new ^= $byte;
}
$idprom .= pack("C", $cksum_new);
# add the extra 16 bytes:
$idprom .= pack("NNNN", 0, 0, 0, 0);
# dump out the IDPROM:
print $idprom;
}
# done:
exit(0);