--LTInstallImpl.mesa
--Created by
--   JFung.PASA	  	22-Sep-83 10:21:23
--	This is a modified version taken from InstallMuImpl.mesa

--last edited by
--   JFung.PASA	   	10-Sep-84 10:43:52


DIRECTORY
     Ascii,
     Display,
     Environment USING [bytesPerPage, PageCount, PageOffset],
     File USING [
          Create, Delete, File, GetAttributes, GetSize, MakePermanent, nullFile,
          PageCount, PageNumber, SetSize, Unknown],
     FileName: TYPE USING [AllocVFN, FreeVFN, NormalizeVFN, UnpackFilename, VFN],
     FileTransfer,
     FileTypes USING [tUntypedFile],
     FormSW,
     Heap,
     Inline USING [LowHalf],
     LispToolOps,
     NSName USING [maxFullNameLength],
     OthelloDefs,
     OthelloOps USING [
          GetPhysicalVolumeBootFile, GetVolumeBootFile, MakeBootable,
          MakeUnbootable, SetPhysicalVolumeBootFile, SetVolumeBootFile,
          VoidPhysicalVolumeBootFile, VoidVolumeBootFile],
     PhysicalVolume USING [GetContainingPhysicalVolume, ID],
     Process USING [Pause, SecondsToTicks],
     PrincOps USING [Port],
     Put,
     Space USING [
          Access, Allocate, CopyOut, Deallocate, InsufficientSpace, Interval, Map,
          nullInterval, PageCount, PageOffset, SwapUnitSize, Unmap, virtualMemory,
          Window],
     Stream,
     String,
     TemporaryBooting USING [InvalidParameters],
     Time,
     ToolWindow,
     UserInput,
     Volume,
     Window;


