|
|
1.1 root 1: #! /usr/pkg/bin/perl -w
2:
3: # $Id: tme-sun-idprom.pl,v 1.1 2003/05/18 00:02:24 fredette Exp $
4:
5: # machine/sun/sun-idprom.pl - dumps and makes Sun IDPROM contents:
6:
7: # Copyright (c) 2003 Matt Fredette
8: # All rights reserved.
9: #
10: # Redistribution and use in source and binary forms, with or without
11: # modification, are permitted provided that the following conditions
12: # are met:
13: # 1. Redistributions of source code must retain the above copyright
14: # notice, this list of conditions and the following disclaimer.
15: # 2. Redistributions in binary form must reproduce the above copyright
16: # notice, this list of conditions and the following disclaimer in the
17: # documentation and/or other materials provided with the distribution.
18: # 3. All advertising materials mentioning features or use of this software
19: # must display the following acknowledgement:
20: # This product includes software developed by Matt Fredette.
21: # 4. The name of the author may not be used to endorse or promote products
22: # derived from this software without specific prior written permission.
23: #
24: # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25: # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26: # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27: # DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
28: # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29: # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30: # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32: # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33: # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34: # POSSIBILITY OF SUCH DAMAGE.
35:
36: # mapping from machine name to Sun code name:
37: @machine_codename =
38: ( '2/120', 'sun2 Multibus',
39: '2/170', 'sun2 Multibus',
40: '2/50', 'sun2 VME',
41: '2/130', 'sun2 VME',
42: '2/160', 'sun2 VME',
43: '3/75', 'Carrera',
44: '3/140', 'Carrera',
45: '3/150', 'Carrera',
46: '3/160', 'Carrera',
47: '3/180', 'Carrera',
48: '3/50', 'Model 25',
49: '3/260', 'Sirius',
50: '3/280', 'Sirius',
51: '3/110', 'Prism',
52: '3/60', 'Ferrari',
53: '3/E', 'Sun3E',
54: '4/260', 'Sunrise',
55: '4/280', 'Sunrise',
56: '4/110', 'Cobra',
57: '4/150', 'Cobra',
58: '4/330', 'Stingray',
59: '4/310', 'Stingray',
60: '4/350', 'Stingray',
61: '4/360', 'Stingray',
62: '4/370', 'Stingray',
63: '4/380', 'Stingray',
64: '4/390', 'Stingray',
65: '4/470', 'Sunray',
66: '4/490', 'Sunray',
67: '386i/150', 'Roadrunner',
68: '386i/250', 'Roadrunner',
69: '3/460', 'Pegasus',
70: '3/470', 'Pegasus',
71: '3/480', 'Pegasus',
72: '3/80', 'Hydra',
73: '*SPARCStation 1', 'Campus',
74: 'SS1', 'Campus',
75: '4/60', 'Campus',
76: '*SPARCstation IPC', 'Phoenix',
77: 'IPC', 'Phoenix',
78: '4/40', 'Phoenix',
79: '*SPARCStation 1+', 'Campus B',
80: 'SS1+', 'Campus B',
81: '4/65', 'Campus B',
82: '*SPARCstation SLC', 'Off-Campus',
83: 'SLC', 'Off-Campus',
84: '4/20', 'Off-Campus',
85: '*SPARCStation 2', 'Calvin',
86: 'SS2', 'Calvin',
87: '4/75', 'Calvin',
88: '*SPARCstation ELC', 'Node Warrior',
89: 'ELC', 'Node Warrior',
90: '4/25', 'Node Warrior',
91: '*SPARCstation IPX', 'Hobbes',
92: 'IPX', 'Hobbes',
93: '4/50', 'Hobbes',
94: '*SPARCengine 1', 'Polaris',
95: '4/E', 'Polaris',
96: '4/600', 'Galaxy',
97: '4/630', 'Galaxy',
98: '4/670', 'Galaxy',
99: '4/690', 'Galaxy',
100: '*SPARCstation 10', 'Campus-2',
101: 'SS10', 'Campus-2',
102: '*SPARCstation 20', 'Kodiak',
103: 'SS20', 'Kodiak',
104: '*SPARCclassic X', 'Hamlet',
105: 'Classic X', 'Hamlet',
106: '4/10', 'Hamlet',
107: '*SPARCClassic', 'Sunergy',
108: '4/15', 'Sunergy',
109: 'classic', 'Sunergy',
110: '4/30', 'Sunergy',
111: 'SPARCstation LX', 'Sunergy',
112: 'LX', 'Sunergy',
113: 'Voyager', 'Gypsy',
114: 'SS5', 'Aurora',
115: 'SS4', 'Perigee',
116: );
117: %machine_codename = @machine_codename;
118:
119: # mapping from Sun code name to IDPROM machine type byte:
120: @codename_machtype =
121: ( 'sun2 Multibus', 0x01,
122: 'sun2 VME', 0x02,
123: 'Carrera', 0x11,
124: 'Model 25', 0x12,
125: 'Sirius', 0x13,
126: 'Prism', 0x14,
127: 'Ferrari', 0x17,
128: 'Sun3E', 0x18,
129: 'Sunrise', 0x21,
130: 'Cobra', 0x22,
131: 'Stingray', 0x23,
132: 'Sunray', 0x24,
133: 'Roadrunner', 0x31,
134: 'Pegasus', 0x41,
135: 'Hydra', 0x42,
136: 'Campus', 0x51,
137: 'Phoenix', 0x52,
138: 'Campus B', 0x53,
139: 'Off-Campus', 0x54,
140: 'Calvin', 0x55,
141: 'Node Warrior', 0x56,
142: 'Hobbes', 0x57,
143: 'Polaris', 0x61,
144: 'Galaxy', 0x71,
145: 'Campus-2', 0x72,
146: 'Kodiak', 0x72,
147: 'Sunergy', 0x80,
148: 'Gypsy', 0x80,
149: 'Aurora', 0x80,
150: 'Perigee', 0x80,
151: );
152: %codename_machtype = @codename_machtype;
153:
154: # mapping from Sun code name to sometime during the
155: # shipping/availability period, if known, for those machines that
156: # shipped with a real manufacture date in the IDPROM:
157: %codename_shipping =
158: ( 'sun2 Multibus', 457370182,
159: 'Carrera', 587239630,
160: 'Ferrari', 564526348,
161: );
162:
163: # if our standard input is not a terminal, assume we're checking an IDPROM there:
164: unless (-t STDIN) {
165:
166: # read in the IDPROM:
167: $size = sysread(STDIN, $idprom, 32);
168: if ($size != 32) {
169: print STDERR "fatal: IDPROM has wrong size ($size), must be exactly 32\n";
170: exit(1);
171: }
172:
173: # unpack the IDPROM:
174: ($format,
175: $machtype,
176: $ether0,
177: $ether1,
178: $ether2,
179: $ether3,
180: $ether4,
181: $ether5,
182: $date,
183: $serial_and_cksum) =
184: (unpack("C C C6 N N", $idprom));
185: $serial = ($serial_and_cksum >> 8);
186:
187: # check the format:
188: if ($format != 1) {
189: print "warning: IDPROM has invalid format byte ($format), must be 1\n";
190: }
191:
192: # check the checksum, which only covers the first 16 bytes:
193: @bytes = (unpack("C16", $idprom));
194: $cksum_old = pop(@bytes);
195: $cksum_new = 0;
196: foreach $byte (@bytes) {
197: $cksum_new ^= $byte;
198: }
199: if ($cksum_new != $cksum_old) {
200: print "warning: IDPROM has bad cksum ";
201: print sprintf("(0x%02x)", $cksum_old);
202: print ", should be ";
203: print sprintf("0x%02x", $cksum_new);
204: print "\n";
205: }
206:
207: # turn the machine type into a set of code names and machines:
208: @codenames = ();
209: @machines = ();
210: for ($i = 0; $i < @codename_machtype; $i += 2) {
211: if ($codename_machtype[$i + 1] == $machtype) {
212: $codename = $codename_machtype[$i + 0];
213: push (@codenames, $codename);
214: @codename_machines = ();
215: for ($j = 0; $j < @machine_codename; $j += 2) {
216: if ($machine_codename[$j + 1] eq $codename) {
217: $machine = $machine_codename[$j + 0];
218: if ($machine =~ /^\*(.*)$/) {
219: push (@codename_machines, $1);
220: last;
221: }
222: else {
223: push(@codename_machines, $machine);
224: }
225: }
226: }
227: if (@codename_machines > 2) {
228: $codename_machines[$#codename_machines] = "or ".$codename_machines[$#codename_machines];
229: $codename_machines = join(", ", @codename_machines);
230: }
231: elsif (@codename_machines == 2) {
232: $codename_machines = join(" or ", @codename_machines);
233: }
234: else {
235: $codename_machines = $codename_machines[0];
236: }
237: push(@machines, $codename_machines);
238: }
239: }
240:
241: # display a PROM-like banner:
242: if (@codenames == 0) {
243: print "warning: IDPROM has unknown machine type ";
244: print sprintf("(0x%02x)", $machtype);
245: print "\n";
246: }
247: elsif (@codenames == 1) {
248: $codename = $codenames[0];
249: $machines = $machines[0];
250: if ($machines =~ /^\d+i?\//
251: || $machines =~ / or /) {
252: print "Sun Workstation, Model ";
253: }
254: print $machines;
255: print " (codename \"$codename\")" unless ($codename =~ /^sun2/);
256: print "\n";
257: }
258: else {
259: print "Sun Workstation, Model ";
260: for ($i = 0; $i < @codenames; $i++) {
261: $codename = $codenames[$i];
262: $machines[$i] .= " (codename \"$codename\")"
263: unless ($codename =~ /^sun2/);
264: }
265: print join((@codenames == 2 ? " or " : ", or "), @machines);
266: print "\n";
267: }
268: print "Serial \#$serial, Ethernet address";
269: $sep = ' ';
270: foreach $byte ($ether0, $ether1, $ether2, $ether3, $ether4, $ether5) {
271: print $sep.sprintf("%x", $byte);
272: $sep = ':';
273: }
274: print "\n";
275: print "Manufacture date ".gmtime($date)."\n";
276: }
277:
278: # otherwise, we're generating a new IDPROM:
279: else {
280:
281: # check our command line:
282: $usage = 0;
283:
284: # the machine or code name:
285: if (@ARGV == 0) {
286: print STDERR "missing machine name\n";
287: $usage = 1;
288: }
289: else {
290: $name = shift(@ARGV);
291: if (defined($codename_machtype{$name})) {
292: $codename = $name;
293: }
294: else {
295: # this should be a machine name:
296: $codename = $machine_codename{$name};
297: if (!defined($codename)) {
298: $codename = $machine_codename{"*$name"};
299: }
300: if (!defined($codename)) {
301: print STDERR "unknown machine name '$name'\n";
302: $usage = 1;
303: }
304: }
305: }
306:
307: # the Ethernet address:
308: if (@ARGV == 0) {
309: print STDERR "missing Ethernet address\n";
310: $usage = 1;
311: }
312: else {
313: $ether = shift(@ARGV);
314: @ether = split(/:/, $ether);
315: unless ($ether =~ /^[0-9a-fA-F:]+/
316: && @ether == 6) {
317: print STDERR "bad Ethernet address '$ether'\n";
318: $usage = 1;
319: }
320: }
321:
322: # the optional serial number:
323: if (@ARGV > 0) {
324: $serial = shift(@ARGV);
325: unless ($serial =~ /^\d+$/) {
326: print STDERR "bad serial number '$serial'\n";
327: $usage = 1;
328: }
329: }
330: else {
331: $serial = 1 + int(rand(100000));
332: }
333:
334: # standard output must not be a terminal:
335: if (-t STDOUT) {
336: print STDERR "standard output must not be a terminal\n";
337: $usage = 1;
338: }
339:
340: # any other arguments are unexpected:
341: if (@ARGV > 0) {
342: print STDERR "unexpected argument '$ARGV[0]'\n";
343: $usage = 1;
344: }
345:
346: if ($usage) {
347: print STDERR "usage: $0 MACHINE ETHERNET [ SERIAL ] > IDPROM\n";
348: print STDERR " $0 < IDPROM\n";
349: exit(1);
350: }
351:
352: # start the IDPROM:
353: $idprom = "";
354:
355: # add in the format byte:
356: $idprom .= pack("C", 1);
357:
358: # add in the machine type:
359: $machtype = $codename_machtype{$codename};
360: if (!defined($machtype)) {
361: die "internal error - machtype byte for codename $codename missing\n";
362: }
363: $idprom .= pack("C", $machtype);
364:
365: # add in the ethernet address:
366: foreach $byte (@ether) {
367: $byte = hex($byte);
368: $idprom .= pack("C", $byte);
369: }
370: if ($ether[0] != 0x08
371: || $ether[1] != 0x00
372: || $ether[2] != 0x20) {
373: print STDERR "warning: Ethernet address $ether doesn't begin with Sun's OUI 8:0:20\n";
374: }
375:
376: # add in a date, if possible:
377: $date = $codename_shipping{$codename};
378: if (defined($date)) {
379: # smear the date within 30 days of the known date:
380: $date += (int(rand(60)) - 30) * (24 * 60 * 60);
381: }
382: else {
383: $date = 0;
384: }
385: $idprom .= pack("N", $date);
386:
387: # add in the serial number:
388: $idprom .= substr(pack("N", $serial), 1);
389:
390: # calculate the checksum:
391: @bytes = (unpack("C*", $idprom));
392: $cksum_new = 0;
393: foreach $byte (@bytes) {
394: $cksum_new ^= $byte;
395: }
396: $idprom .= pack("C", $cksum_new);
397:
398: # add the extra 16 bytes:
399: $idprom .= pack("NNNN", 0, 0, 0, 0);
400:
401: # dump out the IDPROM:
402: print $idprom;
403: }
404:
405: # done:
406: exit(0);
407:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.