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> Reviewed-on: https://review.coreboot.org/c/coreboot/+/79751 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Jérémy Compostella <jeremy.compostella@intel.com> Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
This commit is contained in:
committed by
Lean Sheng Tan
parent
a611634de8
commit
b14b96d29a
@@ -27,6 +27,7 @@ romstage-y += raminit_native.c
|
|||||||
romstage-y += raminit_tables.c
|
romstage-y += raminit_tables.c
|
||||||
else
|
else
|
||||||
romstage-y += raminit_mrc.c
|
romstage-y += raminit_mrc.c
|
||||||
|
romstage-y += mrc_wrapper.S
|
||||||
cbfs-files-y += mrc.bin
|
cbfs-files-y += mrc.bin
|
||||||
mrc.bin-file := $(call strip_quotes,$(CONFIG_MRC_FILE))
|
mrc.bin-file := $(call strip_quotes,$(CONFIG_MRC_FILE))
|
||||||
mrc.bin-position := 0xfffa0000
|
mrc.bin-position := 0xfffa0000
|
||||||
|
27
src/northbridge/intel/sandybridge/mrc_wrapper.S
Normal file
27
src/northbridge/intel/sandybridge/mrc_wrapper.S
Normal file
@@ -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
|
@@ -50,10 +50,10 @@ struct pei_data
|
|||||||
uint32_t scrambler_seed;
|
uint32_t scrambler_seed;
|
||||||
uint32_t scrambler_seed_s3;
|
uint32_t scrambler_seed_s3;
|
||||||
/* Data read from flash and passed into MRC */
|
/* Data read from flash and passed into MRC */
|
||||||
unsigned char *mrc_input;
|
uint32_t mrc_input_ptr;
|
||||||
unsigned int mrc_input_len;
|
unsigned int mrc_input_len;
|
||||||
/* Data from MRC that should be saved to flash */
|
/* Data from MRC that should be saved to flash */
|
||||||
unsigned char *mrc_output;
|
uint32_t mrc_output_ptr;
|
||||||
unsigned int mrc_output_len;
|
unsigned int mrc_output_len;
|
||||||
/*
|
/*
|
||||||
* Max frequency DDR3 could be ran at. Could be one of four values:
|
* 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].
|
* which DIMMs should use the SPD from spd_data[0].
|
||||||
*/
|
*/
|
||||||
uint8_t spd_data[4][256];
|
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;
|
int ddr3lv_support;
|
||||||
/*
|
/*
|
||||||
* pcie_init needs to be set to 1 to have the system agent initialize PCIe.
|
* pcie_init needs to be set to 1 to have the system agent initialize PCIe.
|
||||||
|
@@ -28,6 +28,7 @@
|
|||||||
#include <security/vboot/vboot_common.h>
|
#include <security/vboot/vboot_common.h>
|
||||||
#include <southbridge/intel/bd82x6x/pch.h>
|
#include <southbridge/intel/bd82x6x/pch.h>
|
||||||
#include <memory_info.h>
|
#include <memory_info.h>
|
||||||
|
#include <mode_switch.h>
|
||||||
|
|
||||||
/* Management Engine is in the southbridge */
|
/* Management Engine is in the southbridge */
|
||||||
#include <southbridge/intel/bd82x6x/me.h>
|
#include <southbridge/intel/bd82x6x/me.h>
|
||||||
@@ -49,12 +50,16 @@
|
|||||||
|
|
||||||
#define MRC_CACHE_VERSION 0
|
#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)
|
static void save_mrc_data(struct pei_data *pei_data)
|
||||||
{
|
{
|
||||||
u16 c1, c2, checksum;
|
u16 c1, c2, checksum;
|
||||||
|
|
||||||
/* Save the MRC S3 restore data to cbmem */
|
/* Save the MRC S3 restore data to cbmem */
|
||||||
mrc_cache_stash_data(MRC_TRAINING_DATA, MRC_CACHE_VERSION, pei_data->mrc_output,
|
mrc_cache_stash_data(MRC_TRAINING_DATA, MRC_CACHE_VERSION,
|
||||||
|
(void *)(uintptr_t)pei_data->mrc_output_ptr,
|
||||||
pei_data->mrc_output_len);
|
pei_data->mrc_output_len);
|
||||||
|
|
||||||
/* Save the MRC seed values to CMOS */
|
/* Save the MRC seed values to CMOS */
|
||||||
@@ -81,7 +86,7 @@ static void prepare_mrc_cache(struct pei_data *pei_data)
|
|||||||
size_t mrc_size;
|
size_t mrc_size;
|
||||||
|
|
||||||
/* Preset just in case there is an error */
|
/* 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;
|
pei_data->mrc_input_len = 0;
|
||||||
|
|
||||||
/* Read scrambler seeds from CMOS */
|
/* Read scrambler seeds from CMOS */
|
||||||
@@ -108,18 +113,18 @@ static void prepare_mrc_cache(struct pei_data *pei_data)
|
|||||||
return;
|
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_CACHE_VERSION,
|
||||||
&mrc_size);
|
&mrc_size);
|
||||||
if (!pei_data->mrc_input) {
|
if (!pei_data->mrc_input_ptr) {
|
||||||
/* Error message printed in find_current_mrc_cache */
|
/* Error message printed in find_current_mrc_cache */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pei_data->mrc_input_len = mrc_size;
|
pei_data->mrc_input_len = mrc_size;
|
||||||
|
|
||||||
printk(BIOS_DEBUG, "%s: at %p, size %zx\n", __func__,
|
printk(BIOS_DEBUG, "%s: at 0x%x, size %zx\n", __func__,
|
||||||
pei_data->mrc_input, mrc_size);
|
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)
|
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 */
|
/* Wait for ME to be ready */
|
||||||
intel_early_me_init();
|
intel_early_me_init();
|
||||||
@@ -144,19 +149,19 @@ static void sdram_initialize(struct pei_data *pei_data)
|
|||||||
prepare_mrc_cache(pei_data);
|
prepare_mrc_cache(pei_data);
|
||||||
|
|
||||||
/* If MRC data is not found we cannot continue S3 resume. */
|
/* 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__);
|
printk(BIOS_DEBUG, "Giving up in %s: No MRC data\n", __func__);
|
||||||
system_reset();
|
system_reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pass console handler in pei_data */
|
/* 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. */
|
/* Locate and call UEFI System Agent binary. */
|
||||||
entry = cbfs_map("mrc.bin", NULL);
|
entry = cbfs_map("mrc.bin", NULL);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
int rv;
|
int rv;
|
||||||
rv = entry(pei_data);
|
rv = protected_mode_call_2arg(mrc_wrapper, (uintptr_t)entry, (uintptr_t)pei_data);
|
||||||
if (rv) {
|
if (rv) {
|
||||||
switch (rv) {
|
switch (rv) {
|
||||||
case -1:
|
case -1:
|
||||||
@@ -403,7 +408,7 @@ void perform_raminit(int s3resume)
|
|||||||
|
|
||||||
/* Sanity check mrc_var location by verifying a known field */
|
/* Sanity check mrc_var location by verifying a known field */
|
||||||
mrc_var = (void *)DCACHE_RAM_MRC_VAR_BASE;
|
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",
|
printk(BIOS_DEBUG, "MRC_VAR pool occupied [%08x,%08x]\n",
|
||||||
mrc_var->pool_base, mrc_var->pool_base + mrc_var->pool_used);
|
mrc_var->pool_base, mrc_var->pool_base + mrc_var->pool_used);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user