LTInstallImpl: PROGRAM
     IMPORTS
          File, FileName, FileTransfer, FormSW, Heap, Inline, LispToolOps, 
          OthelloOps, PhysicalVolume, Process, Put, Space, Stream, String,
          TemporaryBooting, Time, UserInput, Volume, Window


     EXPORTS LispToolOps =

     BEGIN OPEN FileName, ILT: LispToolOps;
     PortRep: TYPE = PrincOps.Port;

     buffer: LONG POINTER ← NIL;
     byteCount: LONG INTEGER ← 0;
     conn: FileTransfer.Connection;
     debug: BOOLEAN ← FALSE;
     defaultVMemSize: File.PageCount;
     file: File.File;
     fileName: LONG STRING ← NIL;
     firstPage: File.PageNumber;

     freePages: Volume.PageCount;
     indicatorBox: Window.Box = [[10, 10], [16, 16]];
     readStream: Stream.Handle ← NIL;
     --spaceInterval: Space.Interval ← Space.nullInterval;
     vfn: VFN ← NIL;
     volumeID: Volume.ID ← Volume.nullID;
     volumeOpen: BOOLEAN ← FALSE;
     volSize: Volume.PageCount;



     CheckForAbort: FileTransfer.CheckAbortProc =
          BEGIN

          IF UserInput.UserAbort[ILT.windowHandle] THEN
               BEGIN
               ILT.toolData.busy ← FALSE;
               Put.Line[ILT.toolData.msgSW, "+++Aborted.. "L];
               Cleanup[];
               ILT.DisplayCommandSubwindow;
               --Process.Pause[Process.SecondsToTicks[10]];
               DisplayOldVMemSize;
               RETURN[TRUE];
               END
          ELSE RETURN[FALSE];
          END;



     Cleanup: PROC =
          BEGIN

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "Enter Cleanup....."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          IF readStream # NIL THEN {readStream.Delete[]; readStream ← NIL;};
          IF buffer # NIL THEN buffer ← Space.Unmap[buffer];
          IF vfn # NIL THEN {FreeVFN[vfn]; vfn ← NIL};
          IF conn # NIL THEN {conn.Destroy[]; conn ← NIL};
          END;  


     CloseVolume: PROC =
          BEGIN
          IF volumeOpen THEN {Volume.Close[volumeID]; volumeOpen ← FALSE}
          END;


     DisplayOldVMemSize: PROC =
          BEGIN
          size: File.PageCount;
          size ← ILT.GetFileSize[];

          ILT.DisplayFileSize[size];
          END;
	  
	  
     ExpandVMemSize: PROC [] =
          BEGIN
	  fileSize: File.PageCount;
          [volSize, freePages] ← Volume.GetAttributes[volumeID];

          fileSize ← IF ILT.toolData.vMemSize = 0 THEN volSize ELSE ILT.toolData.vMemSize;

          File.SetSize[
               file, fileSize !
               Volume.InsufficientSpace => {
	            IF debug THEN {
                    Put.Text[ILT.toolData.fileSW, "Can not set VMem at "L];
                    Put.LongDecimal[ILT.toolData.fileSW, fileSize];
                    Put.Line[ILT.toolData.fileSW, " pages; retrying..."L];};
                    fileSize ← fileSize - 100;
                    RETRY;
                    }];
		    
          [volSize, freePages] ← Volume.GetAttributes[volumeID];
	  fileSize ← fileSize + freePages;
          File.SetSize[
               file, fileSize !
               Volume.InsufficientSpace => {
	            fileSize ← fileSize - 10;
                    RETRY;
                    }];
	  
		    
          [volSize, freePages] ← Volume.GetAttributes[volumeID];

          ILT.toolData.vMemSize ← fileSize;
	  ILT.toolData.currentVolFreeSize ← freePages;
	  -- re-display vMem and free size
	  FormSW.DisplayItem[ILT.toolData.paramSW, 2];
	  FormSW.DisplayItem[ILT.toolData.paramSW, 6];

	  END;  -- ExpandVMemSize


     GetBootFile: PUBLIC PROCEDURE [vName: LONG STRING] RETURNS [volumeID: Volume.ID, file: File.File] =
          BEGIN OPEN OthelloOps;
          created: BOOLEAN ← FALSE;

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "Enter GetBootFile Proc "L];
               Put.LongString[ILT.toolData.fileSW, vName];
               Put.Line[ILT.toolData.fileSW, "ILT.GetVolumeID "L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          
          [volumeID, volumeOpen] ← ILT.GetVolumeID[vName];
          IF volumeID = Volume.nullID THEN RETURN[Volume.nullID, File.nullFile];

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "GetVolumeBootFile....."L];
               Process.Pause[Process.SecondsToTicks[10]];
               };
	  [file, firstPage] ← GetVolumeBootFile[volumeID, hardMicrocode];

          IF (created ← file = File.nullFile) THEN
               BEGIN
               --Put.Line[ILT.toolData.msgSW, "+++No Sysout file installed."L];
               IF debug THEN Process.Pause[Process.SecondsToTicks[20]];
               file ← File.Create[volumeID, 1, FileTypes.tUntypedFile];
               END
          ELSE
               BEGIN
               IF debug THEN {
                    Put.Line[ILT.toolData.fileSW, "MakeUnbootable.."L];
                    Process.Pause[Process.SecondsToTicks[10]];
                    };
               MakeUnbootable[
                    file, hardMicrocode, OthelloDefs.leaderPages !
                    File.Unknown =>
                         BEGIN
                         Put.Text[
                              ILT.toolData.msgSW,
                              "Warning: trouble making unbootable"L];
                         Process.Pause[Process.SecondsToTicks[20]];
                         CONTINUE;
                         END];
               END;

	  RETURN[volumeID, file];
          END;  -- GetBootFile
	  
	  
     GetFile: PORT [file: File.File ← File.nullFile, name: LONG STRING ← NIL]
          RETURNS [BOOLEAN];


     InstallProc: PUBLIC PROCEDURE [volName: LONG STRING] =
          BEGIN

          byteCount ← 0;
          fileName ← ILT.toolData.filePathName;
	  
	  IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "Enter Install Proc "L];
               Put.LongString[ILT.toolData.fileSW, volName];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          volumeID ← Volume.nullID;
          volumeOpen ← FALSE;

                    <<IF ValidateString[fileName] THEN
               InstallFileOnVolume[volName ! UNWIND => CloseVolume[]];>>
	       
	  InstallFileOnVolume[volName ! UNWIND => CloseVolume[]];    
          ILT.DisplayFileSize[ILT.toolData.vMemSize];
          END;  --InstallProc



     InstallFileOnVolume: PROC [volName: LONG STRING] =
          BEGIN OPEN OthelloOps;

          created: BOOLEAN ← FALSE;
          --currentSize: File.PageCount;
                    
          -- clean the PORT up from last time
          LOOPHOLE[GetFile, PortRep].in ← 0;
          -- CONNECT GetFile.out TO Retrieve;
          --Sierra code
          --LOOPHOLE[GetFile, PortRep].out ← Retrieve;

          LOOPHOLE[GetFile, PortRep].out ← LOOPHOLE[Retrieve, LONG UNSPECIFIED];

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "GetVolumeID "L];
               Process.Pause[Process.SecondsToTicks[5]];
               };

	  [volumeID, file] ← GetBootFile[ILT.toolData.volName];
