drivers/intel/fsp2_0: Add support to identify GPIO config changes

Traditionally, for each Intel platform using FSP, FSP-S has at some
point configured GPIOs differently than the mainboard configuration in
coreboot. This has resulted in various side-effects in coreboot,
payload and OS because of misconfigured GPIOs. On more recent Intel
platforms, a UPD `GpioOverride` is added that coreboot can use to
ensure that FSP does not touch any GPIO configuration.

This change adds a debug option `CHECK_GPIO_CONFIG_CHANGES` to fsp2_0
driver in coreboot that makes a platform callback `gpio_snapshot` to
snapshot GPIO configuration before making a call to FSP SiliconInit
and Notify phases. This snapshot is then compared against the GPIO
configuration using platform callback `gpio_verify_snapshot` after
returning from FSP. The callbacks are not added to romstage (FSP-M)
because mainboard configures all pads in ramstage.

This debug hook allows developers to dump information about any pads
that have a different configuration after call to FSP in ramstage. It
is useful to identify missed UPD configurations or bugs in FSP that
might not honor the UPDs set by coreboot.

This debug hook expects the platform to implement the callbacks
`gpio_snapshot` and `gpio_verify_snapshot`. These can be implemented
as part of the common GPIO driver for platforms using
FSP2.0+. Platforms that implement this support must select the config
`HAVE_GPIO_SNAPSHOT_VERIFY_SUPPORT` to make the debug config
`CHECK_GPIO_CONFIG_CHANGES` visible to user.

Proposal for the GPIO snapshot/verify support was discussed in the RFC
CB:50829.

Signed-off-by: Furquan Shaikh <furquan@google.com>
Change-Id: I5326fc98b6eba0f8ba946842253b288c0d42c523
Reviewed-on: https://review.coreboot.org/c/coreboot/+/50989
Reviewed-by: Michael Niewöhner <foss@mniewoehner.de>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Furquan Shaikh 2021-04-10 14:26:15 -07:00 committed by Michael Niewöhner
parent 66ab5eb521
commit e07532fb16
3 changed files with 55 additions and 0 deletions

View File

@ -45,4 +45,21 @@ config DISPLAY_FSP_VERSION_INFO_2
Select this option to display Firmware version information Select this option to display Firmware version information
using new header 'FirmwareVersionInfo.h'. using new header 'FirmwareVersionInfo.h'.
config HAVE_GPIO_SNAPSHOT_VERIFY_SUPPORT
bool
default n
help
Select this option if platform provides support for GPIO
config snapshot and verify callbacks: `gpio_snapshot()`
and `gpio_verify_snapshot()`
config CHECK_GPIO_CONFIG_CHANGES
bool "Check GPIO config changes across calls to FSP-S"
depends on HAVE_GPIO_SNAPSHOT_VERIFY_SUPPORT
help
Select this option to identify if any GPIOs are re-configured
by FSP-S differently than the mainboard configuration. This
requires platform support to snapshot and verify that config
matches snapshot.
endif # PLATFORM_USES_FSP2_0 endif # PLATFORM_USES_FSP2_0

View File

@ -11,6 +11,27 @@ asmlinkage size_t fsp_write_line(uint8_t *buffer, size_t number_of_bytes)
return number_of_bytes; return number_of_bytes;
} }
enum fsp_call_phase {
BEFORE_FSP_CALL,
AFTER_FSP_CALL,
};
static void fsp_gpio_config_check(enum fsp_call_phase phase, const char *call_str)
{
switch (phase) {
case BEFORE_FSP_CALL:
printk(BIOS_SPEW, "Snapshot all GPIOs before %s.\n", call_str);
gpio_snapshot();
break;
case AFTER_FSP_CALL:
printk(BIOS_SPEW, "Verify GPIO snapshot after %s...", call_str);
printk(BIOS_SPEW, "%zd changes detected!\n", gpio_verify_snapshot());
break;
default:
break;
}
}
/*----------- /*-----------
* MemoryInit * MemoryInit
*----------- *-----------
@ -62,6 +83,9 @@ void fsp_debug_before_silicon_init(fsp_silicon_init_fn silicon_init,
const FSPS_UPD *fsps_old_upd, const FSPS_UPD *fsps_old_upd,
const FSPS_UPD *fsps_new_upd) const FSPS_UPD *fsps_new_upd)
{ {
if (CONFIG(CHECK_GPIO_CONFIG_CHANGES))
fsp_gpio_config_check(BEFORE_FSP_CALL, "FSP Silicon Init");
display_mtrrs(); display_mtrrs();
/* Display the UPD values */ /* Display the UPD values */
@ -77,6 +101,9 @@ void fsp_debug_before_silicon_init(fsp_silicon_init_fn silicon_init,
void fsp_debug_after_silicon_init(uint32_t status) void fsp_debug_after_silicon_init(uint32_t status)
{ {
if (CONFIG(CHECK_GPIO_CONFIG_CHANGES))
fsp_gpio_config_check(AFTER_FSP_CALL, "FSP Silicon Init");
if (CONFIG(DISPLAY_FSP_CALLS_AND_STATUS)) if (CONFIG(DISPLAY_FSP_CALLS_AND_STATUS))
printk(BIOS_SPEW, "FspSiliconInit returned 0x%08x\n", status); printk(BIOS_SPEW, "FspSiliconInit returned 0x%08x\n", status);
@ -94,6 +121,9 @@ void fsp_debug_after_silicon_init(uint32_t status)
void fsp_before_debug_notify(fsp_notify_fn notify, void fsp_before_debug_notify(fsp_notify_fn notify,
const struct fsp_notify_params *notify_params) const struct fsp_notify_params *notify_params)
{ {
if (CONFIG(CHECK_GPIO_CONFIG_CHANGES))
fsp_gpio_config_check(BEFORE_FSP_CALL, "FSP Notify");
/* Display the call to FspNotify */ /* Display the call to FspNotify */
if (!CONFIG(DISPLAY_FSP_CALLS_AND_STATUS)) if (!CONFIG(DISPLAY_FSP_CALLS_AND_STATUS))
return; return;
@ -105,6 +135,9 @@ void fsp_before_debug_notify(fsp_notify_fn notify,
void fsp_debug_after_notify(uint32_t status) void fsp_debug_after_notify(uint32_t status)
{ {
if (CONFIG(CHECK_GPIO_CONFIG_CHANGES))
fsp_gpio_config_check(AFTER_FSP_CALL, "FSP Notify");
if (CONFIG(DISPLAY_FSP_CALLS_AND_STATUS)) if (CONFIG(DISPLAY_FSP_CALLS_AND_STATUS))
printk(BIOS_SPEW, "FspNotify returned 0x%08x\n", status); printk(BIOS_SPEW, "FspNotify returned 0x%08x\n", status);

View File

@ -57,4 +57,9 @@ void fsp_print_guid_extension_hob(const struct hob_header *hob);
*/ */
asmlinkage size_t fsp_write_line(uint8_t *buffer, size_t number_of_bytes); asmlinkage size_t fsp_write_line(uint8_t *buffer, size_t number_of_bytes);
/* Callback to snapshot all GPIO configurations. */
void gpio_snapshot(void);
/* Callback to verify that current GPIO configuration matches the saved snapshot */
size_t gpio_verify_snapshot(void);
#endif /* _FSP2_0_DEBUG_H_ */ #endif /* _FSP2_0_DEBUG_H_ */