FileInit.mesa - Files initialisation
Copyright © 1984, 1985 by Xerox Corporation. All rights reserved.
Andrew Birrell November 15, 1983 3:03 pm
Levin, September 20, 1983 4:03 pm
Russ Atkinson, February 20, 1985 3:06:14 pm PST
Bob Hagmann January 31, 1985 11:05:40 am PST
Russ Atkinson (RRA) May 15, 1985 8:30:32 pm PDT
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] = {
First, check there is a suitable device (otherwise, don't touch the volumes).
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;
Then, search for an appropriate logical volume
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];
Don't use a non-cedar system volume. Temp kludge: in that case, try Cedar
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 = {
Re-consider debugger location after a rollback
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;
};
We get here regardless of whether we found a VM file. On first time only, read boot file
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;
Compiler won't do equality check for me!
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 = {
First, try (but not very hard) to ensure our VAM information is written out
FOR volume: File.Volume ← File.NextVolume[
NIL,
FALSE], File.NextVolume[volume,
FALSE]
UNTIL volume =
NIL DO
FileInternal.Commit[volume ! File.Error => CONTINUE];
ENDLOOP;
Then lock all the files (before the volumes, to avoid deadlocking
FileInternal.LockAndCloseFiles[];
Then lock all the volumes
FOR volume: File.Volume ← File.NextVolume[
NIL,
FALSE], File.NextVolume[volume,
FALSE]
UNTIL volume =
NIL
DO
FileInternal.LockVolume[volume];
ENDLOOP;
};
MyRollback: Booting.RollbackProc = {
Unlock the files first, to allow opening the volume VAM files
FileInternal.UnlockFiles[];
FOR volume: File.Volume ← File.NextVolume[
NIL,
FALSE], File.NextVolume[volume,
FALSE]
UNTIL volume =
NIL DO
FileInternal.ReadRootPage[volume];
ENDLOOP;
RelocateDebugger[];
};
}.