<> <> 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]; BasicLoadStateImpl: PROGRAM IMPORTS BootStartList, VM EXPORTS BasicLoadState = BEGIN OPEN BasicLoadStateFormat; <> 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; <> <<>> BasicLoadStateGone: ERROR = CODE; BogusConfigID: ERROR = CODE; BogusModuleIndex: ERROR = CODE; <> 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; }; BuildLoadState[]; END.