-- Copyright (C) 1983  by Xerox Corporation. All rights reserved. 
-- ParmsFromEERom.mesa, HGM,  9-Oct-83  1:20:07

DIRECTORY
  Boot USING [Location],
  Checksum USING [ComputeChecksum],
  String USING [AppendChar],
  System USING [GetGreenwichMeanTime, GreenwichMeanTime],
  
  EERom USING [
    BootLocation, bootLocationVersion, Data, dataVersion, FetchBootLocation, FetchData,
    maxChars, StoreBootLocation, StoreData],
  Parms USING [];

 ParmsFromEERom: PROGRAM IMPORTS Checksum, String, System, EERom EXPORTS Parms =
  BEGIN
  
  Error: PUBLIC ERROR [reason: LONG STRING] = CODE;

  GetBootLocation: PUBLIC PROCEDURE RETURNS [Boot.Location, System.GreenwichMeanTime] =
    BEGIN
    data: EERom.BootLocation ← TRASH;
    EERom.FetchBootLocation[@data];
    IF ~BootLocationChecksumValid[@data] THEN ERROR Error["Bad Checksum"L];
    IF data.version # EERom.bootLocationVersion THEN ERROR Error["Bad Version"L];
    RETURN[data.location, data.write];
    END;
    
  WriteBootLocation: PUBLIC PROCEDURE [bootLocation: Boot.Location] =
    BEGIN
    copy: EERom.BootLocation ← TRASH;
    data: EERom.BootLocation ← [
      checksum: TRASH,
      write: System.GetGreenwichMeanTime[],
      location: bootLocation ];
    SetBootLocationChecksum[@data];
    EERom.StoreBootLocation[@data];
    EERom.FetchBootLocation[@copy];
    IF ~BootLocationChecksumValid[@copy] THEN ERROR Error["Read back has bad checksum"L];
    IF ~EqualBootLocation[@copy, @data] THEN ERROR Error["Read back didn't verify"L];
    END;

  
  BootLocationChecksumValid: PROCEDURE [location: POINTER TO EERom.BootLocation]
    RETURNS [ok: BOOLEAN] =
    BEGIN
    -- checksum is known to be the first word
    checksum: WORD = Checksum.ComputeChecksum[0, SIZE[EERom.BootLocation]-1, location+1];
    RETURN[checksum = location.checksum];
    END;
    
  SetBootLocationChecksum: PROCEDURE [location: POINTER TO EERom.BootLocation] =
    BEGIN
    -- checksum is known to be the first word
    location.checksum ← Checksum.ComputeChecksum[0, SIZE[EERom.BootLocation]-1, location+1];
    END;
    
  EqualBootLocation: PROCEDURE [a, b: POINTER]
    RETURNS [ok: BOOLEAN] =
    BEGIN
    FOR i: CARDINAL IN [0..SIZE[EERom.BootLocation]) DO
      IF a↑ # b↑ THEN RETURN[FALSE];
      ENDLOOP;
    RETURN[TRUE];
    END;
    
    
    
  GetMaxChars: PUBLIC PROCEDURE RETURNS [CARDINAL] =
    BEGIN
    RETURN[EERom.maxChars];
    END;

  GetParms: PUBLIC PROCEDURE [s: LONG STRING] RETURNS [System.GreenwichMeanTime] =
    BEGIN
    data: EERom.Data ← TRASH;
    EERom.FetchData[@data];
    IF ~DataChecksumValid[@data] THEN ERROR Error["Bad Checksum"L];
    IF data.version # EERom.dataVersion THEN ERROR Error["Bad Version"L];
    FOR i: CARDINAL IN [0..data.used) DO
      String.AppendChar[s, data.data[i]];
      ENDLOOP;
    RETURN[data.write];
    END;

  WriteParms: PUBLIC PROCEDURE [s: LONG STRING] =
    BEGIN
    verify: EERom.Data ← TRASH;
    data: EERom.Data ← [
      checksum: TRASH,
      write: System.GetGreenwichMeanTime[],
      used: s.length ];
    FOR i: CARDINAL IN [0..s.length) DO data.data[i] ← s[i]; ENDLOOP;
    SetDataChecksum[@data];
    EERom.StoreData[@data];
    EERom.FetchData[@verify];
    IF ~DataChecksumValid[@verify] THEN ERROR Error["Read back has bad checksum"L];
    IF verify # data THEN ERROR Error["Read back didn't verify"L];
    END;
  
  DataChecksumValid: PROCEDURE [data: POINTER TO EERom.Data] RETURNS [ok: BOOLEAN] =
    BEGIN
    -- checksum is known to be the first word
    checksum: WORD = Checksum.ComputeChecksum[0, SIZE[EERom.Data]-1, data+1];
    RETURN[checksum = data.checksum];
    END;
    
  SetDataChecksum: PROCEDURE [data: POINTER TO EERom.Data] =
    BEGIN
    -- checksum is known to be the first word
    data.checksum ← Checksum.ComputeChecksum[0, SIZE[EERom.Data]-1, data+1];
    END;
    
  END.