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"