-- Copyright (C) 1983, 1985 by Xerox Corporation. All rights reserved.
-- EtherBooter.mesa, HGM, 6-Apr-85 12:07:35
DIRECTORY
Boot USING [EthernetRequest],
Device USING [Type],
DeviceTypes USING [ethernet],
Heap USING [systemZone],
NSConstants USING [bootServerSocket],
OthelloDefs USING [
AbortingCommand, CommandProcessor, Confirm, GetName,
IndexTooLarge, MyNameIs, ReadShortNumber, RegisterCommandProc],
Runtime USING [CallDebugger],
SpecialBooting USING [BootFromEthernet, BootFromEthernetOne],
String USING [CopyToNewString],
System USING [
broadcastHostNumber, defaultSwitches, HostNumber,
NetworkAddress, nullNetworkNumber, PowerOff, Switches, UpDown],
TemporaryBooting USING [BootButton],
Unformat USING [Error, HostNumber],
PhoneFace USING [krockDeivceOffsetForBooting, phoneLine],
Watchdog USING [Activate, Deactivate];
EtherBooter: PROGRAM
IMPORTS
Heap, OthelloDefs, Runtime, SpecialBooting, String, System,
TemporaryBooting, Unformat,
Watchdog =
BEGIN
bootFileNumber: LONG STRING;
switches: LONG STRING ← NIL;
EtherBoot: PROCEDURE [device: Device.Type] =
BEGIN
phone: BOOLEAN = device = PhoneFace.phoneLine;
where: Boot.EthernetRequest;
bfn: System.HostNumber;
board: CARDINAL ← 0;
address: System.NetworkAddress;
krock: CARDINAL ← IF phone THEN PhoneFace.krockDeivceOffsetForBooting ELSE 0;
OthelloDefs.GetName[
IF phone THEN "Phone Boot from boot file number: "L
ELSE "Ether Boot from boot file number: "L,
@bootFileNumber];
GetAddress[@bfn, bootFileNumber !
Unformat.Error => OthelloDefs.AbortingCommand["Can't parse that one (No CH)"L]];
OthelloDefs.GetName["Switches: "L, @switches];
board ← OthelloDefs.ReadShortNumber[IF phone THEN "Line: " ELSE "Board: "L, 0, 3, board];
OthelloDefs.Confirm[];
address ← [
net: System.nullNetworkNumber,
host: System.broadcastHostNumber,
socket: NSConstants.bootServerSocket];
where ← [
bfn: [LOOPHOLE[bfn]],
address: address ];
Watchdog.Activate[(IF phone THEN 10 ELSE 5)*60];
SpecialBooting.BootFromEthernet[
ethernetRequest: where, deviceOrdinal: krock+board, switches: DecodeSwitches[switches]];
END;
GetAddress: PROCEDURE [host: POINTER TO System.HostNumber, s: LONG STRING] =
BEGIN
host↑ ← Unformat.HostNumber[s, octal];
END;
PupEtherBoot: PROCEDURE =
BEGIN
bfn: CARDINAL;
board: CARDINAL ← 0;
bfn ← OthelloDefs.ReadShortNumber[
"Pup Boot file number: "L, 0, CARDINAL.LAST, 140000B];
board ← OthelloDefs.ReadShortNumber["Board: "L, 0, 3, board];
OthelloDefs.Confirm[];
Watchdog.Activate[5*60];
SpecialBooting.BootFromEthernetOne[
bootFileNumber: bfn, net: 0, host: 0, deviceOrdinal: board,
switches: DecodeSwitches[switches]];
END;
DecodeSwitches: PUBLIC PROC [switchString: LONG STRING]
RETURNS [switches: System.Switches ← System.defaultSwitches] =
BEGIN
escapeCount: CARDINAL ← 0;
setUpDown: System.UpDown ← down;
escapeChar: CHARACTER ← 0C;
IF switchString = NIL THEN RETURN;
FOR i: CARDINAL IN [0..switchString.length) DO
c: CHARACTER = switchString[i];
SELECT TRUE FROM
c = '-, c = '~ => {
IF setUpDown = up THEN BadSwitches[] ELSE {setUpDown ← up; LOOP}};
c = '\\ => {
IF escapeCount # 0 THEN BadSwitches[] ELSE {escapeCount ← 1; LOOP}};
escapeCount = 1 => {
SELECT c FROM
'n, 'N, 'r, 'R => {switches['\n] ← setUpDown; escapeCount ← 0};
't, 'T => {switches['\t] ← setUpDown; escapeCount ← 0};
'b, 'B => {switches['\b] ← setUpDown; escapeCount ← 0};
'f, 'F => {switches['\f] ← setUpDown; escapeCount ← 0};
'l, 'L => {switches['\l] ← setUpDown; escapeCount ← 0};
'\\ => {switches['\\] ← setUpDown; escapeCount ← 0};
IN ['0..'7] => {
escapeChar ← c - ('0 - 0C); escapeCount ← escapeCount + 1};
ENDCASE => BadSwitches[];
LOOP};
escapeCount # 0 => {
IF c NOT IN ['0..'7] THEN BadSwitches[];
escapeChar ← (c - '0) + (escapeChar - 0C) * 8 + 0C;
IF escapeChar > 377C THEN BadSwitches[];
IF (escapeCount ← escapeCount + 1) = 4 THEN {
switches[escapeChar] ← setUpDown; escapeCount ← 0};
LOOP};
ENDCASE => switches[c] ← setUpDown;
-- fall through to here if normal set or escape set
-- but not on seeing or while collecting escape
setUpDown ← down;
ENDLOOP;
IF escapeCount # 0 THEN BadSwitches[];
END;
BadSwitches: PROCEDURE =
BEGIN
OthelloDefs.AbortingCommand["Bad Switches"L];
END;
Commands: PROCEDURE [index: CARDINAL] =
BEGIN
SELECT index FROM
0 =>
BEGIN
SIGNAL OthelloDefs.MyNameIs[
myNameIs: "Boot Button"L,
myHelpIs: "Push the boot button"L];
OthelloDefs.Confirm[];
TemporaryBooting.BootButton[];
END;
1 =>
BEGIN
OthelloDefs.MyNameIs[
myNameIs: "Boot From Ethernet"L,
myHelpIs: "Load another program over the 10MB Ethernet"L];
EtherBoot[DeviceTypes.ethernet];
END;
2 =>
BEGIN
OthelloDefs.MyNameIs[
myNameIs: "Boot From Phone Line"L,
myHelpIs: "Load another program over the Phone Line"L];
EtherBoot[PhoneFace.phoneLine];
END;
3 =>
BEGIN
OthelloDefs.MyNameIs[
myNameIs: "Boot From Pup(3MB)"L,
myHelpIs: "Load another program over the 3MB Ethernet"L];
PupEtherBoot[];
END;
4 =>
BEGIN
SIGNAL OthelloDefs.MyNameIs[
myNameIs: "Debug",
myHelpIs: "Call CoPilot"L];
OthelloDefs.Confirm[];
Watchdog.Deactivate[];
Runtime.CallDebugger["Hi"L];
END;
5 =>
BEGIN
SIGNAL OthelloDefs.MyNameIs[
myNameIs: "Power Off",
myHelpIs: "Execute System.PowerOff"L];
OthelloDefs.Confirm[];
System.PowerOff[];
END;
ENDCASE => OthelloDefs.IndexTooLarge;
END;
commandProcessor: OthelloDefs.CommandProcessor ← [Commands];
bootFileNumber ← String.CopyToNewString["25200002000", Heap.systemZone]; -- Setup Default
OthelloDefs.RegisterCommandProc[@commandProcessor];
END.....