DIRECTORY Basics USING [HighHalf, LowHalf, UnsafeBlock], Commander USING [CommandProc, Register], DoveInputOutput USING [ Poke ], FS USING [ StreamOpen ], IO USING [ CharClass, EndOfStream, GetTokenRope, RIS, STREAM, UnsafeGetBlock], Rope USING [ROPE], SparcSoftcardOps, SparcSoftcard; SparcSoftcardLoader: CEDAR PROGRAM IMPORTS Basics, Commander, DoveInputOutput, FS, IO, SparcSoftcardOps ~ BEGIN ROPE: TYPE ~ Rope.ROPE; aDotOutIdentificationByte: CARD16 ~ 0; aDotOutEntryPointByte: CARD16 ~ 14H; aDotOutBssSizeByte: CARD16 ~ 0CH; aDotOutHeaderSizeByte: CARD16 ~ 20H; aDotOutIdentificationValue: CARD32 ~ 0103010BH; InsertResetPointer: PUBLIC PROC [resetVector: CARD32] ~ { instruction: CARD32 _ 10800000H; -- ba 0 IF resetVector >= 1000000H THEN ERROR; -- verify max offest instruction _ instruction + resetVector/4; -- add offsett DoveInputOutput.Poke[SparcSoftcard.cedarBackDoorBaseByte/2, Basics.HighHalf[instruction]]; DoveInputOutput.Poke[SparcSoftcard.cedarBackDoorBaseByte/2 + 1, Basics.LowHalf[instruction]]; instruction _ 01000000H; -- nop DoveInputOutput.Poke[SparcSoftcard.cedarBackDoorBaseByte/2 + 2, Basics.HighHalf[instruction]]; DoveInputOutput.Poke[SparcSoftcard.cedarBackDoorBaseByte/2 + 3, Basics.LowHalf[instruction]]; }; CmdTokenBreak: PROC [char: CHAR] RETURNS [IO.CharClass] = { IF char = '_ THEN RETURN [break]; IF char = ' OR char = '\t OR char = ', OR char = '; OR char = '\n THEN RETURN [sepr]; RETURN [other]; }; GetCmdToken: PROC [stream: IO.STREAM] RETURNS [rope: ROPE] = { rope _ NIL; rope _ stream.GetTokenRope[CmdTokenBreak ! IO.EndOfStream => CONTINUE].token; }; SparcSoftcardLoaderProc: Commander.CommandProc ~ { GetLong: PROC [byteAddress: CARD16] RETURNS [result: CARD32] = { IF (byteAddress MOD 4) # 0 THEN ERROR; result _ buffer[byteAddress/2] * 65536 + buffer[byteAddress/2 + 1]; }; SetOneMoreMapPage: PROC ~ { backdoorEntry.virtualAddressByte _ SparcSoftcard.cedarBackDoorBaseByte; superTextEntry.virtualAddressByte _ loadAddress; superDataEntry.virtualAddressByte _ loadAddress; backdoorEntry.realAddressByte _ loadAddress + SparcSoftcard.cedarMemoryExtensionSizeByte; superTextEntry.realAddressByte _ loadAddress + SparcSoftcard.cedarMemoryExtensionSizeByte; superDataEntry.realAddressByte _ loadAddress + SparcSoftcard.cedarMemoryExtensionSizeByte; SparcSoftcardOps.WriteMapEntry[backdoorEntry]; SparcSoftcardOps.WriteMapEntry[superTextEntry]; SparcSoftcardOps.WriteMapEntry[superDataEntry]; }; in: IO.STREAM _ IO.RIS[cmd.commandLine]; fileName: ROPE _ GetCmdToken[in]; inputFile: IO.STREAM _ FS.StreamOpen[fileName: fileName, accessOptions: $read]; startAddress, loadAddress, bssSize: CARD32; backdoorEntry, superTextEntry, superDataEntry: SparcSoftcardOps.MapEntry; backdoorPointerWord16: CARD32; bufSize: NAT = 1000H; buffer: ARRAY [0..bufSize/2) OF CARD16; block: Basics.UnsafeBlock; readSize: CARD16; TRUSTED { block _ [base: @buffer, count: bufSize]; readSize _ IO.UnsafeGetBlock[inputFile, block]; }; IF readSize # bufSize THEN ERROR; IF GetLong[aDotOutIdentificationByte] # aDotOutIdentificationValue THEN ERROR; startAddress _ GetLong[aDotOutEntryPointByte]; IF (startAddress MOD SparcSoftcard.softcardPageSizeByte) # aDotOutHeaderSizeByte THEN ERROR; loadAddress _ startAddress - aDotOutHeaderSizeByte; bssSize _ GetLong[aDotOutBssSizeByte]; SparcSoftcardOps.SparcReset[]; SparcSoftcardOps.SparcCacheDisable[]; backdoorEntry.vMSpace.name _ cP; superTextEntry.vMSpace.name _ sparcSuperProgram; superDataEntry.vMSpace.name _ sparcSuperData; backdoorEntry.virtualAddressByte _ SparcSoftcard.cedarBackDoorBaseByte; backdoorEntry.realAddressByte _ SparcSoftcard.cedarMemoryExtensionSizeByte; SparcSoftcardOps.WriteMapEntry[backdoorEntry]; superTextEntry.virtualAddressByte _ 0; superTextEntry.realAddressByte _ SparcSoftcard.cedarMemoryExtensionSizeByte; SparcSoftcardOps.WriteMapEntry[superTextEntry]; superDataEntry.virtualAddressByte _ 0; superDataEntry.realAddressByte _ SparcSoftcard.cedarMemoryExtensionSizeByte; SparcSoftcardOps.WriteMapEntry[superDataEntry]; InsertResetPointer[startAddress]; WHILE readSize = bufSize DO IF (loadAddress MOD SparcSoftcard.softcardPageSizeByte) = 0 THEN { SetOneMoreMapPage[]; backdoorPointerWord16 _ SparcSoftcard.cedarBackDoorBaseByte/2; }; FOR i: NAT IN [0..bufSize/2) DO DoveInputOutput.Poke[backdoorPointerWord16, buffer[i]]; backdoorPointerWord16 _ backdoorPointerWord16 + 1; ENDLOOP; TRUSTED { readSize _ IO.UnsafeGetBlock[inputFile, block]; }; loadAddress _ loadAddress + bufSize; ENDLOOP; IF readSize # 0 THEN ERROR; WHILE bssSize > 0 DO IF (loadAddress MOD SparcSoftcard.softcardPageSizeByte) = 0 THEN { SetOneMoreMapPage[]; backdoorPointerWord16 _ SparcSoftcard.cedarBackDoorBaseByte/2; }; FOR i: NAT IN [0..bufSize/2) DO DoveInputOutput.Poke[backdoorPointerWord16, 0]; backdoorPointerWord16 _ backdoorPointerWord16 + 1; ENDLOOP; loadAddress _ loadAddress + bufSize; bssSize _ bssSize - bufSize; ENDLOOP; IF bssSize # 0 THEN ERROR; backdoorEntry.virtualAddressByte _ SparcSoftcard.cedarBackDoorBaseByte; backdoorEntry.realAddressByte _ SparcSoftcard.cedarMemoryExtensionSizeByte; SparcSoftcardOps.WriteMapEntry[backdoorEntry]; SparcSoftcardOps.SparcResetAndStart[]; }; Commander.Register[ key: "SparcSoftcardLoader", proc: SparcSoftcardLoaderProc, doc: "Loads a a.out file into the SparcSoftcard memory"]; END. DSparcSoftcardLoader.mesa Copyright Σ 1987 by Xerox Corporation. All rights reserved. First created by Christophe Cuenod, September 9, 1988 10:35:45 am PDT Loads a single a.out file into the SparcSoftcard Basics USING [BITAND, BITNOT, HighHalf, LowHalf, UnsafeBlock], Insert by hand the instruction ba resetVector followed by nop IndicateVMSize: PUBLIC PROC [sparcVMSize: CARD32] ~ { Insert by hand the size of the VM at address 8 (byte address) DoveInputOutput.Poke[SparcSoftcard.cedarBackDoorBaseByte/2 + 4, Basics.HighHalf[sparcVMSize]]; DoveInputOutput.Poke[SparcSoftcard.cedarBackDoorBaseByte/2 + 5, Basics.LowHalf[sparcVMSize]]; }; Always on the same backdoor page Maximum size allowed by the compiler Reads first the beginning of the file to check the header and find out the loading address File way too small Bad magic number or tool version Probably bad linking. The entry point has to be the first effective instruction. Reset the Sparc and the cache Set the first map pages The first page of backdoor points to the begining of free memory The first page of sparcSuperProgram points to the begining of free memory The first page of sparcSuperData points to the begining of free memory Insert the reset pointer Transfert the data and set additional map pages if needed Set one more map page. the file has an odd length (ie non multiple of softcardPageSizeByte) Zero bss Set one more map page. the bss has an odd length (ie non multiple of softcardPageSizeByte) For debug replace the first page of backdoor to the begining of free memory Start the sparc Registration Κ&˜code•Mark outsideHeaderšœ™Kšœ<™Kšœœ"˜.Kšœ œ˜(Kšœœ ˜Kšœœ˜Kšœœ)œœ˜NKšœœœ˜Kšœ˜Kšœ˜—K˜KšΟnœœ˜"Kšœ%œœ˜DK˜šœ˜K˜Kšœœœ˜K˜Kšœœ˜&Kšœœ˜$Kšœœ˜!K˜Kšœœ˜$Kšœœ ˜/K˜K˜šžœœœœ˜9Kšœ=™=Kšœ œΟc˜(KšœœœŸ˜K– "cedar" stylešœœ˜ K– "cedar" stylešœ+œœ˜MKšœ˜—K– "cedar" style˜šžœ˜2K˜– "cedar" styleš žœœœœ œ˜@Jšœœœœ˜&JšœC˜CKšœ˜—K˜šžœœ˜šœG˜GJ™ —Jšœ0˜0Jšœ0˜0JšœY˜YJšœZ˜ZJšœZ˜ZJšœ.˜.Jšœ/˜/Jšœ/˜/K˜—K˜Kš œœœœœ˜(Kšœ œ˜!Jšœ œœœ6˜OJšœ$œ˜+JšœI˜IJšœœ˜šœ œ ˜J™$—Jšœœœœ˜'Jšœ˜Jšœ œ˜J˜J™ZJ˜šœ˜ Jšœ(˜(Kšœ œ"˜/K˜—šœœœ˜!K™—šœAœœ˜NJ™ —Jšœ.˜.šœœ=œœ˜\J™P—Jšœ3˜3Jšœ&˜&K˜™K˜Kšœ˜Kšœ%˜%K˜—™K˜Jšœ ˜ Jšœ0˜0Jšœ-˜-J˜JšœG˜GJšœK˜Kšœ.˜.J™A—K˜Jšœ&˜&JšœL˜Lšœ/˜/JšœJ™J—K˜Jšœ&˜&JšœL˜Lšœ/˜/JšœG™G—K˜—™J™Jšœ!˜!—J™J™™9J˜šœ˜šœœ)œ˜BJ™Kšœ˜Jšœ>˜>J˜—šœœœ˜Jšœ7˜7Jšœ2˜2Jšœ˜—šœ˜ Jšœ œ"˜/J˜—Jšœ œ œ˜$Jšœ˜—J˜šœœœ˜JšœD™D——J˜J˜˜K™—™K™šœ ˜šœœ)œ˜BJ™Kšœ˜Jšœ>˜>J˜—šœœœ˜Jšœ/˜/Jšœ2˜2Jšœ˜—Jšœ œ œ˜$Jšœœœ˜Jšœ˜—J˜šœ œœ˜JšœC™C—K™—™KK™JšœG˜GJšœK˜KJšœ.˜.—K™™K™Jšœ&˜&—šœ˜K™K™———head™ šœ˜Jšœt˜tK™K™——K˜Kšœ˜J˜—…—δ"N