]> git.zerfleddert.de Git - proxmark3-svn/blob - client/flasher.c
remove most of the references to translate.h
[proxmark3-svn] / client / flasher.c
1 #include <usb.h>
2 #include <stdio.h>
3 #include <unistd.h>
4 #include <stdlib.h>
5 #include <stdint.h>
6 #include <stdbool.h>
7 #include <strings.h>
8 #include <string.h>
9 #include <errno.h>
10 #include <ctype.h>
11
12 #include "prox.h"
13 #include "proxmark3.h"
14
15 static uint32_t ExpectedAddr;
16 static uint8_t QueuedToSend[256];
17 static bool AllWritten;
18 #define PHYSICAL_FLASH_START 0x100000
19
20 struct partition {
21 int start;
22 int end;
23 int precious;
24 const char *name;
25 };
26 struct partition partitions[] = {
27 {0x100000, 0x102000, 1, "bootrom"},
28 {0x102000, 0x110000, 0, "fpga"},
29 {0x110000, 0x140000, 0, "os"},
30 };
31
32 /* If translate is set, subtract PHYSICAL_FLASH_START to translate for old
33 * bootroms.
34 */
35 static void FlushPrevious(int translate)
36 {
37 UsbCommand c;
38 memset(&c, 0, sizeof(c));
39
40 printf("expected = %08x flush, ", ExpectedAddr);
41
42 int i;
43 for(i = 0; i < 240; i += 48) {
44 c.cmd = CMD_SETUP_WRITE;
45 memcpy(c.d.asBytes, QueuedToSend+i, 48);
46 c.arg[0] = (i/4);
47 SendCommand(&c, true);
48 }
49
50 c.cmd = CMD_FINISH_WRITE;
51 c.arg[0] = (ExpectedAddr-1) & (~255);
52 if(translate) {
53 c.arg[0] -= PHYSICAL_FLASH_START;
54 }
55 printf("c.arg[0] = %08x\r", c.arg[0]);
56 memcpy(c.d.asBytes, QueuedToSend+240, 16);
57 SendCommand(&c, true);
58
59 AllWritten = true;
60 }
61
62 /* Where must be between start_addr (inclusive) and end_addr (exclusive).
63 */
64 static void GotByte(uint32_t where, uint8_t which, int start_addr, int end_addr, int translate)
65 {
66 AllWritten = false;
67
68 if(where < start_addr || where >= end_addr) {
69 printf("bad: got byte at %08x, outside of range %08x-%08x\n", where, start_addr, end_addr);
70 exit(-1);
71 }
72
73 if(where != ExpectedAddr) {
74 printf("bad: got at %08x, expected at %08x\n", where, ExpectedAddr);
75 exit(-1);
76 }
77 QueuedToSend[where & 255] = which;
78 ExpectedAddr++;
79
80 if((where & 255) == 255) {
81 // we have completed a full page
82 FlushPrevious(translate);
83 }
84 }
85
86 static int HexVal(int c)
87 {
88 c = tolower(c);
89 if(c >= '0' && c <= '9') {
90 return c - '0';
91 } else if(c >= 'a' && c <= 'f') {
92 return (c - 'a') + 10;
93 } else {
94 printf("bad hex digit '%c'\n", c);
95 exit(-1);
96 }
97 }
98
99 static uint8_t HexByte(char *s)
100 {
101 return (HexVal(s[0]) << 4) | HexVal(s[1]);
102 }
103
104 static void LoadFlashFromSRecords(const char *file, int start_addr, int end_addr, int translate)
105 {
106 ExpectedAddr = start_addr;
107
108 FILE *f = fopen(file, "r");
109 if(!f) {
110 printf("couldn't open file\n");
111 exit(-1);
112 }
113
114 char line[512];
115 while(fgets(line, sizeof(line), f)) {
116 if(memcmp(line, "S3", 2)==0) {
117 char *s = line + 2;
118 int len = HexByte(s) - 5;
119 s += 2;
120
121 char addrStr[9];
122 memcpy(addrStr, s, 8);
123 addrStr[8] = '\0';
124 uint32_t addr;
125 sscanf(addrStr, "%x", &addr);
126 s += 8;
127
128 /* Accept files that are located at PHYSICAL_FLASH_START, and files that are located at 0 */
129 if(addr < PHYSICAL_FLASH_START)
130 addr += PHYSICAL_FLASH_START;
131
132 int i;
133 for(i = 0; i < len; i++) {
134 while((addr+i) > ExpectedAddr) {
135 GotByte(ExpectedAddr, 0xff, start_addr, end_addr, translate);
136 }
137 GotByte(addr+i, HexByte(s), start_addr, end_addr, translate);
138 s += 2;
139 }
140 }
141 }
142
143 if(!AllWritten) FlushPrevious(translate);
144
145 fclose(f);
146 printf("\ndone.\n");
147 }
148
149 static int PrepareFlash(struct partition *p, const char *filename, unsigned int state)
150 {
151 int translate = 0;
152 if(state & DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH) {
153 UsbCommand c;
154 c.cmd = CMD_START_FLASH;
155 c.arg[0] = p->start;
156 c.arg[1] = p->end;
157
158 /* Only send magic when flashing bootrom */
159 if(p->precious) {
160 c.arg[2] = START_FLASH_MAGIC;
161 } else {
162 c.arg[2] = 0;
163 }
164 SendCommand(&c, true);
165 translate = 0;
166 } else {
167 fprintf(stderr, "Warning: Your bootloader does not understand the new START_FLASH command\n");
168 fprintf(stderr, " It is recommended that you update your bootloader\n\n");
169 translate = 1;
170 }
171
172 LoadFlashFromSRecords(filename, p->start, p->end, translate);
173 return 1;
174 }
175
176 static unsigned int GetProxmarkState(void)
177 {
178 unsigned int state = 0;
179
180 UsbCommand c;
181 c.cmd = CMD_DEVICE_INFO;
182 SendCommand(&c, false);
183
184 UsbCommand resp;
185 ReceiveCommand(&resp);
186 /* Three cases:
187 * 1. The old bootrom code will ignore CMD_DEVICE_INFO, but respond with an ACK
188 * 2. The old os code will respond with CMD_DEBUG_PRINT_STRING and "unknown command"
189 * 3. The new bootrom and os codes will respond with CMD_DEVICE_INFO and flags
190 */
191
192 switch(resp.cmd) {
193 case CMD_ACK:
194 state = DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM;
195 break;
196 case CMD_DEBUG_PRINT_STRING:
197 state = DEVICE_INFO_FLAG_CURRENT_MODE_OS;
198 break;
199 case CMD_DEVICE_INFO:
200 state = resp.arg[0];
201 break;
202 default:
203 fprintf(stderr, "Couldn't get proxmark state, bad response type: 0x%04X\n", resp.cmd);
204 exit(-1);
205 break;
206 }
207
208 #if 0
209 if(state & DEVICE_INFO_FLAG_BOOTROM_PRESENT) printf("New bootrom present\n");
210 if(state & DEVICE_INFO_FLAG_OSIMAGE_PRESENT) printf("New osimage present\n");
211 if(state & DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM) printf("Currently in bootrom\n");
212 if(state & DEVICE_INFO_FLAG_CURRENT_MODE_OS) printf("Currently in OS\n");
213 #endif
214
215 return state;
216 }
217
218 static unsigned int EnterFlashState(void)
219 {
220 unsigned int state = GetProxmarkState();
221
222 if(state & DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM) {
223 /* Already in flash state, we're done. */
224 return state;
225 }
226
227 if(state & DEVICE_INFO_FLAG_CURRENT_MODE_OS) {
228 fprintf(stderr,"Entering flash-mode...\n");
229 UsbCommand c;
230 bzero(&c, sizeof(c));
231
232 if( (state & DEVICE_INFO_FLAG_BOOTROM_PRESENT) && (state & DEVICE_INFO_FLAG_OSIMAGE_PRESENT) ) {
233 /* New style handover: Send CMD_START_FLASH, which will reset the board and
234 * enter the bootrom on the next boot.
235 */
236 c.cmd = CMD_START_FLASH;
237 SendCommand(&c, false);
238 fprintf(stderr,"(You don't have to do anything. Press and release the button only if you want to abort)\n");
239 fprintf(stderr,"Waiting for Proxmark to reappear on USB... ");
240 } else {
241 /* Old style handover: Ask the user to press the button, then reset the board */
242 c.cmd = CMD_HARDWARE_RESET;
243 SendCommand(&c, false);
244 fprintf(stderr,"(Press and hold down button NOW if your bootloader requires it)\n");
245 fprintf(stderr,"Waiting for Proxmark to reappear on USB... ");
246 }
247
248 CloseProxmark();
249 sleep(1);
250
251 while(!(devh=OpenProxmark(0))) { sleep(1); }
252 fprintf(stderr,"Found.\n");
253
254 return GetProxmarkState();
255 }
256
257 return 0;
258 }
259
260 static void usage(char **argv)
261 {
262 int i;
263 fprintf(stderr, "Usage: %s areas image [image [image]]\n", argv[0]);
264 fprintf(stderr, " areas is a comma-separated list of areas to flash, with no spaces\n");
265 fprintf(stderr, " Known areas are:");
266 for(i=0; i<(sizeof(partitions)/sizeof(partitions[0])); i++) {
267 fprintf(stderr, " %s", partitions[i].name);
268 }
269 fprintf(stderr, "\n");
270 fprintf(stderr, " image is the path to the corresponding image\n\n");
271 fprintf(stderr, "Example: %s os,fpga path/to/osimage.s19 path/to/fpgaimage.s19\n", argv[0]);
272 }
273
274 /* On first call, have *offset = -1, *length = 0; */
275 static int find_next_area(const char *str, int *offset, int *length)
276 {
277 if(*str == '\0') return 0;
278 if((*offset >= 0) && str[*offset + *length] == '\0') return 0;
279 *offset += 1 + *length;
280
281 char *next_comma = strchr(str + *offset, ',');
282 if(next_comma == NULL) {
283 *length = strlen(str) - *offset;
284 } else {
285 *length = next_comma-(str+*offset);
286 }
287 return 1;
288 }
289
290 int main(int argc, char **argv) {
291 if(argc < 2) {
292 usage(argv);
293 exit(-1);
294 }
295
296 /* Count area arguments */
297 int areas = 0, offset=-1, length=0;
298 while(find_next_area(argv[1], &offset, &length)) areas++;
299
300 if(areas != argc - 2) {
301 usage(argv);
302 exit(-1);
303 }
304
305 usb_init();
306
307 fprintf(stderr,"Waiting for Proxmark to appear on USB... ");
308 while(!(devh=OpenProxmark(0))) { sleep(1); }
309 fprintf(stderr,"Found.\n");
310
311 unsigned int state = EnterFlashState();
312
313 if( !(state & DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM) ) {
314 fprintf(stderr, "Proxmark would not enter flash state, abort\n");
315 exit(-1);
316 }
317
318 offset=-1; length=0;
319 int current_area = 0;
320 while(find_next_area(argv[1], &offset, &length)) {
321 int i;
322 struct partition *p = NULL;
323 for(i=0; i<sizeof(partitions)/sizeof(partitions[0]); i++) {
324 if(strncmp(partitions[i].name, argv[1] + offset, length) == 0) {
325 /* Check if the name matches the bootrom partition, and if so, require "bootrom" to
326 * be written in full. The other names may be abbreviated.
327 */
328 if(!partitions[i].precious || (strlen(partitions[i].name) == length)) {
329 p = &partitions[i];
330 }
331 break;
332 }
333 }
334
335 if(p == NULL) {
336 fprintf(stderr, "Warning: area name '");
337 fwrite(argv[1]+offset, length, 1, stderr);
338 fprintf(stderr, "' unknown, ignored\n");
339 } else {
340 fprintf(stderr, "Flashing %s from %s\n", p->name, argv[2+current_area]);
341 PrepareFlash(p, argv[2+current_area], state);
342 }
343 current_area++;
344 }
345
346 UsbCommand c;
347 bzero(&c, sizeof(c));
348 c.cmd = CMD_HARDWARE_RESET;
349 SendCommand(&c, false);
350
351 CloseProxmark();
352
353 fprintf(stderr,"Have a nice day!\n");
354
355 return 0;
356 }
Impressum, Datenschutz