Flashing sled... not yet known to work
authorthequux <thequux@12e2690d-a6be-4b82-a7b7-67c4a43b65c8>
Tue, 8 Nov 2011 22:19:34 +0000 (22:19 +0000)
committerthequux <thequux@12e2690d-a6be-4b82-a7b7-67c4a43b65c8>
Tue, 8 Nov 2011 22:19:34 +0000 (22:19 +0000)
git-svn-id: https://svn.code.sf.net/p/goodfet/code/trunk@1055 12e2690d-a6be-4b82-a7b7-67c4a43b65c8

client/goodfet.bslv2
client/shellcode/bslv2-flasher/Makefile [new file with mode: 0644]
client/shellcode/bslv2-flasher/flasher.bin [new file with mode: 0644]
client/shellcode/bslv2-flasher/flasher.s [new file with mode: 0644]

index 3b1d200..51672ce 100755 (executable)
@@ -3,6 +3,8 @@
 import hidapi
 import struct
 import time
+import os.path
+
 
 BSL_VID = 0x2047
 BSL_PID = 0x0200
@@ -181,7 +183,17 @@ F8 3F 80 00 36 80 80 00 3A 80 FF 3F
 12 34 56 78 99 10 11 12 13 14 15 16 17 18 00 80
 q"""
 
-BLINK_BSL2 = """@2000
+# reta: 10 01; jmp .: ff3f; ret: 3041
+BLINK_BSL3 = """@2400
+B2 40 80 5A 5C 01 E2 43 04 02 E2 43 02 02 2C 43
+3D 40 AD DE 3E 40 EF BE 80 00 02 10
+q"""
+
+RET_BSL = """@2400
+2C 43 3D 40 AD DE 3E 40 EF BE B0 13 02 10
+q"""
+
+BLINK_BSL2 = """@2400
 31 40 00 34 B0 13 0C 20 B0 13 32 20 21 83 D2 43
 04 02 D2 43 02 02 B2 40 80 5A 5C 01 07 3C 91 53
 00 00 B1 93 00 00 FB 23 D2 E3 02 02 81 43 00 00
@@ -215,6 +227,26 @@ class TiHex(object):
 
 
 
+def segment_flash(iterator):
+    flash = {}
+    def insert(base, off, data):
+        assert off + len(data) <= 512
+        orig = flash.get(base, "\0" * 512)
+        new = orig[0:off] + data + orig[off+len(data):]
+        flash[base] = new
+    for addr, data in iterator:
+        while len(data) > 0:
+            base = addr >> 9
+            off = addr % 512
+
+            sub, data = data[0:512-off], data[512-off:]
+            addr += len(sub)
+
+            insert(base, off, sub)
+
+    for addr in sorted(flash):
+        yield (addr << 9), flash[addr]
+
 class BSL(object):
     MSGS = ["SUCCESS",
             "Flash write check failed",
@@ -275,8 +307,8 @@ class BSL(object):
         return self._send_command(0x15, "")
     def CrcCheck(self, addr, length):
         return self._send_command(0x16, _fmt_addr(addr) + _fmt_addr(length, 2))
-    def LoadPc(self, addr):
-        return self._send_command(0x17, _fmt_addr(addr), False)
+    def LoadPc(self, addr, expect_response=False):
+        return self._send_command(0x17, _fmt_addr(addr), expect_response)
     def TxDataBlock(self, addr, length):
         return self._send_command(0x18, _fmt_addr(addr) + _fmt_addr(length, 2))
     def TxBslVersion(self):
@@ -285,11 +317,34 @@ class BSL(object):
         return self._send_command(0x1a, "")
 
     # Helpers
+    def RxLargeDatablock(self, addr, data):
+        # We can send at most 64 bytes at once, due to HID limitations.
+        while len(data) > 0:
+            sub, data = data[:64], data[64:]
+            self.RxDataBlockFast(addr, sub)
+            addr += len(sub)
+
     def RxTIHexFast(self, hexstring):
         tihex = TiHex(hexstring)
         for addr, value in tihex:
             self.RxDataBlockFast(addr, value)
 
+    def FlashTIHex(self, hexstring):
+        flash = segment_flash(TiHex(hexstring))
+        sled_path = os.path.join(os.path.dirname(__file__), "shellcode", "bslv2-flasher", "flasher.bin")
+        sled = open(sled_path, "rb").read()
+        for addr, data in flash:
+            # Maybe flash more than one block at a time? We do have 4K of ram
+            payload = struct.pack("<H", addr >> 8) + data
+            cksum = 256 - ((sum(ord(x) for x in "\001" + payload) + 1) % 256)
+            payload = "\001" + chr(cksum) + payload
+
+            assert (sum(ord(x) for x in payload) % 256) == 255
+
+            self.RxLargeDatablock(0x2400, sled + payload)
+            print repr(self.LoadPc(0x2400, True))
+
+
     def bounce_hid(self):
         "Reconnect to the target"
         self.device.close()
@@ -303,10 +358,12 @@ def main():
     #return
     try:
         print repr(bsl.RxPassword('\xff' * 32))
-        print repr(bsl.RxTIHexFast(RAM_BSL))
-        print repr(bsl.LoadPc(0x2400))
-        #print repr(bsl.RxTIHexFast(file("blinky.tihex","r").read()))
+        #print repr(bsl.FlashTIHex(BLINK_BSL))
+        print repr(bsl.RxTIHexFast(BLINK_BSL2))
         #print repr(bsl.LoadPc(0x2000))
+        #raise SystemExit(0)
+        #print repr(bsl.RxTIHexFast(file("blinky.tihex","r").read()))
+        print repr(bsl.LoadPc(0x2400, True))
         #bsl.device.close()
         print repr("Bouncing...")
         time.sleep(3)
@@ -318,4 +375,10 @@ def main():
     finally:
         bsl.device.close()
 
+def mainx():
+    for addr, data in segment_flash(TiHex(RAM_BSL)):
+        bs = 64
+        hexdata = "\n     ".join(data[s:s+bs].encode("hex") for s in range(0,len(data),bs))
+        print "%04x %s" % (addr, hexdata)
+
 main()
diff --git a/client/shellcode/bslv2-flasher/Makefile b/client/shellcode/bslv2-flasher/Makefile
new file mode 100644 (file)
index 0000000..8fac042
--- /dev/null
@@ -0,0 +1,9 @@
+AS=msp430-as
+OBJCOPY=msp430-objcopy
+
+all: flasher.bin
+
+%.bin: %.elf
+       $(OBJCOPY) -O binary $*.elf $*.bin
+%.elf: %.s
+       $(AS) -mcpu=430xv2 -a -o $*.elf $*.s >$*.lst
diff --git a/client/shellcode/bslv2-flasher/flasher.bin b/client/shellcode/bslv2-flasher/flasher.bin
new file mode 100644 (file)
index 0000000..2964fe4
Binary files /dev/null and b/client/shellcode/bslv2-flasher/flasher.bin differ
diff --git a/client/shellcode/bslv2-flasher/flasher.s b/client/shellcode/bslv2-flasher/flasher.s
new file mode 100644 (file)
index 0000000..9c346ab
--- /dev/null
@@ -0,0 +1,138 @@
+       ;; Org is set at 0 so that there is no padding before the sled.
+       ;; This code should be run from RAM; the address doesn't really matter.
+       BASE == 0x0
+       .org BASE
+       code_size_guess == 0xB2
+       LED_PORT = 0x0200
+       FLASH_LED = 0x02
+       FAIL_LED = 0x04
+
+       ;; MSP430f5510 definitions
+       FCTL1 == 0x0140
+       FCTL3 == 0x0144
+       BUSY == 0x0001
+       FWPW == 0xA500
+       ERASE == 0x0004
+       WRT == 0x0040
+       BLKWRT == 0x0080
+       WAIT == 0x0008
+       LOCK == 0x0010
+
+       ;; Format of payload: (all values MSP-endian)
+       ;; {
+       ;;   number of blocks: 1 byte
+       ;;   checksum: 1 byte (byte such that two's complement sum of payload bytes == 0xff)
+       ;;   repeat: (total of (payload length - 3) bytes)
+       ;;     (start_address >> 8): 2 bytes
+       ;;     block data: 512 bytes
+       ;; }
+       ;; The shortest possible payload would thus be <<0x00 0xFF>>
+       ;; A payload that writes 0's to 0xFE00-0xFFFF would be:
+       ;;    <<0x01 0x00 0xFE 0x00 0x00*512>>
+
+       ;; Assumptions/caveats:
+       ;; 1) Assume RAM is in low memory. It will fail miserably otherwise
+       ;; 2) All this code is very carefully written to be position-independent
+
+       ;; Register usage:
+       ;;
+       ;; r4: start of payload
+       ;; r5: address of start
+start:
+       ;; the next two instructions must be the first two instructions after start
+       mov     r0, r5
+       add     #(code_size_guess + start - .), r5
+       mov     r6, r4
+
+       bis.b   #FLASH_LED+FAIL_LED, &LED_PORT+4
+       bic.b   #FLASH_LED+FAIL_LED, &LED_PORT+2
+       ;; calc checksum
+       ;; local regs:
+       ;; r6: running sum
+       ;; r7: end addr
+       ;; r8: current addr
+       ;; r9: scratch
+       mov     r4, r8
+       mov     r4, r7
+       mov.b   @r8, r9
+       incd    r7
+
+       rla     r9, 1           ; Add r9*514 (r9<<1 + r9 << 9)
+       add     r9, r7
+       rla     r9, 8
+       add     r9, r7
+
+       add     @r8, r7
+       mov.b   #0, r6
+1:     add.b   @r8+, r6
+       cmp     r7, r8
+       jlo     1b
+       cmp     #0xff, r6
+
+       bis.b   #FAIL_LED, &LED_PORT+2
+       reta
+
+       ;; Get flashing
+       ;; local regs:
+       ;; r6: current src
+       ;; r7: current dest
+       ;; r8: block id
+       ;; r9: block count
+       ;; r10: dwords remaining
+       mov     r4, r6
+       clr     r8
+       mov.b   @r4, r9
+       incd    r6
+
+next_block:
+       dec     r9
+       jnc     done_programming
+       bis     #FLASH_LED, &LED_PORT+2
+       ;; calc dest addr
+       mov     @r6+, r7
+       rlam.a  #4, r7          ; multiply by 256 to recover real address
+       rlam.a  #4, r7
+       ;; erase block
+1:     bit     #BUSY, &FCTL3
+       jnz     1b
+       mov     #FWPW, &FCTL3
+       mov     #FWPW+ERASE, &FCTL1
+       clr     @r7
+1:     bit     #BUSY, &FCTL3
+       jnz     1b
+
+       ;; not sure whether I need to bounce LOCK here
+       mov     #32, r10
+       mov     #FWPW+BLKWRT+WRT, &FCTL1
+2:     mov     @r6+, 0(r7)
+       mov     @r6+, 2(r7)
+3:     bit     #WAIT, &FCTL3
+       jz      3b
+       add     #4, r7          ; This was originally 2 incd insns
+       dec     r10
+       jnz     2b
+       mov     #FWPW, &FCTL1
+4:     bit     #BUSY, &FCTL3
+       jnz     4b
+
+       mov     #FWPW+LOCK, &FCTL3
+       jmp     next_block
+
+done_programming:
+       bic.b   #FLASH_LED, &LED_PORT+2
+       bic.b   #FAIL_LED, &LED_PORT+2
+
+bsl_ret:
+       mov     #2, r12
+       mov     #0xDEAD, r13
+       mov     #0xBEEF, r14
+       bra     #0x1002
+
+payload:
+       .data
+       .if (payload-start) != code_size_guess
+
+       .print "Payload guess wrong"
+       .endif
+
+