FreeCalypso > hg > freecalypso-reveng
changeset 105:49c7cda96f04
C139 boot ROM fully cracked
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Mon, 31 Mar 2014 05:51:57 +0000 |
parents | 52cec4b71cfe |
children | a39a38bbec4d |
files | compal/c139-boot.disasm compal/c139-boot.notes |
diffstat | 2 files changed, 105 insertions(+), 21 deletions(-) [+] |
line wrap: on
line diff
--- a/compal/c139-boot.disasm Mon Mar 31 03:11:25 2014 +0000 +++ b/compal/c139-boot.disasm Mon Mar 31 05:51:57 2014 +0000 @@ -296,11 +296,11 @@ ; Main entry routine ad2: b500 push {lr} ad4: b082 sub sp, #8 - ad6: f7ff ff47 bl 0x968 - ada: f001 f8ad bl 0x1c38 - ade: f000 fd73 bl 0x15c8 - ae2: f000 f81f bl 0xb24 - ae6: f000 f96a bl 0xdbe + ad6: f7ff ff47 bl 0x968 ; superfluous + ada: f001 f8ad bl 0x1c38 ; UART init + ade: f000 fd73 bl 0x15c8 ; zero a couple of vars + ae2: f000 f81f bl 0xb24 ; serial protocol + ae6: f000 f96a bl 0xdbe ; ftmtool voodoo aea: b002 add sp, #8 aec: bd00 pop {pc} aee: 46c0 nop (mov r8, r8) @@ -320,14 +320,20 @@ b1c: e12fff1e bx lr b20: e1a00000 mov r0, r0 +; This function (0xb24, called from this bootloader's "main") calls +; 0xbac (serial download attempt) twice, first at 406250 baud, then +; at 115200 baud. Only the MODEM UART is tried, not IrDA. b24: b500 push {lr} b26: b082 sub sp, #8 +; select MODEM UART b28: 49ed ldr r1, =0x83ff00 ; via 0xee0 b2a: 48ee ldr r0, =0xffff5800 ; via 0xee4 b2c: 6008 str r0, [r1, #0] +; set it to /2 (406250 baud) b2e: 2000 mov r0, #0 b30: 2102 mov r1, #2 b32: f000 f9fb bl 0xf2c +; delay loop b36: 2000 mov r0, #0 b38: 9000 str r0, [sp, #0] b3a: 9900 ldr r1, [sp, #0] @@ -343,10 +349,13 @@ b4e: 0300 lsl r0, r0, #12 b50: 4281 cmp r1, r0 b52: d3f7 bcc 0xb44 +; 0xbac called at 406250 baud b54: f000 f82a bl 0xbac +; set it to /7 (115200 baud) b58: 2000 mov r0, #0 b5a: 2107 mov r1, #7 b5c: f000 f9e6 bl 0xf2c +; same delay loop again b60: 2000 mov r0, #0 b62: 9000 str r0, [sp, #0] b64: 9900 ldr r1, [sp, #0] @@ -362,7 +371,9 @@ b78: 0300 lsl r0, r0, #12 b7a: 4281 cmp r1, r0 b7c: d3f7 bcc 0xb6e +; call 0xbac again, this time at 115200 baud b7e: f000 f815 bl 0xbac +; another (longer) delay loop, then return b82: 2000 mov r0, #0 b84: 9001 str r0, [sp, #4] b86: 9000 str r0, [sp, #0] @@ -384,6 +395,9 @@ ba6: d3f4 bcc 0xb92 ba8: b002 add sp, #8 baa: bd00 pop {pc} + +; This function implements the entirety of the serial download protocol, +; see c139-boot.notes for the details. bac: b500 push {lr} bae: b088 sub sp, #32 ; 0x20 bb0: 48dd ldr r0, =0x800100 ; via 0xf28 @@ -603,8 +617,10 @@ db6: f000 f85e bl 0xe76 dba: b008 add sp, #32 ; 0x20 dbc: bd00 pop {pc} + dbe: b500 push {lr} dc0: b081 sub sp, #4 +; transmit "ftmtool" 7 bytes dc2: 2066 mov r0, #102 ; 0x66 dc4: f000 f858 bl 0xe78 dc8: 2074 mov r0, #116 ; 0x74 @@ -622,6 +638,7 @@ dec: 4983 ldr r1, =0x83ff80 ; via 0xffc dee: 2000 mov r0, #0 df0: 7008 strb r0, [r1, #0] +; delay loop df2: 9000 str r0, [sp, #0] df4: 9800 ldr r0, [sp, #0] df6: 0c00 lsr r0, r0, #16 @@ -632,6 +649,7 @@ e00: 9800 ldr r0, [sp, #0] e02: 0c00 lsr r0, r0, #16 e04: d0f9 beq 0xdfa +; call Rx-char: expecting "yes" e06: 2007 mov r0, #7 e08: 0400 lsl r0, r0, #16 e0a: f000 f84d bl 0xea8 @@ -650,6 +668,7 @@ e2a: 4874 ldr r0, =0x83ff80 ; via 0xffc e2c: 2101 mov r1, #1 e2e: 7001 strb r1, [r0, #0] +; "yes" and normal boot code paths merge e30: f000 f8ce bl 0xfd0 e34: 2800 cmp r0, #0 e36: d00d beq 0xe54 @@ -675,7 +694,11 @@ e6e: f000 f803 bl 0xe78 e72: b001 add sp, #4 e74: bd00 pop {pc} + +; Called via Thumb-BL to transfer control to the downloaded image e76: 4708 bx r1 + +; UART character output routine e78: b081 sub sp, #4 e7a: 4669 mov r1, sp e7c: 7008 strb r0, [r1, #0] @@ -691,6 +714,7 @@ e90: 7001 strb r1, [r0, #0] e92: b001 add sp, #4 e94: 46f7 mov pc, lr + e96: 4812 ldr r0, =0x83ff00 ; via 0xee0 e98: 6800 ldr r0, [r0, #0] e9a: 7940 ldrb r0, [r0, #5] @@ -700,6 +724,10 @@ ea2: 6800 ldr r0, [r0, #0] ea4: 7800 ldrb r0, [r0, #0] ea6: 4770 bx lr + +; UART character input with a timeout (number of LSR read tries passed +; in r0). Returns the character read if one was received, or 0xFF +; if timeout. ea8: b083 sub sp, #12 ; 0xc eaa: 9000 str r0, [sp, #0] eac: 9800 ldr r0, [sp, #0] @@ -728,10 +756,10 @@ eda: b003 add sp, #12 ; 0xc edc: 4770 bx lr ede: 46c0 nop (mov r8, r8) - ee0: ff00 <half-bl> - ee2: 0083 lsl r3, r0, #2 - ee4: 5800 ldr r0, [r0, r0] - ee6: ffff <half-bl> + + ee0: 0083ff00 + ee4: ffff5800 + ee8: b081 sub sp, #4 eea: e001 b 0xef0 eec: 9800 ldr r0, [sp, #0] @@ -753,6 +781,7 @@ f0c: 2001 mov r0, #1 f0e: b001 add sp, #4 f10: 4770 bx lr + f12: b082 sub sp, #8 f14: 9000 str r0, [sp, #0] f16: 4669 mov r1, sp @@ -764,8 +793,12 @@ f22: 8008 strh r0, [r1, #0] f24: b002 add sp, #8 f26: 4770 bx lr - f28: 0100 lsl r0, r0, #4 - f2a: 0080 lsl r0, r0, #2 + + f28: 00800100 + +; This function (0xf2c) reprograms the UART selected by the 83FF00 +; var to the baud rate passed as arguments (div upper byte in R0, +; lower byte in R1) and flushes the Rx FIFO. f2c: b081 sub sp, #4 f2e: 466a mov r2, sp f30: 7051 strb r1, [r2, #1] @@ -848,9 +881,11 @@ fca: d2f5 bcs 0xfb8 fcc: b001 add sp, #4 fce: 4770 bx lr + fd0: 480a ldr r0, =0x83ff80 ; via 0xffc fd2: 7800 ldrb r0, [r0, #0] fd4: 4770 bx lr + fd6: b500 push {lr} fd8: b081 sub sp, #4 fda: 4669 mov r1, sp @@ -1608,6 +1643,8 @@ 15c2: 8008 strh r0, [r1, #0] 15c4: b006 add sp, #24 ; 0x18 15c6: 4770 bx lr + +; function zeroes out IRAM word vars at 0x83ff08 and 0x83ff10 15c8: 4907 ldr r1, =0x83ff08 ; via 0x15e8 15ca: 2000 mov r0, #0 15cc: 6008 str r0, [r1, #0] @@ -1616,16 +1653,13 @@ 15d2: 6001 str r1, [r0, #0] 15d4: 4770 bx lr 15d6: 46c0 nop (mov r8, r8) - 15d8: ff10 <half-bl> - 15da: 0083 lsl r3, r0, #2 - 15dc: ff04 <half-bl> - 15de: 0083 lsl r3, r0, #2 - 15e0: ff0e <half-bl> - 15e2: 0083 lsl r3, r0, #2 - 15e4: ff0c <half-bl> - 15e6: 0083 lsl r3, r0, #2 - 15e8: ff08 <half-bl> - 15ea: 0083 lsl r3, r0, #2 + + 15d8: 0083ff10 + 15dc: 0083ff04 + 15e0: 0083ff0e + 15e4: 0083ff0c + 15e8: 0083ff08 + 15ec: b082 sub sp, #8 15ee: 9101 str r1, [sp, #4] 15f0: 9000 str r0, [sp, #0] @@ -1646,6 +1680,7 @@ 160e: 7181 strb r1, [r0, #6] 1610: b002 add sp, #8 1612: 4770 bx lr + 1614: b500 push {lr} 1616: b084 sub sp, #16 ; 0x10 1618: 466b mov r3, sp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/compal/c139-boot.notes Mon Mar 31 05:51:57 2014 +0000 @@ -0,0 +1,49 @@ +Download protocol, attempted first at 406250 baud, then 115200, only on the +MODEM UART: + +The boot code begins by transmitting 1B F6 02 00 41 01 40, then calls the +Rx-with-timeout function 7 times, expecting this seq: 1B F6 02 00 52 01 53. +Getting anything else or timeout causes the 0xbac function to return, +ending that download attempt. If this seq was received, the boot code then +sends 1B F6 02 00 41 02 43 and expects to receive 3 bytes as follows: + +* one dummy byte (stored into an automatic var, but then not used) +* payload length MSB +* payload length LSB + +The boot code then expects to receive the specified # of bytes [0,65535] +and stores them beginning at 0x800100. Then the Rx-with-timeout function +is called again to receive the XOR checksum byte, not counted in the length. +If the checksum fails to match, 0xbac function sends 1B F6 02 00 45 53 16 +and returns. If this check passes, the "1003" check is performed next: +the 4 bytes starting at 0x803ce0 must match. If the downloaded image was +shorter, the comparison will be made against pre-powerup IRAM content, +i.e., law of chance. Furthermore, the comparison is actually an inequality: +each "signature" byte in the downloaded image needs to be >= (in the signed +sense) than the "1003" reference. (0x7F7F7F7F thus ought to be a passing +value.) + +If this last check passes, the 0xbac function jumps to the downloaded image +instead of returning. Control is transferred to 0x800100 in the ARM state. +If the "1003" check fails, 0xbac function sends 1B F6 02 00 41 03 57 +and returns. + +If the boot process is not diverted to a successful serial download as above, +the boot code does one strange thing before it jumps to 0x20f8 (main app entry +point). The boot code unconditionally transmits "ftmtool" on the MODEM UART +and waits a certain time for a "yes" response. If it receives that "yes", +it responds with "modemerror", otherwise just "error". Either way, it then +proceed to jump to the main app entry point at 0x20f8! There is also a bunch +of "dead" code in the 8 KiB "boot block", code which does not seem to be +reachable from any path. There is no check for whether or not the "main app" +is present; if the flash contains the 8 KiB "boot block" followed by blank +space, the boot code will happily jumps to those FFs - but it will still +provide an opportunity for serial download as usual, so no real problem. + +IRAM variables used by the boot code: + +83FF00 holds UART base addr, set to FFFF5800 (MODEM) +83FF08 32-bit var init to 0 +83FF10 32-bit var init to 0 +83FF80 byte var init to 0 at the beginning of ftmtool function (0xdbe), + set to 1 if "yes" received in response to "ftmtool"