13 #include "proxmark3.h"
15 static uint32_t ExpectedAddr
;
16 static uint8_t QueuedToSend
[256];
17 static bool AllWritten
;
18 #define PHYSICAL_FLASH_START 0x100000
19 unsigned int current_command
= CMD_UNKNOWN
;
21 void WaitForAck(void) {
24 if(ack
.cmd
!= CMD_ACK
) {
36 struct partition partitions
[] = {
37 {0x100000, 0x102000, 1, "bootrom"},
38 {0x102000, 0x110000, 0, "fpga"},
39 {0x110000, 0x140000, 0, "os"},
42 /* If translate is set, subtract PHYSICAL_FLASH_START to translate for old
45 static void FlushPrevious(int translate
)
48 memset(&c
, 0, sizeof(c
));
50 printf("expected = %08x flush, ", ExpectedAddr
);
53 for(i
= 0; i
< 240; i
+= 48) {
54 c
.cmd
= CMD_SETUP_WRITE
;
55 memcpy(c
.d
.asBytes
, QueuedToSend
+i
, 48);
61 c
.cmd
= CMD_FINISH_WRITE
;
62 c
.arg
[0] = (ExpectedAddr
-1) & (~255);
64 c
.arg
[0] -= PHYSICAL_FLASH_START
;
66 printf("c.arg[0] = %08x\r", c
.arg
[0]);
67 memcpy(c
.d
.asBytes
, QueuedToSend
+240, 16);
74 /* Where must be between start_addr (inclusive) and end_addr (exclusive).
76 static void GotByte(uint32_t where
, uint8_t which
, int start_addr
, int end_addr
, int translate
)
80 if(where
< start_addr
|| where
>= end_addr
) {
81 printf("bad: got byte at %08x, outside of range %08x-%08x\n", where
, start_addr
, end_addr
);
85 if(where
!= ExpectedAddr
) {
86 printf("bad: got at %08x, expected at %08x\n", where
, ExpectedAddr
);
89 QueuedToSend
[where
& 255] = which
;
92 if((where
& 255) == 255) {
93 // we have completed a full page
94 FlushPrevious(translate
);
98 static int HexVal(int c
)
101 if(c
>= '0' && c
<= '9') {
103 } else if(c
>= 'a' && c
<= 'f') {
104 return (c
- 'a') + 10;
106 printf("bad hex digit '%c'\n", c
);
111 static uint8_t HexByte(char *s
)
113 return (HexVal(s
[0]) << 4) | HexVal(s
[1]);
116 static void LoadFlashFromSRecords(const char *file
, int start_addr
, int end_addr
, int translate
)
118 ExpectedAddr
= start_addr
;
120 FILE *f
= fopen(file
, "r");
122 printf("couldn't open file\n");
127 while(fgets(line
, sizeof(line
), f
)) {
128 if(memcmp(line
, "S3", 2)==0) {
130 int len
= HexByte(s
) - 5;
134 memcpy(addrStr
, s
, 8);
137 sscanf(addrStr
, "%x", &addr
);
140 /* Accept files that are located at PHYSICAL_FLASH_START, and files that are located at 0 */
141 if(addr
< PHYSICAL_FLASH_START
)
142 addr
+= PHYSICAL_FLASH_START
;
145 for(i
= 0; i
< len
; i
++) {
146 while((addr
+i
) > ExpectedAddr
) {
147 GotByte(ExpectedAddr
, 0xff, start_addr
, end_addr
, translate
);
149 GotByte(addr
+i
, HexByte(s
), start_addr
, end_addr
, translate
);
155 if(!AllWritten
) FlushPrevious(translate
);
161 static int PrepareFlash(struct partition
*p
, const char *filename
, unsigned int state
)
164 if(state
& DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH
) {
166 c
.cmd
= CMD_START_FLASH
;
170 /* Only send magic when flashing bootrom */
172 c
.arg
[2] = START_FLASH_MAGIC
;
180 fprintf(stderr
, "Warning: Your bootloader does not understand the new START_FLASH command\n");
181 fprintf(stderr
, " It is recommended that you update your bootloader\n\n");
185 LoadFlashFromSRecords(filename
, p
->start
, p
->end
, translate
);
189 static unsigned int GetProxmarkState(void)
191 unsigned int state
= 0;
194 c
.cmd
= CMD_DEVICE_INFO
;
198 ReceiveCommand(&resp
);
200 * 1. The old bootrom code will ignore CMD_DEVICE_INFO, but respond with an ACK
201 * 2. The old os code will respond with CMD_DEBUG_PRINT_STRING and "unknown command"
202 * 3. The new bootrom and os codes will respond with CMD_DEVICE_INFO and flags
207 state
= DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM
;
209 case CMD_DEBUG_PRINT_STRING
:
210 state
= DEVICE_INFO_FLAG_CURRENT_MODE_OS
;
212 case CMD_DEVICE_INFO
:
216 fprintf(stderr
, "Couldn't get proxmark state, bad response type: 0x%04X\n", resp
.cmd
);
222 if(state
& DEVICE_INFO_FLAG_BOOTROM_PRESENT
) printf("New bootrom present\n");
223 if(state
& DEVICE_INFO_FLAG_OSIMAGE_PRESENT
) printf("New osimage present\n");
224 if(state
& DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM
) printf("Currently in bootrom\n");
225 if(state
& DEVICE_INFO_FLAG_CURRENT_MODE_OS
) printf("Currently in OS\n");
231 static unsigned int EnterFlashState(void)
233 unsigned int state
= GetProxmarkState();
235 if(state
& DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM
) {
236 /* Already in flash state, we're done. */
240 if(state
& DEVICE_INFO_FLAG_CURRENT_MODE_OS
) {
241 fprintf(stderr
,"Entering flash-mode...\n");
243 bzero(&c
, sizeof(c
));
245 if( (state
& DEVICE_INFO_FLAG_BOOTROM_PRESENT
) && (state
& DEVICE_INFO_FLAG_OSIMAGE_PRESENT
) ) {
246 /* New style handover: Send CMD_START_FLASH, which will reset the board and
247 * enter the bootrom on the next boot.
249 c
.cmd
= CMD_START_FLASH
;
251 fprintf(stderr
,"(You don't have to do anything. Press and release the button only if you want to abort)\n");
252 fprintf(stderr
,"Waiting for Proxmark to reappear on USB... ");
254 /* Old style handover: Ask the user to press the button, then reset the board */
255 c
.cmd
= CMD_HARDWARE_RESET
;
257 fprintf(stderr
,"(Press and hold down button NOW if your bootloader requires it)\n");
258 fprintf(stderr
,"Waiting for Proxmark to reappear on USB... ");
264 while(!(devh
=OpenProxmark(0))) { sleep(1); }
265 fprintf(stderr
,"Found.\n");
267 return GetProxmarkState();
273 static void usage(char **argv
)
276 fprintf(stderr
, "Usage: %s areas image [image [image]]\n", argv
[0]);
277 fprintf(stderr
, " areas is a comma-separated list of areas to flash, with no spaces\n");
278 fprintf(stderr
, " Known areas are:");
279 for(i
=0; i
<(sizeof(partitions
)/sizeof(partitions
[0])); i
++) {
280 fprintf(stderr
, " %s", partitions
[i
].name
);
282 fprintf(stderr
, "\n");
283 fprintf(stderr
, " image is the path to the corresponding image\n\n");
284 fprintf(stderr
, "Example: %s os,fpga path/to/osimage.s19 path/to/fpgaimage.s19\n", argv
[0]);
287 /* On first call, have *offset = -1, *length = 0; */
288 static int find_next_area(const char *str
, int *offset
, int *length
)
290 if(*str
== '\0') return 0;
291 if((*offset
>= 0) && str
[*offset
+ *length
] == '\0') return 0;
292 *offset
+= 1 + *length
;
294 char *next_comma
= strchr(str
+ *offset
, ',');
295 if(next_comma
== NULL
) {
296 *length
= strlen(str
) - *offset
;
298 *length
= next_comma
-(str
+*offset
);
303 int main(int argc
, char **argv
) {
309 /* Count area arguments */
310 int areas
= 0, offset
=-1, length
=0;
311 while(find_next_area(argv
[1], &offset
, &length
)) areas
++;
313 if(areas
!= argc
- 2) {
320 fprintf(stderr
,"Waiting for Proxmark to appear on USB... ");
321 while(!(devh
=OpenProxmark(0))) { sleep(1); }
322 fprintf(stderr
,"Found.\n");
324 unsigned int state
= EnterFlashState();
326 if( !(state
& DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM
) ) {
327 fprintf(stderr
, "Proxmark would not enter flash state, abort\n");
332 int current_area
= 0;
333 while(find_next_area(argv
[1], &offset
, &length
)) {
335 struct partition
*p
= NULL
;
336 for(i
=0; i
<sizeof(partitions
)/sizeof(partitions
[0]); i
++) {
337 if(strncmp(partitions
[i
].name
, argv
[1] + offset
, length
) == 0) {
338 /* Check if the name matches the bootrom partition, and if so, require "bootrom" to
339 * be written in full. The other names may be abbreviated.
341 if(!partitions
[i
].precious
|| (strlen(partitions
[i
].name
) == length
)) {
349 fprintf(stderr
, "Warning: area name '");
350 fwrite(argv
[1]+offset
, length
, 1, stderr
);
351 fprintf(stderr
, "' unknown, ignored\n");
353 fprintf(stderr
, "Flashing %s from %s\n", p
->name
, argv
[2+current_area
]);
354 PrepareFlash(p
, argv
[2+current_area
], state
);
360 bzero(&c
, sizeof(c
));
361 c
.cmd
= CMD_HARDWARE_RESET
;
366 fprintf(stderr
,"Have a nice day!\n");