DIRECTORY BootFile USING[ Location, MemorySizeToFileSize ], Booting USING[ Bootee, BootFileNumber, CheckpointProc, MicrocodeType, RollbackProc, Switches ], DeviceCleanup USING[ Perform ], File USING[ Create, Error, Info, FP, GetRoot, Handle, Open, nullFP, nullVolumeID, PageCount, SetRoot, SetSize, SystemVolume, Volume, VolumeFile, VolumeID ], FileInternal USING[ GetFileLocation, GetLogicalLocation, GetPhysicalLocation ], GermSwap USING[ bootedFrom, InLoad, OutLoad, switches ], MicrocodeBooting USING[ GetBootFileNumber, BootSpecificMicrocode ], MPCodes USING[ emptyMP ], PhysicalVolume USING[ GetPhysical, NextPhysical, Physical, PhysicalInfo ], ProcessorFace USING[ BootButton, SetMP ], PrincOps USING[ PsbHandle ], PrincOpsUtils USING[ DisableInterrupts, EnableInterrupts, ReadPSB, ReadPTC, ReadWDC, WritePSB, WritePTC, WriteWDC ], Rope USING[ Length, ROPE ], VM USING[ VMPartition ], VMBacking USING[ RecoverRealMemory ], VMSideDoor USING[ rmPages ], VMStatistics USING[ VirtualAllocation ], VolumeFormat USING[ nullDiskFileID ]; BootingImpl: CEDAR MONITOR IMPORTS BootFile, DeviceCleanup, File, FileInternal, GermSwap, MicrocodeBooting, PhysicalVolume, ProcessorFace, PrincOpsUtils, Rope, VMBacking, VMSideDoor, VMStatistics EXPORTS Booting = BEGIN switches: PUBLIC Booting.Switches _ GermSwap.switches; --Booting.--GetBootFileNumber: PUBLIC PROC[type: Booting.MicrocodeType] RETURNS[Booting.BootFileNumber] = TRUSTED { RETURN[ MicrocodeBooting.GetBootFileNumber[type] ] }; --Booting.--Boot: PUBLIC PROC[ boot: Booting.Bootee, switches: Booting.Switches, outload: Booting.Bootee _ [noOp[]] ] RETURNS[rejection: Rope.ROPE _ NIL] = TRUSTED BEGIN sys: File.Volume = File.SystemVolume[]; GetLocation: PROC[from: Booting.Bootee] RETURNS[loc: BootFile.Location] = TRUSTED BEGIN WITH b: from SELECT FROM noOp => NULL; file => loc _ FileInternal.GetFileLocation[b.file, b.firstPage]; logical => BEGIN v: File.Volume = IF b.volume = NIL THEN sys ELSE b.volume; IF v = NIL THEN ERROR File.Error[unknownFile]; loc _ FileInternal.GetLogicalLocation[v, b.root]; IF loc.diskFileID = VolumeFormat.nullDiskFileID THEN ERROR File.Error[unknownFile]; END; physical => BEGIN id: File.VolumeID = IF b.volume = File.nullVolumeID AND sys # NIL THEN PhysicalVolume.PhysicalInfo[PhysicalVolume.GetPhysical[sys]].id ELSE b.volume; FOR p: PhysicalVolume.Physical _ PhysicalVolume.NextPhysical[NIL], PhysicalVolume.NextPhysical[p] UNTIL p = NIL DO IF PhysicalVolume.PhysicalInfo[p].id = id THEN BEGIN loc _ FileInternal.GetPhysicalLocation[p, b.root]; IF loc.diskFileID = VolumeFormat.nullDiskFileID THEN ERROR File.Error[unknownFile]; EXIT END; REPEAT FINISHED => ERROR File.Error[unknownFile] ENDLOOP; END; microcode => NULL; bootButton => NULL; self => loc _ GermSwap.bootedFrom.location; ENDCASE; END; outloadWanted: BOOL _ outload.type # noOp; outloadLoc, inloadLoc: BootFile.Location; IF NOT outloadWanted AND sys # NIL AND File.GetRoot[sys, debugger].fp # File.nullFP THEN { outloadWanted _ TRUE; outload _ [logical[sys, debugger]] }; IF outloadWanted THEN outloadLoc _ GetLocation[outload]; inloadLoc _ GetLocation[boot]; rejection _ BootFromLocation[ outloadLoc: IF outloadWanted THEN @outloadLoc ELSE NIL, boot: WITH b: boot SELECT FROM noOp => [noOp[]], bootButton => [bootButton[]], microcode => [microcode[b.bfn]], ENDCASE => [inload[@inloadLoc]], switches: switches]; END; inloadedOnce: PUBLIC BOOL _ FALSE; BootFromLocation: ENTRY PROC[ outloadLoc: POINTER TO BootFile.Location _ NIL, boot: RECORD[SELECT t: * FROM noOp => NULL, inload => [inloadLoc: POINTER TO BootFile.Location], bootButton => NULL, microcode => [bfn: Booting.BootFileNumber], ENDCASE], switches: Booting.Switches ] RETURNS[rejection: Rope.ROPE _ NIL] = TRUSTED BEGIN ENABLE UNWIND => NULL; self: BootFile.Location _ GermSwap.bootedFrom.location; inloaded: BOOL _ FALSE; IF outloadLoc # NIL THEN { rejection _ CallCheckpointProcs[]; IF rejection # NIL THEN RETURN }; inloadedOnce _ FALSE; PrincOpsUtils.DisableInterrupts[]; -- make it hold still first DeviceCleanup.Perform[turnOff]; IF outloadLoc # NIL THEN BEGIN psb: PrincOps.PsbHandle; ptc: CARDINAL; wdc: CARDINAL; -- should be in outload file? psb _ PrincOpsUtils.ReadPSB[]; ptc _ PrincOpsUtils.ReadPTC[]; wdc _ PrincOpsUtils.ReadWDC[]; inloaded _ GermSwap.OutLoad[outloadLoc, restore] # outLoaded; PrincOpsUtils.WriteWDC[wdc]; PrincOpsUtils.WritePTC[ptc]; PrincOpsUtils.WritePSB[psb]; END; IF NOT inloaded THEN BEGIN WITH b: boot SELECT FROM noOp => NULL; bootButton => ProcessorFace.BootButton[--switches--]; microcode => MicrocodeBooting.BootSpecificMicrocode[b.bfn--, switches--]; inload => BEGIN VMBacking.RecoverRealMemory[]; -- so that the germ can find it for the next guy. DeviceCleanup.Perform[disconnect]; GermSwap.InLoad[NIL, NIL, 0, b.inloadLoc, switches]; END; ENDCASE => ERROR; END; IF inloadedOnce THEN BEGIN newSwitches: Booting.Switches _ ALL[FALSE]; newSwitches[w] _ TRUE; GermSwap.InLoad[NIL, NIL, 0,@self, newSwitches]; END; DeviceCleanup.Perform[turnOn]; ProcessorFace.SetMP[MPCodes.emptyMP]; PrincOpsUtils.EnableInterrupts[]; IF outloadLoc # NIL THEN CallRollbackProcs[]; END; ProcsRec: TYPE = RECORD[ c: Booting.CheckpointProc, r: Booting.RollbackProc, clientData: REF ANY, nextC: REF ProcsRec _ NIL, nextR: REF ProcsRec _ NIL]; checkpoints: REF ProcsRec _ NIL; -- one end of a two-way linked list rollbacks: REF ProcsRec _ NIL; -- other end of that list RegisterProcs: PUBLIC ENTRY PROC[c: Booting.CheckpointProc _ NIL, r: Booting.RollbackProc _ NIL, clientData: REF ANY _ NIL] = BEGIN ENABLE UNWIND => NULL; new: REF ProcsRec = NEW[ProcsRec _ [c: c, r: r, clientData: clientData]]; IF rollbacks = NIL THEN rollbacks _ new; IF checkpoints # NIL THEN checkpoints.nextR _ new; new.nextC _ checkpoints; checkpoints _ new; END; Deregister: PUBLIC ENTRY PROC[c: Booting.CheckpointProc _ NIL, r: Booting.RollbackProc _ NIL] = BEGIN ENABLE UNWIND => NULL; prev: REF ProcsRec _ NIL; FOR this: REF ProcsRec _ checkpoints, this.nextC UNTIL this = NIL DO IF this.c = c AND this.r = r THEN BEGIN IF this.nextR = NIL THEN checkpoints _ this.nextC ELSE this.nextR.nextC _ this.nextC; IF this.nextC = NIL THEN rollbacks _ this.nextR ELSE this.nextC.nextR _ this.nextR; EXIT END; prev _ this; ENDLOOP; END; CallCheckpointProcs: INTERNAL PROC RETURNS[rejection: Rope.ROPE _ NIL] = TRUSTED BEGIN FOR this: REF ProcsRec _ checkpoints, this.nextC UNTIL this = NIL DO IF this.c # NIL THEN BEGIN rejection _ (this.c)[this.clientData]; IF rejection.Length[] = 0 THEN rejection _ NIL ELSE BEGIN -- undo the damage caused so far ... FOR undo: REF ProcsRec _ this.nextR, undo.nextR UNTIL undo = NIL DO IF undo.c # NIL AND undo.r # NIL THEN (undo.r)[this.clientData] ENDLOOP; RETURN END; END; ENDLOOP; END; CallRollbackProcs: INTERNAL PROC = TRUSTED BEGIN FOR this: REF ProcsRec _ rollbacks, this.nextR UNTIL this = NIL DO IF this.r # NIL THEN (this.r)[this.clientData] ENDLOOP; END; Checkpoint: PUBLIC PROC RETURNS[rejection: Rope.ROPE _ NIL] = BEGIN mySwitches: Booting.Switches _ ALL[FALSE]; mySwitches[v] _ TRUE; -- => copy VM for checkpoint VerifyFile[File.SystemVolume[], checkpoint]; RETURN[Boot[ boot: [self[]], switches: mySwitches, outload: [logical[root: checkpoint]] ]] END; VerifyFile: PROC[volume: File.Volume, which: File.VolumeFile] = TRUSTED BEGIN size: File.PageCount _ BootFile.MemorySizeToFileSize[VMSideDoor.rmPages]+256; oldFP: File.FP = File.GetRoot[volume, which].fp; new: File.Handle; BEGIN -- try to guess the correct size, so our FS will do volume flushing size _ size - VMSideDoor.rmPages; -- size _ boot file overhead FOR p: VM.VMPartition IN VM.VMPartition DO pagesAllocated, pagesFreed, pagesInPartition: INT; [pagesAllocated, pagesFreed, pagesInPartition] _ VMStatistics.VirtualAllocation[p]; size _ size + (pagesAllocated-pagesFreed); ENDLOOP; size _ size + 256; -- guess for checkpoint file overhead END; new _ File.Open[volume, oldFP ! File.Error => { new _ NIL; CONTINUE} ]; IF new = NIL THEN new _ File.Create[volume, size]; IF File.Info[new].size < size THEN File.SetSize[new, size]; File.SetRoot[which, new]; END; END. êCedar Nucleus (Files): per-file operations, locking file header data structures BootingImpl.mesa Andrew Birrell September 20, 1983 3:35 pm ******** Exports to Booting interface ******** nww _ PrincOpsUtils.ReadNWW[]; PrincOpsUtils.WriteNWW[Basics.BitOR[nww, PrincOpsUtils.ReadNWW[]]]; Can't get here Inloaded twice: VM backing file has been disturbed by a previous inload, so re-boot ******** Checkpoint facilities ******** Add to head of CheckpointProcs and tail of RollbackProcs �Ê ý˜JšœP™PJšœ™Jšœ*™*šÏk ˜ Jšœ �œ#˜1Jšœ�œR˜_Jšœ�œ ˜Jšœ�œ�œy˜œJšœ �œ=˜OJšœ �œ*˜8Jšœ�œ-˜CJšœ�œ ˜Jšœ�œ6˜JJšœ�œ˜)Jšœ �œ˜Jšœ�œa˜tJšœ�œ �œ˜Jš�œ�œ˜Jšœ �œ˜%Jšœ �œ ˜Jšœ �œ˜(Jšœ �œ˜%—J˜šœ �œ�˜Jš�œ¡˜¨Jš�œ�œ˜—J˜š�˜J˜—J˜Jšœ.™.˜Jšœ �œ&˜6J˜š Ïc Ïnœ�œ�œ�œ�˜qJšœ�œ0˜8—J˜šž Ÿœ�œ�œ˜Jšœ˜Jšœ˜Jšœ$˜$Jš�œ�œ�œ�˜-Jš�˜Jšœ'˜'šŸ œ�œ�œ�˜QJš�˜š�œ �œ�˜Jšœ�œ˜ šœ˜Jšœ8˜8—šœ ˜ Jš�˜Jš œ�œ �œ�œ�œ ˜:Jš�œ�œ�œ�œ˜.Jšœ1˜1Jš�œ-˜/Jš�œ�œ˜#Jš�œ˜—šœ ˜ Jš�˜šœ�œ�œ�˜AJš�œ@˜DJš�œ ˜—š�œ:�œ˜BJšœ�œ�˜,—š�œ�œ'˜,š�œ�˜ Jšœ2˜2Jš�œ-˜/Jš�œ�œ˜#Jš�˜Jš�œ˜——Jš�œ�œ�œ˜0Jš�œ˜Jš�œ˜—Jšœ �œ˜Jšœ�œ˜šœ˜Jšœ#˜#——Jš�œ˜Jš�œ˜—Jšœ�œ˜*Jšœ)˜)Jš �œ�œ�œ�œ�œ-˜SJš�œ�œ'˜BJš�œ�œ#˜8Jšœ˜šœ˜Jš œ �œ�œ �œ�œ˜7šœ�œ �œ�˜Jšœ˜Jšœ˜Jšœ ˜ Jš�œ˜ —Jšœ˜—Jš�œ˜—J˜Jšœ�œ�œ�œ˜"J˜šŸœ�œ�œ˜Jšœ �œ�œ�œ˜/šœ�œ�œ�˜Jšœ�œ˜ Jšœ�œ�œ˜4Jšœ�œ˜Jšœ+˜+Jš�œ˜ —Jšœ˜Jšœ�œ�œ�œ�˜/Jš�˜Jš�œ�œ�œ˜Jšœ7˜7Jšœ �œ�œ˜Jš�œ�˜Jš �œ&�œ �œ�œ�œ˜KJšœ�œ˜Jšœ#ž˜>Jšœ˜Jš�œ�˜š�œ�˜ Jšœ�œ�œž˜TJšœ˜Jšœ˜Jšœ˜Jšœ™Jšœ=˜=JšœC™CJšœ˜Jšœ˜Jšœ˜Jš�œ˜—Jš�œ�œ ˜š�œ�˜ š�œ �œ�˜Jšœ�œ˜ Jšœ'ž œ˜5Jšœ9žœ˜Išœ ˜ Jš�˜Jšœž1˜PJ˜"Jšœ�œ�œ˜4Jš�œ˜——Jš�œ�œ˜Jšœ™Jš�œ˜—Jš�œ ˜š�œ�˜ JšœS™SJšœ �œ�œ˜+Jšœ�œ˜Jšœ�œ�œ˜0Jš�œ˜—Jšœ˜J˜%Jšœ!˜!Jš�œ�˜Jš�œ˜Jš�œ˜—J˜J˜J˜—Jšœ'™'™šœ �œ�œ˜J˜J˜Jšœ �œ�œ˜Jšœ�œ �œ˜Jšœ�œ �œ˜—J˜Jšœ �œ �œž#˜DJšœ �œ �œž˜8J˜šŸ œ�œ�œ�œ�œ�œ�œ�œ�œ˜}Jš�˜Jš�œ�œ�œ˜Jšœ�œ �œ2˜IJšœ8™8Jš�œ �œ�œ˜(Jš�œ�œ�œ˜2Jšœ+˜+Jš�œ˜—J˜š Ÿ œ�œ�œ�œ�œ�œ˜_Jš�˜Jš�œ�œ�œ˜Jšœ�œ �œ˜Jš�œ�œ$�œ�˜Aš�œ�œ �œ ˜š�œ�˜ Jš�œ�œ�œ�œ˜UJš�œ�œ�œ�œ˜SJš�˜Jš�œ˜—J˜ —Jš�œ˜Jš�œ˜—J˜š Ÿœ�œ�œ�œ�œ�œ�˜PJš�˜Jš�œ�œ$�œ�˜Aš�œ�œ �˜š�œ�˜ Jšœ&˜&Jš�œ˜Jš�œ �˜š�œ�œž$˜/Jš�œ�œ#�œ�˜@Jš�œ�œ �œ�œ �œ�œ�œ˜KJš�˜Jš�œ˜—Jš�œ˜——Jš�œ˜Jš�œ˜—J˜šŸœ�œ�œ�˜*Jš�˜Jš�œ�œ"�œ�˜?Jš �œ�œ �œ�œ�œ˜:Jš�œ˜—J˜š Ÿ œ�œ�œ�œ�œ�œ˜=Jš�˜Jšœ�œ�œ˜*Jšœ�œž˜3Jšœ,˜,š�œ˜ Jšœ˜Jšœ˜Jšœ$˜$J˜—Jš�œ˜—J˜šŸ œ�œ0�˜GJš�˜JšœM˜MJšœ �œ"˜0Jšœ˜š�œžC˜IJšœ"ž˜>Jš�œ�œ �œ�œ ˜'š�œ/�œ˜5JšœS˜SJšœ*˜*—Jš�œ˜Jšœž%˜8—Jš�œ˜Jšœ6�œ�œ˜GJš�œ�œ�œ!˜2Jš�œ�œ˜;Jšœ˜Jš�œ˜—J˜—Jš�œ˜—…—¦,