Tim Wawrzynczak has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/56679 )
Change subject: mb/google/brya: Ensure descriptor is writable before writing ......................................................................
mb/google/brya: Ensure descriptor is writable before writing
Before updating the descriptor region in bootblock, ensure that the region is writeable to avoid infinite boot loops.
BUG=b:188577893
Change-Id: I09613d569ffc92fc3b7334bc30628c4f88955250 Signed-off-by: Tim Wawrzynczak twawrzynczak@chromium.org --- M src/mainboard/google/brya/bootblock.c 1 file changed, 74 insertions(+), 35 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/79/56679/1
diff --git a/src/mainboard/google/brya/bootblock.c b/src/mainboard/google/brya/bootblock.c index ac0dc32..4b655c0 100644 --- a/src/mainboard/google/brya/bootblock.c +++ b/src/mainboard/google/brya/bootblock.c @@ -1,57 +1,97 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */
+#include <arch/mmio.h> #include <baseboard/variants.h> #include <bootblock_common.h> +#include <cf9_reset.h> #include <console/console.h> -#include <fmap.h> #include <commonlib/region.h> #include <console/console.h> #include <cpu/intel/cpu_ids.h> +#include <fmap.h> #include <intelblocks/pmclib.h> -#include <cf9_reset.h> +#include <types.h>
#define SI_DESC_REGION "SI_DESC" #define SI_DESC_REGION_SZ 4096 #define PMC_DESC_7_BYTE3 0xc32 +#define FLASH_SIGN_OFFSET 0x10 +#define FLMSTR1 0x80 +#define FLASH_VAL_SIGN 0xFF0A55A +#define FLMSTR_WR_SHIFT_V2 20
-/* It updates PMC Descriptor in the Descriptor Region */ -static void configure_pmc_descriptor(void) +/* It checks whether host(Flash Master 1) has write access to the Descriptor Region or not */ +static int is_descriptor_writeable(uint8_t *desc) +{ + /* Check flash has valid signature */ + if (read32((void *)(desc + FLASH_SIGN_OFFSET)) != FLASH_VAL_SIGN) { + printk(BIOS_DEBUG, "Flash Descriptor is not valid\n"); + return 0; + } + + /* Check host has write access to the Descriptor Region */ + if (!((read32((void *)(desc + FLMSTR1)) >> FLMSTR_WR_SHIFT_V2) & BIT(0))) { + printk(BIOS_DEBUG, "Host doesn't have write access to Descriptor Region\n"); + return 0; + } + + return 1; +} + +static bool read_descriptor(struct region_device *rdev, uint8_t *buf) +{ + if (fmap_locate_area_as_rdev_rw(SI_DESC_REGION, rdev) < 0) { + printk(BIOS_ERR, "Failed to locate %s in the FMAP\n", SI_DESC_REGION); + return false; + } + + if (rdev_readat(rdev, buf, 0, SI_DESC_REGION_SZ) != SI_DESC_REGION_SZ) { + printk(BIOS_ERR, "Failed to read Descriptor Region from SPI Flash\n"); + return false; + } + + return true; +} + +static bool update_for_a0(uint8_t *desc) +{ + if (cpu_get_cpuid() != CPUID_ALDERLAKE_A0 || desc[PMC_DESC_7_BYTE3] != 0x40) { + printk(BIOS_DEBUG, "Update for A0 Si is not required!\n"); + return false; + } + + desc[PMC_DESC_7_BYTE3] = 0x44; + return true; +} + +static bool write_descriptor(struct region_device *rdev, uint8_t *desc) +{ + if (rdev_eraseat(rdev, 0, SI_DESC_REGION_SZ) != SI_DESC_REGION_SZ) + return false; + + return rdev_writeat(rdev, desc, 0, SI_DESC_REGION_SZ) == SI_DESC_REGION_SZ; +} + +static void configure_descriptor(void) { uint8_t si_desc_buf[SI_DESC_REGION_SZ]; struct region_device desc_rdev;
- if (fmap_locate_area_as_rdev_rw(SI_DESC_REGION, &desc_rdev) < 0) { - printk(BIOS_ERR, "Failed to locate %s in the FMAP\n", SI_DESC_REGION); + if (!read_descriptor(&desc_rdev, si_desc_buf) || !is_descriptor_writeable(si_desc_buf)) + return; + + if (!update_for_a0(si_desc_buf)) + return; + + if (!write_descriptor(&desc_rdev, si_desc_buf)) { + printk(BIOS_INFO, "Failed to update descriptor region!\n"); return; }
- if (rdev_readat(&desc_rdev, si_desc_buf, 0, SI_DESC_REGION_SZ) != SI_DESC_REGION_SZ) { - printk(BIOS_ERR, "Failed to read Descriptor Region from SPI Flash\n"); - return; - } - - if (si_desc_buf[PMC_DESC_7_BYTE3] == 0x40) { - si_desc_buf[PMC_DESC_7_BYTE3] = 0x44; - - if (rdev_eraseat(&desc_rdev, 0, SI_DESC_REGION_SZ) != SI_DESC_REGION_SZ) { - printk(BIOS_ERR, "Failed to erase Descriptor Region area\n"); - return; - } - - if (rdev_writeat(&desc_rdev, si_desc_buf, 0, SI_DESC_REGION_SZ) - != SI_DESC_REGION_SZ) { - printk(BIOS_ERR, "Failed to update Descriptor Region\n"); - return; - } - - printk(BIOS_DEBUG, "Update of PMC Descriptor successful, trigger GLOBAL RESET\n"); - - pmc_global_reset_enable(1); - do_full_reset(); - die("Failed to trigger GLOBAL RESET\n"); - } - - printk(BIOS_DEBUG, "Update of PMC Descriptor is not required!\n"); + printk(BIOS_DEBUG, "Update of Descriptor successful, trigger GLOBAL RESET\n"); + pmc_global_reset_enable(true); + do_full_reset(); + die("Failed to trigger GLOBAL RESET\n"); }
void bootblock_mainboard_early_init(void) @@ -64,6 +104,5 @@
void bootblock_mainboard_init(void) { - if (cpu_get_cpuid() == CPUID_ALDERLAKE_A0) - configure_pmc_descriptor(); + configure_descriptor(); }