summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorReka Norman <rekanorman@google.com>2023-10-03 09:47:01 +1100
committerSubrata Banik <subratabanik@google.com>2024-01-05 05:12:23 +0000
commitc64be928de8421ea1bb2f575e32d74d58e41d659 (patch)
treebf45f43f69740640cd97be5787a15cc5bdcfd2c6 /util
parent0f910e7db903fe07698f01685b880065b2f6ca4e (diff)
util/ifdtool: Add support for disabling GPR0
On ChromeOS devices with updateable CSE firmware, the GPR0 (Global Protected Range) register is used to ensure the CSE RO is write protected even when the FLMSTR-based protection is temporarily disabled by coreboot to allow updating the CSE RW. For more details see Documentation/soc/intel/cse_fw_update/cse_fw_update.md Therefore to allow modifying the CSE firmware from the CPU, the descriptor must have both the FLMSTR-based protection disabled (which can be done using ifdtool --unlock), and GPR0 disabled. Add an ifdtool option for disabling GPR0. For now I've added support for all platforms for which I have the SPI programming guide. Support for more platforms can be added in the future if needed. BUG=b:270275115 TEST=Run `ifdtool -p adl -g image.bin -O image-unlocked.bin` on a locked craask image, check the GPR0 field is set to 0. Change-Id: Iee13ce0b702b3c7a443501cb4fc282580869d03a Signed-off-by: Reka Norman <rekanorman@chromium.org> Reviewed-on: https://review.coreboot.org/c/coreboot/+/79788 Reviewed-by: Subrata Banik <subratabanik@google.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'util')
-rw-r--r--util/ifdtool/ifdtool.c50
1 files changed, 47 insertions, 3 deletions
diff --git a/util/ifdtool/ifdtool.c b/util/ifdtool/ifdtool.c
index 43451b165f..7d69bcf9ff 100644
--- a/util/ifdtool/ifdtool.c
+++ b/util/ifdtool/ifdtool.c
@@ -1497,6 +1497,39 @@ static void unlock_descriptor(const char *filename, char *image, int size)
write_image(filename, image, size);
}
+static void disable_gpr0(const char *filename, char *image, int size)
+{
+ struct fpsba *fpsba = find_fpsba(image, size);
+ if (!fpsba)
+ exit(EXIT_FAILURE);
+
+ /* Offset expressed as number of 32-bit fields from FPSBA */
+ uint32_t gpr0_offset;
+ switch (platform) {
+ case PLATFORM_CNL:
+ gpr0_offset = 0x10;
+ break;
+ case PLATFORM_JSL:
+ gpr0_offset = 0x12;
+ break;
+ case PLATFORM_TGL:
+ case PLATFORM_ADL:
+ gpr0_offset = 0x15;
+ break;
+ case PLATFORM_MTL:
+ gpr0_offset = 0x40;
+ break;
+ default:
+ fprintf(stderr, "Disabling GPR0 not supported on this platform\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* 0 means GPR0 protection is disabled */
+ fpsba->pchstrp[gpr0_offset] = 0;
+
+ write_image(filename, image, size);
+}
+
static void set_pchstrap(struct fpsba *fpsba, const struct fdbar *fdb, const int strap,
const unsigned int value)
{
@@ -1836,6 +1869,7 @@ static void print_usage(const char *name)
" -l | --lock Lock firmware descriptor and ME region\n"
" -r | --read Enable CPU/BIOS read access for ME region\n"
" -u | --unlock Unlock firmware descriptor and ME region\n"
+ " -g | --gpr0-disable Disable GPR0 (Global Protected Range) register\n"
" -M | --altmedisable <0|1> Set the MeDisable and AltMeDisable (or HAP for skylake or newer platform)\n"
" bits to disable ME\n"
" -p | --platform Add platform-specific quirks\n"
@@ -1869,6 +1903,7 @@ int main(int argc, char *argv[])
int mode_em100 = 0, mode_locked = 0, mode_unlocked = 0, mode_validate = 0;
int mode_layout = 0, mode_newlayout = 0, mode_density = 0, mode_setstrap = 0;
int mode_read = 0, mode_altmedisable = 0, altmedisable = 0, mode_fmap_template = 0;
+ int mode_gpr0_disable = 0;
char *region_type_string = NULL, *region_fname = NULL;
const char *layout_fname = NULL;
char *new_filename = NULL;
@@ -1894,6 +1929,7 @@ int main(int argc, char *argv[])
{"lock", 0, NULL, 'l'},
{"read", 0, NULL, 'r'},
{"unlock", 0, NULL, 'u'},
+ {"gpr0-disable", 0, NULL, 'g'},
{"version", 0, NULL, 'v'},
{"help", 0, NULL, 'h'},
{"platform", 0, NULL, 'p'},
@@ -1903,7 +1939,7 @@ int main(int argc, char *argv[])
{0, 0, 0, 0}
};
- while ((opt = getopt_long(argc, argv, "S:V:df:F:D:C:M:xi:n:O:s:p:elruvth?",
+ while ((opt = getopt_long(argc, argv, "S:V:df:F:D:C:M:xi:n:O:s:p:elrugvth?",
long_options, &option_index)) != EOF) {
switch (opt) {
case 'd':
@@ -2106,6 +2142,9 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
break;
+ case 'g':
+ mode_gpr0_disable = 1;
+ break;
case 'p':
if (!strcmp(optarg, "aplk")) {
platform = PLATFORM_APL;
@@ -2158,7 +2197,8 @@ int main(int argc, char *argv[])
if ((mode_dump + mode_layout + mode_fmap_template + mode_extract + mode_inject +
mode_setstrap + mode_newlayout + (mode_spifreq | mode_em100 |
- mode_unlocked | mode_locked) + mode_altmedisable + mode_validate) > 1) {
+ mode_unlocked | mode_locked) + mode_altmedisable + mode_validate +
+ mode_gpr0_disable) > 1) {
fprintf(stderr, "You may not specify more than one mode.\n\n");
fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
exit(EXIT_FAILURE);
@@ -2166,7 +2206,8 @@ int main(int argc, char *argv[])
if ((mode_dump + mode_layout + mode_fmap_template + mode_extract + mode_inject +
mode_setstrap + mode_newlayout + mode_spifreq + mode_em100 +
- mode_locked + mode_unlocked + mode_density + mode_altmedisable + mode_validate) == 0) {
+ mode_locked + mode_unlocked + mode_density + mode_altmedisable +
+ mode_validate + mode_gpr0_disable) == 0) {
fprintf(stderr, "You need to specify a mode.\n\n");
fprintf(stderr, "run '%s -h' for usage\n", argv[0]);
exit(EXIT_FAILURE);
@@ -2263,6 +2304,9 @@ int main(int argc, char *argv[])
if (mode_unlocked)
unlock_descriptor(new_filename, image, size);
+ if (mode_gpr0_disable)
+ disable_gpr0(new_filename, image, size);
+
if (mode_setstrap) {
struct fpsba *fpsba = find_fpsba(image, size);
const struct fdbar *fdb = find_fd(image, size);