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 September 30, 1983 5:06 pm
DIRECTORY
BasicLoadStateFormat USING [
BcdInfo, ConfigIndex, LoadStateObject, ModuleInfo, nullConfig, nullModule, versionID],
BasicLoadStateFormatExtension USING [Extension, nullType],
BcdDefs USING [BcdBase, MTIndex, MTNull],
MB USING [BHandle, Error, Handle],
MBLoaderOps USING [Binding, BindingRecord, BindLink, EnumerationDirection],
MBVM USING [AllocData, DataSeg, HyperSpace, LongCopyWrite, LongPointerFromSeg, Write],
PrincOps USING [GFT, GFTIndex, GlobalFrame, GlobalFrameHandle],
PrincOpsUtils USING [PagesForWords];
MBLoadState: PROGRAM
IMPORTS MB, MBVM, PrincOpsUtils
EXPORTS MBLoaderOps =
BEGIN
OPEN MB;
data: MB.Handle ← NIL;
loadstate: REF BasicLoadStateFormat.LoadStateObject ← NIL;
extension: REF BasicLoadStateFormatExtension.Extension ← NIL;
lsWords, extensionWords: CARDINAL;
nextGFI: CARDINAL ← 1; -- gfi 0 is never used
InitLoadState: PUBLIC PROC [h: MB.Handle] = {data ← h};
FinishLoadState: PUBLIC PROC = {
loadstate ← NIL;
extension ← NIL;
data ← NIL;
};
InputLoadState: PUBLIC PROC RETURNS [nbcds: BasicLoadStateFormat.ConfigIndex] = {
IF loadstate = NIL THEN {
IF ~data.germ THEN {
lsWords ←
SIZE[BasicLoadStateFormat.LoadStateObject[BasicLoadStateFormat.ConfigIndex.LAST]];
extensionWords ← SIZE[BasicLoadStateFormatExtension.Extension];
data.lsseg ← MBVM.AllocData[
base: MBVM.HyperSpace,
pages: PrincOpsUtils.PagesForWords[lsWords+extensionWords],
dir: up
];
data.lsseg.info.readOnly ← FALSE;
data.lsseg.bootLoaded ← TRUE;
};
allocate temporary copy of loadstate (written into MBVM loadstate by WriteLoadState)
loadstate ←
NEW[BasicLoadStateFormat.LoadStateObject[BasicLoadStateFormat.ConfigIndex.LAST]];
loadstate.versionident ← BasicLoadStateFormat.versionID;
FOR gfi: PrincOps.GFTIndex IN [0..data.gftLength) DO
loadstate.gft[gfi] ← BasicLoadStateFormat.nullModule;
ENDLOOP;
FOR i: BasicLoadStateFormat.ConfigIndex IN [0..BasicLoadStateFormat.ConfigIndex.LAST) DO
loadstate.bcds[i] ← [ptr[NIL]];
ENDLOOP;
loadstate.nBcds ← 0;
extension ← NEW[BasicLoadStateFormatExtension.Extension];
FOR gfi: PrincOps.GFTIndex IN [0..data.gftLength) DO
extension[gfi] ← [mti: BcdDefs.MTNull, type: BasicLoadStateFormatExtension.nullType];
ENDLOOP;
nextGFI ← 1;
};
RETURN[loadstate.nBcds]
};
UpdateLoadState: PUBLIC PROC [
config: BasicLoadStateFormat.ConfigIndex, handle: MB.BHandle] = {
bcd: BcdDefs.BcdBase = handle.bcd;
IF config = BasicLoadStateFormat.nullConfig THEN ERROR;
loadstate.bcds[config].bcd ←
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 = {
p: LONG POINTER;
IF data.germ THEN RETURN;
p ← MBVM.LongPointerFromSeg[data.lsseg];
MBVM.LongCopyWrite[
from: LOOPHOLE[loadstate], to: p,
nwords: lsWords
];
MBVM.LongCopyWrite[
from: LOOPHOLE[extension], to: p + lsWords,
nwords: extensionWords
];
};
EnterModule: PUBLIC PROC [
rgfi: PrincOps.GFTIndex, module: BasicLoadStateFormat.ModuleInfo,
mti: BcdDefs.MTIndex ← BcdDefs.MTNull] = {
loadstate.gft[rgfi] ← module;
IF mti ~= BcdDefs.MTNull THEN extension[rgfi].mti ← mti;
};
GetModule: PUBLIC PROC [rgfi: PrincOps.GFTIndex]
RETURNS [module: BasicLoadStateFormat.ModuleInfo] = {
RETURN[loadstate.gft[rgfi]]};
AcquireBcd: PUBLIC PROC [config: BasicLoadStateFormat.ConfigIndex]
RETURNS [handle: MB.BHandle] = {
RETURN[data.inputBCDs.bcds[config]]};
InitBinding: PUBLIC PROC [bcd: BcdDefs.BcdBase] RETURNS [binding: MBLoaderOps.Binding] = {
binding ← NEW[MBLoaderOps.BindingRecord[bcd.nDummies] ← [
bias: bcd.firstdummy,
b: NULL --ALL[MBLoaderOps.BindLink[whichgfi: 0, body: notbound[]]]
]];
FOR i: CARDINAL IN [0..binding.n) DO
binding.b[i] ← MBLoaderOps.BindLink[whichgfi: 0, body: notbound[]];
ENDLOOP;
};
BcdUnresolved: PUBLIC PROC [
bcd: BasicLoadStateFormat.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: BasicLoadStateFormat.ConfigIndex] RETURNS [BOOL] = {
RETURN[loadstate.bcds[bcd].exports]};
BcdExportsTypes: PUBLIC PROC [bcd: BasicLoadStateFormat.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"];
nextGFI ← nextGFI + reserve;
};
SetGFTEntry: PUBLIC PROC [
frame: PrincOps.GlobalFrameHandle, gfi: PrincOps.GFTIndex, ngfi: CARDINAL] = {
IF gfi+ngfi >= data.gftLength THEN MB.Error["GFT Full"];
FOR i: CARDINAL IN [gfi..gfi+ngfi) DO
bias: CARDINAL = (i-gfi);
MBVM.Write[
@PrincOps.GFT[i].framePtr,
(frame + bias)]; -- bottom two bits of GFT entries bias evi's
ENDLOOP;
};
EnumerateModules: PUBLIC PROC [
proc: PROC [rgfi: PrincOps.GFTIndex, module: BasicLoadStateFormat.ModuleInfo] RETURNS [BOOL]]
RETURNS [i: PrincOps.GFTIndex] = {
FOR i IN [0..nextGFI) DO
IF loadstate.gft[i].config ~= BasicLoadStateFormat.nullConfig AND proc[i, loadstate.gft[i]] THEN
EXIT;
ENDLOOP;
};
EnumerateBcds: PUBLIC PROC [
dir: MBLoaderOps.EnumerationDirection,
proc: PROC [BasicLoadStateFormat.ConfigIndex] RETURNS [BOOL]]
RETURNS [config: BasicLoadStateFormat.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[BasicLoadStateFormat.nullConfig]
};
END.