DIRECTORY Ascii USING [CR], Basics USING [LongMult, LongNumber], BcdDefs USING [MTHandle], BootFile USING [ Entry, Header, maxEntriesPerHeader, maxEntriesPerTrailer, MemorySizeToFileSize, Trailer, currentVersion], BootStartList USING [Base, Entry, SwapUnitIndex, SwapUnitInfo], ConvertUnsafe USING [AppendRope], FileIO USING [CapabilityFromStream, Open], IO USING [ bool, card, Close, GetIndex, GetLength, PutChar, PutF, PutRope, rope, SetIndex, SetLength, STREAM, UnsafeGetBlock, UnsafePutBlock], MB USING [BHandle, DoAllModules, DumpSegs, Handle, StartControlLink], MBVM USING [ Base, CodeSeg, CopyRead, CopyWrite, DataSeg, FileSeg, GetPage, ReleaseCodeSegs, Seg, Segs, SortSegs, Write], PrincOps USING [ bytesPerPage, flagsClean, flagsReadOnly, GlobalFrame, InterimPageState, PageFlags, PageNumber, wordsPerPage], PrincOpsUtils USING [LowHalf, ZERO], Rope USING [ROPE], Segments USING [ FHandle, FP, InsertFile, ReleaseFile, SegmentAddress, SetFileTimes, SHandle, SwapIn, Unlock, Write], Space USING [Create, Delete, Handle, LongPointer, Map, virtualMemory], Time USING [Packed]; MBOutput: PROGRAM IMPORTS Basics, BootFile, ConvertUnsafe, FileIO, IO, MB, MBVM, PrincOpsUtils, Segments, Space EXPORTS MB = BEGIN OPEN MBVM; wordsPerPage: CARDINAL = PrincOps.wordsPerPage; bytesPerPage: CARDINAL = PrincOps.bytesPerPage; PageOfWords: TYPE = ARRAY [0..wordsPerPage) OF WORD; data: MB.Handle _ NIL; header: REF BootFile.Header _ NIL; trailer: REF BootFile.Trailer _ NIL; nEntries, currentEntry: CARDINAL; filePage: MBVM.Base; trailerIndex: LONG CARDINAL; EtherHeader: TYPE = MACHINE DEPENDENT RECORD [ version(0): CARDINAL _ 1, mustBeZero(1): LONG CARDINAL _ 0, createTime(3): BCPLTime ]; BCPLTime: TYPE = MACHINE DEPENDENT RECORD [high, low: CARDINAL]; InitOutput: PUBLIC PROC [h: MB.Handle] = {data _ h}; FinishOutput: PUBLIC PROC = { IF data.bootStream ~= NIL THEN {data.bootStream.Close[abort: TRUE]; data.bootStream _ NIL}; header _ NIL; trailer _ NIL; MBVM.ReleaseCodeSegs[]; data _ NIL; }; PreScanSegsForOutput: PUBLIC PROC [segs: MBVM.Segs] RETURNS [lastBootedPage: PrincOps.PageNumber] = { scriptBase: BootStartList.Base = data.scriptBase; nFilePages: CARDINAL _ 0; data.nBootLoadedPages _ 0; FOR i: CARDINAL IN [0..segs.length) DO seg: MBVM.Seg = segs[i]; su: LONG POINTER TO swapUnit BootStartList.Entry = @scriptBase[seg.index]; WITH s: seg SELECT FROM data => IF scriptBase[su.parent].bootLoaded THEN { IF s.base = 376B THEN IF s.pages ~= 1 THEN ERROR ELSE LOOP; -- ugh! IF su.info.state = resident THEN data.nResidentPages _ data.nResidentPages + su.pages; data.nBootLoadedPages _ data.nBootLoadedPages + su.pages; lastBootedPage _ MAX[lastBootedPage, scriptBase[su.parent].vmPage + su.base + su.pages - 1]; }; code => { nUnits: CARDINAL = IF s.sph = NIL THEN 1 ELSE s.sph.length; index: BootStartList.SwapUnitIndex _ s.index; THROUGH [0..nUnits) DO su: LONG POINTER TO swapUnit BootStartList.Entry = @scriptBase[index]; IF scriptBase[su.parent].bootLoaded THEN { IF su.info.state = resident THEN data.nResidentPages _ data.nResidentPages + su.pages; data.nBootLoadedPages _ data.nBootLoadedPages + su.pages; lastBootedPage _ MAX[lastBootedPage, scriptBase[su.parent].vmPage + su.base + su.pages - 1]; }; index _ index + SIZE[swapUnit BootStartList.Entry]; ENDLOOP; }; file => IF scriptBase[su.parent].bootLoaded THEN { IF su.info.state = resident THEN data.nResidentPages _ data.nResidentPages + s.pages; data.nBootLoadedPages _ data.nBootLoadedPages + s.pages; lastBootedPage _ s.base + s.pages - 1; }; ENDCASE; ENDLOOP; nFilePages _ BootFile.MemorySizeToFileSize[data.nBootLoadedPages]; FOR i: CARDINAL IN [0..segs.length) DO seg: MBVM.Seg = segs[i]; su: LONG POINTER TO swapUnit BootStartList.Entry = @scriptBase[seg.index]; WITH s: seg SELECT FROM data => IF AppendNecessary[su] THEN { scriptBase[su.parent].backingStore _ self; IF scriptBase[su.parent].backingPage = 0 THEN scriptBase[su.parent].backingPage _ nFilePages; nFilePages _ nFilePages + su.pages; }; code => { nUnits: CARDINAL = IF s.sph = NIL THEN 1 ELSE s.sph.length; index: BootStartList.SwapUnitIndex _ s.index; THROUGH [0..nUnits) DO su: LONG POINTER TO swapUnit BootStartList.Entry = @scriptBase[index]; IF AppendNecessary[su] THEN { scriptBase[su.parent].backingStore _ self; IF scriptBase[su.parent].backingPage = 0 THEN scriptBase[su.parent].backingPage _ nFilePages; nFilePages _ nFilePages + su.pages; }; index _ index + SIZE[swapUnit BootStartList.Entry]; ENDLOOP; }; file => IF AppendNecessary[su] THEN { scriptBase[su.parent].backingStore _ self; IF scriptBase[su.parent].backingPage = 0 THEN scriptBase[su.parent].backingPage _ nFilePages; nFilePages _ nFilePages + s.pages; }; ENDCASE; ENDLOOP; data.nFilePages _ nFilePages; }; WriteBootFile: PUBLIC PROC = { data.typescript.PutRope["Writing boot file..."]; InitializeBootFile[]; WriteVM[]; FinalizeBootFile[]; data.typescript.PutRope["finished writing.\N"]; IF data.etherFormat THEN MakeEtherFile[]; }; InitializeBootFile: PROC = { data.bootStream _ FileIO.Open[ fileName: data.output, accessOptions: overwrite, createLength: Basics.LongMult[data.nFilePages, bytesPerPage] ]; data.bootStream.SetLength[bytesPerPage]; data.bootStream.SetIndex[bytesPerPage]; data.bootHeader _ header _ LOOPHOLE[NEW[PageOfWords]]; PrincOpsUtils.ZERO[LOOPHOLE[header], wordsPerPage]; header^ _ BootFile.Header[ creationDate: data.buildTime, pStartListHeader: PrincOpsUtils.LowHalf[data.scriptBaseInVM], inLoadMode: load, continuation: [vp: initial[mdsi: [data.mdsBase/256], destination: MB.StartControlLink[]]], countData: data.nBootLoadedPages, entries: ]; trailer _ NIL; nEntries _ BootFile.maxEntriesPerHeader; currentEntry _ 0; filePage _ 1; }; FinalizeBootFile: PROC = { fp: Segments.FP _ FileIO.CapabilityFromStream[data.bootStream]; file: Segments.FHandle; length: INT = data.bootStream.GetIndex[]; data.bootStream.SetIndex[0]; data.bootStream.UnsafePutBlock[ block: [base: LOOPHOLE[header], startIndex: 0, stopIndexPlusOne: bytesPerPage]]; data.bootStream.SetIndex[length]; data.bootStream.SetLength[length]; data.bootStream.Close[]; data.bootStream _ NIL; file _ Segments.InsertFile[@fp, Segments.Write]; Segments.SetFileTimes[file: file, create: data.buildTime]; Segments.ReleaseFile[file]; }; WriteVM: PROC = { segs: MBVM.Segs = MBVM.SortSegs[]; scriptBase: BootStartList.Base = data.scriptBase; loadmap: IO.STREAM = data.loadmap; loadmap.PutRope["\N\NBOOT FILE MAP\N\N"]; BootloadedHeadingToLoadmap[" Bootloaded Memory\N"]; loadmap.PutF["%6n Header Page\N", IO.card[filePage-1]]; -- header page data.typescript.PutRope["bootloaded memory..."]; FOR i: CARDINAL IN [0..segs.length) DO WITH s: segs[i] SELECT FROM data => WriteDataSeg[@s]; code => WriteCodeSeg[@s]; file => WriteFileSeg[@s]; ENDCASE; ENDLOOP; IF trailer ~= NIL THEN [] _ WriteTrailerPage[]; NonBootloadedHeadingToLoadmap["\N Non-Bootloaded Memory\N"]; data.typescript.PutRope["non-bootloaded memory..."]; FOR i: CARDINAL IN [0..segs.length) DO WITH s: segs[i] SELECT FROM data => AppendDataSeg[@s]; code => AppendCodeSeg[@s]; file => AppendFileSeg[@s]; ENDCASE; ENDLOOP; loadmap.PutF["\N\NBoot file pages: %n (%n bootloaded, of which %n are resident)\N", IO.card[data.nFilePages], IO.card[data.nBootLoadedPages], IO.card[data.nResidentPages]]; }; WriteDataSeg: PROC [seg: MBVM.DataSeg] = { scriptBase: BootStartList.Base = data.scriptBase; su: LONG POINTER TO swapUnit BootStartList.Entry = @scriptBase[seg.index]; v: PrincOps.InterimPageState = MapValueForSeg[seg]; IF ~scriptBase[su.parent].bootLoaded THEN RETURN; IF seg.base = 376B THEN IF seg.pages ~= 1 THEN ERROR ELSE RETURN; -- ugh! BootloadedSegToLoadmap[seg, filePage, v.flags]; FOR page: CARDINAL IN [seg.base..seg.base+seg.pages) DO lp: LONG POINTER; EnterPage[page: page, value: v]; lp _ MBVM.GetPage[page]; IF lp = NIL THEN WriteEmptyPage[] ELSE WritePage[lp]; ENDLOOP; }; WriteCodeSeg: PROC [seg: MBVM.CodeSeg] = { nUnits: CARDINAL = IF seg.sph = NIL THEN 1 ELSE seg.sph.length; scriptBase: BootStartList.Base = data.scriptBase; index: BootStartList.SwapUnitIndex _ seg.index; v: PrincOps.InterimPageState = MapValueForSeg[seg]; lp: LONG POINTER; THROUGH [0..nUnits) DO su: LONG POINTER TO swapUnit BootStartList.Entry = @scriptBase[index]; IF scriptBase[su.parent].bootLoaded THEN EXIT; index _ index + SIZE[swapUnit BootStartList.Entry]; REPEAT FINISHED => RETURN; ENDLOOP; lp _ OpenSegForTransfer[seg.segment]; IF seg.sph = NIL THEN { BootloadedSegToLoadmap[seg, filePage, v.flags]; FOR page: CARDINAL IN [seg.base..seg.base+seg.pages) DO EnterPage[page: page, value: v]; WritePage[lp]; lp _ lp + wordsPerPage; ENDLOOP; } ELSE { index: BootStartList.SwapUnitIndex _ seg.index; THROUGH [0..nUnits) DO su: LONG POINTER TO swapUnit BootStartList.Entry = @scriptBase[index]; IF scriptBase[su.parent].bootLoaded THEN { BootloadedSwapUnitToLoadmap[index, filePage, v.flags, seg]; FOR i: CARDINAL IN CARDINAL[0..su.pages) DO EnterPage[page: scriptBase[su.parent].vmPage + su.base + i, value: v]; WritePage[lp]; lp _ lp + wordsPerPage; ENDLOOP; } ELSE lp _ lp + su.pages*wordsPerPage; index _ index + SIZE[swapUnit BootStartList.Entry]; ENDLOOP; }; CloseSegAfterTransfer[seg.segment]; }; WriteFileSeg: PROC [seg: MBVM.FileSeg] = { scriptBase: BootStartList.Base = data.scriptBase; su: LONG POINTER TO swapUnit BootStartList.Entry = @scriptBase[seg.index]; v: PrincOps.InterimPageState = MapValueForSeg[seg]; lp: LONG POINTER; IF ~scriptBase[su.parent].bootLoaded THEN RETURN; lp _ OpenSegForTransfer[seg.segment]; BootloadedSegToLoadmap[seg, filePage, v.flags]; FOR page: CARDINAL IN [seg.base..seg.base+seg.pages) DO EnterPage[page: page, value: v]; WritePage[lp]; lp _ lp + wordsPerPage; ENDLOOP; CloseSegAfterTransfer[seg.segment]; }; AppendDataSeg: PROC [seg: MBVM.DataSeg] = { IF ~AppendNecessary[@data.scriptBase[seg.index]] THEN RETURN; SegToLoadmap[seg, filePage]; FOR page: CARDINAL IN [seg.base..seg.base+seg.pages) DO lp: LONG POINTER = MBVM.GetPage[page]; IF lp = NIL THEN WriteEmptyPage[] ELSE WritePage[lp]; ENDLOOP; }; AppendCodeSeg: PROC [seg: MBVM.CodeSeg] = { lp: LONG POINTER; nUnits: CARDINAL = IF seg.sph = NIL THEN 1 ELSE seg.sph.length; index: BootStartList.SwapUnitIndex _ seg.index; scriptBase: BootStartList.Base = data.scriptBase; THROUGH [0..nUnits) DO su: LONG POINTER TO swapUnit BootStartList.Entry = @scriptBase[index]; IF AppendNecessary[su] THEN EXIT; index _ index + SIZE[swapUnit BootStartList.Entry]; REPEAT FINISHED => RETURN; ENDLOOP; lp _ OpenSegForTransfer[seg.segment]; IF seg.sph = NIL THEN { SegToLoadmap[seg, filePage]; THROUGH [0..seg.pages) DO WritePage[lp]; lp _ lp + wordsPerPage; ENDLOOP; } ELSE { index: BootStartList.SwapUnitIndex _ seg.index; THROUGH [0..nUnits) DO su: LONG POINTER TO swapUnit BootStartList.Entry = @scriptBase[index]; IF AppendNecessary[su] THEN { SwapUnitToLoadmap[index, filePage, seg]; THROUGH [0..su.pages) DO WritePage[lp]; lp _ lp + wordsPerPage; ENDLOOP; } ELSE lp _ lp + su.pages*wordsPerPage; index _ index + SIZE[swapUnit BootStartList.Entry]; ENDLOOP; }; CloseSegAfterTransfer[seg.segment]; }; AppendFileSeg: PROC [seg: MBVM.FileSeg] = { lp: LONG POINTER; IF ~AppendNecessary[@data.scriptBase[seg.index]] THEN RETURN; lp _ OpenSegForTransfer[seg.segment]; SegToLoadmap[seg, filePage]; IF data.debug THEN { loadmap: IO.STREAM = data.loadmap; index: BootStartList.SwapUnitIndex _ seg.index; loadmap.PutF["%sSwapUnits[", IO.card[26]]; FOR i: CARDINAL IN [0..seg.nUnits) DO loadmap.PutF["%n", IO.card[LOOPHOLE[index].LONG]]; IF i ~= seg.nUnits - 1 THEN loadmap.PutRope[", "]; index _ index + SIZE[swapUnit BootStartList.Entry]; ENDLOOP; loadmap.PutRope["]\N"]; }; FOR i: CARDINAL IN [0..seg.pages) DO WritePage[lp]; lp _ lp + wordsPerPage; ENDLOOP; CloseSegAfterTransfer[seg.segment]; }; AppendNecessary: PROC [su: LONG POINTER TO swapUnit BootStartList.Entry] RETURNS [BOOL] = {RETURN[~data.scriptBase[su.parent].bootLoaded]}; GermMDS: CARDINAL = 37000B; BootXferLocation: POINTER = LOOPHOLE[1376B]; GermPageCountLocation: POINTER = LOOPHOLE[1377B]; WriteGermFile: PUBLIC PROC = { data.typescript.PutRope["Writing germ file..."]; InitializeGermFile[]; data.nFilePages _ data.nResidentPages _ data.nBootLoadedPages _ WriteGerm[]; FinalizeGermFile[]; data.typescript.PutRope["finished writing.\N"]; IF data.etherFormat THEN MakeEtherFile[]; }; InitializeGermFile: PROC = { data.bootStream _ FileIO.Open[fileName: data.output, accessOptions: overwrite]; filePage _ 0; }; FinalizeGermFile: PROC = { fp: Segments.FP _ FileIO.CapabilityFromStream[data.bootStream]; file: Segments.FHandle; data.bootStream.Close[]; data.bootStream _ NIL; file _ Segments.InsertFile[@fp, Segments.Write]; Segments.SetFileTimes[file: file, create: data.buildTime]; Segments.ReleaseFile[file]; }; WriteGerm: PROC RETURNS [germPages: CARDINAL _ 0] = { segs: MBVM.Segs = MBVM.SortSegs[]; relocationPages: CARDINAL; RelocateGerm: PROC = { codeRelocation: LONG CARDINAL = Basics.LongMult[(relocationPages _ GermMDS - data.mdsBase), wordsPerPage]; RelocateOneModule: PROC [loadee: MB.BHandle, mth: BcdDefs.MTHandle] RETURNS [BOOL] = { gf: PrincOps.GlobalFrame; MBVM.CopyRead[from: loadee.mt[mth.gfi].frame, to: @gf, nwords: SIZE[PrincOps.GlobalFrame]]; gf.code.longbase _ gf.code.longbase + codeRelocation; MBVM.CopyWrite[to: loadee.mt[mth.gfi].frame, from: @gf, nwords: SIZE[PrincOps.GlobalFrame]]; RETURN[FALSE] }; [] _ MB.DoAllModules[RelocateOneModule]; }; IF data.debug THEN MB.DumpSegs[segs, "WRITING GERM"]; RelocateGerm[]; FOR i: CARDINAL IN [0..segs.length) DO germPages _ germPages + segs[i].pages; ENDLOOP; MBVM.Write[p: BootXferLocation, v: MB.StartControlLink[]]; MBVM.Write[p: GermPageCountLocation, v: germPages]; BootloadedHeadingToLoadmap["\N\NGERM FILE MAP\N\N"]; FOR i: CARDINAL IN [0..segs.length) DO WITH s: segs[i] SELECT FROM data => WriteGermData[@s, relocationPages]; code => WriteGermCode[@s, relocationPages]; file => ERROR; ENDCASE; ENDLOOP; data.loadmap.PutF["\N\NGerm file pages: %n\N", IO.card[germPages]]; }; WriteGermData: PROC [seg: MBVM.DataSeg, relocationPages: CARDINAL] = { v: PrincOps.InterimPageState _ MapValueForSeg[seg]; BootloadedSegToLoadmap[seg, filePage, v.flags, relocationPages]; FOR page: CARDINAL IN [seg.base..seg.base+seg.pages) DO lp: LONG POINTER = MBVM.GetPage[page]; IF lp = NIL THEN WriteEmptyPage[] ELSE WritePage[lp]; ENDLOOP; }; WriteGermCode: PROC [seg: MBVM.CodeSeg, relocationPages: CARDINAL] = { v: PrincOps.InterimPageState _ MapValueForSeg[seg]; lp: LONG POINTER _ OpenSegForTransfer[seg.segment]; BootloadedSegToLoadmap[seg, filePage, v.flags, relocationPages]; THROUGH [0..seg.pages) DO WritePage[lp]; lp _ lp + wordsPerPage; ENDLOOP; CloseSegAfterTransfer[seg.segment]; }; MapValueForSeg: PROC [seg: MBVM.Seg] RETURNS [PrincOps.InterimPageState] = { flags: PrincOps.PageFlags _ IF ~seg.info.readOnly THEN PrincOps.flagsClean ELSE PrincOps.flagsReadOnly; RETURN[PrincOps.InterimPageState[logSingleError: FALSE, flags: flags, realPage: 0]] }; OpenSegForTransfer: PROC [seg: Segments.SHandle] RETURNS [lp: LONG POINTER] = { Segments.SwapIn[seg]; lp _ Segments.SegmentAddress[seg]; }; CloseSegAfterTransfer: PROC [seg: Segments.SHandle] = INLINE {Segments.Unlock[seg]}; EnterPage: PROC [page: MBVM.Base, value: PrincOps.InterimPageState] = { entries: LONG POINTER TO ARRAY [0..0) OF BootFile.Entry; IF currentEntry = nEntries THEN AddTrailerPage[]; entries _ IF nEntries = BootFile.maxEntriesPerTrailer THEN @trailer.entries ELSE @header.entries; entries[currentEntry] _ [page: page, value: value]; currentEntry _ currentEntry + 1; }; AddTrailerPage: PROC = { stream: IO.STREAM = data.bootStream; IF trailer ~= NIL THEN trailerIndex _ WriteTrailerPage[] ELSE { trailer _ LOOPHOLE[NEW[PageOfWords]]; trailerIndex _ stream.GetIndex[]; }; stream.SetLength[trailerIndex+bytesPerPage]; stream.SetIndex[trailerIndex+bytesPerPage]; PrincOpsUtils.ZERO[LOOPHOLE[trailer], wordsPerPage]; trailer.version _ BootFile.currentVersion; nEntries _ BootFile.maxEntriesPerTrailer; currentEntry _ 0; data.loadmap.PutF["%6n Trailer Page\N", IO.card[filePage]]; filePage _ filePage + 1; }; WriteTrailerPage: PROC RETURNS [index: INT] = { stream: IO.STREAM = data.bootStream; index _ stream.GetIndex[]; stream.SetIndex[trailerIndex]; stream.UnsafePutBlock[ block: [base: LOOPHOLE[trailer], startIndex: 0, stopIndexPlusOne: bytesPerPage]]; stream.SetIndex[index]; }; WritePage: PROC [p: LONG POINTER] = { filePage _ filePage + 1; data.bootStream.UnsafePutBlock[block: [base: p, startIndex: 0, stopIndexPlusOne: bytesPerPage]]; }; WriteEmptyPage: PROC = { filePage _ filePage + 1; THROUGH [0..bytesPerPage) DO data.bootStream.PutChar['\000]; ENDLOOP; }; BootloadedHeadingToLoadmap: PROC [r: Rope.ROPE] = { loadmap: IO.STREAM = data.loadmap; loadmap.PutRope[r]; loadmap.PutRope[" File VM Pages Map Type Source[base,pages]\N"]; loadmap.PutRope[" Page Address (*=Pin) Flags\N"]; }; BootloadedSegToLoadmap: PROC [ seg: MBVM.Seg, filePage: MBVM.Base, flags: PrincOps.PageFlags, relocation: CARDINAL _ 0] = { loadmap: IO.STREAM = data.loadmap; BootloadedCommonToLoadmap[ filePage, seg.base.LONG + relocation, seg.pages, flags, data.germ OR (data.scriptBase[seg.index].info.state = resident), seg]; loadmap.PutChar[Ascii.CR]; }; BootloadedSwapUnitToLoadmap: PROC [ index: BootStartList.SwapUnitIndex, filePage: MBVM.Base, flags: PrincOps.PageFlags, seg: MBVM.Seg] = { loadmap: IO.STREAM = data.loadmap; su: LONG POINTER TO swapUnit BootStartList.Entry = @data.scriptBase[index]; BootloadedCommonToLoadmap[ filePage, data.scriptBase[su.parent].vmPage + su.base, su.pages, flags, su.info.state = resident, seg]; loadmap.PutF["[%n,%n]", IO.card[su.base], IO.card[su.pages]]; IF data.debug THEN loadmap.PutF[" SwapUnit[%n]", IO.card[LOOPHOLE[index, CARDINAL].LONG]]; loadmap.PutChar[Ascii.CR]; }; BootloadedCommonToLoadmap: PROC [ filePage: MBVM.Base, vmPage: PrincOps.PageNumber, pages: CARDINAL, flags: PrincOps.PageFlags, resident: BOOL, seg: MBVM.Seg] = { loadmap: IO.STREAM = data.loadmap; loadmap.PutF["%6n %8n %4n%g", IO.card[filePage], IO.card[vmPage*wordsPerPage], IO.card[pages], IO.rope[IF resident THEN "*" ELSE " "] ]; loadmap.PutF[" %g%g%g ", IO.rope[IF flags.readonly THEN "W" ELSE " "], IO.rope[IF flags.dirty THEN "D" ELSE " "], IO.rope[IF flags.referenced THEN "R" ELSE " "] ]; SegmentSourceToLoadmap[seg]; }; NonBootloadedHeadingToLoadmap: PROC [r: Rope.ROPE] = { loadmap: IO.STREAM = data.loadmap; loadmap.PutRope[r]; loadmap.PutRope[" File VM Pages Type Source[base,pages]\N"]; loadmap.PutRope[" Page Address\N"]; }; SegToLoadmap: PROC [seg: MBVM.Seg, backingPage: MBVM.Base] = { CommonToLoadmap[backingPage, seg.base.LONG, seg.pages, seg]; data.loadmap.PutChar[Ascii.CR]; }; SwapUnitToLoadmap: PROC [ index: BootStartList.SwapUnitIndex, backingPage: MBVM.Base, seg: MBVM.Seg] = { loadmap: IO.STREAM = data.loadmap; su: LONG POINTER TO swapUnit BootStartList.Entry = @data.scriptBase[index]; CommonToLoadmap[ backingPage, data.scriptBase[su.parent].vmPage + su.base, su.pages, seg]; loadmap.PutF["[%n,%n]", IO.card[su.base], IO.card[su.pages]]; IF data.debug THEN loadmap.PutF[" SwapUnit[%n]", IO.card[LOOPHOLE[index, CARDINAL].LONG]]; loadmap.PutChar[Ascii.CR]; }; CommonToLoadmap: PROC [ filePage: MBVM.Base, vmPage: PrincOps.PageNumber, pages: CARDINAL, seg: MBVM.Seg] = { data.loadmap.PutF["%6n %8n %4n ", IO.card[filePage], IO.card[vmPage*wordsPerPage], IO.card[pages] ]; SegmentSourceToLoadmap[seg]; }; SegmentSourceToLoadmap: PROC [seg: MBVM.Seg] = { loadmap: IO.STREAM = data.loadmap; file: Segments.FHandle; fileBase: CARDINAL; WITH s: seg SELECT FROM data => {loadmap.PutRope["data"]; RETURN}; code => {loadmap.PutRope["code "]; file _ s.file; fileBase _ s.fileBase}; file => {loadmap.PutRope["file "]; file _ s.file; fileBase _ s.fileBase}; ENDCASE; data.loadmap.PutF["%f[%n,%n]", IO.card[LOOPHOLE[file.LONG]], IO.card[fileBase], IO.card[seg.pages]]; }; MakeEtherFile: PROC = { inStream, outStream: IO.STREAM _ NIL; name: STRING _ [40]; bufferPages: CARDINAL = 50; bufferSpace: Space.Handle = Space.Create[bufferPages, Space.virtualMemory]; buffer: LONG POINTER = Space.LongPointer[bufferSpace]; PutEtherHeader: PROC [stream: IO.STREAM] = { etherHeader: EtherHeader _ [createTime: MesaToBCPLTime[data.buildTime]]; stream.UnsafePutBlock[ block: [base: @etherHeader, startIndex: 0, stopIndexPlusOne: 2*SIZE[EtherHeader]]]; stream.UnsafePutBlock[ block: [base: name, startIndex: 0, stopIndexPlusOne: 2*SIZE[StringBody[name.maxlength]]]]; THROUGH [2*(SIZE[EtherHeader]+SIZE[StringBody[name.maxlength]])..bytesPerPage) DO stream.PutChar['\000]; ENDLOOP; }; MesaToBCPLTime: PROC [t: Time.Packed] RETURNS [BCPLTime] = INLINE { ln: Basics.LongNumber = LOOPHOLE[t]; RETURN [[high: ln.highbits, low: ln.lowbits]] }; Space.Map[bufferSpace]; data.typescript.PutF["Writing ether %y file...", IO.bool[data.germ]]; {ENABLE UNWIND => { IF inStream ~= NIL THEN inStream.Close[]; IF outStream ~= NIL THEN outStream.Close[]; Space.Delete[bufferSpace]; }; ConvertUnsafe.AppendRope[to: name, from: data.output]; inStream _ FileIO.Open[fileName: data.output]; outStream _ FileIO.Open[ fileName: data.etherOutput, accessOptions: overwrite, createLength: inStream.GetLength[] + bytesPerPage ]; PutEtherHeader[outStream]; DO bytes: INT = inStream.UnsafeGetBlock[ block: [base: buffer, startIndex: 0, stopIndexPlusOne: bufferPages*bytesPerPage]]; IF bytes = 0 THEN EXIT; outStream.UnsafePutBlock[block: [base: buffer, startIndex: 0, stopIndexPlusOne: bytes]]; ENDLOOP; }; inStream.Close[]; outStream.Close[]; Space.Delete[bufferSpace]; data.typescript.PutRope["finished writing.\N"]; }; END. @MBOutput.mesa Edited by Sandman on 6-Aug-81 15:41:43 Edited by Lewis on 25-Sep-81 15:01:46 Edited by Levin on September 30, 1983 4:08 pm the following are implicit name(5): StringBody, fill(5+WordsForString[name]): ARRAY [5+WordsForString[name]..wordsPerPage) OF WORD _ ALL[0] Boot file (not germ) output Now set the create time to the desired value Germ file output Now set the create time to the desired value Output Subroutines reserved = FALSE (0) on a D0 means don't log single bit memory error create trailer page Loadmap Subroutines Ether Boot/Germ Output Ê&˜Jšœ™Jšœ&™&Jšœ%™%Jšœ-™-J˜šÏk ˜ Jšœœœ˜Jšœœ˜$Jšœœ ˜šœ œ˜J˜i—Jšœœ,˜?Jšœœ˜!Jšœœ˜*šœœ˜ Jšœ[œ"˜ƒ—Jšœœ=˜Ešœœ˜ J˜l—šœ œ˜Jšœm˜m—Jšœœ œ˜$Jšœœœ˜šœ œ˜Jšœ œY˜d—Jšœœ;˜FJšœœ ˜J˜—šœ ˜Jšœ*œœœ ˜]Jšœœ˜ —J˜Jš˜J˜Jšœœ˜ J˜Jšœœ˜/Jšœœ˜/J˜Jš œ œœœœ˜4J˜Jšœœ œ˜J˜Jšœœœ˜"Jšœ œœ˜$Jšœœ˜!Jšœ œ˜Jšœœœ˜J˜š œ œœ œœ˜.Jšœ œ˜Jšœœœ˜!J˜Jšœ™Jšœ™Jšœ[™[J˜J˜—Jš œ œœ œœ œ˜@J˜JšÏn œœœœ˜4J˜šž œœœ˜Jš œœœœœ˜[Jšœ œ˜ Jšœ œ˜Jšœ˜Jšœ˜ Jšœ˜J˜—Jšœ™J˜šžœœœœ˜3Jšœ*˜1J˜1Jšœ œ˜Jšœ˜šœœœ˜&Jšœœ˜Jšœ œœ7˜Jšœœ˜šœ˜šœ"œ˜*JšœœœœœœœÏc˜Dšœ˜ Jšœ5˜5—Jšœ9˜9šœ˜JšœH˜K—J˜——˜ Jš œœœ œœœ˜;J˜-šœ ˜Jšœ œœ3˜Fšœ"œ˜*šœ˜ Jšœ5˜5—Jšœ9˜9šœ˜JšœH˜K—J˜—Jšœœ˜3Jšœ˜—Jšœ˜—˜šœ"œ˜*šœ˜ Jšœ4˜4—Jšœ8˜8Jšœ&˜&J˜——Jšœ˜—Jšœ˜—JšœB˜Bšœœœ˜&Jšœœ˜Jšœ œœ7˜Jšœœ˜šœ˜šœœ˜Jšœ*˜*šœ'˜-J˜/—J˜#J˜——˜ Jš œœœ œœœ˜;J˜-šœ ˜Jšœ œœ3˜Fšœœ˜Jšœ*˜*šœ'˜-J˜/—Jšœ#˜#J˜—Jšœœ˜3Jšœ˜—Jšœ˜—šœ˜šœœ˜Jšœ*˜*šœ'˜-J˜/—J˜"J˜——Jšœ˜—Jš˜—J˜šœ˜J˜——šž œœœ˜Jšœ0˜0J˜Jšœ ˜ J˜Jšœ/˜/Jšœœ˜)Jšœ˜J˜—šžœœ˜˜J˜J˜J˜Jšœ4˜4šœœœ˜&šœ œ˜Jšœ˜J˜Jšœ˜Jšœ˜—Jš˜—šœS˜SJšœœœ˜X—šœ˜J˜——šž œœœ ˜*J˜1Jšœ œœ7˜JJ˜3Jšœ#œœ˜1JšœœœœœœœŸ˜JJ˜/šœœœ ˜7Jšœœœ˜J˜ Jšœœ˜Jšœœœœ˜5Jš˜—šœ˜J˜——šž œœœ ˜*Jš œœœ œœœ˜?J˜1J˜/J˜3Jšœœœ˜šœ ˜Jšœ œœ3˜FJšœ"œœ˜.Jšœœ˜3š˜Jšœœ˜—Jšœ˜—Jšœœ"˜%šœ œœ˜Jšœ/˜/šœœœ ˜7J˜ J˜J˜Jšœ˜—J˜—šœ˜J˜/šœ ˜Jšœ œœ3˜Fšœ"œ˜*Jšœ;˜;š œœœœ˜+JšœF˜FJ˜J˜Jšœ˜—J˜—Jšœ!˜%Jšœœ˜3Jšœ˜—J˜—J˜#J˜J˜—šž œœœ ˜*J˜1Jšœ œœ7˜JJ˜3Jšœœœ˜Jšœ#œœ˜1Jšœ%˜%J˜/šœœœ ˜7J˜ J˜J˜Jšœ˜—J˜#J˜J˜—šž œœœ ˜+Jšœ/œœ˜=J˜šœœœ ˜7Jšœœœœ˜&Jšœœœœ˜5Jšœ˜—šœ˜J˜——šž œœœ ˜+Jšœœœ˜Jš œœœ œœœ˜?J˜/J˜1šœ ˜Jšœ œœ3˜FJšœœœ˜!Jšœœ˜3š˜Jšœœ˜—Jšœ˜—J˜%šœ œœ˜Jšœ˜šœ˜Jšœ˜J˜Jšœ˜—J˜—šœ˜J˜/šœ ˜Jšœ œœ3˜Fšœœ˜Jšœ(˜(šœ˜Jšœ˜J˜Jšœ˜—J˜—Jšœ!˜%Jšœœ˜3Jšœ˜—J˜—J˜#J˜J˜—šž œœœ ˜+Jšœœœ˜Jšœ/œœ˜=Jšœœ"˜%J˜šœ œ˜Jšœ œœ˜"J˜/Jšœœ ˜*šœœœ˜%Jšœœœœ˜2Jšœœ˜2Jšœœ˜3Jšœ˜—Jšœ˜Jšœ˜—šœœœ˜$J˜J˜Jšœ˜—J˜#J˜J˜—š žœœœœœ˜HJšœœœ*˜B—J™Jšœ™J˜Jšœ œ ˜Jšœœœ˜,Jšœœœ˜1J˜šž œœœ˜Jšœ0˜0J˜JšœL˜LJ˜Jšœ/˜/Jšœœ˜)Jšœ˜J˜—šžœœ˜J˜OJšœ ˜ J˜J˜—šžœœ˜Jšœ œ0˜?J˜Jšœ˜Jšœ˜Jšœ,™,J˜0Jšœ:˜:J˜Jšœ˜J˜—šž œœœ œ ˜5Jšœœœ ˜"Jšœœ˜šž œœ˜šœœœ˜J˜J—š žœœ œ!œœ˜VJ˜Jšœ;œ˜[J˜5Jšœ<œ˜\Jšœœ˜ Jšœ˜—Jšœœ!˜(Jšœ˜—Jšœ œœ ˜5J˜Jš œœœœ(œ˜VJšœœ˜:Jšœ/˜3J˜4šœœœ˜&šœ œ˜J˜+J˜+Jšœœ˜Jšœ˜—Jš˜—Jšœ.œ˜Cšœ˜J˜——šž œœœœ˜FJ˜3J˜@šœœœ ˜7Jšœœœœ˜&Jšœœœœ˜5Jš˜—šœ˜J˜——šž œœœœ˜FJ˜3Jšœœœ#˜3J˜@šœ˜J˜J˜Jšœ˜—J˜#J˜J˜—Jšœ™J˜šžœœœœ ˜L˜Jšœœœ˜K—JšœD™DJšœ+œ˜SJšœ˜J˜—š žœœœœœ˜OJ˜J˜"J˜J˜—šžœœœ˜TJ˜—šž œœœ,˜GJš œ œœœœœ˜8Jšœœ˜1˜ Jšœ*œœ˜W—J˜3J˜ J˜J˜—šžœœ˜Jšœœœ˜$Jšœ œœ"˜8šœ˜Jšœ™Jšœ œœ˜%Jšœ!˜!J˜—J˜,J˜+Jšœœœ˜4J˜*J˜)J˜Jšœ)œ˜Jšœ&œ˜