ifdtool: Improve PCH strap handling

Read the PCH Strap Length field in FLMAP1 as described in the
"SPI Programming Guide" and print the number of fields specified there.

This code dumps the following straps:
* Intel GM45: 8 straps
* Intel C216: 72 straps
* Intel C240: 360 straps

Add a new function to easily set PCH straps, which is useful for debugging.

Change-Id: Ieb7891b214d82c984379794de9b3fe1a6d0d3466
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/41693
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Philipp Hug <philipp@hug.cx>
Reviewed-by: Christian Walter <christian.walter@9elements.com>
Reviewed-by: Philipp Deppenwiese <zaolin.daisuki@gmail.com>
This commit is contained in:
Patrick Rudolph 2020-05-25 12:18:11 +02:00 committed by Patrick Georgi
parent aeacf8b444
commit 802cbee789
2 changed files with 54 additions and 11 deletions

View File

@ -145,7 +145,11 @@ static fpsba_t *find_fpsba(char *image, int size)
return NULL; return NULL;
fpsba_t *fpsba = fpsba_t *fpsba =
(fpsba_t *) (image + (((fdb->flmap1 >> 16) & 0xff) << 4)); (fpsba_t *) (image + (((fdb->flmap1 >> 16) & 0xff) << 4));
return PTR_IN_RANGE(fpsba, image, size) ? fpsba : NULL;
int SSL = ((fdb->flmap1 >> 24) & 0xff) * sizeof(uint32_t);
if ((((char *)fpsba) + SSL) >= (image + size))
return NULL;
return fpsba;
} }
static fmsba_t *find_fmsba(char *image, int size) static fmsba_t *find_fmsba(char *image, int size)
@ -516,13 +520,15 @@ static void dump_fcba(const fcba_t *fcba)
(fcba->flpb & 0xfff) << 12); (fcba->flpb & 0xfff) << 12);
} }
static void dump_fpsba(const fpsba_t *fpsba) static void dump_fpsba(const fdbar_t *fdb, const fpsba_t *fpsba)
{ {
unsigned int i; unsigned int i;
/* SoC Strap Length, aka PSL, aka ISL */
unsigned int SSL = ((fdb->flmap1 >> 24) & 0xff) * sizeof(uint32_t);
printf("Found PCH Strap Section\n"); printf("Found PCH Strap Section\n");
for (i = 0; i < ARRAY_SIZE(fpsba->pchstrp); i++) for (i = 0; i < SSL; i++)
printf("PCHSTRP%u:%s 0x%08x\n", i, printf("PCHSTRP%-3u: 0x%08x\n", i, fpsba->pchstrp[i]);
i < 10 ? " " : "", fpsba->pchstrp[i]);
if (ifd_version >= IFD_VERSION_2) { if (ifd_version >= IFD_VERSION_2) {
printf("HAP bit is %sset\n", printf("HAP bit is %sset\n",
@ -751,7 +757,7 @@ static void dump_fd(char *image, int size)
if (frba && fcba && fpsba && fmba && fmsba) { if (frba && fcba && fpsba && fmba && fmsba) {
dump_frba(frba); dump_frba(frba);
dump_fcba(fcba); dump_fcba(fcba);
dump_fpsba(fpsba); dump_fpsba(fdb, fpsba);
dump_fmba(fmba); dump_fmba(fmba);
dump_fmsba(fmsba); dump_fmsba(fmsba);
} else { } else {
@ -1099,6 +1105,23 @@ static void unlock_descriptor(const char *filename, char *image, int size)
write_image(filename, image, size); write_image(filename, image, size);
} }
static void set_pchstrap(fpsba_t *fpsba, const fdbar_t *fdb, const int strap,
const unsigned int value)
{
if (!fpsba || !fdb) {
fprintf(stderr, "Internal error\n");
exit(EXIT_FAILURE);
}
/* SoC Strap Length, aka PSL, aka ISL */
int SSL = ((fdb->flmap1 >> 24) & 0xff) * sizeof(uint32_t);
if (strap >= SSL) {
fprintf(stderr, "Strap index %d out of range (max: %d)\n", strap, SSL);
exit(EXIT_FAILURE);
}
fpsba->pchstrp[strap] = value;
}
/* Set the AltMeDisable (or HAP for >= IFD_VERSION_2) */ /* Set the AltMeDisable (or HAP for >= IFD_VERSION_2) */
static void fpsba_set_altmedisable(fpsba_t *fpsba, fmsba_t *fmsba, bool altmedisable) static void fpsba_set_altmedisable(fpsba_t *fpsba, fmsba_t *fmsba, bool altmedisable)
{ {
@ -1428,6 +1451,8 @@ static void print_usage(const char *name)
" cnl - Cannon Lake\n" " cnl - Cannon Lake\n"
" glk - Gemini Lake\n" " glk - Gemini Lake\n"
" sklkbl - Skylake/Kaby Lake\n" " sklkbl - Skylake/Kaby Lake\n"
" -S | --setpchstrap Write a PCH strap\n"
" -V | --newvalue The new value to write into PCH strap specified by -S\n"
" -v | --version: print the version\n" " -v | --version: print the version\n"
" -h | --help: print this help\n\n" " -h | --help: print this help\n\n"
"<region> is one of Descriptor, BIOS, ME, GbE, Platform\n" "<region> is one of Descriptor, BIOS, ME, GbE, Platform\n"
@ -1439,12 +1464,14 @@ int main(int argc, char *argv[])
int opt, option_index = 0; int opt, option_index = 0;
int mode_dump = 0, mode_extract = 0, mode_inject = 0, mode_spifreq = 0; int mode_dump = 0, mode_extract = 0, mode_inject = 0, mode_spifreq = 0;
int mode_em100 = 0, mode_locked = 0, mode_unlocked = 0, mode_validate = 0; int mode_em100 = 0, mode_locked = 0, mode_unlocked = 0, mode_validate = 0;
int mode_layout = 0, mode_newlayout = 0, mode_density = 0; int mode_layout = 0, mode_newlayout = 0, mode_density = 0, mode_setstrap = 0;
int mode_altmedisable = 0, altmedisable = 0; int mode_altmedisable = 0, altmedisable = 0;
char *region_type_string = NULL, *region_fname = NULL; char *region_type_string = NULL, *region_fname = NULL;
const char *layout_fname = NULL; const char *layout_fname = NULL;
char *new_filename = NULL; char *new_filename = NULL;
int region_type = -1, inputfreq = 0; int region_type = -1, inputfreq = 0;
unsigned int value = 0;
unsigned int pchstrap = 0;
unsigned int new_density = 0; unsigned int new_density = 0;
enum spi_frequency spifreq = SPI_FREQUENCY_20MHZ; enum spi_frequency spifreq = SPI_FREQUENCY_20MHZ;
@ -1466,15 +1493,24 @@ int main(int argc, char *argv[])
{"help", 0, NULL, 'h'}, {"help", 0, NULL, 'h'},
{"platform", 0, NULL, 'p'}, {"platform", 0, NULL, 'p'},
{"validate", 0, NULL, 't'}, {"validate", 0, NULL, 't'},
{"setpchstrap", 1, NULL, 'S'},
{"newvalue", 1, NULL, 'V'},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
while ((opt = getopt_long(argc, argv, "df:D:C:M:xi:n:O:s:p:eluvth?", while ((opt = getopt_long(argc, argv, "S:V:df:D:C:M:xi:n:O:s:p:eluvth?",
long_options, &option_index)) != EOF) { long_options, &option_index)) != EOF) {
switch (opt) { switch (opt) {
case 'd': case 'd':
mode_dump = 1; mode_dump = 1;
break; break;
case 'S':
mode_setstrap = 1;
pchstrap = strtoul(optarg, NULL, 0);
break;
case 'V':
value = strtoul(optarg, NULL, 0);
break;
case 'f': case 'f':
mode_layout = 1; mode_layout = 1;
layout_fname = strdup(optarg); layout_fname = strdup(optarg);
@ -1674,7 +1710,7 @@ int main(int argc, char *argv[])
} }
} }
if ((mode_dump + mode_layout + mode_extract + mode_inject + if ((mode_dump + mode_layout + mode_extract + mode_inject + mode_setstrap +
mode_newlayout + (mode_spifreq | mode_em100 | mode_unlocked | mode_newlayout + (mode_spifreq | mode_em100 | mode_unlocked |
mode_locked) + mode_altmedisable + mode_validate) > 1) { mode_locked) + mode_altmedisable + mode_validate) > 1) {
fprintf(stderr, "You may not specify more than one mode.\n\n"); fprintf(stderr, "You may not specify more than one mode.\n\n");
@ -1682,7 +1718,7 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if ((mode_dump + mode_layout + mode_extract + mode_inject + if ((mode_dump + mode_layout + mode_extract + mode_inject + mode_setstrap +
mode_newlayout + mode_spifreq + mode_em100 + mode_locked + mode_newlayout + mode_spifreq + mode_em100 + mode_locked +
mode_unlocked + mode_density + mode_altmedisable + mode_validate) == 0) { mode_unlocked + mode_density + mode_altmedisable + mode_validate) == 0) {
fprintf(stderr, "You need to specify a mode.\n\n"); fprintf(stderr, "You need to specify a mode.\n\n");
@ -1772,6 +1808,13 @@ int main(int argc, char *argv[])
if (mode_unlocked) if (mode_unlocked)
unlock_descriptor(new_filename, image, size); unlock_descriptor(new_filename, image, size);
if (mode_setstrap) {
fpsba_t *fpsba = find_fpsba(image, size);
const fdbar_t *fdb = find_fd(image, size);
set_pchstrap(fpsba, fdb, pchstrap, value);
write_image(new_filename, image, size);
}
if (mode_altmedisable) { if (mode_altmedisable) {
fpsba_t *fpsba = find_fpsba(image, size); fpsba_t *fpsba = find_fpsba(image, size);
fmsba_t *fmsba = find_fmsba(image, size); fmsba_t *fmsba = find_fmsba(image, size);

View File

@ -105,7 +105,7 @@ typedef struct {
} __attribute__((packed)) fcba_t; } __attribute__((packed)) fcba_t;
// pch strap // pch strap
#define MAX_PCHSTRP 18 #define MAX_PCHSTRP 1024
typedef struct { typedef struct {
uint32_t pchstrp[MAX_PCHSTRP]; uint32_t pchstrp[MAX_PCHSTRP];