|
|
1.1 root 1: #! /usr/pkg/bin/perl -w
2:
1.1.1.2 ! root 3: # $Id: tme-sun-idprom.pl,v 1.2 2003/07/29 18:21:31 fredette Exp $
1.1 root 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',
1.1.1.2 ! root 67: '386i/MB1', 'Roadrunner-MB1',
1.1 root 68: '386i/150', 'Roadrunner',
69: '386i/250', 'Roadrunner',
70: '3/460', 'Pegasus',
71: '3/470', 'Pegasus',
72: '3/480', 'Pegasus',
73: '3/80', 'Hydra',
74: '*SPARCStation 1', 'Campus',
75: 'SS1', 'Campus',
76: '4/60', 'Campus',
77: '*SPARCstation IPC', 'Phoenix',
78: 'IPC', 'Phoenix',
79: '4/40', 'Phoenix',
80: '*SPARCStation 1+', 'Campus B',
81: 'SS1+', 'Campus B',
82: '4/65', 'Campus B',
83: '*SPARCstation SLC', 'Off-Campus',
84: 'SLC', 'Off-Campus',
85: '4/20', 'Off-Campus',
86: '*SPARCStation 2', 'Calvin',
87: 'SS2', 'Calvin',
88: '4/75', 'Calvin',
89: '*SPARCstation ELC', 'Node Warrior',
90: 'ELC', 'Node Warrior',
91: '4/25', 'Node Warrior',
92: '*SPARCstation IPX', 'Hobbes',
93: 'IPX', 'Hobbes',
94: '4/50', 'Hobbes',
95: '*SPARCengine 1', 'Polaris',
96: '4/E', 'Polaris',
97: '4/600', 'Galaxy',
98: '4/630', 'Galaxy',
99: '4/670', 'Galaxy',
100: '4/690', 'Galaxy',
101: '*SPARCstation 10', 'Campus-2',
102: 'SS10', 'Campus-2',
103: '*SPARCstation 20', 'Kodiak',
104: 'SS20', 'Kodiak',
105: '*SPARCclassic X', 'Hamlet',
106: 'Classic X', 'Hamlet',
107: '4/10', 'Hamlet',
108: '*SPARCClassic', 'Sunergy',
109: '4/15', 'Sunergy',
110: 'classic', 'Sunergy',
111: '4/30', 'Sunergy',
112: 'SPARCstation LX', 'Sunergy',
113: 'LX', 'Sunergy',
114: 'Voyager', 'Gypsy',
115: 'SS5', 'Aurora',
116: 'SS4', 'Perigee',
117: );
118: %machine_codename = @machine_codename;
119:
120: # mapping from Sun code name to IDPROM machine type byte:
121: @codename_machtype =
122: ( 'sun2 Multibus', 0x01,
123: 'sun2 VME', 0x02,
124: 'Carrera', 0x11,
125: 'Model 25', 0x12,
126: 'Sirius', 0x13,
127: 'Prism', 0x14,
128: 'Ferrari', 0x17,
129: 'Sun3E', 0x18,
130: 'Sunrise', 0x21,
131: 'Cobra', 0x22,
132: 'Stingray', 0x23,
133: 'Sunray', 0x24,
134: 'Roadrunner', 0x31,
1.1.1.2 ! root 135: 'Roadrunner-MB1', 0x3a,
1.1 root 136: 'Pegasus', 0x41,
137: 'Hydra', 0x42,
138: 'Campus', 0x51,
139: 'Phoenix', 0x52,
140: 'Campus B', 0x53,
141: 'Off-Campus', 0x54,
142: 'Calvin', 0x55,
143: 'Node Warrior', 0x56,
144: 'Hobbes', 0x57,
145: 'Polaris', 0x61,
146: 'Galaxy', 0x71,
147: 'Campus-2', 0x72,
148: 'Kodiak', 0x72,
149: 'Sunergy', 0x80,
150: 'Gypsy', 0x80,
151: 'Aurora', 0x80,
152: 'Perigee', 0x80,
153: );
154: %codename_machtype = @codename_machtype;
155:
156: # mapping from Sun code name to sometime during the
157: # shipping/availability period, if known, for those machines that
158: # shipped with a real manufacture date in the IDPROM:
159: %codename_shipping =
160: ( 'sun2 Multibus', 457370182,
161: 'Carrera', 587239630,
162: 'Ferrari', 564526348,
163: );
164:
165: # if our standard input is not a terminal, assume we're checking an IDPROM there:
166: unless (-t STDIN) {
167:
168: # read in the IDPROM:
169: $size = sysread(STDIN, $idprom, 32);
170: if ($size != 32) {
171: print STDERR "fatal: IDPROM has wrong size ($size), must be exactly 32\n";
172: exit(1);
173: }
174:
175: # unpack the IDPROM:
176: ($format,
177: $machtype,
178: $ether0,
179: $ether1,
180: $ether2,
181: $ether3,
182: $ether4,
183: $ether5,
184: $date,
185: $serial_and_cksum) =
186: (unpack("C C C6 N N", $idprom));
187: $serial = ($serial_and_cksum >> 8);
188:
189: # check the format:
190: if ($format != 1) {
191: print "warning: IDPROM has invalid format byte ($format), must be 1\n";
192: }
193:
194: # check the checksum, which only covers the first 16 bytes:
195: @bytes = (unpack("C16", $idprom));
196: $cksum_old = pop(@bytes);
197: $cksum_new = 0;
198: foreach $byte (@bytes) {
199: $cksum_new ^= $byte;
200: }
201: if ($cksum_new != $cksum_old) {
202: print "warning: IDPROM has bad cksum ";
203: print sprintf("(0x%02x)", $cksum_old);
204: print ", should be ";
205: print sprintf("0x%02x", $cksum_new);
206: print "\n";
207: }
208:
209: # turn the machine type into a set of code names and machines:
210: @codenames = ();
211: @machines = ();
212: for ($i = 0; $i < @codename_machtype; $i += 2) {
213: if ($codename_machtype[$i + 1] == $machtype) {
214: $codename = $codename_machtype[$i + 0];
215: push (@codenames, $codename);
216: @codename_machines = ();
217: for ($j = 0; $j < @machine_codename; $j += 2) {
218: if ($machine_codename[$j + 1] eq $codename) {
219: $machine = $machine_codename[$j + 0];
220: if ($machine =~ /^\*(.*)$/) {
221: push (@codename_machines, $1);
222: last;
223: }
224: else {
225: push(@codename_machines, $machine);
226: }
227: }
228: }
229: if (@codename_machines > 2) {
230: $codename_machines[$#codename_machines] = "or ".$codename_machines[$#codename_machines];
231: $codename_machines = join(", ", @codename_machines);
232: }
233: elsif (@codename_machines == 2) {
234: $codename_machines = join(" or ", @codename_machines);
235: }
236: else {
237: $codename_machines = $codename_machines[0];
238: }
239: push(@machines, $codename_machines);
240: }
241: }
242:
243: # display a PROM-like banner:
244: if (@codenames == 0) {
245: print "warning: IDPROM has unknown machine type ";
246: print sprintf("(0x%02x)", $machtype);
247: print "\n";
248: }
249: elsif (@codenames == 1) {
250: $codename = $codenames[0];
251: $machines = $machines[0];
252: if ($machines =~ /^\d+i?\//
253: || $machines =~ / or /) {
254: print "Sun Workstation, Model ";
255: }
256: print $machines;
257: print " (codename \"$codename\")" unless ($codename =~ /^sun2/);
258: print "\n";
259: }
260: else {
261: print "Sun Workstation, Model ";
262: for ($i = 0; $i < @codenames; $i++) {
263: $codename = $codenames[$i];
264: $machines[$i] .= " (codename \"$codename\")"
265: unless ($codename =~ /^sun2/);
266: }
267: print join((@codenames == 2 ? " or " : ", or "), @machines);
268: print "\n";
269: }
270: print "Serial \#$serial, Ethernet address";
271: $sep = ' ';
272: foreach $byte ($ether0, $ether1, $ether2, $ether3, $ether4, $ether5) {
273: print $sep.sprintf("%x", $byte);
274: $sep = ':';
275: }
276: print "\n";
277: print "Manufacture date ".gmtime($date)."\n";
278: }
279:
280: # otherwise, we're generating a new IDPROM:
281: else {
282:
283: # check our command line:
284: $usage = 0;
285:
286: # the machine or code name:
287: if (@ARGV == 0) {
288: print STDERR "missing machine name\n";
289: $usage = 1;
290: }
291: else {
292: $name = shift(@ARGV);
293: if (defined($codename_machtype{$name})) {
294: $codename = $name;
295: }
296: else {
297: # this should be a machine name:
298: $codename = $machine_codename{$name};
299: if (!defined($codename)) {
300: $codename = $machine_codename{"*$name"};
301: }
302: if (!defined($codename)) {
303: print STDERR "unknown machine name '$name'\n";
304: $usage = 1;
305: }
306: }
307: }
308:
309: # the Ethernet address:
310: if (@ARGV == 0) {
311: print STDERR "missing Ethernet address\n";
312: $usage = 1;
313: }
314: else {
315: $ether = shift(@ARGV);
316: @ether = split(/:/, $ether);
317: unless ($ether =~ /^[0-9a-fA-F:]+/
318: && @ether == 6) {
319: print STDERR "bad Ethernet address '$ether'\n";
320: $usage = 1;
321: }
322: }
323:
324: # the optional serial number:
325: if (@ARGV > 0) {
326: $serial = shift(@ARGV);
327: unless ($serial =~ /^\d+$/) {
328: print STDERR "bad serial number '$serial'\n";
329: $usage = 1;
330: }
331: }
332: else {
333: $serial = 1 + int(rand(100000));
334: }
335:
336: # standard output must not be a terminal:
337: if (-t STDOUT) {
338: print STDERR "standard output must not be a terminal\n";
339: $usage = 1;
340: }
341:
342: # any other arguments are unexpected:
343: if (@ARGV > 0) {
344: print STDERR "unexpected argument '$ARGV[0]'\n";
345: $usage = 1;
346: }
347:
348: if ($usage) {
349: print STDERR "usage: $0 MACHINE ETHERNET [ SERIAL ] > IDPROM\n";
350: print STDERR " $0 < IDPROM\n";
351: exit(1);
352: }
353:
354: # start the IDPROM:
355: $idprom = "";
356:
357: # add in the format byte:
358: $idprom .= pack("C", 1);
359:
360: # add in the machine type:
361: $machtype = $codename_machtype{$codename};
362: if (!defined($machtype)) {
363: die "internal error - machtype byte for codename $codename missing\n";
364: }
365: $idprom .= pack("C", $machtype);
366:
367: # add in the ethernet address:
368: foreach $byte (@ether) {
369: $byte = hex($byte);
370: $idprom .= pack("C", $byte);
371: }
372: if ($ether[0] != 0x08
373: || $ether[1] != 0x00
374: || $ether[2] != 0x20) {
375: print STDERR "warning: Ethernet address $ether doesn't begin with Sun's OUI 8:0:20\n";
376: }
377:
378: # add in a date, if possible:
379: $date = $codename_shipping{$codename};
380: if (defined($date)) {
381: # smear the date within 30 days of the known date:
382: $date += (int(rand(60)) - 30) * (24 * 60 * 60);
383: }
384: else {
385: $date = 0;
386: }
387: $idprom .= pack("N", $date);
388:
389: # add in the serial number:
390: $idprom .= substr(pack("N", $serial), 1);
391:
392: # calculate the checksum:
393: @bytes = (unpack("C*", $idprom));
394: $cksum_new = 0;
395: foreach $byte (@bytes) {
396: $cksum_new ^= $byte;
397: }
398: $idprom .= pack("C", $cksum_new);
399:
400: # add the extra 16 bytes:
401: $idprom .= pack("NNNN", 0, 0, 0, 0);
402:
403: # dump out the IDPROM:
404: print $idprom;
405: }
406:
407: # done:
408: exit(0);
409:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.