Merge branch 'master' of github.com:RfidResearchGroup/proxmark3
[RRG-proxmark3.git] / tools / deprecated-hid-flasher / flasher / flash.c
blob179693d8be0bbc56fd27ca22fe7d258c3a12a3ad
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 Hector Martin "marcan" <marcan@marcansoft.com>
3 //
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
6 // the license.
7 //-----------------------------------------------------------------------------
8 // ELF file flasher
9 //-----------------------------------------------------------------------------
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include "proxusb.h"
15 #include "flash.h"
16 #include "elf.h"
17 #include "proxendian.h"
18 #include "sleep.h"
20 #define FLASH_START 0x100000
21 #define FLASH_SIZE (256*1024)
22 #define FLASH_END (FLASH_START + FLASH_SIZE)
23 #define BOOTLOADER_SIZE 0x2000
24 #define BOOTLOADER_END (FLASH_START + BOOTLOADER_SIZE)
26 #define BLOCK_SIZE 0x100
28 static const uint8_t elf_ident[] = {
29 0x7f, 'E', 'L', 'F',
30 ELFCLASS32,
31 ELFDATA2LSB,
32 EV_CURRENT
35 // Turn PHDRs into flasher segments, checking for PHDR sanity and merging adjacent
36 // unaligned segments if needed
37 static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, int num_phdrs) {
38 Elf32_Phdr *phdr = phdrs;
39 flash_seg_t *seg;
40 uint32_t last_end = 0;
42 ctx->segments = calloc(sizeof(flash_seg_t) * num_phdrs, sizeof(uint8_t));
43 if (!ctx->segments) {
44 fprintf(stderr, "Out of memory\n");
45 return -1;
47 ctx->num_segs = 0;
48 seg = ctx->segments;
50 fprintf(stdout, "Loading usable ELF segments:\n");
51 for (int i = 0; i < num_phdrs; i++) {
52 if (le32(phdr->p_type) != PT_LOAD) {
53 phdr++;
54 continue;
56 uint32_t vaddr = le32(phdr->p_vaddr);
57 uint32_t paddr = le32(phdr->p_paddr);
58 uint32_t filesz = le32(phdr->p_filesz);
59 uint32_t memsz = le32(phdr->p_memsz);
60 uint32_t offset = le32(phdr->p_offset);
61 uint32_t flags = le32(phdr->p_flags);
62 if (!filesz) {
63 phdr++;
64 continue;
66 fprintf(stdout, "%d: V 0x%08x P 0x%08x (0x%08x->0x%08x) [%c%c%c] @0x%x\n",
67 i, vaddr, paddr, filesz, memsz,
68 (flags & PF_R) ? 'R' : ' ',
69 (flags & PF_W) ? 'W' : ' ',
70 (flags & PF_X) ? 'X' : ' ',
71 offset);
72 if (filesz != memsz) {
73 fprintf(stderr, "Error: PHDR file size does not equal memory size\n"
74 "(DATA+BSS PHDRs do not make sense on ROM platforms!)\n");
75 return -1;
77 if (paddr < last_end) {
78 fprintf(stderr, "Error: PHDRs not sorted or overlap\n");
79 return -1;
81 if (paddr < FLASH_START || (paddr + filesz) > FLASH_END) {
82 fprintf(stderr, "Error: PHDR is not contained in Flash\n");
83 return -1;
85 if (vaddr >= FLASH_START && vaddr < FLASH_END && (flags & PF_W)) {
86 fprintf(stderr, "Error: Flash VMA segment is writable\n");
87 return -1;
90 uint8_t *data;
91 // make extra space if we need to move the data forward
92 data = calloc(filesz + BLOCK_SIZE, sizeof(uint8_t));
93 if (!data) {
94 fprintf(stderr, "Error: Out of memory\n");
95 return -1;
97 if (fseek(fd, offset, SEEK_SET) < 0 || fread(data, 1, filesz, fd) != filesz) {
98 fprintf(stderr, "Error while reading PHDR payload\n");
99 free(data);
100 return -1;
103 uint32_t block_offset = paddr & (BLOCK_SIZE - 1);
104 if (block_offset) {
105 if (ctx->num_segs) {
106 flash_seg_t *prev_seg = seg - 1;
107 uint32_t this_end = paddr + filesz;
108 uint32_t this_firstblock = paddr & ~(BLOCK_SIZE - 1);
109 uint32_t prev_lastblock = (last_end - 1) & ~(BLOCK_SIZE - 1);
111 if (this_firstblock == prev_lastblock) {
112 uint32_t new_length = this_end - prev_seg->start;
113 uint32_t this_offset = paddr - prev_seg->start;
114 uint32_t hole = this_offset - prev_seg->length;
115 uint8_t *new_data = calloc(new_length, sizeof(uint8_t));
116 if (!new_data) {
117 fprintf(stderr, "Error: Out of memory\n");
118 free(data);
119 return -1;
121 memset(new_data, 0xff, new_length);
122 memcpy(new_data, prev_seg->data, prev_seg->length);
123 memcpy(new_data + this_offset, data, filesz);
124 fprintf(stderr, "Note: Extending previous segment from 0x%x to 0x%x bytes\n",
125 prev_seg->length, new_length);
126 if (hole)
127 fprintf(stderr, "Note: 0x%x-byte hole created\n", hole);
128 free(data);
129 free(prev_seg->data);
130 prev_seg->data = new_data;
131 prev_seg->length = new_length;
132 last_end = this_end;
133 phdr++;
134 continue;
137 fprintf(stderr, "Warning: segment does not begin on a block boundary, will pad\n");
138 memmove(data + block_offset, data, filesz);
139 memset(data, 0xFF, block_offset);
140 filesz += block_offset;
141 paddr -= block_offset;
144 seg->data = data;
145 seg->start = paddr;
146 seg->length = filesz;
147 seg++;
148 ctx->num_segs++;
150 last_end = paddr + filesz;
151 phdr++;
153 return 0;
156 // Sanity check segments and check for bootloader writes
157 static int check_segs(flash_file_t *ctx, int can_write_bl) {
158 for (int i = 0; i < ctx->num_segs; i++) {
159 flash_seg_t *seg = &ctx->segments[i];
161 if (seg->start & (BLOCK_SIZE - 1)) {
162 fprintf(stderr, "Error: Segment is not aligned\n");
163 return -1;
165 if (seg->start < FLASH_START) {
166 fprintf(stderr, "Error: Segment is outside of flash bounds\n");
167 return -1;
169 if (seg->start + seg->length > FLASH_END) {
170 fprintf(stderr, "Error: Segment is outside of flash bounds\n");
171 return -1;
173 if (!can_write_bl && seg->start < BOOTLOADER_END) {
174 fprintf(stderr, "Attempted to write bootloader but bootloader writes are not enabled\n");
175 return -1;
178 return 0;
181 // Load an ELF file and prepare it for flashing
182 int flash_load(flash_file_t *ctx, const char *name, int can_write_bl) {
183 FILE *fd;
184 Elf32_Ehdr ehdr;
185 Elf32_Phdr *phdrs = NULL;
186 int num_phdrs;
187 int res;
189 fd = fopen(name, "rb");
190 if (!fd) {
191 fprintf(stderr, "Could not open file '%s': ", name);
192 perror(NULL);
193 goto fail;
196 fprintf(stderr, "Loading ELF file '%s'...\n", name);
198 if (fread(&ehdr, sizeof(ehdr), 1, fd) != 1) {
199 fprintf(stderr, "Error while reading ELF file header\n");
200 goto fail;
202 if (memcmp(ehdr.e_ident, elf_ident, sizeof(elf_ident))
203 || le32(ehdr.e_version) != 1) {
204 fprintf(stderr, "Not an ELF file or wrong ELF type\n");
205 goto fail;
207 if (le16(ehdr.e_type) != ET_EXEC) {
208 fprintf(stderr, "ELF is not executable\n");
209 goto fail;
211 if (le16(ehdr.e_machine) != EM_ARM) {
212 fprintf(stderr, "Wrong ELF architecture\n");
213 goto fail;
215 if (!ehdr.e_phnum || !ehdr.e_phoff) {
216 fprintf(stderr, "ELF has no PHDRs\n");
217 goto fail;
219 if (le16(ehdr.e_phentsize) != sizeof(Elf32_Phdr)) {
220 // could be a structure padding issue...
221 fprintf(stderr, "Either the ELF file or this code is made of fail\n");
222 goto fail;
224 num_phdrs = le16(ehdr.e_phnum);
226 phdrs = calloc(le16(ehdr.e_phnum) * sizeof(Elf32_Phdr), sizeof(uint8_t));
227 if (!phdrs) {
228 fprintf(stderr, "Out of memory\n");
229 goto fail;
231 if (fseek(fd, le32(ehdr.e_phoff), SEEK_SET) < 0) {
232 fprintf(stderr, "Error while reading ELF PHDRs\n");
233 goto fail;
235 if (fread(phdrs, sizeof(Elf32_Phdr), num_phdrs, fd) != num_phdrs) {
236 fprintf(stderr, "Error while reading ELF PHDRs\n");
237 goto fail;
240 res = build_segs_from_phdrs(ctx, fd, phdrs, num_phdrs);
241 if (res < 0)
242 goto fail;
243 res = check_segs(ctx, can_write_bl);
244 if (res < 0)
245 goto fail;
247 free(phdrs);
248 fclose(fd);
249 ctx->filename = name;
250 return 0;
252 fail:
253 if (phdrs)
254 free(phdrs);
255 if (fd)
256 fclose(fd);
257 flash_free(ctx);
258 return -1;
261 // Get the state of the proxmark, backwards compatible
262 static int get_proxmark_state(uint32_t *state) {
263 SendCommandBL(CMD_DEVICE_INFO, 0, 0, 0, NULL, 0);
264 PacketResponseOLD resp;
265 ReceiveCommand(&resp);
267 // Three outcomes:
268 // 1. The old bootrom code will ignore CMD_DEVICE_INFO, but respond with an ACK
269 // 2. The old os code will respond with CMD_DEBUG_PRINT_STRING and "unknown command"
270 // 3. The new bootrom and os codes will respond with CMD_DEVICE_INFO and flags
272 switch (resp.cmd) {
273 case CMD_ACK:
274 *state = DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM;
275 break;
276 case CMD_DEBUG_PRINT_STRING:
277 *state = DEVICE_INFO_FLAG_CURRENT_MODE_OS;
278 break;
279 case CMD_DEVICE_INFO:
280 *state = resp.arg[0];
281 break;
282 default:
283 fprintf(stderr, "Error: Couldn't get Proxmark3 state, bad response type: 0x%04x\n", resp.cmd);
284 return -1;
285 break;
288 return 0;
291 // Enter the bootloader to be able to start flashing
292 static int enter_bootloader(void) {
293 uint32_t state;
295 if (get_proxmark_state(&state) < 0)
296 return -1;
298 if (state & DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM) {
299 /* Already in flash state, we're done. */
300 return 0;
303 if (state & DEVICE_INFO_FLAG_CURRENT_MODE_OS) {
304 fprintf(stderr, "Entering bootloader...\n");
306 if ((state & DEVICE_INFO_FLAG_BOOTROM_PRESENT)
307 && (state & DEVICE_INFO_FLAG_OSIMAGE_PRESENT)) {
308 // New style handover: Send CMD_START_FLASH, which will reset the board
309 // and enter the bootrom on the next boot.
310 SendCommandBL(CMD_START_FLASH, 0, 0, 0, NULL, 0);
311 fprintf(stderr, "(Press and release the button only to abort)\n");
312 } else {
313 // Old style handover: Ask the user to press the button, then reset the board
314 SendCommandBL(CMD_HARDWARE_RESET, 0, 0, 0, NULL, 0);
315 fprintf(stderr, "Press and hold down button NOW if your bootloader requires it.\n");
317 fprintf(stderr, "Waiting for Proxmark3 to reappear on USB...");
319 CloseProxmark();
320 msleep(1000);
321 while (!OpenProxmark(0)) {
322 msleep(1000);
323 fprintf(stderr, ".");
324 fflush(stdout);
326 fprintf(stderr, " Found.\n");
328 return 0;
331 fprintf(stderr, "Error: Unknown Proxmark3 mode\n");
332 return -1;
335 static int wait_for_ack(void) {
336 PacketResponseOLD ack;
337 ReceiveCommand(&ack);
338 if (ack.cmd != CMD_ACK) {
339 printf("Error: Unexpected reply 0x%04x (expected ACK)\n", ack.cmd);
340 return -1;
342 return 0;
345 // Go into flashing mode
346 int flash_start_flashing(int enable_bl_writes) {
347 uint32_t state;
349 if (enter_bootloader() < 0)
350 return -1;
352 if (get_proxmark_state(&state) < 0)
353 return -1;
355 if (state & DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH) {
356 // This command is stupid. Why the heck does it care which area we're
357 // flashing, as long as it's not the bootloader area? The mind boggles.
358 if (enable_bl_writes) {
359 SendCommandBL(CMD_START_FLASH, FLASH_START, FLASH_END, START_FLASH_MAGIC, NULL, 0);
360 } else {
361 SendCommandBL(CMD_START_FLASH, BOOTLOADER_END, FLASH_END, 0, NULL, 0);
363 return wait_for_ack();
364 } else {
365 fprintf(stderr, "Note: Your bootloader does not understand the new START_FLASH command\n");
366 fprintf(stderr, " It is recommended that you update your bootloader\n\n");
369 return 0;
372 static int write_block(uint32_t address, uint8_t *data, uint32_t length) {
373 uint8_t block_buf[BLOCK_SIZE];
375 memset(block_buf, 0xFF, BLOCK_SIZE);
376 memcpy(block_buf, data, length);
378 for (int i = 0; i < 240; i += 48) {
379 SendCommandBL(CMD_SETUP_WRITE, i / 4, 0, 0, block_buf + i, 48);
380 if (wait_for_ack() < 0)
381 return -1;
384 SendCommandBL(CMD_FINISH_WRITE, address, 0, 0, block_buf + 240, 16);
385 return wait_for_ack();
388 // Write a file's segments to Flash
389 int flash_write(flash_file_t *ctx) {
390 fprintf(stdout, "Writing segments for file: %s\n", ctx->filename);
391 for (int i = 0; i < ctx->num_segs; i++) {
392 flash_seg_t *seg = &ctx->segments[i];
394 uint32_t length = seg->length;
395 uint32_t blocks = (length + BLOCK_SIZE - 1) / BLOCK_SIZE;
396 uint32_t end = seg->start + length;
398 fprintf(stdout, " 0x%08x..0x%08x [0x%x / %u blocks]", seg->start, end - 1, length, blocks);
399 fflush(stdout);
400 int block = 0;
401 uint8_t *data = seg->data;
402 uint32_t baddr = seg->start;
404 while (length) {
405 uint32_t block_size = length;
406 if (block_size > BLOCK_SIZE)
407 block_size = BLOCK_SIZE;
409 if (write_block(baddr, data, block_size) < 0) {
410 fprintf(stderr, " ERROR\n");
411 fprintf(stderr, "Error writing block %d of %u\n", block, blocks);
412 return -1;
415 data += block_size;
416 baddr += block_size;
417 length -= block_size;
418 block++;
419 fprintf(stdout, ".");
420 fflush(stdout);
422 fprintf(stderr, " OK\n");
423 fflush(stdout);
425 return 0;
428 // free a file context
429 void flash_free(flash_file_t *ctx) {
430 if (!ctx)
431 return;
432 if (ctx->segments) {
433 for (int i = 0; i < ctx->num_segs; i++)
434 free(ctx->segments[i].data);
435 free(ctx->segments);
436 ctx->segments = NULL;
437 ctx->num_segs = 0;
441 // just reset the unit
442 int flash_stop_flashing(void) {
443 SendCommandBL(CMD_HARDWARE_RESET, 0, 0, 0, NULL, 0);
444 msleep(100);
445 return 0;