Subrata Banik has submitted this change. ( https://review.coreboot.org/c/coreboot/+/79788?usp=email )
Change subject: util/ifdtool: Add support for disabling GPR0 ......................................................................
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 --- M util/ifdtool/ifdtool.c 1 file changed, 47 insertions(+), 3 deletions(-)
Approvals: Subrata Banik: Looks good to me, approved build bot (Jenkins): Verified
diff --git a/util/ifdtool/ifdtool.c b/util/ifdtool/ifdtool.c index 43451b1..7d69bcf 100644 --- a/util/ifdtool/ifdtool.c +++ b/util/ifdtool/ifdtool.c @@ -1497,6 +1497,39 @@ 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 @@ " -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 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 @@ {"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 @@ {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 @@ exit(EXIT_FAILURE); } break; + case 'g': + mode_gpr0_disable = 1; + break; case 'p': if (!strcmp(optarg, "aplk")) { platform = PLATFORM_APL; @@ -2158,7 +2197,8 @@
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 @@
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 @@ 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);