10 #include "translate.h"
12 #include "proxmark3.h"
14 static DWORD ExpectedAddr
;
15 static BYTE QueuedToSend
[256];
16 static BOOL AllWritten
;
17 #define PHYSICAL_FLASH_START 0x100000
25 struct partition partitions
[] = {
26 {0x100000, 0x102000, 1, "bootrom"},
27 {0x102000, 0x110000, 0, "fpga"},
28 {0x110000, 0x140000, 0, "os"},
31 /* If translate is set, subtract PHYSICAL_FLASH_START to translate for old
34 static void FlushPrevious(int translate
)
37 memset(&c
, 0, sizeof(c
));
39 printf("expected = %08x flush, ", ExpectedAddr
);
42 for(i
= 0; i
< 240; i
+= 48) {
43 c
.cmd
= CMD_SETUP_WRITE
;
44 memcpy(c
.d
.asBytes
, QueuedToSend
+i
, 48);
46 SendCommand(&c
, TRUE
);
49 c
.cmd
= CMD_FINISH_WRITE
;
50 c
.arg
[0] = (ExpectedAddr
-1) & (~255);
52 c
.arg
[0] -= PHYSICAL_FLASH_START
;
54 printf("c.arg[0] = %08x\r", c
.arg
[0]);
55 memcpy(c
.d
.asBytes
, QueuedToSend
+240, 16);
56 SendCommand(&c
, TRUE
);
61 /* Where must be between start_addr (inclusive) and end_addr (exclusive).
63 static void GotByte(DWORD where
, BYTE which
, int start_addr
, int end_addr
, int translate
)
67 if(where
< start_addr
|| where
>= end_addr
) {
68 printf("bad: got byte at %08x, outside of range %08x-%08x\n", where
, start_addr
, end_addr
);
72 if(where
!= ExpectedAddr
) {
73 printf("bad: got at %08x, expected at %08x\n", where
, ExpectedAddr
);
76 QueuedToSend
[where
& 255] = which
;
79 if((where
& 255) == 255) {
80 // we have completed a full page
81 FlushPrevious(translate
);
85 static int HexVal(int c
)
88 if(c
>= '0' && c
<= '9') {
90 } else if(c
>= 'a' && c
<= 'f') {
91 return (c
- 'a') + 10;
93 printf("bad hex digit '%c'\n", c
);
98 static BYTE
HexByte(char *s
)
100 return (HexVal(s
[0]) << 4) | HexVal(s
[1]);
103 static void LoadFlashFromSRecords(const char *file
, int start_addr
, int end_addr
, int translate
)
105 ExpectedAddr
= start_addr
;
107 FILE *f
= fopen(file
, "r");
109 printf("couldn't open file\n");
114 while(fgets(line
, sizeof(line
), f
)) {
115 if(memcmp(line
, "S3", 2)==0) {
117 int len
= HexByte(s
) - 5;
121 memcpy(addrStr
, s
, 8);
124 sscanf(addrStr
, "%x", &addr
);
127 /* Accept files that are located at PHYSICAL_FLASH_START, and files that are located at 0 */
128 if(addr
< PHYSICAL_FLASH_START
)
129 addr
+= PHYSICAL_FLASH_START
;
132 for(i
= 0; i
< len
; i
++) {
133 while((addr
+i
) > ExpectedAddr
) {
134 GotByte(ExpectedAddr
, 0xff, start_addr
, end_addr
, translate
);
136 GotByte(addr
+i
, HexByte(s
), start_addr
, end_addr
, translate
);
142 if(!AllWritten
) FlushPrevious(translate
);
148 static int PrepareFlash(struct partition
*p
, const char *filename
, unsigned int state
)
151 if(state
& DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH
) {
153 c
.cmd
= CMD_START_FLASH
;
157 /* Only send magic when flashing bootrom */
159 c
.arg
[2] = START_FLASH_MAGIC
;
163 SendCommand(&c
, TRUE
);
166 fprintf(stderr
, "Warning: Your bootloader does not understand the new START_FLASH command\n");
167 fprintf(stderr
, " It is recommended that you update your bootloader\n\n");
171 LoadFlashFromSRecords(filename
, p
->start
, p
->end
, translate
);
175 static unsigned int GetProxmarkState(void)
177 unsigned int state
= 0;
180 c
.cmd
= CMD_DEVICE_INFO
;
181 SendCommand(&c
, FALSE
);
184 ReceiveCommand(&resp
);
186 * 1. The old bootrom code will ignore CMD_DEVICE_INFO, but respond with an ACK
187 * 2. The old os code will respond with CMD_DEBUG_PRINT_STRING and "unknown command"
188 * 3. The new bootrom and os codes will respond with CMD_DEVICE_INFO and flags
193 state
= DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM
;
195 case CMD_DEBUG_PRINT_STRING
:
196 state
= DEVICE_INFO_FLAG_CURRENT_MODE_OS
;
198 case CMD_DEVICE_INFO
:
202 fprintf(stderr
, "Couldn't get proxmark state, bad response type: 0x%04X\n", resp
.cmd
);
208 if(state
& DEVICE_INFO_FLAG_BOOTROM_PRESENT
) printf("New bootrom present\n");
209 if(state
& DEVICE_INFO_FLAG_OSIMAGE_PRESENT
) printf("New osimage present\n");
210 if(state
& DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM
) printf("Currently in bootrom\n");
211 if(state
& DEVICE_INFO_FLAG_CURRENT_MODE_OS
) printf("Currently in OS\n");
217 static unsigned int EnterFlashState(void)
219 unsigned int state
= GetProxmarkState();
221 if(state
& DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM
) {
222 /* Already in flash state, we're done. */
226 if(state
& DEVICE_INFO_FLAG_CURRENT_MODE_OS
) {
227 fprintf(stderr
,"Entering flash-mode...\n");
229 bzero(&c
, sizeof(c
));
231 if( (state
& DEVICE_INFO_FLAG_BOOTROM_PRESENT
) && (state
& DEVICE_INFO_FLAG_OSIMAGE_PRESENT
) ) {
232 /* New style handover: Send CMD_START_FLASH, which will reset the board and
233 * enter the bootrom on the next boot.
235 c
.cmd
= CMD_START_FLASH
;
236 SendCommand(&c
, FALSE
);
237 fprintf(stderr
,"(You don't have to do anything. Press and release the button only if you want to abort)\n");
238 fprintf(stderr
,"Waiting for Proxmark to reappear on USB... ");
240 /* Old style handover: Ask the user to press the button, then reset the board */
241 c
.cmd
= CMD_HARDWARE_RESET
;
242 SendCommand(&c
, FALSE
);
243 fprintf(stderr
,"(Press and hold down button NOW if your bootloader requires it)\n");
244 fprintf(stderr
,"Waiting for Proxmark to reappear on USB... ");
250 while(!(devh
=OpenProxmark(0))) { sleep(1); }
251 fprintf(stderr
,"Found.\n");
253 return GetProxmarkState();
259 static void usage(char **argv
)
262 fprintf(stderr
, "Usage: %s areas image [image [image]]\n", argv
[0]);
263 fprintf(stderr
, " areas is a comma-separated list of areas to flash, with no spaces\n");
264 fprintf(stderr
, " Known areas are:");
265 for(i
=0; i
<(sizeof(partitions
)/sizeof(partitions
[0])); i
++) {
266 fprintf(stderr
, " %s", partitions
[i
].name
);
268 fprintf(stderr
, "\n");
269 fprintf(stderr
, " image is the path to the corresponding image\n\n");
270 fprintf(stderr
, "Example: %s os,fpga path/to/osimage.s19 path/to/fpgaimage.s19\n", argv
[0]);
273 /* On first call, have *offset = -1, *length = 0; */
274 static int find_next_area(const char *str
, int *offset
, int *length
)
276 if(*str
== '\0') return 0;
277 if((*offset
>= 0) && str
[*offset
+ *length
] == '\0') return 0;
278 *offset
+= 1 + *length
;
280 char *next_comma
= strchr(str
+ *offset
, ',');
281 if(next_comma
== NULL
) {
282 *length
= strlen(str
) - *offset
;
284 *length
= next_comma
-(str
+*offset
);
289 int main(int argc
, char **argv
) {
295 /* Count area arguments */
296 int areas
= 0, offset
=-1, length
=0;
297 while(find_next_area(argv
[1], &offset
, &length
)) areas
++;
299 if(areas
!= argc
- 2) {
306 fprintf(stderr
,"Waiting for Proxmark to appear on USB... ");
307 while(!(devh
=OpenProxmark(0))) { sleep(1); }
308 fprintf(stderr
,"Found.\n");
310 unsigned int state
= EnterFlashState();
312 if( !(state
& DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM
) ) {
313 fprintf(stderr
, "Proxmark would not enter flash state, abort\n");
318 int current_area
= 0;
319 while(find_next_area(argv
[1], &offset
, &length
)) {
321 struct partition
*p
= NULL
;
322 for(i
=0; i
<sizeof(partitions
)/sizeof(partitions
[0]); i
++) {
323 if(strncmp(partitions
[i
].name
, argv
[1] + offset
, length
) == 0) {
324 /* Check if the name matches the bootrom partition, and if so, require "bootrom" to
325 * be written in full. The other names may be abbreviated.
327 if(!partitions
[i
].precious
|| (strlen(partitions
[i
].name
) == length
)) {
335 fprintf(stderr
, "Warning: area name '");
336 fwrite(argv
[1]+offset
, length
, 1, stderr
);
337 fprintf(stderr
, "' unknown, ignored\n");
339 fprintf(stderr
, "Flashing %s from %s\n", p
->name
, argv
[2+current_area
]);
340 PrepareFlash(p
, argv
[2+current_area
], state
);
346 bzero(&c
, sizeof(c
));
347 c
.cmd
= CMD_HARDWARE_RESET
;
348 SendCommand(&c
, FALSE
);
352 fprintf(stderr
,"Have a nice day!\n");