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