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