/ util / ifdtool / ifdtool.c
ifdtool.c
   1  /* ifdtool - dump Intel Firmware Descriptor information */
   2  /* SPDX-License-Identifier: GPL-2.0-only */
   3  
   4  #include <unistd.h>
   5  #include <stdlib.h>
   6  #include <stdio.h>
   7  #include <string.h>
   8  #include <getopt.h>
   9  #include <fcntl.h>
  10  #include <sys/types.h>
  11  #include <sys/stat.h>
  12  #include <commonlib/helpers.h>
  13  #include <fmap.h>
  14  #include "ifdtool.h"
  15  
  16  #ifndef O_BINARY
  17  #define O_BINARY 0
  18  #endif
  19  
  20  /**
  21   * PTR_IN_RANGE - examine whether a pointer falls in [base, base + limit)
  22   * @param ptr:    the non-void* pointer to a single arbitrary-sized object.
  23   * @param base:   base address represented with char* type.
  24   * @param limit:  upper limit of the legal address.
  25   *
  26   */
  27  #define PTR_IN_RANGE(ptr, base, limit)			\
  28  	((const char *)(ptr) >= (base) &&		\
  29  	 (const char *)&(ptr)[1] <= (base) + (limit))
  30  
  31  /**
  32   * PLATFORM_HAS_GBE_REGION - some platforms do not support the PCH GbE LAN region
  33   */
  34  #define PLATFORM_HAS_GBE_REGION (platform != PLATFORM_DNV)
  35  
  36  /*
  37   * PLATFORM_HAS_EC_REGION - some platforms do not support the EC region
  38   */
  39  #define PLATFORM_HAS_EC_REGION (ifd_version >= IFD_VERSION_2 && platform != PLATFORM_DNV)
  40  
  41  /*
  42   * PLATFORM_HAS_10GBE_X_REGION - some platforms have 1 or more 10GbE LAN regions
  43   */
  44  #define PLATFORM_HAS_10GBE_0_REGION (platform == PLATFORM_DNV)
  45  #define PLATFORM_HAS_10GBE_1_REGION (platform == PLATFORM_DNV)
  46  
  47  union gprd {
  48  	struct bit_field {
  49  		/*
  50  		 * Start Address: bit 0-14 of the GPRD represents the
  51  		 * protected region start address, where bit 0-11 of
  52  		 * the start address are assumed to be zero.
  53  		 */
  54  		uint32_t start : 15;
  55  
  56  		/* Specifies read protection is enabled */
  57  		uint32_t read_protect_en : 1;
  58  
  59  		/*
  60  		 * End Address: bit 16-30 of the GPRD represents the
  61  		 * protected region end address, where bit 0-11 of
  62  		 * the end address are assumed to be 0xfff.
  63  		 */
  64  		uint32_t end : 15;
  65  
  66  		/* Specifies write protection is enabled */
  67  		uint32_t write_protect_en : 1;
  68  	} __packed data;
  69  
  70  	uint32_t value;
  71  };
  72  
  73  static int max_regions_from_fdbar(const struct fdbar *fdb);
  74  
  75  static int ifd_version;
  76  static int chipset;
  77  static unsigned int max_regions = 0;
  78  static int selected_chip = 0;
  79  static int platform = -1;
  80  
  81  static const struct region_name region_names[MAX_REGIONS] = {
  82  	{ "Flash Descriptor", "fd", "flashregion_0_flashdescriptor.bin", "SI_DESC" },
  83  	{ "BIOS", "bios", "flashregion_1_bios.bin", "SI_BIOS" },
  84  	{ "Intel ME", "me", "flashregion_2_intel_me.bin", "SI_ME" },
  85  	{ "GbE", "gbe", "flashregion_3_gbe.bin", "SI_GBE" },
  86  	{ "Platform Data", "pd", "flashregion_4_platform_data.bin", "SI_PDR" },
  87  	{ "Device Exp1", "devexp", "flashregion_5_device_exp.bin", "SI_DEVICEEXT" },
  88  	{ "Secondary BIOS", "bios2", "flashregion_6_bios2.bin", "SI_BIOS2" },
  89  	{ "Reserved", "res7", "flashregion_7_reserved.bin", NULL },
  90  	{ "EC", "ec", "flashregion_8_ec.bin", "SI_EC" },
  91  	{ "Device Exp2", "devexp2", "flashregion_9_device_exp.bin", "SI_DEVICEEXT2" },
  92  	{ "IE", "ie", "flashregion_10_ie.bin", "SI_IE" },
  93  	{ "10GbE_0", "10gbe_0", "flashregion_11_10gbe0.bin", "SI_10GBE0" },
  94  	{ "10GbE_1", "10gbe_1", "flashregion_12_10gbe1.bin", "SI_10GBE1" },
  95  	{ "Reserved", "res13", "flashregion_13_reserved.bin", NULL },
  96  	{ "Reserved", "res14", "flashregion_14_reserved.bin", NULL },
  97  	{ "PTT", "ptt", "flashregion_15_ptt.bin", "SI_PTT" },
  98  };
  99  
 100  /* port from flashrom */
 101  static const char *const ich_chipset_names[] = {
 102  	"Unknown ICH",
 103  	"ICH8",
 104  	"ICH9",
 105  	"ICH10",
 106  	"Unknown PCH",
 107  	"5 series Ibex Peak",
 108  	"6 series Cougar Point",
 109  	"7 series Panther Point",
 110  	"8 series Lynx Point",
 111  	"Baytrail",
 112  	"8 series Lynx Point LP",
 113  	"8 series Wellsburg",
 114  	"9 series Wildcat Point",
 115  	"9 series Wildcat Point LP",
 116  	"Apollo Lake: N3xxx, J3xxx",
 117  	"Gemini Lake: N5xxx, J5xxx, N4xxx, J4xxx",
 118  	"Jasper Lake: N6xxx, N51xx, N45xx",
 119  	"Elkhart Lake: x6000 series Atom",
 120  	"100/200 series Sunrise Point",
 121  	"300 series Cannon Point",
 122  	"400 series Ice Point",
 123  	"500 series Tiger Point/ 600 series Alder Point",
 124  	"800 series Meteor Lake",
 125  	"C620 series Lewisburg",
 126  	"Denverton: C39xx",
 127  	NULL
 128  };
 129  
 130  static struct fdbar *find_fd(char *image, int size)
 131  {
 132  	int i, found = 0;
 133  
 134  	/* Scan for FD signature */
 135  	for (i = 0; i < (size - 4); i += 4) {
 136  		if (*(uint32_t *)(image + i) == 0x0FF0A55A) {
 137  			found = 1;
 138  			break; // signature found.
 139  		}
 140  	}
 141  
 142  	if (!found) {
 143  		printf("No Flash Descriptor found in this image\n");
 144  		return NULL;
 145  	}
 146  
 147  	struct fdbar *fdb = (struct fdbar *)(image + i);
 148  	return PTR_IN_RANGE(fdb, image, size) ? fdb : NULL;
 149  }
 150  
 151  static char *find_flumap(char *image, int size)
 152  {
 153  	/* The upper map is located in the word before the 256B-long OEM section
 154  	 * at the end of the 4kB-long flash descriptor. In the official
 155  	 * documentation this is defined as FDBAR + 0xEFC. However, starting
 156  	 * with B-Step of Ibex Peak (5 series) the signature (and thus FDBAR)
 157  	 * has moved 16 bytes back to offset 0x10 of the image. Although
 158  	 * official documentation still maintains the offset relative to FDBAR
 159  	 * this is wrong and a simple fixed offset from the start of the image
 160  	 * works.
 161  	 */
 162  	char *flumap = image + 4096 - 256 - 4;
 163  	return PTR_IN_RANGE(flumap, image, size) ? flumap : NULL;
 164  }
 165  
 166  static struct fcba *find_fcba(char *image, int size)
 167  {
 168  	struct fdbar *fdb = find_fd(image, size);
 169  	if (!fdb)
 170  		return NULL;
 171  	struct fcba *fcba = (struct fcba *)(image + ((fdb->flmap0 & 0xff) << 4));
 172  	return PTR_IN_RANGE(fcba, image, size) ? fcba : NULL;
 173  }
 174  
 175  static struct fmba *find_fmba(char *image, int size)
 176  {
 177  	struct fdbar *fdb = find_fd(image, size);
 178  	if (!fdb)
 179  		return NULL;
 180  	struct fmba *fmba = (struct fmba *)(image + ((fdb->flmap1 & 0xff) << 4));
 181  	return PTR_IN_RANGE(fmba, image, size) ? fmba : NULL;
 182  }
 183  
 184  static struct frba *find_frba(char *image, int size)
 185  {
 186  	struct fdbar *fdb = find_fd(image, size);
 187  	if (!fdb)
 188  		return NULL;
 189  	struct frba *frba =
 190  		(struct frba *) (image + (((fdb->flmap0 >> 16) & 0xff) << 4));
 191  	return PTR_IN_RANGE(frba, image, size) ? frba : NULL;
 192  }
 193  
 194  static struct fpsba *find_fpsba(char *image, int size)
 195  {
 196  	struct fdbar *fdb = find_fd(image, size);
 197  	if (!fdb)
 198  		return NULL;
 199  	struct fpsba *fpsba =
 200  		(struct fpsba *) (image + (((fdb->flmap1 >> 16) & 0xff) << 4));
 201  
 202  	int SSL = ((fdb->flmap1 >> 24) & 0xff) * sizeof(uint32_t);
 203  	if ((((char *)fpsba) + SSL) >= (image + size))
 204  		return NULL;
 205  	return fpsba;
 206  }
 207  
 208  static struct fmsba *find_fmsba(char *image, int size)
 209  {
 210  	struct fdbar *fdb = find_fd(image, size);
 211  	if (!fdb)
 212  		return NULL;
 213  	struct fmsba *fmsba = (struct fmsba *)(image + ((fdb->flmap2 & 0xff) << 4));
 214  	return PTR_IN_RANGE(fmsba, image, size) ? fmsba : NULL;
 215  }
 216  
 217  /* port from flashrom */
 218  static enum ich_chipset ifd1_guess_chipset(char *image, int size)
 219  {
 220  	const struct fdbar *fdb = find_fd(image, size);
 221  	if (!fdb)
 222  		exit(EXIT_FAILURE);
 223  	uint32_t iccriba = (fdb->flmap2 >> 16) & 0xff;
 224  	uint32_t msl = (fdb->flmap2 >> 8) & 0xff;
 225  	uint32_t isl = (fdb->flmap1 >> 24);
 226  
 227  	/* Rest for IFD1 chipset type */
 228  	if (iccriba == 0x00) {
 229  		if (msl == 0 && isl <= 2)
 230  			return CHIPSET_ICH8;
 231  		else if (isl <= 2)
 232  			return CHIPSET_ICH9;
 233  		else if (isl <= 10)
 234  			return CHIPSET_ICH10;
 235  		else if (isl <= 16)
 236  			return CHIPSET_5_SERIES_IBEX_PEAK;
 237  		printf("Peculiar firmware descriptor, assuming Ibex Peak compatibility.\n");
 238  		return CHIPSET_5_SERIES_IBEX_PEAK;
 239  	} else if (iccriba < 0x31 && (fdb->flmap2 & 0xff) < 0x30) {
 240  		if (msl == 0 && isl <= 17)
 241  			return CHIPSET_BAYTRAIL;
 242  		else if (msl <= 1 && isl <= 18)
 243  			return CHIPSET_6_SERIES_COUGAR_POINT;
 244  		else if (msl <= 1 && isl <= 21)
 245  			return CHIPSET_8_SERIES_LYNX_POINT;
 246  		printf("Peculiar firmware descriptor, assuming Wildcat Point compatibility.\n");
 247  		return CHIPSET_9_SERIES_WILDCAT_POINT;
 248  	}
 249  	return CHIPSET_PCH_UNKNOWN;
 250  }
 251  
 252  static enum ich_chipset ifd2_platform_to_chipset(const int pindex)
 253  {
 254  	switch (pindex) {
 255  	case PLATFORM_APL:
 256  		return CHIPSET_N_J_SERIES_APOLLO_LAKE;
 257  	case PLATFORM_GLK:
 258  		return CHIPSET_N_J_SERIES_GEMINI_LAKE;
 259  	case PLATFORM_JSL:
 260  		return CHIPSET_N_SERIES_JASPER_LAKE;
 261  	case PLATFORM_EHL:
 262  		return CHIPSET_x6000_SERIES_ELKHART_LAKE;
 263  	case PLATFORM_SKLKBL:
 264  		return CHIPSET_100_200_SERIES_SUNRISE_POINT;
 265  	case PLATFORM_CNL:
 266  		return CHIPSET_300_SERIES_CANNON_POINT;
 267  	case PLATFORM_TGL:
 268  	case PLATFORM_ADL:
 269  	case PLATFORM_IFD2:
 270  		return CHIPSET_500_600_SERIES_TIGER_ALDER_POINT;
 271  	case PLATFORM_MTL:
 272  		return CHIPSET_800_SERIES_METEOR_LAKE;
 273  	case PLATFORM_PTL:
 274  		return CHIPSET_900_SERIES_PANTHER_LAKE;
 275  	case PLATFORM_ICL:
 276  		return CHIPSET_400_SERIES_ICE_POINT;
 277  	case PLATFORM_LBG:
 278  		return CHIPSET_C620_SERIES_LEWISBURG;
 279  	case PLATFORM_DNV:
 280  		return CHIPSET_DENVERTON;
 281  	case PLATFORM_WBG:
 282  		return CHIPSET_8_SERIES_WELLSBURG;
 283  	default:
 284  		return CHIPSET_PCH_UNKNOWN;
 285  	}
 286  }
 287  
 288  /*
 289   * Some newer platforms have re-defined the FCBA field that was used to
 290   * distinguish IFD v1 v/s v2. Define a list of platforms that we know do not
 291   * have the required FCBA field, but are IFD v2 and return true if current
 292   * platform is one of them.
 293   */
 294  static int is_platform_ifd_2(void)
 295  {
 296  	static const int ifd_2_platforms[] = {
 297  		PLATFORM_APL,
 298  		PLATFORM_GLK,
 299  		PLATFORM_CNL,
 300  		PLATFORM_LBG,
 301  		PLATFORM_DNV,
 302  		PLATFORM_ICL,
 303  		PLATFORM_TGL,
 304  		PLATFORM_JSL,
 305  		PLATFORM_EHL,
 306  		PLATFORM_ADL,
 307  		PLATFORM_SKLKBL,
 308  		PLATFORM_IFD2,
 309  		PLATFORM_MTL,
 310  		PLATFORM_PTL,
 311  		PLATFORM_WBG,
 312  	};
 313  	unsigned int i;
 314  
 315  	for (i = 0; i < ARRAY_SIZE(ifd_2_platforms); i++) {
 316  		if (platform == ifd_2_platforms[i])
 317  			return 1;
 318  	}
 319  
 320  	return 0;
 321  }
 322  
 323  static void check_ifd_version(char *image, int size)
 324  {
 325  	const struct fdbar *fdb = find_fd(image, size);
 326  
 327  	if (is_platform_ifd_2()) {
 328  		chipset = ifd2_platform_to_chipset(platform);
 329  		if (chipset == CHIPSET_8_SERIES_WELLSBURG)
 330  			ifd_version = IFD_VERSION_1_5;
 331  		else
 332  			ifd_version = IFD_VERSION_2;
 333  		max_regions = MIN(max_regions_from_fdbar(fdb), MAX_REGIONS);
 334  	} else {
 335  		ifd_version = IFD_VERSION_1;
 336  		chipset = ifd1_guess_chipset(image, size);
 337  		max_regions = MIN(max_regions_from_fdbar(fdb), MAX_REGIONS_OLD);
 338  	}
 339  }
 340  
 341  static struct region get_region(const struct frba *frba, unsigned int region_type)
 342  {
 343  	int base_mask;
 344  	int limit_mask;
 345  	uint32_t flreg;
 346  	struct region region;
 347  
 348  	if (ifd_version >= IFD_VERSION_2)
 349  		base_mask = 0x7fff;
 350  	else
 351  		base_mask = 0xfff;
 352  
 353  	limit_mask = base_mask << 16;
 354  
 355  	if (region_type >= max_regions) {
 356  		fprintf(stderr, "Invalid region type %d.\n", region_type);
 357  		exit(EXIT_FAILURE);
 358  	}
 359  
 360  	flreg = frba->flreg[region_type];
 361  	region.base = (flreg & base_mask) << 12;
 362  	region.limit = ((flreg & limit_mask) >> 4) | 0xfff;
 363  	region.size = region.limit - region.base + 1;
 364  	region.type = region_type;
 365  
 366  	if (region.size < 0)
 367  		region.size = 0;
 368  
 369  	return region;
 370  }
 371  
 372  static void set_region(struct frba *frba, unsigned int region_type,
 373  		       const struct region *region)
 374  {
 375  	if (region_type >= max_regions) {
 376  		fprintf(stderr, "Invalid region type %u.\n", region_type);
 377  		exit (EXIT_FAILURE);
 378  	}
 379  
 380  	frba->flreg[region_type] =
 381  		(((region->limit >> 12) & 0x7fff) << 16) |
 382  		((region->base >> 12) & 0x7fff);
 383  }
 384  
 385  static const char *region_name(unsigned int region_type)
 386  {
 387  	if (region_type >= max_regions) {
 388  		fprintf(stderr, "Invalid region type.\n");
 389  		exit(EXIT_FAILURE);
 390  	}
 391  
 392  	return region_names[region_type].pretty;
 393  }
 394  
 395  static int region_num(const char *name)
 396  {
 397  	unsigned int i;
 398  
 399  	for (i = 0; i < max_regions; i++) {
 400  		if (strcasecmp(name, region_names[i].pretty) == 0)
 401  			return i;
 402  		if (strcasecmp(name, region_names[i].terse) == 0)
 403  			return i;
 404  	}
 405  
 406  	return -1;
 407  }
 408  
 409  static void dump_region(unsigned int num, const struct frba *frba)
 410  {
 411  	struct region region = get_region(frba, num);
 412  	printf("  Flash Region %d (%s): %08x - %08x %s\n",
 413  		num, region_name(num), region.base, region.limit,
 414  		region.size < 1 ? "(unused)" : "");
 415  }
 416  
 417  static int sort_compare(const void *a, const void *b)
 418  {
 419  	return *(size_t *)a - *(size_t *)b;
 420  }
 421  
 422  /*
 423   * IFDv1 always has 8 regions, while IFDv2 always has 16 regions.
 424   *
 425   * It's platform specific which regions are used or are reserved.
 426   * The 'SPI programming guide' as the name says is a guide only,
 427   * not a specification what the hardware actually does.
 428   * The best to do is not to rely on the guide, but detect how many
 429   * regions are present in the IFD and expose them all.
 430   *
 431   * Very early IFDv2 chipsets, sometimes unofficially referred to as
 432   * IFDv1.5 platforms, only have 8 regions. To not corrupt the IFD when
 433   * operating on an IFDv1.5 detect how much space is actually present
 434   * in the IFD.
 435   */
 436  static int max_regions_from_fdbar(const struct fdbar *fdb)
 437  {
 438  	const size_t fcba = (fdb->flmap0 & 0xff) << 4;
 439  	const size_t fmba = (fdb->flmap1 & 0xff) << 4;
 440  	const size_t frba = ((fdb->flmap0 >> 16) & 0xff) << 4;
 441  	const size_t fpsba = ((fdb->flmap1 >> 16) & 0xff) << 4;
 442  	const size_t flumap = 4096 - 256 - 4;
 443  	size_t sorted[5] = {fcba, fmba, frba, fpsba, flumap};
 444  
 445  	qsort(sorted, ARRAY_SIZE(sorted), sizeof(size_t), sort_compare);
 446  
 447  	for (size_t i = 0; i < 4; i++) {
 448  		/*
 449  		 * Find FRBA in the sorted array and determine the size of the
 450  		 * region by the start of the next region. Every region requires
 451  		 * 4 bytes of space.
 452  		 */
 453  		if (sorted[i] == frba)
 454  			return MIN((sorted[i + 1] - sorted[i]) / 4, MAX_REGIONS);
 455  	}
 456  	/* Never reaches this point */
 457  	return 0;
 458  }
 459  
 460  static void dump_frba(const struct frba *frba)
 461  {
 462  	unsigned int i;
 463  	struct region region;
 464  	printf("Found Region Section\n");
 465  	for (i = 0; i < max_regions; i++) {
 466  		region = get_region(frba, i);
 467  		/* Skip unused & reserved Flash Region */
 468  		if (region.size < 1 && !strcmp(region_name(i), "Reserved"))
 469  			continue;
 470  
 471  		printf("FLREG%u:    0x%08x\n", i, frba->flreg[i]);
 472  		dump_region(i, frba);
 473  	}
 474  }
 475  
 476  static void dump_flashrom_layout(char *image, int size, const char *layout_fname)
 477  {
 478  	const struct frba *frba = find_frba(image, size);
 479  	if (!frba)
 480  		exit(EXIT_FAILURE);
 481  
 482  	int layout_fd = open(layout_fname, O_WRONLY | O_CREAT | O_TRUNC, 0644);
 483  	if (layout_fd == -1) {
 484  		perror("Could not open file");
 485  		exit(EXIT_FAILURE);
 486  	}
 487  
 488  	for (unsigned int i = 0; i < max_regions; i++) {
 489  		struct region region = get_region(frba, i);
 490  
 491  		/* A region limit of 0 is an indicator of an unused region
 492  		 * A region base of 7FFFh is an indicator of a reserved region
 493  		 */
 494  		if (region.limit == 0 || region.base == 0x07FFF000)
 495  			continue;
 496  
 497  		char buf[LAYOUT_LINELEN];
 498  		snprintf(buf, LAYOUT_LINELEN, "%08x:%08x %s\n", region.base, region.limit, region_names[i].terse);
 499  		if (write(layout_fd, buf, strlen(buf)) < 0) {
 500  			perror("Could not write to file");
 501  			exit(EXIT_FAILURE);
 502  		}
 503  	}
 504  	close(layout_fd);
 505  	printf("Wrote layout to %s\n", layout_fname);
 506  }
 507  
 508  static void _decode_spi_frequency(unsigned int freq)
 509  {
 510  	switch (freq) {
 511  	case SPI_FREQUENCY_20MHZ:
 512  		printf("20MHz");
 513  		break;
 514  	case SPI_FREQUENCY_33MHZ:
 515  		printf("33MHz");
 516  		break;
 517  	case SPI_FREQUENCY_48MHZ:
 518  		printf("48MHz");
 519  		break;
 520  	case SPI_FREQUENCY_50MHZ_30MHZ:
 521  		switch (ifd_version) {
 522  		case IFD_VERSION_1:
 523  		case IFD_VERSION_1_5:
 524  			printf("50MHz");
 525  			break;
 526  		case IFD_VERSION_2:
 527  			printf("30MHz");
 528  			break;
 529  		}
 530  		break;
 531  	case SPI_FREQUENCY_17MHZ:
 532  		printf("17MHz");
 533  		break;
 534  	default:
 535  		printf("unknown<%x>MHz", freq);
 536  	}
 537  }
 538  
 539  static void _decode_spi_frequency_500_series(unsigned int freq)
 540  {
 541  	switch (freq) {
 542  	case SPI_FREQUENCY_100MHZ:
 543  		printf("100MHz");
 544  		break;
 545  	case SPI_FREQUENCY_50MHZ:
 546  		printf("50MHz");
 547  		break;
 548  	case SPI_FREQUENCY_500SERIES_33MHZ:
 549  		printf("33MHz");
 550  		break;
 551  	case SPI_FREQUENCY_25MHZ:
 552  		printf("25MHz");
 553  		break;
 554  	case SPI_FREQUENCY_14MHZ:
 555  		printf("14MHz");
 556  		break;
 557  	default:
 558  		printf("unknown<%x>MHz", freq);
 559  	}
 560  }
 561  
 562  static void decode_spi_frequency(unsigned int freq)
 563  {
 564  	switch (chipset) {
 565  	case CHIPSET_500_600_SERIES_TIGER_ALDER_POINT:
 566  	case CHIPSET_800_SERIES_METEOR_LAKE:
 567  	case CHIPSET_900_SERIES_PANTHER_LAKE:
 568  		_decode_spi_frequency_500_series(freq);
 569  		break;
 570  	default:
 571  		_decode_spi_frequency(freq);
 572  	}
 573  }
 574  
 575  static void _decode_espi_frequency(unsigned int freq)
 576  {
 577  	switch (freq) {
 578  	case ESPI_FREQUENCY_20MHZ:
 579  		printf("20MHz");
 580  		break;
 581  	case ESPI_FREQUENCY_24MHZ:
 582  		printf("24MHz");
 583  		break;
 584  	case ESPI_FREQUENCY_30MHZ:
 585  		printf("30MHz");
 586  		break;
 587  	case ESPI_FREQUENCY_48MHZ:
 588  		printf("48MHz");
 589  		break;
 590  	case ESPI_FREQUENCY_60MHZ:
 591  		printf("60MHz");
 592  		break;
 593  	case ESPI_FREQUENCY_17MHZ:
 594  		printf("17MHz");
 595  		break;
 596  	default:
 597  		printf("unknown<%x>MHz", freq);
 598  	}
 599  }
 600  
 601  static void _decode_espi_frequency_500_series(unsigned int freq)
 602  {
 603  	switch (freq) {
 604  	case ESPI_FREQUENCY_500SERIES_20MHZ:
 605  		printf("20MHz");
 606  		break;
 607  	case ESPI_FREQUENCY_500SERIES_24MHZ:
 608  		printf("24MHz");
 609  		break;
 610  	case ESPI_FREQUENCY_500SERIES_25MHZ:
 611  		printf("25MHz");
 612  		break;
 613  	case ESPI_FREQUENCY_500SERIES_48MHZ:
 614  		printf("48MHz");
 615  		break;
 616  	case ESPI_FREQUENCY_500SERIES_60MHZ:
 617  		printf("60MHz");
 618  		break;
 619  	default:
 620  		printf("unknown<%x>MHz", freq);
 621  	}
 622  }
 623  
 624  static void _decode_espi_frequency_800_series(unsigned int freq)
 625  {
 626  	switch (freq) {
 627  	case ESPI_FREQUENCY_800SERIES_20MHZ:
 628  		printf("20MHz");
 629  		break;
 630  	case ESPI_FREQUENCY_800SERIES_25MHZ:
 631  		printf("25MHz");
 632  		break;
 633  	case ESPI_FREQUENCY_800SERIES_33MHZ:
 634  		printf("33MHz");
 635  		break;
 636  	case ESPI_FREQUENCY_800SERIES_50MHZ:
 637  		printf("50MHz");
 638  		break;
 639  	default:
 640  		printf("unknown<%x>MHz", freq);
 641  	}
 642  }
 643  
 644  static void decode_espi_frequency(unsigned int freq)
 645  {
 646  	switch (chipset) {
 647  	case CHIPSET_500_600_SERIES_TIGER_ALDER_POINT:
 648  		_decode_espi_frequency_500_series(freq);
 649  		break;
 650  	case CHIPSET_800_SERIES_METEOR_LAKE:
 651  	case CHIPSET_900_SERIES_PANTHER_LAKE:
 652  		_decode_espi_frequency_800_series(freq);
 653  		break;
 654  	default:
 655  		_decode_espi_frequency(freq);
 656  	}
 657  }
 658  
 659  static void decode_component_density(unsigned int density)
 660  {
 661  	switch (density) {
 662  	case COMPONENT_DENSITY_512KB:
 663  		printf("512KB");
 664  		break;
 665  	case COMPONENT_DENSITY_1MB:
 666  		printf("1MB");
 667  		break;
 668  	case COMPONENT_DENSITY_2MB:
 669  		printf("2MB");
 670  		break;
 671  	case COMPONENT_DENSITY_4MB:
 672  		printf("4MB");
 673  		break;
 674  	case COMPONENT_DENSITY_8MB:
 675  		printf("8MB");
 676  		break;
 677  	case COMPONENT_DENSITY_16MB:
 678  		printf("16MB");
 679  		break;
 680  	case COMPONENT_DENSITY_32MB:
 681  		printf("32MB");
 682  		break;
 683  	case COMPONENT_DENSITY_64MB:
 684  		printf("64MB");
 685  		break;
 686  	case COMPONENT_DENSITY_UNUSED:
 687  		printf("UNUSED");
 688  		break;
 689  	default:
 690  		printf("unknown<%x>MB", density);
 691  	}
 692  }
 693  
 694  static int is_platform_with_pch(void)
 695  {
 696  	if (chipset >= CHIPSET_5_SERIES_IBEX_PEAK)
 697  		return 1;
 698  
 699  	return 0;
 700  }
 701  
 702  /* FLMAP0 register bit 24 onwards are reserved from SPT PCH */
 703  static int is_platform_with_100x_series_pch(void)
 704  {
 705  	if (chipset >= CHIPSET_100_200_SERIES_SUNRISE_POINT &&
 706  			chipset <= CHIPSET_900_SERIES_PANTHER_LAKE)
 707  		return 1;
 708  
 709  	return 0;
 710  }
 711  
 712  static void dump_fcba(const struct fcba *fcba, const struct fpsba *fpsba)
 713  {
 714  	unsigned int freq;
 715  
 716  	printf("\nFound Component Section\n");
 717  	printf("FLCOMP     0x%08x\n", fcba->flcomp);
 718  	printf("  Dual Output Fast Read Support:       %ssupported\n",
 719  		(fcba->flcomp & (1 << 30)) ? "" : "not ");
 720  	printf("  Read ID/Read Status Clock Frequency: ");
 721  	decode_spi_frequency((fcba->flcomp >> 27) & 7);
 722  	printf("\n  Write/Erase Clock Frequency:         ");
 723  	decode_spi_frequency((fcba->flcomp >> 24) & 7);
 724  	printf("\n  Fast Read Clock Frequency:           ");
 725  	decode_spi_frequency((fcba->flcomp >> 21) & 7);
 726  	printf("\n  Fast Read Support:                   %ssupported",
 727  		(fcba->flcomp & (1 << 20)) ? "" : "not ");
 728  	if (is_platform_with_100x_series_pch() &&
 729  			chipset != CHIPSET_100_200_SERIES_SUNRISE_POINT) {
 730  		printf("\n  Read eSPI/EC Bus Frequency:          ");
 731  		if (chipset == CHIPSET_500_600_SERIES_TIGER_ALDER_POINT)
 732  			freq = (fpsba->pchstrp[22] & 0x38) >> 3;
 733  		else if (chipset == CHIPSET_800_SERIES_METEOR_LAKE)
 734  			freq = (fpsba->pchstrp[65] & 0x38) >> 3;
 735  		else if (chipset == CHIPSET_900_SERIES_PANTHER_LAKE)
 736  			freq = (fpsba->pchstrp[119] & 0x38) >> 3;
 737  		else
 738  			freq = (fcba->flcomp >> 17) & 7;
 739  		decode_espi_frequency(freq);
 740  
 741  		printf("\n  Quad I/O Read:                       %s",
 742  			(fcba->flcomp & (1 << 15)) ? "enabled" : "disabled");
 743  		printf("\n  Quad Output Read:                    %s",
 744  			(fcba->flcomp & (1 << 14)) ? "enabled" : "disabled");
 745  		printf("\n  Dual I/O Read:                       %s",
 746  			(fcba->flcomp & (1 << 13)) ? "enabled" : "disabled");
 747  		printf("\n  Dual Output Read:                    %s",
 748  			(fcba->flcomp & (1 << 12)) ? "enabled" : "disabled");
 749  	} else {
 750  		printf("\n  Read Clock Frequency:                ");
 751  		decode_spi_frequency((fcba->flcomp >> 17) & 7);
 752  	}
 753  
 754  	switch (ifd_version) {
 755  	case IFD_VERSION_1:
 756  		printf("\n  Component 2 Density:                 ");
 757  		decode_component_density((fcba->flcomp >> 3) & 7);
 758  		printf("\n  Component 1 Density:                 ");
 759  		decode_component_density(fcba->flcomp & 7);
 760  		break;
 761  	case IFD_VERSION_1_5:
 762  	case IFD_VERSION_2:
 763  		printf("\n  Component 2 Density:                 ");
 764  		decode_component_density((fcba->flcomp >> 4) & 0xf);
 765  		printf("\n  Component 1 Density:                 ");
 766  		decode_component_density(fcba->flcomp & 0xf);
 767  		break;
 768  	}
 769  
 770  	printf("\n");
 771  	printf("FLILL      0x%08x\n", fcba->flill);
 772  	printf("  Invalid Instruction 3: 0x%02x\n",
 773  		(fcba->flill >> 24) & 0xff);
 774  	printf("  Invalid Instruction 2: 0x%02x\n",
 775  		(fcba->flill >> 16) & 0xff);
 776  	printf("  Invalid Instruction 1: 0x%02x\n",
 777  		(fcba->flill >> 8) & 0xff);
 778  	printf("  Invalid Instruction 0: 0x%02x\n",
 779  		fcba->flill & 0xff);
 780  	if (is_platform_with_100x_series_pch()) {
 781  		printf("FLILL1     0x%08x\n", fcba->flpb);
 782  		printf("  Invalid Instruction 7: 0x%02x\n",
 783  			(fcba->flpb >> 24) & 0xff);
 784  		printf("  Invalid Instruction 6: 0x%02x\n",
 785  			(fcba->flpb >> 16) & 0xff);
 786  		printf("  Invalid Instruction 5: 0x%02x\n",
 787  			(fcba->flpb >> 8) & 0xff);
 788  		printf("  Invalid Instruction 4: 0x%02x\n",
 789  			fcba->flpb & 0xff);
 790  	} else {
 791  		printf("FLPB       0x%08x\n", fcba->flpb);
 792  		printf("  Flash Partition Boundary Address: 0x%06x\n\n",
 793  				(fcba->flpb & 0xfff) << 12);
 794  	}
 795  }
 796  
 797  static void dump_fpsba(const struct fdbar *fdb, const struct fpsba *fpsba)
 798  {
 799  	unsigned int i;
 800  	/* SoC Straps, aka PSL, aka ISL */
 801  	unsigned int SS = (fdb->flmap1 >> 24) & 0xff;
 802  
 803  	printf("Found PCH Strap Section\n");
 804  	for (i = 0; i < SS; i++)
 805  		printf("PCHSTRP%-3u: 0x%08x\n", i, fpsba->pchstrp[i]);
 806  
 807  	if (ifd_version >= IFD_VERSION_2) {
 808  		printf("HAP bit is %sset\n",
 809  		       fpsba->pchstrp[0] & (1 << 16) ? "" : "not ");
 810  	} else if (chipset >= CHIPSET_ICH8 && chipset <= CHIPSET_ICH10) {
 811  		printf("ICH_MeDisable bit is %sset\n",
 812  		       fpsba->pchstrp[0] & 1 ? "" : "not ");
 813  	} else {
 814  		printf("AltMeDisable bit is %sset\n",
 815  		       fpsba->pchstrp[10] & (1 << 7) ? "" : "not ");
 816  	}
 817  
 818  	printf("\n");
 819  }
 820  
 821  static void decode_flmstr(uint32_t flmstr)
 822  {
 823  	int wr_shift, rd_shift;
 824  	if (ifd_version >= IFD_VERSION_2) {
 825  		wr_shift = FLMSTR_WR_SHIFT_V2;
 826  		rd_shift = FLMSTR_RD_SHIFT_V2;
 827  	} else {
 828  		wr_shift = FLMSTR_WR_SHIFT_V1;
 829  		rd_shift = FLMSTR_RD_SHIFT_V1;
 830  	}
 831  
 832  	/* EC region access only available on v2+ */
 833  	if (PLATFORM_HAS_EC_REGION)
 834  		printf("  EC Region Write Access:            %s\n",
 835  			(flmstr & (1 << (wr_shift + 8))) ?
 836  			"enabled" : "disabled");
 837  	printf("  Platform Data Region Write Access: %s\n",
 838  			(flmstr & (1 << (wr_shift + 4))) ? "enabled" : "disabled");
 839  	if (PLATFORM_HAS_GBE_REGION) {
 840  		printf("  GbE Region Write Access:           %s\n",
 841  			(flmstr & (1 << (wr_shift + 3))) ? "enabled" : "disabled");
 842  	}
 843  	printf("  Intel ME Region Write Access:      %s\n",
 844  		(flmstr & (1 << (wr_shift + 2))) ? "enabled" : "disabled");
 845  	printf("  Host CPU/BIOS Region Write Access: %s\n",
 846  		(flmstr & (1 << (wr_shift + 1))) ? "enabled" : "disabled");
 847  	printf("  Flash Descriptor Write Access:     %s\n",
 848  		(flmstr & (1 << wr_shift)) ? "enabled" : "disabled");
 849  	if (PLATFORM_HAS_10GBE_0_REGION) {
 850  		printf("  10GbE_0 Write Access:               %s\n",
 851  			(flmstr & (1 << (wr_shift + 11))) ? "enabled" : "disabled");
 852  	}
 853  	if (PLATFORM_HAS_10GBE_1_REGION) {
 854  		printf("  10GbE_1 Write Access:               %s\n",
 855  			(flmstr & (1 << 4)) ? "enabled" : "disabled");
 856  	}
 857  
 858  	if (PLATFORM_HAS_EC_REGION)
 859  		printf("  EC Region Read Access:             %s\n",
 860  			(flmstr & (1 << (rd_shift + 8))) ?
 861  			"enabled" : "disabled");
 862  	printf("  Platform Data Region Read Access:  %s\n",
 863  		(flmstr & (1 << (rd_shift + 4))) ? "enabled" : "disabled");
 864  	if (PLATFORM_HAS_GBE_REGION) {
 865  		printf("  GbE Region Read Access:            %s\n",
 866  			(flmstr & (1 << (rd_shift + 3))) ? "enabled" : "disabled");
 867  	}
 868  	printf("  Intel ME Region Read Access:       %s\n",
 869  		(flmstr & (1 << (rd_shift + 2))) ? "enabled" : "disabled");
 870  	printf("  Host CPU/BIOS Region Read Access:  %s\n",
 871  		(flmstr & (1 << (rd_shift + 1))) ? "enabled" : "disabled");
 872  	printf("  Flash Descriptor Read Access:      %s\n",
 873  		(flmstr & (1 << rd_shift)) ? "enabled" : "disabled");
 874  	if (PLATFORM_HAS_10GBE_0_REGION) {
 875  		printf("  10GbE_0 Read Access:                %s\n",
 876  			(flmstr & (1 << (rd_shift + 11))) ? "enabled" : "disabled");
 877  	}
 878  	if (PLATFORM_HAS_10GBE_1_REGION) {
 879  		printf("  10GbE_1 Read Access:                %s\n",
 880  			(flmstr & (1 << 0)) ? "enabled" : "disabled");
 881  	}
 882  
 883  	/* Requestor ID doesn't exist for ifd 2 */
 884  	if (ifd_version < IFD_VERSION_2)
 885  		printf("  Requester ID:                      0x%04x\n\n",
 886  			flmstr & 0xffff);
 887  }
 888  
 889  static void dump_fmba(const struct fmba *fmba)
 890  {
 891  	printf("Found Master Section\n");
 892  	printf("FLMSTR1:   0x%08x (Host CPU/BIOS)\n", fmba->flmstr1);
 893  	decode_flmstr(fmba->flmstr1);
 894  	printf("FLMSTR2:   0x%08x (Intel ME)\n", fmba->flmstr2);
 895  	decode_flmstr(fmba->flmstr2);
 896  	if (PLATFORM_HAS_GBE_REGION) {
 897  		printf("FLMSTR3:   0x%08x (GbE)\n", fmba->flmstr3);
 898  		decode_flmstr(fmba->flmstr3);
 899  		if (ifd_version >= IFD_VERSION_2) {
 900  			printf("FLMSTR5:   0x%08x (EC)\n", fmba->flmstr5);
 901  			decode_flmstr(fmba->flmstr5);
 902  		}
 903  	} else {
 904  		printf("FLMSTR6:  0x%08x (IE)\n", fmba->flmstr6);
 905  		decode_flmstr(fmba->flmstr6);
 906  	}
 907  }
 908  
 909  static void dump_fmsba(const struct fmsba *fmsba)
 910  {
 911  	unsigned int i;
 912  	printf("Found Processor Strap Section\n");
 913  	for (i = 0; i < ARRAY_SIZE(fmsba->data); i++)
 914  		printf("????:      0x%08x\n", fmsba->data[i]);
 915  
 916  	if (chipset >= CHIPSET_ICH8 && chipset <= CHIPSET_ICH10) {
 917  		printf("MCH_MeDisable bit is %sset\n",
 918  			fmsba->data[0] & 1 ? "" : "not ");
 919  		printf("MCH_AltMeDisable bit is %sset\n",
 920  			fmsba->data[0] & (1 << 7) ? "" : "not ");
 921  	}
 922  }
 923  
 924  static void dump_jid(uint32_t jid)
 925  {
 926  	printf("    SPI Component Vendor ID:            0x%02x\n",
 927  		jid & 0xff);
 928  	printf("    SPI Component Device ID 0:          0x%02x\n",
 929  		(jid >> 8) & 0xff);
 930  	printf("    SPI Component Device ID 1:          0x%02x\n",
 931  		(jid >> 16) & 0xff);
 932  }
 933  
 934  static void dump_vscc(uint32_t vscc)
 935  {
 936  	printf("    Lower Erase Opcode:                 0x%02x\n",
 937  		vscc >> 24);
 938  	printf("    Lower Write Enable on Write Status: 0x%02x\n",
 939  		vscc & (1 << 20) ? 0x06 : 0x50);
 940  	printf("    Lower Write Status Required:        %s\n",
 941  		vscc & (1 << 19) ? "Yes" : "No");
 942  	printf("    Lower Write Granularity:            %d bytes\n",
 943  		vscc & (1 << 18) ? 64 : 1);
 944  	printf("    Lower Block / Sector Erase Size:    ");
 945  	switch ((vscc >> 16) & 0x3) {
 946  	case 0:
 947  		printf("256 Byte\n");
 948  		break;
 949  	case 1:
 950  		printf("4KB\n");
 951  		break;
 952  	case 2:
 953  		printf("8KB\n");
 954  		break;
 955  	case 3:
 956  		printf("64KB\n");
 957  		break;
 958  	}
 959  
 960  	printf("    Upper Erase Opcode:                 0x%02x\n",
 961  		(vscc >> 8) & 0xff);
 962  	printf("    Upper Write Enable on Write Status: 0x%02x\n",
 963  		vscc & (1 << 4) ? 0x06 : 0x50);
 964  	printf("    Upper Write Status Required:        %s\n",
 965  		vscc & (1 << 3) ? "Yes" : "No");
 966  	printf("    Upper Write Granularity:            %d bytes\n",
 967  		vscc & (1 << 2) ? 64 : 1);
 968  	printf("    Upper Block / Sector Erase Size:    ");
 969  	switch (vscc & 0x3) {
 970  	case 0:
 971  		printf("256 Byte\n");
 972  		break;
 973  	case 1:
 974  		printf("4KB\n");
 975  		break;
 976  	case 2:
 977  		printf("8KB\n");
 978  		break;
 979  	case 3:
 980  		printf("64KB\n");
 981  		break;
 982  	}
 983  }
 984  
 985  static void dump_vtba(const struct vtba *vtba, int vtl)
 986  {
 987  	int i;
 988  	int max_len = sizeof(struct vtba) / sizeof(struct vscc);
 989  	int num = (vtl >> 1) < max_len ? (vtl >> 1) : max_len;
 990  
 991  	printf("ME VSCC table:\n");
 992  	for (i = 0; i < num; i++) {
 993  		printf("  JID%d:  0x%08x\n", i, vtba->entry[i].jid);
 994  		dump_jid(vtba->entry[i].jid);
 995  		printf("  VSCC%d: 0x%08x\n", i, vtba->entry[i].vscc);
 996  		dump_vscc(vtba->entry[i].vscc);
 997  	}
 998  	printf("\n");
 999  }
