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.
-
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.
-
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.
-
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.
-
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.
-
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.
-
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.
-
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:
-
(gdb) set *0x54fc = 0x0000
-
(gdb) set *0x54fe = 0x5500
-
(gdb) set *0x54f8 = 0x0001
-
(gdb) set *0x54fa = 0x0000
-
This requires four sets since each set only writes 16-bits.
To run the checksum routine at address 0x4316
-
(gdb) set $a0 = 0x4316
-
(gdb) set $pc = $a0
-
(gdb) c
-
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.
-
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
-
(gdb) set *0x54f4 = 0x0013
-
(gdb) set *0x54f6 = 0x0000
-
If you found the flash_rom function at address 0x436a, type
-
(gdb) set $a0 = 0x436a
-
(gdb) set $pc = $a0
-
(gdb) c
-
After about 5 seconds, you should get another (gdb) prompt and another
error. You have flashed a sector of your rom.
-
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.