-- Copyright (C) 1983, 1985 by Xerox Corporation. All rights reserved. -- PupBootServerNoDisk.mesa, HGM, 6-Aug-85 21:05:49 DIRECTORY Ascii USING [CR], CmFile USING [Handle, TableError], Event USING [aboutToSwap], EventTypes USING [aboutToBoot, aboutToBootPhysicalVolume], Heap USING [systemZone], Process USING [Detach], Put USING [Text], String USING [AppendChar, AppendNumber, AppendString], StringLookUp USING [noMatch], Supervisor USING [ AddDependency, AgentProcedure, CreateSubsystem, RemoveDependency, SubsystemHandle], Token USING [FreeTokenString, Item, Octal], Buffer USING [ReturnBuffer], BootServerDefs USING [ bootStatsRequest, BreatherOff, BreatherOn, lockBooterRequest, lockBooterReply, unlockBooterRequest, unlockBooterReply, microcodeRequest, slowMicrocodeRequest, sunBootRequest], Indirect USING [Close, GetParmFileName, NextValue, OpenSection], MiscServerDefs USING [ PupMiscServerOn, PupMiscServerOff, IgnoreThisPacket, SetBootServer], PupDefs USING [ GetLocalPupAddress, GetPupAddress, GetPupContentsBytes, PupBuffer, PupNameTrouble, PupRouterSendThis, PupSocket, PupSocketDestroy, PupSocketMake, ReturnPup, SecondsToTocks, Tocks], PupRouterDefs USING [NetworkContext], PupTypes USING [fillInPupAddress, fillInSocketID, miscSrvSoc, PupAddress, PupNetID], Stats USING [StatCounterIndex, StatsStringToIndex]; PupBootServerNoDisk: MONITOR IMPORTS CmFile, Event, Heap, Indirect, Process, Put, String, Supervisor, Token, MiscServerDefs, Buffer, BootServerDefs, PupDefs, Stats EXPORTS BootServerDefs = BEGIN broom: Supervisor.SubsystemHandle = Supervisor.CreateSubsystem[Broom]; z: UNCOUNTED ZONE = Heap.systemZone; remote: Chain ← NIL; relaying: BOOL ← FALSE; Chain: TYPE = LONG POINTER TO ChainSlot; ChainSlot: TYPE = RECORD [ next: Chain, source: PupTypes.PupNetID, dest: PupTypes.PupAddress, target: LONG STRING]; dirRunning: PUBLIC BOOLEAN ← FALSE; useCount: CARDINAL ← 0; lock: BOOLEAN ← FALSE; verbose: BOOLEAN = TRUE; parmFileName: LONG STRING ← Indirect.GetParmFileName[]; statLife: PUBLIC Stats.StatCounterIndex; PupBootServerOn: PUBLIC ENTRY PROCEDURE = BEGIN IF (useCount ← useCount + 1) = 1 THEN BEGIN Supervisor.AddDependency[client: broom, implementor: Event.aboutToSwap]; dirRunning ← TRUE; Starter[]; END; END; Starter: PROCEDURE = BEGIN MiscServerDefs.PupMiscServerOn[]; ScanParameterFile[]; MiscServerDefs.SetBootServer[PupBootServer]; Process.Detach[FORK BootServerDefs.BreatherOn[]]; END; PupBootServerOff: PUBLIC ENTRY PROCEDURE = BEGIN IF useCount # 0 AND (useCount ← useCount - 1) = 0 THEN BEGIN dirRunning ← FALSE; Stopper[]; Supervisor.RemoveDependency[client: broom, implementor: Event.aboutToSwap]; END; END; Stopper: INTERNAL PROCEDURE = BEGIN BootServerDefs.BreatherOff[]; MiscServerDefs.SetBootServer[MiscServerDefs.IgnoreThisPacket]; ForgetParameters[]; MiscServerDefs.PupMiscServerOff[]; END; PupBootServer: PUBLIC PROCEDURE [b: PupDefs.PupBuffer] = BEGIN OPEN BootServerDefs; SELECT b.pup.pupType FROM bootFileSend, microcodeRequest, slowMicrocodeRequest => ForwardThisOne[b]; bootDirReq, sunBootRequest => ForwardThisOne[b]; bootStatsRequest => Buffer.ReturnBuffer[b]; lockBooterRequest => BEGIN lock ← TRUE; PupDefs.ReturnPup[b, lockBooterReply, 0]; END; unlockBooterRequest => BEGIN lock ← FALSE; PupDefs.ReturnPup[b, unlockBooterReply, 0]; END; ENDCASE => Buffer.ReturnBuffer[b]; END; ForwardThisOne: PROCEDURE [b: PupDefs.PupBuffer] = BEGIN context: PupRouterDefs.NetworkContext = b.context; IF b.pup.source.net = 0 THEN b.pup.source.net ← [context.pupNetNumber]; FOR finger: Chain ← remote, finger.next UNTIL finger = NIL DO IF context.pupNetNumber = finger.source THEN BEGIN IF finger.dest = PupTypes.fillInPupAddress THEN EXIT; IF b.pup.pupType = BootServerDefs.microcodeRequest OR b.pup.pupType = BootServerDefs.slowMicrocodeRequest THEN { IF relaying THEN EXIT; relaying ← TRUE; Process.Detach[FORK RelayThisOne[b, finger.dest]]; RETURN; }; b.pup.dest.net ← finger.dest.net; b.pup.dest.host ← finger.dest.host; PupDefs.PupRouterSendThis[b]; RETURN; END; ENDLOOP; Buffer.ReturnBuffer[b]; END; -- Yuck, Dorados (and probably Dolphins) filter pupType on whole word -- Rejecting things with a non-zero hop count second: PupDefs.Tocks = PupDefs.SecondsToTocks[1]; RelayThisOne: PROCEDURE [b: PupDefs.PupBuffer, server: PupTypes.PupAddress] = BEGIN him: PupTypes.PupAddress ← b.pup.source; me: PupTypes.PupAddress ← PupDefs.GetLocalPupAddress[PupTypes.miscSrvSoc, @him]; soc: PupDefs.PupSocket ← PupDefs.PupSocketMake[PupTypes.fillInSocketID, server, second]; b.pup.dest.net ← server.net; b.pup.dest.host ← server.host; b.pup.source ← soc.getLocalAddress[]; b.pup.pupType ← BootServerDefs.slowMicrocodeRequest; PupDefs.PupRouterSendThis[b]; DO b ← soc.get[]; IF b = NIL THEN EXIT; -- Timeout b.pup.dest ← him; b.pup.source ← me; PupDefs.PupRouterSendThis[b]; IF PupDefs.GetPupContentsBytes[b] = 0 THEN EXIT; ENDLOOP; PupDefs.PupSocketDestroy[soc]; relaying ← FALSE; END; ScanParameterFile: PROCEDURE = BEGIN cmFile: CmFile.Handle; Option: TYPE = {remote}; NextValue: PROCEDURE [ h: CmFile.Handle, table: LONG DESCRIPTOR FOR ARRAY Option OF LONG STRING] RETURNS [Option] = LOOPHOLE[Indirect.NextValue]; optionTable: ARRAY Option OF LONG STRING ← [remote: "Remote"L]; cmFile ← Indirect.OpenSection["PupBootServer"L]; IF cmFile = NIL THEN RETURN; DO option: Option; option ← NextValue[ cmFile, DESCRIPTOR[optionTable] ! CmFile.TableError => BEGIN IF name[0] # '; THEN Message["Unrecognized parameter: ", name]; RETRY; END]; SELECT option FROM LOOPHOLE[StringLookUp.noMatch] => EXIT; remote => BEGIN source: PupTypes.PupNetID = [Token.Octal[cmFile]]; temp: LONG STRING ← Token.Item[cmFile, FALSE]; new: Chain ← z.NEW[ChainSlot]; new↑ ← [NIL, source, PupTypes.fillInPupAddress, z.NEW[StringBody[temp.length]]]; String.AppendString[new.target, temp]; [] ← Token.FreeTokenString[temp]; PupDefs.GetPupAddress[@new.dest, new.target ! PupDefs.PupNameTrouble => CONTINUE]; IF remote = NIL THEN remote ← new ELSE BEGIN FOR finger: Chain ← remote, finger.next DO IF finger.next = NIL THEN BEGIN finger.next ← new; EXIT; END; ENDLOOP; END; MessageNet["Forwarding Pup boot requests from net "L, new.source, " to "L, new.target]; END; ENDCASE => ERROR; ENDLOOP; Indirect.Close[cmFile]; END; ForgetParameters: PROCEDURE = BEGIN UNTIL remote = NIL DO temp: Chain ← remote; remote ← remote.next; z.FREE[@temp.target]; z.FREE[@temp]; ENDLOOP; END; MessageNet: PROCEDURE [one: LONG STRING, net: CARDINAL, three, four: LONG STRING] = BEGIN two: STRING = [20]; String.AppendNumber[two, net, 8]; Message[one, two, three, four]; END; Message: PROCEDURE [one, two, three, four: LONG STRING ← NIL] = BEGIN text: STRING = [200]; String.AppendString[text, one]; IF two # NIL THEN String.AppendString[text, two]; IF three # NIL THEN String.AppendString[text, three]; IF four # NIL THEN String.AppendString[text, four]; LogString[text]; END; LogString: PROCEDURE [text: LONG STRING] = BEGIN String.AppendChar[text, '.]; String.AppendChar[text, Ascii.CR]; Put.Text[NIL, text]; END; Broom: ENTRY Supervisor.AgentProcedure = BEGIN SELECT event FROM EventTypes.aboutToBoot, EventTypes.aboutToBootPhysicalVolume => IF dirRunning THEN Stopper[]; ENDCASE => NULL; END; -- initialization statLife ← Stats.StatsStringToIndex["Breath of Life packets sent"]; PupBootServerOn[]; END.