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