diff --git a/3rdparty/dasharo-blobs b/3rdparty/dasharo-blobs index 8dce760434d..b1e4c3ad236 160000 --- a/3rdparty/dasharo-blobs +++ b/3rdparty/dasharo-blobs @@ -1 +1 @@ -Subproject commit 8dce760434d3cf3c6acfc7c2f07028d37365aa79 +Subproject commit b1e4c3ad2363ee36dfef76acf640a8d48a0237bf diff --git a/Makefile.mk b/Makefile.mk index 10f707b9d1d..c320f68d2b2 100644 --- a/Makefile.mk +++ b/Makefile.mk @@ -996,6 +996,14 @@ extract_nth=$(subst *,$(spc),$(patsubst -%-,%,$(word $(1), $(subst |,- -,-$(2)-) # multiple CBFSes in fmap regions, override it. regions-for-file ?= $(if $(value regions-for-file-$(1)), $(regions-for-file-$(1)), COREBOOT) +ifeq ($(CONFIG_INTEL_ADD_TOP_SWAP_BOOTBLOCK),y) +ifneq ($(CONFIG_INTEL_TOP_SWAP_SEPARATE_REGIONS),y) +TS_OPTIONS := -j $(CONFIG_INTEL_TOP_SWAP_BOOTBLOCK_SIZE) +else +regions-for-file = $(if $(value regions-for-file-$(1)), $(regions-for-file-$(1)), COREBOOT,COREBOOT_TS) +endif +endif + ifeq ($(CONFIG_CBFS_AUTOGEN_ATTRIBUTES),y) cbfs-autogen-attributes=-g endif @@ -1288,8 +1296,16 @@ $(obj)/fmap.fmap: $(obj)/fmap.fmd $(FMAPTOOL) echo " FMAP $(FMAPTOOL) -h $(obj)/fmap_config.h $< $@" $(FMAPTOOL) -h $(obj)/fmap_config.h -R $(obj)/fmap.desc $< $@ -ifeq ($(CONFIG_INTEL_ADD_TOP_SWAP_BOOTBLOCK),y) -TS_OPTIONS := -j $(CONFIG_INTEL_TOP_SWAP_BOOTBLOCK_SIZE) +ifneq ($(CONFIG_INTEL_TOP_SWAP_SEPARATE_REGIONS),y) +BB_FIT_REGION = COREBOOT +TS_FIT_REGION = COREBOOT +else +BB_FIT_REGION = BOOTBLOCK +TS_FIT_REGION = TOPSWAP +bootblock_add_params = -f $(objcbfs)/bootblock.bin \ + -n bootblock -t bootblock \ + -b -$(call file-size,$(objcbfs)/bootblock.bin) \ + $(TXTIBB) $(cbfs-autogen-attributes) $(TS_OPTIONS) $(CBFSTOOL_ADD_CMD_OPTIONS) endif ifneq ($(CONFIG_ARCH_X86),y) @@ -1304,7 +1320,9 @@ ifneq ($(CONFIG_UPDATE_IMAGE),y) $(obj)/coreboot.pre: $$(prebuilt-files) $(CBFSTOOL) $(obj)/fmap.fmap $(obj)/fmap.desc $(objcbfs)/bootblock.bin $(CBFSTOOL) $@.tmp create -M $(obj)/fmap.fmap -r $(shell cat $(obj)/fmap.desc) printf " BOOTBLOCK\n" +ifneq ($(CONFIG_INTEL_TOP_SWAP_SEPARATE_REGIONS),y) $(call add_bootblock,$@.tmp,$(objcbfs)/bootblock.bin) +endif # ifneq ($(CONFIG_INTEL_TOP_SWAP_SEPARATE_REGIONS),y) $(prebuild-files) true mv $@.tmp $@ else # ifneq ($(CONFIG_UPDATE_IMAGE),y) @@ -1334,6 +1352,15 @@ add_intermediate = \ $(1): $(obj)/coreboot.pre $(2) | $(INTERMEDIATE) \ $(eval INTERMEDIATE+=$(1)) $(eval PHONY+=$(1)) +ifeq ($(CONFIG_INTEL_TOP_SWAP_SEPARATE_REGIONS),y) +$(call add_intermediate, prep_bb_regions, $(CBFSTOOL)) + @printf " PREP place bootblocks in BOOTBLOCK and TOPSWAP\n" + @printf " BOOTBLOCK\n" + $(CBFSTOOL) $< add -r $(BB_FIT_REGION) $(bootblock_add_params) + @printf " TOPSWAP\n" + $(CBFSTOOL) $< add -r $(TS_FIT_REGION) $(bootblock_add_params) +endif + $(obj)/coreboot.rom: $(obj)/coreboot.pre $(CBFSTOOL) $(IFITTOOL) $$(INTERMEDIATE) @printf " CBFS $(subst $(obj)/,,$(@))\n" # The full ROM may be larger than the CBFS part, so create an empty @@ -1342,11 +1369,11 @@ $(obj)/coreboot.rom: $(obj)/coreboot.pre $(CBFSTOOL) $(IFITTOOL) $$(INTERMEDIATE dd if=$(obj)/coreboot.pre of=$@.tmp bs=8192 conv=notrunc 2> /dev/null ifeq ($(CONFIG_CPU_INTEL_FIRMWARE_INTERFACE_TABLE),y) # Print final FIT table - $(IFITTOOL) -f $@.tmp -D -r COREBOOT + $(IFITTOOL) -f $@.tmp -D -r $(BB_FIT_REGION) # Print final TS BOOTBLOCK FIT table ifeq ($(CONFIG_INTEL_ADD_TOP_SWAP_BOOTBLOCK),y) @printf " TOP SWAP FIT table\n" - $(IFITTOOL) -f $@.tmp -D $(TS_OPTIONS) -r COREBOOT + $(IFITTOOL) -f $@.tmp -D $(TS_OPTIONS) -r $(TS_FIT_REGION) endif # CONFIG_INTEL_ADD_TOP_SWAP_BOOTBLOCK endif # CONFIG_CPU_INTEL_FIRMWARE_INTERFACE_TABLE mv $@.tmp $@ diff --git a/build.sh b/build.sh index 3493287b7a2..73fbb402c8e 100755 --- a/build.sh +++ b/build.sh @@ -359,7 +359,7 @@ case "$CMD" in build_msi ddr5 "Z790-P DDR5 " ;; "vp66xx" | "VP66XX") - BOARD="vp66xx" + BOARD="vp66xx_cmos_edk2" build_protectli_vault ;; "vp46xx" | "VP46XX") diff --git a/configs/config.protectli_vp66xx_cmos_edk2 b/configs/config.protectli_vp66xx_cmos_edk2 new file mode 100644 index 00000000000..4f25318fe3a --- /dev/null +++ b/configs/config.protectli_vp66xx_cmos_edk2 @@ -0,0 +1,62 @@ +CONFIG_LOCALVERSION="v0.9.3-rc1" +CONFIG_USE_OPTION_TABLE=y +CONFIG_VENDOR_PROTECTLI=y +CONFIG_PCIEXP_L1_SUB_STATE=y +CONFIG_PCIEXP_CLK_PM=y +CONFIG_IFD_BIN_PATH="3rdparty/dasharo-blobs/$(MAINBOARDDIR)/descriptor.bin" +CONFIG_ME_BIN_PATH="3rdparty/dasharo-blobs/$(MAINBOARDDIR)/me.bin" +CONFIG_CONSOLE_CBMEM_BUFFER_SIZE=0x100000 +CONFIG_HAVE_IFD_BIN=y +CONFIG_BOARD_PROTECTLI_VP66XX=y +CONFIG_POWER_STATE_OFF_AFTER_FAILURE=y +CONFIG_HAVE_ME_BIN=y +CONFIG_ME_REGION_ALLOW_CPU_READ_ACCESS=y +CONFIG_PCIEXP_LANE_ERR_STAT_CLEAR=y +CONFIG_DRIVERS_EFI_VARIABLE_STORE=y +CONFIG_DRIVERS_EFI_FW_INFO=y +CONFIG_DRIVERS_GENERIC_CBFS_SERIAL=y +CONFIG_DRIVERS_GENERIC_CBFS_UUID=y +CONFIG_TPM2=y +# CONFIG_CONSOLE_USE_ANSI_ESCAPES is not set +CONFIG_POST_DEVICE_LPC=y +CONFIG_PAYLOAD_EDK2=y +CONFIG_EDK2_SERIAL_SUPPORT=y +CONFIG_DASHARO=y +CONFIG_EDK2_DASHARO_SERIAL_REDIRECTION_DEFAULT_ENABLE=y +# CONFIG_EDK2_SECURE_BOOT_DEFAULT_ENABLE is not set +CONFIG_EDK2_HAVE_2ND_UART=y +CONFIG_EDK2_DASHARO_SERIAL_REDIRECTION2_DEFAULT_ENABLE=y +CONFIG_EDK2_DASHARO_CPU_CONFIG=y +CONFIG_EDK2_CORE_DISABLE_OPTION=y +CONFIG_EDK2_HYPERTHREADING_OPTION=y +CONFIG_EDK2_BOOT_MENU_KEY=0x0015 +CONFIG_EDK2_SETUP_MENU_KEY=0x0008 +CONFIG_EDK2_DISABLE_OPTION_ROMS=y +CONFIG_EDK2_CREATE_PREINSTALLED_BOOT_OPTIONS=y +CONFIG_EDK2_SETUP_PASSWORD=y +CONFIG_EDK2_DASHARO_SYSTEM_FEATURES=y +CONFIG_EDK2_DASHARO_SECURITY_OPTIONS=y +CONFIG_EDK2_DASHARO_USB_CONFIG=y +CONFIG_EDK2_DASHARO_POWER_CONFIG=y +CONFIG_EDK2_FAN_CURVE_OPTION=y +CONFIG_EDK2_FAN_OFF_CURVE_OPTION=y +CONFIG_EDK2_CPU_THROTTLING_THRESHOLD_OPTION=y +CONFIG_EDK2_DASHARO_NETWORK_BOOT_DEFAULT_ENABLE=y +CONFIG_EDK2_USE_EDK2_PLATFORMS=y +CONFIG_EDK2_PLATFORMS_REPOSITORY="https://github.com/Dasharo/edk2-platforms" +CONFIG_EDK2_PLATFORMS_TAG_OR_REV="1002a59639f111a2f8178b77d1f5fde0ea8d976f" +CONFIG_EDK2_CBMEM_LOGGING=y +CONFIG_EDK2_FOLLOW_BGRT_SPEC=y +# CONFIG_EDK2_PRIORITIZE_INTERNAL is not set +# CONFIG_EDK2_PS2_SUPPORT is not set +CONFIG_EDK2_SERIAL_SUPPORT=y +CONFIG_BUILD_IPXE=y +CONFIG_IPXE_ADD_SCRIPT=y +CONFIG_IPXE_SCRIPT="3rdparty/dasharo-blobs/dasharo/protectli.ipxe" +CONFIG_IPXE_CUSTOM_BUILD_ID="0123456789" +CONFIG_EDK2_ENABLE_IPXE=y +CONFIG_EDK2_IPXE_OPTION_NAME="Network Boot and Utilities" +CONFIG_DEFAULT_CONSOLE_LOGLEVEL_0=y +# CONFIG_CONSOLE_USE_LOGLEVEL_PREFIX is not set +# CONFIG_CONSOLE_USE_ANSI_ESCAPES is not set +CONFIG_POST_DEVICE_LPC=y diff --git a/configs/config.protectli_vp66xx_cmos_seabios b/configs/config.protectli_vp66xx_cmos_seabios new file mode 100644 index 00000000000..948f34fd8c4 --- /dev/null +++ b/configs/config.protectli_vp66xx_cmos_seabios @@ -0,0 +1,24 @@ +CONFIG_LOCALVERSION="v0.9.3-rc1" +CONFIG_VENDOR_PROTECTLI=y +CONFIG_BOARD_PROTECTLI_VP66XX=y +CONFIG_PCIEXP_L1_SUB_STATE=y +CONFIG_PCIEXP_CLK_PM=y +CONFIG_IFD_BIN_PATH="3rdparty/dasharo-blobs/$(MAINBOARDDIR)/descriptor.bin" +CONFIG_ME_BIN_PATH="3rdparty/dasharo-blobs/$(MAINBOARDDIR)/me.bin" +CONFIG_CONSOLE_CBMEM_BUFFER_SIZE=0x100000 +CONFIG_HAVE_IFD_BIN=y +CONFIG_POWER_STATE_OFF_AFTER_FAILURE=y +CONFIG_HAVE_ME_BIN=y +CONFIG_ME_REGION_ALLOW_CPU_READ_ACCESS=y +CONFIG_PCIEXP_LANE_ERR_STAT_CLEAR=y +CONFIG_DRIVERS_GENERIC_CBFS_SERIAL=y +CONFIG_DRIVERS_GENERIC_CBFS_UUID=y +CONFIG_TPM2=y +CONFIG_BOOTMEDIA_LOCK_CONTROLLER=y +CONFIG_BOOTMEDIA_SMM_BWP=y +# CONFIG_CONSOLE_USE_ANSI_ESCAPES is not set +CONFIG_POST_DEVICE_LPC=y +# CONFIG_OPTION_BACKEND_NONE is not set +CONFIG_HAVE_OPTION_TABLE=y +CONFIG_HAVE_CMOS_DEFAULT=y +CONFIG_USE_OPTION_TABLE=y diff --git a/src/cpu/intel/fit/Makefile.mk b/src/cpu/intel/fit/Makefile.mk index 0661984f155..5c2ed7379f2 100644 --- a/src/cpu/intel/fit/Makefile.mk +++ b/src/cpu/intel/fit/Makefile.mk @@ -17,9 +17,14 @@ ifneq ($(CONFIG_INTEL_FIT_LOC),) intel_fit-COREBOOT-position := $(CONFIG_INTEL_FIT_LOC) endif +ifeq ($(CONFIG_INTEL_TOP_SWAP_SEPARATE_REGIONS),y) +regions-for-file-intel_fit = BOOTBLOCK +regions-for-file-intel_fit_ts = TOPSWAP +endif + $(call add_intermediate, set_fit_ptr, $(IFITTOOL)) @printf " UPDATE-FIT set FIT pointer to table\n" - $(IFITTOOL) -f $< -F -n intel_fit -r COREBOOT -c + $(IFITTOOL) -f $< -F -n intel_fit -r $(BB_FIT_REGION) -c FIT_ENTRY=$(call strip_quotes, $(CONFIG_INTEL_TOP_SWAP_FIT_ENTRY_FMAP_REG)) @@ -28,22 +33,23 @@ ifneq ($(CONFIG_UPDATE_IMAGE),y) # never update the bootblock ifneq ($(CONFIG_CPU_MICROCODE_CBFS_NONE)$(CONFIG_CPU_INTEL_MICROCODE_CBFS_SPLIT_BINS),y) $(call add_intermediate, add_mcu_fit, set_fit_ptr $(IFITTOOL)) + @printf "$(call regions-for-file,$(cpu_microcode_blob.bin))" @printf " UPDATE-FIT Microcode\n" - $(IFITTOOL) -f $< -a -n cpu_microcode_blob.bin -t 1 -s $(CONFIG_CPU_INTEL_NUM_FIT_ENTRIES) -r COREBOOT + $(IFITTOOL) -f $< -a -n cpu_microcode_blob.bin -t 1 -s $(CONFIG_CPU_INTEL_NUM_FIT_ENTRIES) -r $(BB_FIT_REGION) -R COREBOOT # Second FIT in TOP_SWAP bootblock ifeq ($(CONFIG_INTEL_ADD_TOP_SWAP_BOOTBLOCK),y) $(call add_intermediate, set_ts_fit_ptr, $(IFITTOOL)) @printf " UPDATE-FIT Top Swap: set FIT pointer to table\n" - $(IFITTOOL) -f $< -F -n intel_fit_ts -r COREBOOT $(TS_OPTIONS) + $(IFITTOOL) -f $< -F -n intel_fit_ts -r $(TS_FIT_REGION) $(TS_OPTIONS) $(call add_intermediate, add_ts_mcu_fit, set_ts_fit_ptr $(IFITTOOL)) @printf " UPDATE-FIT Top Swap: Microcode\n" ifneq ($(FIT_ENTRY),) - $(IFITTOOL) -f $< -A -n $(FIT_ENTRY) -t 1 -s $(CONFIG_CPU_INTEL_NUM_FIT_ENTRIES) $(TS_OPTIONS) -r COREBOOT + $(IFITTOOL) -f $< -A -n $(FIT_ENTRY) -t 1 -s $(CONFIG_CPU_INTEL_NUM_FIT_ENTRIES) $(TS_OPTIONS) -r $(TS_FIT_REGION) endif # FIT_ENTRY - $(IFITTOOL) -f $< -a -n cpu_microcode_blob.bin -t 1 -s $(CONFIG_CPU_INTEL_NUM_FIT_ENTRIES) $(TS_OPTIONS) -r COREBOOT + $(IFITTOOL) -f $< -a -n cpu_microcode_blob.bin -t 1 -s $(CONFIG_CPU_INTEL_NUM_FIT_ENTRIES) $(TS_OPTIONS) -r $(TS_FIT_REGION) -R COREBOOT cbfs-files-y += intel_fit_ts intel_fit_ts-file := fit_table.c:struct diff --git a/src/include/fmap.h b/src/include/fmap.h index 761e742f560..b21701e87ae 100644 --- a/src/include/fmap.h +++ b/src/include/fmap.h @@ -8,6 +8,10 @@ #include #include +/* Return the name of the boot region. Falls back to COREBOOT, if not overriden + * by any multi-slot mechanism (e.g Intel Top Swap, vboot). */ +const char *cbfs_fmap_region_hint(const char *default_region); + /* Locate the named area in the fmap and fill in a region device representing * that area. The region is a sub-region of the readonly boot media. Return * 0 on success, < 0 on error. */ diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c index df34594a53c..d501e782c3b 100644 --- a/src/lib/cbfs.c +++ b/src/lib/cbfs.c @@ -31,6 +31,11 @@ struct mem_pool cbfs_cache = MEM_POOL_INIT(_cbfs_cache, REGION_SIZE(cbfs_cache), CONFIG_CBFS_CACHE_ALIGN); #endif +__weak const char *cbfs_fmap_region_hint(const char *default_region) +{ + return default_region; +} + static void switch_to_postram_cache(int unused) { if (_preram_cbfs_cache != _postram_cbfs_cache) @@ -670,6 +675,7 @@ enum cb_err cbfs_init_boot_device(const struct cbfs_boot_device *cbd, const struct cbfs_boot_device *cbfs_get_boot_device(bool force_ro) { + printk(BIOS_DEBUG, "Starting cbfs_boot_device\n"); static struct cbfs_boot_device ro; /* Ensure we always init RO mcache, even if the first file is from the RW CBFS. @@ -693,8 +699,14 @@ const struct cbfs_boot_device *cbfs_get_boot_device(bool force_ro) if (region_device_sz(&ro.rdev)) return &ro; - if (fmap_locate_area_as_rdev("COREBOOT", &ro.rdev)) - die("Cannot locate primary CBFS"); + /* Falls back to the default COREBOOT region if no overriding mechanisms are in + place (e.g. Intel Top Swap). */ + const char *region = cbfs_fmap_region_hint("COREBOOT"); + + if (fmap_locate_area_as_rdev(region, &ro.rdev)) + die("Cannot locate %s CBFS", region); + + printk(BIOS_INFO, "Booting from %s region\n", region); if (ENV_INITIAL_STAGE) { enum cb_err err = cbfs_init_boot_device(&ro, metadata_hash_get()); diff --git a/src/mainboard/protectli/vault_adl_p/Kconfig b/src/mainboard/protectli/vault_adl_p/Kconfig index aa8da560753..815ab48eb89 100644 --- a/src/mainboard/protectli/vault_adl_p/Kconfig +++ b/src/mainboard/protectli/vault_adl_p/Kconfig @@ -16,6 +16,13 @@ config BOARD_SPECIFIC_OPTIONS select INTEL_GMA_HAVE_VBT select MEMORY_MAPPED_TPM select USE_DDR5 + select HAVE_OPTION_TABLE + select HAVE_CMOS_DEFAULT + select USE_OPTION_TABLE + select INTEL_HAS_TOP_SWAP + select INTEL_ADD_TOP_SWAP_BOOTBLOCK + select INTEL_TOP_SWAP_SEPARATE_REGIONS + select INTEL_TOP_SWAP_OPTION_CONTROL config MAINBOARD_DIR default "protectli/vault_adl_p" @@ -67,7 +74,8 @@ config SOC_INTEL_CSE_SEND_EOP_EARLY default n config FMDFILE - default "src/mainboard/\$(CONFIG_MAINBOARD_DIR)/vboot-rwa.fmd" if VBOOT && VBOOT_SLOTS_RW_A + default "src/mainboard/\$(CONFIG_MAINBOARD_DIR)/vboot-rwa.fmd" if VBOOT + default "src/mainboard/\$(CONFIG_MAINBOARD_DIR)/top_swap.fmd" if INTEL_HAS_TOP_SWAP config BEEP_ON_BOOT bool "Beep on successful boot" diff --git a/src/mainboard/protectli/vault_adl_p/cmos.default b/src/mainboard/protectli/vault_adl_p/cmos.default new file mode 100644 index 00000000000..ee8f645e365 --- /dev/null +++ b/src/mainboard/protectli/vault_adl_p/cmos.default @@ -0,0 +1,6 @@ +## SPDX-License-Identifier: GPL-2.0-only + +boot_option=Fallback +debug_level=Debug +me_state=Disable +attempt_slot_b=Disable diff --git a/src/mainboard/protectli/vault_adl_p/cmos.layout b/src/mainboard/protectli/vault_adl_p/cmos.layout new file mode 100644 index 00000000000..d5b0813cd18 --- /dev/null +++ b/src/mainboard/protectli/vault_adl_p/cmos.layout @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: GPL-2.0-only + +entries + +0 384 r 0 reserved_memory + +# RTC_BOOT_BYTE (coreboot hardcoded) +384 1 e 4 boot_option +388 4 h 0 reboot_counter + +# RTC_CLK_ALTCENTURY +400 8 r 0 century + +412 4 e 6 debug_level +416 1 e 2 me_state +417 3 h 0 me_state_counter +420 1 e 7 attempt_slot_b + +# CMOS_VSTART_ramtop +800 80 r 0 ramtop + +984 16 h 0 check_sum + +enumerations + +2 0 Enable +2 1 Disable + +4 0 Fallback +4 1 Normal + +6 0 Emergency +6 1 Alert +6 2 Critical +6 3 Error +6 4 Warning +6 5 Notice +6 6 Info +6 7 Debug +6 8 Spew + +7 0 Disable +7 1 Enable + +checksums + +checksum 408 799 984 diff --git a/src/mainboard/protectli/vault_adl_p/top_swap.fmd b/src/mainboard/protectli/vault_adl_p/top_swap.fmd new file mode 100644 index 00000000000..703d63701b3 --- /dev/null +++ b/src/mainboard/protectli/vault_adl_p/top_swap.fmd @@ -0,0 +1,40 @@ +FLASH 16M { + SI_ALL@0x0 { + SI_DESC 4K + SI_ME 0x4c0000 + SI_DEVICEEXT2 0xbf000 + } + SI_BIOS@0x580000 0xa80000 { + SMMSTORE(PRESERVE) 256K + + RW_MISC 320K { + UNIFIED_MRC_CACHE(PRESERVE) { + RECOVERY_MRC_CACHE 128K + RW_MRC_CACHE 128K + } + RW_VPD(PRESERVE) 8K + RW_NVRAM(PRESERVE) 24K + } + + BOOTSPLASH(CBFS) 512K + + RW_SECTION_A { + VBLOCK_A 64K + COREBOOT_TS(CBFS) + RW_FWID_A 0x100 + } + + WP_RO 4M { + RO_VPD(PRESERVE) 16K + RO_SECTION { + FMAP 2K + RO_FRID 0x100 + RO_FRID_PAD 0x700 + GBB 12K + COREBOOT(CBFS) + } + } + TOPSWAP(CBFS) 512K + BOOTBLOCK(CBFS) 512K + } +} diff --git a/src/soc/intel/alderlake/bootblock/bootblock.c b/src/soc/intel/alderlake/bootblock/bootblock.c index e9a691c37bf..7ef78b6884f 100644 --- a/src/soc/intel/alderlake/bootblock/bootblock.c +++ b/src/soc/intel/alderlake/bootblock/bootblock.c @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -34,4 +35,7 @@ void bootblock_soc_init(void) if (CONFIG(INTEL_CBNT_LOGGING)) intel_cbnt_log_registers(); + + if (CONFIG(INTEL_TOP_SWAP_OPTION_CONTROL)) + sync_rtc_buc_top_swap(); } diff --git a/src/soc/intel/common/Kconfig.common b/src/soc/intel/common/Kconfig.common index 7ce93d45937..7037dd76af9 100644 --- a/src/soc/intel/common/Kconfig.common +++ b/src/soc/intel/common/Kconfig.common @@ -23,7 +23,19 @@ config INTEL_TOP_SWAP_BOOTBLOCK_SIZE default 0x10000 help Set this config to a supported topswap size. - Valid sizes: 0x10000 0x20000 0x40000 0x80000 0x100000 + Valid sizes: 0x10000/0x20000/0x40000/0x80000/0x100000/ + 0x200000/0x400000/0x800000. The maximum size + varies depending on the platform. + +config INTEL_IFD_SET_TOP_SWAP_BOOTBLOCK_SIZE + bool "Replace the TSBS value with INTEL_TOP_SWAP_BOOTBLOCK_SIZE" + default n + depends on HAVE_IFD_BIN + help + Set to use ifdtool to replace the Top Swap Block Size + PCH strap value in the Intel Firmware Descriptor + with INTEL_TOP_SWAP_BOOTBLOCK_SIZE + config INTEL_TOP_SWAP_FIT_ENTRY_FMAP_REG string @@ -36,6 +48,24 @@ config INTEL_TOP_SWAP_FIT_ENTRY_FMAP_REG onto ifittool (-A -n option). ifittool will not parse the region for MCU entries, and only locate the region and insert its address into FIT. +config INTEL_TOP_SWAP_SEPARATE_REGIONS + bool "Place the regular and Top Swap bootblocks in separate fmap regions" + depends on INTEL_ADD_TOP_SWAP_BOOTBLOCK && BOOTBLOCK_IN_CBFS + default n + help + Place the bootblocks in BOOTBLOCK and TOPSWAP regions for easy access, to + facilitate firmware updates using the Top Swap as Slot A/Slot B redundancy. + Requires a custom .fmd with the regions added at the end. + +config INTEL_TOP_SWAP_OPTION_CONTROL + bool "Toggle the Top Swap functionality using a CMOS option" + depends on INTEL_TOP_SWAP_SEPARATE_REGIONS && USE_OPTION_TABLE && SOC_INTEL_ALDERLAKE + default n + help + Switch between the Top Swap bootblocks using the "attempt_slot_b" CMOS + option. Note that the option must be present in the board's cmos.layout. + file. + endif config SOC_INTEL_COMMON diff --git a/src/soc/intel/common/block/include/intelblocks/rtc.h b/src/soc/intel/common/block/include/intelblocks/rtc.h index 0f09d7e0fb7..ca53996c6b5 100644 --- a/src/soc/intel/common/block/include/intelblocks/rtc.h +++ b/src/soc/intel/common/block/include/intelblocks/rtc.h @@ -3,6 +3,8 @@ #ifndef SOC_INTEL_COMMON_BLOCK_RTC_H #define SOC_INTEL_COMMON_BLOCK_RTC_H +#define TOP_SWAP_ENABLE_CMOS_OPTION "attempt_slot_b" + /* Top swap feature enable/disable config */ enum ts_config { TS_DISABLE, @@ -32,6 +34,11 @@ void configure_rtc_buc_top_swap(enum ts_config ts_state); */ enum ts_config get_rtc_buc_top_swap_status(void); +/* + * Set/unset the top swap bit based on TOP_SWAP_ENABLE_CMOS_OPTION state + */ +void sync_rtc_buc_top_swap(void); + /* Set RTC Configuration BILD bit. */ void rtc_conf_set_bios_interface_lockdown(void); #endif /* SOC_INTEL_COMMON_BLOCK_RTC_H */ diff --git a/src/soc/intel/common/block/rtc/rtc.c b/src/soc/intel/common/block/rtc/rtc.c index 5a5de912bba..718aab41987 100644 --- a/src/soc/intel/common/block/rtc/rtc.c +++ b/src/soc/intel/common/block/rtc/rtc.c @@ -1,9 +1,12 @@ /* SPDX-License-Identifier: GPL-2.0-only */ +#include #include #include -#include +#include #include +#include +#include /* RTC PCR configuration */ #define PCR_RTC_CONF 0x3400 @@ -53,4 +56,34 @@ enum ts_config get_rtc_buc_top_swap_status(void) else return TS_DISABLE; } + +void sync_rtc_buc_top_swap(void) +{ + uint8_t cmos_slotb_option, topswap_control_bit; + cmos_slotb_option = get_uint_option(TOP_SWAP_ENABLE_CMOS_OPTION, 0); + topswap_control_bit = get_rtc_buc_top_swap_status(); + printk(BIOS_INFO, "Top Swap: CMOS option state: %d\n", cmos_slotb_option); + printk(BIOS_INFO, "Top Swap: RTC BUC control bit: %d\n", topswap_control_bit); + if (cmos_slotb_option != topswap_control_bit) { + configure_rtc_buc_top_swap(cmos_slotb_option); + printk(BIOS_INFO, "Top Swap: RTC BUC control bit set to: %d, platform reset is necessary\n", get_rtc_buc_top_swap_status()); + board_reset(); + } +} + +/* + * Select the FMAP region to continue booting from, depending on the state of + * Top Swap + */ +const char *cbfs_fmap_region_hint(const char *default_region) +{ + if (!CONFIG(INTEL_TOP_SWAP_OPTION_CONTROL)) + return default_region; + + if (get_rtc_buc_top_swap_status()) + return "COREBOOT_TS"; + else + return "COREBOOT"; +} + #endif diff --git a/src/southbridge/intel/common/firmware/Makefile.mk b/src/southbridge/intel/common/firmware/Makefile.mk index a7431902c45..10b1c4c906b 100644 --- a/src/southbridge/intel/common/firmware/Makefile.mk +++ b/src/southbridge/intel/common/firmware/Makefile.mk @@ -49,9 +49,22 @@ ifeq ($(CONFIG_HAVE_EC_BIN),y) add_intel_firmware: $(call strip_quotes,$(CONFIG_EC_BIN_PATH)) endif add_intel_firmware: $(obj)/coreboot.pre $(IFDTOOL) +ifeq ($(INTEL_IFD_SET_TOP_SWAP_BOOTBLOCK_SIZE),y) + printf " IFDTOOL Modifying top swap PCH strap in IFD\n" + printf " $(IFDTOOL_USE_CHIPSET)" + $(objutil)/ifdtool/ifdtool \ + $(IFDTOOL_USE_CHIPSET) \ + -T $(CONFIG_INTEL_TOP_SWAP_BOOTBLOCK_SIZE) \ + -O $(obj)/ifd_custom_tsbs \ + $(IFD_BIN_PATH) + printf " DD Adding Intel Firmware Descriptor\n" + dd if=$(obj)/ifd_custom_tsbs\ + of=$(obj)/coreboot.pre conv=notrunc >/dev/null 2>&1 +else printf " DD Adding Intel Firmware Descriptor\n" dd if=$(IFD_BIN_PATH) \ of=$(obj)/coreboot.pre conv=notrunc >/dev/null 2>&1 +endif ifeq ($(CONFIG_IFDTOOL_DISABLE_ME),y) printf " IFDTOOL set AltMeDisable/HAP bit\n" $(objutil)/ifdtool/ifdtool \ diff --git a/util/cbfstool/fit.c b/util/cbfstool/fit.c index d4e48f19462..2c625a37e7b 100644 --- a/util/cbfstool/fit.c +++ b/util/cbfstool/fit.c @@ -491,7 +491,7 @@ static void update_fit_key_manifest_entry(struct fit_table *fit, /* Special case for ucode CBFS file, as it might contain more than one ucode */ int fit_add_microcode_file(struct fit_table *fit, - struct cbfs_image *image, + struct cbfs_image *file_source_image, const char *blob_name, fit_offset_converter_t offset_helper, const size_t max_fit_entries) @@ -507,7 +507,7 @@ int fit_add_microcode_file(struct fit_table *fit, return 1; } - if (parse_microcode_blob(image, blob_name, &mcus_found, mcus, + if (parse_microcode_blob(file_source_image, blob_name, &mcus_found, mcus, max_fit_entries)) { free(mcus); return 1; @@ -515,7 +515,7 @@ int fit_add_microcode_file(struct fit_table *fit, for (i = 0; i < mcus_found; i++) { if (fit_add_entry(fit, - offset_to_ptr(offset_helper, &image->buffer, + offset_to_ptr(offset_helper, &file_source_image->buffer, mcus[i].offset), 0, FIT_TYPE_MICROCODE, diff --git a/util/cbfstool/fit.h b/util/cbfstool/fit.h index 6d7681f7109..9df546ffa59 100644 --- a/util/cbfstool/fit.h +++ b/util/cbfstool/fit.h @@ -54,7 +54,7 @@ int fit_delete_entry(struct fit_table *fit, const size_t idx); int fit_add_microcode_file(struct fit_table *fit, - struct cbfs_image *image, + struct cbfs_image *file_source_image, const char *blob_name, fit_offset_converter_t offset_helper, const size_t max_fit_entries); diff --git a/util/cbfstool/ifittool.c b/util/cbfstool/ifittool.c index d0d9431804b..d289ef746aa 100644 --- a/util/cbfstool/ifittool.c +++ b/util/cbfstool/ifittool.c @@ -15,10 +15,11 @@ /* Global variables */ partitioned_file_t *image_file; -static const char *optstring = "H:j:f:r:d:t:n:s:cAaDvhF?"; +static const char *optstring = "H:j:f:r:R:d:t:n:s:cAaDvhF?"; static struct option long_options[] = { {"file", required_argument, 0, 'f' }, {"region", required_argument, 0, 'r' }, + {"file-region", required_argument, 0, 'R' }, {"add-cbfs-entry", no_argument, 0, 'a' }, {"add-region", no_argument, 0, 'A' }, {"del-entry", required_argument, 0, 'd' }, @@ -54,10 +55,12 @@ static void usage(const char *name) "\t\t-D|--dump : Dump FIT table (at end of operation)\n" "\t\t-c|--clear-table : Remove all existing entries (do not update)\n" "\t\t-j|--topswap-size : Use second FIT table if non zero\n" + "\t\t-R|--file-region : The FMAP region of the added file,\n" + "\t\t : defaults to the value of -r\n" "\tREQUIRED ARGUMENTS:\n" "\t\t-f|--file name : The file containing the CBFS\n" "\t\t-s|--max-table-size : The number of possible FIT entries in table\n" - "\t\t-r|--region : The FMAP region to operate on\n" + "\t\t-r|--region : The FMAP region of the FIT table\n" , name); } @@ -139,6 +142,7 @@ int main(int argc, char *argv[]) const char *input_file = NULL; const char *name = NULL; const char *region_name = NULL; + const char *file_region_name = NULL; enum fit_operation op = NO_OP; bool dump = false, clear_table = false; size_t max_table_size = 0; @@ -228,6 +232,9 @@ int main(int argc, char *argv[]) case 'r': region_name = optarg; break; + case 'R': + file_region_name = optarg; + break; case 's': max_table_size = atoi(optarg); break; @@ -282,7 +289,9 @@ int main(int argc, char *argv[]) op != NO_OP || clear_table); struct buffer image_region; + struct buffer file_image_region; + // Open the FIT table's region if (!partitioned_file_read_region(&image_region, image_file, region_name)) { partitioned_file_close(image_file); @@ -290,16 +299,37 @@ int main(int argc, char *argv[]) return 1; } + // If the added file region is not specified, default to the FIT table's one. + if (!file_region_name) { + file_image_region = image_region; + } else { + // Open the -n file-to-add region + if (!partitioned_file_read_region(&file_image_region, image_file, + file_region_name)) { + partitioned_file_close(image_file); + ERROR("The image will be left unmodified.\n"); + return 1; + } + } + struct buffer bootblock; // The bootblock is part of the CBFS on x86 buffer_clone(&bootblock, &image_region); + // Open the FIT table's CBFS struct cbfs_image image; if (cbfs_image_from_buffer(&image, &image_region, headeroffset)) { partitioned_file_close(image_file); return 1; } + // Open the -n file-to-add CBFS + struct cbfs_image file_source_image; + if (cbfs_image_from_buffer(&file_source_image, &file_image_region, HEADER_OFFSET_UNKNOWN)) { + partitioned_file_close(image_file); + return 1; + } + struct fit_table *fit = NULL; if (op != SET_FIT_PTR_OP) { fit = fit_get_table(&bootblock, convert_to_from_top_aligned, topswap_size); @@ -339,8 +369,8 @@ int main(int argc, char *argv[]) case ADD_CBFS_OP: { if (fit_type == FIT_TYPE_MICROCODE) { - if (fit_add_microcode_file(fit, &image, name, - convert_to_from_top_aligned, + if (fit_add_microcode_file(fit, &file_source_image, name, + convert_to_from_absolute_top_aligned, max_table_size)) { return 1; } @@ -348,7 +378,7 @@ int main(int argc, char *argv[]) uint32_t offset, len; struct cbfs_file *cbfs_file; - cbfs_file = cbfs_get_entry(&image, name); + cbfs_file = cbfs_get_entry(&file_source_image, name); if (!cbfs_file) { partitioned_file_close(image_file); ERROR("%s not found in CBFS.\n", name); @@ -356,9 +386,9 @@ int main(int argc, char *argv[]) } len = be32toh(cbfs_file->len); - offset = offset_to_ptr(convert_to_from_top_aligned, - &image.buffer, - cbfs_get_entry_addr(&image, cbfs_file) + + offset = offset_to_ptr(convert_to_from_absolute_top_aligned, + &file_source_image.buffer, + cbfs_get_entry_addr(&file_source_image, cbfs_file) + be32toh(cbfs_file->offset)); diff --git a/util/ifdtool/ifdtool.c b/util/ifdtool/ifdtool.c index cf726feacae..d44acae7a23 100644 --- a/util/ifdtool/ifdtool.c +++ b/util/ifdtool/ifdtool.c @@ -2389,6 +2389,16 @@ static void new_layout(const char *filename, char *image, int size, free(new_image); } +static uint32_t uint_log2(uint32_t n) +{ + int log = -1; + while (n) { + n >>= 1; + ++log; + } + return log; +} + static void print_version(void) { printf("ifdtool v%s -- ", IFDTOOL_VERSION); @@ -2447,6 +2457,9 @@ static void print_usage(const char *name) " wbg - Wellsburg\n" " -S | --setpchstrap Write a PCH strap\n" " -V | --newvalue The new value to write into PCH strap specified by -S\n" + " -T | --topswapsize Set the Top Swap Block Size PCH strap value\n" + " Possible values: 0x10000, 0x20000, 0x40000, 0x80000,\n" + " 0x100000, 0x200000, 0x400000, 0x800000\n" " -v | --version: print the version\n" " -h | --help: print this help\n\n" " is one of Descriptor, BIOS, ME, GbE, Platform Data, Secondary BIOS, " @@ -2462,9 +2475,9 @@ int main(int argc, char *argv[]) int mode_layout = 0, mode_newlayout = 0, mode_density = 0, mode_setstrap = 0; int mode_read = 0, mode_altmedisable = 0, altmedisable = 0, mode_fmap_template = 0; int mode_gpr0_disable = 0, mode_gpr0_enable = 0, mode_gpr0_status = 0; - char *region_type_string = NULL, *region_fname = NULL; - const char *layout_fname = NULL; - char *new_filename = NULL; + int mode_settopswapsize = 0; + char *region_type_string = NULL, *region_fname = NULL, *layout_fname = NULL; + char *new_filename = NULL, *top_swap_size_arg = NULL; int region_type = -1, inputfreq = 0; unsigned int value = 0; unsigned int pchstrap = 0; @@ -2496,10 +2509,11 @@ int main(int argc, char *argv[]) {"validate", 0, NULL, 't'}, {"setpchstrap", 1, NULL, 'S'}, {"newvalue", 1, NULL, 'V'}, + {"topswapsize", 1, NULL, 'T'}, {0, 0, 0, 0} }; - while ((opt = getopt_long(argc, argv, "S:V:df:F:D:C:M:xi:n:O:s:p:elrugEcvth?", + while ((opt = getopt_long(argc, argv, "S:V:df:F:D:C:M:xi:n:O:s:p:T:elrugEcvth?", long_options, &option_index)) != EOF) { switch (opt) { case 'd': @@ -2750,6 +2764,10 @@ int main(int argc, char *argv[]) case 't': mode_validate = 1; break; + case 'T': + mode_settopswapsize = 1; + top_swap_size_arg = optarg; + break; case 'v': print_version(); exit(EXIT_SUCCESS); @@ -2767,7 +2785,7 @@ int main(int argc, char *argv[]) } if ((mode_dump + mode_layout + mode_fmap_template + mode_extract + mode_inject + - mode_setstrap + mode_newlayout + (mode_spifreq | mode_em100 | + mode_setstrap + mode_settopswapsize + mode_newlayout + (mode_spifreq | mode_em100 | mode_unlocked | mode_locked) + mode_altmedisable + mode_validate + (mode_gpr0_disable | mode_gpr0_enable) + mode_gpr0_status) > 1) { fprintf(stderr, "You may not specify more than one mode.\n\n"); @@ -2776,7 +2794,7 @@ int main(int argc, char *argv[]) } if ((mode_dump + mode_layout + mode_fmap_template + mode_extract + mode_inject + - mode_setstrap + mode_newlayout + mode_spifreq + mode_em100 + + mode_setstrap + mode_settopswapsize + mode_newlayout + mode_spifreq + mode_em100 + mode_locked + mode_unlocked + mode_density + mode_altmedisable + mode_validate + (mode_gpr0_disable | mode_gpr0_enable) + mode_gpr0_status) == 0) { fprintf(stderr, "You need to specify a mode.\n\n"); @@ -2884,6 +2902,59 @@ int main(int argc, char *argv[]) if (mode_gpr0_status) is_gpr0_protected(image, size); + if (mode_settopswapsize) { + if (platform == -1) { + fprintf(stderr, "Error: No platform specified.\n"); + exit(EXIT_FAILURE); + } + struct fpsba *fpsba = find_fpsba(image, size); + uint32_t top_swap_size_offset = 0; + switch (platform) { + case PLATFORM_ADL: + // fixed bits for ADL-P / ADL-N + if (fpsba->pchstrp[0xd0 / 4] == 0x00000300) { + // fixed bits for ADL-P + if (((fpsba->pchstrp[0x7c / 4] >> 1) & 0xff) == 0x18) { + printf("Detected ADL-P flash descriptor\n"); + pchstrap = 0x4C / 4; + top_swap_size_offset = 4; + // fixed bits for ADL-N + } else if (((fpsba->pchstrp[0x7c / 4] >> 1) & 0xff) == 0x51) { + printf("Detected ADL-N flash descriptor\n"); + pchstrap = 0x4C / 4; + top_swap_size_offset = 4; + } + } + break; + default: + break; + } + if (pchstrap == 0) { + fprintf(stderr, "Setting top swap size not supported on selected platform.\n"); + exit(EXIT_FAILURE); + } + + uint32_t top_swap_size = strtoul(top_swap_size_arg, NULL, 0); + if (top_swap_size < 0x10000 || !IS_POWER_OF_2(top_swap_size) || top_swap_size > 0x800000) { + fprintf(stderr, + "Unsupported top swap size: %s\n" + "Supported top swap sizes:\n" + "\t0x10000, 0x20000, 0x40000, 0x80000, 0x100000,\n" + "\t0x200000, 0x400000, 0x800000\n", + top_swap_size_arg); + exit(EXIT_FAILURE); + } + // convert to 0x00-0x07 + top_swap_size = uint_log2(top_swap_size / 0x10000); + const struct fdbar *fdb = find_fd(image, size); + value = fpsba->pchstrp[pchstrap]; + value &= ~(0x7 << top_swap_size_offset); + value |= (top_swap_size << top_swap_size_offset); + + set_pchstrap(fpsba, fdb, pchstrap, value); + write_image(new_filename, image, size); + } + if (mode_setstrap) { struct fpsba *fpsba = find_fpsba(image, size); const struct fdbar *fdb = find_fd(image, size);