Flash ROM Programming of the new USR Courier Modems
---------------------------------------------------

Note: Do not try anything described in this text without having a
      working SDL.EXE at hand. Any error at an arbitrary stage can
      result in erasure of the flash ROM.

Before you can feed new data to the flash ROM you will have to get
in touch with your modem. For this purpose use the undocumented
^BE^GHmX^I^H command:

1. Send the character sequence

        AT^BE^GHmX^I^H

   to the modem, where ^ marks a control character (so it is ten
   characters altogether), *without* a terminating carriage
   return. The modem acknowledges this with the character 3Fh,
   E3h, or E4h. A look at the modem shows something happening: the
   MR LED is off now. You have ten seconds to perform steps (2)
   through (4). If nothing has happened by then the modem will
   assume a timeout and return to normal operations.

2. The echo-safe echo test.

   To ensure that no hacker is listening in and recording the
   programming sequence, both computer and modem then change the
   bitrate twice. First, switch to 19200bps and send a 'Q' to the
   modem. Wait about 100ms, flush the input buffer, switch to
   9600bps, and--ho!--the 'Q' sent at 19200bps will be returned at
   9600bps.

3. Immediately afterwards the original bit rate is restored. The
   modem sends four additional bytes to the computer. Assuming a
   Dual Standard V.34 Ready they are as follows:

      00h  Country code. SDL.EXE uses this to ensure that the bad
           guys do not upload the American firmware to a PTT-
           approved modem. 00h or E2h mean North America.
           (Possibly only one of these means North America and the
           other one "any country".)

      0Dh  Modem type. #13 is a Courier Dual Standard V.34 Ready.
           The same firmware can also be loaded into modem types
           2, 5, 9, or 12.

      00h  This must be zero. Conceivably, this is the version
           number of the firmware programming scheme.

      00h  (Reserved; currently no meaning.)

4. The next byte tells the modem how many 128k-banks of the flash
   ROM to erase:

      00h  Nothing is erased at all. Can be used to abort the
           operation in case a problem has occured.

      02h  The range C0000-FFFFF is erased (for transfer of old
           pre-V.34 firmware or a new loader).

      04h  All of the ROM, 80000-FFFFF, is erased (for transfer of
           V.34 firmware).

   Subsequently a 2-byte checksum is transmitted which will be
   required for step (7) (see below). The algorithm to calculate
   this checksum will be described below. The checksums for the
   SDL releases available at the time of writing are:

     SDL 17.06.94 (firmware)    0Bh / 11h
     SDL 17.08.94 (firmware)    FBh / E1h
                  (loader)      49h / E8h

   If you have sent 00h to abort the operation a 2-byte dummy
   checksum must still be appended.

   The modem acknowledges the erasure command with 15h.
   (Details on the loader: see the section after the next one.)

5. The modem now attemps to clear the specified ROM range and
   returns the result of the operation:

      16h  =  erasure complete
      1Bh  =  block erase error
      1Dh  =  bad programming voltage

6. After successful erasure the ROM can be reprogrammed. This is
   accomplished by simply transmitting all of the new ROM image en
   bloc to the modem, using XON/XOFF flow control.

   If the programming has been successful, the modem will return
   14h. Otherwise it will produce one of the following error
   codes:

      18h  =  bad line checksum
      19h  =  bad CRC
      1Ah  =  inter-gap timeout
      1Ch  =  write error
      1Dh  =  bad programming voltage

   The error codes can also occur anytime during the transfer. In
   this case the programming must be aborted at once and must be
   repeated completely.

7. Finally the modem calculates a CRC over the data block and
   acknowledges this with 14h in case of success or reports 19h,
   respectively, if the checksum is incorrect. The calculation can
   run for a maximum of 6 seconds.



Modem Firmware
--------------

If you have been following this text closely, you certainly have
been wondering how the modem recognizes the end of the firmware
data. The solution is simple: apart from the actual firmware the
image contains additional check and control data.

The transferred data consists entirely of small data blocks called
"lines". Each line has a structure like this:

  Byte #        Content
  ------------------------------------------------------
  0             length of data field (n)
  1 - 2         offset address of data block, MSB first
  3             flag byte:  0 = normal data block
                            1 = terminating data block
                            2 = segment block
                            3 = adress block
  4 - n+3       data
  n+4           checksum

