<> <> <> <> <<>> DIRECTORY BootFile USING[ Location ], Booting USING[ CheckpointProc, RegisterProcs, RollbackProc ], BootStartList USING [EntryPointer, Enumerate, IndexToEntryPointer, IndexToSpaceEntryPointer, Proc, SpaceEntryPointer], DebuggerSwap USING[ CallDebugger, NoteDiskDebugger ], Disk USING[ Channel, DriveAttributes, GetPageNumber, NextChannel, PageNumber ], DiskFace USING[ Type ], File USING[ Error, FindVolumeFromName, FP, GetRoot, Handle, NextVolume, nullFP, Open, PageCount, PageNumber, Read, Volume ], FileInternal USING[ Commit, GetLogicalLocation, GetPhysicalLocation, LockAndCloseFiles, LockVolume, ReadRootPage, RegisterVMFile, UnlockFiles, VolumeObject ], GermSwap USING[ bootedFrom, switches ], MPCodes USING[ fileInitialized ], PhysicalVolume USING[ GetPhysical, SubVolumeDetails ], Process USING [Detach], ProcessorFace USING[ SetMP ], VM USING [AddressForPageNumber, Interval, MakeReadOnly], VolumeFormat USING[ nullDiskFileID, RelID ]; FileInit: CEDAR MONITOR IMPORTS Booting, BootStartList, DebuggerSwap, Disk, File, FileInternal, GermSwap, PhysicalVolume, Process, ProcessorFace, VM EXPORTS DiskFace--RelID--, File = BEGIN <> Volume: TYPE = REF VolumeObject; VolumeObject: PUBLIC TYPE = FileInternal.VolumeObject; FindVolumeFromLocation: PROC[loc: BootFile.Location] RETURNS[File.Volume] = BEGIN <> FOR channel: Disk.Channel _ Disk.NextChannel[NIL], Disk.NextChannel[channel] UNTIL channel = NIL DO IF Disk.DriveAttributes[channel].type = loc.deviceType THEN EXIT REPEAT FINISHED => RETURN[NIL] ENDLOOP; <> FOR v: Volume _ File.NextVolume[NIL,FALSE], File.NextVolume[v,FALSE] UNTIL v = NIL DO FOR sv: LIST OF PhysicalVolume.SubVolumeDetails _ v.subVolumes, sv.rest UNTIL sv = NIL DO type: DiskFace.Type; ordinal: CARDINAL; [type: type, ordinal: ordinal] _ Disk.DriveAttributes[sv.first.channel]; IF type = loc.deviceType AND ordinal = loc.deviceOrdinal THEN BEGIN page: Disk.PageNumber = Disk.GetPageNumber[sv.first.channel, loc.diskFileID.firstLink]; IF page >= sv.first.address AND page < (sv.first.address + sv.first.size) THEN RETURN[v]; END; ENDLOOP; ENDLOOP; RETURN[NIL] END; systemVolume: Volume _ NIL; --File.--FindSystemVolume: PUBLIC ENTRY PROC RETURNS [found: BOOL]= BEGIN ENABLE UNWIND => NULL; IF systemVolume = NIL THEN BEGIN systemVolume _ FindVolumeFromLocation[GermSwap.bootedFrom.location]; <> IF systemVolume # NIL AND systemVolume.rootStatus = nonCedarVolume THEN systemVolume _ File.FindVolumeFromName["NucleusTest"]; END; FindDebugger[]; RETURN[systemVolume # NIL] END; --File.--SystemVolume: PUBLIC ENTRY PROC RETURNS[volume: Volume] = { RETURN[IF systemVolume = NIL OR systemVolume.destroyed THEN NIL ELSE systemVolume] }; --File.--SetSystemVolume: PUBLIC ENTRY PROC[volume: Volume] = { systemVolume _ volume; FindDebugger[ ! UNWIND => NULL] }; debuggerFound: BOOL _ FALSE; FindDebugger: INTERNAL PROC = TRUSTED BEGIN IF systemVolume = NIL OR debuggerFound THEN RETURN; FOR v: Volume _ File.NextVolume[NIL], File.NextVolume[v] UNTIL v = NIL DO IF (v.rootStatus = ok OR v.rootStatus = nonCedarVolume) AND v.root.bootingInfo[debuggee] # VolumeFormat.nullDiskFileID AND systemVolume # NIL AND ( SELECT systemVolume.root.type FROM pilot => v.root.type = pilotDebugger, pilotDebugger => v.root.type = pilotDebuggerDebugger, pilotDebuggerDebugger => FALSE, cedar => IF v.root.type = cedar THEN ( NOT systemVolume.root.coCedar AND v.root.coCedar) ELSE v.root.type = pilotDebugger -- change to FALSE after bootstrap to 5.0--, ENDCASE => FALSE) THEN BEGIN type: DiskFace.Type; ordinal: CARDINAL; [type: type, ordinal: ordinal] _ Disk.DriveAttributes[v.subVolumes.first.channel]; DebuggerSwap.NoteDiskDebugger[ debugger: [type, ordinal, disk[v.root.bootingInfo[debugger]]], debuggee: [type, ordinal, disk[v.root.bootingInfo[debuggee]]] ]; debuggerFound _ TRUE; EXIT END; ENDLOOP; END; RelocateDebugger: ENTRY PROC = <> { debuggerFound _ FALSE; FindDebugger[ ! UNWIND => NULL] }; vmFound: BOOL _ FALSE; CheckVMFP: PROC[volume: Volume] RETURNS[BOOL] = BEGIN fp: File.FP = File.GetRoot[volume, VM ! File.Error => GOTO noGo ].fp; file: File.Handle = File.Open[volume, fp ! File.Error => GOTO noGo ]; FileInternal.RegisterVMFile[file]; RETURN[vmFound _ TRUE]; EXITS noGo => RETURN[FALSE] END; bootFileRead: BOOL _ FALSE; --File.--FindVM: PUBLIC ENTRY PROC RETURNS[found: BOOL _ FALSE] = TRUSTED BEGIN ENABLE UNWIND => NULL; IF vmFound THEN RETURN[TRUE]; IF systemVolume # NIL THEN BEGIN IF CheckVMFP[systemVolume] THEN found _ TRUE ELSE FOR v: Volume _ File.NextVolume[NIL], File.NextVolume[v] UNTIL v = NIL DO weAreCoCedar: BOOL = systemVolume.rootStatus = ok AND systemVolume.root.coCedar; itsCoCedar: BOOL = v.rootStatus = ok AND v.root.coCedar; IF itsCoCedar = weAreCoCedar AND CheckVMFP[v] THEN { found _ TRUE; EXIT }; ENDLOOP; END; <> IF NOT bootFileRead THEN { bootFileRead _ TRUE; CopyBootFile[]--releases monitor-- }; TRUSTED {IF GermSwap.switches[four] THEN DebuggerSwap.CallDebugger["Key stop 4"L]}; END; CheckpointThings: ENTRY PROC = BEGIN ENABLE UNWIND => NULL; checkPointExists: BOOL _ systemVolume # NIL; IF checkPointExists THEN checkPointExists _ (File.GetRoot[systemVolume, checkpoint ! File.Error => { checkPointExists _ FALSE; CONTINUE }].fp # File.nullFP); IF checkPointExists THEN BEGIN bootedLoc: BootFile.Location = GermSwap.bootedFrom.location; <> Equal: PROC[diskLoc: --disk-- BootFile.Location] RETURNS[BOOL] = TRUSTED { RETURN[diskLoc.deviceType = bootedLoc.deviceType AND diskLoc.deviceOrdinal = bootedLoc.deviceOrdinal AND diskLoc.diskFileID = bootedLoc.diskFileID] }; IF Equal[FileInternal.GetLogicalLocation[systemVolume,bootFile]] OR Equal[FileInternal.GetPhysicalLocation[PhysicalVolume.GetPhysical[systemVolume],bootFile]] THEN GermSwap.switches[r] _ TRUE; END ELSE GermSwap.switches[r] _ FALSE; IF GermSwap.switches[f] THEN GermSwap.switches[r] _ FALSE; Booting.RegisterProcs[c: MyCheckpoint, r: MyRollback]; END; MyCheckpoint: Booting.CheckpointProc = BEGIN <> FOR volume: File.Volume _ File.NextVolume[NIL,FALSE], File.NextVolume[volume, FALSE] UNTIL volume = NIL DO FileInternal.Commit[volume ! File.Error => CONTINUE] ENDLOOP; <> FileInternal.LockAndCloseFiles[]; <> FOR volume: File.Volume _ File.NextVolume[NIL,FALSE], File.NextVolume[volume, FALSE] UNTIL volume = NIL DO FileInternal.LockVolume[volume] ENDLOOP; END; MyRollback: Booting.RollbackProc = BEGIN <> FileInternal.UnlockFiles[]; FOR volume: File.Volume _ File.NextVolume[NIL,FALSE], File.NextVolume[volume, FALSE] UNTIL volume = NIL DO FileInternal.ReadRootPage[volume] ENDLOOP; RelocateDebugger[]; END; <> --DiskFace.--RelID: PUBLIC TYPE = VolumeFormat.RelID; CopyBootFile: INTERNAL PROC = TRUSTED BEGIN maxProcesses: NAT = 2; processesInUse: NAT _ 0; processAvailable: CONDITION _ [timeout: 0]; bootFileVolume: File.Volume; bootFileFP: RelID; bootFileHandle: File.Handle; ForkedRead: UNSAFE PROC [from: File.PageNumber, nPages: File.PageCount, to: LONG POINTER] = UNCHECKED { File.Read[file: bootFileHandle, from: from, nPages: nPages, to: to]; NotifyProcessAvailable[]; }; WaitForAProcess: INTERNAL PROC = CHECKED { WHILE processesInUse = maxProcesses DO WAIT processAvailable ENDLOOP; processesInUse _ processesInUse + 1; }; NotifyProcessAvailable: ENTRY PROC = CHECKED { ENABLE UNWIND => NULL; processesInUse _ processesInUse - 1; NOTIFY processAvailable; }; WaitUntilDone: INTERNAL PROC = CHECKED { UNTIL processesInUse = 0 DO WAIT processAvailable ENDLOOP; }; somethingToDo: BOOL _ FALSE; CheckForSwappedOut: BootStartList.Proc--RETURNS [stop: BOOL_FALSE]-- = UNCHECKED { OPEN BootStartList; entry: EntryPointer = IndexToEntryPointer[index]; WITH e: entry SELECT FROM space => IF ~e.bootLoaded AND e.type.class ~= empty THEN { somethingToDo _ TRUE; stop _ TRUE; }; swapUnit => NULL; ENDCASE => ERROR; }; SwapIn: INTERNAL BootStartList.Proc = UNCHECKED { OPEN BootStartList; entry: EntryPointer = IndexToEntryPointer[index]; WITH e: entry SELECT FROM space => IF ~e.bootLoaded AND e.type.class ~= empty THEN { WaitForAProcess[]; Process.Detach[FORK ForkedRead[ from: [e.backingPage], nPages: e.pages, to: VM.AddressForPageNumber[e.vmPage] ]]; }; swapUnit => NULL; ENDCASE => ERROR; }; MakeReadOnly: BootStartList.Proc = UNCHECKED { OPEN BootStartList; entry: EntryPointer = IndexToEntryPointer[index]; WITH e: entry SELECT FROM swapUnit => { parent: SpaceEntryPointer = IndexToSpaceEntryPointer[e.parent]; IF ~parent.bootLoaded AND e.info.readOnly THEN VM.MakeReadOnly[VM.Interval[parent.vmPage+e.base, e.pages]]; }; space => NULL; ENDCASE => ERROR; }; BootStartList.Enumerate[CheckForSwappedOut]; IF somethingToDo THEN { <<"bootFileVolume" is logically independent of "SystemVolume[]">> bootFileVolume _ FindVolumeFromLocation[GermSwap.bootedFrom.location]; IF bootFileVolume = NIL THEN RETURN; bootFileFP _ GermSwap.bootedFrom.location.diskFileID.fID.relID; bootFileHandle _ File.Open[bootFileVolume, bootFileFP ! File.Error => GOTO noGo]; BootStartList.Enumerate[SwapIn]; WaitUntilDone[]; -- before making them read-only! BootStartList.Enumerate[MakeReadOnly]; EXITS noGo => NULL }; END; <
> IF NOT GermSwap.switches[n] THEN [] _ FindSystemVolume[]; CheckpointThings[]; TRUSTED {IF GermSwap.switches[three] THEN DebuggerSwap.CallDebugger["Key stop 3"L]}; TRUSTED {ProcessorFace.SetMP[MPCodes.fileInitialized]}; END.