SDP.mesa
last edited by Levin on August 16, 1983 10:30 am
DIRECTORY
Boot USING [Location, LVBootFiles],
BootFile USING [
currentVersion, Entry, Header, maxEntriesPerHeader, maxEntriesPerTrailer, MDSIndex, Trailer],
BootStartList USING [Base, versionID],
ConvertUnsafe USING [AppendRope, ToRope],
Device USING [Type],
Directory USING [Error, Lookup],
Environment USING [PageNumber, wordsPerPage],
File USING [Capability, nullCapability, nullID, PageCount, PageNumber, read, write],
Inline USING [LongDivMod, LongNumber, LowHalf],
IO USING [GetToken, EndOfStream, PutF, PutRope, RIS, rope, STREAM, WhiteSpace],
PhysicalVolume USING [
GetAttributes, GetContainingPhysicalVolume, Handle, ID, InterpretHandle],
Rope USING [Concat, Find, Length, ROPE],
Space USING [CopyIn, CopyOut, Create, Delete, Handle, LongPointer, Map, virtualMemory],
SpecialVolume USING [GetLogicalVolumeBootFiles],
Commander USING [CommandProc, Register],
Volume USING [GetLabelString, GetNext, ID, maxNameLength, nullID, TypeSet];
SDP: PROGRAM
IMPORTS
ConvertUnsafe, Directory, Inline, IO, PhysicalVolume, Rope, Space, SpecialVolume, Commander, Volume
SHARES File =
BEGIN
BootHeadPtr: TYPE = LONG POINTER TO BootFile.Header;
Outcome: TYPE = {success, startListHeaderHasBadVersion, notInitialBootFile};
SetDebuggerPointers: Commander.CommandProc = TRUSTED {
commandLine: IO.STREAM = IO.RIS[cmd.commandLine];
typescript: IO.STREAM = cmd.out;
FindDebugger: PROC RETURNS [debugger: Volume.ID ← Volume.nullID] = {
debugTypeOnly: Volume.TypeSet = [debugger: TRUE];
DO
debuggerBootFiles: Boot.LVBootFiles;
IF (debugger ← Volume.GetNext[debugger, debugTypeOnly]) = Volume.nullID THEN EXIT;
SpecialVolume.GetLogicalVolumeBootFiles[debugger, @debuggerBootFiles];
IF debuggerBootFiles[pilot].fID ~= File.nullID AND
debuggerBootFiles[debugger].fID ~= File.nullID AND
debuggerBootFiles[debuggee].fID ~= File.nullID THEN {
debuggerNameS: STRING ← [Volume.maxNameLength];
Volume.GetLabelString[debugger, debuggerNameS];
debuggerName ← ConvertUnsafe.ToRope[debuggerNameS];
EXIT
};
ENDLOOP;
};
debuggerName: Rope.ROPENIL;
debugger: Volume.ID = FindDebugger[];
fileName: Rope.ROPENIL;
fileNameS: STRING ← [100];
debuggeeFile: File.Capability ← File.nullCapability;
fileName ← commandLine.GetToken[IO.WhiteSpace ! IO.EndOfStream => CONTINUE];
SELECT TRUE FROM
fileName.Length[] = 0 => fileName ← "BasicCedarDorado.boot";
fileName.Find["."] = -1 => fileName ← fileName.Concat[".boot"];
ENDCASE;
ConvertUnsafe.AppendRope[to: fileNameS, from: fileName];
debuggeeFile ← Directory.Lookup[fileNameS ! Directory.Error => CONTINUE];
IF debuggeeFile = File.nullCapability THEN {
typescript.PutF["'%g' cannot be found./N", IO.rope[fileName]];
RETURN
};
IF debugger = Volume.nullID THEN {
typescript.PutRope["No installed debugger can be found./N"];
RETURN
};
debuggeeFile.permissions ← File.read+File.write;
IF SetDebugger[debuggeeFile, 1, debugger] = success THEN
typescript.PutF[
"'%g' will now world-swap to the debugger installed on volume '%g'.\N",
IO.rope[fileName], IO.rope[debuggerName]]
ELSE typescript.PutF["'%g' is an unsuitable boot file./N", IO.rope[fileName]];
};
SetDebugger: PROC [
debuggeeFile: File.Capability, debuggeePage: File.PageNumber, debugger: Volume.ID]
RETURNS [outcome: Outcome] = {
bootSpace: Space.Handle = Space.Create[1, Space.virtualMemory];
pBootHeader: BootHeadPtr = Space.LongPointer[bootSpace];
BEGIN ENABLE UNWIND => Space.Delete[bootSpace];
Space.Map[bootSpace];
Space.CopyIn[bootSpace, [debuggeeFile, debuggeePage]];
SELECT TRUE FROM
pBootHeader.version ~= BootFile.currentVersion =>
outcome ← startListHeaderHasBadVersion;
pBootHeader.continuation.kind ~= initial =>
outcome ← notInitialBootFile;
ENDCASE => {
filePage: File.PageNumber ← debuggeePage + 1; -- start at page following header
pStartListHeader: BootStartList.Base;
bufferSpace: Space.Handle = Space.Create[1, Space.virtualMemory];
BEGIN
ENABLE UNWIND => Space.Delete[bufferSpace];
FindStartListHeader: PROC = --INLINE-- {
buffer: LONG POINTER = Space.LongPointer[bufferSpace];
pTrailer: LONG POINTER TO BootFile.Trailer = LOOPHOLE[buffer];
pagesRemaining: File.PageCount ← pBootHeader.countData;
entries: LONG DESCRIPTOR FOR ARRAY OF BootFile.Entry;
slPage: Environment.PageNumber;
slOffset: [0..377B];
PointerMunge: PROC [p: POINTER, n: BootFile.MDSIndex] = INLINE {
ln: Inline.LongNumber = [num[lowbits: LOOPHOLE[p], highbits: n]];
[slPage, slOffset] ← Inline.LongDivMod[ln.lc, Environment.wordsPerPage];
};
PointerMunge[
pBootHeader.pStartListHeader,
WITH pBootHeader.continuation SELECT FROM
initial => mdsi, ENDCASE => ERROR
];
Space.Map[bufferSpace];
entries ← DESCRIPTOR[
@pBootHeader.entries,
Inline.LowHalf[MIN[pagesRemaining, BootFile.maxEntriesPerHeader]]];
DO
FOR i: CARDINAL IN [0..LENGTH[entries]) DO
IF entries[i].page = slPage THEN {filePage ← filePage + i; GO TO found};
ENDLOOP;
filePage ← filePage + LENGTH[entries];
pagesRemaining ← pagesRemaining - LENGTH[entries];
IF pagesRemaining = 0 THEN ERROR;
Space.CopyIn[bufferSpace, [debuggeeFile, filePage]];
filePage ← filePage.SUCC;
entries ← DESCRIPTOR[
@pTrailer.entries,
Inline.LowHalf[MIN[pagesRemaining, BootFile.maxEntriesPerTrailer]]];
REPEAT
found => NULL;
ENDLOOP;
Space.CopyIn[bufferSpace, [debuggeeFile, filePage]];
pStartListHeader ← LOOPHOLE[buffer + slOffset];
};
FindStartListHeader[];
SELECT TRUE FROM
pStartListHeader.version ~= BootStartList.versionID =>
outcome ← startListHeaderHasBadVersion;
ENDCASE => {
pv: PhysicalVolume.ID = PhysicalVolume.GetContainingPhysicalVolume[debugger];
h: PhysicalVolume.Handle = PhysicalVolume.GetAttributes[pv].instance;
dT: Device.Type = PhysicalVolume.InterpretHandle[h].type;
dO: --DeviceOrdinal--CARDINAL = PhysicalVolume.InterpretHandle[h].index;
debuggerBootFiles: Boot.LVBootFiles;
SpecialVolume.GetLogicalVolumeBootFiles[debugger, @debuggerBootFiles];
pStartListHeader.locDebuggerMicrocode ← LOOPHOLE[Boot.Location[
deviceType: dT, deviceOrdinal: dO, vp: disk[debuggerBootFiles[softMicrocode]]]];
pStartListHeader.locDebuggerGerm ← LOOPHOLE[Boot.Location[
deviceType: dT, deviceOrdinal: dO, vp: disk[debuggerBootFiles[germ]]]];
pStartListHeader.locDebugger ← LOOPHOLE[Boot.Location[
deviceType: dT, deviceOrdinal: dO, vp: disk[debuggerBootFiles[debugger]]]];
pStartListHeader.locDebuggee ← LOOPHOLE[Boot.Location[
deviceType: dT, deviceOrdinal: dO, vp: disk[debuggerBootFiles[debuggee]]]];
Space.CopyOut[bufferSpace, [debuggeeFile, filePage]];
outcome ← success;
};
Space.Delete[bufferSpace];
END;
};
END;
Space.Delete[bootSpace];
};
Commander.Register["SDP", SetDebuggerPointers, NIL];
END.