Patrick Rudolph has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/79751?usp=email )
Change subject: northbridge/intel/sandybridge/raminit: Prepare MRC path for x86_64 ......................................................................
northbridge/intel/sandybridge/raminit: Prepare MRC path for x86_64
- 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 patrick.rudolph@9elements.com --- M src/northbridge/intel/sandybridge/Makefile.inc A src/northbridge/intel/sandybridge/mrc_wrapper.S M src/northbridge/intel/sandybridge/pei_data.h M src/northbridge/intel/sandybridge/raminit_mrc.c 4 files changed, 51 insertions(+), 15 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/51/79751/1
diff --git a/src/northbridge/intel/sandybridge/Makefile.inc b/src/northbridge/intel/sandybridge/Makefile.inc index 36fc16b..6ecb17a 100644 --- a/src/northbridge/intel/sandybridge/Makefile.inc +++ b/src/northbridge/intel/sandybridge/Makefile.inc @@ -27,6 +27,7 @@ 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 0000000..e169064 --- /dev/null +++ b/src/northbridge/intel/sandybridge/mrc_wrapper.S @@ -0,0 +1,28 @@ +/* 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 7abc25f..0309cf3 100644 --- a/src/northbridge/intel/sandybridge/pei_data.h +++ b/src/northbridge/intel/sandybridge/pei_data.h @@ -50,10 +50,10 @@ 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 @@ * 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 68b02b8..d59aa86 100644 --- a/src/northbridge/intel/sandybridge/raminit_mrc.c +++ b/src/northbridge/intel/sandybridge/raminit_mrc.c @@ -28,6 +28,7 @@ #include <security/vboot/vboot_common.h> #include <southbridge/intel/bd82x6x/pch.h> #include <memory_info.h> +#include <mode_switch.h>
/* Management Engine is in the southbridge */ #include <southbridge/intel/bd82x6x/me.h> @@ -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 @@ 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 @@ 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 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 @@ 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 @@
/* 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);