-- Copyright (C) 1983 by Xerox Corporation. All rights reserved. -- FixBootFileChecksum.mesa, HGM, 8-Jan-83 12:57:34 DIRECTORY Checksum USING [ComputeChecksum], Environment USING [wordsPerPage], FormSW USING [ AllocateItemDescriptor, ClientItemsProcType, CommandItem, Display, newLine, NumberItem, ProcType, StringItem], Heap USING [systemZone], Inline USING [BITNOT, LowHalf], MFile USING [Error, GetLength, Handle, ReadWrite], MSegment USING [Address, Create, Delete, Handle], Runtime USING [GetBcdTime], String USING [AppendString], Time USING [Append, Unpack], Tool USING [Create, MakeSWsProc, MakeFormSW], ToolWindow USING [TransitionProcType], UserTerminal USING [BlinkDisplay], Window USING [Handle]; FixBootFileChecksum: PROGRAM IMPORTS Checksum, FormSW, Heap, Inline, MFile, MSegment, Runtime, String, Time, Tool, UserTerminal = BEGIN z: UNCOUNTED ZONE = Heap.systemZone; form: Window.Handle; fileName: LONG STRING ← NIL; oldCS, oldValue, newCS, newValue: WORD ← 0; Init: PROCEDURE = BEGIN herald: STRING = [100]; String.AppendString[herald, "FixBootFileChecksum of "L]; Time.Append[herald, Time.Unpack[Runtime.GetBcdTime[]]]; [] ← Tool.Create[ name: herald, makeSWsProc: MakeSWs, clientTransition: ClientTransition]; END; Smash: FormSW.ProcType = BEGIN file: MFile.Handle ← NIL; seg: MSegment.Handle; words: LONG CARDINAL; buffer: LONG POINTER; file ← MFile.ReadWrite[fileName, [], null ! MFile.Error => CONTINUE]; IF file = NIL THEN BEGIN UserTerminal.BlinkDisplay[]; RETURN; END; words ← (MFile.GetLength[file] + 1)/2; seg ← MSegment.Create[file, [], 0]; buffer ← MSegment.Address[seg]; BEGIN loc: LONG POINTER ← buffer + words - 1; IF words > 100*Environment.wordsPerPage THEN BEGIN hunk: CARDINAL ← 20*Environment.wordsPerPage; finger: LONG POINTER ← buffer; left: LONG CARDINAL ← words; oldCS ← 0; UNTIL left = 0 DO IF left < hunk THEN hunk ← Inline.LowHalf[left]; oldCS ← Checksum.ComputeChecksum[oldCS, hunk, finger]; left ← left - hunk; finger ← finger + hunk; ENDLOOP; END ELSE oldCS ← Checksum.ComputeChecksum[0, Inline.LowHalf[words], buffer]; oldValue ← loc↑; newValue ← NewValueToMakeChecksumZero[oldCS, oldValue, words - 1, words]; loc↑ ← newValue; IF words > 100*Environment.wordsPerPage THEN BEGIN hunk: CARDINAL ← 20*Environment.wordsPerPage; finger: LONG POINTER ← buffer; left: LONG CARDINAL ← words; newCS ← 0; UNTIL left = 0 DO IF left < hunk THEN hunk ← Inline.LowHalf[left]; newCS ← Checksum.ComputeChecksum[newCS, hunk, finger]; left ← left - hunk; finger ← finger + hunk; ENDLOOP; END ELSE newCS ← Checksum.ComputeChecksum[0, Inline.LowHalf[words], buffer]; END; MSegment.Delete[seg]; FormSW.Display[form]; END; MakeSWs: Tool.MakeSWsProc = BEGIN form ← Tool.MakeFormSW[window: window, formProc: MakeForm]; END; MakeForm: FormSW.ClientItemsProcType = BEGIN nParams: CARDINAL = 6; items ← FormSW.AllocateItemDescriptor[nParams]; items[0] ← FormSW.CommandItem[ tag: "Smash"L, proc: Smash, place: FormSW.newLine]; items[1] ← FormSW.StringItem[tag: "Filename"L, string: @fileName, inHeap: TRUE]; items[2] ← FormSW.NumberItem[ tag: "OldCS"L, value: @oldCS, radix: octal, place: FormSW.newLine]; items[3] ← FormSW.NumberItem[ tag: "OldValue"L, value: @oldValue, radix: octal]; items[4] ← FormSW.NumberItem[ tag: "NewCS"L, value: @newCS, radix: octal, place: FormSW.newLine]; items[5] ← FormSW.NumberItem[ tag: "NewValue"L, value: @newValue, radix: octal]; RETURN[items, TRUE]; END; ClientTransition: ToolWindow.TransitionProcType = BEGIN SELECT TRUE FROM old = inactive => fileName ← z.NEW[StringBody[10]]; new = inactive => z.FREE[@fileName]; ENDCASE; END; NewValueToMakeChecksumZero: PROCEDURE [ oldChecksum: WORD, oldValue: WORD, offsetOfOldValue: LONG CARDINAL, -- words length: LONG CARDINAL] RETURNS [newValue: WORD] = BEGIN newValue ← OnesAdd[ LeftCycle[OnesSub[0, oldChecksum], offsetOfOldValue - length], oldValue] END; OnesAdd: PROCEDURE [a, b: CARDINAL] RETURNS [c: CARDINAL] = INLINE BEGIN c ← a + b; IF c < a THEN c ← c + 1; IF c = 177777B THEN c ← 0; END; OnesSub: PROCEDURE [a, b: CARDINAL] RETURNS [CARDINAL] = INLINE BEGIN RETURN[OnesAdd[a, Inline.BITNOT[b]]]; END; LeftCycle: PROCEDURE [a: WORD, b: LONG INTEGER] RETURNS [c: CARDINAL] = INLINE BEGIN n: LONG INTEGER ← b MOD 16; c ← a; IF b < 0 THEN n ← n + 16; UNTIL n = 0 DO IF c < 100000B THEN c ← c*2 ELSE c ← c*2 + 1; n ← n - 1; ENDLOOP; END; Init[]; END.