turn ftdi driver into echo server
[goodfet] / client / shellcode / bslv2-flasher / flasher.s
1         ;; Org is set at 0 so that there is no padding before the sled.
2         ;; This code should be run from RAM; the address doesn't really matter.
3         BASE == 0x0
4         .org BASE
5         code_size_guess == 0xB2
6         LED_PORT = 0x0200
7         FLASH_LED = 0x02
8         FAIL_LED = 0x04
9
10         ;; MSP430f5510 definitions
11         FCTL1 == 0x0140
12         FCTL3 == 0x0144
13         BUSY == 0x0001
14         FWPW == 0xA500
15         ERASE == 0x0004
16         WRT == 0x0040
17         BLKWRT == 0x0080
18         WAIT == 0x0008
19         LOCK == 0x0010
20
21         ;; Format of payload: (all values MSP-endian)
22         ;; {
23         ;;   number of blocks: 1 byte
24         ;;   checksum: 1 byte (byte such that two's complement sum of payload bytes == 0xff)
25         ;;   repeat: (total of (payload length - 3) bytes)
26         ;;     (start_address >> 8): 2 bytes
27         ;;     block data: 512 bytes
28         ;; }
29         ;; The shortest possible payload would thus be <<0x00 0xFF>>
30         ;; A payload that writes 0's to 0xFE00-0xFFFF would be:
31         ;;    <<0x01 0x00 0xFE 0x00 0x00*512>>
32
33         ;; Assumptions/caveats:
34         ;; 1) Assume RAM is in low memory. It will fail miserably otherwise
35         ;; 2) All this code is very carefully written to be position-independent
36
37         ;; Register usage:
38         ;;
39         ;; r4: start of payload
40         ;; r5: address of start
41 start:
42         ;; the next two instructions must be the first two instructions after start
43         mov     r0, r5
44         add     #(code_size_guess + start - .), r5
45         mov     r6, r4
46
47         bis.b   #FLASH_LED+FAIL_LED, &LED_PORT+4
48         bic.b   #FLASH_LED+FAIL_LED, &LED_PORT+2
49         ;; calc checksum
50         ;; local regs:
51         ;; r6: running sum
52         ;; r7: end addr
53         ;; r8: current addr
54         ;; r9: scratch
55         mov     r4, r8
56         mov     r4, r7
57         mov.b   @r8, r9
58         incd    r7
59
60         rla     r9, 1           ; Add r9*514 (r9<<1 + r9 << 9)
61         add     r9, r7
62         rla     r9, 8
63         add     r9, r7
64
65         add     @r8, r7
66         mov.b   #0, r6
67 1:      add.b   @r8+, r6
68         cmp     r7, r8
69         jlo     1b
70         cmp     #0xff, r6
71
72         bis.b   #FAIL_LED, &LED_PORT+2
73         reta
74
75         ;; Get flashing
76         ;; local regs:
77         ;; r6: current src
78         ;; r7: current dest
79         ;; r8: block id
80         ;; r9: block count
81         ;; r10: dwords remaining
82         mov     r4, r6
83         clr     r8
84         mov.b   @r4, r9
85         incd    r6
86
87 next_block:
88         dec     r9
89         jnc     done_programming
90         bis     #FLASH_LED, &LED_PORT+2
91         ;; calc dest addr
92         mov     @r6+, r7
93         rlam.a  #4, r7          ; multiply by 256 to recover real address
94         rlam.a  #4, r7
95         ;; erase block
96 1:      bit     #BUSY, &FCTL3
97         jnz     1b
98         mov     #FWPW, &FCTL3
99         mov     #FWPW+ERASE, &FCTL1
100         clr     @r7
101 1:      bit     #BUSY, &FCTL3
102         jnz     1b
103
104         ;; not sure whether I need to bounce LOCK here
105         mov     #32, r10
106         mov     #FWPW+BLKWRT+WRT, &FCTL1
107 2:      mov     @r6+, 0(r7)
108         mov     @r6+, 2(r7)
109 3:      bit     #WAIT, &FCTL3
110         jz      3b
111         add     #4, r7          ; This was originally 2 incd insns
112         dec     r10
113         jnz     2b
114         mov     #FWPW, &FCTL1
115 4:      bit     #BUSY, &FCTL3
116         jnz     4b
117
118         mov     #FWPW+LOCK, &FCTL3
119         jmp     next_block
120
121 done_programming:
122         bic.b   #FLASH_LED, &LED_PORT+2
123         bic.b   #FAIL_LED, &LED_PORT+2
124
125 bsl_ret:
126         mov     #2, r12
127         mov     #0xDEAD, r13
128         mov     #0xBEEF, r14
129         bra     #0x1002
130
131 payload:
132         .data
133         .if (payload-start) != code_size_guess
134
135         .print "Payload guess wrong"
136         .endif
137
138