MBLoadState.mesa
Last modified by Sandman on March 13, 1981 4:01 PM
Last modified by Lewis on 21-Sep-81 17:08:04
Last modified by Levin on April 5, 1983 3:12 pm
DIRECTORY
BcdOps USING [BcdBase],
Environment USING [wordsPerPage],
PrincOps USING [GFTIndex, GlobalFrame, GlobalFrameHandle],
MB USING [BHandle, Error, Handle, Zero],
MBLoaderOps USING [Binding, BindLink, EnumerationDirection],
MBStorage USING [FreePages, Pages, PagesForWords],
MBVM USING [AllocData, DataSeg, HyperSpace, LongCopyWrite, LongPointerFromSeg, Write],
PilotLoadStateFormat
USING [
BcdInfo, ConfigIndex, LoadState, LoadStateObject, ModuleInfo, NullConfig, NullModule, PilotVersionID],
PrincOpsRuntime USING [GFT];
MBLoadState:
PROGRAM
IMPORTS MB, MBStorage, MBVM
EXPORTS MBLoaderOps =
BEGIN
OPEN MB;
data: MB.Handle ← NIL;
loadstate: PilotLoadStateFormat.LoadState ← NIL;
nextGFI: CARDINAL ← 1; -- gfi 0 is never used
InitLoadState: PUBLIC PROC [h: MB.Handle] = {data ← h};
FinishLoadState:
PUBLIC
PROC = {
IF loadstate # NIL THEN {MBStorage.FreePages[loadstate]; loadstate ← NIL};
data ← NIL;
};
InputLoadState:
PUBLIC
PROC
RETURNS [nbcds: PilotLoadStateFormat.ConfigIndex] = {
IF loadstate =
NIL
THEN {
lsPages:
CARDINAL = MBStorage.PagesForWords[
SIZE[PilotLoadStateFormat.LoadStateObject] -- full-size module table, 0-size bcd table-- +
LAST[PilotLoadStateFormat.ConfigIndex] * SIZE[PilotLoadStateFormat.BcdInfo]
];
IF ~data.germ
THEN {
data.lsseg ← MBVM.AllocData[base: MBVM.HyperSpace, pages: lsPages, dir: up];
data.lsseg.info.readOnly ← FALSE;
data.lsseg.bootLoaded ← TRUE;
};
allocate temporary copy of loadstate (written into MBVM loadstate by WriteLoadState)
loadstate ← MBStorage.Pages[lsPages];
MB.Zero[loadstate, lsPages*Environment.wordsPerPage];
loadstate.versionident ← PilotLoadStateFormat.PilotVersionID;
FOR i:
CARDINAL
IN [0..data.gftLength)
DO
loadstate.gft[i] ← PilotLoadStateFormat.NullModule;
ENDLOOP;
loadstate.nBcds ← 0;
LOOPHOLE[@loadstate.bcds,
LONG
POINTER
TO
CARDINAL]^ ←
LAST[PilotLoadStateFormat.ConfigIndex];
nextGFI ← 1;
};
RETURN[loadstate.nBcds]
};
UpdateLoadState:
PUBLIC
PROC [
config: PilotLoadStateFormat.ConfigIndex, handle: MB.BHandle] = {
bcd: BcdOps.BcdBase = handle.bcd;
IF config = PilotLoadStateFormat.NullConfig THEN ERROR;
loadstate.bcds[config].origin ←
IF data.germ THEN NIL ELSE MBVM.LongPointerFromSeg[handle.bcdSeg];
loadstate.bcds[config].typeExported ← bcd.typeExported;
loadstate.bcds[config].exports ← (bcd.nExports # 0);
IF config >= loadstate.nBcds THEN loadstate.nBcds ← loadstate.nBcds + 1;
};
WriteLoadState:
PUBLIC
PROC = {
IF data.germ THEN RETURN;
MBVM.LongCopyWrite[
from: loadstate, to: MBVM.LongPointerFromSeg[data.lsseg],
nwords: data.lsseg.pages * Environment.wordsPerPage];
EnterModule:
PUBLIC
PROC [rgfi: PrincOps.GFTIndex, module: PilotLoadStateFormat.ModuleInfo] =
{loadstate.gft[rgfi] ← module};
GetModule:
PUBLIC
PROC [rgfi: PrincOps.GFTIndex]
RETURNS [module: PilotLoadStateFormat.ModuleInfo] = {
RETURN[loadstate.gft[rgfi]]};
AcquireBcd:
PUBLIC
PROC [config: PilotLoadStateFormat.ConfigIndex]
RETURNS [handle: MB.BHandle] = {
RETURN[data.inputBCDs.bcds[config]]};
ReleaseBcd: PUBLIC PROC [handle: MB.BHandle] = {};
InitBinding:
PUBLIC
PROC [
bcd: BcdOps.BcdBase] RETURNS [binding: MBLoaderOps.Binding] = {
BindingSequence: TYPE = RECORD[SEQUENCE COMPUTED CARDINAL OF MBLoaderOps.BindLink];
p: LONG POINTER ← data.zone.NEW[BindingSequence[bcd.nDummies]];
binding ←
DESCRIPTOR[
-- BASE[binding] is biased by bcd.firstdummy
(p - CARDINAL[bcd.firstdummy * SIZE[MBLoaderOps.BindLink]]), bcd.nDummies];
FOR i:
CARDINAL
IN [bcd.firstdummy..bcd.firstdummy + bcd.nDummies)
DO
binding[i] ← MBLoaderOps.BindLink[whichgfi: 0, body: notbound[]];
ENDLOOP;
ReleaseBinding:
PUBLIC
PROC [
bcd: BcdOps.BcdBase, binding: MBLoaderOps.Binding]
RETURNS [null: MBLoaderOps.Binding] = {
IF
BASE[binding] #
NIL
THEN {
avoid compiler warning message
p: LONG POINTER ← BASE[binding] + bcd.firstdummy*SIZE[MBLoaderOps.BindLink];
data.zone.FREE[@p];
};
RETURN[DESCRIPTOR[NIL, 0]]
};
BcdUnresolved:
PUBLIC
PROC [
bcd: PilotLoadStateFormat.ConfigIndex] RETURNS [BOOL] = {
FOR i: PrincOps.GFTIndex
IN [0..data.gftLength)
DO
IF bcd = loadstate.gft[i].config AND ~loadstate.gft[i].resolved THEN RETURN[TRUE];
ENDLOOP;
RETURN[FALSE]
};
BcdExports:
PUBLIC
PROC [bcd: PilotLoadStateFormat.ConfigIndex]
RETURNS [
BOOL] = {
RETURN[loadstate.bcds[bcd].exports]};
BcdExportsTypes:
PUBLIC
PROC [bcd: PilotLoadStateFormat.ConfigIndex]
RETURNS [
BOOL] = {
RETURN[loadstate.bcds[bcd].typeExported]};
GFT management
GetNextGFI:
PUBLIC
PROC [reserve:
CARDINAL]
RETURNS [next: PrincOps.GFTIndex] = {
IF (next ← nextGFI) >= data.gftLength THEN MB.Error["GFT overflow"L];
nextGFI ← nextGFI + reserve;
};
SetGFTEntry:
PUBLIC
PROC [
frame: PrincOps.GlobalFrameHandle, gfi: PrincOps.GFTIndex, ngfi: CARDINAL] = {
IF gfi+ngfi >= data.gftLength THEN MB.Error["GFT Full"L];
FOR i:
CARDINAL
IN [gfi..gfi+ngfi)
DO
bias: CARDINAL = (i-gfi);
MBVM.Write[
@PrincOpsRuntime.GFT[i].framePtr,
(frame + bias)]; -- bottom two bits of GFT entries bias evi's
ENDLOOP;
EnumerateModules:
PUBLIC
PROC [
proc: PROC [rgfi: PrincOps.GFTIndex, module: PilotLoadStateFormat.ModuleInfo] RETURNS [BOOL]]
RETURNS [i: PrincOps.GFTIndex] = {
FOR i
IN [0..nextGFI)
DO
IF loadstate.gft[i].config ~= PilotLoadStateFormat.NullConfig
AND proc[i, loadstate.gft[i]]
THEN
EXIT;
ENDLOOP;
EnumerateBcds:
PUBLIC
PROC [
dir: MBLoaderOps.EnumerationDirection,
proc: PROC [PilotLoadStateFormat.ConfigIndex] RETURNS [BOOL]]
RETURNS [config: PilotLoadStateFormat.ConfigIndex] = {
SELECT dir
FROM
recentfirst =>
FOR config
DECREASING
IN [0..loadstate.nBcds)
DO
IF proc[config] THEN RETURN;
ENDLOOP;
recentlast =>
FOR config
IN [0..loadstate.nBcds)
DO
IF proc[config] THEN RETURN;
ENDLOOP;
ENDCASE;
RETURN[PilotLoadStateFormat.NullConfig]
};