]> cvs.zerfleddert.de Git - proxmark3-svn/blame - client/flash.c
Removing windows specific code. Everything now compile and work the same for the...
[proxmark3-svn] / client / flash.c
CommitLineData
6e4d4ee6 1#include <stdio.h>
6e4d4ee6 2#include <string.h>
83a9b236 3#include <stdlib.h>
4cd41f34 4#include "sleep.h"
5#include "proxusb.h"
6e4d4ee6 6#include "flash.h"
2cab856f 7#include "elf.h"
6e4d4ee6 8
9static uint32_t ExpectedAddr;
10static uint8_t QueuedToSend[256];
6e4d4ee6 11#define PHYSICAL_FLASH_START 0x100000
2cab856f 12#define PHYSICAL_FLASH_END 0x200000
6e4d4ee6 13
7fe9b0b7 14void WaitForAck(void)
15{
16 UsbCommand ack;
17 ReceiveCommand(&ack);
18 if (ack.cmd != CMD_ACK) {
19 printf("bad ACK\n");
20 exit(-1);
21 }
6e4d4ee6 22}
23
24struct partition partitions[] = {
7fe9b0b7 25 {0x100000, 0x102000, 1, "bootrom"},
26 {0x102000, 0x110000, 0, "fpga"},
27 {0x110000, 0x140000, 0, "os"},
28 {0, 0, 0, NULL},
6e4d4ee6 29};
30
2cab856f 31void WriteBlock(unsigned int block_start, unsigned int len, unsigned char *buf)
6e4d4ee6 32{
7fe9b0b7 33 unsigned char temp_buf[256];
34 if (block_start & 0xFF) {
35 printf("moving stuff forward by %d bytes\n", block_start & 0xFF);
36 memset(temp_buf, 0xFF, block_start & 0xFF);
37 memcpy(temp_buf + (block_start & 0xFF), buf, len - (block_start & 0xFF));
38 block_start &= ~0xFF;
39 } else {
40 memcpy(temp_buf, buf, len);
41 }
42
43 UsbCommand c = {CMD_SETUP_WRITE};
44
45 for (int i = 0; i < 240; i += 48) {
46 memcpy(c.d.asBytes, temp_buf+i, 48);
47 c.arg[0] = (i/4);
48 SendCommand(&c);
49 WaitForAck();
50 }
51
52 c.cmd = CMD_FINISH_WRITE;
53 c.arg[0] = block_start;
54
55// printf("writing block %08x\r", c.arg[0]);
56 memcpy(c.d.asBytes, temp_buf+240, 16);
57 SendCommand(&c);
58 WaitForAck();
6e4d4ee6 59}
60
2cab856f 61void LoadFlashFromFile(const char *file, int start_addr, int end_addr)
6e4d4ee6 62{
7fe9b0b7 63 FILE *f = fopen(file, "rb");
64 if (!f) {
65 printf("couldn't open file\n");
66 exit(-1);
67 }
68
69 char buf[4];
70 fread(buf, 1, 4, f);
71 if (memcmp(buf, "\x7F" "ELF", 4) == 0) {
72 fseek(f, 0, SEEK_SET);
73 Elf32_Ehdr header;
74 fread(&header, 1, sizeof(header), f);
75 int count = header.e_phnum;
76 printf("count=%d phoff=%x\n", count, header.e_phoff);
77 Elf32_Phdr phdr;
78
79 for (int i = 0; i < header.e_phnum; ++i) {
80 fseek(f, header.e_phoff + i * sizeof(Elf32_Phdr), SEEK_SET);
81 fread(&phdr, 1, sizeof(phdr), f);
82 printf("type=%d offset=%x paddr=%x vaddr=%x filesize=%x memsize=%x flags=%x align=%x\n",
83 phdr.p_type, phdr.p_offset, phdr.p_paddr, phdr.p_vaddr, phdr.p_filesz, phdr.p_memsz, phdr.p_flags, phdr.p_align);
84 if (phdr.p_type == PT_LOAD && phdr.p_filesz > 0 && phdr.p_paddr >= PHYSICAL_FLASH_START
85 && (phdr.p_paddr + phdr.p_filesz) < PHYSICAL_FLASH_END) {
86 printf("flashing offset=%x paddr=%x size=%x\n", phdr.p_offset, phdr.p_paddr, phdr.p_filesz);
87 if (phdr.p_offset == 0) {
88 printf("skipping forward 0x2000 because of strange linker thing\n");
89 phdr.p_offset += 0x2000;
90 phdr.p_paddr += 0x2000;
91 phdr.p_filesz -= 0x2000;
92 phdr.p_memsz -= 0x2000;
2cab856f 93 }
6e4d4ee6 94
7fe9b0b7 95 fseek(f, phdr.p_offset, SEEK_SET);
96 ExpectedAddr = phdr.p_paddr;
97 while (ExpectedAddr < (phdr.p_paddr + phdr.p_filesz)) {
98 unsigned int bytes_to_read = phdr.p_paddr + phdr.p_filesz - ExpectedAddr;
99 if (bytes_to_read > 256)
100 bytes_to_read=256;
101 else
102 memset(QueuedToSend, 0xFF, 256);
103 fread(QueuedToSend, 1, bytes_to_read, f);
104 printf("WriteBlock(%x, %d, %02x %02x %02x %02x %02x %02x %02x %02x ... %02x %02x %02x %02x %02x %02x %02x %02x)\n", ExpectedAddr, bytes_to_read,
105 QueuedToSend[0], QueuedToSend[1], QueuedToSend[2], QueuedToSend[3],
106 QueuedToSend[4], QueuedToSend[5], QueuedToSend[6], QueuedToSend[7],
107 QueuedToSend[248], QueuedToSend[249], QueuedToSend[250], QueuedToSend[251],
108 QueuedToSend[252], QueuedToSend[253], QueuedToSend[254], QueuedToSend[255]);
109 WriteBlock(ExpectedAddr, 256, QueuedToSend);
110 ExpectedAddr += bytes_to_read;
111 }
112 }
113 }
114
115 fclose(f);
116 printf("\ndone.\n");
117 return;
118 } else printf("Bad file format\n");
6e4d4ee6 119}
120
121int PrepareFlash(struct partition *p, const char *filename, unsigned int state)
122{
7fe9b0b7 123 if (state & DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH) {
124 UsbCommand c = {CMD_START_FLASH, {p->start, p->end, 0}};
125
126 /* Only send magic when flashing bootrom */
127 if (p->precious)
128 c.arg[2] = START_FLASH_MAGIC;
129 else
130 c.arg[2] = 0;
131
132 SendCommand(&c);
133 WaitForAck();
134 } else {
135 fprintf(stderr, "Warning: Your bootloader does not understand the new START_FLASH command\n");
136 fprintf(stderr, " It is recommended that you update your bootloader\n\n");
137 exit(0);
138 }
139
140 LoadFlashFromFile(filename, p->start, p->end);
141 return 1;
6e4d4ee6 142}
143
144unsigned int GetProxmarkState(void)
145{
7fe9b0b7 146 unsigned int state = 0;
147
148 UsbCommand c;
149 c.cmd = CMD_DEVICE_INFO;
150 SendCommand(&c);
151
152 UsbCommand resp;
153 ReceiveCommand(&resp);
154 /* Three cases:
155 * 1. The old bootrom code will ignore CMD_DEVICE_INFO, but respond with an ACK
156 * 2. The old os code will respond with CMD_DEBUG_PRINT_STRING and "unknown command"
157 * 3. The new bootrom and os codes will respond with CMD_DEVICE_INFO and flags
158 */
159
160 switch (resp.cmd) {
161 case CMD_ACK:
162 state = DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM;
163 break;
164 case CMD_DEBUG_PRINT_STRING:
165 state = DEVICE_INFO_FLAG_CURRENT_MODE_OS;
166 break;
167 case CMD_DEVICE_INFO:
168 state = resp.arg[0];
169 break;
170 default:
171 fprintf(stderr, "Couldn't get proxmark state, bad response type: 0x%04X\n", resp.cmd);
172 exit(-1);
173 break;
174 }
175
176 return state;
6e4d4ee6 177}
178
179unsigned int EnterFlashState(void)
180{
7fe9b0b7 181 unsigned int state = GetProxmarkState();
182
183 if (state & DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM) {
184 /* Already in flash state, we're done. */
185 return state;
186 }
187
188 if (state & DEVICE_INFO_FLAG_CURRENT_MODE_OS) {
189 fprintf(stderr,"Entering flash-mode...\n");
190 UsbCommand c;
4cd41f34 191 memset(&c, 0, sizeof (c));
7fe9b0b7 192
193 if ((state & DEVICE_INFO_FLAG_BOOTROM_PRESENT) && (state & DEVICE_INFO_FLAG_OSIMAGE_PRESENT)) {
194 /* New style handover: Send CMD_START_FLASH, which will reset the board and
195 * enter the bootrom on the next boot.
196 */
197 c.cmd = CMD_START_FLASH;
198 SendCommand(&c);
199 fprintf(stderr,"(You don't have to do anything. Press and release the button only if you want to abort)\n");
200 fprintf(stderr,"Waiting for Proxmark to reappear on USB... ");
201 } else {
202 /* Old style handover: Ask the user to press the button, then reset the board */
203 c.cmd = CMD_HARDWARE_RESET;
204 SendCommand(&c);
205 fprintf(stderr,"(Press and hold down button NOW if your bootloader requires it)\n");
206 fprintf(stderr,"Waiting for Proxmark to reappear on USB... ");
207 }
6e4d4ee6 208
7fe9b0b7 209 CloseProxmark();
210 sleep(1);
6e4d4ee6 211
7fe9b0b7 212 while (!OpenProxmark(0)) { sleep(1); }
7fe9b0b7 213 fprintf(stderr,"Found.\n");
214
215 return GetProxmarkState();
216 }
6e4d4ee6 217
7fe9b0b7 218 return 0;
6e4d4ee6 219}
220
221/* On first call, have *offset = -1, *length = 0; */
222int find_next_area(const char *str, int *offset, int *length)
223{
7fe9b0b7 224 if (*str == '\0') return 0;
225 if ((*offset >= 0) && str[*offset + *length] == '\0') return 0;
226 *offset += 1 + *length;
227
228 char *next_comma = strchr(str + *offset, ',');
229 if (next_comma == NULL) {
230 *length = strlen(str) - *offset;
231 } else {
232 *length = next_comma-(str+*offset);
233 }
234 return 1;
6e4d4ee6 235}
236
7fe9b0b7 237void do_flash(char **argv)
238{
239 unsigned int state = EnterFlashState();
240
241 if (!(state & DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM)) {
242 fprintf(stderr, "Proxmark would not enter flash state, abort\n");
243 exit(-1);
244 }
245
246 int offset=-1, length=0;
247 int current_area = 0;
248 while (find_next_area(argv[1], &offset, &length)) {
249 struct partition *p = NULL;
250 for (int i = 0; i<sizeof(partitions)/sizeof(partitions[0]); ++i) {
251 if (strncmp(partitions[i].name, argv[1] + offset, length) == 0) {
252 /* Check if the name matches the bootrom partition, and if so, require "bootrom" to
253 * be written in full. The other names may be abbreviated.
254 */
255 if(!partitions[i].precious || (strlen(partitions[i].name) == length))
256 p = &partitions[i];
257 break;
258 }
259 }
260
261 if (p == NULL) {
262 fprintf(stderr, "Warning: area name '");
263 fwrite(argv[1]+offset, length, 1, stderr);
264 fprintf(stderr, "' unknown, ignored\n");
265 } else {
266 fprintf(stderr, "Flashing %s from %s\n", p->name, argv[2+current_area]);
267 PrepareFlash(p, argv[2+current_area], state);
268 }
269 current_area++;
270 }
6e4d4ee6 271}
Impressum, Datenschutz