-- 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.....