1 /* 2 * ifdtool - Manage Intel Firmware Descriptor information 3 * 4 * Copyright 2014 Google, Inc 5 * 6 * SPDX-License-Identifier: GPL-2.0 7 * 8 * From Coreboot project, but it got a serious code clean-up 9 * and a few new features 10 */ 11 12 #include <assert.h> 13 #include <fcntl.h> 14 #include <getopt.h> 15 #include <stdlib.h> 16 #include <stdio.h> 17 #include <string.h> 18 #include <unistd.h> 19 #include <sys/types.h> 20 #include <sys/stat.h> 21 #include "ifdtool.h" 22 23 #undef DEBUG 24 25 #ifdef DEBUG 26 #define debug(fmt, args...) printf(fmt, ##args) 27 #else 28 #define debug(fmt, args...) 29 #endif 30 31 #define FD_SIGNATURE 0x0FF0A55A 32 #define FLREG_BASE(reg) ((reg & 0x00000fff) << 12); 33 #define FLREG_LIMIT(reg) (((reg & 0x0fff0000) >> 4) | 0xfff); 34 35 /** 36 * find_fd() - Find the flash description in the ROM image 37 * 38 * @image: Pointer to image 39 * @size: Size of image in bytes 40 * @return pointer to structure, or NULL if not found 41 */ 42 static struct fdbar_t *find_fd(char *image, int size) 43 { 44 uint32_t *ptr, *end; 45 46 /* Scan for FD signature */ 47 for (ptr = (uint32_t *)image, end = ptr + size / 4; ptr < end; ptr++) { 48 if (*ptr == FD_SIGNATURE) 49 break; 50 } 51 52 if (ptr == end) { 53 printf("No Flash Descriptor found in this image\n"); 54 return NULL; 55 } 56 57 debug("Found Flash Descriptor signature at 0x%08lx\n", 58 (char *)ptr - image); 59 60 return (struct fdbar_t *)ptr; 61 } 62 63 /** 64 * get_region() - Get information about the selected region 65 * 66 * @frba: Flash region list 67 * @region_type: Type of region (0..MAX_REGIONS-1) 68 * @region: Region information is written here 69 * @return 0 if OK, else -ve 70 */ 71 static int get_region(struct frba_t *frba, int region_type, 72 struct region_t *region) 73 { 74 if (region_type >= MAX_REGIONS) { 75 fprintf(stderr, "Invalid region type.\n"); 76 return -1; 77 } 78 79 region->base = FLREG_BASE(frba->flreg[region_type]); 80 region->limit = FLREG_LIMIT(frba->flreg[region_type]); 81 region->size = region->limit - region->base + 1; 82 83 return 0; 84 } 85 86 static const char *region_name(int region_type) 87 { 88 static const char *const regions[] = { 89 "Flash Descriptor", 90 "BIOS", 91 "Intel ME", 92 "GbE", 93 "Platform Data" 94 }; 95 96 assert(region_type < MAX_REGIONS); 97 98 return regions[region_type]; 99 } 100 101 static const char *region_filename(int region_type) 102 { 103 static const char *const region_filenames[] = { 104 "flashregion_0_flashdescriptor.bin", 105 "flashregion_1_bios.bin", 106 "flashregion_2_intel_me.bin", 107 "flashregion_3_gbe.bin", 108 "flashregion_4_platform_data.bin" 109 }; 110 111 assert(region_type < MAX_REGIONS); 112 113 return region_filenames[region_type]; 114 } 115 116 static int dump_region(int num, struct frba_t *frba) 117 { 118 struct region_t region; 119 int ret; 120 121 ret = get_region(frba, num, ®ion); 122 if (ret) 123 return ret; 124 125 printf(" Flash Region %d (%s): %08x - %08x %s\n", 126 num, region_name(num), region.base, region.limit, 127 region.size < 1 ? "(unused)" : ""); 128 129 return ret; 130 } 131 132 static void dump_frba(struct frba_t *frba) 133 { 134 int i; 135 136 printf("Found Region Section\n"); 137 for (i = 0; i < MAX_REGIONS; i++) { 138 printf("FLREG%d: 0x%08x\n", i, frba->flreg[i]); 139 dump_region(i, frba); 140 } 141 } 142 143 static void decode_spi_frequency(unsigned int freq) 144 { 145 switch (freq) { 146 case SPI_FREQUENCY_20MHZ: 147 printf("20MHz"); 148 break; 149 case SPI_FREQUENCY_33MHZ: 150 printf("33MHz"); 151 break; 152 case SPI_FREQUENCY_50MHZ: 153 printf("50MHz"); 154 break; 155 default: 156 printf("unknown<%x>MHz", freq); 157 } 158 } 159 160 static void decode_component_density(unsigned int density) 161 { 162 switch (density) { 163 case COMPONENT_DENSITY_512KB: 164 printf("512KiB"); 165 break; 166 case COMPONENT_DENSITY_1MB: 167 printf("1MiB"); 168 break; 169 case COMPONENT_DENSITY_2MB: 170 printf("2MiB"); 171 break; 172 case COMPONENT_DENSITY_4MB: 173 printf("4MiB"); 174 break; 175 case COMPONENT_DENSITY_8MB: 176 printf("8MiB"); 177 break; 178 case COMPONENT_DENSITY_16MB: 179 printf("16MiB"); 180 break; 181 default: 182 printf("unknown<%x>MiB", density); 183 } 184 } 185 186 static void dump_fcba(struct fcba_t *fcba) 187 { 188 printf("\nFound Component Section\n"); 189 printf("FLCOMP 0x%08x\n", fcba->flcomp); 190 printf(" Dual Output Fast Read Support: %ssupported\n", 191 (fcba->flcomp & (1 << 30)) ? "" : "not "); 192 printf(" Read ID/Read Status Clock Frequency: "); 193 decode_spi_frequency((fcba->flcomp >> 27) & 7); 194 printf("\n Write/Erase Clock Frequency: "); 195 decode_spi_frequency((fcba->flcomp >> 24) & 7); 196 printf("\n Fast Read Clock Frequency: "); 197 decode_spi_frequency((fcba->flcomp >> 21) & 7); 198 printf("\n Fast Read Support: %ssupported", 199 (fcba->flcomp & (1 << 20)) ? "" : "not "); 200 printf("\n Read Clock Frequency: "); 201 decode_spi_frequency((fcba->flcomp >> 17) & 7); 202 printf("\n Component 2 Density: "); 203 decode_component_density((fcba->flcomp >> 3) & 7); 204 printf("\n Component 1 Density: "); 205 decode_component_density(fcba->flcomp & 7); 206 printf("\n"); 207 printf("FLILL 0x%08x\n", fcba->flill); 208 printf(" Invalid Instruction 3: 0x%02x\n", 209 (fcba->flill >> 24) & 0xff); 210 printf(" Invalid Instruction 2: 0x%02x\n", 211 (fcba->flill >> 16) & 0xff); 212 printf(" Invalid Instruction 1: 0x%02x\n", 213 (fcba->flill >> 8) & 0xff); 214 printf(" Invalid Instruction 0: 0x%02x\n", 215 fcba->flill & 0xff); 216 printf("FLPB 0x%08x\n", fcba->flpb); 217 printf(" Flash Partition Boundary Address: 0x%06x\n\n", 218 (fcba->flpb & 0xfff) << 12); 219 } 220 221 static void dump_fpsba(struct fpsba_t *fpsba) 222 { 223 int i; 224 225 printf("Found PCH Strap Section\n"); 226 for (i = 0; i < MAX_STRAPS; i++) 227 printf("PCHSTRP%-2d: 0x%08x\n", i, fpsba->pchstrp[i]); 228 } 229 230 static const char *get_enabled(int flag) 231 { 232 return flag ? "enabled" : "disabled"; 233 } 234 235 static void decode_flmstr(uint32_t flmstr) 236 { 237 printf(" Platform Data Region Write Access: %s\n", 238 get_enabled(flmstr & (1 << 28))); 239 printf(" GbE Region Write Access: %s\n", 240 get_enabled(flmstr & (1 << 27))); 241 printf(" Intel ME Region Write Access: %s\n", 242 get_enabled(flmstr & (1 << 26))); 243 printf(" Host CPU/BIOS Region Write Access: %s\n", 244 get_enabled(flmstr & (1 << 25))); 245 printf(" Flash Descriptor Write Access: %s\n", 246 get_enabled(flmstr & (1 << 24))); 247 248 printf(" Platform Data Region Read Access: %s\n", 249 get_enabled(flmstr & (1 << 20))); 250 printf(" GbE Region Read Access: %s\n", 251 get_enabled(flmstr & (1 << 19))); 252 printf(" Intel ME Region Read Access: %s\n", 253 get_enabled(flmstr & (1 << 18))); 254 printf(" Host CPU/BIOS Region Read Access: %s\n", 255 get_enabled(flmstr & (1 << 17))); 256 printf(" Flash Descriptor Read Access: %s\n", 257 get_enabled(flmstr & (1 << 16))); 258 259 printf(" Requester ID: 0x%04x\n\n", 260 flmstr & 0xffff); 261 } 262 263 static void dump_fmba(struct fmba_t *fmba) 264 { 265 printf("Found Master Section\n"); 266 printf("FLMSTR1: 0x%08x (Host CPU/BIOS)\n", fmba->flmstr1); 267 decode_flmstr(fmba->flmstr1); 268 printf("FLMSTR2: 0x%08x (Intel ME)\n", fmba->flmstr2); 269 decode_flmstr(fmba->flmstr2); 270 printf("FLMSTR3: 0x%08x (GbE)\n", fmba->flmstr3); 271 decode_flmstr(fmba->flmstr3); 272 } 273 274 static void dump_fmsba(struct fmsba_t *fmsba) 275 { 276 int i; 277 278 printf("Found Processor Strap Section\n"); 279 for (i = 0; i < 4; i++) 280 printf("????: 0x%08x\n", fmsba->data[0]); 281 } 282 283 static void dump_jid(uint32_t jid) 284 { 285 printf(" SPI Component Device ID 1: 0x%02x\n", 286 (jid >> 16) & 0xff); 287 printf(" SPI Component Device ID 0: 0x%02x\n", 288 (jid >> 8) & 0xff); 289 printf(" SPI Component Vendor ID: 0x%02x\n", 290 jid & 0xff); 291 } 292 293 static void dump_vscc(uint32_t vscc) 294 { 295 printf(" Lower Erase Opcode: 0x%02x\n", 296 vscc >> 24); 297 printf(" Lower Write Enable on Write Status: 0x%02x\n", 298 vscc & (1 << 20) ? 0x06 : 0x50); 299 printf(" Lower Write Status Required: %s\n", 300 vscc & (1 << 19) ? "Yes" : "No"); 301 printf(" Lower Write Granularity: %d bytes\n", 302 vscc & (1 << 18) ? 64 : 1); 303 printf(" Lower Block / Sector Erase Size: "); 304 switch ((vscc >> 16) & 0x3) { 305 case 0: 306 printf("256 Byte\n"); 307 break; 308 case 1: 309 printf("4KB\n"); 310 break; 311 case 2: 312 printf("8KB\n"); 313 break; 314 case 3: 315 printf("64KB\n"); 316 break; 317 } 318 319 printf(" Upper Erase Opcode: 0x%02x\n", 320 (vscc >> 8) & 0xff); 321 printf(" Upper Write Enable on Write Status: 0x%02x\n", 322 vscc & (1 << 4) ? 0x06 : 0x50); 323 printf(" Upper Write Status Required: %s\n", 324 vscc & (1 << 3) ? "Yes" : "No"); 325 printf(" Upper Write Granularity: %d bytes\n", 326 vscc & (1 << 2) ? 64 : 1); 327 printf(" Upper Block / Sector Erase Size: "); 328 switch (vscc & 0x3) { 329 case 0: 330 printf("256 Byte\n"); 331 break; 332 case 1: 333 printf("4KB\n"); 334 break; 335 case 2: 336 printf("8KB\n"); 337 break; 338 case 3: 339 printf("64KB\n"); 340 break; 341 } 342 } 343 344 static void dump_vtba(struct vtba_t *vtba, int vtl) 345 { 346 int i; 347 int num = (vtl >> 1) < 8 ? (vtl >> 1) : 8; 348 349 printf("ME VSCC table:\n"); 350 for (i = 0; i < num; i++) { 351 printf(" JID%d: 0x%08x\n", i, vtba->entry[i].jid); 352 dump_jid(vtba->entry[i].jid); 353 printf(" VSCC%d: 0x%08x\n", i, vtba->entry[i].vscc); 354 dump_vscc(vtba->entry[i].vscc); 355 } 356 printf("\n"); 357 } 358 359 static void dump_oem(uint8_t *oem) 360 { 361 int i, j; 362 printf("OEM Section:\n"); 363 for (i = 0; i < 4; i++) { 364 printf("%02x:", i << 4); 365 for (j = 0; j < 16; j++) 366 printf(" %02x", oem[(i<<4)+j]); 367 printf("\n"); 368 } 369 printf("\n"); 370 } 371 372 /** 373 * dump_fd() - Display a dump of the full flash description 374 * 375 * @image: Pointer to image 376 * @size: Size of image in bytes 377 * @return 0 if OK, -1 on error 378 */ 379 static int dump_fd(char *image, int size) 380 { 381 struct fdbar_t *fdb = find_fd(image, size); 382 383 if (!fdb) 384 return -1; 385 386 printf("FLMAP0: 0x%08x\n", fdb->flmap0); 387 printf(" NR: %d\n", (fdb->flmap0 >> 24) & 7); 388 printf(" FRBA: 0x%x\n", ((fdb->flmap0 >> 16) & 0xff) << 4); 389 printf(" NC: %d\n", ((fdb->flmap0 >> 8) & 3) + 1); 390 printf(" FCBA: 0x%x\n", ((fdb->flmap0) & 0xff) << 4); 391 392 printf("FLMAP1: 0x%08x\n", fdb->flmap1); 393 printf(" ISL: 0x%02x\n", (fdb->flmap1 >> 24) & 0xff); 394 printf(" FPSBA: 0x%x\n", ((fdb->flmap1 >> 16) & 0xff) << 4); 395 printf(" NM: %d\n", (fdb->flmap1 >> 8) & 3); 396 printf(" FMBA: 0x%x\n", ((fdb->flmap1) & 0xff) << 4); 397 398 printf("FLMAP2: 0x%08x\n", fdb->flmap2); 399 printf(" PSL: 0x%04x\n", (fdb->flmap2 >> 8) & 0xffff); 400 printf(" FMSBA: 0x%x\n", ((fdb->flmap2) & 0xff) << 4); 401 402 printf("FLUMAP1: 0x%08x\n", fdb->flumap1); 403 printf(" Intel ME VSCC Table Length (VTL): %d\n", 404 (fdb->flumap1 >> 8) & 0xff); 405 printf(" Intel ME VSCC Table Base Address (VTBA): 0x%06x\n\n", 406 (fdb->flumap1 & 0xff) << 4); 407 dump_vtba((struct vtba_t *) 408 (image + ((fdb->flumap1 & 0xff) << 4)), 409 (fdb->flumap1 >> 8) & 0xff); 410 dump_oem((uint8_t *)image + 0xf00); 411 dump_frba((struct frba_t *)(image + (((fdb->flmap0 >> 16) & 0xff) 412 << 4))); 413 dump_fcba((struct fcba_t *)(image + (((fdb->flmap0) & 0xff) << 4))); 414 dump_fpsba((struct fpsba_t *) 415 (image + (((fdb->flmap1 >> 16) & 0xff) << 4))); 416 dump_fmba((struct fmba_t *)(image + (((fdb->flmap1) & 0xff) << 4))); 417 dump_fmsba((struct fmsba_t *)(image + (((fdb->flmap2) & 0xff) << 4))); 418 419 return 0; 420 } 421 422 /** 423 * write_regions() - Write each region from an image to its own file 424 * 425 * The filename to use in each case is fixed - see region_filename() 426 * 427 * @image: Pointer to image 428 * @size: Size of image in bytes 429 * @return 0 if OK, -ve on error 430 */ 431 static int write_regions(char *image, int size) 432 { 433 struct fdbar_t *fdb; 434 struct frba_t *frba; 435 int ret = 0; 436 int i; 437 438 fdb = find_fd(image, size); 439 if (!fdb) 440 return -1; 441 442 frba = (struct frba_t *)(image + (((fdb->flmap0 >> 16) & 0xff) << 4)); 443 444 for (i = 0; i < MAX_REGIONS; i++) { 445 struct region_t region; 446 int region_fd; 447 448 ret = get_region(frba, i, ®ion); 449 if (ret) 450 return ret; 451 dump_region(i, frba); 452 if (region.size == 0) 453 continue; 454 region_fd = open(region_filename(i), 455 O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | 456 S_IWUSR | S_IRGRP | S_IROTH); 457 if (write(region_fd, image + region.base, region.size) != 458 region.size) { 459 perror("Error while writing"); 460 ret = -1; 461 } 462 close(region_fd); 463 } 464 465 return ret; 466 } 467 468 static int perror_fname(const char *fmt, const char *fname) 469 { 470 char msg[strlen(fmt) + strlen(fname) + 1]; 471 472 sprintf(msg, fmt, fname); 473 perror(msg); 474 475 return -1; 476 } 477 478 /** 479 * write_image() - Write the image to a file 480 * 481 * @filename: Filename to use for the image 482 * @image: Pointer to image 483 * @size: Size of image in bytes 484 * @return 0 if OK, -ve on error 485 */ 486 static int write_image(char *filename, char *image, int size) 487 { 488 int new_fd; 489 490 debug("Writing new image to %s\n", filename); 491 492 new_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | 493 S_IWUSR | S_IRGRP | S_IROTH); 494 if (new_fd < 0) 495 return perror_fname("Could not open file '%s'", filename); 496 if (write(new_fd, image, size) != size) 497 return perror_fname("Could not write file '%s'", filename); 498 close(new_fd); 499 500 return 0; 501 } 502 503 /** 504 * set_spi_frequency() - Set the SPI frequency to use when booting 505 * 506 * Several frequencies are supported, some of which work with fast devices. 507 * For SPI emulators, the slowest (SPI_FREQUENCY_20MHZ) is often used. The 508 * Intel boot system uses this information somehow on boot. 509 * 510 * The image is updated with the supplied value 511 * 512 * @image: Pointer to image 513 * @size: Size of image in bytes 514 * @freq: SPI frequency to use 515 */ 516 static void set_spi_frequency(char *image, int size, enum spi_frequency freq) 517 { 518 struct fdbar_t *fdb = find_fd(image, size); 519 struct fcba_t *fcba; 520 521 fcba = (struct fcba_t *)(image + (((fdb->flmap0) & 0xff) << 4)); 522 523 /* clear bits 21-29 */ 524 fcba->flcomp &= ~0x3fe00000; 525 /* Read ID and Read Status Clock Frequency */ 526 fcba->flcomp |= freq << 27; 527 /* Write and Erase Clock Frequency */ 528 fcba->flcomp |= freq << 24; 529 /* Fast Read Clock Frequency */ 530 fcba->flcomp |= freq << 21; 531 } 532 533 /** 534 * set_em100_mode() - Set a SPI frequency that will work with Dediprog EM100 535 * 536 * @image: Pointer to image 537 * @size: Size of image in bytes 538 */ 539 static void set_em100_mode(char *image, int size) 540 { 541 struct fdbar_t *fdb = find_fd(image, size); 542 struct fcba_t *fcba; 543 544 fcba = (struct fcba_t *)(image + (((fdb->flmap0) & 0xff) << 4)); 545 fcba->flcomp &= ~(1 << 30); 546 set_spi_frequency(image, size, SPI_FREQUENCY_20MHZ); 547 } 548 549 /** 550 * lock_descriptor() - Lock the NE descriptor so it cannot be updated 551 * 552 * @image: Pointer to image 553 * @size: Size of image in bytes 554 */ 555 static void lock_descriptor(char *image, int size) 556 { 557 struct fdbar_t *fdb = find_fd(image, size); 558 struct fmba_t *fmba; 559 560 /* 561 * TODO: Dynamically take Platform Data Region and GbE Region into 562 * account. 563 */ 564 fmba = (struct fmba_t *)(image + (((fdb->flmap1) & 0xff) << 4)); 565 fmba->flmstr1 = 0x0a0b0000; 566 fmba->flmstr2 = 0x0c0d0000; 567 fmba->flmstr3 = 0x08080118; 568 } 569 570 /** 571 * unlock_descriptor() - Lock the NE descriptor so it can be updated 572 * 573 * @image: Pointer to image 574 * @size: Size of image in bytes 575 */ 576 static void unlock_descriptor(char *image, int size) 577 { 578 struct fdbar_t *fdb = find_fd(image, size); 579 struct fmba_t *fmba; 580 581 fmba = (struct fmba_t *)(image + (((fdb->flmap1) & 0xff) << 4)); 582 fmba->flmstr1 = 0xffff0000; 583 fmba->flmstr2 = 0xffff0000; 584 fmba->flmstr3 = 0x08080118; 585 } 586 587 /** 588 * open_for_read() - Open a file for reading 589 * 590 * @fname: Filename to open 591 * @sizep: Returns file size in bytes 592 * @return 0 if OK, -1 on error 593 */ 594 int open_for_read(const char *fname, int *sizep) 595 { 596 int fd = open(fname, O_RDONLY); 597 struct stat buf; 598 599 if (fd == -1) 600 return perror_fname("Could not open file '%s'", fname); 601 if (fstat(fd, &buf) == -1) 602 return perror_fname("Could not stat file '%s'", fname); 603 *sizep = buf.st_size; 604 debug("File %s is %d bytes\n", fname, *sizep); 605 606 return fd; 607 } 608 609 /** 610 * inject_region() - Add a file to an image region 611 * 612 * This puts a file into a particular region of the flash. Several pre-defined 613 * regions are used. 614 * 615 * @image: Pointer to image 616 * @size: Size of image in bytes 617 * @region_type: Region where the file should be added 618 * @region_fname: Filename to add to the image 619 * @return 0 if OK, -ve on error 620 */ 621 int inject_region(char *image, int size, int region_type, char *region_fname) 622 { 623 struct fdbar_t *fdb = find_fd(image, size); 624 struct region_t region; 625 struct frba_t *frba; 626 int region_size; 627 int offset = 0; 628 int region_fd; 629 int ret; 630 631 if (!fdb) 632 exit(EXIT_FAILURE); 633 frba = (struct frba_t *)(image + (((fdb->flmap0 >> 16) & 0xff) << 4)); 634 635 ret = get_region(frba, region_type, ®ion); 636 if (ret) 637 return -1; 638 if (region.size <= 0xfff) { 639 fprintf(stderr, "Region %s is disabled in target. Not injecting.\n", 640 region_name(region_type)); 641 return -1; 642 } 643 644 region_fd = open_for_read(region_fname, ®ion_size); 645 if (region_fd < 0) 646 return region_fd; 647 648 if ((region_size > region.size) || 649 ((region_type != 1) && (region_size > region.size))) { 650 fprintf(stderr, "Region %s is %d(0x%x) bytes. File is %d(0x%x) bytes. Not injecting.\n", 651 region_name(region_type), region.size, 652 region.size, region_size, region_size); 653 return -1; 654 } 655 656 if ((region_type == 1) && (region_size < region.size)) { 657 fprintf(stderr, "Region %s is %d(0x%x) bytes. File is %d(0x%x) bytes. Padding before injecting.\n", 658 region_name(region_type), region.size, 659 region.size, region_size, region_size); 660 offset = region.size - region_size; 661 memset(image + region.base, 0xff, offset); 662 } 663 664 if (size < region.base + offset + region_size) { 665 fprintf(stderr, "Output file is too small. (%d < %d)\n", 666 size, region.base + offset + region_size); 667 return -1; 668 } 669 670 if (read(region_fd, image + region.base + offset, region_size) 671 != region_size) { 672 perror("Could not read file"); 673 return -1; 674 } 675 676 close(region_fd); 677 678 debug("Adding %s as the %s section\n", region_fname, 679 region_name(region_type)); 680 681 return 0; 682 } 683 684 /** 685 * write_data() - Write some raw data into a region 686 * 687 * This puts a file into a particular place in the flash, ignoring the 688 * regions. Be careful not to overwrite something important. 689 * 690 * @image: Pointer to image 691 * @size: Size of image in bytes 692 * @addr: x86 ROM address to put file. The ROM ends at 693 * 0xffffffff so use an address relative to that. For an 694 * 8MB ROM the start address is 0xfff80000. 695 * @write_fname: Filename to add to the image 696 * @return 0 if OK, -ve on error 697 */ 698 static int write_data(char *image, int size, unsigned int addr, 699 const char *write_fname) 700 { 701 int write_fd, write_size; 702 int offset; 703 704 write_fd = open_for_read(write_fname, &write_size); 705 if (write_fd < 0) 706 return write_fd; 707 708 offset = addr + size; 709 debug("Writing %s to offset %#x\n", write_fname, offset); 710 711 if (offset < 0 || offset + write_size > size) { 712 fprintf(stderr, "Output file is too small. (%d < %d)\n", 713 size, offset + write_size); 714 return -1; 715 } 716 717 if (read(write_fd, image + offset, write_size) != write_size) { 718 perror("Could not read file"); 719 return -1; 720 } 721 722 close(write_fd); 723 724 return 0; 725 } 726 727 static void print_version(void) 728 { 729 printf("ifdtool v%s -- ", IFDTOOL_VERSION); 730 printf("Copyright (C) 2014 Google Inc.\n\n"); 731 printf("SPDX-License-Identifier: GPL-2.0+\n"); 732 } 733 734 static void print_usage(const char *name) 735 { 736 printf("usage: %s [-vhdix?] <filename> [<outfile>]\n", name); 737 printf("\n" 738 " -d | --dump: dump intel firmware descriptor\n" 739 " -x | --extract: extract intel fd modules\n" 740 " -i | --inject <region>:<module> inject file <module> into region <region>\n" 741 " -w | --write <addr>:<file> write file to appear at memory address <addr>\n" 742 " multiple files can be written simultaneously\n" 743 " -s | --spifreq <20|33|50> set the SPI frequency\n" 744 " -e | --em100 set SPI frequency to 20MHz and disable\n" 745 " Dual Output Fast Read Support\n" 746 " -l | --lock Lock firmware descriptor and ME region\n" 747 " -u | --unlock Unlock firmware descriptor and ME region\n" 748 " -r | --romsize Specify ROM size\n" 749 " -D | --write-descriptor <file> Write descriptor at base\n" 750 " -c | --create Create a new empty image\n" 751 " -v | --version: print the version\n" 752 " -h | --help: print this help\n\n" 753 "<region> is one of Descriptor, BIOS, ME, GbE, Platform\n" 754 "\n"); 755 } 756 757 /** 758 * get_two_words() - Convert a string into two words separated by : 759 * 760 * The supplied string is split at ':', two substrings are allocated and 761 * returned. 762 * 763 * @str: String to split 764 * @firstp: Returns first string 765 * @secondp: Returns second string 766 * @return 0 if OK, -ve if @str does not have a : 767 */ 768 static int get_two_words(const char *str, char **firstp, char **secondp) 769 { 770 const char *p; 771 772 p = strchr(str, ':'); 773 if (!p) 774 return -1; 775 *firstp = strdup(str); 776 (*firstp)[p - str] = '\0'; 777 *secondp = strdup(p + 1); 778 779 return 0; 780 } 781 782 int main(int argc, char *argv[]) 783 { 784 int opt, option_index = 0; 785 int mode_dump = 0, mode_extract = 0, mode_inject = 0; 786 int mode_spifreq = 0, mode_em100 = 0, mode_locked = 0; 787 int mode_unlocked = 0, mode_write = 0, mode_write_descriptor = 0; 788 int create = 0; 789 char *region_type_string = NULL, *inject_fname = NULL; 790 char *desc_fname = NULL, *addr_str = NULL; 791 int region_type = -1, inputfreq = 0; 792 enum spi_frequency spifreq = SPI_FREQUENCY_20MHZ; 793 unsigned int addr[WRITE_MAX]; 794 char *wr_fname[WRITE_MAX]; 795 unsigned char wr_idx, wr_num = 0; 796 int rom_size = -1; 797 bool write_it; 798 char *filename; 799 char *outfile = NULL; 800 struct stat buf; 801 int size = 0; 802 int bios_fd; 803 char *image; 804 int ret; 805 static struct option long_options[] = { 806 {"create", 0, NULL, 'c'}, 807 {"dump", 0, NULL, 'd'}, 808 {"descriptor", 1, NULL, 'D'}, 809 {"em100", 0, NULL, 'e'}, 810 {"extract", 0, NULL, 'x'}, 811 {"inject", 1, NULL, 'i'}, 812 {"lock", 0, NULL, 'l'}, 813 {"romsize", 1, NULL, 'r'}, 814 {"spifreq", 1, NULL, 's'}, 815 {"unlock", 0, NULL, 'u'}, 816 {"write", 1, NULL, 'w'}, 817 {"version", 0, NULL, 'v'}, 818 {"help", 0, NULL, 'h'}, 819 {0, 0, 0, 0} 820 }; 821 822 while ((opt = getopt_long(argc, argv, "cdD:ehi:lr:s:uvw:x?", 823 long_options, &option_index)) != EOF) { 824 switch (opt) { 825 case 'c': 826 create = 1; 827 break; 828 case 'd': 829 mode_dump = 1; 830 break; 831 case 'D': 832 mode_write_descriptor = 1; 833 desc_fname = optarg; 834 break; 835 case 'e': 836 mode_em100 = 1; 837 break; 838 case 'i': 839 if (get_two_words(optarg, ®ion_type_string, 840 &inject_fname)) { 841 print_usage(argv[0]); 842 exit(EXIT_FAILURE); 843 } 844 if (!strcasecmp("Descriptor", region_type_string)) 845 region_type = 0; 846 else if (!strcasecmp("BIOS", region_type_string)) 847 region_type = 1; 848 else if (!strcasecmp("ME", region_type_string)) 849 region_type = 2; 850 else if (!strcasecmp("GbE", region_type_string)) 851 region_type = 3; 852 else if (!strcasecmp("Platform", region_type_string)) 853 region_type = 4; 854 if (region_type == -1) { 855 fprintf(stderr, "No such region type: '%s'\n\n", 856 region_type_string); 857 print_usage(argv[0]); 858 exit(EXIT_FAILURE); 859 } 860 mode_inject = 1; 861 break; 862 case 'l': 863 mode_locked = 1; 864 break; 865 case 'r': 866 rom_size = strtol(optarg, NULL, 0); 867 debug("ROM size %d\n", rom_size); 868 break; 869 case 's': 870 /* Parse the requested SPI frequency */ 871 inputfreq = strtol(optarg, NULL, 0); 872 switch (inputfreq) { 873 case 20: 874 spifreq = SPI_FREQUENCY_20MHZ; 875 break; 876 case 33: 877 spifreq = SPI_FREQUENCY_33MHZ; 878 break; 879 case 50: 880 spifreq = SPI_FREQUENCY_50MHZ; 881 break; 882 default: 883 fprintf(stderr, "Invalid SPI Frequency: %d\n", 884 inputfreq); 885 print_usage(argv[0]); 886 exit(EXIT_FAILURE); 887 } 888 mode_spifreq = 1; 889 break; 890 case 'u': 891 mode_unlocked = 1; 892 break; 893 case 'v': 894 print_version(); 895 exit(EXIT_SUCCESS); 896 break; 897 case 'w': 898 mode_write = 1; 899 if (wr_num < WRITE_MAX) { 900 if (get_two_words(optarg, &addr_str, 901 &wr_fname[wr_num])) { 902 print_usage(argv[0]); 903 exit(EXIT_FAILURE); 904 } 905 addr[wr_num] = strtol(optarg, NULL, 0); 906 wr_num++; 907 } else { 908 fprintf(stderr, 909 "The number of files to write simultaneously exceeds the limitation (%d)\n", 910 WRITE_MAX); 911 } 912 break; 913 case 'x': 914 mode_extract = 1; 915 break; 916 case 'h': 917 case '?': 918 default: 919 print_usage(argv[0]); 920 exit(EXIT_SUCCESS); 921 break; 922 } 923 } 924 925 if (mode_locked == 1 && mode_unlocked == 1) { 926 fprintf(stderr, "Locking/Unlocking FD and ME are mutually exclusive\n"); 927 exit(EXIT_FAILURE); 928 } 929 930 if (mode_inject == 1 && mode_write == 1) { 931 fprintf(stderr, "Inject/Write are mutually exclusive\n"); 932 exit(EXIT_FAILURE); 933 } 934 935 if ((mode_dump + mode_extract + mode_inject + 936 (mode_spifreq | mode_em100 | mode_unlocked | 937 mode_locked)) > 1) { 938 fprintf(stderr, "You may not specify more than one mode.\n\n"); 939 print_usage(argv[0]); 940 exit(EXIT_FAILURE); 941 } 942 943 if ((mode_dump + mode_extract + mode_inject + mode_spifreq + 944 mode_em100 + mode_locked + mode_unlocked + mode_write + 945 mode_write_descriptor) == 0 && !create) { 946 fprintf(stderr, "You need to specify a mode.\n\n"); 947 print_usage(argv[0]); 948 exit(EXIT_FAILURE); 949 } 950 951 if (create && rom_size == -1) { 952 fprintf(stderr, "You need to specify a rom size when creating.\n\n"); 953 exit(EXIT_FAILURE); 954 } 955 956 if (optind + 1 != argc) { 957 fprintf(stderr, "You need to specify a file.\n\n"); 958 print_usage(argv[0]); 959 exit(EXIT_FAILURE); 960 } 961 962 filename = argv[optind]; 963 if (optind + 2 != argc) 964 outfile = argv[optind + 1]; 965 966 if (create) 967 bios_fd = open(filename, O_WRONLY | O_CREAT, 0666); 968 else 969 bios_fd = open(filename, outfile ? O_RDONLY : O_RDWR); 970 971 if (bios_fd == -1) { 972 perror("Could not open file"); 973 exit(EXIT_FAILURE); 974 } 975 976 if (!create) { 977 if (fstat(bios_fd, &buf) == -1) { 978 perror("Could not stat file"); 979 exit(EXIT_FAILURE); 980 } 981 size = buf.st_size; 982 } 983 984 debug("File %s is %d bytes\n", filename, size); 985 986 if (rom_size == -1) 987 rom_size = size; 988 989 image = malloc(rom_size); 990 if (!image) { 991 printf("Out of memory.\n"); 992 exit(EXIT_FAILURE); 993 } 994 995 memset(image, '\xff', rom_size); 996 if (!create && read(bios_fd, image, size) != size) { 997 perror("Could not read file"); 998 exit(EXIT_FAILURE); 999 } 1000 if (size != rom_size) { 1001 debug("ROM size changed to %d bytes\n", rom_size); 1002 size = rom_size; 1003 } 1004 1005 write_it = true; 1006 ret = 0; 1007 if (mode_dump) { 1008 ret = dump_fd(image, size); 1009 write_it = false; 1010 } 1011 1012 if (mode_extract) { 1013 ret = write_regions(image, size); 1014 write_it = false; 1015 } 1016 1017 if (mode_write_descriptor) 1018 ret = write_data(image, size, -size, desc_fname); 1019 1020 if (mode_inject) 1021 ret = inject_region(image, size, region_type, inject_fname); 1022 1023 if (mode_write) { 1024 for (wr_idx = 0; wr_idx < wr_num; wr_idx++) { 1025 ret = write_data(image, size, 1026 addr[wr_idx], wr_fname[wr_idx]); 1027 if (ret) 1028 break; 1029 } 1030 } 1031 1032 if (mode_spifreq) 1033 set_spi_frequency(image, size, spifreq); 1034 1035 if (mode_em100) 1036 set_em100_mode(image, size); 1037 1038 if (mode_locked) 1039 lock_descriptor(image, size); 1040 1041 if (mode_unlocked) 1042 unlock_descriptor(image, size); 1043 1044 if (write_it) { 1045 if (outfile) { 1046 ret = write_image(outfile, image, size); 1047 } else { 1048 if (lseek(bios_fd, 0, SEEK_SET)) { 1049 perror("Error while seeking"); 1050 ret = -1; 1051 } 1052 if (write(bios_fd, image, size) != size) { 1053 perror("Error while writing"); 1054 ret = -1; 1055 } 1056 } 1057 } 1058 1059 free(image); 1060 close(bios_fd); 1061 1062 return ret ? 1 : 0; 1063 } 1064