The checksum is calculated by adding modulo 256 all bytes from 0
up to and including n+3 and negating (one's complement) the
result.

Segment blocks are always of size 2 and contain the segment
address of the following data blocks, MSB first, in the data
field. The first block is always a segment block. (If you do not
know what segments and offsets are, you should familiarize
yourself with the architecture of the 8086 CPU.) The modem saves
the received "lines" at the given segment:offset address.

The terminating data block has always size 0.



Address Block and Loader Trick
------------------------------

Immediately before the terminating data block there is an address
block of size 4, containing the segment:offset address (MSB first)
at which the modem is to continue execution after the programming
has succeeded. Normally, this starts power-on initialization code
of the modem.

The new V.34-SDL uses this entry point to first transmit a new
loader program (SDL message: "Transmitting loader..."). After the
transfer, the address block of the loader program causes the newly
transferred loader to be activated. It copies itself into the
modem RAM, permitting the ROM to be erased completely and the
transfer of the actual firmware.

Altogether, the V.34-SDL does the following:
- start programming (steps 1-3)
- erase ROM at C0000-FFFFF (steps 4-5)
- transfer loader (about 6kB) (steps 6-7)
- erase ROM at 80000-FFFFF (steps 4-5)
- transfer firmware (about 312kB) (steps 6-7)



SDL.EXE
-------

The download program features two undocumented parameters that
might be useful for some applications:

     SDL /p     Skips the prompt and starts programming at once.

     SDL /u     Only seems to check the consistency of the
                firmware. /u allows for a couple of additional
                parameters. If you know your way around the
                Borland C runtime library, you are invited to find
                out their meanings...

The integrity of the firmware is checked by means of a 16-bit
checksum every time SDL.EXE starts up. Thus direct patching of
random ASCII data in SDL.EXE is not possible (ignoring the
additional modem CRC).

Finding the firmware within SDL.EXE is rather simple. It always
starts out with a segment block (02 00 00 02 ...) and ends with a
terminating block (00 00 00 01 ff). In the V.34-SDL, the firmware
is immediately followed by the loader which again starts with 02
00 00 02 ... and ends with 00 00 00 01 ff.

When extracting the firmware from SDL.EXE, attention must be payed
to the fact that because of Intel linking technique the data is
split into several segments of about 60000 bytes each, and that
every segment is extended to a multiple of 16 bytes. These segment
boundaries in the EXE file do NOT match boundaries between data
blocks. The correct segment boundaries are only revealed by
debugging since these segments do not have entries in the
relocation table. There is a table of relative segment addresses
followed by a table of segment lengths in the data segment.

The file addresses of the segments for the currently existing SDL
releases are (no responsibility taken):

              | SDL 1994-06-17 | SDL 1994-08-17 | SDL 1994-08-25
  Segment     |  Start  Length |  Start  Length |  Start  Length
  ------------+----------------+----------------+----------------
  Firmware #0 |  05410   ea2e  |  055b0   ea2e  |  055b0   ea2e
  Firmware #1 |  13e40   ea65  |  13fe0   ea65  |  13fe0   ea65
  Firmware #2 |  228b0   ea65  |  22a50   ea65  |  22a50   ea65
  Firmware #3 |  31320   ea65  |  314c0   ea65  |  314c0   ea65
  Firmware #4 |  3fd90   a7a6  |  3ff30   ea65  |  3ff30   ea65
  Firmware #5 |                |  4e9a0   4e3c  |  4e9a0   531a
  Loader      |                |  537e0   182b  |  53cc0   182b



Checksum
--------

The 16-bit checksum used in steps (4) and (7) is not calculated
from the transferred data but from all of the newly programmed
memory including all unused bytes, which have the value FFh.
Producing the checksum thus requires reconstructing the content of
the modem ROM from the transferred data.

The algorithm depends on whether the whole ROM has been programmed
or only the part starting at C0000. The calculation always works
like this:

    - Initialize the checksum to FFFFh.
    - Sequentially add all bytes of the range to be checked.

For the checksum from C0000 on the checked range is C0000 to
F7FFFD, i.e. it is 37FFE bytes long. The calculation from 80000 on
is done in two steps: First, the checksum for the range 80000-
BFFFF is calculated and the result is stored at F7FFC (LSB first).
The subsequent proceeding is analogous to that for a "short"
checksum.

The following function is used for "adding" a single byte:
 
  int AddByte(int chksum, int b)
  {
    int  i;

    i  = (chksum ^ b);
    b  = (i & 0xff)
    i ^= (b << 4);
    i  = (i >> 8) + ((i & 0xff) << 8);
    i ^= (b << 3);
    b  = (b & 0xf);
    i ^= (b ^ (b << 7));

    return i;
  }



Reading from Modem Memory
-------------------------

For the purpose of porting SDL.EXE to a different platform, if
there is already a reprogrammed modem at hand, the simplest way to
find out the checksum is to read it directly from the modem
memory. The command

AT G=ssss:oooo

displays a hexdump of the modem memory from address ssss:oooo on.
The checksum is stored at F7FFE, i.e. for instance at F7FF:000E,
LSB first.

