[PATCH v15 21/28] x86/boot: Place TXT MLE header in the kernel_info section

Ross Philipson
2025-12-15T23:41:58Z

The Measured Launch Environment (MLE) header must be locatable by the
boot loader and Intel TXT must be setup to do a launch with this header's
location. While the offset to the kernel_info structure does not need
to be at a fixed offset, the offsets in the header must be relative
offsets from the start of the setup kernel. Note that from the viewpoint
of the prelaunch phase and TXT, the setup kernel image as loaded into
memory is the MLE image.

The changes to the linker file achieve this by making available the
offset values which are updated in the MLE header structure. The following
are the needed offsets from the beginning of the setup kernel image:

- kernel_info_offset: Offset of the main kernel_info structure.
- mle_header_offset: Offset of the MLE header structure.
- sl_stub_entry_offset: Offset of the Secure Launch initial entry point.
- _edata_offset: Offset of the _edata label used as the end of the MLE image.

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
Suggested-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
---
arch/x86/boot/compressed/kernel_info.S | 50 +++++++++++++++++++++++---
arch/x86/boot/compressed/vmlinux.lds.S | 7 ++++
2 files changed, 53 insertions(+), 4 deletions(-)

diff --git a/arch/x86/boot/compressed/kernel_info.S b/arch/x86/boot/compressed/kernel_info.S
index f818ee8fba38..e3c9816eacbf 100644
--- a/arch/x86/boot/compressed/kernel_info.S
+++ b/arch/x86/boot/compressed/kernel_info.S
@@ -1,12 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0 */

+#include <linux/linkage.h>
#include <asm/bootparam.h>

- .section ".rodata.kernel_info", "a"
+/*
+ * The kernel_info structure is not placed at a fixed offset in the
+ * kernel image. So this macro and the support in the linker file
+ * allow the relative offsets for the MLE header within the kernel
+ * image to be configured at build time.
+ */
+#define roffset(X) ((X) - kernel_info)

- .global kernel_info
+ .section ".rodata.kernel_info", "a"

-kernel_info:
+ .balign 16
+SYM_DATA_START(kernel_info)
/* Header, Linux top (structure). */
.ascii "LToP"
/* Size. */
@@ -17,6 +25,40 @@ kernel_info:
/* Maximal allowed type for setup_data and setup_indirect structs. */
.long SETUP_TYPE_MAX

+ /* Offset to the MLE header structure */
+#if IS_ENABLED(CONFIG_SECURE_LAUNCH)
+ .long roffset(mle_header_offset)
+#else
+ .long 0
+#endif
+
kernel_info_var_len_data:
/* Empty for time being... */
-kernel_info_end:
+SYM_DATA_END_LABEL(kernel_info, SYM_L_LOCAL, kernel_info_end)
+
+#if IS_ENABLED(CONFIG_SECURE_LAUNCH)
+ /*
+ * The MLE Header per the TXT Specification, section 2.1
+ * MLE capabilities, see table 4. Capabilities set:
+ * bit 0: Support for GETSEC[WAKEUP] for RLP wakeup
+ * bit 1: Support for RLP wakeup using MONITOR address
+ * bit 2: The ECX register will contain the pointer to the MLE page table
+ * bit 5: TPM 1.2 family: Details/authorities PCR usage support
+ * bit 9: Supported format of TPM 2.0 event log - TCG compliant
+ */
+SYM_DATA_START(mle_header)
+ .long 0x9082ac5a /* UUID0 */
+ .long 0x74a7476f /* UUID1 */
+ .long 0xa2555c0f /* UUID2 */
+ .long 0x42b651cb /* UUID3 */
+ .long 0x00000034 /* MLE header size */
+ .long 0x00020002 /* MLE version 2.2 */
+ .long roffset(sl_stub_entry_offset) /* Linear entry point of MLE (virt. address) */
+ .long 0x00000000 /* First valid page of MLE */
+ .long 0x00000000 /* Offset within binary of first byte of MLE */
+ .long roffset(_edata_offset) /* Offset within binary of last byte + 1 of MLE */
+ .long 0x00000227 /* Bit vector of MLE-supported capabilities */
+ .long 0x00000000 /* Starting linear address of command line (unused) */
+ .long 0x00000000 /* Ending linear address of command line (unused) */
+SYM_DATA_END(mle_header)
+#endif
diff --git a/arch/x86/boot/compressed/vmlinux.lds.S b/arch/x86/boot/compressed/vmlinux.lds.S
index 587ce3e7c504..d061ae6046b2 100644
--- a/arch/x86/boot/compressed/vmlinux.lds.S
+++ b/arch/x86/boot/compressed/vmlinux.lds.S
@@ -126,3 +126,10 @@ SECTIONS
}
ASSERT(SIZEOF(.rela.dyn) == 0, "Unexpected run-time relocations (.rela) detected!")
}
+
+#ifdef CONFIG_SECURE_LAUNCH
+PROVIDE(kernel_info_offset = ABSOLUTE(kernel_info - startup_32));
+PROVIDE(mle_header_offset = kernel_info_offset + ABSOLUTE(mle_header - startup_32));
+PROVIDE(sl_stub_entry_offset = kernel_info_offset + ABSOLUTE(sl_stub_entry - startup_32));
+PROVIDE(_edata_offset = kernel_info_offset + ABSOLUTE(_edata - startup_32));
+#endif
--
2.43.7