-- 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.