From 2012ab71de0f2f2a4627156d0da6e1388b84dd48 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 22 Feb 2026 23:13:00 +0000 Subject: [PATCH] [pxeprefix] Add a minimal iPXE NBP metadata header There is no fixed structure for a PXE NBP: the format is just an opaque block of executable code that is loaded into memory verbatim and executed by jumping to the first byte. It is consequently impossible for external code to unambiguously identify a PXE NBP, or to inspect any metadata about the NBP's functionality. The first five bytes of an iPXE NBP are already fixed as being an ljmp instruction that resets the code segment to 0x7c0 and continues execution from the following byte. We can extend this to include a minimal header as follows: Offset Content ------ ------- 0 ljmp instruction (0xea) 1-2 ljmp offset (and therefore length of header) 3-4 ljmp segment (0x07c0) 5+ Metadata fields \_ 5 CPU architecture (0x32=i386, 0x64=x86_64) \_ 6-7 Magic value (0x18ae) This is backwards-compatible to existing binaries (which effectively have zero bytes of metadata following the ljmp instruction), and allows for future expansion by appending metadata fields (with the ljmp offset used to determine the overall header length and therefore the presence of further fields). In this initial version of the header, define a magic value (used to differentiate an iPXE NBP from other binaries that happen to start with an ljmp instruction), and a single-byte value that encodes whether this binary is built for 32-bit or 64-bit CPUs. Signed-off-by: Michael Brown --- src/arch/x86/prefix/pxeprefix.S | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/arch/x86/prefix/pxeprefix.S b/src/arch/x86/prefix/pxeprefix.S index 067af99fa..db8359fbf 100644 --- a/src/arch/x86/prefix/pxeprefix.S +++ b/src/arch/x86/prefix/pxeprefix.S @@ -24,6 +24,16 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ) #define EB_MAGIC_1 ( 'E' + ( 't' << 8 ) + ( 'h' << 16 ) + ( 'e' << 24 ) ) #define EB_MAGIC_2 ( 'r' + ( 'b' << 8 ) + ( 'o' << 16 ) + ( 'o' << 24 ) ) +/* Magic signature word */ +#define IPXE_NBP_MAGIC 0x18ae + +/* Architecture byte */ +#ifdef __x86_64__ +#define IPXE_NBP_ARCH 0x64 +#else +#define IPXE_NBP_ARCH 0x32 +#endif + /* Prefix memory layout: * * iPXE binary image @@ -44,7 +54,21 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ) .section ".prefix", "ax", @progbits .globl _pxe_start _pxe_start: + /* iPXE NBP magic header: + * + * Offset Content + * ------ ------- + * 0 ljmp instruction (0xea) + * 1-2 ljmp offset (and therefore length of header) + * 3-4 ljmp segment (0x07c0) + * 5+ Metadata fields + * \_ 5 CPU architecture (0x32=i386, 0x64=x86_64) + * \_ 6-7 Magic value (0x18ae) + * + */ jmp $0x7c0, $1f + .byte IPXE_NBP_ARCH + .word IPXE_NBP_MAGIC 1: /* Preserve registers for possible return to PXE */ pushfl