1000  
1001  static void dump_oem(const uint8_t *oem)
1002  {
1003  	int i, j;
1004  	printf("OEM Section:\n");
1005  	for (i = 0; i < 4; i++) {
1006  		printf("%02x:", i << 4);
1007  		for (j = 0; j < 16; j++)
1008  			printf(" %02x", oem[(i << 4) + j]);
1009  		printf("\n");
1010  	}
1011  	printf("\n");
1012  }
1013  
1014  static void dump_fd(char *image, int size)
1015  {
1016  	const struct fdbar *fdb = find_fd(image, size);
1017  	if (!fdb)
1018  		exit(EXIT_FAILURE);
1019  
1020  	printf("%s", is_platform_with_pch() ? "PCH" : "ICH");
1021  	printf(" Revision: %s\n", ich_chipset_names[chipset]);
1022  	printf("FLMAP0:    0x%08x\n", fdb->flmap0);
1023  	if (!is_platform_with_100x_series_pch())
1024  		printf("  NR:      %d\n", (fdb->flmap0 >> 24) & 7);
1025  	printf("  FRBA:    0x%x\n", ((fdb->flmap0 >> 16) & 0xff) << 4);
1026  	printf("  NC:      %d\n", ((fdb->flmap0 >> 8) & 3) + 1);
1027  	printf("  FCBA:    0x%x\n", ((fdb->flmap0) & 0xff) << 4);
1028  
1029  	printf("FLMAP1:    0x%08x\n", fdb->flmap1);
1030  	printf("  %s:     ", is_platform_with_100x_series_pch() ? "PSL" : "ISL");
1031  	printf("0x%02x\n", (fdb->flmap1 >> 24) & 0xff);
1032  	printf("  FPSBA:   0x%x\n", ((fdb->flmap1 >> 16) & 0xff) << 4);
1033  	printf("  NM:      %d\n", (fdb->flmap1 >> 8) & 3);
1034  	printf("  FMBA:    0x%x\n", ((fdb->flmap1) & 0xff) << 4);
1035  
1036  	if (!is_platform_with_100x_series_pch()) {
1037  		printf("FLMAP2:    0x%08x\n", fdb->flmap2);
1038  		printf("  PSL:     0x%04x\n", (fdb->flmap2 >> 8) & 0xffff);
1039  		printf("  FMSBA:   0x%x\n", ((fdb->flmap2) & 0xff) << 4);
1040  	}
1041  
1042  	if (chipset == CHIPSET_500_600_SERIES_TIGER_ALDER_POINT ||
1043  		 chipset == CHIPSET_800_SERIES_METEOR_LAKE ||
1044  		 chipset == CHIPSET_900_SERIES_PANTHER_LAKE) {
1045  		printf("FLMAP3:    0x%08x\n", fdb->flmap3);
1046  		printf("  Minor Revision ID:     0x%04x\n", (fdb->flmap3 >> 14) & 0x7f);
1047  		printf("  Major Revision ID:     0x%04x\n", (fdb->flmap3 >> 21) & 0x7ff);
1048  	}
1049  
1050  	char *flumap = find_flumap(image, size);
1051  	uint32_t flumap1 = *(uint32_t *)flumap;
1052  	printf("FLUMAP1:   0x%08x\n", flumap1);
1053  	printf("  Intel ME VSCC Table Length (VTL):        %d\n",
1054  		(flumap1 >> 8) & 0xff);
1055  	printf("  Intel ME VSCC Table Base Address (VTBA): 0x%06x\n\n",
1056  		(flumap1 & 0xff) << 4);
1057  	dump_vtba((struct vtba *)
1058  			(image + ((flumap1 & 0xff) << 4)),
1059  			(flumap1 >> 8) & 0xff);
1060  	dump_oem((const uint8_t *)image + 0xf00);
1061  
1062  	const struct frba *frba = find_frba(image, size);
1063  	const struct fcba *fcba = find_fcba(image, size);
1064  	const struct fpsba *fpsba = find_fpsba(image, size);
1065  	const struct fmba *fmba = find_fmba(image, size);
1066  	const struct fmsba *fmsba = find_fmsba(image, size);
1067  
1068  	if (frba && fcba && fpsba && fmba && fmsba) {
1069  		dump_frba(frba);
1070  		dump_fcba(fcba, fpsba);
1071  		dump_fpsba(fdb, fpsba);
1072  		dump_fmba(fmba);
1073  		dump_fmsba(fmsba);
1074  	} else {
1075  		printf("FD is corrupted!\n");
1076  	}
1077  }
1078  
1079  /* Takes an image containing an IFD and creates a Flashmap .fmd file template.
1080   * This flashmap will contain all IFD regions except the BIOS region.
1081   * The BIOS region is created by coreboot itself and 'should' match the IFD region
1082   * anyway (CONFIG_VALIDATE_INTEL_DESCRIPTOR should make sure). coreboot built system will use
1083   * this template to generate the final Flashmap file.
1084   */
1085  static void create_fmap_template(char *image, int size, const char *layout_fname)
1086  {
1087  	const struct frba *frba = find_frba(image, size);
1088  	if (!frba)
1089  		exit(EXIT_FAILURE);
1090  
1091  	int layout_fd = open(layout_fname, O_WRONLY | O_CREAT | O_TRUNC, 0644);
1092  	if (layout_fd == -1) {
1093  		perror("Could not open file");
1094  		exit(EXIT_FAILURE);
1095  	}
1096  
1097  	char *bbuf = "FLASH@##ROM_BASE## ##ROM_SIZE## {\n";
1098  	if (write(layout_fd, bbuf, strlen(bbuf)) < 0) {
1099  		perror("Could not write to file");
1100  		exit(EXIT_FAILURE);
1101  	}
1102  
1103  	/* fmaptool requires regions in .fmd to be sorted.
1104  	 * => We need to sort the regions by base address before writing them in .fmd File
1105  	 */
1106  	int count_regions = 0;
1107  	struct region sorted_regions[MAX_REGIONS] = { 0 };
1108  	for (unsigned int i = 0; i < max_regions; i++) {
1109  		struct region region = get_region(frba, i);
1110  
1111  		/* A region limit of 0 is an indicator of an unused region
1112  		 * A region base of 7FFFh is an indicator of a reserved region
1113  		 */
1114  		if (region.limit == 0 || region.base == 0x07FFF000)
1115  			continue;
1116  
1117  		/* Is there an FMAP equivalent? IFD reserved regions are usually thrown out
1118  		 * of the FMAP here
1119  		 */
1120  		if (!region_names[region.type].fmapname) {
1121  			printf("Skip IFD region: %s\n", region_names[region.type].pretty);
1122  			continue;
1123  		}
1124  
1125  		/* Here we decide to use the coreboot generated FMAP BIOS region, instead of
1126  		 * the one specified in the IFD. The case when IFD and FMAP BIOS region do not
1127  		 * match cannot be caught here, therefore one should still validate IFD and
1128  		 * FMAP via CONFIG_VALIDATE_INTEL_DESCRIPTOR
1129  		 */
1130  		if (i == REGION_BIOS)
1131  			continue;
1132  
1133  		sorted_regions[count_regions] = region;
1134  		// basically insertion sort
1135  		for (int i = count_regions - 1; i >= 0; i--) {
1136  			if (sorted_regions[i].base > sorted_regions[i + 1].base) {
1137  				struct region tmp = sorted_regions[i];
1138  				sorted_regions[i] = sorted_regions[i + 1];
1139  				sorted_regions[i + 1] = tmp;
1140  			}
1141  		}
1142  		count_regions++;
1143  	}
1144  
1145  	// Now write regions sorted by base address in the fmap file
1146  	for (int i = 0; i < count_regions; i++) {
1147  		struct region region = sorted_regions[i];
1148  		char buf[LAYOUT_LINELEN];
1149  		snprintf(buf, LAYOUT_LINELEN, "\t%s@0x%X 0x%X\n", region_names[region.type].fmapname, region.base, region.size);
1150  		if (write(layout_fd, buf, strlen(buf)) < 0) {
1151  			perror("Could not write to file");
1152  			exit(EXIT_FAILURE);
1153  		}
1154  	}
1155  
1156  	char *ebuf = "\tSI_BIOS@##BIOS_BASE## ##BIOS_SIZE## {\n"
1157  		     "\t\t##CONSOLE_ENTRY##\n"
1158  		     "\t\t##MRC_CACHE_ENTRY##\n"
1159  		     "\t\t##SMMSTORE_ENTRY##\n"
1160  		     "\t\t##SPD_CACHE_ENTRY##\n"
1161  		     "\t\t##VPD_ENTRY##\n"
1162  		     "\t\tFMAP@##FMAP_BASE## ##FMAP_SIZE##\n"
1163  		     "\t\tCOREBOOT(CBFS)@##CBFS_BASE## ##CBFS_SIZE##\n"
1164  		     "\t}\n"
1165  		     "}\n";
1166  	if (write(layout_fd, ebuf, strlen(ebuf)) < 0) {
1167  		perror("Could not write to file");
1168  		exit(EXIT_FAILURE);
1169  	}
1170  
1171  	close(layout_fd);
1172  	printf("Wrote layout to %s\n", layout_fname);
1173  }
1174  
1175  static void write_regions(char *image, int size)
1176  {
1177  	unsigned int i;
1178  	const struct frba *frba = find_frba(image, size);
1179  
1180  	if (!frba)
1181  		exit(EXIT_FAILURE);
1182  
1183  	for (i = 0; i < max_regions; i++) {
1184  		struct region region = get_region(frba, i);
1185  		dump_region(i, frba);
1186  		if (region.size > 0) {
1187  			int region_fd;
1188  			region_fd = open(region_names[i].filename,
1189  					 O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
1190  					 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
1191  			if (region_fd < 0) {
1192  				perror("Error while trying to open file");
1193  				exit(EXIT_FAILURE);
1194  			}
1195  			if (write(region_fd, image + region.base, region.size) != region.size)
1196  				perror("Error while writing");
1197  			close(region_fd);
1198  		}
1199  	}
1200  }
1201  
1202  static void validate_layout(char *image, int size)
1203  {
1204  	uint i, errors = 0;
1205  	struct fmap *fmap;
1206  	long int fmap_loc = fmap_find((uint8_t *)image, size);
1207  	const struct frba *frba = find_frba(image, size);
1208  
1209  	if (fmap_loc < 0 || !frba) {
1210  		printf("Could not find FMAP (%p) or Intel Flash Descriptor (%p)\n",
1211  			(void *)fmap_loc, frba);
1212  		exit(EXIT_FAILURE);
1213  	}
1214  
1215  	fmap = (struct fmap *)(image + fmap_loc);
1216  
1217  	int matches = 0;
1218  	for (i = 0; i < max_regions; i++) {
1219  		struct region region = get_region(frba, i);
1220  		if (region.size == 0)
1221  			continue;
1222  
1223  		const struct fmap_area *area = fmap_find_area(fmap, region_names[i].fmapname);
1224  		if (!area)
1225  			continue;
1226  
1227  		matches++; // found a match between FMAP and IFD region
1228  
1229  		if ((uint)region.base != area->offset || (uint)region.size != area->size) {
1230  			if (i == REGION_BIOS) {
1231  				/*
1232  				 * BIOS FMAP region is a special case
1233  				 * coreboots FMAP BIOS region depends on the CONFIG_CBFS_SIZE
1234  				 * while the IFD BIOS region is always of static size.
1235  				 * Therefore we just make sure that the BIOS region of the FMAP
1236  				 * is inside the region specified by the IFD
1237  				 */
1238  				if ((uint)region.base <= area->offset &&
1239  				   ((uint)region.base + region.size) >= (area->offset + area->size)) {
1240  					continue;
1241  				}
1242  			}
1243  			printf("Region mismatch between %s and %s\n", region_names[i].terse, area->name);
1244  			printf(" Descriptor region %s:\n", region_names[i].terse);
1245  			printf("  offset: 0x%08x\n", region.base);
1246  			printf("  length: 0x%08x\n", region.size);
1247  			printf(" FMAP area %s:\n", area->name);
1248  			printf("  offset: 0x%08x\n", area->offset);
1249  			printf("  length: 0x%08x\n", area->size);
1250  			errors++;
1251  		}
1252  	}
1253  
1254  	if (!matches) {
1255  		// At least a BIOS region should be present in both IFD and FMAP
1256  		fprintf(stderr, "Warning: Not a single IFD region found in FMAP\n");
1257  	}
1258  
1259  	if (errors > 0)
1260  		exit(EXIT_FAILURE);
1261  }
1262  
1263  static void write_image(const char *filename, char *image, int size)
1264  {
1265  	int new_fd;
1266  	printf("Writing new image to %s\n", filename);
1267  
1268  	// Now write out new image
1269  	new_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
1270  	if (new_fd < 0) {
1271  		perror("Error while trying to open file");
1272  		exit(EXIT_FAILURE);
1273  	}
1274  	if (write(new_fd, image, size) != size)
1275  		perror("Error while writing");
1276  	close(new_fd);
1277  }
1278  
1279  static void set_spi_frequency(const char *filename, char *image, int size,
1280  			      enum spi_frequency freq)
1281  {
1282  	struct fcba *fcba = find_fcba(image, size);
1283  	if (!fcba)
1284  		exit(EXIT_FAILURE);
1285  
1286  	/* clear bits 21-29 */
1287  	fcba->flcomp &= ~0x3fe00000;
1288  	/* Read ID and Read Status Clock Frequency */
1289  	fcba->flcomp |= freq << 27;
1290  	/* Write and Erase Clock Frequency */
1291  	fcba->flcomp |= freq << 24;
1292  	/* Fast Read Clock Frequency */
1293  	fcba->flcomp |= freq << 21;
1294  
1295  	write_image(filename, image, size);
1296  }
1297  
1298  static void set_em100_mode(const char *filename, char *image, int size)
1299  {
1300  	struct fcba *fcba = find_fcba(image, size);
1301  	if (!fcba)
1302  		exit(EXIT_FAILURE);
1303  
1304  	int freq;
1305  
1306  	switch (ifd_version) {
1307  	case IFD_VERSION_1:
1308  	case IFD_VERSION_1_5:
1309  		freq = SPI_FREQUENCY_20MHZ;
1310  		break;
1311  	case IFD_VERSION_2:
1312  		freq = SPI_FREQUENCY_17MHZ;
1313  		break;
1314  	default:
1315  		freq = SPI_FREQUENCY_17MHZ;
1316  		break;
1317  	}
1318  
1319  	fcba->flcomp &= ~(1 << 30);
1320  	set_spi_frequency(filename, image, size, freq);
1321  }
1322  
1323  static void set_chipdensity(const char *filename, char *image, int size,
1324  			    unsigned int density)
1325  {
1326  	struct fcba *fcba = find_fcba(image, size);
1327  	uint8_t mask, chip2_offset;
1328  	if (!fcba)
1329  		exit(EXIT_FAILURE);
1330  
1331  	printf("Setting chip density to ");
1332  	decode_component_density(density);
1333  	printf("\n");
1334  
1335  	switch (ifd_version) {
1336  	case IFD_VERSION_1:
1337  		/* fail if selected density is not supported by this version */
1338  		if ( (density == COMPONENT_DENSITY_32MB) ||
1339  		     (density == COMPONENT_DENSITY_64MB) ||
1340  		     (density == COMPONENT_DENSITY_UNUSED) ) {
1341  			printf("error: Selected density not supported in IFD version 1.\n");
1342  			exit(EXIT_FAILURE);
1343  		}
1344  		mask = 0x7;
1345  		chip2_offset = 3;
1346  		break;
1347  	case IFD_VERSION_1_5:
1348  	case IFD_VERSION_2:
1349  		mask = 0xf;
1350  		chip2_offset = 4;
1351  		break;
1352  	default:
1353  		printf("error: Unknown IFD version\n");
1354  		exit(EXIT_FAILURE);
1355  		break;
1356  	}
1357  
1358  	/* clear chip density for corresponding chip */
1359  	switch (selected_chip) {
1360  	case 1:
1361  		fcba->flcomp &= ~mask;
1362  		break;
1363  	case 2:
1364  		fcba->flcomp &= ~(mask << chip2_offset);
1365  		break;
1366  	default: /*both chips*/
1367  		fcba->flcomp &= ~(mask | (mask << chip2_offset));
1368  		break;
1369  	}
1370  
1371  	/* set the new density */
1372  	if (selected_chip == 1 || selected_chip == 0)
1373  		fcba->flcomp |= (density); /* first chip */
1374  	if (selected_chip == 2 || selected_chip == 0)
1375  		fcba->flcomp |= (density << chip2_offset); /* second chip */
1376  
1377  	write_image(filename, image, size);
1378  }
1379  
1380  static int check_region(const struct frba *frba, unsigned int region_type)
1381  {
1382  	struct region region;
1383  
1384  	if (!frba)
1385  		return 0;
1386  
1387  	region = get_region(frba, region_type);
1388  	return !!((region.base < region.limit) && (region.size > 0));
1389  }
1390  
1391  /*
1392   * Platforms from CNL onwards support up to 16 flash regions, not 12. The
1393   * permissions for regions [15:12] are stored in extended region read/write
1394   * access fields in the FLMSTR registers.
1395   *
1396   * FLMSTR with extended regions:
1397   *   31:20 Region Write Access
1398   *   19:8  Region Read Access
1399   *    7:4  Extended Region Write Access
1400   *    3:0  Extended Region Read Access
1401   *
1402   * FLMSTR without extended regions:
1403   *   31:20 Region Write Access
1404   *   19:8  Region Read Access
1405   *    7:0  Reserved
1406   */
1407  static bool platform_has_extended_regions(void)
1408  {
1409  	switch (platform) {
1410  	case PLATFORM_CNL:
1411  	case PLATFORM_JSL:
1412  	case PLATFORM_TGL:
1413  	case PLATFORM_ADL:
1414  	case PLATFORM_MTL:
1415  	case PLATFORM_PTL:
1416  		return true;
1417  	default:
1418  		return false;
1419  	}
1420  }
1421  
1422  static void lock_descriptor(const char *filename, char *image, int size)
1423  {
1424  	int wr_shift, rd_shift;
1425  	struct fmba *fmba = find_fmba(image, size);
1426  	const struct frba *frba = find_frba(image, size);
1427  	if (!fmba)
1428  		exit(EXIT_FAILURE);
1429  
1430  	if (ifd_version >= IFD_VERSION_2) {
1431  		wr_shift = FLMSTR_WR_SHIFT_V2;
1432  		rd_shift = FLMSTR_RD_SHIFT_V2;
1433  
1434  		/*
1435  		 * Clear all read/write access bits. See comment on
1436  		 * platform_has_extended_regions() for bitfields.
1437  		 */
1438  		if (platform_has_extended_regions()) {
1439  			fmba->flmstr1 = 0;
1440  			fmba->flmstr2 = 0;
1441  			fmba->flmstr3 = 0;
1442  			fmba->flmstr5 = 0;
1443  		} else {
1444  			fmba->flmstr1 &= 0xff;
1445  			fmba->flmstr2 &= 0xff;
1446  			fmba->flmstr3 &= 0xff;
1447  			fmba->flmstr5 &= 0xff;
1448  		}
1449  	} else {
1450  		wr_shift = FLMSTR_WR_SHIFT_V1;
1451  		rd_shift = FLMSTR_RD_SHIFT_V1;
1452  
1453  		fmba->flmstr1 = 0;
1454  		fmba->flmstr2 = 0;
1455  		/* Requestor ID */
1456  		fmba->flmstr3 = 0x118;
1457  	}
1458  
1459  	switch (platform) {
1460  	case PLATFORM_APL:
1461  	case PLATFORM_GLK:
1462  		/* CPU/BIOS can read descriptor and BIOS */
1463  		fmba->flmstr1 |= 0x3 << rd_shift;
1464  		/* CPU/BIOS can write BIOS */
1465  		fmba->flmstr1 |= 0x2 << wr_shift;
1466  		/* TXE can read descriptor, BIOS and Device Expansion */
1467  		fmba->flmstr2 |= 0x23 << rd_shift;
1468  		/* TXE can only write Device Expansion */
1469  		fmba->flmstr2 |= 0x20 << wr_shift;
1470  		break;
1471  	case PLATFORM_CNL:
1472  	case PLATFORM_ICL:
1473  	case PLATFORM_SKLKBL:
1474  	case PLATFORM_TGL:
1475  	case PLATFORM_JSL:
1476  	case PLATFORM_EHL:
1477  	case PLATFORM_ADL:
1478  	case PLATFORM_IFD2:
1479  	case PLATFORM_MTL:
1480  	case PLATFORM_PTL:
1481  		/* CPU/BIOS can read descriptor and BIOS. */
1482  		fmba->flmstr1 |= (1 << REGION_DESC) << rd_shift;
1483  		fmba->flmstr1 |= (1 << REGION_BIOS) << rd_shift;
1484  		/* CPU/BIOS can write BIOS. */
1485  		fmba->flmstr1 |= (1 << REGION_BIOS) << wr_shift;
1486  		/* ME can read descriptor and ME. */
1487  		fmba->flmstr2 |= (1 << REGION_DESC) << rd_shift;
1488  		fmba->flmstr2 |= (1 << REGION_ME) << rd_shift;
1489  		/* ME can write ME. */
1490  		fmba->flmstr2 |= (1 << REGION_ME) << wr_shift;
1491  		if (check_region(frba, REGION_GBE)) {
1492  			/* BIOS can read/write GbE. */
1493  			fmba->flmstr1 |= (1 << REGION_GBE) << rd_shift;
1494  			fmba->flmstr1 |= (1 << REGION_GBE) << wr_shift;
1495  			/* ME can read GbE. */
1496  			fmba->flmstr2 |= (1 << REGION_GBE) << rd_shift;
1497  			/* GbE can read descriptor and read/write GbE.. */
1498  			fmba->flmstr3 |= (1 << REGION_DESC) << rd_shift;
1499  			fmba->flmstr3 |= (1 << REGION_GBE) << rd_shift;
1500  			fmba->flmstr3 |= (1 << REGION_GBE) << wr_shift;
1501  		}
1502  		if (check_region(frba, REGION_PDR)) {
1503  			/* BIOS can read/write PDR. */
1504  			fmba->flmstr1 |= (1 << REGION_PDR) << rd_shift;
1505  			fmba->flmstr1 |= (1 << REGION_PDR) << wr_shift;
1506  		}
1507  		if (check_region(frba, REGION_EC)) {
1508  			/* BIOS can read EC. */
1509  			fmba->flmstr1 |= (1 << REGION_EC) << rd_shift;
1510  			/* EC can read descriptor and read/write EC. */
1511  			fmba->flmstr5 |= (1 << REGION_DESC) << rd_shift;
1512  			fmba->flmstr5 |= (1 << REGION_EC) << rd_shift;
1513  			fmba->flmstr5 |= (1 << REGION_EC) << wr_shift;
1514  		}
1515  		if (check_region(frba, REGION_DEV_EXP2)) {
1516  			/* BIOS can read SPI device expansion 2 region. */
1517  			fmba->flmstr1 |= (1 << REGION_DEV_EXP2) << rd_shift;
1518  		}
1519  		break;
1520  	case PLATFORM_DNV:
1521  	case PLATFORM_WBG:
1522  		/* CPU/BIOS can read descriptor and BIOS. */
1523  		fmba->flmstr1 |= (1 << REGION_DESC) << rd_shift;
1524  		fmba->flmstr1 |= (1 << REGION_BIOS) << rd_shift;
1525  		/* CPU/BIOS can write BIOS. */
1526  		fmba->flmstr1 |= (1 << REGION_BIOS) << wr_shift;
1527  		/* ME can read descriptor and ME. */
1528  		fmba->flmstr2 |= (1 << REGION_DESC) << rd_shift;
1529  		fmba->flmstr2 |= (1 << REGION_ME) << rd_shift;
1530  		/* ME can write ME. */
1531  		fmba->flmstr2 |= (1 << REGION_ME) << wr_shift;
1532  		break;
1533  	default:
1534  		/* CPU/BIOS can read descriptor and BIOS. */
1535  		fmba->flmstr1 |= (1 << REGION_DESC) << rd_shift;
1536  		fmba->flmstr1 |= (1 << REGION_BIOS) << rd_shift;
1537  		/* CPU/BIOS can write BIOS. */
1538  		fmba->flmstr1 |= (1 << REGION_BIOS) << wr_shift;
1539  		/* ME can read descriptor and ME. */
1540  		fmba->flmstr2 |= (1 << REGION_DESC) << rd_shift;
1541  		fmba->flmstr2 |= (1 << REGION_ME) << rd_shift;
1542  		/* ME can write ME. */
1543  		fmba->flmstr2 |= (1 << REGION_ME) << wr_shift;
1544  		if (check_region(frba, REGION_GBE)) {
1545  			/* BIOS can read GbE. */
1546  			fmba->flmstr1 |= (1 << REGION_GBE) << rd_shift;
1547  			/* BIOS can write GbE. */
1548  			fmba->flmstr1 |= (1 << REGION_GBE) << wr_shift;
1549  			/* ME can read GbE. */
1550  			fmba->flmstr2 |= (1 << REGION_GBE) << rd_shift;
1551  			/* ME can write GbE. */
1552  			fmba->flmstr2 |= (1 << REGION_GBE) << wr_shift;
1553  			/* GbE can write GbE. */
1554  			fmba->flmstr3 |= (1 << REGION_GBE) << rd_shift;
1555  			/* GbE can read GbE. */
1556  			fmba->flmstr3 |= (1 << REGION_GBE) << wr_shift;
1557  		}
1558  		break;
1559  	}
1560  
1561  	write_image(filename, image, size);
1562  }
1563  
1564  static void enable_cpu_read_me(const char *filename, char *image, int size)
1565  {
1566  	int rd_shift;
1567  	struct fmba *fmba = find_fmba(image, size);
1568  
1569  	if (!fmba)
1570  		exit(EXIT_FAILURE);
1571  
1572  	if (ifd_version >= IFD_VERSION_2)
1573  		rd_shift = FLMSTR_RD_SHIFT_V2;
1574  	else
1575  		rd_shift = FLMSTR_RD_SHIFT_V1;
1576  
1577  	/* CPU/BIOS can read ME. */
1578  	fmba->flmstr1 |= (1 << REGION_ME) << rd_shift;
1579  
1580  	write_image(filename, image, size);
1581  }
1582  
1583  static void unlock_descriptor(const char *filename, char *image, int size)
1584  {
1585  	struct fmba *fmba = find_fmba(image, size);
1586  	if (!fmba)
1587  		exit(EXIT_FAILURE);
1588  
1589  	if (ifd_version >= IFD_VERSION_2) {
1590  		/*
1591  		 * Set all read/write access bits. See comment on
1592  		 * platform_has_extended_regions() for bitfields.
1593  		 */
1594  		if (platform_has_extended_regions()) {
1595  			fmba->flmstr1 = 0xffffffff;
1596  			fmba->flmstr2 = 0xffffffff;
1597  			fmba->flmstr3 = 0xffffffff;
1598  			fmba->flmstr5 = 0xffffffff;
1599  		} else {
1600  			fmba->flmstr1 = 0xffffff00 | (fmba->flmstr1 & 0xff);
1601  			fmba->flmstr2 = 0xffffff00 | (fmba->flmstr2 & 0xff);
1602  			fmba->flmstr3 = 0xffffff00 | (fmba->flmstr3 & 0xff);
1603  			fmba->flmstr5 = 0xffffff00 | (fmba->flmstr5 & 0xff);
1604  		}
1605  	} else {
1606  		fmba->flmstr1 = 0xffff0000;
1607  		fmba->flmstr2 = 0xffff0000;
1608  		/* Keep chipset specific Requester ID */
1609  		fmba->flmstr3 = 0x08080000 | (fmba->flmstr3 & 0xffff);
1610  	}
1611  
1612  	write_image(filename, image, size);
1613  }
1614  
1615  static void print_gpr0_range(union gprd reg)
1616  {
1617  	printf("--------- GPR0 Protected Range --------------\n");
1618  	printf("Start address = 0x%08x\n", reg.data.start << 12);
1619  	printf("End address = 0x%08x\n", (reg.data.end << 12) | 0xfff);
1620  }
1621  
1622  static uint8_t get_cse_data_partition_offset(void)
1623  {
1624  	uint8_t data_offset = 0xff;
1625  
1626  	switch (platform) {
1627  	case PLATFORM_CNL:
1628  	case PLATFORM_JSL:
1629  		data_offset = 0x10;
1630  		break;
1631  	case PLATFORM_TGL:
1632  	case PLATFORM_ADL:
1633  	case PLATFORM_MTL:
1634  	case PLATFORM_PTL:
1635  		data_offset = 0x18;
1636  		break;
1637  	default:
1638  		break;
1639  	}
1640  
1641  	return data_offset;
1642  }
1643  
1644  static uint32_t get_gpr0_offset(void)
1645  {
1646  	/* Offset expressed as number of 32-bit fields from FPSBA */
1647  	uint32_t gpr0_offset = 0xffffffff;
1648  
1649  	switch (platform) {
1650  	case PLATFORM_CNL:
1651  		gpr0_offset = 0x10;
1652  		break;
1653  	case PLATFORM_JSL:
1654  		gpr0_offset = 0x12;
1655  		break;
1656  	case PLATFORM_TGL:
1657  	case PLATFORM_ADL:
1658  		gpr0_offset = 0x15;
1659  		break;
1660  	case PLATFORM_MTL:
1661  		gpr0_offset = 0x40;
1662  		break;
1663  	case PLATFORM_PTL:
1664  		gpr0_offset = 0x76;
1665  		break;
1666  	default:
1667  		break;
1668  	}
1669  
1670  	return gpr0_offset;
1671  }
1672  
1673  static void disable_gpr0(const char *filename, char *image, int size)
1674  {
1675  	struct fpsba *fpsba = find_fpsba(image, size);
1676  	if (!fpsba)
1677  		exit(EXIT_FAILURE);
1678  
1679  	uint32_t gpr0_offset = get_gpr0_offset();
1680  	if (gpr0_offset == 0xffffffff) {
1681  		fprintf(stderr, "Disabling GPR0 not supported on this platform\n");
1682  		exit(EXIT_FAILURE);
1683  	}
1684  
1685  	union gprd reg;
1686  	/* If bit 31 is set then GPR0 protection is enable */
1687  	reg.value = fpsba->pchstrp[gpr0_offset];
1688  	if (!reg.data.write_protect_en) {
1689  		printf("GPR0 protection is already disabled\n");
1690  		return;
1691  	}
1692  
1693  	printf("Value at GPRD offset (%d) is 0x%08x\n", gpr0_offset, reg.value);
1694  	print_gpr0_range(reg);
1695  	/* 0 means GPR0 protection is disabled */
1696  	fpsba->pchstrp[gpr0_offset] = 0;
1697  	write_image(filename, image, size);
1698  	printf("GPR0 protection is now disabled\n");
1699  }
1700  
1701  /*
1702   * Helper function to parse the FPT to retrieve the FITC start offset and size.
1703   * FITC is a sub-partition table inside CSE data partition known as FPT.
1704   *
1705   * CSE Region
1706   *   |-----> CSE Data Partition Offset
1707   *   |              |------->  FPT Entry
1708   *   |              |              |-> Sub Partition 1
1709   *   |              |              |-> Sub Partition 2
1710   *   |              |              |-> FITC
1711   *   |              |              |     | -> FITC Offset
1712   *   |              |              |     | -> FITC Length
1713   */
1714  static int parse_fitc_table(struct cse_fpt *fpt, uint32_t *offset,
1715  		 size_t *size)
1716  {
1717  	size_t num_part_header = fpt->count;
1718  	/* Move to the next structure which is FPT sub-partition entries */
1719  	struct cse_fpt_sub_part *fpt_sub_part = (struct cse_fpt_sub_part *)(fpt + 1);
1720  	for (size_t index = 0; index < num_part_header; index++) {
1721  		if (!strncmp(fpt_sub_part->signature, "FITC", 4)) {
1722  			*offset = fpt_sub_part->offset;
1723  			*size = fpt_sub_part->length;
1724  			return 0;
1725  		}
1726  		fpt_sub_part++;
1727  	}
1728  
1729  	return -1;
1730  }
1731  
1732  /*
1733   * Formula to calculate the GPR0 protection range as below:
1734   * Start: CSE Region Base Offset
1735   * End: Till the end of FITC sub-partition
1736   */
1737  static int calculate_gpr0_range(char *image, int size,
1738  		 uint32_t *gpr0_start, uint32_t *gpr0_end)
1739  {
1740  	struct frba *frba = find_frba(image, size);
1741  	if (!frba)
1742  		return -1;
1743  
1744  	struct region region = get_region(frba, REGION_ME);
1745  	if (region.size <= 0) {
1746  		fprintf(stderr, "Region %s is disabled in target\n",
1747  				region_name(REGION_ME));
1748  		return -1;
1749  	}
1750  
1751  	/* CSE Region Start */
1752  	uint32_t cse_region_start = region.base;
1753  	/* Get CSE Data Partition Offset */
1754  	uint8_t cse_data_offset = get_cse_data_partition_offset();
1755  	if (cse_data_offset == 0xff) {
1756  		fprintf(stderr, "Unsupported platform\n");
1757  		exit(EXIT_FAILURE);
1758  	}
1759  	const uint32_t *data_part_offset_ptr = (uint32_t *)(image + cse_region_start +
1760  							    cse_data_offset);
1761  	if (!PTR_IN_RANGE(data_part_offset_ptr, image, size)) {
1762  		fprintf(stderr, "Data part offset %d exceeds image size %d\n",
1763  			cse_region_start + cse_data_offset, size);
1764  		return -1;
1765  	}
1766  	uint32_t data_part_offset = *data_part_offset_ptr;
1767  
1768  	/* Start reading the CSE Data Partition Table, also known as FPT */
1769  	uint32_t data_part_start = data_part_offset + cse_region_start;
1770  	struct cse_fpt *fpt = (struct cse_fpt *)(image + data_part_start);
1771  	if (!PTR_IN_RANGE(fpt, image, size)) {
1772  		fprintf(stderr, "FPT offset %d exceeds image size %d\n",
1773  			data_part_start, size);
1774  		return -1;
1775  	}
1776  
1777  	uint32_t fitc_region_start = 0;
1778  	size_t fitc_region_size = 0;
1779  	/*
1780  	 * FPT holds entry for own FPT data structure also bunch of sub-partitions.
1781  	 * `FITC` is one of such sub-partition entry.
1782  	 */
1783  	if (parse_fitc_table(fpt, &fitc_region_start, &fitc_region_size) < 0) {
1784  		fprintf(stderr, "Unable to find FITC entry\n");
1785  		return -1;
1786  	}
1787  
1788  	/*
1789  	 * GPR0 protection is configured to the following range:
1790  	 * start: CSE region base offset
1791  	 * end: Till the end of FITC sub-partition (i.e. CSE region + data partition offset +
1792  	 *       FITC sub partition offset + FITC sub partition size)
1793  	 */
1794  	*gpr0_start = cse_region_start;
1795  	*gpr0_end = (cse_region_start + data_part_offset +
1796  				 fitc_region_start + fitc_region_size) - 1;
1797  
1798  	return 0;
1799  }
1800  
1801  static union gprd get_enabled_gprd(char *image, int size)
1802  {
1803  	union gprd enabled_gprd_reg;
1804  	uint32_t gpr0_range_start, gpr0_range_end;
1805  	enabled_gprd_reg.value = 0;
1806  	if (calculate_gpr0_range(image, size, &gpr0_range_start, &gpr0_range_end))
1807  		exit(EXIT_FAILURE);
1808  
1809  	enabled_gprd_reg.data.start = (gpr0_range_start >> 12) & 0x7fff;
1810  	enabled_gprd_reg.data.end = (gpr0_range_end >> 12) & 0x7fff;
1811  	enabled_gprd_reg.data.read_protect_en = 0;
1812  	enabled_gprd_reg.data.write_protect_en = 1;
1813  
1814  	return enabled_gprd_reg;
1815  }
1816  
1817  static void enable_gpr0(const char *filename, char *image, int size)
1818  {
1819  	struct fpsba *fpsba = find_fpsba(image, size);
1820  	if (!fpsba)
1821  		exit(EXIT_FAILURE);
1822  
1823  	uint32_t gpr0_offset = get_gpr0_offset();
1824  	if (gpr0_offset == 0xffffffff) {
1825  		fprintf(stderr, "Enabling GPR0 not supported on this platform\n");
1826  		exit(EXIT_FAILURE);
1827  	}
1828  
1829  	union gprd reg;
1830  	/* If bit 31 is set then GPR0 protection is enable */
1831  	reg.value = fpsba->pchstrp[gpr0_offset];
1832  	if (reg.data.write_protect_en) {
1833  		printf("GPR0 protection is already enabled\n");
1834  		print_gpr0_range(reg);
1835  		return;
1836  	}
1837  
1838  	union gprd enabled_gprd = get_enabled_gprd(image, size);
1839  
1840  	fpsba->pchstrp[gpr0_offset] = enabled_gprd.value;
1841  	printf("Value at GPRD offset (%d) is 0x%08x\n", gpr0_offset, enabled_gprd.value);
1842  	print_gpr0_range(enabled_gprd);
1843  	write_image(filename, image, size);
1844  	printf("GPR0 protection is now enabled\n");
1845  }
1846  
1847  static void is_gpr0_protected(char *image, int size)
1848  {
1849  	struct fpsba *fpsba = find_fpsba(image, size);
1850  	if (!fpsba)
1851  		exit(EXIT_FAILURE);
1852  
1853  	uint32_t gpr0_offset = get_gpr0_offset();
1854  	if (gpr0_offset == 0xffffffff) {
1855  		fprintf(stderr, "Checking GPR0 not supported on this platform\n");
1856  		exit(EXIT_FAILURE);
1857  	}
1858  	union gprd reg;
1859  	union gprd enabled_gprd = get_enabled_gprd(image, size);
1860  	reg.value = fpsba->pchstrp[gpr0_offset];
1861  
1862  	if (fpsba->pchstrp[gpr0_offset] == enabled_gprd.value)
1863  		printf("GPR0 status: Enabled\n\n");
1864  	else if (fpsba->pchstrp[gpr0_offset] == 0)
1865  		printf("GPR0 status: Disabled\n\n");
1866  	else
1867  		printf("ERROR: GPR0 setting is not expected\n\n");
1868  
1869  	printf("Value at GPRD offset (%d) is 0x%08x\n", gpr0_offset, fpsba->pchstrp[gpr0_offset]);
1870  	print_gpr0_range(reg);
1871  }
1872  
1873  static void set_pchstrap(struct fpsba *fpsba, const struct fdbar *fdb, const int strap,
1874  			const unsigned int value)
1875  {
1876  	if (!fpsba || !fdb) {
1877  		fprintf(stderr, "Internal error\n");
1878  		exit(EXIT_FAILURE);
1879  	}
1880  
1881  	/* SoC Strap, aka PSL, aka ISL */
1882  	int SS = (fdb->flmap1 >> 24) & 0xff;
1883  	if (strap >= SS) {
1884  		fprintf(stderr, "Strap index %d out of range (max: %d)\n", strap, SS);
1885  		exit(EXIT_FAILURE);
1886  	}
1887  	fpsba->pchstrp[strap] = value;
1888  }
1889  
1890  /* Set the AltMeDisable (or HAP for >= IFD_VERSION_2) */
1891  static void fpsba_set_altmedisable(struct fpsba *fpsba, struct fmsba *fmsba, bool altmedisable)
1892  {
1893  	if (ifd_version >= IFD_VERSION_2) {
1894  		printf("%sting the HAP bit to %s Intel ME...\n",
1895  			altmedisable ? "Set" : "Unset",
1896  			altmedisable ? "disable" : "enable");
1897  		if (altmedisable)
1898  			fpsba->pchstrp[0] |= (1 << 16);
1899  		else
1900  			fpsba->pchstrp[0] &= ~(1 << 16);
1901  	} else {
1902  		if (chipset >= CHIPSET_ICH8 && chipset <= CHIPSET_ICH10) {
1903  			printf("%sting the ICH_MeDisable, MCH_MeDisable, "
1904  			       "and MCH_AltMeDisable to %s Intel ME...\n",
1905  			       altmedisable ? "Set" : "Unset",
1906  			       altmedisable ? "disable" : "enable");
1907  			if (altmedisable) {
1908  				/* MCH_MeDisable */
1909  				fmsba->data[0] |= 1;
1910  				/* MCH_AltMeDisable */
1911  				fmsba->data[0] |= (1 << 7);
1912  				/* ICH_MeDisable */
1913  				fpsba->pchstrp[0] |= 1;
1914  			} else {
1915  				fmsba->data[0] &= ~1;
1916  				fmsba->data[0] &= ~(1 << 7);
1917  				fpsba->pchstrp[0] &= ~1;
1918  			}
1919  		} else {
1920  			printf("%sting the AltMeDisable to %s Intel ME...\n",
1921  				altmedisable ? "Set" : "Unset",
1922  				altmedisable ? "disable" : "enable");
1923  			if (altmedisable)
1924  				fpsba->pchstrp[10] |= (1 << 7);
1925  			else
1926  				fpsba->pchstrp[10] &= ~(1 << 7);
1927  		}
1928  	}
1929  }
1930  
1931  static void inject_region(const char *filename, char *image, int size,
1932  			  unsigned int region_type, const char *region_fname)
1933  {
1934  	struct frba *frba = find_frba(image, size);
1935  	if (!frba)
1936  		exit(EXIT_FAILURE);
1937  
1938  	struct region region = get_region(frba, region_type);
1939  	if (region.size <= 0xfff) {
1940  		fprintf(stderr, "Region %s is disabled in target. Not injecting.\n",
1941  				region_name(region_type));
1942  		exit(EXIT_FAILURE);
1943  	}
1944  
1945  	int region_fd = open(region_fname, O_RDONLY | O_BINARY);
1946  	if (region_fd == -1) {
1947  		perror("Could not open file");
1948  		exit(EXIT_FAILURE);
1949  	}
1950  	struct stat buf;
1951  	if (fstat(region_fd, &buf) == -1) {
1952  		perror("Could not stat file");
1953  		exit(EXIT_FAILURE);
1954  	}
1955  	int region_size = buf.st_size;
1956  
1957  	printf("File %s is %d bytes\n", region_fname, region_size);
1958  
1959  	if (region_size > region.size) {
1960  		fprintf(stderr, "Region %s is %d(0x%x) bytes. File is %d(0x%x)"
1961  				" bytes. Not injecting.\n",
1962  				region_name(region_type), region.size,
1963  				region.size, region_size, region_size);
1964  		exit(EXIT_FAILURE);
1965  	}
1966  
1967  	int offset = 0;
1968  	if ((region_type == 1) && (region_size < region.size)) {
1969  		fprintf(stderr, "Region %s is %d(0x%x) bytes. File is %d(0x%x)"
1970  				" bytes. Padding before injecting.\n",
1971  				region_name(region_type), region.size,
1972  				region.size, region_size, region_size);
1973  		offset = region.size - region_size;
1974  		memset(image + region.base, 0xff, offset);
1975  	}
1976  
1977  	if (size < region.base + offset + region_size) {
1978  		fprintf(stderr, "Output file is too small. (%d < %d)\n",
1979  			size, region.base + offset + region_size);
1980  		exit(EXIT_FAILURE);
1981  	}
1982  
1983  	if (read(region_fd, image + region.base + offset, region_size) != region_size) {
1984  		perror("Could not read file");
1985  		exit(EXIT_FAILURE);
1986  	}
1987  
1988  	close(region_fd);
1989  
1990  	printf("Adding %s as the %s section of %s\n",
1991  	       region_fname, region_name(region_type), filename);
1992  	write_image(filename, image, size);
1993  }
1994  
1995  static unsigned int next_pow2(unsigned int x)
1996  {
1997  	unsigned int y = 1;
1998  	if (x == 0)
1999  		return 0;
2000  	while (y <= x)
2001  		y = y << 1;
2002  
2003  	return y;
2004  }
2005  
2006  /**
2007   * Determine if two memory regions overlap.
2008   *
2009   * @param r1, r2 Memory regions to compare.
2010   * @return 0 if the two regions are separate
2011   * @return 1 if the two regions overlap
2012   */
2013  static int regions_collide(const struct region *r1, const struct region *r2)
2014  {
2015  	if ((r1->size == 0) || (r2->size == 0))
2016  		return 0;
2017  
2018  	/* r1 should be either completely below or completely above r2 */
2019  	return !(r1->limit < r2->base || r1->base > r2->limit);
2020  }
2021  
2022  static void new_layout(const char *filename, char *image, int size,
2023  		const char *layout_fname)
2024  {
2025  	FILE *romlayout;
2026  	char tempstr[256];
2027  	char layout_region_name[256];
2028  	unsigned int i, j;
2029  	int region_number;
2030  	struct region current_regions[MAX_REGIONS];
2031  	struct region new_regions[MAX_REGIONS];
2032  	int new_extent = 0;
2033  	char *new_image;
2034  
2035  	/* load current descriptor map and regions */
2036  	struct frba *frba = find_frba(image, size);
2037  	if (!frba)
2038  		exit(EXIT_FAILURE);
2039  
2040  	for (i = 0; i < max_regions; i++) {
2041  		current_regions[i] = get_region(frba, i);
2042  		new_regions[i] = get_region(frba, i);
2043  	}
2044  
2045  	/* read new layout */
2046  	romlayout = fopen(layout_fname, "r");
2047  
2048  	if (!romlayout) {
2049  		perror("Could not read layout file.\n");
2050  		exit(EXIT_FAILURE);
2051  	}
2052  
2053  	while (!feof(romlayout)) {
2054  		char *tstr1, *tstr2;
2055  
2056  		if (2 != fscanf(romlayout, "%255s %255s\n", tempstr,
2057  					layout_region_name))
2058  			continue;
2059  
2060  		region_number = region_num(layout_region_name);
2061  		if (region_number < 0)
2062  			continue;
2063  
2064  		tstr1 = strtok(tempstr, ":");
2065  		tstr2 = strtok(NULL, ":");
2066  		if (!tstr1 || !tstr2) {
2067  			fprintf(stderr, "Could not parse layout file.\n");
2068  			exit(EXIT_FAILURE);
2069  		}
2070  		new_regions[region_number].base = strtol(tstr1,
2071  				(char **)NULL, 16);
2072  		new_regions[region_number].limit = strtol(tstr2,
2073  				(char **)NULL, 16);
2074  		new_regions[region_number].size =
2075  			new_regions[region_number].limit -
2076  			new_regions[region_number].base + 1;
2077  
2078  		if (new_regions[region_number].size < 0)
2079  			new_regions[region_number].size = 0;
2080  	}
2081  	fclose(romlayout);
2082  
2083  	/* check new layout */
2084  	for (i = 0; i < max_regions; i++) {
2085  		if (new_regions[i].size == 0)
2086  			continue;
2087  
2088  		if (new_regions[i].size < current_regions[i].size) {
2089  			printf("DANGER: Region %s is shrinking.\n",
2090  					region_name(i));
2091  			printf("    The region will be truncated to fit.\n");
2092  			printf("    This may result in an unusable image.\n");
2093  		}
2094  
2095  		for (j = i + 1; j < max_regions; j++) {
2096  			if (regions_collide(&new_regions[i], &new_regions[j])) {
2097  				fprintf(stderr, "Regions would overlap.\n");
2098  				exit(EXIT_FAILURE);
2099  			}
2100  		}
2101  
2102  		/* detect if the image size should grow */
2103  		if (new_extent < new_regions[i].limit)
2104  			new_extent = new_regions[i].limit;
2105  	}
2106  
2107  	/* check if the image is actually a Flash Descriptor region */
2108  	if (size == new_regions[0].size) {
2109  		printf("The image is a single Flash Descriptor:\n");
2110  		printf("    Only the descriptor will be modified\n");
2111  		new_extent = size;
2112  	} else {
2113  		new_extent = next_pow2(new_extent - 1);
2114  		if (new_extent != size) {
2115  			printf("The image has changed in size.\n");
2116  			printf("The old image is %d bytes.\n", size);
2117  			printf("The new image is %d bytes.\n", new_extent);
2118  		}
2119  	}
2120  
2121  	/* copy regions to a new image */
2122  	new_image = malloc(new_extent);
2123  	memset(new_image, 0xff, new_extent);
2124  	for (i = 0; i < max_regions; i++) {
2125  		int copy_size = new_regions[i].size;
2126  		int offset_current = 0, offset_new = 0;
2127  		const struct region *current = &current_regions[i];
2128  		const struct region *new = &new_regions[i];
2129  
2130  		if (new->size == 0)
2131  			continue;
2132  
2133  		if (new->size > current->size) {
2134  			/* copy from the end of the current region */
2135  			copy_size = current->size;
2136  			if (i == REGION_BIOS)
2137  				offset_new = new->size - current->size;
2138  		}
2139  
2140  		if ((i == REGION_BIOS) && (new->size < current->size)) {
2141  			/* copy BIOS region to the end of the new region */
2142  			offset_current = current->size - new->size;
2143  		}
2144  
2145  		if (size < current->base + offset_current + copy_size) {
2146  			printf("Skip descriptor %d (%s) (region missing in the old image)\n", i,
2147  				region_name(i));
2148  			continue;
2149  		};
2150  
2151  		printf("Copy Descriptor %d (%s) (%d bytes)\n", i,
2152  				region_name(i), copy_size);
2153  		printf("   from %08x+%08x:%08x (%10d)\n", current->base,
2154  				offset_current, current->limit, current->size);
2155  		printf("     to %08x+%08x:%08x (%10d)\n", new->base,
2156  				offset_new, new->limit, new->size);
2157  
2158  		memcpy(new_image + new->base + offset_new,
2159  				image + current->base + offset_current,
2160  				copy_size);
2161  	}
2162  
2163  	/* update new descriptor regions */
2164  	frba = find_frba(new_image, new_extent);
2165  	if (!frba)
2166  		exit(EXIT_FAILURE);
2167  
2168  	printf("Modify Flash Descriptor regions\n");
2169  	for (i = 1; i < max_regions; i++)
2170  		set_region(frba, i, &new_regions[i]);
2171  
2172  	write_image(filename, new_image, new_extent);
2173  	free(new_image);
2174  }
2175  
2176  static void print_version(void)
2177  {
2178  	printf("ifdtool v%s -- ", IFDTOOL_VERSION);
2179  	printf("Copyright (C) 2011 Google Inc.\n\n");
2180  	printf
2181  	    ("This program is free software: you can redistribute it and/or modify\n"
2182  	     "it under the terms of the GNU General Public License as published by\n"
2183  	     "the Free Software Foundation, version 2 of the License.\n\n"
2184  	     "This program is distributed in the hope that it will be useful,\n"
2185  	     "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
2186  	     "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
2187  	     "GNU General Public License for more details.\n\n");
2188  }
2189  
2190  static void print_usage(const char *name)
2191  {
2192  	printf("usage: %s [-vhdix?] <filename>\n", name);
2193  	printf("\n"
2194  	       "   -d | --dump:                          dump intel firmware descriptor\n"
2195  	       "   -f | --layout <filename>              dump regions into a flashrom layout file\n"
2196  	       "   -F | --fmap-layout <filename>         dump IFD regions into a fmap layout template (.fmd) file\n"
2197  	       "   -t | --validate                       Validate that the firmware descriptor layout matches the fmap layout\n"
2198  	       "   -x | --extract:                       extract intel fd modules\n"
2199  	       "   -i | --inject <region>:<module>       inject file <module> into region <region>\n"
2200  	       "   -n | --newlayout <filename>           update regions using a flashrom layout file\n"
2201  	       "   -O | --output <filename>              output filename\n"
2202  	       "   -s | --spifreq <17|20|30|33|48|50>    set the SPI frequency\n"
2203  	       "   -D | --density <512|1|2|4|8|16|32|64> set chip density (512 in KByte, others in MByte)\n"
2204  	       "   -C | --chip <0|1|2>                   select spi chip on which to operate\n"
2205  	       "                                         can only be used once per run:\n"
2206  	       "                                         0 - both chips (default), 1 - first chip, 2 - second chip\n"
2207  	       "   -e | --em100                          set SPI frequency to 20MHz and disable\n"
2208  	       "                                         Dual Output Fast Read Support\n"
2209  	       "   -l | --lock                           Lock firmware descriptor and ME region\n"
2210  	       "   -r | --read				 Enable CPU/BIOS read access for ME region\n"
2211  	       "   -u | --unlock                         Unlock firmware descriptor and ME region\n"
2212  	       "   -g | --gpr0-disable                   Disable GPR0 (Global Protected Range) register\n"
2213  	       "   -E | --gpr0-enable                    Enable GPR0 (Global Protected Range) register\n"
2214  	       "   -c | --gpr0-status                    Checking GPR0 (Global Protected Range) register status\n"
2215  	       "   -M | --altmedisable <0|1>             Set the MeDisable and AltMeDisable (or HAP for skylake or newer platform)\n"
2216  	       "                                         bits to disable ME\n"
2217  	       "   -p | --platform                       Add platform-specific quirks\n"
2218  	       "                                         adl    - Alder Lake\n"
2219  	       "                                         aplk   - Apollo Lake\n"
2220  	       "                                         cnl    - Cannon Lake\n"
2221  	       "                                         lbg    - Lewisburg PCH\n"
2222  	       "                                         dnv    - Denverton\n"
2223  	       "                                         ehl    - Elkhart Lake\n"
2224  	       "                                         glk    - Gemini Lake\n"
2225  	       "                                         icl    - Ice Lake\n"
2226  	       "                                         ifd2   - IFDv2 Platform\n"
2227  	       "                                         jsl    - Jasper Lake\n"
2228  	       "                                         mtl    - Meteor Lake\n"
2229  	       "                                         sklkbl - Sky Lake/Kaby Lake\n"
2230  	       "                                         tgl    - Tiger Lake\n"
2231  	       "                                         wbg    - Wellsburg\n"
2232  	       "   -S | --setpchstrap                    Write a PCH strap\n"
2233  	       "   -V | --newvalue                       The new value to write into PCH strap specified by -S\n"
2234  	       "   -v | --version:                       print the version\n"
2235  	       "   -h | --help:                          print this help\n\n"
2236  	       "<region> is one of Descriptor, BIOS, ME, GbE, Platform Data, Secondary BIOS, "
2237  	       "Device Exp1, EC, Device Exp2, IE, 10GbE_0, 10GbE_1, PTT\n"
2238  	       "\n");
2239  }
2240  
2241  int main(int argc, char *argv[])
2242  {
2243  	int opt, option_index = 0;
2244  	int mode_dump = 0, mode_extract = 0, mode_inject = 0, mode_spifreq = 0;
2245  	int mode_em100 = 0, mode_locked = 0, mode_unlocked = 0, mode_validate = 0;
2246  	int mode_layout = 0, mode_newlayout = 0, mode_density = 0, mode_setstrap = 0;
2247  	int mode_read = 0, mode_altmedisable = 0, altmedisable = 0, mode_fmap_template = 0;
2248  	int mode_gpr0_disable = 0, mode_gpr0_enable = 0, mode_gpr0_status = 0;
2249  	char *region_type_string = NULL, *region_fname = NULL, *layout_fname = NULL;
2250  	char *new_filename = NULL;
2251  	int region_type = -1, inputfreq = 0;
2252  	unsigned int value = 0;
2253  	unsigned int pchstrap = 0;
2254  	unsigned int new_density = 0;
2255  	enum spi_frequency spifreq = SPI_FREQUENCY_20MHZ;
2256  
2257  	static const struct option long_options[] = {
2258  		{"dump", 0, NULL, 'd'},
2259  		{"layout", 1, NULL, 'f'},
2260  		{"fmap-template", 1, NULL, 'F'},
2261  		{"extract", 0, NULL, 'x'},
2262  		{"inject", 1, NULL, 'i'},
2263  		{"newlayout", 1, NULL, 'n'},
2264  		{"output", 1, NULL, 'O'},
2265  		{"spifreq", 1, NULL, 's'},
2266  		{"density", 1, NULL, 'D'},
2267  		{"chip", 1, NULL, 'C'},
2268  		{"altmedisable", 1, NULL, 'M'},
2269  		{"em100", 0, NULL, 'e'},
2270  		{"lock", 0, NULL, 'l'},
2271  		{"read", 0, NULL, 'r'},
2272  		{"unlock", 0, NULL, 'u'},
2273  		{"gpr0-disable", 0, NULL, 'g'},
2274  		{"gpr0-enable", 0, NULL, 'E'},
2275  		{"gpr0-status", 0, NULL, 'c'},
2276  		{"version", 0, NULL, 'v'},
2277  		{"help", 0, NULL, 'h'},
2278  		{"platform", 1, NULL, 'p'},
2279  		{"validate", 0, NULL, 't'},
2280  		{"setpchstrap", 1, NULL, 'S'},
2281  		{"newvalue", 1, NULL, 'V'},
2282  		{0, 0, 0, 0}
2283  	};
2284  
2285  	while ((opt = getopt_long(argc, argv, "S:V:df:F:D:C:M:xi:n:O:s:p:elrugEcvth?",
2286  					long_options, &option_index)) != EOF) {
2287  		switch (opt) {
2288  		case 'd':
2289  			mode_dump = 1;
2290  			break;
2291  		case 'S':
2292  			mode_setstrap = 1;
2293  			pchstrap = strtoul(optarg, NULL, 0);
2294  			break;
2295  		case 'V':
2296  			value = strtoul(optarg, NULL, 0);
2297  			break;
2298  		case 'f':
2299  			mode_layout = 1;
2300  			layout_fname = strdup(optarg);
2301  			if (!layout_fname) {
2302  				fprintf(stderr, "No layout file specified\n");
2303  				fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
2304  				exit(EXIT_FAILURE);
2305  			}
2306  			break;
2307  		case 'F':
2308  			mode_fmap_template = 1;
2309  			layout_fname = strdup(optarg);
2310  			if (!layout_fname) {
2311  				fprintf(stderr, "No layout file specified\n");
2312  				fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
2313  				exit(EXIT_FAILURE);
2314  			}
2315  			break;
2316  		case 'x':
2317  			mode_extract = 1;
2318  			break;
2319  		case 'i':
2320  			// separate type and file name
2321  			region_type_string = strdup(optarg);
2322  			region_fname = strchr(region_type_string, ':');
2323  			if (!region_fname) {
2324  				fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
2325  				exit(EXIT_FAILURE);
2326  			}
2327  			region_fname[0] = '\0';
2328  			region_fname++;
2329  			// Descriptor, BIOS, ME, GbE, Platform
2330  			// valid type?
2331  			if (!strcasecmp("Descriptor", region_type_string))
2332  				region_type = 0;
2333  			else if (!strcasecmp("BIOS", region_type_string))
2334  				region_type = 1;
2335  			else if (!strcasecmp("ME", region_type_string))
2336  				region_type = 2;
2337  			else if (!strcasecmp("GbE", region_type_string))
2338  				region_type = 3;
2339  			else if (!strcasecmp("Platform Data", region_type_string))
2340  				region_type = 4;
2341  			else if (!strcasecmp("Device Exp1", region_type_string))
2342  				region_type = 5;
2343  			else if (!strcasecmp("Secondary BIOS", region_type_string))
2344  				region_type = 6;
2345  			else if (!strcasecmp("Reserved", region_type_string))
2346  				region_type = 7;
2347  			else if (!strcasecmp("EC", region_type_string))
2348  				region_type = 8;
2349  			else if (!strcasecmp("Device Exp2", region_type_string))
2350  				region_type = 9;
2351  			else if (!strcasecmp("IE", region_type_string))
2352  				region_type = 10;
2353  			else if (!strcasecmp("10GbE_0", region_type_string))
2354  				region_type = 11;
2355  			else if (!strcasecmp("10GbE_1", region_type_string))
2356  				region_type = 12;
2357  			else if (!strcasecmp("PTT", region_type_string))
2358  				region_type = 15;
2359  			if (region_type == -1) {
2360  				fprintf(stderr, "No such region type: '%s'\n\n",
2361  					region_type_string);
2362  				fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
2363  				exit(EXIT_FAILURE);
2364  			}
2365  			mode_inject = 1;
2366  			break;
2367  		case 'n':
2368  			mode_newlayout = 1;
2369  			layout_fname = strdup(optarg);
2370  			if (!layout_fname) {
2371  				fprintf(stderr, "No layout file specified\n");
2372  				fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
2373  				exit(EXIT_FAILURE);
2374  			}
2375  			break;
2376  		case 'O':
2377  			new_filename = strdup(optarg);
2378  			if (!new_filename) {
2379  				fprintf(stderr, "No output filename specified\n");
2380  				fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
2381  				exit(EXIT_FAILURE);
2382  			}
2383  			break;
2384  		case 'D':
2385  			mode_density = 1;
2386  			new_density = strtoul(optarg, NULL, 0);
2387  			switch (new_density) {
2388  			case 512:
2389  				new_density = COMPONENT_DENSITY_512KB;
2390  				break;
2391  			case 1:
2392  				new_density = COMPONENT_DENSITY_1MB;
2393  				break;
2394  			case 2:
2395  				new_density = COMPONENT_DENSITY_2MB;
2396  				break;
2397  			case 4:
2398  				new_density = COMPONENT_DENSITY_4MB;
2399  				break;
2400  			case 8:
2401  				new_density = COMPONENT_DENSITY_8MB;
2402  				break;
2403  			case 16:
2404  				new_density = COMPONENT_DENSITY_16MB;
2405  				break;
2406  			case 32:
2407  				new_density = COMPONENT_DENSITY_32MB;
2408  				break;
2409  			case 64:
2410  				new_density = COMPONENT_DENSITY_64MB;
2411  				break;
2412  			case 0:
2413  				new_density = COMPONENT_DENSITY_UNUSED;
2414  				break;
2415  			default:
2416  				printf("error: Unknown density\n");
2417  				fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
2418  				exit(EXIT_FAILURE);
2419  			}
2420  			break;
2421  		case 'C':
2422  			selected_chip = strtol(optarg, NULL, 0);
2423  			if (selected_chip > 2) {
2424  				fprintf(stderr, "error: Invalid chip selection\n");
2425  				fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
2426  				exit(EXIT_FAILURE);
2427  			}
2428  			break;
2429  		case 'M':
2430  			mode_altmedisable = 1;
2431  			altmedisable = strtol(optarg, NULL, 0);
2432  			if (altmedisable > 1) {
2433  				fprintf(stderr, "error: Illegal value\n");
2434  				fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
2435  				exit(EXIT_FAILURE);
2436  			}
2437  			break;
2438  		case 's':
2439  			// Parse the requested SPI frequency
2440  			inputfreq = strtol(optarg, NULL, 0);
2441  			switch (inputfreq) {
2442  			case 17:
2443  				spifreq = SPI_FREQUENCY_17MHZ;
2444  				break;
2445  			case 20:
2446  				spifreq = SPI_FREQUENCY_20MHZ;
2447  				break;
2448  			case 30:
2449  				spifreq = SPI_FREQUENCY_50MHZ_30MHZ;
2450  				break;
2451  			case 33:
2452  				spifreq = SPI_FREQUENCY_33MHZ;
2453  				break;
2454  			case 48:
2455  				spifreq = SPI_FREQUENCY_48MHZ;
2456  				break;
2457  			case 50:
2458  				spifreq = SPI_FREQUENCY_50MHZ_30MHZ;
2459  				break;
2460  			default:
2461  				fprintf(stderr, "Invalid SPI Frequency: %d\n",
2462  					inputfreq);
2463  				fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
2464  				exit(EXIT_FAILURE);
2465  			}
2466  			mode_spifreq = 1;
2467  			break;
2468  		case 'e':
2469  			mode_em100 = 1;
2470  			break;
2471  		case 'l':
2472  			mode_locked = 1;
2473  			if (mode_unlocked == 1) {
2474  				fprintf(stderr, "Locking/Unlocking FD and ME are mutually exclusive\n");
2475  				exit(EXIT_FAILURE);
2476  			}
2477  			break;
2478  		case 'r':
2479  			mode_read = 1;
2480  			break;
2481  		case 'u':
2482  			mode_unlocked = 1;
2483  			if (mode_locked == 1) {
2484  				fprintf(stderr, "Locking/Unlocking FD and ME are mutually exclusive\n");
2485  				exit(EXIT_FAILURE);
2486  			}
2487  			break;
2488  		case 'g':
2489  			mode_gpr0_disable = 1;
2490  			break;
2491  		case 'E':
2492  			mode_gpr0_enable = 1;
2493  			break;
2494  		case 'c':
2495  			mode_gpr0_status = 1;
2496  			break;
2497  		case 'p':
2498  			if (!strcmp(optarg, "aplk")) {
2499  				platform = PLATFORM_APL;
2500  			} else if (!strcmp(optarg, "cnl")) {
2501  				platform = PLATFORM_CNL;
2502  			} else if (!strcmp(optarg, "lbg")) {
2503  				platform = PLATFORM_LBG;
2504  			} else if (!strcmp(optarg, "dnv")) {
2505  				platform = PLATFORM_DNV;
2506  			} else if (!strcmp(optarg, "ehl")) {
2507  				platform = PLATFORM_EHL;
2508  			} else if (!strcmp(optarg, "glk")) {
2509  				platform = PLATFORM_GLK;
2510  			} else if (!strcmp(optarg, "icl")) {
2511  				platform = PLATFORM_ICL;
2512  			} else if (!strcmp(optarg, "jsl")) {
2513  				platform = PLATFORM_JSL;
2514  			} else if (!strcmp(optarg, "sklkbl")) {
2515  				platform = PLATFORM_SKLKBL;
2516  			} else if (!strcmp(optarg, "tgl")) {
2517  				platform = PLATFORM_TGL;
2518  			} else if (!strcmp(optarg, "adl")) {
2519  				platform = PLATFORM_ADL;
2520  			} else if (!strcmp(optarg, "ifd2")) {
2521  				platform = PLATFORM_IFD2;
2522  			} else if (!strcmp(optarg, "mtl")) {
2523  				platform = PLATFORM_MTL;
2524  			} else if (!strcmp(optarg, "ptl")) {
2525  				platform = PLATFORM_PTL;
2526  			} else if (!strcmp(optarg, "wbg")) {
2527  				platform = PLATFORM_WBG;
2528  			} else {
2529  				fprintf(stderr, "Unknown platform: %s\n", optarg);
2530  				exit(EXIT_FAILURE);
2531  			}
2532  			break;
2533  		case 't':
2534  			mode_validate = 1;
2535  			break;
2536  		case 'v':
2537  			print_version();
2538  			exit(EXIT_SUCCESS);
2539  			break;
2540  		case 'h':
2541  		case '?':
2542  			print_usage(argv[0]);
2543  			exit(EXIT_SUCCESS);
2544  			break;
2545  		default:
2546  			print_usage(argv[0]);
2547  			exit(EXIT_FAILURE);
2548  			break;
2549  		}
2550  	}
2551  
2552  	if ((mode_dump + mode_layout + mode_fmap_template + mode_extract + mode_inject +
2553  			mode_setstrap + mode_newlayout + (mode_spifreq | mode_em100 |
2554  			mode_unlocked | mode_locked) + mode_altmedisable + mode_validate +
2555  			(mode_gpr0_disable | mode_gpr0_enable) + mode_gpr0_status) > 1) {
2556  		fprintf(stderr, "You may not specify more than one mode.\n\n");
2557  		fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
2558  		exit(EXIT_FAILURE);
2559  	}
2560  
2561  	if ((mode_dump + mode_layout + mode_fmap_template + mode_extract + mode_inject +
2562  			mode_setstrap + mode_newlayout + mode_spifreq + mode_em100 +
2563  			mode_locked + mode_unlocked + mode_density + mode_altmedisable +
2564  			mode_validate + (mode_gpr0_disable | mode_gpr0_enable) + mode_gpr0_status) == 0) {
2565  		fprintf(stderr, "You need to specify a mode.\n\n");
2566  		fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
2567  		exit(EXIT_FAILURE);
2568  	}
2569  
2570  	if (optind + 1 != argc) {
2571  		fprintf(stderr, "You need to specify a file.\n\n");
2572  		fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
2573  		exit(EXIT_FAILURE);
2574  	}
2575  
2576  	if (platform == -1)
2577  		fprintf(stderr, "Warning: No platform specified. Output may be incomplete\n");
2578  
2579  	char *filename = argv[optind];
2580  	int bios_fd = open(filename, O_RDONLY | O_BINARY);
2581  	if (bios_fd == -1) {
2582  		perror("Could not open file");
2583  		exit(EXIT_FAILURE);
2584  	}
2585  	struct stat buf;
2586  	if (fstat(bios_fd, &buf) == -1) {
2587  		perror("Could not stat file");
2588  		exit(EXIT_FAILURE);
2589  	}
2590  	int size = buf.st_size;
2591  
2592  	printf("File %s is %d bytes\n", filename, size);
2593  
2594  	char *image = malloc(size);
2595  	if (!image) {
2596  		printf("Out of memory.\n");
2597  		exit(EXIT_FAILURE);
2598  	}
2599  
2600  	if (read(bios_fd, image, size) != size) {
2601  		perror("Could not read file");
2602  		exit(EXIT_FAILURE);
2603  	}
2604  
2605  	close(bios_fd);
2606  
2607  	// generate new filename
2608  	if (new_filename == NULL) {
2609  		new_filename = (char *)malloc((strlen(filename) + 5) * sizeof(char));
2610  		if (!new_filename) {
2611  			printf("Out of memory.\n");
2612  			exit(EXIT_FAILURE);
2613  		}
2614  		// - 5: leave room for ".new\0"
2615  		strcpy(new_filename, filename);
2616  		strcat(new_filename, ".new");
2617  	}
2618  
2619  	check_ifd_version(image, size);
2620  
2621  	if (mode_dump)
2622  		dump_fd(image, size);
2623  
2624  	if (mode_layout)
2625  		dump_flashrom_layout(image, size, layout_fname);
2626  
2627  	if (mode_fmap_template)
2628  		create_fmap_template(image, size, layout_fname);
2629  
2630  	if (mode_extract)
2631  		write_regions(image, size);
2632  
2633  	if (mode_validate)
2634  		validate_layout(image, size);
2635  
2636  	if (mode_inject)
2637  		inject_region(new_filename, image, size, region_type,
2638  				region_fname);
2639  
2640  	if (mode_newlayout)
2641  		new_layout(new_filename, image, size, layout_fname);
2642  
2643  	if (mode_spifreq)
2644  		set_spi_frequency(new_filename, image, size, spifreq);
2645  
2646  	if (mode_density)
2647  		set_chipdensity(new_filename, image, size, new_density);
2648  
2649  	if (mode_em100)
2650  		set_em100_mode(new_filename, image, size);
2651  
2652  	if (mode_locked)
2653  		lock_descriptor(new_filename, image, size);
2654  
2655  	if (mode_read)
2656  		enable_cpu_read_me(new_filename, image, size);
2657  
2658  	if (mode_unlocked)
2659  		unlock_descriptor(new_filename, image, size);
2660  
2661  	if (mode_gpr0_disable)
2662  		disable_gpr0(new_filename, image, size);
2663  
2664  	if (mode_gpr0_enable)
2665  		enable_gpr0(new_filename, image, size);
2666  
2667  	if (mode_gpr0_status)
2668  		is_gpr0_protected(image, size);
2669  
2670  	if (mode_setstrap) {
2671  		struct fpsba *fpsba = find_fpsba(image, size);
2672  		const struct fdbar *fdb = find_fd(image, size);
2673  		set_pchstrap(fpsba, fdb, pchstrap, value);
2674  		write_image(new_filename, image, size);
2675  	}
2676  
2677  	if (mode_altmedisable) {
2678  		struct fpsba *fpsba = find_fpsba(image, size);
2679  		struct fmsba *fmsba = find_fmsba(image, size);
2680  		fpsba_set_altmedisable(fpsba, fmsba, altmedisable);
2681  		write_image(new_filename, image, size);
2682  	}
2683  
2684  	free(region_type_string);
2685  	free(layout_fname);
2686  	free(new_filename);
2687  	free(image);
2688  
2689  	return 0;
2690  }