Booting.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Andrew Birrell September 20, 1983 3:34 pm
Russ Atkinson (RRA) February 20, 1985 2:56:53 pm PST
Doug Wyatt, February 27, 1985 9:47:40 am PST
Public interface to booting facilities.
DIRECTORY
MicrocodeBooting USING [ BootFileNumber, MicrocodeType, nullBootFileNumber ],
File USING [ Handle, PageNumber, Volume, VolumeFile, VolumeID, nullVolumeID ],
GermSwap USING [ Switches ],
Rope USING [ ROPE ];
Booting: CEDAR DEFINITIONS
= BEGIN
ROPE: TYPE ~ Rope.ROPE;
Switches: TYPE = GermSwap.Switches;
switches: Switches;
The switches with which we were booted. Get them here in preference to GermSwap.
MicrocodeType: TYPE = MicrocodeBooting.MicrocodeType;
= { altoMesa, lisp, smalltalk76, smalltalk80, pilotMesa, cedarMesa }
BootFileNumber: TYPE = MicrocodeBooting.BootFileNumber;
nullMicrocode: BootFileNumber = MicrocodeBooting.nullBootFileNumber;
Bootee: TYPE = RECORD[
SELECT type: * FROM
noOp =>
NULL,
file =>
[ file: File.Handle, firstPage: File.PageNumber ← [0] ],
logical =>
[ volume: File.Volume ← NIL, root: File.VolumeFile[checkpoint..debuggee] ← bootFile ],
physical =>
[ volume: File.--Physical--VolumeID ← File.nullVolumeID, root: File.VolumeFile[checkpoint..bootFile] ← bootFile ],
microcode =>
[ bfn: BootFileNumber ← nullMicrocode ],
bootButton =>
NULL,
self =>
NULL,
ENDCASE
];
Boot: PROC [boot: Bootee, switches: Switches, outload: Bootee ← [noOp[]] ] RETURNS [rejection: ROPENIL];
Runs any registered booting procs, and if they all allow the boot, boots from the indicated source.
outload.type must be in [noOp..physical]. If outload.type = noOp and there is a system volume and the system volume has a "debugger" root file, then this is used in place of the argument. If outload.type is now not "noOp", first calls any registered CheckpointProcs (see below), and if any of them reject the checkpoint, Boot returns the rejection rope; then outloads to specified place, then performs the boot. When the outload is resumed, calls any registered RollbackProcs. If outload.type is noOp, then no CheckpointProcs are called, and rejection will be NIL.
"switches" is ignored by some variants. (Today, "bootButton" and "microcode".)
"self" boots from the boot location which was used to boot this run.
"bootButton" emulates pressing the physical boot button
"microcode" boots new microcode. Default will use installed disk microcode.
"physical" boots from the specified root of the physical volume having the specified ID (nullVolumeID means the physical volume containing page 0 of the system volume).
"logical" boots from the specified root of the specified logical volume (NIL means the system volume).
"file" boots from the specified file (first makes the file bootable).
This procedure may raise File.Error[wentOffline, nonCedarVolume, inconsistent, software, hardware, unknownFile, unknownPage, mixedDevices]. In particular, it will raise File.Error[unknownFile] if the specified boot or outload location does not exist or implies a null FP. Other failures may cause the Germ to stop with a maintenance panel code, or may cause the microcode to stop.
inloadedOnce: BOOL;
Used for the world-swap debugger's "inloaded twice" flag, which indicates that the VM image is out of date because the outload has executed after a subsequent inload. This boolean is set to FALSE by BootingImpl before making the outload. On a subsequent inload, if the boolean is TRUE then BootingImpl will boot [self[]] with no outload and with the "W" switch. After an inload, a client (typically WVMOutLd) may patch the outload file (!) to set the boolean FALSE, thus disabling any second inload. You don't need to understand all that: keep well clear of this boolean.
GetBootFileNumber: PROC [MicrocodeType] RETURNS [BootFileNumber];
Returns the BootFileNumber of the specified microcode for this machine and (in the case of pilotMesa or cedarMesa) for the release of Pilot currently running on this machine. Returns nullBootFileNumber if no such microcode is known to exist.
Checkpoint: PROC RETURNS [rejection: ROPENIL];
Checkpoint saves the state of the currently allocated virtual memory, so that it can be restored by subsequent rollbacks. It does so by preserving the real memory in an outload file associated with the present system volume, then re-booting the current boot file with a switch requesting a checkpoint; this switch causes the boot file to make a copy of the current virtual memory backing storage, then inload the real memory. Subsequently, if you boot a boot file with the r switch, and there is a checkpoint associated with its system volume, the boot file will perform a rollback. A boot file will also perform a rollback if it is booted with no switches and there is a checkpoint associated with its system volume and the boot file is the installed boot file on that volume or on the corresponding physical volume. Performing a rollback causes the boot file to copy VM from the checkpoint back into the backing storage and inload the real memory. A checkpoint is tied to a particular volume, and a rollback occurs automatically only when booting the installed boot file on that volume (or its physical volume): any other boot file booted with no switches and this system volume will ignore the checkpoint, as will any boot file booted with any other system volume. There can be at most one checkpoint for any volume. Booting an installed bootfile with the f switch will cause it to ignore any checkpoint and go through the full booting sequence. An existing checkpoint can be destroyed by invoking the DeleteCheckpoint procedure in this interface.
Before making the outload, Checkpoint invokes each registered CheckpointProc once. These are invoked in the reverse of the order in which they were registered (in particular, if CheckpointProc's are registered during the synchronous start-up of the system, then they will be called in the reverse of the start-up order). After invoking all the CheckpointProc's, the system preserves the virtual memory (via the outload+inload sequence described above), then behaves precisely as if a rollback had occurred (including calling RollbackProc's, as described below). Whenever the saved virtual memory is rolled back, the program appears to be inside Checkpoint again. First, the registered RollbackProc's are each invoked, in the order in which they were registered. Then the call of Checkpoint returns with the result NIL.
When CheckpointProc's are invoked, parallel processes may still be executing; each package is responsible for blocking processes that might rely on the package's state which has been flushed by a CheckpointProc. In general, a package will need to have a CheckpointProc and/or a RollbackProc if it maintains state which may be invalidated when the virtual memory is restored on a rollback.
Each CheckpointProc has the option of refusing the checkpoint by returning a non-empty rope. If this happens, then the system invokes the RollbackProc's corresponding to CheckpointProcs that had accepted the checkpoint, and the call of Checkpoint returns the rejection reason.
A call of Checkpoint may raise File.Error[wentOffline, nonCedarVolume, inconsistent, software, hardware, volumeFull, mixedDevices].
CheckpointProc: TYPE = PROC [clientData: REF ANY] RETURNS [rejection: ROPENIL];
Invoked before making the checkpoint (or otherwise booting). Returning a non-empty rope prevents the checkpoint being made (see comments above); in this case "rejection" should be a human-readable explanation.
RollbackProc: TYPE = PROC [clientData: REF ANY];
Invoked on each rollback (including the one that occurs immediately after a successful checkpoint). Also invoked if the corresponding CheckpointProc had been invoked in a checkpoint that is rejected by a subsequent CheckpointProc.
RegisterProcs: PROC [c: CheckpointProc ← NIL, r: RollbackProc ← NIL, b: CheckpointProc ← NIL, clientData: REF ANYNIL];
... registers checkpoint, roolback, and booting procedures to be called when the appropriate event occurs. Note that the pairing of the procs is important if someone rejects the checkpoint: for each CheckpointProc that had been called, the associated RollbackProc (if any) is called on a rejection. The booting procedure needs no such pairing (it is not expected to make significant changes).
Deregister: PROC [c: CheckpointProc ← NIL, r: RollbackProc ← NIL, b: CheckpointProc ← NIL];
... removes the given registration.
DeleteCheckpoint: PROC [volume: File.Volume];
Destroys any existing checkpoint associated with the volume. This happens automatically when making a new checkpoint.
CallBootingProcs: PROC RETURNS [rejection: ROPE];
Calls the booting procs to determine if there is any reason to NOT boot. NIL is returned if it is OK to boot. The booting procs should perform no significant state changes (forcing flushes of files is OK, for example). This is useful if one if about to power off the machine, rather than booting, but wants to check if there is anything interesting going on first.
END.