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
26 struct partition partitions
[] = {
27 {0x100000, 0x102000, 1, "bootrom"},
28 {0x102000, 0x110000, 0, "fpga"},
29 {0x110000, 0x140000, 0, "os"},
32 /* If translate is set, subtract PHYSICAL_FLASH_START to translate for old
35 static void FlushPrevious(int translate
)
38 memset(&c
, 0, sizeof(c
));
40 printf("expected = %08x flush, ", ExpectedAddr
);
43 for(i
= 0; i
< 240; i
+= 48) {
44 c
.cmd
= CMD_SETUP_WRITE
;
45 memcpy(c
.d
.asBytes
, QueuedToSend
+i
, 48);
47 SendCommand(&c
, true);
50 c
.cmd
= CMD_FINISH_WRITE
;
51 c
.arg
[0] = (ExpectedAddr
-1) & (~255);
53 c
.arg
[0] -= PHYSICAL_FLASH_START
;
55 printf("c.arg[0] = %08x\r", c
.arg
[0]);
56 memcpy(c
.d
.asBytes
, QueuedToSend
+240, 16);
57 SendCommand(&c
, true);
62 /* Where must be between start_addr (inclusive) and end_addr (exclusive).
64 static void GotByte(uint32_t where
, uint8_t which
, int start_addr
, int end_addr
, int translate
)
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
);
73 if(where
!= ExpectedAddr
) {
74 printf("bad: got at %08x, expected at %08x\n", where
, ExpectedAddr
);
77 QueuedToSend
[where
& 255] = which
;
80 if((where
& 255) == 255) {
81 // we have completed a full page
82 FlushPrevious(translate
);
86 static int HexVal(int c
)
89 if(c
>= '0' && c
<= '9') {
91 } else if(c
>= 'a' && c
<= 'f') {
92 return (c
- 'a') + 10;
94 printf("bad hex digit '%c'\n", c
);
99 static uint8_t HexByte(char *s
)
101 return (HexVal(s
[0]) << 4) | HexVal(s
[1]);
104 static void LoadFlashFromSRecords(const char *file
, int start_addr
, int end_addr
, int translate
)
106 ExpectedAddr
= start_addr
;
108 FILE *f
= fopen(file
, "r");
110 printf("couldn't open file\n");
115 while(fgets(line
, sizeof(line
), f
)) {
116 if(memcmp(line
, "S3", 2)==0) {
118 int len
= HexByte(s
) - 5;
122 memcpy(addrStr
, s
, 8);
125 sscanf(addrStr
, "%x", &addr
);
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
;
133 for(i
= 0; i
< len
; i
++) {
134 while((addr
+i
) > ExpectedAddr
) {
135 GotByte(ExpectedAddr
, 0xff, start_addr
, end_addr
, translate
);
137 GotByte(addr
+i
, HexByte(s
), start_addr
, end_addr
, translate
);
143 if(!AllWritten
) FlushPrevious(translate
);
149 static int PrepareFlash(struct partition
*p
, const char *filename
, unsigned int state
)
152 if(state
& DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH
) {
154 c
.cmd
= CMD_START_FLASH
;
158 /* Only send magic when flashing bootrom */
160 c
.arg
[2] = START_FLASH_MAGIC
;
164 SendCommand(&c
, true);
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");
172 LoadFlashFromSRecords(filename
, p
->start
, p
->end
, translate
);
176 static unsigned int GetProxmarkState(void)
178 unsigned int state
= 0;
181 c
.cmd
= CMD_DEVICE_INFO
;
182 SendCommand(&c
, false);
185 ReceiveCommand(&resp
);
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
194 state
= DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM
;
196 case CMD_DEBUG_PRINT_STRING
:
197 state
= DEVICE_INFO_FLAG_CURRENT_MODE_OS
;
199 case CMD_DEVICE_INFO
:
203 fprintf(stderr
, "Couldn't get proxmark state, bad response type: 0x%04X\n", resp
.cmd
);
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");
218 static unsigned int EnterFlashState(void)
220 unsigned int state
= GetProxmarkState();
222 if(state
& DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM
) {
223 /* Already in flash state, we're done. */
227 if(state
& DEVICE_INFO_FLAG_CURRENT_MODE_OS
) {
228 fprintf(stderr
,"Entering flash-mode...\n");
230 bzero(&c
, sizeof(c
));
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.
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... ");
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... ");
251 while(!(devh
=OpenProxmark(0))) { sleep(1); }
252 fprintf(stderr
,"Found.\n");
254 return GetProxmarkState();
260 static void usage(char **argv
)
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
);
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]);
274 /* On first call, have *offset = -1, *length = 0; */
275 static int find_next_area(const char *str
, int *offset
, int *length
)
277 if(*str
== '\0') return 0;
278 if((*offset
>= 0) && str
[*offset
+ *length
] == '\0') return 0;
279 *offset
+= 1 + *length
;
281 char *next_comma
= strchr(str
+ *offset
, ',');
282 if(next_comma
== NULL
) {
283 *length
= strlen(str
) - *offset
;
285 *length
= next_comma
-(str
+*offset
);
290 int main(int argc
, char **argv
) {
296 /* Count area arguments */
297 int areas
= 0, offset
=-1, length
=0;
298 while(find_next_area(argv
[1], &offset
, &length
)) areas
++;
300 if(areas
!= argc
- 2) {
307 fprintf(stderr
,"Waiting for Proxmark to appear on USB... ");
308 while(!(devh
=OpenProxmark(0))) { sleep(1); }
309 fprintf(stderr
,"Found.\n");
311 unsigned int state
= EnterFlashState();
313 if( !(state
& DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM
) ) {
314 fprintf(stderr
, "Proxmark would not enter flash state, abort\n");
319 int current_area
= 0;
320 while(find_next_area(argv
[1], &offset
, &length
)) {
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.
328 if(!partitions
[i
].precious
|| (strlen(partitions
[i
].name
) == length
)) {
336 fprintf(stderr
, "Warning: area name '");
337 fwrite(argv
[1]+offset
, length
, 1, stderr
);
338 fprintf(stderr
, "' unknown, ignored\n");
340 fprintf(stderr
, "Flashing %s from %s\n", p
->name
, argv
[2+current_area
]);
341 PrepareFlash(p
, argv
[2+current_area
], state
);
347 bzero(&c
, sizeof(c
));
348 c
.cmd
= CMD_HARDWARE_RESET
;
349 SendCommand(&c
, false);
353 fprintf(stderr
,"Have a nice day!\n");