safety checkin of fwflash tool (hacking counterpart (lpcload) atm)
[my-code/arm.git] / betty / fwflash.c
1 /*
2  * fwflash.c - handling the betty flashes
3  *
4  * author: hackbard@hackdaworld.org
5  *
6  */
7
8 /*
9  * include files
10  */
11
12 #include <stdio.h>
13
14 #include "lpc2xxx.h"
15
16 /*
17  * defines
18  */
19
20 /* bank 0/2 and boootloader addr/size */
21 #define BANK0                   0x80000000
22 #define BANK2                   0x82000000
23 #define BANK_SIZE               0x00100000
24 #define BOOTLOADER              0x7fffe000
25 #define BL_SIZE                 0x00000800
26
27 /* flash cmd addresses - flash[0-18] <--> arm[1-19]*/
28 #define B0F555  (*((volatile unsigned long *)(BANK0|0xaaa)))    // 0x555
29 #define B0F2AA  (*((volatile unsigned long *)(BANK0|0x554)))    // 0x2aa
30 #define B2F555  (*((volatile unsigned long *)(BANK2|0xaaa)))    // 0x555
31 #define B2F2AA  (*((volatile unsigned long *)(BANK2|0x554)))    // 0x2aa
32
33 /* commands */
34 #define CMD_READ                'R'
35 #define CMD_CHIP_ERASE          'E'
36 #define CMD_CHIP_ID             'I'
37
38 #define BUFSIZE                 16
39
40 /*
41  * type definitions
42  */
43
44 typedef unsigned char u8;
45 typedef unsigned short u16;
46 typedef unsigned int u32;
47
48 /*
49  * functions
50  */
51
52 void mmap_init(u8 memtype) {
53
54         MEMMAP=memtype;
55 }
56
57 void uart0_init(void) {
58
59         PINSEL0=0x05;                   // pin select -> tx, rx
60         UART0_FCR=0x07;                 // enable fifo
61         UART0_LCR=0x83;                 // set dlab + word length
62         UART0_DLL=0x10;                 // br: 9600 @ 10/4 mhz
63         UART0_DLM=0x00;
64         UART0_LCR=0x03;                 // unset dlab
65 }
66
67 void uart0_send_string(char *txbuf) {
68
69         int i;
70
71         i=0;
72
73         while(txbuf[i]) {
74                 UART0_THR=txbuf[i++];
75                 /* flush if tx buffer maximum reached */
76                 if(!(i%16))
77                         while(!(UART0_LSR&(1<<6)))
78                                 continue;
79         }
80         
81         /* flush if \n and \r do not fit in the tx buffer */
82         if(i>14)
83                 while(!(UART0_LSR&(1<<6)))
84                         continue;
85
86         UART0_THR='\n';
87         UART0_THR='\r';
88
89         /* flush uart0 anyways */
90         while(!(UART0_LSR&(1<<6)))
91                 continue;
92 }
93
94 void uart0_send_buf16(u16 *buf,int len) {
95
96         int i;
97
98         i=0;
99
100         for(i=0;i<len;i++) {
101                 if(!(i%8))
102                         while(!(UART0_LSR&(1<<6)))
103                                 continue;
104                 UART0_THR=buf[i]&0xff;
105                 UART0_THR=(buf[i]>>8)&0xff;
106         }
107 }
108
109 void uart0_send_buf32(u32 *buf,int len) {
110
111         int i;
112
113         i=0;
114
115         for(i=0;i<len;i++) {
116                 if(!(i%4))
117                         while(!(UART0_LSR&(1<<6)))
118                                 continue;
119                 UART0_THR=buf[i]&0xff;
120                 UART0_THR=(buf[i]>>8)&0xff;
121                 UART0_THR=(buf[i]>>16)&0xff;
122                 UART0_THR=(buf[i]>>24)&0xff;
123         }
124 }
125
126 void uart0_send_byte(u8 send) {
127
128         while(!(UART0_LSR&(1<<5)))
129                 continue;
130
131         UART0_THR=send;
132 }
133
134 u8 uart0_get_byte(void) {
135
136         u8 rx;
137
138         while(!(UART0_LSR&(1<<0)))
139                 continue;
140
141         rx=UART0_RBR;
142
143         return rx;
144 }
145
146 /*
147  * main function
148  */
149
150 int main(void) {
151
152         /* variables */
153
154         u32 i,addrlen,datalen,addr;
155         u8 buf[BUFSIZE];
156         u16 data;
157         u8 cmd;
158         u8 txrx;
159
160         /* memory mapping of interrupt vectors to static ram */
161
162         //mmap_init(MMAP_RAM);
163
164         /* uart initialization */
165         uart0_init();
166
167         /* external memory init */
168         BCFG0=0x1000FBEF;               // BCFG2 should be fine as is
169
170         /* begin the main loop */
171         while(1) {
172
173         /* receive cmd */
174         while(1) {
175
176                 cmd=uart0_get_byte();
177                 txrx=1;
178                 switch(cmd) {
179                         case CMD_CHIP_ERASE:
180                                 addrlen=0;
181                                 datalen=1;
182                                 break;
183                         case CMD_READ:
184                                 addrlen=4;
185                                 datalen=4;
186                                 break;
187                         case CMD_CHIP_ID:
188                                 addrlen=0;
189                                 datalen=1;
190                                 break;
191                         default:
192                                 uart0_send_byte('f');
193                                 txrx=0;
194                                 break;
195                 }
196
197                 if(txrx) {
198                         /* send an ack */
199                         uart0_send_byte(cmd);
200                         break;
201                 }
202         }
203
204         /* receive (only if there is) more data from uart0 */
205         addr=0;
206         for(i=0;i<addrlen;i++) {
207                 txrx=uart0_get_byte();
208                 addr|=(txrx<<((addrlen-i-1)*8));
209         }
210
211         for(i=0;i<datalen;i++)
212                 buf[i]=uart0_get_byte();
213
214         /* process the cmd */
215         switch(cmd) {
216                 case CMD_READ:
217                         /* data length to read */
218                         datalen=buf[0]<<24|buf[1]<<16|buf[2]<<8|buf[3];
219                         /* check addr and datalen */
220                         if((addr>=BANK0)&(addr+datalen<BANK0+BANK_SIZE))
221                                 uart0_send_buf16((u16 *)addr,datalen);
222                         if((addr>=BANK2)&(addr+datalen<BANK2+BANK_SIZE))
223                                 uart0_send_buf16((u16 *)addr,datalen);
224                         if((addr>=BOOTLOADER)&(addr+datalen<BOOTLOADER+BL_SIZE))
225                                 uart0_send_buf32((u32 *)addr,datalen);
226                         break;
227                 case CMD_CHIP_ERASE:
228                         if(buf[0]=='0') {
229                                 B0F555=0xaa;
230                                 B0F2AA=0x55;
231                                 B0F555=0x80;
232                                 B0F555=0xaa;
233                                 B0F2AA=0x55;
234                                 B0F555=0x10;
235                         }
236                         else if(buf[0]=='2') {
237                                 B2F555=0xaa;
238                                 B2F2AA=0x55;
239                                 B2F555=0x80;
240                                 B2F555=0xaa;
241                                 B2F2AA=0x55;
242                                 B2F555=0x10;
243                         }
244                         uart0_send_byte(buf[0]);
245                         break;
246                 case CMD_CHIP_ID:
247                         if(buf[0]=='0') {
248                                 B0F555=0xaa;
249                                 B0F2AA=0x55;
250                                 B0F555=0x90;
251                                 data=*((u16 *)BANK0);
252                                 data=*((u16 *)(BANK0|0x200));
253                         }
254                         else if(buf[0]=='2') {
255                                 B2F555=0xaa;
256                                 B2F2AA=0x55;
257                                 B2F555=0x90;
258                                 data=*((u16 *)BANK2);
259                                 data=*((u16 *)(BANK2|0x200));
260                         }
261                         uart0_send_buf16(&data,2);
262                         break;
263                 default:
264                         break;
265         }
266                 
267         }
268
269         return 0;
270 }
271