DIRECTORY
BasicLoadState USING [ModuleIndex, NullModule],
BasicLoadStateFormat
USING [
BcdInfo, ConfigIndex, LoadState, ModuleInfo, nullConfig],
BcdDefs USING [BcdBase, MTHandle],
BootStartList
USING [
h, IndexToSpaceEntryPointer, IndexToSwapUnitEntryPointer, SpaceEntryPointer, SwapUnitEntryPointer],
PrincOps USING [GFT, GFTIndex, GFTItem, GlobalFrameHandle],
VM USING [Allocate, Free, Interval, PageNumberToAddress, WordsToPages];
ConfigID: PUBLIC TYPE = ConfigIndex;
ModuleIndex: TYPE = BasicLoadState.ModuleIndex;
TypeCode: PUBLIC TYPE = CARDINAL;
Extension: TYPE = LONG POINTER TO ConfigTable;
ConfigTable: TYPE = RECORD[SEQUENCE COMPUTED ConfigID OF ModuleMap];
ModuleMap: TYPE = LONG POINTER TO ModuleMapTable;
ModuleMapTable:
TYPE =
RECORD[
SEQUENCE length: CARDINAL OF ModuleEntry];
ModuleEntry:
TYPE =
RECORD [
gfh: PrincOps.GlobalFrameHandle,
type: TypeCode];
NullConfig: PUBLIC ConfigID ← BasicLoadStateFormat.nullConfig;
loadState: LoadState ← NIL;
extension: Extension ← NIL;
loadStateInterval, extensionInterval: VM.Interval;
Destroy:
PUBLIC PROC = {
IF loadState = NIL THEN RETURN;
VM.Free[extensionInterval];
VM.Free[loadStateInterval];
loadState ← NIL;
};
ModuleToGlobalFrame:
PUBLIC PROC [config: ConfigID, module: ModuleIndex]
RETURNS [gfh: PrincOps.GlobalFrameHandle] = {
moduleMap: ModuleMap;
IF loadState = NIL THEN ERROR BasicLoadStateGone;
IF ~(config IN [ConfigID.FIRST..loadState.nBcds)) THEN ERROR BogusConfigID;
moduleMap ← extension[config];
IF module >= moduleMap.length THEN ERROR BogusModuleIndex;
RETURN [moduleMap[module].gfh]
};
GlobalFrameToModule:
PUBLIC PROC [gfh: PrincOps.GlobalFrameHandle]
RETURNS [config: ConfigID, module: ModuleIndex] = {
info: ModuleInfo;
IF loadState = NIL THEN ERROR BasicLoadStateGone;
info ← loadState.gft[gfh.gfi];
RETURN[config: info.config, module: info.module]
};
GlobalFrameToType:
PUBLIC PROC [gfh: PrincOps.GlobalFrameHandle]
RETURNS [type: TypeCode] = {
info: ModuleInfo;
IF loadState = NIL THEN ERROR BasicLoadStateGone;
info ← loadState.gft[gfh.gfi];
RETURN[extension[info.config]^[info.module].type]
};
SetType:
PUBLIC PROC [gfh: PrincOps.GlobalFrameHandle, type: TypeCode] = {
info: ModuleInfo;
IF loadState = NIL THEN ERROR BasicLoadStateGone;
info ← loadState.gft[gfh.gfi];
IF extension[info.config]^[info.module].gfh ~= gfh THEN ERROR;
extension[info.config]^[info.module].type ← type;
};
ConfigInfo:
PUBLIC PROC [config: ConfigID]
RETURNS [
bcd: BcdDefs.BcdBase, exports, exportsTypes: BOOL] = {
bi: BcdInfo;
IF loadState = NIL THEN ERROR BasicLoadStateGone;
IF ~(config IN [ConfigID.FIRST..loadState.nBcds)) THEN ERROR BogusConfigID;
bi ← loadState.bcds[config];
exports ← bi.exports; exportsTypes ← bi.typeExported;
bi.exports ← bi.typeExported ← FALSE;
bcd ← bi.bcd;
};
EnumerateConfigs:
PUBLIC PROC [proc:
PROC [ConfigID]
RETURNS [
BOOL]]
RETURNS [config: ConfigID] = {
IF loadState = NIL THEN ERROR BasicLoadStateGone;
FOR config
IN [0..loadState.nBcds)
DO
IF proc[config] THEN RETURN;
ENDLOOP;
RETURN[nullConfig]
};
EnumerateModulesInConfig:
PUBLIC
PROC [
config: ConfigID, proc: PROC [ModuleIndex] RETURNS [BOOL]]
RETURNS [module: ModuleIndex] = {
moduleMap: ModuleMap;
prev: PrincOps.GlobalFrameHandle ← NIL;
IF loadState = NIL THEN ERROR BasicLoadStateGone;
moduleMap ← extension[config];
FOR module
IN [1..moduleMap.length)
DO
IF moduleMap[module].gfh = prev THEN LOOP;
IF proc[module] THEN RETURN;
prev ← moduleMap[module].gfh;
ENDLOOP;
RETURN[BasicLoadState.NullModule]
};
EnumerateAllModules:
PUBLIC PROC [
proc: PROC [ConfigID, ModuleIndex] RETURNS [BOOL]]
RETURNS [config: ConfigID, module: ModuleIndex] = {
IF loadState = NIL THEN ERROR BasicLoadStateGone;
FOR config
IN [0..loadState.nBcds)
DO
prev: PrincOps.GlobalFrameHandle ← NIL;
moduleMap: ModuleMap = extension[config];
FOR module
IN [1..moduleMap.length)
DO
IF moduleMap[module].gfh = prev THEN LOOP;
IF proc[config, module] THEN RETURN;
prev ← moduleMap[module].gfh;
ENDLOOP;
ENDLOOP;
RETURN[NullConfig, BasicLoadState.NullModule]
};
ConfigToBcd:
PROC [config: ConfigID]
RETURNS [BcdDefs.BcdBase] = {
bi: BcdInfo ← loadState.bcds[config];
bi.exports ← bi.typeExported ← FALSE;
RETURN [bi.bcd]
};
BuildLoadState:
PROC = {
FindLoadState:
PROC
RETURNS [LoadState] = {
OPEN BootStartList;
su: SwapUnitEntryPointer = IndexToSwapUnitEntryPointer[h.initLoadState];
parent: SpaceEntryPointer = IndexToSpaceEntryPointer[su.parent];
loadStateInterval ← [page: parent.vmPage + su.base, count: su.pages];
RETURN[VM.PageNumberToAddress[loadStateInterval.page]]
};
GetFrame:
PROC [g: PrincOps.GFTItem]
RETURNS [PrincOps.GlobalFrameHandle] = {
g.epbias ← 0;
RETURN[g.framePtr]
};
MapSize:
PROC [bcd: BcdDefs.BcdBase]
RETURNS [
CARDINAL] = {
IF bcd.nModules > 1 THEN RETURN[bcd.firstdummy];
RETURN[1+LOOPHOLE[bcd+bcd.mtOffset, BcdDefs.MTHandle].ngfi]
};
extensionSize, configTableSize: NAT;
moduleMap: ModuleMap;
loadState ← FindLoadState[];
extensionSize ← configTableSize ← SIZE[ConfigTable[loadState.nBcds]];
FOR config: ConfigID
IN [0..loadState.nBcds)
DO
bcd: BcdDefs.BcdBase = ConfigToBcd[config];
extensionSize ← extensionSize + SIZE[ModuleMapTable[MapSize[bcd]]];
ENDLOOP;
extensionInterval ← VM.Allocate[VM.WordsToPages[extensionSize]];
extension ← VM.PageNumberToAddress[extensionInterval.page];
moduleMap ← LOOPHOLE[extension + configTableSize];
FOR config: ConfigID
IN [0..loadState.nBcds)
DO
bcd: BcdDefs.BcdBase = ConfigToBcd[config];
mapSize: CARDINAL = MapSize[bcd];
extension[config] ← moduleMap;
LOOPHOLE[moduleMap, LONG POINTER TO CARDINAL]^ ← mapSize;
moduleMap[0] ← [gfh: NIL, type: 0];
FOR gfi: PrincOps.GFTIndex
IN PrincOps.GFTIndex
DO
IF loadState.gft[gfi].config = config
THEN {
IF loadState.gft[gfi].module >= mapSize THEN ERROR;
moduleMap[loadState.gft[gfi].module] ← [
gfh: GetFrame[PrincOps.GFT[gfi]],
type: 0
];
};
ENDLOOP;
moduleMap ← moduleMap + SIZE[ModuleMapTable[mapSize]];
ENDLOOP;
};