From f0215b4cae32be8ddee3435941988d5efd84dad6 Mon Sep 17 00:00:00 2001 From: Bill XIE Date: Sat, 20 Mar 2021 21:06:11 +0800 Subject: [PATCH] arch/x86: Init firmware pointer for EC SMSC KBC1098/KBC1126 at build time According to util/kbc1126/README.md, for these ECs to work, the address and size of their two firmware should be written to $s-0x100` (`$s` means the image size, done with kbc1126_ec_insert), which means that every existing section (especially those used to store code) should not overlap this address, otherwise the bootblock will get damaged when inserting firmwares of the EC. In this commit, ecfw_ptr is a structure initialized at build time according to CONFIG_KBC1126_FW1_OFFSET and CONFIG_KBC1126_FW2_OFFSET (to do so, they should be redefined as hex), and linked to CONFIG_ECFW_PTR_ADDR within bootblock, so kbc1126_ec_insert is not needed at build time any more. Test passed on Elitebook Folio 9470m. Signed-off-by: Bill XIE Change-Id: I4f0de0c4d7283e630242fbe84a46e0547783c49e Reviewed-on: https://review.coreboot.org/c/coreboot/+/51671 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber --- src/arch/x86/Kconfig | 19 +++++++++++++++++++ src/arch/x86/bootblock.ld | 9 ++++++++- src/ec/hp/kbc1126/Kconfig | 14 ++++++++++---- src/ec/hp/kbc1126/Makefile.inc | 12 ++---------- src/ec/hp/kbc1126/ecfw_ptr.c | 16 ++++++++++++++++ src/ec/hp/kbc1126/ecfw_ptr.h | 20 ++++++++++++++++++++ 6 files changed, 75 insertions(+), 15 deletions(-) create mode 100644 src/ec/hp/kbc1126/ecfw_ptr.c create mode 100644 src/ec/hp/kbc1126/ecfw_ptr.h diff --git a/src/arch/x86/Kconfig b/src/arch/x86/Kconfig index 6af3fa8b69..207654d8a9 100644 --- a/src/arch/x86/Kconfig +++ b/src/arch/x86/Kconfig @@ -340,4 +340,23 @@ config MEMLAYOUT_LD_FILE string default "src/arch/x86/memlayout.ld" +# Some EC need an "EC firmware pointer" (a data structure hinting the address +# of its firmware blobs) being put at a fixed position. Its space +# (__section__(".ecfw_ptr")) should be reserved if it lies in the range of a +# stage. Different EC may have different format and/or value for it. The actual +# address of EC firmware pointer should be provided in the Kconfig of the EC +# requiring it, and its value could be filled by linking a read-only global +# data object to the section above. + +config ECFW_PTR_ADDR + hex + help + Address of reserved space for EC firmware pointer, which should not + overlap other data such as reset vector or FIT pointer if present. + +config ECFW_PTR_SIZE + int + help + Size of reserved space for EC firmware pointer + endif diff --git a/src/arch/x86/bootblock.ld b/src/arch/x86/bootblock.ld index 4ab2275998..0b908bbec6 100644 --- a/src/arch/x86/bootblock.ld +++ b/src/arch/x86/bootblock.ld @@ -31,7 +31,7 @@ SECTIONS { */ PROGRAM_SZ = SIZEOF(.text) + 512; - . = MIN(_ID_SECTION, _FIT_POINTER) - EARLYASM_SZ; + . = MIN(_ECFW_PTR, MIN(_ID_SECTION, _FIT_POINTER)) - EARLYASM_SZ; . = CONFIG(SIPI_VECTOR_IN_ROM) ? ALIGN(4096) : ALIGN(16); BOOTBLOCK_TOP = .; .init (.) : { @@ -56,6 +56,13 @@ SECTIONS { _ID_SECTION_END = SIZEOF(.fit_pointer) && SIZEOF(.id) > 0x28 ? 0xffffff80 : _X86_RESET_VECTOR; _ID_SECTION = _ID_SECTION_END - SIZEOF(.id); + . = _ECFW_PTR; + .ecfw_ptr (.): { + ASSERT((SIZEOF(.ecfw_ptr) == CONFIG_ECFW_PTR_SIZE), "Size of ecfw_ptr is incorrect"); + KEEP(*(.ecfw_ptr)); + } + _ECFW_PTR = SIZEOF(.ecfw_ptr) ? CONFIG_ECFW_PTR_ADDR : _X86_RESET_VECTOR; + . = _FIT_POINTER; .fit_pointer (.): { KEEP(*(.fit_pointer)); diff --git a/src/ec/hp/kbc1126/Kconfig b/src/ec/hp/kbc1126/Kconfig index cb4ddec7e4..5e6edd6a69 100644 --- a/src/ec/hp/kbc1126/Kconfig +++ b/src/ec/hp/kbc1126/Kconfig @@ -27,6 +27,12 @@ config KBC1126_FIRMWARE Select this option to add the two firmware blobs for KBC1126. You need these two blobs to power on your machine. +config ECFW_PTR_ADDR + default 0xffffff00 + +config ECFW_PTR_SIZE + default 8 + config KBC1126_FW1 string "KBC1126 firmware #1 path and filename" depends on KBC1126_FIRMWARE @@ -37,9 +43,9 @@ config KBC1126_FW1 vendor firmware. config KBC1126_FW1_OFFSET - string "Offset of KBC1126 firmware #1" + hex "Offset of KBC1126 firmware #1" depends on KBC1126_FIRMWARE - default "0xfffe8000" + default 0xfffe8000 config KBC1126_FW2 string "KBC1126 filename #2 path and filename" @@ -51,8 +57,8 @@ config KBC1126_FW2 vendor firmware. config KBC1126_FW2_OFFSET - string "Offset of KBC1126 firmware #2" + hex "Offset of KBC1126 firmware #2" depends on KBC1126_FIRMWARE - default "0xfffd0000" + default 0xfffd0000 endif diff --git a/src/ec/hp/kbc1126/Makefile.inc b/src/ec/hp/kbc1126/Makefile.inc index 4d7d46d9e7..3f7fa19b5d 100644 --- a/src/ec/hp/kbc1126/Makefile.inc +++ b/src/ec/hp/kbc1126/Makefile.inc @@ -1,7 +1,8 @@ ## SPDX-License-Identifier: GPL-2.0-only ifeq ($(CONFIG_EC_HP_KBC1126_ECFW_IN_CBFS),y) -KBC1126_EC_INSERT:=$(top)/util/kbc1126/kbc1126_ec_insert + +bootblock-y += ecfw_ptr.c ifeq ($(CONFIG_KBC1126_FIRMWARE),y) cbfs-files-y += ecfw1.bin @@ -16,15 +17,6 @@ ecfw2.bin-position := $(CONFIG_KBC1126_FW2_OFFSET) ecfw2.bin-type := raw endif -$(call add_intermediate, kbc1126_ec_insert) -ifeq ($(CONFIG_KBC1126_FIRMWARE),y) - printf " Building kbc1126_ec_insert.\n" - $(MAKE) -C util/kbc1126 - printf " KBC1126 Inserting KBC1126 firmware blobs.\n" - $(KBC1126_EC_INSERT) $(obj)/coreboot.pre \ - $(CONFIG_KBC1126_FW1_OFFSET) $(CONFIG_KBC1126_FW2_OFFSET) -endif - build_complete:: ifeq ($(CONFIG_KBC1126_FIRMWARE),) printf "\n** WARNING **\n" diff --git a/src/ec/hp/kbc1126/ecfw_ptr.c b/src/ec/hp/kbc1126/ecfw_ptr.c new file mode 100644 index 0000000000..8a29c6cd33 --- /dev/null +++ b/src/ec/hp/kbc1126/ecfw_ptr.c @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include "ecfw_ptr.h" + +/* + * Address info for EC SMSC KBC1098/KBC1126 to find their firmware blobs, + * linked to CONFIG_ECFW_PTR_ADDR via src/arch/x86/bootblock.ld + */ +__attribute__((used, __section__(".ecfw_ptr"))) +const struct ecfw_ptr ecfw_ptr = { + .fw1.off = cpu_to_be16((uint16_t)(CONFIG_KBC1126_FW1_OFFSET >> 8)), + .fw1.inv = cpu_to_be16((uint16_t)~(CONFIG_KBC1126_FW1_OFFSET >> 8)), + .fw2.off = cpu_to_be16((uint16_t)(CONFIG_KBC1126_FW2_OFFSET >> 8)), + .fw2.inv = cpu_to_be16((uint16_t)~(CONFIG_KBC1126_FW2_OFFSET >> 8)), +}; diff --git a/src/ec/hp/kbc1126/ecfw_ptr.h b/src/ec/hp/kbc1126/ecfw_ptr.h new file mode 100644 index 0000000000..acf54f20dd --- /dev/null +++ b/src/ec/hp/kbc1126/ecfw_ptr.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _EC_HP_KBC1126_PTR_H +#define _EC_HP_KBC1126_PTR_H + +#include + +struct __attribute__((__packed__)) ecfw_addr { + /* 8-byte offset of firmware blob in big endian */ + uint16_t off; + /* bitwise inverse of "off", for error checking */ + uint16_t inv; +}; + +struct __attribute__((__packed__)) ecfw_ptr { + struct ecfw_addr fw1; + struct ecfw_addr fw2; +}; + +#endif