--ILTBootImpl.mesa --Created by -- JFung.PASA 19-Dec-83 11:35:03 --last edited by -- JFung.PASA 19-Dec-83 13:55:39 DIRECTORY CmFile, Display, Environment, Event, Exec, File, FileTypes, FileTransfer, FormSW, Heap, Inline, LispToolOps, OthelloOps, Process, Put, Runtime, Space, String, TemporaryBooting, Time, Token, Tool, ToolDriver, ToolWindow, UserInput, Version, Volume, Window; ILTBootImpl: PROGRAM IMPORTS Display, File, FormSW, Heap, Inline, LispToolOps, OthelloOps, Process, Put, Runtime, Space, String, TemporaryBooting, Time, Tool, ToolDriver, UserInput, Version, Volume, Window EXPORTS LispToolOps = BEGIN OPEN ILT: LispToolOps, OthelloOps; -- TYPEs Indicator: TYPE = {off, left, right}; VolHints: TYPE = RECORD [names: SEQUENCE length: CARDINAL OF LONG STRING]; SizeHints: TYPE = RECORD [names: SEQUENCE length: CARDINAL OF CARDINAL]; DataHandle: TYPE = LONG POINTER TO Data; Data: TYPE = MACHINE DEPENDENT RECORD [ -- Message subwindow stuff msgSW(0): Window.Handle ← NIL, -- File subwindow stuff fileSW(2): Window.Handle ← NIL, -- Form subwindow stuff -- Note: enumerateds and booleans must be word boundary -- aligned as addresses for them must be generated --formSW: Window.Handle ← NIL, paramSW(4): Window.Handle ← NIL, commandSW(6): Window.Handle ← NIL, busy(8): BOOLEAN ← FALSE, -- command is running destVolName(9): LONG STRING ← NIL, srcVolName(11): LONG STRING ← NIL, connection(13): FileTransfer.Connection ← NIL, indicator(15): Indicator ← left]; active: BOOLEAN ← FALSE; copyWH: Window.Handle ← NIL; debug: BOOLEAN ← FALSE; toolData: DataHandle ← NIL; formDisplay: ToolWindow.DisplayProcType ← NIL; indicatorBox: Window.Box = [[10, 10], [16, 16]]; volume: Volume.ID ← Volume.nullID; BootStuff: PUBLIC PROCEDURE = BEGIN IF toolData = NIL THEN toolData ← Heap.systemZone.NEW[Data ← []]; IF debug THEN { Put.Line[ILT.toolData.fileSW, "MakeTool...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; IF ILT.Confirm[] THEN copyWH ← MakeTool[]; END; --BootStuff ClearCommandSubwindow: PROCEDURE = BEGIN item: FormSW.ItemHandle; FOR i: CARDINAL ← 0, i + 1 UNTIL (item ← FormSW.FindItem[toolData.commandSW, i]) = NIL DO item.flags.invisible ← TRUE ENDLOOP; FormSW.Display[toolData.commandSW]; toolData.indicator ← left; formDisplay ← Window.GetDisplayProc[toolData.commandSW]; [] ← Window.SetDisplayProc[toolData.commandSW, DisplayEmpty]; END; --ClearCommandSubwindow ClearFileSubwindow: PROCEDURE = BEGIN item: FormSW.ItemHandle; FOR i: CARDINAL ← 0, i + 1 UNTIL (item ← FormSW.FindItem[toolData.fileSW, i]) = NIL DO item.flags.invisible ← TRUE ENDLOOP; FormSW.Display[toolData.fileSW]; --formDisplay ← Window.GetDisplayProc[toolData.fileSW]; END; --ClearFileSubwindow ClearMsgSubwindow: PROCEDURE = BEGIN item: FormSW.ItemHandle; FOR i: CARDINAL ← 0, i + 1 UNTIL (item ← FormSW.FindItem[toolData.msgSW, i]) = NIL DO item.flags.invisible ← TRUE ENDLOOP; FormSW.Display[toolData.msgSW]; --formDisplay ← Window.GetDisplayProc[toolData.msgSW]; END; --ClearMsgSubwindow ClearSubWindows: PROCEDURE = BEGIN --ClearFileSubwindow; ClearMsgSubwindow; END; --ClearSubWindows CloseVolume: PUBLIC PROC [vID: Volume.ID] RETURNS [vOpen: BOOLEAN] = BEGIN IF vOpen THEN {Volume.Close[vID]; vOpen ← FALSE; } END; << ClientTransition: ToolWindow.TransitionProcType = -- This procedure is called whenever the system determines that this -- Tool's state is undergoing a user invoked transition. -- In this Example we demonstrate a technique that minimizes the memory -- requirements for a Tool that is inactive. BEGIN SELECT TRUE FROM old = inactive => BEGIN IF toolData = NIL THEN toolData ← Heap.systemZone.NEW[Data ← []]; active ← TRUE; END; new = inactive => BEGIN IF toolData # NIL THEN BEGIN FormSW.Destroy[toolData.paramSW]; FormSW.Destroy[toolData.commandSW]; Heap.systemZone.FREE[@toolData]; END; --ToolDriver.RemoveSWs[tool: "LispTool"L]; active ← FALSE; END; ENDCASE END; --ClientTransition >> DisplayCommandSubwindow: PROCEDURE = BEGIN item: FormSW.ItemHandle; toolData.indicator ← off; [] ← Window.SetDisplayProc[toolData.commandSW, formDisplay]; FormSW.Display[toolData.commandSW]; FOR i: CARDINAL ← 0, i + 1 UNTIL (item ← FormSW.FindItem[toolData.commandSW, i]) = NIL DO item.flags.invisible ← FALSE ENDLOOP; FormSW.Display[toolData.commandSW]; END; --DisplayCommandSubwindow DisplayEmpty: ToolWindow.DisplayProcType = BEGIN ENABLE UNWIND => NULL; IF ~toolData.busy THEN RETURN; DisplayIndicator[window]; END; DisplayIndicator: ToolWindow.DisplayProcType = { pattern: ARRAY [0..1] OF ARRAY [0..8) OF WORD; SELECT toolData.indicator FROM left => { pattern ← [ [ 111000B, 052000B, 034000B, 177000B, 034000B, 052000B, 111000B, 000000B], [ 000222B, 000124B, 000070B, 000376B, 000070B, 000124B, 000222B, 000000B]]; Display.Bitmap[ window, indicatorBox, [@pattern, , 0], 16, Display.replaceFlags]}; right => { pattern ← [ [ 000222B, 000124B, 000070B, 000376B, 000070B, 000124B, 000222B, 000000B], [ 111000B, 052000B, 034000B, 177000B, 034000B, 052000B, 111000B, 000000B]]; Display.Bitmap[ window, indicatorBox, [@pattern, , 0], 16, Display.replaceFlags]}; ENDCASE}; --DisplayIndicator DoInstall: UserInput.PeriodicProcType = BEGIN ClearMsgSubwindow; IF debug THEN { Put.Line[toolData.fileSW, "Start Install ....."L]; Process.Pause[Process.SecondsToTicks[5]]; }; ClearCommandSubwindow; DisplayIndicator[toolData.commandSW]; toolData.busy ← TRUE; IF Retrieve[] THEN BEGIN Put.Line[toolData.fileSW, "\n Boot destination volume?"L]; IF ILT.Confirm[] THEN TemporaryBooting.BootButton[]; END; DisplayCommandSubwindow; toolData.busy ← FALSE; END; --DoInstall FormSWBoot: FormSW.ProcType = BEGIN IF debug THEN { Put.Line[toolData.fileSW, "FormSWCopyProc...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; [] ← UserInput.CreatePeriodicNotify[ proc: DoInstall, window: sw, rate: 0]; END; --FormSWBoot FormSWQuit: FormSW.ProcType = BEGIN IF toolData # NIL THEN BEGIN Tool.Destroy[copyWH]; Heap.systemZone.FREE[@toolData]; END; END; --FormSWQuit FormSWVolHintsProc: FormSW.MenuProcType = BEGIN RETURN[ hints: DESCRIPTOR[ @ILT.toolData.volHints[0], ILT.toolData.volHints.length], freeHintsProc: HintsNoLongerBusy, replace: TRUE]; END; HintsNoLongerBusy: FormSW.FreeHintsProcType = BEGIN END; InvertIndicator: PROC [] = BEGIN ENABLE UNWIND => NULL; pattern: ARRAY [0..1] OF ARRAY [0..8) OF WORD; IF ~toolData.busy THEN RETURN; SELECT toolData.indicator FROM left => { pattern ← [ [ 000222B, 000124B, 000070B, 000376B, 000070B, 000124B, 000222B, 000000B], [ 111000B, 052000B, 034000B, 177000B, 034000B, 052000B, 111000B, 000000B]]; Display.Bitmap[ toolData.commandSW, indicatorBox, [@pattern, , 0], 16, Display.replaceFlags]; toolData.indicator ← right}; right => { pattern ← [ [ 111000B, 052000B, 034000B, 177000B, 034000B, 052000B, 111000B, 000000B], [ 000222B, 000124B, 000070B, 000376B, 000070B, 000124B, 000222B, 000000B]]; Display.Bitmap[ toolData.commandSW, indicatorBox, [@pattern, , 0], 16, Display.replaceFlags]; toolData.indicator ← left}; off => toolData.indicator ← left; ENDCASE; END; MakeCommands: FormSW.ClientItemsProcType = BEGIN OPEN FormSW; tabs: ARRAY [0..2) OF CARDINAL ← [0, 60]; nItems: CARDINAL = 2; items ← AllocateItemDescriptor[nItems]; items[0] ← CommandItem[tag: "Start"L, place: newLine, proc: FormSWBoot]; items[1] ← CommandItem[tag: "Quit"L, place: newLine, proc: FormSWQuit]; SetTagPlaces[items, DESCRIPTOR[tabs], FALSE]; RETURN[items, TRUE]; END; --MakeCommands MakeParams: FormSW.ClientItemsProcType = BEGIN OPEN FormSW; i, nVols: CARDINAL; tabs: ARRAY [0..4) OF CARDINAL ← [0, 30, 60, 75]; nItems: CARDINAL = 2; items ← AllocateItemDescriptor[nItems]; nVols ← ILT.ListLogicalVolumes[]; String.Copy[toolData.destVolName, ILT.toolData.volHints[0]]; FOR i IN [0..nVols) DO IF String.Equivalent[ILT.toolData.volHints[i], "Lisp"L] THEN BEGIN String.Replace[ @toolData.destVolName, ILT.toolData.volHints[i], Heap.systemZone]; EXIT; END; ENDLOOP; String.Copy[toolData.srcVolName, ILT.toolData.volHints[0]]; FOR i IN [0..nVols) DO IF String.Equivalent[ILT.toolData.volHints[i], "Lisp"L] THEN BEGIN String.Replace[ @toolData.srcVolName, ILT.toolData.volHints[i], Heap.systemZone]; EXIT; END; ENDLOOP; items[0] ← StringItem[ tag: "Source Volume"L, place: newLine, string: @toolData.srcVolName, inHeap: TRUE, menuProc: FormSWVolHintsProc]; items[1] ← StringItem[ tag: "Dest. Volume"L, string: @toolData.destVolName, inHeap: TRUE, menuProc: FormSWVolHintsProc]; SetTagPlaces[items, DESCRIPTOR[tabs], FALSE]; RETURN[items, TRUE] END; --MakeParams MakeSWs: Tool.MakeSWsProc = BEGIN addresses: ARRAY [0..4) OF ToolDriver.Address; logName: STRING ← [20]; Tool.UnusedLogName[unused: logName, root: "CopyOption.log"L]; toolData.msgSW ← Tool.MakeMsgSW[window: window, lines: 1]; toolData.paramSW ← Tool.MakeFormSW[window: window, formProc: MakeParams]; toolData.commandSW ← Tool.MakeFormSW[ window: window, formProc: MakeCommands]; --note: logName is compulsory, else it bombs toolData.fileSW ← Tool.MakeFileSW[window: window, name: logName]; --Supervisor.AddDependency[client: agent, implementor: Event.toolWindow]; -- do the ToolDriver stuff addresses ← [ [name: "msgSW"L, sw: toolData.msgSW], --[name: "formSW"L, sw: toolData.formSW], [name: "ParamSW"L, sw: toolData.paramSW], [ name: "CmdSW"L, sw: toolData.commandSW], [ name: "fileSW"L, sw: toolData.fileSW]]; ToolDriver.NoteSWs[ tool: "Boot Options"L, subwindows: DESCRIPTOR[addresses]]; END; --MakeSWs MakeTool: PROCEDURE RETURNS [wh: Window.Handle] = BEGIN heraldName: STRING ← [80]; String.AppendString[heraldName, "XSIS:Xerox Remote Boot Option"L]; String.AppendString[heraldName, " of "L]; Time.Append[heraldName, Time.Unpack[Runtime.GetBcdTime[]]]; heraldName.length ← heraldName.length - 3; String.AppendString[heraldName, " on Pilot Version "L]; Version.Append[heraldName]; RETURN[ Tool.Create[ makeSWsProc: MakeSWs, initialState: default, --clientTransition: ClientTransition, name: heraldName]]; --initialBox: [ --place: sw.BitmapPlace[[10, hisBox.dims.h]], --dims: [hisBox.dims.w - 20, 180]]]; END; --MakeTool Retrieve: PROC[] RETURNS [BOOLEAN] = BEGIN OPEN OthelloOps; base: LONG POINTER ← NIL; bufferPages: Space.PageCount = 100; created: BOOLEAN ← FALSE; destCap: File.Capability; destVolumeID: Volume.ID ← Volume.nullID; destVolumeOpen: BOOLEAN ← FALSE; firstPage: File.PageNumber; freePages: Volume.PageCount; pageCount: INTEGER ← 0; space: Space.Handle ← Space.nullHandle; srcCap: File.Capability; srcVolumeID: Volume.ID ← Volume.nullID; srcVolumeOpen: BOOLEAN ← FALSE; uCodeSize: File.PageCount ← 0; volSize: Volume.PageCount ← 0; Cleanup: PROC = BEGIN IF debug THEN { Put.Line[toolData.fileSW, "Enter Cleanup....."L]; Process.Pause[Process.SecondsToTicks[5]]; }; IF space # Space.nullHandle THEN BEGIN IF debug THEN { Put.Line[toolData.fileSW, "space # null handle..."L]; Process.Pause[Process.SecondsToTicks[5]]; }; Space.Delete[space]; space ← Space.nullHandle; END; --CloseVolume[]; END; --Cleanup Put.Line[toolData.fileSW, "Will copy Source Volume boot file into Dest. Volume and boot Dest. Volume"L]; Put.Line[toolData.fileSW, "Confirm to continue?"L]; IF ~ILT.Confirm[] THEN RETURN[FALSE]; [srcVolumeID, srcVolumeOpen] ← ILT.GetVolumeID[toolData.srcVolName]; IF srcVolumeID = Volume.nullID THEN RETURN[FALSE]; [destVolumeID, destVolumeOpen] ← ILT.GetVolumeID[toolData.destVolName]; IF destVolumeID = Volume.nullID THEN RETURN[FALSE]; IF String.Equivalent[toolData.srcVolName, toolData.destVolName] THEN BEGIN Put.Line[toolData.msgSW, " Source Volume equals Destination Volume"]; RETURN[FALSE]; END; [volSize, freePages] ← Volume.GetAttributes[srcVolumeID]; Put.Text[toolData.fileSW, " \n Source Volume size = "L]; Put.LongDecimal[toolData.fileSW, volSize]; Put.Line[toolData.fileSW, " pages"L]; Put.Text[toolData.fileSW, " Free pages on source volume = "L]; Put.LongDecimal[toolData.fileSW, freePages]; Put.CR[toolData.fileSW]; [volSize, freePages] ← Volume.GetAttributes[destVolumeID]; Put.Text[toolData.fileSW, " \n Destination Volume size = "L]; Put.LongDecimal[toolData.fileSW, volSize]; Put.Line[toolData.fileSW, " pages"L]; Put.Text[toolData.fileSW, " Free pages on destination volume = "L]; Put.LongDecimal[toolData.fileSW, freePages]; Put.CR[toolData.fileSW]; [srcCap, firstPage] ← GetVolumeBootFile[srcVolumeID, hardMicrocode]; [destCap, firstPage] ← GetVolumeBootFile[destVolumeID, hardMicrocode]; IF destCap = File.nullCapability THEN BEGIN IF debug THEN { Put.Line[ILT.toolData.fileSW, " = nullCapability...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; destCap ← File.Create[destVolumeID, 0, FileTypes.tUntypedFile]; END ELSE BEGIN IF debug THEN { Put.Line[ILT.toolData.fileSW, " MakeUnbootable.."L]; Process.Pause[Process.SecondsToTicks[5]]; }; MakeUnbootable[ destCap, hardMicrocode, firstPage ! TemporaryBooting.InvalidParameters => BEGIN Put.Text[ILT.toolData.msgSW, "Warning: trouble making unbootable"L]; CONTINUE; END]; END; IF srcCap = File.nullCapability THEN uCodeSize ← 0 ELSE uCodeSize ← File.GetSize[srcCap]; Put.Text[toolData.fileSW, " Source boot file size = "]; Put.LongDecimal[toolData.fileSW, uCodeSize]; Put.Text[toolData.fileSW, " pages; "]; Put.LongDecimal[toolData.fileSW, uCodeSize*512]; Put.Line[toolData.fileSW, " bytes."]; <<File.SetSize[destCap, uCodeSize ! File.Unknown => { Put.Line[toolData.fileSW, " File.Unknown!"L]; Cleanup[]; GOTO noGood}]; IF debug THEN { Put.Line[toolData.fileSW, "SetSize...."L]; Process.Pause[Process.SecondsToTicks[10]]; }; File.SetSize[destCap, uCodeSize ! Volume.Unknown => { Put.Line[toolData.fileSW, " Volume.Unknown!"L]; Cleanup[]; GOTO noGood}];>> IF debug THEN { Put.Line[toolData.fileSW, "SetSize...."L]; Process.Pause[Process.SecondsToTicks[10]]; }; File.SetSize[destCap, uCodeSize ! Volume.InsufficientSpace => { Put.Line[toolData.fileSW, " Not enough room on dest. volume!"L]; Cleanup[]; GOTO noGood}]; IF debug THEN { Put.Line[toolData.fileSW, "Create...."L]; Process.Pause[Process.SecondsToTicks[10]]; }; space ← Space.Create[bufferPages, Space.virtualMemory]; IF debug THEN { Put.Line[toolData.fileSW, "Map...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; Space.Map[space]; IF debug THEN { Put.Line[toolData.fileSW, "CreateUniformSwapUnits...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; Space.CreateUniformSwapUnits[size: 16, parent: space]; IF debug THEN { Put.Line[toolData.fileSW, "LongPointer...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; base ← Space.LongPointer[space]; FOR windowPage: Space.PageOffset ← 0, windowPage + bufferPages WHILE windowPage < Inline.LowHalf[uCodeSize] DO Space.CopyIn[space, [srcCap, windowPage]]; Space.CopyOut[space, [destCap, windowPage]]; pageCount ← pageCount + bufferPages; Put.Text[toolData.msgSW, "Pages transfered: "]; Put.Decimal[toolData.msgSW, pageCount]; Put.CR[toolData.msgSW]; InvertIndicator[]; ENDLOOP; IF debug THEN { Put.Line[toolData.fileSW, "Cleanup...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; Cleanup[]; IF debug THEN { Put.Text[toolData.fileSW, "SetVolumeBootFile..."L]; Process.Pause[Process.SecondsToTicks[5]]; }; SetVolumeBootFile[destCap, hardMicrocode, 0]; IF debug THEN { Put.Text[toolData.fileSW, "MakePermanent..."L]; Process.Pause[Process.SecondsToTicks[5]]; }; File.MakePermanent[destCap]; IF debug THEN { Put.Text[toolData.fileSW, "MakeBootable..."L]; Process.Pause[Process.SecondsToTicks[5]]; }; MakeBootable[ destCap, hardMicrocode, 0 ! TemporaryBooting.InvalidParameters => BEGIN Put.Text[toolData.msgSW, "Warning: trouble making bootable"L]; CONTINUE; END]; Put.Line[toolData.fileSW, " installed."L]; IF debug THEN { Put.Text[toolData.fileSW, "SetPhysicalVolumeBootFile..."L]; Process.Pause[Process.SecondsToTicks[5]]; }; SetPhysicalVolumeBootFile[destCap, hardMicrocode, 0]; destVolumeOpen ← CloseVolume[destVolumeID]; srcVolumeOpen ← CloseVolume[srcVolumeID]; RETURN[TRUE]; EXITS noGood => RETURN[FALSE]; END; --Retrieve END...ILTBootImpl.mesa