summaryrefslogtreecommitdiff
path: root/config/coreboot
diff options
context:
space:
mode:
authorLeah Rowe <vimuser@noreply.codeberg.org>2025-10-06 03:22:07 +0200
committerLeah Rowe <vimuser@noreply.codeberg.org>2025-10-06 03:22:07 +0200
commitb5ad829ffe9dfb9f5a32f4ac95159a35d2662877 (patch)
treed5ae2cec7ca0a4643b7368b64bf500ed36b7fd95 /config/coreboot
parent9b104fca44a1d4a73fbfb4eed308098c51cc43e3 (diff)
parente82e2a133210d5e8fe195a2b94e491b4f9a3605f (diff)
Merge pull request 'config/coreboot/default: Add Haswell NRI SMBIOS type 16/17 patch' (#363) from noisytoot/haswell-nri-smbios-memory into master
Reviewed-on: https://codeberg.org/libreboot/lbmk/pulls/363
Diffstat (limited to 'config/coreboot')
-rw-r--r--config/coreboot/default/patches/0041-Haswell-NRI-Implement-SMBIOS-type-16-17.patch184
1 files changed, 184 insertions, 0 deletions
diff --git a/config/coreboot/default/patches/0041-Haswell-NRI-Implement-SMBIOS-type-16-17.patch b/config/coreboot/default/patches/0041-Haswell-NRI-Implement-SMBIOS-type-16-17.patch
new file mode 100644
index 00000000..aeaf2fa2
--- /dev/null
+++ b/config/coreboot/default/patches/0041-Haswell-NRI-Implement-SMBIOS-type-16-17.patch
@@ -0,0 +1,184 @@
+From b00d35efc78b13d53c8f0b35b869811c5a2c56cf Mon Sep 17 00:00:00 2001
+From: Ron Nazarov <ron@noisytoot.org>
+Date: Tue, 30 Sep 2025 22:36:53 +0100
+Subject: [PATCH] Haswell NRI: Implement SMBIOS type 16/17
+
+Based on the implementation from Ivy/Sandy Bridge NRI.
+
+Tested on a Dell OptiPlex 9020 SFF with libreboot.
+
+Change-Id: I5e153258f9f88726f54c98baac0b1788a839f934
+Signed-off-by: Ron Nazarov <ron@noisytoot.org>
+---
+ .../haswell/native_raminit/raminit_main.c | 6 +-
+ .../haswell/native_raminit/raminit_native.c | 83 +++++++++++++++++--
+ .../haswell/native_raminit/raminit_native.h | 2 +-
+ 3 files changed, 81 insertions(+), 10 deletions(-)
+
+diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_main.c b/src/northbridge/intel/haswell/native_raminit/raminit_main.c
+index 84db33ebdf..328f777ee1 100644
+--- a/src/northbridge/intel/haswell/native_raminit/raminit_main.c
++++ b/src/northbridge/intel/haswell/native_raminit/raminit_main.c
+@@ -245,7 +245,7 @@ static enum raminit_status try_raminit(
+ return status;
+ }
+
+-void raminit_main(const enum raminit_boot_mode bootmode)
++const struct sysinfo *raminit_main(const enum raminit_boot_mode bootmode)
+ {
+ /*
+ * The mighty_ctrl struct. Will happily nuke the pre-RAM stack
+@@ -261,7 +261,7 @@ void raminit_main(const enum raminit_boot_mode bootmode)
+ if (bootmode != BOOTMODE_COLD) {
+ status = try_raminit(&mighty_ctrl, fast_boot, ARRAY_SIZE(fast_boot));
+ if (status == RAMINIT_STATUS_SUCCESS)
+- return;
++ return &mighty_ctrl;
+ }
+
+ /** TODO: Try more than once **/
+@@ -269,4 +269,6 @@ void raminit_main(const enum raminit_boot_mode bootmode)
+
+ if (status != RAMINIT_STATUS_SUCCESS)
+ die("Memory initialization was met with utmost failure and misery\n");
++
++ return &mighty_ctrl;
+ }
+diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.c b/src/northbridge/intel/haswell/native_raminit/raminit_native.c
+index 3ad8ce29e7..73532592e8 100644
+--- a/src/northbridge/intel/haswell/native_raminit/raminit_native.c
++++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.c
+@@ -16,6 +16,73 @@
+
+ #include "raminit_native.h"
+
++static uint8_t nb_get_ecc_type(const uint32_t capid0_a)
++{
++ return capid0_a & CAPID_ECCDIS ? MEMORY_ARRAY_ECC_NONE : MEMORY_ARRAY_ECC_SINGLE_BIT;
++}
++
++static uint16_t nb_slots_per_channel(const uint32_t capid0_a)
++{
++ return !(capid0_a & CAPID_DDPCD) + 1;
++}
++
++static uint16_t nb_number_of_channels(const uint32_t capid0_a)
++{
++ return !(capid0_a & CAPID_PDCD) + 1;
++}
++
++static uint32_t nb_max_chan_capacity_mib(const uint32_t capid0_a)
++{
++ uint32_t ddrsz;
++
++ /* Values from documentation, which assume two DIMMs per channel */
++ switch (CAPID_DDRSZ(capid0_a)) {
++ case 1:
++ ddrsz = 8192;
++ break;
++ case 2:
++ ddrsz = 2048;
++ break;
++ case 3:
++ ddrsz = 512;
++ break;
++ default:
++ ddrsz = 16384;
++ break;
++ }
++
++ /* Account for the maximum number of DIMMs per channel */
++ return (ddrsz / 2) * nb_slots_per_channel(capid0_a);
++}
++
++/* Fill cbmem with information for SMBIOS type 16 and type 17 */
++static void setup_sdram_meminfo(const struct sysinfo *ctrl)
++{
++ const u16 ddr_freq = (1000 << 8) / ctrl->tCK;
++
++ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) {
++ for (uint8_t slot = 0; slot < NUM_SLOTS; slot++) {
++ enum cb_err ret = spd_add_smbios17(channel, slot, ddr_freq,
++ &ctrl->dimms[channel][slot].data);
++ if (ret != CB_SUCCESS)
++ printk(BIOS_ERR, "RAMINIT: Failed to add SMBIOS17\n");
++ }
++ }
++
++ /* The 'spd_add_smbios17' function allocates this CBMEM area */
++ struct memory_info *m = cbmem_find(CBMEM_ID_MEMINFO);
++ if (!m)
++ return;
++
++ const uint32_t capid0_a = pci_read_config32(HOST_BRIDGE, CAPID0_A);
++
++ const uint16_t channels = nb_number_of_channels(capid0_a);
++
++ m->ecc_type = nb_get_ecc_type(capid0_a);
++ m->max_capacity_mib = channels * nb_max_chan_capacity_mib(capid0_a);
++ m->number_of_devices = channels * nb_slots_per_channel(capid0_a);
++}
++
+ static void wait_txt_clear(void)
+ {
+ const struct cpuid_result cpuid = cpuid_ext(1, 0);
+@@ -90,7 +157,8 @@ static void raminit_reset(void)
+ static enum raminit_boot_mode do_actual_raminit(
+ const bool s3resume,
+ const bool cpu_replaced,
+- const enum raminit_boot_mode orig_bootmode)
++ const enum raminit_boot_mode orig_bootmode,
++ const struct sysinfo **ctrl)
+ {
+ struct mrc_data md = prepare_mrc_cache();
+
+@@ -158,7 +226,7 @@ static enum raminit_boot_mode do_actual_raminit(
+ * And now, the actual memory initialization thing.
+ */
+ printk(RAM_DEBUG, "\nStarting native raminit\n");
+- raminit_main(bootmode);
++ *ctrl = raminit_main(bootmode);
+
+ return bootmode;
+ }
+@@ -176,8 +244,9 @@ void perform_raminit(const int s3resume)
+ wait_txt_clear();
+ wrmsr(0x2e6, (msr_t) {.lo = 0, .hi = 0});
+
++ const struct sysinfo *ctrl;
+ const enum raminit_boot_mode bootmode =
+- do_actual_raminit(s3resume, cpu_replaced, orig_bootmode);
++ do_actual_raminit(s3resume, cpu_replaced, orig_bootmode, &ctrl);
+
+ /** TODO: report_memory_config **/
+
+@@ -204,9 +273,9 @@ void perform_raminit(const int s3resume)
+ system_reset();
+ }
+
+- /* Save training data on non-S3 resumes */
+- if (!s3resume)
++ /* Save training data and set up SMBIOS type 16/17 on non-S3 resumes */
++ if (!s3resume) {
+ save_mrc_data();
+-
+- /** TODO: setup_sdram_meminfo **/
++ setup_sdram_meminfo(ctrl);
++ }
+ }
+diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.h b/src/northbridge/intel/haswell/native_raminit/raminit_native.h
+index b9e84a11df..1401feedc5 100644
+--- a/src/northbridge/intel/haswell/native_raminit/raminit_native.h
++++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.h
+@@ -476,7 +476,7 @@ static inline void mchbar_write64(const uintptr_t x, const uint64_t v)
+ "m"(mmxsave));
+ }
+
+-void raminit_main(enum raminit_boot_mode bootmode);
++const struct sysinfo *raminit_main(enum raminit_boot_mode bootmode);
+
+ enum raminit_status collect_spd_info(struct sysinfo *ctrl);
+ enum raminit_status initialise_mpll(struct sysinfo *ctrl);
+--
+2.50.1
+