<> <> <> <> <> <> <> <<>> 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, Handle, NextVolume, nullFP, Open, PageCount, PageNumber, Read, Volume ], FileBackdoor USING [ GetRoot], 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, FileBackdoor, FileInternal, GermSwap, PhysicalVolume, Process, ProcessorFace, VM EXPORTS DiskFace--RelID--, File = { <> Volume: TYPE = REF VolumeObject; VolumeObject: PUBLIC TYPE = FileInternal.VolumeObject; FindVolumeFromLocation: PROC [loc: BootFile.Location] RETURNS [File.Volume] = { <> 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 { 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]; }; ENDLOOP; ENDLOOP; RETURN[NIL] }; systemVolume: Volume _ NIL; --File.--FindSystemVolume: PUBLIC ENTRY PROC RETURNS [found: BOOL] = { ENABLE UNWIND => NULL; IF systemVolume = NIL THEN { systemVolume _ FindVolumeFromLocation[GermSwap.bootedFrom.location]; <> IF systemVolume # NIL AND systemVolume.rootStatus = nonCedarVolume THEN systemVolume _ File.FindVolumeFromName["Cedar"]; }; FindDebugger[]; RETURN[systemVolume # NIL] }; --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 { 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 { 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 }; ENDLOOP; }; RelocateDebugger: ENTRY PROC = { <> debuggerFound _ FALSE; FindDebugger[ ! UNWIND => NULL]; }; vmFound: BOOL _ FALSE; CheckVMFP: PROC [volume: Volume] RETURNS [BOOL] = { fp: File.FP = FileBackdoor.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] }; bootFileRead: BOOL _ FALSE; --File.--FindVM: PUBLIC ENTRY PROC RETURNS [found: BOOL _ FALSE] = TRUSTED { ENABLE UNWIND => NULL; IF vmFound THEN RETURN[TRUE]; IF systemVolume # NIL THEN { 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; }; <> IF NOT bootFileRead THEN { bootFileRead _ TRUE; CopyBootFile[]--releases monitor-- }; TRUSTED {IF GermSwap.switches[four] THEN DebuggerSwap.CallDebugger["Key stop 4"L]}; }; CheckpointThings: ENTRY PROC = { ENABLE UNWIND => NULL; checkPointExists: BOOL _ systemVolume # NIL; IF checkPointExists THEN checkPointExists _ (FileBackdoor.GetRoot[systemVolume, checkpoint ! File.Error => { checkPointExists _ FALSE; CONTINUE }].fp # File.nullFP); IF checkPointExists THEN { 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; } ELSE GermSwap.switches[r] _ FALSE; IF GermSwap.switches[f] THEN GermSwap.switches[r] _ FALSE; Booting.RegisterProcs[c: MyCheckpoint, r: MyRollback]; }; MyCheckpoint: Booting.CheckpointProc = { <> 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; }; MyRollback: Booting.RollbackProc = { <> FileInternal.UnlockFiles[]; FOR volume: File.Volume _ File.NextVolume[NIL,FALSE], File.NextVolume[volume, FALSE] UNTIL volume = NIL DO FileInternal.ReadRootPage[volume]; ENDLOOP; RelocateDebugger[]; }; <> --DiskFace.--RelID: PUBLIC TYPE = VolumeFormat.RelID; CopyBootFile: INTERNAL PROC = TRUSTED { 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 }; }; TRUSTED { <> IF NOT GermSwap.switches[n] THEN [] _ FindSystemVolume[]; CheckpointThings[]; IF GermSwap.switches[three] THEN DebuggerSwap.CallDebugger["Key stop 3"L]; ProcessorFace.SetMP[MPCodes.fileInitialized]; }; }. <> <> <> <<>>