5 #define bzero(b,len) (memset((b), '\0', (len)), (void) 0)
22 #include "proxmark3.h"
26 static uint32_t ExpectedAddr
;
27 static uint8_t QueuedToSend
[256];
28 static bool AllWritten
;
29 #define PHYSICAL_FLASH_START 0x100000
31 void WaitForAck(void) {
34 if(ack
.cmd
!= CMD_ACK
) {
40 struct partition partitions
[] = {
41 {0x100000, 0x102000, 1, "bootrom"},
42 {0x102000, 0x110000, 0, "fpga"},
43 {0x110000, 0x140000, 0, "os"},
47 /* If translate is set, subtract PHYSICAL_FLASH_START to translate for old
50 void FlushPrevious(int translate
)
53 memset(&c
, 0, sizeof(c
));
55 printf("expected = %08x flush, ", ExpectedAddr
);
58 for(i
= 0; i
< 240; i
+= 48) {
59 c
.cmd
= CMD_SETUP_WRITE
;
60 memcpy(c
.d
.asBytes
, QueuedToSend
+i
, 48);
66 c
.cmd
= CMD_FINISH_WRITE
;
67 c
.arg
[0] = (ExpectedAddr
-1) & (~255);
69 c
.arg
[0] -= PHYSICAL_FLASH_START
;
71 printf("c.arg[0] = %08x\r", c
.arg
[0]);
72 memcpy(c
.d
.asBytes
, QueuedToSend
+240, 16);
79 /* Where must be between start_addr (inclusive) and end_addr (exclusive).
81 void GotByte(uint32_t where
, uint8_t which
, int start_addr
, int end_addr
, int translate
)
85 if(where
< start_addr
|| where
>= end_addr
) {
86 printf("bad: got byte at %08x, outside of range %08x-%08x\n", where
, start_addr
, end_addr
);
90 if(where
!= ExpectedAddr
) {
91 printf("bad: got at %08x, expected at %08x\n", where
, ExpectedAddr
);
94 QueuedToSend
[where
& 255] = which
;
97 if((where
& 255) == 255) {
98 // we have completed a full page
99 FlushPrevious(translate
);
106 if(c
>= '0' && c
<= '9') {
108 } else if(c
>= 'a' && c
<= 'f') {
109 return (c
- 'a') + 10;
111 printf("bad hex digit '%c'\n", c
);
116 uint8_t HexByte(char *s
)
118 return (HexVal(s
[0]) << 4) | HexVal(s
[1]);
121 void LoadFlashFromSRecords(const char *file
, int start_addr
, int end_addr
, int translate
)
123 ExpectedAddr
= start_addr
;
125 FILE *f
= fopen(file
, "r");
127 printf("couldn't open file\n");
132 while(fgets(line
, sizeof(line
), f
)) {
133 if(memcmp(line
, "S3", 2)==0) {
135 int len
= HexByte(s
) - 5;
139 memcpy(addrStr
, s
, 8);
142 sscanf(addrStr
, "%x", &addr
);
145 /* Accept files that are located at PHYSICAL_FLASH_START, and files that are located at 0 */
146 if(addr
< PHYSICAL_FLASH_START
)
147 addr
+= PHYSICAL_FLASH_START
;
150 for(i
= 0; i
< len
; i
++) {
151 while((addr
+i
) > ExpectedAddr
) {
152 GotByte(ExpectedAddr
, 0xff, start_addr
, end_addr
, translate
);
154 GotByte(addr
+i
, HexByte(s
), start_addr
, end_addr
, translate
);
160 if(!AllWritten
) FlushPrevious(translate
);
166 int PrepareFlash(struct partition
*p
, const char *filename
, unsigned int state
)
169 if(state
& DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH
) {
171 c
.cmd
= CMD_START_FLASH
;
175 /* Only send magic when flashing bootrom */
177 c
.arg
[2] = START_FLASH_MAGIC
;
185 fprintf(stderr
, "Warning: Your bootloader does not understand the new START_FLASH command\n");
186 fprintf(stderr
, " It is recommended that you update your bootloader\n\n");
190 LoadFlashFromSRecords(filename
, p
->start
, p
->end
, translate
);
194 unsigned int GetProxmarkState(void)
196 unsigned int state
= 0;
199 c
.cmd
= CMD_DEVICE_INFO
;
203 ReceiveCommand(&resp
);
205 * 1. The old bootrom code will ignore CMD_DEVICE_INFO, but respond with an ACK
206 * 2. The old os code will respond with CMD_DEBUG_PRINT_STRING and "unknown command"
207 * 3. The new bootrom and os codes will respond with CMD_DEVICE_INFO and flags
212 state
= DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM
;
214 case CMD_DEBUG_PRINT_STRING
:
215 state
= DEVICE_INFO_FLAG_CURRENT_MODE_OS
;
217 case CMD_DEVICE_INFO
:
221 fprintf(stderr
, "Couldn't get proxmark state, bad response type: 0x%04X\n", resp
.cmd
);
229 unsigned int EnterFlashState(void)
231 unsigned int state
= GetProxmarkState();
233 if(state
& DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM
) {
234 /* Already in flash state, we're done. */
238 if(state
& DEVICE_INFO_FLAG_CURRENT_MODE_OS
) {
239 fprintf(stderr
,"Entering flash-mode...\n");
241 bzero(&c
, sizeof(c
));
243 if( (state
& DEVICE_INFO_FLAG_BOOTROM_PRESENT
) && (state
& DEVICE_INFO_FLAG_OSIMAGE_PRESENT
) ) {
244 /* New style handover: Send CMD_START_FLASH, which will reset the board and
245 * enter the bootrom on the next boot.
247 c
.cmd
= CMD_START_FLASH
;
249 fprintf(stderr
,"(You don't have to do anything. Press and release the button only if you want to abort)\n");
250 fprintf(stderr
,"Waiting for Proxmark to reappear on USB... ");
252 /* Old style handover: Ask the user to press the button, then reset the board */
253 c
.cmd
= CMD_HARDWARE_RESET
;
255 fprintf(stderr
,"(Press and hold down button NOW if your bootloader requires it)\n");
256 fprintf(stderr
,"Waiting for Proxmark to reappear on USB... ");
261 while(!UsbConnect()) { Sleep(1000); }
266 while(!(devh
=OpenProxmark(0))) { sleep(1); }
268 fprintf(stderr
,"Found.\n");
270 return GetProxmarkState();
276 /* On first call, have *offset = -1, *length = 0; */
277 int find_next_area(const char *str
, int *offset
, int *length
)
279 if(*str
== '\0') return 0;
280 if((*offset
>= 0) && str
[*offset
+ *length
] == '\0') return 0;
281 *offset
+= 1 + *length
;
283 char *next_comma
= strchr(str
+ *offset
, ',');
284 if(next_comma
== NULL
) {
285 *length
= strlen(str
) - *offset
;
287 *length
= next_comma
-(str
+*offset
);
292 void do_flash(char **argv
) {
293 unsigned int state
= EnterFlashState();
295 if (!(state
& DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM
)) {
296 fprintf(stderr
, "Proxmark would not enter flash state, abort\n");
300 int offset
=-1, length
=0;
301 int current_area
= 0;
302 while(find_next_area(argv
[1], &offset
, &length
)) {
304 struct partition
*p
= NULL
;
305 for (i
=0; i
<sizeof(partitions
)/sizeof(partitions
[0]); i
++) {
306 if (strncmp(partitions
[i
].name
, argv
[1] + offset
, length
) == 0) {
307 /* Check if the name matches the bootrom partition, and if so, require "bootrom" to
308 * be written in full. The other names may be abbreviated.
310 if(!partitions
[i
].precious
|| (strlen(partitions
[i
].name
) == length
))
317 fprintf(stderr
, "Warning: area name '");
318 fwrite(argv
[1]+offset
, length
, 1, stderr
);
319 fprintf(stderr
, "' unknown, ignored\n");
321 fprintf(stderr
, "Flashing %s from %s\n", p
->name
, argv
[2+current_area
]);
322 PrepareFlash(p
, argv
[2+current_area
], state
);