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 _ 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. ÖCedar Nucleus (Files): initialisation FileInit.mesa Andrew Birrell November 15, 1983 3:03 pm Last Edited by: Levin, September 20, 1983 4:03 pm 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 NucleusTest 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šœ ™ Jšœ)™)Jšœ1™1J™šÏk ˜ Jšœ œ ˜Jšœœ0˜=Jšœœc˜vJšœ œ#˜5JšœœE˜OJšœ œ ˜JšœœœS˜|Jšœ œŒ˜žJšœ œ˜'Jšœœ˜!Jšœœ"˜6Jšœœ ˜Jšœœ ˜Jšœœ0˜8Jšœ œ˜,—J˜šœ œ˜Jšœs˜|Jšœ Ïc œ˜!—J˜Jš˜˜J˜—JšœV™V˜Jšœœœ˜ J˜Jšœœœ˜6J˜šÏnœœœ˜KJš˜JšœM™MJšœ*œ˜LJšœ ˜Jšœœ5œ˜CJšœœœœ˜Jšœ˜Jšœ.™.Jš œœœœœ˜Ršœœœœ8˜JJšœ˜šœ˜Jšœ œ˜JšœH˜HJšœœ˜8šœ˜ JšœW˜WJšœœ*˜JJšœœ˜Jšœ˜——Jšœ˜—Jšœ˜Jšœœ˜ Jšœ˜—J˜Jšœœ˜J˜š ž Ÿœœœœœ œ˜CJš˜Jšœœœ˜Jšœ˜šœ˜ JšœD˜DJšœP™PJšœœœ)˜BJšœ7˜;Jšœ˜—J˜Jšœœ˜Jšœ˜—J˜š ž Ÿ œœœœœ˜BJšœœœœœœœœ˜W—J˜š ž Ÿœœœœ˜=Jšœ)œœ˜;—J˜Jšœœœ˜J˜šŸ œœœ˜%Jš˜Jš œœœœœ˜3Jšœœœ˜Fšœœœ˜:Jšœ;˜>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˜—…—#ä49