Bug Summary

File:util/ifdtool/ifdtool.c
Warning:line 2496, column 7
Potential leak of memory pointed to by 'region_type_string'

Annotated Source Code

Press '?' to see keyboard shortcuts

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