From b14b96d29a5ed196b2205a1bbd239c23d684fa47 Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Wed, 27 Dec 2023 10:59:25 +0100 Subject: [PATCH] northbridge/intel/sandybridge/raminit: Prepare MRC path for x86_64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove pointers in argument list passed to MRC to make sure the struct has the same size on x86_64 as on x86_32. - Add assembly wrapper to call the MRC with argument in EAX. - Wrap calling MRC in protected_mode_call_2arg, which is a stub on x86_32 Tested: Boots on Lenovo X220 using MRC in x86_32 and x86_64 mode. Change-Id: Id755e7381c5a94360e3511c53432d68b7687df67 Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/79751 Tested-by: build bot (Jenkins) Reviewed-by: Jérémy Compostella Reviewed-by: Arthur Heymans --- .../intel/sandybridge/Makefile.inc | 1 + .../intel/sandybridge/mrc_wrapper.S | 27 +++++++++++++++++ src/northbridge/intel/sandybridge/pei_data.h | 8 +++-- .../intel/sandybridge/raminit_mrc.c | 29 +++++++++++-------- 4 files changed, 50 insertions(+), 15 deletions(-) create mode 100644 src/northbridge/intel/sandybridge/mrc_wrapper.S diff --git a/src/northbridge/intel/sandybridge/Makefile.inc b/src/northbridge/intel/sandybridge/Makefile.inc index 36fc16b4c4..6ecb17a378 100644 --- a/src/northbridge/intel/sandybridge/Makefile.inc +++ b/src/northbridge/intel/sandybridge/Makefile.inc @@ -27,6 +27,7 @@ romstage-y += raminit_native.c romstage-y += raminit_tables.c else romstage-y += raminit_mrc.c +romstage-y += mrc_wrapper.S cbfs-files-y += mrc.bin mrc.bin-file := $(call strip_quotes,$(CONFIG_MRC_FILE)) mrc.bin-position := 0xfffa0000 diff --git a/src/northbridge/intel/sandybridge/mrc_wrapper.S b/src/northbridge/intel/sandybridge/mrc_wrapper.S new file mode 100644 index 0000000000..860526b03c --- /dev/null +++ b/src/northbridge/intel/sandybridge/mrc_wrapper.S @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Functions to call MRC.bin from x86_64 */ + +.text +.code32 + .section ".text.mrc_wrapper", "ax", @progbits + .globl mrc_wrapper +mrc_wrapper: + /* Set up new stack frame */ + pushal + mov %esp, %ebp + + /* Align stack */ + andl $0xfffffff0, %esp + + movl 36(%ebp), %ebx /* Get function pointer */ + movl 40(%ebp), %eax /* Get argument */ + + call *%ebx + + /* Place return value on stack so that popal fetches it */ + movl %eax, 28(%ebp) + + /* Restore stack pointer */ + mov %ebp, %esp + popal + ret diff --git a/src/northbridge/intel/sandybridge/pei_data.h b/src/northbridge/intel/sandybridge/pei_data.h index 7abc25f8b6..0309cf3b89 100644 --- a/src/northbridge/intel/sandybridge/pei_data.h +++ b/src/northbridge/intel/sandybridge/pei_data.h @@ -50,10 +50,10 @@ struct pei_data uint32_t scrambler_seed; uint32_t scrambler_seed_s3; /* Data read from flash and passed into MRC */ - unsigned char *mrc_input; + uint32_t mrc_input_ptr; unsigned int mrc_input_len; /* Data from MRC that should be saved to flash */ - unsigned char *mrc_output; + uint32_t mrc_output_ptr; unsigned int mrc_output_len; /* * Max frequency DDR3 could be ran at. Could be one of four values: @@ -87,7 +87,9 @@ struct pei_data * which DIMMs should use the SPD from spd_data[0]. */ uint8_t spd_data[4][256]; - tx_byte_func tx_byte; + /* 32 bit pointer to tx_byte_func */ + uint32_t tx_byte_ptr; + int ddr3lv_support; /* * pcie_init needs to be set to 1 to have the system agent initialize PCIe. diff --git a/src/northbridge/intel/sandybridge/raminit_mrc.c b/src/northbridge/intel/sandybridge/raminit_mrc.c index 68b02b81bc..d59aa8687f 100644 --- a/src/northbridge/intel/sandybridge/raminit_mrc.c +++ b/src/northbridge/intel/sandybridge/raminit_mrc.c @@ -28,6 +28,7 @@ #include #include #include +#include /* Management Engine is in the southbridge */ #include @@ -49,13 +50,17 @@ #define MRC_CACHE_VERSION 0 +/* Assembly functions: */ +void mrc_wrapper(void *func_ptr, uint32_t arg1); + static void save_mrc_data(struct pei_data *pei_data) { u16 c1, c2, checksum; /* Save the MRC S3 restore data to cbmem */ - mrc_cache_stash_data(MRC_TRAINING_DATA, MRC_CACHE_VERSION, pei_data->mrc_output, - pei_data->mrc_output_len); + mrc_cache_stash_data(MRC_TRAINING_DATA, MRC_CACHE_VERSION, + (void *)(uintptr_t)pei_data->mrc_output_ptr, + pei_data->mrc_output_len); /* Save the MRC seed values to CMOS */ cmos_write32(pei_data->scrambler_seed, CMOS_OFFSET_MRC_SEED); @@ -81,7 +86,7 @@ static void prepare_mrc_cache(struct pei_data *pei_data) size_t mrc_size; /* Preset just in case there is an error */ - pei_data->mrc_input = NULL; + pei_data->mrc_input_ptr = 0; pei_data->mrc_input_len = 0; /* Read scrambler seeds from CMOS */ @@ -108,18 +113,18 @@ static void prepare_mrc_cache(struct pei_data *pei_data) return; } - pei_data->mrc_input = mrc_cache_current_mmap_leak(MRC_TRAINING_DATA, + pei_data->mrc_input_ptr = (uintptr_t)mrc_cache_current_mmap_leak(MRC_TRAINING_DATA, MRC_CACHE_VERSION, &mrc_size); - if (!pei_data->mrc_input) { + if (!pei_data->mrc_input_ptr) { /* Error message printed in find_current_mrc_cache */ return; } pei_data->mrc_input_len = mrc_size; - printk(BIOS_DEBUG, "%s: at %p, size %zx\n", __func__, - pei_data->mrc_input, mrc_size); + printk(BIOS_DEBUG, "%s: at 0x%x, size %zx\n", __func__, + pei_data->mrc_input_ptr, mrc_size); } /** @@ -129,7 +134,7 @@ static void prepare_mrc_cache(struct pei_data *pei_data) */ static void sdram_initialize(struct pei_data *pei_data) { - int (*entry)(struct pei_data *pei_data) __attribute__((regparm(1))); + int (*entry)(struct pei_data *pei_data); /* Wait for ME to be ready */ intel_early_me_init(); @@ -144,19 +149,19 @@ static void sdram_initialize(struct pei_data *pei_data) prepare_mrc_cache(pei_data); /* If MRC data is not found we cannot continue S3 resume. */ - if (pei_data->boot_mode == 2 && !pei_data->mrc_input) { + if (pei_data->boot_mode == 2 && !pei_data->mrc_input_ptr) { printk(BIOS_DEBUG, "Giving up in %s: No MRC data\n", __func__); system_reset(); } /* Pass console handler in pei_data */ - pei_data->tx_byte = do_putchar; + pei_data->tx_byte_ptr = (uintptr_t)do_putchar; /* Locate and call UEFI System Agent binary. */ entry = cbfs_map("mrc.bin", NULL); if (entry) { int rv; - rv = entry(pei_data); + rv = protected_mode_call_2arg(mrc_wrapper, (uintptr_t)entry, (uintptr_t)pei_data); if (rv) { switch (rv) { case -1: @@ -403,7 +408,7 @@ void perform_raminit(int s3resume) /* Sanity check mrc_var location by verifying a known field */ mrc_var = (void *)DCACHE_RAM_MRC_VAR_BASE; - if (mrc_var->tx_byte == (uintptr_t)pei_data.tx_byte) { + if (mrc_var->tx_byte == pei_data.tx_byte_ptr) { printk(BIOS_DEBUG, "MRC_VAR pool occupied [%08x,%08x]\n", mrc_var->pool_base, mrc_var->pool_base + mrc_var->pool_used);