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.