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["Cedar"]; 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 _ 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. (FileInit.mesa Cedar Nucleus (Files): initialisation Copyright c 1984 by Xerox Corporation. All rights reserved. Andrew Birrell November 15, 1983 3:03 pm Levin, September 20, 1983 4:03 pm Russ Atkinson, June 13, 1984 5:13:19 pm PDT Operations on the system volume: finding it, finding debugger, finding VM backing file First, check there is a suitable device (otherwise, don't touch the volumes). Then, search for an appropriate logical volume Don't use a non-cedar system volume. Temp kludge: in that case, try Cedar Re-consider debugger location after a rollback We get here regardless of whether we found a VM file. On first time only, read boot file Compiler won't do equality check for me! First, try (but not very hard) to ensure our VAM information is written out Then lock all the files (before the volumes, to avoid deadlocking Then lock all the volumes Unlock the files first, to allow opening the volume VAM files Copying in the non-initial-loaded part of the boot file "bootFileVolume" is logically independent of "SystemVolume[]" Main body Ê ”˜šœ ™ Jšœ&™&Jšœ Ïmœ1™Jšžœž˜šžœžœž˜(Jšœ%˜%Jšœ5˜5Jšœžœ˜šœ žœ˜Jšžœžœžœ˜8JšžœŸ+œ˜M—Jšžœžœ˜—šžœž˜ J˜Jšœ žœ˜JšœR˜Ršœ˜Jšœ>˜>Jšœ=˜=Jšœ˜—Jšœžœ˜Jšž˜Jšžœ˜——Jšžœ˜Jšžœ˜—J˜š œžœžœ˜Jšœ.™.Jšœžœžœžœ˜;—J˜Jšœ žœžœ˜J˜š  œžœžœžœ˜/Jšž˜Jšœ žœžœžœ ˜EJšœ9žœ˜EJšœ"˜"Jšžœ žœ˜Jšžœ žœžœ˜Jšžœ˜—J˜Jšœžœžœ˜J˜šŸ  œžœžœžœžœžœžœž˜IJšž˜Jšžœžœžœ˜Jšžœ žœžœžœ˜Jšžœž˜šžœž˜ Jšžœ˜Jšžœ ž˜š žœžœžœžœž˜Kšžœžœ žœ˜SJšœ žœžœ˜8Jš žœžœžœ žœžœ˜J—Jšžœ˜—Jšžœ˜—JšœY™YJš žœžœžœžœŸœ˜UJšžœžœžœ+˜SJšžœ˜—J˜š œžœžœ˜Jšž˜Jšžœžœžœ˜Jšœžœžœ˜,šžœžœ<˜TJšœ#žœžœ˜H—Jšžœ˜šžœž˜ Jšœ<˜˜@Jšžœ[˜]Jšžœžœ˜!Jšž˜—Jšžœžœ˜"Jšžœžœžœ˜:Jšœ6˜6Jšžœ˜—J˜š  œ˜&Jšž˜JšœK™KJšžœ'žœžœžœ˜TJšžœ ž˜Jšžœ,žœžœ˜@JšœA™AJ˜!Jšœ™Jšžœ'žœžœžœ˜TJšžœ ž˜Jšžœ!žœ˜+Jšžœ˜—J˜š  œ˜"Jšž˜Jšœ=™=J˜Jšžœ'žœžœžœ˜TJšžœ ž˜Jšžœ#žœ˜-J˜Jšžœ˜—˜J˜—J˜—Jšœ7™7˜JšŸ œžœžœ˜5J˜š  œžœžœž˜%Jšž˜J˜Jšœžœ˜J˜Jšœžœ˜Jšœž œ˜+J˜Jšœ˜Jšœ˜Jšœ˜J˜š   œžœžœ5žœžœž œ˜gJšœD˜DJ˜J˜—š œžœžœžœ˜*Jšžœžœžœžœ˜EJ˜$J˜—š œžœžœžœ˜.Jšžœžœžœ˜J˜$Jšžœ˜J˜—š  œžœžœžœ˜(Jšžœžœžœžœ˜:J˜—Jšœžœžœ˜š ÏbœŸžœžœžœŸœž œ˜RJšžœ˜Jšœ1˜1šžœ žœž˜šœ˜šžœžœžœ˜1Jšœžœ žœ˜"J˜——Jšœ žœ˜Jšžœžœ˜—Jšœ˜—š¡œžœž œ˜1Jšžœ˜Jšœ1˜1šžœ žœž˜šœ˜šžœžœžœ˜1J˜šœžœ ˜Jšœ˜Jšœ˜Jšœžœ˜%Jšœ˜—J˜——Jšœ žœ˜Jšžœžœ˜—J˜—š¡ œž œ˜.Jšžœ˜Jšœ1˜1šžœ žœž˜šœ ˜ J˜?šžœžœž˜.Jšžœžœ*˜<—J˜—Jšœ žœ˜Jšžœžœ˜—J˜—J˜Jšœ,˜,šžœžœ˜Jšœ=™=JšœF˜FJšžœžœžœžœ˜$Jšœ?˜?JšœFžœ˜QJ˜ JšœŸ!˜1J˜&Jšžœ ž˜J˜—Jšžœ˜J˜J˜—J˜—Jšœ ™ ˜Jšžœžœžœ˜9J˜J˜J˜Jšžœžœžœ+˜TJ˜Jšžœ0˜7J˜—Jšžœ˜J˜J˜—…—#Þ4š