<<
          [volumeID, volumeOpen] ← ILT.GetVolumeID[volName];
          IF volumeID = Volume.nullID THEN RETURN;

          IF debug THEN {
               Put.Text[ILT.toolData.fileSW, "File name ="L];
               Put.LongString[ILT.toolData.fileSW, fileName];
               Put.Line[ILT.toolData.fileSW, " ...."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          conn ← FileTransfer.Create[];
          FileTransfer.SetProcs[
               conn: conn, clientData: NIL, messages: PostComment, login: NIL,
               checkAbort: CheckForAbort];

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "GetVolumeBootFile....."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          [file, firstPage] ← GetVolumeBootFile[volumeID, hardMicrocode];
	  
	  IF ~GetFile[name: fileName] THEN
               BEGIN
               CloseVolume[];
               Put.Line[ILT.toolData.fileSW, " Install failed."L];
               DisplayOldVMemSize;
               ILT.toolData.busy ← FALSE;
               RETURN;
               END;

          [volSize, freePages] ← Volume.GetAttributes[volumeID];

          defaultVMemSize ← volSize;

          IF (created ← file = File.nullFile) THEN
               BEGIN
               IF debug THEN {
                    Put.Line[ILT.toolData.fileSW, " = nullFile...."L];
                    Process.Pause[Process.SecondsToTicks[5]];
                    };
               file ← File.Create[volumeID, 1, FileTypes.tUntypedFile];
               --set default vMem size
               --dont overwrite user's selection
               IF ILT.toolData.vMemSize = 0 THEN
                    ILT.toolData.vMemSize ← defaultVMemSize;
               END
          ELSE
               BEGIN
               IF debug THEN {
                    Put.Line[ILT.toolData.fileSW, " MakeUnbootable.."L];
                    Process.Pause[Process.SecondsToTicks[5]];
                    };

               MakeUnbootable[
                    file, hardMicrocode, firstPage !
		    File.Unknown => CONTINUE;
                    TemporaryBooting.InvalidParameters =>
                         BEGIN
                         Put.Text[
                              ILT.toolData.msgSW,
                              "+++Warning: trouble making unbootable"L];
                         Put.Line[
                              ILT.toolData.msgSW,
                              "+++InvalidParameters error in MakeUnbootable.."L];
                         Process.Pause[Process.SecondsToTicks[20]];
                         CONTINUE;
                         END];
               END;

          --ILT.DisplayFileSize[ILT.toolData.vMemSize];
          [volSize, freePages] ← Volume.GetAttributes[volumeID];
>>

	  
          conn ← FileTransfer.Create[];
          FileTransfer.SetProcs[
               conn: conn, clientData: NIL, messages: PostComment, login: NIL,
               checkAbort: CheckForAbort];

	  
	  IF ~GetFile[name: fileName] THEN
               BEGIN
               CloseVolume[];
               Put.Line[ILT.toolData.fileSW, " Install failed."L];
               DisplayOldVMemSize;
               ILT.toolData.busy ← FALSE;
               RETURN;
               END;


	  -- control goes to Retrieve procedure
	  
          Put.Text[ILT.toolData.fileSW, " Fetching... "L];
          IF ~GetFile[
               file: file !
               UNWIND => {
                    IF created THEN File.Delete[file];
                    --Put.Line[ILT.toolData.fileSW, " UNWIND  ~GetFile"L];
                    CloseVolume[]}] THEN
               BEGIN
               IF created THEN File.Delete[file];
               CloseVolume[];
               Put.Line[ILT.toolData.msgSW, "+++cannot fetch file "L];
               DisplayOldVMemSize;
               RETURN;
               END;
	       
	 SetupBootFile[volumeID];    
<<      ILT.SetVMemSize[];

10-Sep-84 17:06:28	  

          IF debug THEN {
               Put.Text[ILT.toolData.fileSW, "SetVolumeProc..."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          [] ← ILT.SetVolumeProc[ILT.toolData.volName];
          SetVolumeBootFile[
               file, hardMicrocode, OthelloDefs.leaderPages !
               File.Unknown => {
                    Put.Text[
                         ILT.toolData.msgSW,
                         "+++File.Unknown error in SetVolumeBootFile"L];
                    Process.Pause[Process.SecondsToTicks[10]];
                    CONTINUE;
                    }];

          IF debug THEN {
               Put.Text[ILT.toolData.fileSW, "MakePermanent..."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          file.MakePermanent;

          IF debug THEN {
               Put.Text[ILT.toolData.fileSW, "MakeBootable..."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          MakeBootable[
               file, hardMicrocode, OthelloDefs.leaderPages !
               File.Unknown =>
                    BEGIN
                    Put.Text[
                         ILT.toolData.msgSW,
                         "+++File.Unknown: trouble making bootable"L];
                    Process.Pause[Process.SecondsToTicks[10]];
                    CONTINUE;
                    END];
          Put.Line[ILT.toolData.fileSW, " installed."L];

          IF debug THEN {
               Put.Text[ILT.toolData.fileSW, "SetPhysicalVolumeBootFile..."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          SetPhysicalVolumeBootFile[
               file, hardMicrocode, OthelloDefs.leaderPages !
               File.Unknown => {
                    Put.Text[
                         ILT.toolData.msgSW,
                         "+++File.Unknown error in SetPhysicalVolumeBootFile"L];
                    Process.Pause[Process.SecondsToTicks[10]];
                    CONTINUE;
                    }];

          CloseVolume[];
>>	  
          END;  --InstallFileOnVolume;


     PostComment: FileTransfer.MessageProc =
          BEGIN
          IF ~ILT.toolData.busy THEN RETURN;
          IF level > terse THEN Post[ILT.toolData.msgSW, s1, s2, s3, s4];
          Post[ILT.toolData.fileSW, s1, s2, s3, s4];
          IF debug THEN Process.Pause[Process.SecondsToTicks[5]];
          END;


     Post: PROCEDURE [w: Window.Handle, s1, s2, s3, s4: LONG STRING] =
          BEGIN
          IF s1 # NIL THEN Put.LongString[w, s1];
          IF s2 # NIL THEN Put.LongString[w, s2];
          IF s3 # NIL THEN Put.LongString[w, s3];
          IF s4 # NIL THEN Put.LongString[w, s4];
          END;


     Retrieve: PROCEDURE [file: File.File, name: LONG STRING]
          RETURNS [gotIt: BOOLEAN ← TRUE] =

          BEGIN OPEN FileTransfer;

          ResumeSetup: PORT [BOOLEAN] RETURNS [file: File.File, name: LONG STRING];

          z: UNCOUNTED ZONE = Heap.systemZone;
          --access: Space.Access ← readWrite;
          --spaceBase: File.PageNumber ← NULL;
          --bufferPages: Space.PageCount = 64;
          bufferPages: File.PageCount = 100;
          bufferBytes: CARDINAL = CARDINAL[bufferPages * Environment.bytesPerPage];
          fileSize: File.PageCount ← ILT.toolData.vMemSize;
          i: CARDINAL ← 0;
          --spaceWindow: Space.Window;
          --swapUnitSize: Space.SwapUnitSize = 10;
          sysoutSize: File.PageCount;
          temp: LONG STRING;

          -- CONNECT ResumeSetup.out TO GetFile
          LOOPHOLE[ResumeSetup, PortRep].out ← @GetFile;
          -- CONNECT GetFile.out TO ResumeSetup
          LOOPHOLE[GetFile, PortRep].out ← @ResumeSetup;

          temp ← String.MakeString[z, 100];

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "Enter Retrieve"L];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "AllocVFN..."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          vfn ← AllocVFN[name];

          --patch vfn.host chop out leading "<" for DEI servers
          i ← 0;

          IF vfn.directory[i] = '< THEN
               BEGIN
               i ← 1;
               UNTIL i = vfn.directory.length DO
                    String.AppendCharAndGrow[@temp, vfn.directory[i], z];
                    i ← i + 1;
                    ENDLOOP;
               String.Replace[@vfn.directory, temp, z];
               temp.length ← 0;
               END;
          --ELSE Put.Line[ILT.toolData.fileSW, "missing left angle bracket"L];

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "ReadStream...."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          readStream ← conn.ReadStream[
               files: vfn ! Error => {gotIt ← FALSE; CONTINUE}];

          IF debug THEN {
               IF readStream = NIL THEN
                    Put.Line[ILT.toolData.fileSW, "readStream NIL"L];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          IF ~gotIt THEN {Cleanup[]; GOTO noGood};  -- FileTransfer has ML bug!

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "ResumeSetup...."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          file ← ResumeSetup[gotIt].file;

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "sysoutSize...."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          sysoutSize ←
               (FileTransfer.GetStreamInfo[readStream].size +
                     Environment.bytesPerPage - 1) / Environment.bytesPerPage;
          Put.Text[ILT.toolData.fileSW, "Sysout size = "];
          Put.LongDecimal[ILT.toolData.fileSW, sysoutSize];
          Put.Text[ILT.toolData.fileSW, " pages; "];
          Put.LongDecimal[ILT.toolData.fileSW, sysoutSize * 512];
          Put.Line[ILT.toolData.fileSW, " bytes."];

          -- set up initial default size
          <<
          IF LOOPHOLE[ILT.GetFileSize, CARDINAL] = 0 THEN
               ILT.toolData.vMemSize ← defaultVMemSize;
>>
          IF (ILT.toolData.vMemSize < sysoutSize) AND (ILT.toolData.vMemSize > 0)
               THEN
               BEGIN
               Put.Line[ILT.toolData.msgSW,
                    "+++Virtual memory smaller than Sysout size, please respecify."L];
               --size ← ILT.GetFileSize[];
               --ILT.DisplayFileSize[size];
               --CloseVolume[];
               RETURN[FALSE];
               END;
	       
	  ExpandVMemSize[];  

<<
          fileSize ← ILT.toolData.vMemSize;
          File.SetSize[
               file, fileSize !
               Volume.InsufficientSpace => {
	            IF debug THEN {
                    Put.Text[ILT.toolData.fileSW, "Can not set VMem at "L];
                    Put.LongDecimal[ILT.toolData.fileSW, fileSize];
                    Put.Line[ILT.toolData.fileSW, " pages; retrying..."L];};
                    fileSize ← fileSize - 100;
                    RETRY;
                    }];
		    
		    
          [volSize, freePages] ← Volume.GetAttributes[volumeID];
	  fileSize ← fileSize + freePages;
          File.SetSize[
               file, fileSize !
               Volume.InsufficientSpace => {
	            fileSize ← fileSize - 10;
                    RETRY;
                    }];
	  
		    
          [volSize, freePages] ← Volume.GetAttributes[volumeID];

          ILT.toolData.vMemSize ← fileSize;
	  ILT.toolData.currentVolFreeSize ← freePages;
	  -- re-display vMem and free size
	  FormSW.DisplayItem[ILT.toolData.paramSW, 2];
	  FormSW.DisplayItem[ILT.toolData.paramSW, 6];
>>	  
	  
          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "Create...."L];
               --Process.Pause[Process.SecondsToTicks[5]];
               };

          buffer ← Space.Map[
	  	window: [file: File.nullFile, base: NULL, count: bufferPages], 
      		class: data, swapUnits: [uniform[4]]].pointer;

	  SetLeaderPage[file, readStream, vfn];

          FOR windowPage: Space.PageOffset ← OthelloDefs.leaderPages, windowPage + bufferPages WHILE
               windowPage < Inline.LowHalf[sysoutSize] DO
               bytesTransferred: LONG INTEGER;
               cc: Stream.CompletionCode;
               eos: BOOLEAN ← FALSE;  --end of stream indicator
               sst: Stream.SubSequenceType;  --used in debug mode
               [bytesTransferred, cc] ← readStream.GetBlock[
                    [buffer, 0, bufferBytes] !
               Error => {
                         Put.Line[ILT.toolData.fileSW, "GetBlock.Error"L];
                         Process.Pause[Process.SecondsToTicks[20]];
                         gotIt ← FALSE;
                         CONTINUE;
                         }; ];
			 
               SELECT cc FROM
                    normal => {
                         IF debug THEN Put.Text[ILT.toolData.fileSW, " normal "L];
                         };
                    endRecord => {
                         Put.Line[ILT.toolData.fileSW, "endRecord detected"L];
                         };
                    sstChange => Put.Line[ILT.toolData.fileSW, "sstChange detected"L];
                    endOfStream => {
                         IF debug THEN {
                              Put.Line[ILT.toolData.fileSW, "end of stream detected"L];
                              };
                         eos ← TRUE;
                         };
                    attention => {
                         Put.Line[ILT.toolData.fileSW, "attention detected"L];
                         Process.Pause[Process.SecondsToTicks[30]];
                         };
                    ENDCASE => {
                         IF debug THEN Put.Line[ILT.toolData.fileSW, "ENDCASE"L];
                         Process.Pause[Process.SecondsToTicks[30]];
                         };

               --Put.Decimal[ILT.toolData.fileSW, sst];
               --Put.CR[ILT.toolData.fileSW];
               [] ← Space.CopyOut[buffer, [file, windowPage, bufferPages]];
               byteCount ← byteCount + bytesTransferred;
               Put.Text[ILT.toolData.msgSW, "Bytes transferred: "];
               Put.LongDecimal[ILT.toolData.msgSW, byteCount];
               Put.CR[ILT.toolData.msgSW];
               ILT.InvertIndicator[];
               IF eos THEN {
                    Put.LongDecimal[ILT.toolData.fileSW, byteCount];
                    Put.Line[ILT.toolData.fileSW, " bytes retrieved. "];
                    RETURN[TRUE];
                    };
               ENDLOOP;

          Cleanup[];
          RETURN[TRUE];
          EXITS noGood => RETURN[FALSE];
          END;  --Retrieve



     SetLeaderPage: PROC [
          file: File.File, stream: Stream.Handle, vfn: FileName.VFN] =
          BEGIN

          lp: LONG POINTER TO OthelloDefs.LeaderPage = Space.Map[
               [file, 0, OthelloDefs.leaderPages]].pointer;
          note: LONG STRING ← Heap.systemZone.NEW[StringBody [60]];
          -- STARTKLUDGE: work around the FileTransfer not giving the host name
          <<String.AppendStringAndGrow[
      @note, FileTransfer.GetStreamName[stream], Heap.systemZone];>>
          vfn.NormalizeVFN;
          IF NOT String.Empty[vfn.host] THEN {
               String.AppendStringAndGrow[@note, "["L, Heap.systemZone];
               String.AppendStringAndGrow[@note, vfn.host, Heap.systemZone];
               String.AppendStringAndGrow[@note, "]"L, Heap.systemZone]};

          IF NOT String.Empty[vfn.directory] THEN {
               String.AppendStringAndGrow[@note, vfn.directory, Heap.systemZone];
               String.AppendStringAndGrow[@note, ">"L, Heap.systemZone]};

          IF NOT String.Empty[vfn.name] THEN
               String.AppendStringAndGrow[@note, vfn.name, Heap.systemZone];

          IF NOT String.Empty[vfn.version] THEN {
               String.AppendStringAndGrow[@note, "!"L, Heap.systemZone];
               String.AppendStringAndGrow[@note, vfn.version, Heap.systemZone]};
          -- ENDKLUDGE
          String.AppendStringAndGrow[@note, " ("L, Heap.systemZone];
          -- STARTKLUDGE: Time.Append screws up on StringBoundsFault
          {
          oldLength: CARDINAL = note.length;
          Time.Append[
               s: note, zone: TRUE,
               unpacked: Time.Unpack[FileTransfer.GetStreamInfo[stream].create] !
               String.StringBoundsFault => {
                    ns ← String.CopyToNewString[
                         s: note, z: Heap.systemZone,
                         longer: s.maxlength - s.length + 20];
                    Heap.systemZone.FREE[@note];
                    note ← ns;
                    note.length ← oldLength;
                    RETRY}];
          };  -- ENDKLUDGE
          String.AppendCharAndGrow[@note, '), Heap.systemZone];
          lp.version ← OthelloDefs.lpVersion;
          lp.length ← MIN[note.length, OthelloDefs.lpNoteLength];
	  
	  IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "vfn name "L];
               Put.LongString[ILT.toolData.fileSW, note];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          FOR i: CARDINAL IN [0..lp.length) DO lp.note[i] ← note[i]; ENDLOOP;
          [] ← Space.Unmap[lp];
          Heap.systemZone.FREE[@note]
          END;

	   
      SetupBootFile:  PUBLIC PROCEDURE [volumeID: Volume.ID] =
          BEGIN OPEN OthelloOps;

          IF debug THEN {
               Put.Text[ILT.toolData.fileSW, "SetupBootFile..."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
	       
	  [file, firstPage] ← GetVolumeBootFile[volumeID, hardMicrocode];

          SetVolumeBootFile[file, hardMicrocode, OthelloDefs.leaderPages];
          File.MakePermanent[file];
          MakeBootable[
               file, hardMicrocode, firstPage !
               TemporaryBooting.InvalidParameters =>
                    BEGIN
                    Put.Text[
                         ILT.toolData.msgSW,
                         "+++Warning: trouble making bootable"L];
                    CONTINUE;
                    END];

          IF debug THEN {
               Put.Text[ILT.toolData.fileSW, "SetPhysicalVolumeBootFile..."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          SetPhysicalVolumeBootFile[file, hardMicrocode, OthelloDefs.leaderPages];
          CloseVolume[];
          END;  --SetupBootFile
   

     SetVolumeProc: PUBLIC PROCEDURE [vName: LONG STRING] RETURNS [BOOLEAN] =
          BEGIN OPEN OthelloOps;
          created: BOOLEAN ← FALSE;

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "Enter SetVolume Proc "L];
               Put.LongString[ILT.toolData.fileSW, vName];
               Put.Line[ILT.toolData.fileSW, "ILT.GetVolumeID "L];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          [volumeID, volumeOpen] ← ILT.GetVolumeID[vName];
          IF volumeID = Volume.nullID THEN RETURN[FALSE];

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "GetVolumeBootFile....."L];
               Process.Pause[Process.SecondsToTicks[10]];
               };
	  [file, firstPage] ← GetVolumeBootFile[volumeID, hardMicrocode];

<<
          IF file # File.nullFile THEN
               BEGIN
               ENABLE
                    File.Unknown => {
                         file ← File.nullFile;
                         Put.Line[ILT.toolData.fileSW, " File.Unknown...."L];
                         Process.Pause[Process.SecondsToTicks[5]];
                         CONTINUE};
               IF debug THEN {
                    Put.Line[ILT.toolData.fileSW, " not nullFile...."L];
                    Process.Pause[Process.SecondsToTicks[5]];
                    };
            END;
>>


          IF (created ← file = File.nullFile) THEN
               BEGIN
               --Put.Line[ILT.toolData.msgSW, "+++No Sysout file installed."L];
               IF debug THEN Process.Pause[Process.SecondsToTicks[20]];
               RETURN[FALSE];
               --file ← File.Create[volumeID, 1, FileTypes.tUntypedFile];
               END
          ELSE
               BEGIN
               IF debug THEN {
                    Put.Line[ILT.toolData.fileSW, "MakeUnbootable.."L];
                    Process.Pause[Process.SecondsToTicks[10]];
                    };
               MakeUnbootable[
                    file, hardMicrocode, OthelloDefs.leaderPages !
                    File.Unknown =>
                         BEGIN
                         Put.Text[
                              ILT.toolData.msgSW,
                              "Warning: trouble making unbootable"L];
                         Process.Pause[Process.SecondsToTicks[20]];
                         CONTINUE;
                         END];
               END;

          IF debug THEN {
               Put.Text[ILT.toolData.fileSW, "SetVolumeBootFile..."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          SetVolumeBootFile[file, hardMicrocode, OthelloDefs.leaderPages];
          File.MakePermanent[file];
          MakeBootable[
               file, hardMicrocode, firstPage !
               TemporaryBooting.InvalidParameters =>
                    BEGIN
                    Put.Text[
                         ILT.toolData.msgSW,
                         "+++Warning: trouble making bootable"L];
                    CONTINUE;
                    END];

          IF debug THEN {
               Put.Text[ILT.toolData.fileSW, "SetPhysicalVolumeBootFile..."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          SetPhysicalVolumeBootFile[file, hardMicrocode, OthelloDefs.leaderPages];
          CloseVolume[];
          RETURN[TRUE];
          END;  --SetVolumeProc


     -- This procedure validates the syntax for the file name used by NS file server .
     -- Allowable string is an
     -- alpha-numeric string beginning with a capital or small letter ['A .. 'Z]
     -- followed by any number (up to maxStringSize) of letters or numbers.

     ValidateString: PROC [sName: LONG STRING] RETURNS [BOOLEAN] =
          BEGIN
          currentString: STRING = [maxStringSize];
          currentChar: CARDINAL ← 0;
          c: CHARACTER;
          maxStringSize: CARDINAL = NSName.maxFullNameLength;  -- bytes

          CheckChar: PROC [] RETURNS [BOOLEAN] =
               BEGIN
               IF currentString.length >= maxStringSize THEN
                    BEGIN
                    Put.Line[
                         ILT.toolData.msgSW,
                         "+++Scan Error: string length too long"L];
                    Put.LongString[ILT.toolData.msgSW, sName];
                    Put.CR[ILT.toolData.msgSW];
                    RETURN[FALSE];
                    END;
               currentString.text[currentString.length] ← c;
               currentString.length ← currentString.length + 1;
               currentChar ← currentChar + 1;
               RETURN[TRUE];
               END;  --CheckChar  

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "ValidateString"L];
               Put.Text[ILT.toolData.fileSW, sName];
               Put.CR[ILT.toolData.fileSW];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          WHILE (currentChar < sName.length) DO
               c ← sName.text[currentChar];

               --Put.Char[ILT.toolData.fileSW, c];
               --Process.Pause[Process.SecondsToTicks[5]];

               SELECT ILT.toolData.fileServer FROM
                    FS =>
                         BEGIN
                         IF
                              (c = '- OR c = '* OR c = '@ OR c = ': OR c = Ascii.SP
                                   OR c = '[ OR c = '] OR c = '< OR c = '>
                                   OR c IN ['a..'z] OR c IN ['A..'Z]
                                   OR c IN ['0..'9]) THEN RETURN[CheckChar[]]
                         ELSE
                              BEGIN
                              Put.Text[ILT.toolData.msgSW, "+++Scan Error on: "L];
                              Put.LongString[ILT.toolData.msgSW, sName];
                              Put.Text[
                                   ILT.toolData.fileSW,
                                   " Bad character detected: "];
                              Put.Char[ILT.toolData.fileSW, c];
                              RETURN[FALSE];
                              END;
                         END;
                    IFS =>
                         BEGIN
                         IF
                              (c = '- OR c = '* OR c = '@ OR c = Ascii.SP OR c = '[
                                   OR c = '] OR c = '< OR c = '> OR c IN ['a..'z]
                                   OR c IN ['A..'Z] OR c IN ['0..'9]) THEN
                              RETURN[CheckChar[]]
                         ELSE
                              BEGIN
                              Put.Line[ILT.toolData.fileSW, "Scan Error"L];
                              Put.LongString[ILT.toolData.fileSW, sName];
                              RETURN[FALSE];
                              END;
                         END;
                    ENDCASE;
               ENDLOOP;
          RETURN[TRUE];
          END;  --ValidateString
     END.