RomRescue: The Palm Emergency Rom Restoration Kit

These tools and instructions may help you fix your Palm Pilot after a failed attempt to flash the ROM has left it for dead.  If you're looking for tools to flash your rom, you might try osflash.  These instructions won't always work, and they are definitely not for the faint of heart.  You will need to use a debugger and probably modify some short C and Tcl programs to fit your situation.

If you find these instructions daunting, overwhelming, or just plain incomprehensible, send me some email.  I will be happy to try to make this stuff easier to use.

Background and Requirements

The Palm ROM is divided into two major regions, the Small ROM and the Big ROM.  In recent Palms (pretty much anything since PalmOS 3.10, although some Palm VII's are exceptional), the Small ROM starts at address 0x10C00000 and the Big ROM at 0x10C08000.  Both ROM's contain a debugger which can be driven from a PC via the HotSync cradle.  The idea behind these tools is to use the Small ROM debugger to flash a working ROM into the Big ROM area.

The Palm ROM is divided into sectors of 64K.  To write data to a sector, it must first be cleared to all 0xFF, and then data can be written to it.  The tools, as written, only flash a sector at a time.  This was fine for me, since I wrote this program to correct only 3 bad sectors of my ROM.  If you need to flash all 2M of the big rom, this may become tedious.  Feel free to automate this and send me a patch.

I've tested this on my Debian Linux system with a PalmVx, but it should work on most unix machines, and maybe even some other palms.  You'll need prc-tools (in particular the m68k-palmos-gcc, m68k-palmos-gdb, and m68k-palmos-objdump), a compiler for your host (presumably gcc), and expect.  You'll also need a valid ROM image, which I'll assume you called palm.rom.  You may use either a ROM obtained from the Palm website or via pi-getrom.  The ROM formats are the same, except that the Palm website ROMS are missing the 32K small rom image at the beginning.  I'll assume the small rom is present in the image since it makes the math a little easier.  If your image doesn't have the small rom, just subtract 0x8000 from all the file offsets in these instructions.

Now let's do this thing.

  1. Download and untar the utilities.  They can be compiled with a simple make.  You should have bin2hex, csum, flash_fix, and send_to_palm.exp.
  2. Boot your palm into the Small ROM debugger by holding down the Down button while resetting.  You can tell that the Palm is in debugging mode if it has a small flashing dot in the upper left corner of the screen.
  3. Make sure your palm and gdb can talk to eachother.  To verify this, run m68k-palmos-gdb on your PC, and type target pilot /dev/pilot (or whatever device your HotSync cable is hooked to) to connect to the Pilot.  Make sure no other Pilot syncing software is running (such as gnome-pilot) or it will interfere with the communications.  If gdb doesn't give you a prompt immediately, you may need to hit Ctrl-C to get it to connect.  If everything goes well, you can now examine and modify your Palm's memory via normal gdb commands.  For example, typing p /x *0x5500 @ 200 should print out, in hex, the 200 Palm memory words starting at address 0x5500.  Once you're sure everything is working, quit gdb by typing quit.  Note that this may cause your Palm to spontaneously reset.  That's ok.  Just reset it into debugging mode again.  Occasionally your palm and gdb may become confused and unable to communicate, you can always quit gdb and reset your palm into debugging mode to continue.  Resetting the Palm does not clear the memory, so you shouldn't lose any work by doing this.
  4. Now use bin2hex and send_to_palm.exp to send a sector of your rom image to the palm.  Suppose you want to flash the sector of your ROM at address 0x10D30000.  The corresponding location in your rom image is 0x00130000.  You first need to convert this section of the image into something send_to_palm.exp can understand.  To do this, type ./bin2hex palm.rom 0x00130000 0x00010000 > /tmp/palm.rom.shorts.  The syntax of this command is ./bin2hex <infile> <offset> <size>, and you need to redirect the stdout to a file.  The size will almost always be 0x00010000 (64K in hex).  To copy these bytes to memory location 0x5500 on your palm, make sure your palm is in debugging mode, and type ./send_to_palm.exp 0x5500 /tmp/palm.rom.shorts.  The send_to_palm.exp program is an expect script that uses gdb to copy the bytes to your palm, 2 bytes at a time.  It is very, very slow, taking about 5 minutes to transfer 64K.  While it's doing all this, you should see thousands of gdb commands scrolling by.  If it gets caught at the very start trying to connect to the palm, you may need to hit Ctrl-C to get it going.  When it's finished, it will drop you into the gdb session.  You'll use this later, but for now, just quit.
  5. Now transfer the flash_fix program to the palm using bin2hex and send_to_palm.exp.  I suggest placing the program at location 0x4000.  Don't quit the debugger.
  6. Use the debugger and m68k-palmos-objdump to find the locations of the functions cksum and flash_rom (inside flash_fix) in your palm.  To do this, disassemble flash_fix in another window by typing m68k-palmos-objdump -d flash_fix.  This will give you the byte codes of the instructions in those functions.  Then use p /x * 0x4*** @ 200 commands to hunt for those functions in your palm memory.  For me, cksum was at 0x4316 and flash_rom was at 0x436a, but these will vary with the versions of prc-tools, so don't trust these numbers.  For the rest of this tutorial, I will assume those are the locations, though.
  7. Checksum the sector you transferred over.  This is very important.  I have copied over sectors and then had them not checksum. The cksum routine takes two arguments: the base address and size of the memory to be checksummed.  It takes these arguments in an unusual way.  The base address should be written, as a 32-bit integer, into memory location 0x54fc.  The size should be placed at 0x54f8.  So to checksum a 64K block copied into the Palm at location 0x5500, use the commands:
    1. (gdb) set *0x54fc = 0x0000
    2. (gdb) set *0x54fe = 0x5500
    3. (gdb) set *0x54f8 = 0x0001
    4. (gdb) set *0x54fa = 0x0000
  8. This requires four sets since each set only writes 16-bits.  To run the checksum routine at address 0x4316
    1. (gdb) set $a0 = 0x4316
    2. (gdb) set $pc = $a0
    3. (gdb) c
  9. After a very brief delay, gdb should return a prompt, complaining of an illegal instruction or bus error or something.  It doesn't matter.  To view the results of the checksum, type p /x *0x54f0 @ 2.  To compute the checksum of the original sector, run (in the shell, not in the debugger) ./csum palm.rom 0x00130000 0x00010000.  If the two checksums match, you're good to flash.  If not, try transferring it again.
  10. Now flash your rom.  The flash_rom function expects the location and size of the source bytes in the same places the cksum routine does, so those should already be set up after checksumming the sector you copied over.  It takes one additional argument, the offset of the sector in the rom to be flashed.  Since we want to flash the sector at 0x10D30000, which has offset 0x00130000, type
    1. (gdb) set *0x54f4 = 0x0013
    2. (gdb) set *0x54f6 = 0x0000
  11. If you found the flash_rom function at address 0x436a, type
    1. (gdb) set $a0 = 0x436a
    2. (gdb) set $pc = $a0
    3. (gdb) c
  12. After about 5 seconds, you should get another (gdb) prompt and another error.  You have flashed a sector of your rom.
  13. Now transfer the next sector of your ROM, checksum and flash it.  You shouldn't need to transfer the flash_fix program again.  You may also transfer and checksum multiple sectors at once, but you will have to flash each one individually. If you change flash_fix to flash multiple sectors, send me a patch and I'll put it here.