xref: /aosp_15_r20/external/coreboot/util/ifdtool/ifdtool.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
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 
find_fd(char * image,int size)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 
find_flumap(char * image,int size)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 
find_fcba(char * image,int size)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 
find_fmba(char * image,int size)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 
find_frba(char * image,int size)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 
find_fpsba(char * image,int size)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 
find_fmsba(char * image,int size)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 */
ifd1_guess_chipset(char * image,int size)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 
ifd2_platform_to_chipset(const int pindex)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  */
is_platform_ifd_2(void)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 
check_ifd_version(char * image,int size)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 
get_region(const struct frba * frba,unsigned int region_type)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 
set_region(struct frba * frba,unsigned int region_type,const struct region * region)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 
region_name(unsigned int region_type)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 
region_num(const char * name)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 
dump_region(unsigned int num,const struct frba * frba)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 
sort_compare(const void * a,const void * b)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  */
max_regions_from_fdbar(const struct fdbar * fdb)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 
dump_frba(const struct frba * frba)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 
dump_flashrom_layout(char * image,int size,const char * layout_fname)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 
_decode_spi_frequency(unsigned int freq)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 
_decode_spi_frequency_500_series(unsigned int freq)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 
decode_spi_frequency(unsigned int freq)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 
_decode_espi_frequency(unsigned int freq)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 
_decode_espi_frequency_500_series(unsigned int freq)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 
_decode_espi_frequency_800_series(unsigned int freq)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 
decode_espi_frequency(unsigned int freq)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 
decode_component_density(unsigned int density)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 
is_platform_with_pch(void)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 */
is_platform_with_100x_series_pch(void)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 
dump_fcba(const struct fcba * fcba,const struct fpsba * fpsba)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 
dump_fpsba(const struct fdbar * fdb,const struct fpsba * fpsba)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 
decode_flmstr(uint32_t flmstr)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 
dump_fmba(const struct fmba * fmba)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 
dump_fmsba(const struct fmsba * fmsba)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 
dump_jid(uint32_t jid)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 
dump_vscc(uint32_t vscc)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 
dump_vtba(const struct vtba * vtba,int vtl)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 
dump_oem(const uint8_t * oem)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 
dump_fd(char * image,int size)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  */
create_fmap_template(char * image,int size,const char * layout_fname)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 
write_regions(char * image,int size)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 
validate_layout(char * image,int size)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 			printf("Region mismatch between %s and %s\n", region_names[i].terse, area->name);
1231 			printf(" Descriptor region %s:\n", region_names[i].terse);
1232 			printf("  offset: 0x%08x\n", region.base);
1233 			printf("  length: 0x%08x\n", region.size);
1234 			printf(" FMAP area %s:\n", area->name);
1235 			printf("  offset: 0x%08x\n", area->offset);
1236 			printf("  length: 0x%08x\n", area->size);
1237 			errors++;
1238 		}
1239 	}
1240 
1241 	if (!matches) {
1242 		// At least a BIOS region should be present in both IFD and FMAP
1243 		fprintf(stderr, "Warning: Not a single IFD region found in FMAP\n");
1244 	}
1245 
1246 	if (errors > 0)
1247 		exit(EXIT_FAILURE);
1248 }
1249 
write_image(const char * filename,char * image,int size)1250 static void write_image(const char *filename, char *image, int size)
1251 {
1252 	int new_fd;
1253 	printf("Writing new image to %s\n", filename);
1254 
1255 	// Now write out new image
1256 	new_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
1257 	if (new_fd < 0) {
1258 		perror("Error while trying to open file");
1259 		exit(EXIT_FAILURE);
1260 	}
1261 	if (write(new_fd, image, size) != size)
1262 		perror("Error while writing");
1263 	close(new_fd);
1264 }
1265 
set_spi_frequency(const char * filename,char * image,int size,enum spi_frequency freq)1266 static void set_spi_frequency(const char *filename, char *image, int size,
1267 			      enum spi_frequency freq)
1268 {
1269 	struct fcba *fcba = find_fcba(image, size);
1270 	if (!fcba)
1271 		exit(EXIT_FAILURE);
1272 
1273 	/* clear bits 21-29 */
1274 	fcba->flcomp &= ~0x3fe00000;
1275 	/* Read ID and Read Status Clock Frequency */
1276 	fcba->flcomp |= freq << 27;
1277 	/* Write and Erase Clock Frequency */
1278 	fcba->flcomp |= freq << 24;
1279 	/* Fast Read Clock Frequency */
1280 	fcba->flcomp |= freq << 21;
1281 
1282 	write_image(filename, image, size);
1283 }
1284 
set_em100_mode(const char * filename,char * image,int size)1285 static void set_em100_mode(const char *filename, char *image, int size)
1286 {
1287 	struct fcba *fcba = find_fcba(image, size);
1288 	if (!fcba)
1289 		exit(EXIT_FAILURE);
1290 
1291 	int freq;
1292 
1293 	switch (ifd_version) {
1294 	case IFD_VERSION_1:
1295 	case IFD_VERSION_1_5:
1296 		freq = SPI_FREQUENCY_20MHZ;
1297 		break;
1298 	case IFD_VERSION_2:
1299 		freq = SPI_FREQUENCY_17MHZ;
1300 		break;
1301 	default:
1302 		freq = SPI_FREQUENCY_17MHZ;
1303 		break;
1304 	}
1305 
1306 	fcba->flcomp &= ~(1 << 30);
1307 	set_spi_frequency(filename, image, size, freq);
1308 }
1309 
set_chipdensity(const char * filename,char * image,int size,unsigned int density)1310 static void set_chipdensity(const char *filename, char *image, int size,
1311 			    unsigned int density)
1312 {
1313 	struct fcba *fcba = find_fcba(image, size);
1314 	uint8_t mask, chip2_offset;
1315 	if (!fcba)
1316 		exit(EXIT_FAILURE);
1317 
1318 	printf("Setting chip density to ");
1319 	decode_component_density(density);
1320 	printf("\n");
1321 
1322 	switch (ifd_version) {
1323 	case IFD_VERSION_1:
1324 		/* fail if selected density is not supported by this version */
1325 		if ( (density == COMPONENT_DENSITY_32MB) ||
1326 		     (density == COMPONENT_DENSITY_64MB) ||
1327 		     (density == COMPONENT_DENSITY_UNUSED) ) {
1328 			printf("error: Selected density not supported in IFD version 1.\n");
1329 			exit(EXIT_FAILURE);
1330 		}
1331 		mask = 0x7;
1332 		chip2_offset = 3;
1333 		break;
1334 	case IFD_VERSION_1_5:
1335 	case IFD_VERSION_2:
1336 		mask = 0xf;
1337 		chip2_offset = 4;
1338 		break;
1339 	default:
1340 		printf("error: Unknown IFD version\n");
1341 		exit(EXIT_FAILURE);
1342 		break;
1343 	}
1344 
1345 	/* clear chip density for corresponding chip */
1346 	switch (selected_chip) {
1347 	case 1:
1348 		fcba->flcomp &= ~mask;
1349 		break;
1350 	case 2:
1351 		fcba->flcomp &= ~(mask << chip2_offset);
1352 		break;
1353 	default: /*both chips*/
1354 		fcba->flcomp &= ~(mask | (mask << chip2_offset));
1355 		break;
1356 	}
1357 
1358 	/* set the new density */
1359 	if (selected_chip == 1 || selected_chip == 0)
1360 		fcba->flcomp |= (density); /* first chip */
1361 	if (selected_chip == 2 || selected_chip == 0)
1362 		fcba->flcomp |= (density << chip2_offset); /* second chip */
1363 
1364 	write_image(filename, image, size);
1365 }
1366 
check_region(const struct frba * frba,unsigned int region_type)1367 static int check_region(const struct frba *frba, unsigned int region_type)
1368 {
1369 	struct region region;
1370 
1371 	if (!frba)
1372 		return 0;
1373 
1374 	region = get_region(frba, region_type);
1375 	return !!((region.base < region.limit) && (region.size > 0));
1376 }
1377 
1378 /*
1379  * Platforms from CNL onwards support up to 16 flash regions, not 12. The
1380  * permissions for regions [15:12] are stored in extended region read/write
1381  * access fields in the FLMSTR registers.
1382  *
1383  * FLMSTR with extended regions:
1384  *   31:20 Region Write Access
1385  *   19:8  Region Read Access
1386  *    7:4  Extended Region Write Access
1387  *    3:0  Extended Region Read Access
1388  *
1389  * FLMSTR without extended regions:
1390  *   31:20 Region Write Access
1391  *   19:8  Region Read Access
1392  *    7:0  Reserved
1393  */
platform_has_extended_regions(void)1394 static bool platform_has_extended_regions(void)
1395 {
1396 	switch (platform) {
1397 	case PLATFORM_CNL:
1398 	case PLATFORM_JSL:
1399 	case PLATFORM_TGL:
1400 	case PLATFORM_ADL:
1401 	case PLATFORM_MTL:
1402 	case PLATFORM_PTL:
1403 		return true;
1404 	default:
1405 		return false;
1406 	}
1407 }
1408 
lock_descriptor(const char * filename,char * image,int size)1409 static void lock_descriptor(const char *filename, char *image, int size)
1410 {
1411 	int wr_shift, rd_shift;
1412 	struct fmba *fmba = find_fmba(image, size);
1413 	const struct frba *frba = find_frba(image, size);
1414 	if (!fmba)
1415 		exit(EXIT_FAILURE);
1416 
1417 	if (ifd_version >= IFD_VERSION_2) {
1418 		wr_shift = FLMSTR_WR_SHIFT_V2;
1419 		rd_shift = FLMSTR_RD_SHIFT_V2;
1420 
1421 		/*
1422 		 * Clear all read/write access bits. See comment on
1423 		 * platform_has_extended_regions() for bitfields.
1424 		 */
1425 		if (platform_has_extended_regions()) {
1426 			fmba->flmstr1 = 0;
1427 			fmba->flmstr2 = 0;
1428 			fmba->flmstr3 = 0;
1429 			fmba->flmstr5 = 0;
1430 		} else {
1431 			fmba->flmstr1 &= 0xff;
1432 			fmba->flmstr2 &= 0xff;
1433 			fmba->flmstr3 &= 0xff;
1434 			fmba->flmstr5 &= 0xff;
1435 		}
1436 	} else {
1437 		wr_shift = FLMSTR_WR_SHIFT_V1;
1438 		rd_shift = FLMSTR_RD_SHIFT_V1;
1439 
1440 		fmba->flmstr1 = 0;
1441 		fmba->flmstr2 = 0;
1442 		/* Requestor ID */
1443 		fmba->flmstr3 = 0x118;
1444 	}
1445 
1446 	switch (platform) {
1447 	case PLATFORM_APL:
1448 	case PLATFORM_GLK:
1449 		/* CPU/BIOS can read descriptor and BIOS */
1450 		fmba->flmstr1 |= 0x3 << rd_shift;
1451 		/* CPU/BIOS can write BIOS */
1452 		fmba->flmstr1 |= 0x2 << wr_shift;
1453 		/* TXE can read descriptor, BIOS and Device Expansion */
1454 		fmba->flmstr2 |= 0x23 << rd_shift;
1455 		/* TXE can only write Device Expansion */
1456 		fmba->flmstr2 |= 0x20 << wr_shift;
1457 		break;
1458 	case PLATFORM_CNL:
1459 	case PLATFORM_ICL:
1460 	case PLATFORM_SKLKBL:
1461 	case PLATFORM_TGL:
1462 	case PLATFORM_JSL:
1463 	case PLATFORM_EHL:
1464 	case PLATFORM_ADL:
1465 	case PLATFORM_IFD2:
1466 	case PLATFORM_MTL:
1467 	case PLATFORM_PTL:
1468 		/* CPU/BIOS can read descriptor and BIOS. */
1469 		fmba->flmstr1 |= (1 << REGION_DESC) << rd_shift;
1470 		fmba->flmstr1 |= (1 << REGION_BIOS) << rd_shift;
1471 		/* CPU/BIOS can write BIOS. */
1472 		fmba->flmstr1 |= (1 << REGION_BIOS) << wr_shift;
1473 		/* ME can read descriptor and ME. */
1474 		fmba->flmstr2 |= (1 << REGION_DESC) << rd_shift;
1475 		fmba->flmstr2 |= (1 << REGION_ME) << rd_shift;
1476 		/* ME can write ME. */
1477 		fmba->flmstr2 |= (1 << REGION_ME) << wr_shift;
1478 		if (check_region(frba, REGION_GBE)) {
1479 			/* BIOS can read/write GbE. */
1480 			fmba->flmstr1 |= (1 << REGION_GBE) << rd_shift;
1481 			fmba->flmstr1 |= (1 << REGION_GBE) << wr_shift;
1482 			/* ME can read GbE. */
1483 			fmba->flmstr2 |= (1 << REGION_GBE) << rd_shift;
1484 			/* GbE can read descriptor and read/write GbE.. */
1485 			fmba->flmstr3 |= (1 << REGION_DESC) << rd_shift;
1486 			fmba->flmstr3 |= (1 << REGION_GBE) << rd_shift;
1487 			fmba->flmstr3 |= (1 << REGION_GBE) << wr_shift;
1488 		}
1489 		if (check_region(frba, REGION_PDR)) {
1490 			/* BIOS can read/write PDR. */
1491 			fmba->flmstr1 |= (1 << REGION_PDR) << rd_shift;
1492 			fmba->flmstr1 |= (1 << REGION_PDR) << wr_shift;
1493 		}
1494 		if (check_region(frba, REGION_EC)) {
1495 			/* BIOS can read EC. */
1496 			fmba->flmstr1 |= (1 << REGION_EC) << rd_shift;
1497 			/* EC can read descriptor and read/write EC. */
1498 			fmba->flmstr5 |= (1 << REGION_DESC) << rd_shift;
1499 			fmba->flmstr5 |= (1 << REGION_EC) << rd_shift;
1500 			fmba->flmstr5 |= (1 << REGION_EC) << wr_shift;
1501 		}
1502 		if (check_region(frba, REGION_DEV_EXP2)) {
1503 			/* BIOS can read SPI device expansion 2 region. */
1504 			fmba->flmstr1 |= (1 << REGION_DEV_EXP2) << rd_shift;
1505 		}
1506 		break;
1507 	case PLATFORM_DNV:
1508 	case PLATFORM_WBG:
1509 		/* CPU/BIOS can read descriptor and BIOS. */
1510 		fmba->flmstr1 |= (1 << REGION_DESC) << rd_shift;
1511 		fmba->flmstr1 |= (1 << REGION_BIOS) << rd_shift;
1512 		/* CPU/BIOS can write BIOS. */
1513 		fmba->flmstr1 |= (1 << REGION_BIOS) << wr_shift;
1514 		/* ME can read descriptor and ME. */
1515 		fmba->flmstr2 |= (1 << REGION_DESC) << rd_shift;
1516 		fmba->flmstr2 |= (1 << REGION_ME) << rd_shift;
1517 		/* ME can write ME. */
1518 		fmba->flmstr2 |= (1 << REGION_ME) << wr_shift;
1519 		break;
1520 	default:
1521 		/* CPU/BIOS can read descriptor and BIOS. */
1522 		fmba->flmstr1 |= (1 << REGION_DESC) << rd_shift;
1523 		fmba->flmstr1 |= (1 << REGION_BIOS) << rd_shift;
1524 		/* CPU/BIOS can write BIOS. */
1525 		fmba->flmstr1 |= (1 << REGION_BIOS) << wr_shift;
1526 		/* ME can read descriptor and ME. */
1527 		fmba->flmstr2 |= (1 << REGION_DESC) << rd_shift;
1528 		fmba->flmstr2 |= (1 << REGION_ME) << rd_shift;
1529 		/* ME can write ME. */
1530 		fmba->flmstr2 |= (1 << REGION_ME) << wr_shift;
1531 		if (check_region(frba, REGION_GBE)) {
1532 			/* BIOS can read GbE. */
1533 			fmba->flmstr1 |= (1 << REGION_GBE) << rd_shift;
1534 			/* BIOS can write GbE. */
1535 			fmba->flmstr1 |= (1 << REGION_GBE) << wr_shift;
1536 			/* ME can read GbE. */
1537 			fmba->flmstr2 |= (1 << REGION_GBE) << rd_shift;
1538 			/* ME can write GbE. */
1539 			fmba->flmstr2 |= (1 << REGION_GBE) << wr_shift;
1540 			/* GbE can write GbE. */
1541 			fmba->flmstr3 |= (1 << REGION_GBE) << rd_shift;
1542 			/* GbE can read GbE. */
1543 			fmba->flmstr3 |= (1 << REGION_GBE) << wr_shift;
1544 		}
1545 		break;
1546 	}
1547 
1548 	write_image(filename, image, size);
1549 }
1550 
enable_cpu_read_me(const char * filename,char * image,int size)1551 static void enable_cpu_read_me(const char *filename, char *image, int size)
1552 {
1553 	int rd_shift;
1554 	struct fmba *fmba = find_fmba(image, size);
1555 
1556 	if (!fmba)
1557 		exit(EXIT_FAILURE);
1558 
1559 	if (ifd_version >= IFD_VERSION_2)
1560 		rd_shift = FLMSTR_RD_SHIFT_V2;
1561 	else
1562 		rd_shift = FLMSTR_RD_SHIFT_V1;
1563 
1564 	/* CPU/BIOS can read ME. */
1565 	fmba->flmstr1 |= (1 << REGION_ME) << rd_shift;
1566 
1567 	write_image(filename, image, size);
1568 }
1569 
unlock_descriptor(const char * filename,char * image,int size)1570 static void unlock_descriptor(const char *filename, char *image, int size)
1571 {
1572 	struct fmba *fmba = find_fmba(image, size);
1573 	if (!fmba)
1574 		exit(EXIT_FAILURE);
1575 
1576 	if (ifd_version >= IFD_VERSION_2) {
1577 		/*
1578 		 * Set all read/write access bits. See comment on
1579 		 * platform_has_extended_regions() for bitfields.
1580 		 */
1581 		if (platform_has_extended_regions()) {
1582 			fmba->flmstr1 = 0xffffffff;
1583 			fmba->flmstr2 = 0xffffffff;
1584 			fmba->flmstr3 = 0xffffffff;
1585 			fmba->flmstr5 = 0xffffffff;
1586 		} else {
1587 			fmba->flmstr1 = 0xffffff00 | (fmba->flmstr1 & 0xff);
1588 			fmba->flmstr2 = 0xffffff00 | (fmba->flmstr2 & 0xff);
1589 			fmba->flmstr3 = 0xffffff00 | (fmba->flmstr3 & 0xff);
1590 			fmba->flmstr5 = 0xffffff00 | (fmba->flmstr5 & 0xff);
1591 		}
1592 	} else {
1593 		fmba->flmstr1 = 0xffff0000;
1594 		fmba->flmstr2 = 0xffff0000;
1595 		/* Keep chipset specific Requester ID */
1596 		fmba->flmstr3 = 0x08080000 | (fmba->flmstr3 & 0xffff);
1597 	}
1598 
1599 	write_image(filename, image, size);
1600 }
1601 
print_gpr0_range(union gprd reg)1602 static void print_gpr0_range(union gprd reg)
1603 {
1604 	printf("--------- GPR0 Protected Range --------------\n");
1605 	printf("Start address = 0x%08x\n", reg.data.start << 12);
1606 	printf("End address = 0x%08x\n", (reg.data.end << 12) | 0xfff);
1607 }
1608 
get_cse_data_partition_offset(void)1609 static uint8_t get_cse_data_partition_offset(void)
1610 {
1611 	uint8_t data_offset = 0xff;
1612 
1613 	switch (platform) {
1614 	case PLATFORM_CNL:
1615 	case PLATFORM_JSL:
1616 		data_offset = 0x10;
1617 		break;
1618 	case PLATFORM_TGL:
1619 	case PLATFORM_ADL:
1620 	case PLATFORM_MTL:
1621 	case PLATFORM_PTL:
1622 		data_offset = 0x18;
1623 		break;
1624 	default:
1625 		break;
1626 	}
1627 
1628 	return data_offset;
1629 }
1630 
get_gpr0_offset(void)1631 static uint32_t get_gpr0_offset(void)
1632 {
1633 	/* Offset expressed as number of 32-bit fields from FPSBA */
1634 	uint32_t gpr0_offset = 0xffffffff;
1635 
1636 	switch (platform) {
1637 	case PLATFORM_CNL:
1638 		gpr0_offset = 0x10;
1639 		break;
1640 	case PLATFORM_JSL:
1641 		gpr0_offset = 0x12;
1642 		break;
1643 	case PLATFORM_TGL:
1644 	case PLATFORM_ADL:
1645 		gpr0_offset = 0x15;
1646 		break;
1647 	case PLATFORM_MTL:
1648 		gpr0_offset = 0x40;
1649 		break;
1650 	case PLATFORM_PTL:
1651 		gpr0_offset = 0x76;
1652 		break;
1653 	default:
1654 		break;
1655 	}
1656 
1657 	return gpr0_offset;
1658 }
1659 
disable_gpr0(const char * filename,char * image,int size)1660 static void disable_gpr0(const char *filename, char *image, int size)
1661 {
1662 	struct fpsba *fpsba = find_fpsba(image, size);
1663 	if (!fpsba)
1664 		exit(EXIT_FAILURE);
1665 
1666 	uint32_t gpr0_offset = get_gpr0_offset();
1667 	if (gpr0_offset == 0xffffffff) {
1668 		fprintf(stderr, "Disabling GPR0 not supported on this platform\n");
1669 		exit(EXIT_FAILURE);
1670 	}
1671 
1672 	union gprd reg;
1673 	/* If bit 31 is set then GPR0 protection is enable */
1674 	reg.value = fpsba->pchstrp[gpr0_offset];
1675 	if (!reg.data.write_protect_en) {
1676 		printf("GPR0 protection is already disabled\n");
1677 		return;
1678 	}
1679 
1680 	printf("Value at GPRD offset (%d) is 0x%08x\n", gpr0_offset, reg.value);
1681 	print_gpr0_range(reg);
1682 	/* 0 means GPR0 protection is disabled */
1683 	fpsba->pchstrp[gpr0_offset] = 0;
1684 	write_image(filename, image, size);
1685 	printf("GPR0 protection is now disabled\n");
1686 }
1687 
1688 /*
1689  * Helper function to parse the FPT to retrieve the FITC start offset and size.
1690  * FITC is a sub-partition table inside CSE data partition known as FPT.
1691  *
1692  * CSE Region
1693  *   |-----> CSE Data Partition Offset
1694  *   |              |------->  FPT Entry
1695  *   |              |              |-> Sub Partition 1
1696  *   |              |              |-> Sub Partition 2
1697  *   |              |              |-> FITC
1698  *   |              |              |     | -> FITC Offset
1699  *   |              |              |     | -> FITC Length
1700  */
parse_fitc_table(struct cse_fpt * fpt,uint32_t * offset,size_t * size)1701 static int parse_fitc_table(struct cse_fpt *fpt, uint32_t *offset,
1702 		 size_t *size)
1703 {
1704 	size_t num_part_header = fpt->count;
1705 	/* Move to the next structure which is FPT sub-partition entries */
1706 	struct cse_fpt_sub_part *fpt_sub_part = (struct cse_fpt_sub_part *)(fpt + 1);
1707 	for (size_t index = 0; index < num_part_header; index++) {
1708 		if (!strncmp(fpt_sub_part->signature, "FITC", 4)) {
1709 			*offset = fpt_sub_part->offset;
1710 			*size = fpt_sub_part->length;
1711 			return 0;
1712 		}
1713 		fpt_sub_part++;
1714 	}
1715 
1716 	return -1;
1717 }
1718 
1719 /*
1720  * Formula to calculate the GPR0 protection range as below:
1721  * Start: CSE Region Base Offset
1722  * End: Till the end of FITC sub-partition
1723  */
calculate_gpr0_range(char * image,int size,uint32_t * gpr0_start,uint32_t * gpr0_end)1724 static int calculate_gpr0_range(char *image, int size,
1725 		 uint32_t *gpr0_start, uint32_t *gpr0_end)
1726 {
1727 	struct frba *frba = find_frba(image, size);
1728 	if (!frba)
1729 		return -1;
1730 
1731 	struct region region = get_region(frba, REGION_ME);
1732 	if (region.size <= 0) {
1733 		fprintf(stderr, "Region %s is disabled in target\n",
1734 				region_name(REGION_ME));
1735 		return -1;
1736 	}
1737 
1738 	/* CSE Region Start */
1739 	uint32_t cse_region_start = region.base;
1740 	/* Get CSE Data Partition Offset */
1741 	uint8_t cse_data_offset = get_cse_data_partition_offset();
1742 	if (cse_data_offset == 0xff) {
1743 		fprintf(stderr, "Unsupported platform\n");
1744 		exit(EXIT_FAILURE);
1745 	}
1746 	uint32_t data_part_offset = *((uint32_t *)(image + cse_region_start + cse_data_offset));
1747 	/* Start reading the CSE Data Partition Table, also known as FPT */
1748 	uint32_t data_part_start = data_part_offset + cse_region_start;
1749 
1750 	uint32_t fitc_region_start = 0;
1751 	size_t fitc_region_size = 0;
1752 	/*
1753 	 * FPT holds entry for own FPT data structure also bunch of sub-partitions.
1754 	 * `FITC` is one of such sub-partition entry.
1755 	 */
1756 	if (parse_fitc_table(((struct cse_fpt *)(image + data_part_start)),
1757 			 &fitc_region_start, &fitc_region_size) < 0) {
1758 		fprintf(stderr, "Unable to find FITC entry\n");
1759 		return -1;
1760 	}
1761 
1762 	/*
1763 	 * GPR0 protection is configured to the following range:
1764 	 * start: CSE region base offset
1765 	 * end: Till the end of FITC sub-partition (i.e. CSE region + data partition offset +
1766 	 *       FITC sub partition offset + FITC sub partition size)
1767 	 */
1768 	*gpr0_start = cse_region_start;
1769 	*gpr0_end = (cse_region_start + data_part_offset +
1770 				 fitc_region_start + fitc_region_size) - 1;
1771 
1772 	return 0;
1773 }
1774 
get_enabled_gprd(char * image,int size)1775 static union gprd get_enabled_gprd(char *image, int size)
1776 {
1777 	union gprd enabled_gprd_reg;
1778 	uint32_t gpr0_range_start, gpr0_range_end;
1779 	enabled_gprd_reg.value = 0;
1780 	if (calculate_gpr0_range(image, size, &gpr0_range_start, &gpr0_range_end))
1781 		exit(EXIT_FAILURE);
1782 
1783 	enabled_gprd_reg.data.start = (gpr0_range_start >> 12) & 0x7fff;
1784 	enabled_gprd_reg.data.end = (gpr0_range_end >> 12) & 0x7fff;
1785 	enabled_gprd_reg.data.read_protect_en = 0;
1786 	enabled_gprd_reg.data.write_protect_en = 1;
1787 
1788 	return enabled_gprd_reg;
1789 }
1790 
enable_gpr0(const char * filename,char * image,int size)1791 static void enable_gpr0(const char *filename, char *image, int size)
1792 {
1793 	struct fpsba *fpsba = find_fpsba(image, size);
1794 	if (!fpsba)
1795 		exit(EXIT_FAILURE);
1796 
1797 	uint32_t gpr0_offset = get_gpr0_offset();
1798 	if (gpr0_offset == 0xffffffff) {
1799 		fprintf(stderr, "Enabling GPR0 not supported on this platform\n");
1800 		exit(EXIT_FAILURE);
1801 	}
1802 
1803 	union gprd reg;
1804 	/* If bit 31 is set then GPR0 protection is enable */
1805 	reg.value = fpsba->pchstrp[gpr0_offset];
1806 	if (reg.data.write_protect_en) {
1807 		printf("GPR0 protection is already enabled\n");
1808 		print_gpr0_range(reg);
1809 		return;
1810 	}
1811 
1812 	union gprd enabled_gprd = get_enabled_gprd(image, size);
1813 
1814 	fpsba->pchstrp[gpr0_offset] = enabled_gprd.value;
1815 	printf("Value at GPRD offset (%d) is 0x%08x\n", gpr0_offset, enabled_gprd.value);
1816 	print_gpr0_range(enabled_gprd);
1817 	write_image(filename, image, size);
1818 	printf("GPR0 protection is now enabled\n");
1819 }
1820 
is_gpr0_protected(char * image,int size)1821 static void is_gpr0_protected(char *image, int size)
1822 {
1823 	struct fpsba *fpsba = find_fpsba(image, size);
1824 	if (!fpsba)
1825 		exit(EXIT_FAILURE);
1826 
1827 	uint32_t gpr0_offset = get_gpr0_offset();
1828 	if (gpr0_offset == 0xffffffff) {
1829 		fprintf(stderr, "Checking GPR0 not supported on this platform\n");
1830 		exit(EXIT_FAILURE);
1831 	}
1832 	union gprd reg;
1833 	union gprd enabled_gprd = get_enabled_gprd(image, size);
1834 	reg.value = fpsba->pchstrp[gpr0_offset];
1835 
1836 	if (fpsba->pchstrp[gpr0_offset] == enabled_gprd.value)
1837 		printf("GPR0 status: Enabled\n\n");
1838 	else if (fpsba->pchstrp[gpr0_offset] == 0)
1839 		printf("GPR0 status: Disabled\n\n");
1840 	else
1841 		printf("ERROR: GPR0 setting is not expected\n\n");
1842 
1843 	printf("Value at GPRD offset (%d) is 0x%08x\n", gpr0_offset, fpsba->pchstrp[gpr0_offset]);
1844 	print_gpr0_range(reg);
1845 }
1846 
set_pchstrap(struct fpsba * fpsba,const struct fdbar * fdb,const int strap,const unsigned int value)1847 static void set_pchstrap(struct fpsba *fpsba, const struct fdbar *fdb, const int strap,
1848 			const unsigned int value)
1849 {
1850 	if (!fpsba || !fdb) {
1851 		fprintf(stderr, "Internal error\n");
1852 		exit(EXIT_FAILURE);
1853 	}
1854 
1855 	/* SoC Strap, aka PSL, aka ISL */
1856 	int SS = (fdb->flmap1 >> 24) & 0xff;
1857 	if (strap >= SS) {
1858 		fprintf(stderr, "Strap index %d out of range (max: %d)\n", strap, SS);
1859 		exit(EXIT_FAILURE);
1860 	}
1861 	fpsba->pchstrp[strap] = value;
1862 }
1863 
1864 /* Set the AltMeDisable (or HAP for >= IFD_VERSION_2) */
fpsba_set_altmedisable(struct fpsba * fpsba,struct fmsba * fmsba,bool altmedisable)1865 static void fpsba_set_altmedisable(struct fpsba *fpsba, struct fmsba *fmsba, bool altmedisable)
1866 {
1867 	if (ifd_version >= IFD_VERSION_2) {
1868 		printf("%sting the HAP bit to %s Intel ME...\n",
1869 			altmedisable ? "Set" : "Unset",
1870 			altmedisable ? "disable" : "enable");
1871 		if (altmedisable)
1872 			fpsba->pchstrp[0] |= (1 << 16);
1873 		else
1874 			fpsba->pchstrp[0] &= ~(1 << 16);
1875 	} else {
1876 		if (chipset >= CHIPSET_ICH8 && chipset <= CHIPSET_ICH10) {
1877 			printf("%sting the ICH_MeDisable, MCH_MeDisable, "
1878 			       "and MCH_AltMeDisable to %s Intel ME...\n",
1879 			       altmedisable ? "Set" : "Unset",
1880 			       altmedisable ? "disable" : "enable");
1881 			if (altmedisable) {
1882 				/* MCH_MeDisable */
1883 				fmsba->data[0] |= 1;
1884 				/* MCH_AltMeDisable */
1885 				fmsba->data[0] |= (1 << 7);
1886 				/* ICH_MeDisable */
1887 				fpsba->pchstrp[0] |= 1;
1888 			} else {
1889 				fmsba->data[0] &= ~1;
1890 				fmsba->data[0] &= ~(1 << 7);
1891 				fpsba->pchstrp[0] &= ~1;
1892 			}
1893 		} else {
1894 			printf("%sting the AltMeDisable to %s Intel ME...\n",
1895 				altmedisable ? "Set" : "Unset",
1896 				altmedisable ? "disable" : "enable");
1897 			if (altmedisable)
1898 				fpsba->pchstrp[10] |= (1 << 7);
1899 			else
1900 				fpsba->pchstrp[10] &= ~(1 << 7);
1901 		}
1902 	}
1903 }
1904 
inject_region(const char * filename,char * image,int size,unsigned int region_type,const char * region_fname)1905 static void inject_region(const char *filename, char *image, int size,
1906 			  unsigned int region_type, const char *region_fname)
1907 {
1908 	struct frba *frba = find_frba(image, size);
1909 	if (!frba)
1910 		exit(EXIT_FAILURE);
1911 
1912 	struct region region = get_region(frba, region_type);
1913 	if (region.size <= 0xfff) {
1914 		fprintf(stderr, "Region %s is disabled in target. Not injecting.\n",
1915 				region_name(region_type));
1916 		exit(EXIT_FAILURE);
1917 	}
1918 
1919 	int region_fd = open(region_fname, O_RDONLY | O_BINARY);
1920 	if (region_fd == -1) {
1921 		perror("Could not open file");
1922 		exit(EXIT_FAILURE);
1923 	}
1924 	struct stat buf;
1925 	if (fstat(region_fd, &buf) == -1) {
1926 		perror("Could not stat file");
1927 		exit(EXIT_FAILURE);
1928 	}
1929 	int region_size = buf.st_size;
1930 
1931 	printf("File %s is %d bytes\n", region_fname, region_size);
1932 
1933 	if (region_size > region.size) {
1934 		fprintf(stderr, "Region %s is %d(0x%x) bytes. File is %d(0x%x)"
1935 				" bytes. Not injecting.\n",
1936 				region_name(region_type), region.size,
1937 				region.size, region_size, region_size);
1938 		exit(EXIT_FAILURE);
1939 	}
1940 
1941 	int offset = 0;
1942 	if ((region_type == 1) && (region_size < region.size)) {
1943 		fprintf(stderr, "Region %s is %d(0x%x) bytes. File is %d(0x%x)"
1944 				" bytes. Padding before injecting.\n",
1945 				region_name(region_type), region.size,
1946 				region.size, region_size, region_size);
1947 		offset = region.size - region_size;
1948 		memset(image + region.base, 0xff, offset);
1949 	}
1950 
1951 	if (size < region.base + offset + region_size) {
1952 		fprintf(stderr, "Output file is too small. (%d < %d)\n",
1953 			size, region.base + offset + region_size);
1954 		exit(EXIT_FAILURE);
1955 	}
1956 
1957 	if (read(region_fd, image + region.base + offset, region_size) != region_size) {
1958 		perror("Could not read file");
1959 		exit(EXIT_FAILURE);
1960 	}
1961 
1962 	close(region_fd);
1963 
1964 	printf("Adding %s as the %s section of %s\n",
1965 	       region_fname, region_name(region_type), filename);
1966 	write_image(filename, image, size);
1967 }
1968 
next_pow2(unsigned int x)1969 static unsigned int next_pow2(unsigned int x)
1970 {
1971 	unsigned int y = 1;
1972 	if (x == 0)
1973 		return 0;
1974 	while (y <= x)
1975 		y = y << 1;
1976 
1977 	return y;
1978 }
1979 
1980 /**
1981  * Determine if two memory regions overlap.
1982  *
1983  * @param r1, r2 Memory regions to compare.
1984  * @return 0 if the two regions are separate
1985  * @return 1 if the two regions overlap
1986  */
regions_collide(const struct region * r1,const struct region * r2)1987 static int regions_collide(const struct region *r1, const struct region *r2)
1988 {
1989 	if ((r1->size == 0) || (r2->size == 0))
1990 		return 0;
1991 
1992 	/* r1 should be either completely below or completely above r2 */
1993 	return !(r1->limit < r2->base || r1->base > r2->limit);
1994 }
1995 
new_layout(const char * filename,char * image,int size,const char * layout_fname)1996 static void new_layout(const char *filename, char *image, int size,
1997 		const char *layout_fname)
1998 {
1999 	FILE *romlayout;
2000 	char tempstr[256];
2001 	char layout_region_name[256];
2002 	unsigned int i, j;
2003 	int region_number;
2004 	struct region current_regions[MAX_REGIONS];
2005 	struct region new_regions[MAX_REGIONS];
2006 	int new_extent = 0;
2007 	char *new_image;
2008 
2009 	/* load current descriptor map and regions */
2010 	struct frba *frba = find_frba(image, size);
2011 	if (!frba)
2012 		exit(EXIT_FAILURE);
2013 
2014 	for (i = 0; i < max_regions; i++) {
2015 		current_regions[i] = get_region(frba, i);
2016 		new_regions[i] = get_region(frba, i);
2017 	}
2018 
2019 	/* read new layout */
2020 	romlayout = fopen(layout_fname, "r");
2021 
2022 	if (!romlayout) {
2023 		perror("Could not read layout file.\n");
2024 		exit(EXIT_FAILURE);
2025 	}
2026 
2027 	while (!feof(romlayout)) {
2028 		char *tstr1, *tstr2;
2029 
2030 		if (2 != fscanf(romlayout, "%255s %255s\n", tempstr,
2031 					layout_region_name))
2032 			continue;
2033 
2034 		region_number = region_num(layout_region_name);
2035 		if (region_number < 0)
2036 			continue;
2037 
2038 		tstr1 = strtok(tempstr, ":");
2039 		tstr2 = strtok(NULL, ":");
2040 		if (!tstr1 || !tstr2) {
2041 			fprintf(stderr, "Could not parse layout file.\n");
2042 			exit(EXIT_FAILURE);
2043 		}
2044 		new_regions[region_number].base = strtol(tstr1,
2045 				(char **)NULL, 16);
2046 		new_regions[region_number].limit = strtol(tstr2,
2047 				(char **)NULL, 16);
2048 		new_regions[region_number].size =
2049 			new_regions[region_number].limit -
2050 			new_regions[region_number].base + 1;
2051 
2052 		if (new_regions[region_number].size < 0)
2053 			new_regions[region_number].size = 0;
2054 	}
2055 	fclose(romlayout);
2056 
2057 	/* check new layout */
2058 	for (i = 0; i < max_regions; i++) {
2059 		if (new_regions[i].size == 0)
2060 			continue;
2061 
2062 		if (new_regions[i].size < current_regions[i].size) {
2063 			printf("DANGER: Region %s is shrinking.\n",
2064 					region_name(i));
2065 			printf("    The region will be truncated to fit.\n");
2066 			printf("    This may result in an unusable image.\n");
2067 		}
2068 
2069 		for (j = i + 1; j < max_regions; j++) {
2070 			if (regions_collide(&new_regions[i], &new_regions[j])) {
2071 				fprintf(stderr, "Regions would overlap.\n");
2072 				exit(EXIT_FAILURE);
2073 			}
2074 		}
2075 
2076 		/* detect if the image size should grow */
2077 		if (new_extent < new_regions[i].limit)
2078 			new_extent = new_regions[i].limit;
2079 	}
2080 
2081 	/* check if the image is actually a Flash Descriptor region */
2082 	if (size == new_regions[0].size) {
2083 		printf("The image is a single Flash Descriptor:\n");
2084 		printf("    Only the descriptor will be modified\n");
2085 		new_extent = size;
2086 	} else {
2087 		new_extent = next_pow2(new_extent - 1);
2088 		if (new_extent != size) {
2089 			printf("The image has changed in size.\n");
2090 			printf("The old image is %d bytes.\n", size);
2091 			printf("The new image is %d bytes.\n", new_extent);
2092 		}
2093 	}
2094 
2095 	/* copy regions to a new image */
2096 	new_image = malloc(new_extent);
2097 	memset(new_image, 0xff, new_extent);
2098 	for (i = 0; i < max_regions; i++) {
2099 		int copy_size = new_regions[i].size;
2100 		int offset_current = 0, offset_new = 0;
2101 		const struct region *current = &current_regions[i];
2102 		const struct region *new = &new_regions[i];
2103 
2104 		if (new->size == 0)
2105 			continue;
2106 
2107 		if (new->size > current->size) {
2108 			/* copy from the end of the current region */
2109 			copy_size = current->size;
2110 			if (i == REGION_BIOS)
2111 				offset_new = new->size - current->size;
2112 		}
2113 
2114 		if ((i == REGION_BIOS) && (new->size < current->size)) {
2115 			/* copy BIOS region to the end of the new region */
2116 			offset_current = current->size - new->size;
2117 		}
2118 
2119 		if (size < current->base + offset_current + copy_size) {
2120 			printf("Skip descriptor %d (%s) (region missing in the old image)\n", i,
2121 				region_name(i));
2122 			continue;
2123 		};
2124 
2125 		printf("Copy Descriptor %d (%s) (%d bytes)\n", i,
2126 				region_name(i), copy_size);
2127 		printf("   from %08x+%08x:%08x (%10d)\n", current->base,
2128 				offset_current, current->limit, current->size);
2129 		printf("     to %08x+%08x:%08x (%10d)\n", new->base,
2130 				offset_new, new->limit, new->size);
2131 
2132 		memcpy(new_image + new->base + offset_new,
2133 				image + current->base + offset_current,
2134 				copy_size);
2135 	}
2136 
2137 	/* update new descriptor regions */
2138 	frba = find_frba(new_image, new_extent);
2139 	if (!frba)
2140 		exit(EXIT_FAILURE);
2141 
2142 	printf("Modify Flash Descriptor regions\n");
2143 	for (i = 1; i < max_regions; i++)
2144 		set_region(frba, i, &new_regions[i]);
2145 
2146 	write_image(filename, new_image, new_extent);
2147 	free(new_image);
2148 }
2149 
print_version(void)2150 static void print_version(void)
2151 {
2152 	printf("ifdtool v%s -- ", IFDTOOL_VERSION);
2153 	printf("Copyright (C) 2011 Google Inc.\n\n");
2154 	printf
2155 	    ("This program is free software: you can redistribute it and/or modify\n"
2156 	     "it under the terms of the GNU General Public License as published by\n"
2157 	     "the Free Software Foundation, version 2 of the License.\n\n"
2158 	     "This program is distributed in the hope that it will be useful,\n"
2159 	     "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
2160 	     "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
2161 	     "GNU General Public License for more details.\n\n");
2162 }
2163 
print_usage(const char * name)2164 static void print_usage(const char *name)
2165 {
2166 	printf("usage: %s [-vhdix?] <filename>\n", name);
2167 	printf("\n"
2168 	       "   -d | --dump:                          dump intel firmware descriptor\n"
2169 	       "   -f | --layout <filename>              dump regions into a flashrom layout file\n"
2170 	       "   -F | --fmap-layout <filename>         dump IFD regions into a fmap layout template (.fmd) file\n"
2171 	       "   -t | --validate                       Validate that the firmware descriptor layout matches the fmap layout\n"
2172 	       "   -x | --extract:                       extract intel fd modules\n"
2173 	       "   -i | --inject <region>:<module>       inject file <module> into region <region>\n"
2174 	       "   -n | --newlayout <filename>           update regions using a flashrom layout file\n"
2175 	       "   -O | --output <filename>              output filename\n"
2176 	       "   -s | --spifreq <17|20|30|33|48|50>    set the SPI frequency\n"
2177 	       "   -D | --density <512|1|2|4|8|16|32|64> set chip density (512 in KByte, others in MByte)\n"
2178 	       "   -C | --chip <0|1|2>                   select spi chip on which to operate\n"
2179 	       "                                         can only be used once per run:\n"
2180 	       "                                         0 - both chips (default), 1 - first chip, 2 - second chip\n"
2181 	       "   -e | --em100                          set SPI frequency to 20MHz and disable\n"
2182 	       "                                         Dual Output Fast Read Support\n"
2183 	       "   -l | --lock                           Lock firmware descriptor and ME region\n"
2184 	       "   -r | --read				 Enable CPU/BIOS read access for ME region\n"
2185 	       "   -u | --unlock                         Unlock firmware descriptor and ME region\n"
2186 	       "   -g | --gpr0-disable                   Disable GPR0 (Global Protected Range) register\n"
2187 	       "   -E | --gpr0-enable                    Enable GPR0 (Global Protected Range) register\n"
2188 	       "   -c | --gpr0-status                    Checking GPR0 (Global Protected Range) register status\n"
2189 	       "   -M | --altmedisable <0|1>             Set the MeDisable and AltMeDisable (or HAP for skylake or newer platform)\n"
2190 	       "                                         bits to disable ME\n"
2191 	       "   -p | --platform                       Add platform-specific quirks\n"
2192 	       "                                         adl    - Alder Lake\n"
2193 	       "                                         aplk   - Apollo Lake\n"
2194 	       "                                         cnl    - Cannon Lake\n"
2195 	       "                                         lbg    - Lewisburg PCH\n"
2196 	       "                                         dnv    - Denverton\n"
2197 	       "                                         ehl    - Elkhart Lake\n"
2198 	       "                                         glk    - Gemini Lake\n"
2199 	       "                                         icl    - Ice Lake\n"
2200 	       "                                         ifd2   - IFDv2 Platform\n"
2201 	       "                                         jsl    - Jasper Lake\n"
2202 	       "                                         mtl    - Meteor Lake\n"
2203 	       "                                         sklkbl - Sky Lake/Kaby Lake\n"
2204 	       "                                         tgl    - Tiger Lake\n"
2205 	       "                                         wbg    - Wellsburg\n"
2206 	       "   -S | --setpchstrap                    Write a PCH strap\n"
2207 	       "   -V | --newvalue                       The new value to write into PCH strap specified by -S\n"
2208 	       "   -v | --version:                       print the version\n"
2209 	       "   -h | --help:                          print this help\n\n"
2210 	       "<region> is one of Descriptor, BIOS, ME, GbE, Platform Data, Secondary BIOS, "
2211 	       "Device Exp1, EC, Device Exp2, IE, 10GbE_0, 10GbE_1, PTT\n"
2212 	       "\n");
2213 }
2214 
main(int argc,char * argv[])2215 int main(int argc, char *argv[])
2216 {
2217 	int opt, option_index = 0;
2218 	int mode_dump = 0, mode_extract = 0, mode_inject = 0, mode_spifreq = 0;
2219 	int mode_em100 = 0, mode_locked = 0, mode_unlocked = 0, mode_validate = 0;
2220 	int mode_layout = 0, mode_newlayout = 0, mode_density = 0, mode_setstrap = 0;
2221 	int mode_read = 0, mode_altmedisable = 0, altmedisable = 0, mode_fmap_template = 0;
2222 	int mode_gpr0_disable = 0, mode_gpr0_enable = 0, mode_gpr0_status = 0;
2223 	char *region_type_string = NULL, *region_fname = NULL;
2224 	const char *layout_fname = NULL;
2225 	char *new_filename = NULL;
2226 	int region_type = -1, inputfreq = 0;
2227 	unsigned int value = 0;
2228 	unsigned int pchstrap = 0;
2229 	unsigned int new_density = 0;
2230 	enum spi_frequency spifreq = SPI_FREQUENCY_20MHZ;
2231 
2232 	static const struct option long_options[] = {
2233 		{"dump", 0, NULL, 'd'},
2234 		{"layout", 1, NULL, 'f'},
2235 		{"fmap-template", 1, NULL, 'F'},
2236 		{"extract", 0, NULL, 'x'},
2237 		{"inject", 1, NULL, 'i'},
2238 		{"newlayout", 1, NULL, 'n'},
2239 		{"output", 1, NULL, 'O'},
2240 		{"spifreq", 1, NULL, 's'},
2241 		{"density", 1, NULL, 'D'},
2242 		{"chip", 1, NULL, 'C'},
2243 		{"altmedisable", 1, NULL, 'M'},
2244 		{"em100", 0, NULL, 'e'},
2245 		{"lock", 0, NULL, 'l'},
2246 		{"read", 0, NULL, 'r'},
2247 		{"unlock", 0, NULL, 'u'},
2248 		{"gpr0-disable", 0, NULL, 'g'},
2249 		{"gpr0-enable", 0, NULL, 'E'},
2250 		{"gpr0-status", 0, NULL, 'c'},
2251 		{"version", 0, NULL, 'v'},
2252 		{"help", 0, NULL, 'h'},
2253 		{"platform", 1, NULL, 'p'},
2254 		{"validate", 0, NULL, 't'},
2255 		{"setpchstrap", 1, NULL, 'S'},
2256 		{"newvalue", 1, NULL, 'V'},
2257 		{0, 0, 0, 0}
2258 	};
2259 
2260 	while ((opt = getopt_long(argc, argv, "S:V:df:F:D:C:M:xi:n:O:s:p:elrugEcvth?",
2261 					long_options, &option_index)) != EOF) {
2262 		switch (opt) {
2263 		case 'd':
2264 			mode_dump = 1;
2265 			break;
2266 		case 'S':
2267 			mode_setstrap = 1;
2268 			pchstrap = strtoul(optarg, NULL, 0);
2269 			break;
2270 		case 'V':
2271 			value = strtoul(optarg, NULL, 0);
2272 			break;
2273 		case 'f':
2274 			mode_layout = 1;
2275 			layout_fname = strdup(optarg);
2276 			if (!layout_fname) {
2277 				fprintf(stderr, "No layout file specified\n");
2278 				fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
2279 				exit(EXIT_FAILURE);
2280 			}
2281 			break;
2282 		case 'F':
2283 			mode_fmap_template = 1;
2284 			layout_fname = strdup(optarg);
2285 			if (!layout_fname) {
2286 				fprintf(stderr, "No layout file specified\n");
2287 				fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
2288 				exit(EXIT_FAILURE);
2289 			}
2290 			break;
2291 		case 'x':
2292 			mode_extract = 1;
2293 			break;
2294 		case 'i':
2295 			// separate type and file name
2296 			region_type_string = strdup(optarg);
2297 			region_fname = strchr(region_type_string, ':');
2298 			if (!region_fname) {
2299 				fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
2300 				exit(EXIT_FAILURE);
2301 			}
2302 			region_fname[0] = '\0';
2303 			region_fname++;
2304 			// Descriptor, BIOS, ME, GbE, Platform
2305 			// valid type?
2306 			if (!strcasecmp("Descriptor", region_type_string))
2307 				region_type = 0;
2308 			else if (!strcasecmp("BIOS", region_type_string))
2309 				region_type = 1;
2310 			else if (!strcasecmp("ME", region_type_string))
2311 				region_type = 2;
2312 			else if (!strcasecmp("GbE", region_type_string))
2313 				region_type = 3;
2314 			else if (!strcasecmp("Platform Data", region_type_string))
2315 				region_type = 4;
2316 			else if (!strcasecmp("Device Exp1", region_type_string))
2317 				region_type = 5;
2318 			else if (!strcasecmp("Secondary BIOS", region_type_string))
2319 				region_type = 6;
2320 			else if (!strcasecmp("Reserved", region_type_string))
2321 				region_type = 7;
2322 			else if (!strcasecmp("EC", region_type_string))
2323 				region_type = 8;
2324 			else if (!strcasecmp("Device Exp2", region_type_string))
2325 				region_type = 9;
2326 			else if (!strcasecmp("IE", region_type_string))
2327 				region_type = 10;
2328 			else if (!strcasecmp("10GbE_0", region_type_string))
2329 				region_type = 11;
2330 			else if (!strcasecmp("10GbE_1", region_type_string))
2331 				region_type = 12;
2332 			else if (!strcasecmp("PTT", region_type_string))
2333 				region_type = 15;
2334 			if (region_type == -1) {
2335 				fprintf(stderr, "No such region type: '%s'\n\n",
2336 					region_type_string);
2337 				fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
2338 				exit(EXIT_FAILURE);
2339 			}
2340 			mode_inject = 1;
2341 			break;
2342 		case 'n':
2343 			mode_newlayout = 1;
2344 			layout_fname = strdup(optarg);
2345 			if (!layout_fname) {
2346 				fprintf(stderr, "No layout file specified\n");
2347 				fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
2348 				exit(EXIT_FAILURE);
2349 			}
2350 			break;
2351 		case 'O':
2352 			new_filename = strdup(optarg);
2353 			if (!new_filename) {
2354 				fprintf(stderr, "No output filename specified\n");
2355 				fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
2356 				exit(EXIT_FAILURE);
2357 			}
2358 			break;
2359 		case 'D':
2360 			mode_density = 1;
2361 			new_density = strtoul(optarg, NULL, 0);
2362 			switch (new_density) {
2363 			case 512:
2364 				new_density = COMPONENT_DENSITY_512KB;
2365 				break;
2366 			case 1:
2367 				new_density = COMPONENT_DENSITY_1MB;
2368 				break;
2369 			case 2:
2370 				new_density = COMPONENT_DENSITY_2MB;
2371 				break;
2372 			case 4:
2373 				new_density = COMPONENT_DENSITY_4MB;
2374 				break;
2375 			case 8:
2376 				new_density = COMPONENT_DENSITY_8MB;
2377 				break;
2378 			case 16:
2379 				new_density = COMPONENT_DENSITY_16MB;
2380 				break;
2381 			case 32:
2382 				new_density = COMPONENT_DENSITY_32MB;
2383 				break;
2384 			case 64:
2385 				new_density = COMPONENT_DENSITY_64MB;
2386 				break;
2387 			case 0:
2388 				new_density = COMPONENT_DENSITY_UNUSED;
2389 				break;
2390 			default:
2391 				printf("error: Unknown density\n");
2392 				fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
2393 				exit(EXIT_FAILURE);
2394 			}
2395 			break;
2396 		case 'C':
2397 			selected_chip = strtol(optarg, NULL, 0);
2398 			if (selected_chip > 2) {
2399 				fprintf(stderr, "error: Invalid chip selection\n");
2400 				fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
2401 				exit(EXIT_FAILURE);
2402 			}
2403 			break;
2404 		case 'M':
2405 			mode_altmedisable = 1;
2406 			altmedisable = strtol(optarg, NULL, 0);
2407 			if (altmedisable > 1) {
2408 				fprintf(stderr, "error: Illegal value\n");
2409 				fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
2410 				exit(EXIT_FAILURE);
2411 			}
2412 			break;
2413 		case 's':
2414 			// Parse the requested SPI frequency
2415 			inputfreq = strtol(optarg, NULL, 0);
2416 			switch (inputfreq) {
2417 			case 17:
2418 				spifreq = SPI_FREQUENCY_17MHZ;
2419 				break;
2420 			case 20:
2421 				spifreq = SPI_FREQUENCY_20MHZ;
2422 				break;
2423 			case 30:
2424 				spifreq = SPI_FREQUENCY_50MHZ_30MHZ;
2425 				break;
2426 			case 33:
2427 				spifreq = SPI_FREQUENCY_33MHZ;
2428 				break;
2429 			case 48:
2430 				spifreq = SPI_FREQUENCY_48MHZ;
2431 				break;
2432 			case 50:
2433 				spifreq = SPI_FREQUENCY_50MHZ_30MHZ;
2434 				break;
2435 			default:
2436 				fprintf(stderr, "Invalid SPI Frequency: %d\n",
2437 					inputfreq);
2438 				fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
2439 				exit(EXIT_FAILURE);
2440 			}
2441 			mode_spifreq = 1;
2442 			break;
2443 		case 'e':
2444 			mode_em100 = 1;
2445 			break;
2446 		case 'l':
2447 			mode_locked = 1;
2448 			if (mode_unlocked == 1) {
2449 				fprintf(stderr, "Locking/Unlocking FD and ME are mutually exclusive\n");
2450 				exit(EXIT_FAILURE);
2451 			}
2452 			break;
2453 		case 'r':
2454 			mode_read = 1;
2455 			break;
2456 		case 'u':
2457 			mode_unlocked = 1;
2458 			if (mode_locked == 1) {
2459 				fprintf(stderr, "Locking/Unlocking FD and ME are mutually exclusive\n");
2460 				exit(EXIT_FAILURE);
2461 			}
2462 			break;
2463 		case 'g':
2464 			mode_gpr0_disable = 1;
2465 			break;
2466 		case 'E':
2467 			mode_gpr0_enable = 1;
2468 			break;
2469 		case 'c':
2470 			mode_gpr0_status = 1;
2471 			break;
2472 		case 'p':
2473 			if (!strcmp(optarg, "aplk")) {
2474 				platform = PLATFORM_APL;
2475 			} else if (!strcmp(optarg, "cnl")) {
2476 				platform = PLATFORM_CNL;
2477 			} else if (!strcmp(optarg, "lbg")) {
2478 				platform = PLATFORM_LBG;
2479 			} else if (!strcmp(optarg, "dnv")) {
2480 				platform = PLATFORM_DNV;
2481 			} else if (!strcmp(optarg, "ehl")) {
2482 				platform = PLATFORM_EHL;
2483 			} else if (!strcmp(optarg, "glk")) {
2484 				platform = PLATFORM_GLK;
2485 			} else if (!strcmp(optarg, "icl")) {
2486 				platform = PLATFORM_ICL;
2487 			} else if (!strcmp(optarg, "jsl")) {
2488 				platform = PLATFORM_JSL;
2489 			} else if (!strcmp(optarg, "sklkbl")) {
2490 				platform = PLATFORM_SKLKBL;
2491 			} else if (!strcmp(optarg, "tgl")) {
2492 				platform = PLATFORM_TGL;
2493 			} else if (!strcmp(optarg, "adl")) {
2494 				platform = PLATFORM_ADL;
2495 			} else if (!strcmp(optarg, "ifd2")) {
2496 				platform = PLATFORM_IFD2;
2497 			} else if (!strcmp(optarg, "mtl")) {
2498 				platform = PLATFORM_MTL;
2499 			} else if (!strcmp(optarg, "ptl")) {
2500 				platform = PLATFORM_PTL;
2501 			} else if (!strcmp(optarg, "wbg")) {
2502 				platform = PLATFORM_WBG;
2503 			} else {
2504 				fprintf(stderr, "Unknown platform: %s\n", optarg);
2505 				exit(EXIT_FAILURE);
2506 			}
2507 			break;
2508 		case 't':
2509 			mode_validate = 1;
2510 			break;
2511 		case 'v':
2512 			print_version();
2513 			exit(EXIT_SUCCESS);
2514 			break;
2515 		case 'h':
2516 		case '?':
2517 		default:
2518 			print_usage(argv[0]);
2519 			exit(EXIT_SUCCESS);
2520 			break;
2521 		}
2522 	}
2523 
2524 	if ((mode_dump + mode_layout + mode_fmap_template + mode_extract + mode_inject +
2525 			mode_setstrap + mode_newlayout + (mode_spifreq | mode_em100 |
2526 			mode_unlocked | mode_locked) + mode_altmedisable + mode_validate +
2527 			(mode_gpr0_disable | mode_gpr0_enable) + mode_gpr0_status) > 1) {
2528 		fprintf(stderr, "You may not specify more than one mode.\n\n");
2529 		fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
2530 		exit(EXIT_FAILURE);
2531 	}
2532 
2533 	if ((mode_dump + mode_layout + mode_fmap_template + mode_extract + mode_inject +
2534 			mode_setstrap + mode_newlayout + mode_spifreq + mode_em100 +
2535 			mode_locked + mode_unlocked + mode_density + mode_altmedisable +
2536 			mode_validate + (mode_gpr0_disable | mode_gpr0_enable) + mode_gpr0_status) == 0) {
2537 		fprintf(stderr, "You need to specify a mode.\n\n");
2538 		fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
2539 		exit(EXIT_FAILURE);
2540 	}
2541 
2542 	if (optind + 1 != argc) {
2543 		fprintf(stderr, "You need to specify a file.\n\n");
2544 		fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
2545 		exit(EXIT_FAILURE);
2546 	}
2547 
2548 	if (platform == -1)
2549 		fprintf(stderr, "Warning: No platform specified. Output may be incomplete\n");
2550 
2551 	char *filename = argv[optind];
2552 	int bios_fd = open(filename, O_RDONLY | O_BINARY);
2553 	if (bios_fd == -1) {
2554 		perror("Could not open file");
2555 		exit(EXIT_FAILURE);
2556 	}
2557 	struct stat buf;
2558 	if (fstat(bios_fd, &buf) == -1) {
2559 		perror("Could not stat file");
2560 		exit(EXIT_FAILURE);
2561 	}
2562 	int size = buf.st_size;
2563 
2564 	printf("File %s is %d bytes\n", filename, size);
2565 
2566 	char *image = malloc(size);
2567 	if (!image) {
2568 		printf("Out of memory.\n");
2569 		exit(EXIT_FAILURE);
2570 	}
2571 
2572 	if (read(bios_fd, image, size) != size) {
2573 		perror("Could not read file");
2574 		exit(EXIT_FAILURE);
2575 	}
2576 
2577 	close(bios_fd);
2578 
2579 	// generate new filename
2580 	if (new_filename == NULL) {
2581 		new_filename = (char *)malloc((strlen(filename) + 5) * sizeof(char));
2582 		if (!new_filename) {
2583 			printf("Out of memory.\n");
2584 			exit(EXIT_FAILURE);
2585 		}
2586 		// - 5: leave room for ".new\0"
2587 		strcpy(new_filename, filename);
2588 		strcat(new_filename, ".new");
2589 	}
2590 
2591 	check_ifd_version(image, size);
2592 
2593 	if (mode_dump)
2594 		dump_fd(image, size);
2595 
2596 	if (mode_layout)
2597 		dump_flashrom_layout(image, size, layout_fname);
2598 
2599 	if (mode_fmap_template)
2600 		create_fmap_template(image, size, layout_fname);
2601 
2602 	if (mode_extract)
2603 		write_regions(image, size);
2604 
2605 	if (mode_validate)
2606 		validate_layout(image, size);
2607 
2608 	if (mode_inject)
2609 		inject_region(new_filename, image, size, region_type,
2610 				region_fname);
2611 
2612 	if (mode_newlayout)
2613 		new_layout(new_filename, image, size, layout_fname);
2614 
2615 	if (mode_spifreq)
2616 		set_spi_frequency(new_filename, image, size, spifreq);
2617 
2618 	if (mode_density)
2619 		set_chipdensity(new_filename, image, size, new_density);
2620 
2621 	if (mode_em100)
2622 		set_em100_mode(new_filename, image, size);
2623 
2624 	if (mode_locked)
2625 		lock_descriptor(new_filename, image, size);
2626 
2627 	if (mode_read)
2628 		enable_cpu_read_me(new_filename, image, size);
2629 
2630 	if (mode_unlocked)
2631 		unlock_descriptor(new_filename, image, size);
2632 
2633 	if (mode_gpr0_disable)
2634 		disable_gpr0(new_filename, image, size);
2635 
2636 	if (mode_gpr0_enable)
2637 		enable_gpr0(new_filename, image, size);
2638 
2639 	if (mode_gpr0_status)
2640 		is_gpr0_protected(image, size);
2641 
2642 	if (mode_setstrap) {
2643 		struct fpsba *fpsba = find_fpsba(image, size);
2644 		const struct fdbar *fdb = find_fd(image, size);
2645 		set_pchstrap(fpsba, fdb, pchstrap, value);
2646 		write_image(new_filename, image, size);
2647 	}
2648 
2649 	if (mode_altmedisable) {
2650 		struct fpsba *fpsba = find_fpsba(image, size);
2651 		struct fmsba *fmsba = find_fmsba(image, size);
2652 		fpsba_set_altmedisable(fpsba, fmsba, altmedisable);
2653 		write_image(new_filename, image, size);
2654 	}
2655 
2656 	free(new_filename);
2657 	free(image);
2658 
2659 	return 0;
2660 }
2661