From f1d06a5ad49e2a8138981661cf5c5c7611e96b05 Mon Sep 17 00:00:00 2001 From: Werner Zeh Date: Tue, 1 Jul 2025 08:11:55 +0200 Subject: [PATCH] soc/intel/common/block/memory: Provide a way to use SPD data from memory There can be cases where it is needed to provide the SPD data in a different way than an EEPROM or CBFS file. This patch adds a third method where the SPD data can be provided in a memory buffer for memory-down configurations. Where this memory buffer comes from and how SPD data is filled in is up to the mainboard code. To use this new method set 'spd_data.in_mem' to 'true' and provide a pointer to the SPD data in memory via 'spd_data.ptr' where 'spd_data.len' holds the length of the SPD data in that buffer. This feature is useful for Siemens mainboards where the SPD data is part of a larger configuration block called 'HWInfo block'. Though this block itself do reside in CBFS, the SPD data cannot simply be indexed into (like with the cbfs_index). Instead, the hwinfo-lib is used to get dedicated fields from that block, this includes the SPD data, too. With this patch the SPD data can be retrieved from HWInfo block and passed as a buffer to the memory initialization code. Change-Id: I2bd4970967cfe81bba96d8e2b2fd3a0bb85430c4 Signed-off-by: Werner Zeh Reviewed-on: https://review.coreboot.org/c/coreboot/+/88258 Reviewed-by: Subrata Banik Tested-by: build bot (Jenkins) --- .../block/include/intelblocks/meminit.h | 11 +++++++++ src/soc/intel/common/block/memory/meminit.c | 23 ++++++++++++------- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/soc/intel/common/block/include/intelblocks/meminit.h b/src/soc/intel/common/block/include/intelblocks/meminit.h index a4fb9fa1f3..566efa03d9 100644 --- a/src/soc/intel/common/block/include/intelblocks/meminit.h +++ b/src/soc/intel/common/block/include/intelblocks/meminit.h @@ -57,6 +57,17 @@ struct mem_spd { struct { uint8_t addr_dimm[CONFIG_DIMMS_PER_CHANNEL]; } smbus[MRC_CHANNELS]; + + /* If the SPD data is provided in a memory buffer, spd_data.in_mem needs to be + * set to 'true'. In this case spd_data.ptr points to the memory buffer where the + * SPD data is stored in and spd_data.len stores the length of the SPD data + * in that buffer. In this case cbfs_index is ignored. + */ + struct { + bool in_mem; + size_t len; + uintptr_t ptr; + } spd_data; }; /* Information about memory technology supported by SoC */ diff --git a/src/soc/intel/common/block/memory/meminit.c b/src/soc/intel/common/block/memory/meminit.c index 3c310798d0..fa80017c50 100644 --- a/src/soc/intel/common/block/memory/meminit.c +++ b/src/soc/intel/common/block/memory/meminit.c @@ -60,17 +60,24 @@ static void read_spd_md(const struct soc_mem_cfg *soc_mem_cfg, const struct mem_ if (pop_mask == 0) die("Memory technology does not support the selected configuration!\n"); + if (!(info->spd_data.in_mem)) { - printk(BIOS_DEBUG, "SPD index = %zu\n", info->cbfs_index); + printk(BIOS_DEBUG, "SPD index = %zu\n", info->cbfs_index); - /* Memory leak is ok as long as we have memory mapped boot media */ - _Static_assert(CONFIG(BOOT_DEVICE_MEMORY_MAPPED), - "Function assumes memory-mapped boot media"); + /* Memory leak is ok as long as we have memory mapped boot media */ + _Static_assert(CONFIG(BOOT_DEVICE_MEMORY_MAPPED), + "Function assumes memory-mapped boot media"); - *spd_len = CONFIG_DIMM_SPD_SIZE; - spd_data = spd_cbfs_map(info->cbfs_index); - if (!spd_data) - die("SPD not found in CBFS or incorrect index!\n"); + *spd_len = CONFIG_DIMM_SPD_SIZE; + spd_data = spd_cbfs_map(info->cbfs_index); + if (!spd_data) + die("SPD not found in CBFS or incorrect index!\n"); + } else { + *spd_len = info->spd_data.len; + spd_data = info->spd_data.ptr; + if (!spd_data) + die("SPD data in memory expected but no buffer provided!\n"); + } print_spd_info((uint8_t *)spd_data);