Makefile.inc: Generate master header and pointer as C structs

The makefiles don't like cbfs file names with spaces in them so update
the file name with '_' instead of spaces. To keep the master header at
the top of cbfs, add a placeholder.

This removes the need to handle the cbfs master header in cbfstool.
This functionality will be dropped in a later CL.

On x86 reserve some space in the linker script to add the pointer.
On non-x86 generate a pointer inside a C struct file.

As a bonus this would actually fix the master header pointer mechanism
on Intel/APL as only the bootblock inside IFWI gets memory mapped.

TESTED on thinkpad X201: SeaBIOS correctly finds the cbfs master
header.

Change-Id: I3ba01be7da1f09a8cac287751497c18cda97d293
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/59132
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Raul Rangel <rrangel@chromium.org>
diff --git a/Makefile.inc b/Makefile.inc
index 654b366..ff2b0c4 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -1120,18 +1120,7 @@
 	$(CBFSTOOL) $@.tmp write -u \
 		-r BOOTBLOCK \
 		-f $(objcbfs)/bootblock.bin
-	# make space for the CBFS master header pointer. "ptr_" is just
-	# arbitrary 4 bytes that will be overwritten by add-master-header.
-	printf "ptr_" > $@.tmp.2
-	$(CBFSTOOL) $@.tmp add \
-		-f $@.tmp.2 \
-		-n "header pointer" \
-		-t "cbfs header" \
-		-b -4 \
-		$(CBFSTOOL_ADD_CMD_OPTIONS)
-	rm -f $@.tmp.2
 endif # ifeq ($(CONFIG_ARCH_X86),y)
-	$(CBFSTOOL) $@.tmp add-master-header $(TS_OPTIONS) $(CBFSTOOL_ADD_CMD_OPTIONS)
 	$(prebuild-files) true
 	mv $@.tmp $@
 else # ifneq ($(CONFIG_UPDATE_IMAGE),y)
diff --git a/src/arch/x86/bootblock.ld b/src/arch/x86/bootblock.ld
index 0b908bb..d59eb27 100644
--- a/src/arch/x86/bootblock.ld
+++ b/src/arch/x86/bootblock.ld
@@ -73,9 +73,14 @@
 	_X86_RESET_VECTOR = .;
 	.reset . : {
 		*(.reset);
-		. = 15;
-		BYTE(0x00);
+		. = _X86_RESET_VECTOR_FILLING;
+		BYTE(0);
 	}
+	. = 0xfffffffc;
+	.header_pointer . : {
+		KEEP(*(.header_pointer));
+	}
+	_X86_RESET_VECTOR_FILLING = 15 - SIZEOF(.header_pointer);
 	_ebootblock = .;
 }
 
diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc
index f3da503..a930663 100644
--- a/src/lib/Makefile.inc
+++ b/src/lib/Makefile.inc
@@ -393,3 +393,18 @@
 ramstage-y += uuid.c
 
 romstage-$(CONFIG_SPD_CACHE_IN_FMAP) += spd_cache.c
+
+cbfs-files-y += cbfs_master_header
+cbfs_master_header-file := cbfs_master_header.c:struct
+cbfs_master_header-type := "cbfs header"
+cbfs_master_header-position := 0
+
+ifeq ($(CONFIG_ARCH_X86),y)
+$(call src-to-obj,bootblock,$(dir)/header_pointer.c): $(obj)/fmap_config.h
+bootblock-y += master_header_pointer.c
+else
+cbfs-files-y += header_pointer
+header_pointer-file := master_header_pointer.c:struct
+header_pointer-position := -4
+header_pointer-type := "cbfs header"
+endif
diff --git a/src/lib/cbfs_master_header.c b/src/lib/cbfs_master_header.c
new file mode 100644
index 0000000..d358d1a
--- /dev/null
+++ b/src/lib/cbfs_master_header.c
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <endian.h>
+#include <fmap_config.h>
+#include <commonlib/bsd/cbfs_serialized.h>
+
+struct cbfs_header header = {
+	.magic = cpu_to_be32(CBFS_HEADER_MAGIC),
+	.version = cpu_to_be32(CBFS_HEADER_VERSION),
+	/*
+	 * The offset and romsize fields within the master header are absolute
+	 * values within the boot media. As such, romsize needs to reflect
+	 * the end 'offset' for a CBFS. To achieve that the current buffer
+	 * representing the CBFS region's size is added to the offset of
+	 * the region within a larger image.
+	 */
+	.romsize = cpu_to_be32(FMAP_SECTION_COREBOOT_START + FMAP_SECTION_COREBOOT_SIZE
+			       - FMAP_SECTION_FLASH_START),
+	/*
+	 * The 4 bytes are left out for two reasons:
+	 * 1. the cbfs master header pointer resides there
+	 * 2. some cbfs implementations assume that an image that resides
+	 *    below 4GB has a bootblock and get confused when the end of the
+	 *    image is at 4GB == 0.
+	 */
+	.bootblocksize = cpu_to_be32(4),
+	.align = cpu_to_be32(CBFS_ALIGNMENT),
+	.offset = cpu_to_be32(FMAP_SECTION_COREBOOT_START - FMAP_SECTION_FLASH_START),
+	.architecture = cpu_to_be32(CBFS_ARCHITECTURE_UNKNOWN),
+};
diff --git a/src/lib/master_header_pointer.c b/src/lib/master_header_pointer.c
new file mode 100644
index 0000000..b114612
--- /dev/null
+++ b/src/lib/master_header_pointer.c
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <commonlib/bsd/cbfs_serialized.h>
+#include <endian.h>
+#include <fmap_config.h>
+#include <stdint.h>
+
+#if ENV_X86
+__attribute__((used, __section__(".header_pointer")))
+#endif
+
+#if FMAP_SECTION_COREBOOT_START < (0xffffffff - CONFIG_ROM_SIZE + 1)
+#define COREBOOT_CBFS_START (0xffffffff - CONFIG_ROM_SIZE + 1 + FMAP_SECTION_COREBOOT_START)
+#else
+#define COREBOOT_CBFS_START FMAP_SECTION_COREBOOT_START
+#endif
+
+uint32_t header_pointer =
+	cpu_to_le32(COREBOOT_CBFS_START + ALIGN_UP(sizeof(struct cbfs_file)
+						   + sizeof("cbfs_master_header"),
+						   CBFS_ATTRIBUTE_ALIGN));
diff --git a/src/security/vboot/Makefile.inc b/src/security/vboot/Makefile.inc
index d604d1c..2ea5d30 100644
--- a/src/security/vboot/Makefile.inc
+++ b/src/security/vboot/Makefile.inc
@@ -175,6 +175,8 @@
 		$(regions-for-file-$(1)), \
 		$(if $(filter $(if $(filter y,$(CONFIG_VBOOT_STARTS_IN_ROMSTAGE)), \
 			%/romstage,) \
+		header_pointer \
+		cbfs_master_header \
 		mts \
 		%/verstage \
 		locales \