<> <> <> <> DIRECTORY BootFile USING[ Location ], BootStartList USING [EntryPointer, Enumerate, IndexToEntryPointer, IndexToSpaceEntryPointer, Proc, SpaceEntryPointer], DebuggerSwap USING[ CallDebugger, NoteDiskDebugger ], Disk USING[ Channel, DriveAttributes, GetPageNumber, PageNumber ], DiskFace USING[ Type ], File USING[ Error, FP, GetRoot, Handle, NextVolume, Open, PageCount, PageNumber, Read, Volume ], FileInternal USING[ RegisterVMFile, VolumeObject ], GermSwap USING[ bootedFrom, switches ], MPCodes USING[ fileInitialized ], PhysicalVolume USING[ SubVolumeDetails ], Process USING [Detach], ProcessorFace USING[ SetMP ], VM USING [Interval, MakeReadOnly, PageNumberToAddress], VolumeFormat USING[ nullDiskFileID, RelID ]; FileInit: CEDAR MONITOR IMPORTS BootStartList, DebuggerSwap, Disk, File, FileInternal, GermSwap, 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 channel: Disk.Channel _ NIL; 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; FindSystemVolume: PROC RETURNS[File.Volume] = BEGIN IF GermSwap.switches[n] THEN RETURN[NIL]; RETURN[ FindVolumeFromLocation[GermSwap.bootedFrom.location] ] END; --File.--SystemVolume: PUBLIC PROC RETURNS[volume: Volume] = { RETURN[systemVolume] }; FindDebugger: PROC = TRUSTED BEGIN IF GermSwap.switches[n] OR systemVolume = NIL 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]]] ]; EXIT END; ENDLOOP; END; 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[TRUE]; EXITS noGo => RETURN[FALSE] END; FindVM: PROC = TRUSTED BEGIN IF GermSwap.switches[n] OR systemVolume = NIL THEN RETURN; IF CheckVMFP[systemVolume] THEN RETURN; 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 RETURN; ENDLOOP; END; <> --DiskFace.--RelID: PUBLIC TYPE = VolumeFormat.RelID; CopyBootFile: 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: ENTRY PROC = CHECKED { WHILE processesInUse = maxProcesses DO WAIT processAvailable ENDLOOP; processesInUse _ processesInUse + 1; }; NotifyProcessAvailable: ENTRY PROC = CHECKED { processesInUse _ processesInUse - 1; NOTIFY processAvailable; }; WaitUntilDone: ENTRY PROC = CHECKED { UNTIL processesInUse = 0 DO WAIT processAvailable ENDLOOP; }; SwapIn: BootStartList.Proc = UNCHECKED { OPEN BootStartList; entry: EntryPointer = IndexToEntryPointer[index]; WITH e: entry SELECT FROM space => IF ~e.bootLoaded THEN { WaitForAProcess[]; Process.Detach[FORK ForkedRead[ from: [e.backingPage], nPages: e.pages, to: VM.PageNumberToAddress[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; }; IF GermSwap.switches[n] THEN RETURN; <<"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[systemVolume, bootFileFP ! File.Error => GOTO noGo]; BootStartList.Enumerate[SwapIn]; BootStartList.Enumerate[MakeReadOnly]; WaitUntilDone[]; EXITS noGo => NULL END; <
> systemVolume: Volume _ FindSystemVolume[]; FindDebugger[]; FindVM[]; CopyBootFile[]; TRUSTED {IF GermSwap.switches[three] THEN DebuggerSwap.CallDebugger["Key stop 3"L]}; TRUSTED {ProcessorFace.SetMP[MPCodes.fileInitialized]}; END.