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 POINTERBASE[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]
};
END.