Message ID | 1457317732-18406-58-git-send-email-sjg@chromium.org |
---|---|
State | Superseded |
Delegated to: | Bin Meng |
Headers | show |
Hi Simon, On Mon, Mar 7, 2016 at 10:28 AM, Simon Glass <sjg@chromium.org> wrote: > Broadwell needs a special binary blob to set up the PCH. Add code to run > this on start-up. > > Signed-off-by: Simon Glass <sjg@chromium.org> > --- > > arch/x86/cpu/broadwell/Makefile | 1 + > arch/x86/cpu/broadwell/refcode.c | 108 +++++++++++++++++++++++++++++++++++++++ > 2 files changed, 109 insertions(+) > create mode 100644 arch/x86/cpu/broadwell/refcode.c > > diff --git a/arch/x86/cpu/broadwell/Makefile b/arch/x86/cpu/broadwell/Makefile > index 3054a89..a542fef 100644 > --- a/arch/x86/cpu/broadwell/Makefile > +++ b/arch/x86/cpu/broadwell/Makefile > @@ -10,4 +10,5 @@ obj-y += lpc.o > obj-y += northbridge.o > obj-y += pch.o > obj-y += pinctrl_broadwell.o > +obj-y += refcode.o > obj-y += sata.o > diff --git a/arch/x86/cpu/broadwell/refcode.c b/arch/x86/cpu/broadwell/refcode.c > new file mode 100644 > index 0000000..8c1d99c > --- /dev/null > +++ b/arch/x86/cpu/broadwell/refcode.c > @@ -0,0 +1,108 @@ > +/* > + * Read a coreboot rmodule and execute it. > + * The rmodule_header struct is from coreboot. > + * > + * Copyright (c) 2016 Google, Inc > + * > + * SPDX-License-Identifier: GPL-2.0 nits: GPL-2.0+ > + */ > + > +#include <common.h> > +#include <errno.h> > +#include <asm/arch/pei_data.h> > + > +#define RMODULE_MAGIC 0xf8fe > +#define RMODULE_VERSION_1 1 > + > +/* > + * All fields with '_offset' in the name are byte offsets into the flat blob. > + * The linker and the linker script takes are of assigning the values. > + */ > +struct rmodule_header { > + uint16_t magic; > + uint8_t version; > + uint8_t type; > + /* The payload represents the program's loadable code and data. */ nits: remove ending . > + uint32_t payload_begin_offset; > + uint32_t payload_end_offset; > + /* Begin and of relocation information about the program module. */ nits: remove ending . > + uint32_t relocations_begin_offset; > + uint32_t relocations_end_offset; > + /* The starting address of the linked program. This address is vital > + * for determining relocation offsets as the relocation info and other > + * symbols (bss, entry point) need this value as a basis to calculate > + * the offsets. > + */ nits: please use correct multi-line comment format. > + uint32_t module_link_start_address; > + /* The module_program_size is the size of memory used while running > + * the program. The program is assumed to consume a contiguous amount > + * of memory. */ ditto. > + uint32_t module_program_size; > + /* This is program's execution entry point. */ nits: remove ending . > + uint32_t module_entry_point; > + /* Optional parameter structure that can be used to pass data into > + * the module. */ nits: please use correct multi-line comment format. > + uint32_t parameters_begin; > + uint32_t parameters_end; > + /* BSS section information so the loader can clear the bss. */ nits: remove ending . > + uint32_t bss_begin; > + uint32_t bss_end; > + /* Add some room for growth. */ nits: remove ending . > + uint32_t padding[4]; > +} __packed; > + > +int cpu_run_reference_code(void) > +{ > + struct pei_data _pei_data __aligned(8); > + struct pei_data *pei_data = &_pei_data; > + asmlinkage int (*func)(void *); > + struct rmodule_header *hdr; > + char *src, *dest; > + int ret, dummy; > + int size; > + > + hdr = (struct rmodule_header *)CONFIG_X86_REFCODE_ADDR; > + debug("Extracting code from rmodule at %p\n", hdr); > + if (hdr->magic != RMODULE_MAGIC) { > + debug("Invalid rmodule magic\n"); > + return -EINVAL; > + } > + if (hdr->module_link_start_address != 0) { > + debug("Link start address must be 0\n"); > + return -EPERM; > + } > + if (hdr->module_entry_point != 0) { > + debug("Entry point must be 0\n"); > + return -EPERM; > + } > + > + memset(pei_data, '\0', sizeof(struct pei_data)); > + broadwell_fill_pei_data(pei_data); > + mainboard_fill_pei_data(pei_data); > + pei_data->saved_data = (void *)&dummy; > + > + src = (char *)hdr + hdr->payload_begin_offset; > + dest = (char *)CONFIG_X86_REFCODE_RUN_ADDR; > + > + size = hdr->payload_end_offset - hdr->payload_begin_offset; > + debug("Copying refcode from %p to %p, size %x\n", src, dest, size); > + memcpy(dest, src, size); > + > + size = hdr->bss_end - hdr->bss_begin; > + debug("Zeroing BSS at %p, size %x\n", dest + hdr->bss_begin, size); > + memset(dest + hdr->bss_begin, '\0', size); > + > + func = (asmlinkage int (*)(void *))dest; > + debug("Running reference code at %p\n", func); > +#ifdef DEBUG > + print_buffer(CONFIG_X86_REFCODE_RUN_ADDR, (void *)func, 1, 0x40, 0); > +#endif > + ret = func(pei_data); > + if (ret != 0) { > + debug("Reference code returned %d\n", ret); > + return -EL2HLT; > + } > + debug("Refereence code completed\n"); > + > + return 0; > +} > -- Regards, Bin
diff --git a/arch/x86/cpu/broadwell/Makefile b/arch/x86/cpu/broadwell/Makefile index 3054a89..a542fef 100644 --- a/arch/x86/cpu/broadwell/Makefile +++ b/arch/x86/cpu/broadwell/Makefile @@ -10,4 +10,5 @@ obj-y += lpc.o obj-y += northbridge.o obj-y += pch.o obj-y += pinctrl_broadwell.o +obj-y += refcode.o obj-y += sata.o diff --git a/arch/x86/cpu/broadwell/refcode.c b/arch/x86/cpu/broadwell/refcode.c new file mode 100644 index 0000000..8c1d99c --- /dev/null +++ b/arch/x86/cpu/broadwell/refcode.c @@ -0,0 +1,108 @@ +/* + * Read a coreboot rmodule and execute it. + * The rmodule_header struct is from coreboot. + * + * Copyright (c) 2016 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <errno.h> +#include <asm/arch/pei_data.h> + +#define RMODULE_MAGIC 0xf8fe +#define RMODULE_VERSION_1 1 + +/* + * All fields with '_offset' in the name are byte offsets into the flat blob. + * The linker and the linker script takes are of assigning the values. + */ +struct rmodule_header { + uint16_t magic; + uint8_t version; + uint8_t type; + /* The payload represents the program's loadable code and data. */ + uint32_t payload_begin_offset; + uint32_t payload_end_offset; + /* Begin and of relocation information about the program module. */ + uint32_t relocations_begin_offset; + uint32_t relocations_end_offset; + /* The starting address of the linked program. This address is vital + * for determining relocation offsets as the relocation info and other + * symbols (bss, entry point) need this value as a basis to calculate + * the offsets. + */ + uint32_t module_link_start_address; + /* The module_program_size is the size of memory used while running + * the program. The program is assumed to consume a contiguous amount + * of memory. */ + uint32_t module_program_size; + /* This is program's execution entry point. */ + uint32_t module_entry_point; + /* Optional parameter structure that can be used to pass data into + * the module. */ + uint32_t parameters_begin; + uint32_t parameters_end; + /* BSS section information so the loader can clear the bss. */ + uint32_t bss_begin; + uint32_t bss_end; + /* Add some room for growth. */ + uint32_t padding[4]; +} __packed; + +int cpu_run_reference_code(void) +{ + struct pei_data _pei_data __aligned(8); + struct pei_data *pei_data = &_pei_data; + asmlinkage int (*func)(void *); + struct rmodule_header *hdr; + char *src, *dest; + int ret, dummy; + int size; + + hdr = (struct rmodule_header *)CONFIG_X86_REFCODE_ADDR; + debug("Extracting code from rmodule at %p\n", hdr); + if (hdr->magic != RMODULE_MAGIC) { + debug("Invalid rmodule magic\n"); + return -EINVAL; + } + if (hdr->module_link_start_address != 0) { + debug("Link start address must be 0\n"); + return -EPERM; + } + if (hdr->module_entry_point != 0) { + debug("Entry point must be 0\n"); + return -EPERM; + } + + memset(pei_data, '\0', sizeof(struct pei_data)); + broadwell_fill_pei_data(pei_data); + mainboard_fill_pei_data(pei_data); + pei_data->saved_data = (void *)&dummy; + + src = (char *)hdr + hdr->payload_begin_offset; + dest = (char *)CONFIG_X86_REFCODE_RUN_ADDR; + + size = hdr->payload_end_offset - hdr->payload_begin_offset; + debug("Copying refcode from %p to %p, size %x\n", src, dest, size); + memcpy(dest, src, size); + + size = hdr->bss_end - hdr->bss_begin; + debug("Zeroing BSS at %p, size %x\n", dest + hdr->bss_begin, size); + memset(dest + hdr->bss_begin, '\0', size); + + func = (asmlinkage int (*)(void *))dest; + debug("Running reference code at %p\n", func); +#ifdef DEBUG + print_buffer(CONFIG_X86_REFCODE_RUN_ADDR, (void *)func, 1, 0x40, 0); +#endif + ret = func(pei_data); + if (ret != 0) { + debug("Reference code returned %d\n", ret); + return -EL2HLT; + } + debug("Refereence code completed\n"); + + return 0; +}
Broadwell needs a special binary blob to set up the PCH. Add code to run this on start-up. Signed-off-by: Simon Glass <sjg@chromium.org> --- arch/x86/cpu/broadwell/Makefile | 1 + arch/x86/cpu/broadwell/refcode.c | 108 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 arch/x86/cpu/broadwell/refcode.c