From b4c558731d6efefcdd77325be934e89adf991556 Mon Sep 17 00:00:00 2001 From: thequux Date: Tue, 8 Nov 2011 22:19:34 +0000 Subject: [PATCH] Flashing sled... not yet known to work git-svn-id: https://svn.code.sf.net/p/goodfet/code/trunk@1055 12e2690d-a6be-4b82-a7b7-67c4a43b65c8 --- client/goodfet.bslv2 | 75 ++++++++++- client/shellcode/bslv2-flasher/Makefile | 9 ++ client/shellcode/bslv2-flasher/flasher.bin | Bin 0 -> 178 bytes client/shellcode/bslv2-flasher/flasher.s | 138 +++++++++++++++++++++ 4 files changed, 216 insertions(+), 6 deletions(-) create mode 100644 client/shellcode/bslv2-flasher/Makefile create mode 100644 client/shellcode/bslv2-flasher/flasher.bin create mode 100644 client/shellcode/bslv2-flasher/flasher.s diff --git a/client/goodfet.bslv2 b/client/goodfet.bslv2 index 3b1d200..51672ce 100755 --- a/client/goodfet.bslv2 +++ b/client/goodfet.bslv2 @@ -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("> 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 index 0000000..8fac042 --- /dev/null +++ b/client/shellcode/bslv2-flasher/Makefile @@ -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 index 0000000000000000000000000000000000000000..2964fe47c7ac7fda11f29d84231930e331bd777e GIT binary patch literal 178 zcmZQ|Fb&wiz~c7l0viJh)29P$3`|TMF6=Iu9_qoIk?fHmtRCU!To%DG{jav!g#QeW zE-^6)FtWLDIA^-31xq&TXe_$S#ANQ~&gafIX|oICU*$~>3`<=YH#x8@bzp3FW?+Db zS~(~%Y;rgN6x;5`z_8toiDA> 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 + + -- 2.20.1