Nico Huber has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/63748 )
Change subject: libpayload: Support x86 payload loaded via Linux Boot Protocol ......................................................................
libpayload: Support x86 payload loaded via Linux Boot Protocol
There's been a rarely used feature in FILO for some years to add a Linux header to its binary so a Linux loader could load it. One thing overlooked was that a Linux loader is unaware of anything like a `.bss` section that would have to be cleared. As execution starts in libpayload this needs to be handled here.
Beside clearing everything from `_edata` to `_end`, we also take the kernel command line as `argv[0]`.
Change-Id: Ief6bca8534d07458b9c5a315f297cb62d727917f Signed-off-by: Nico Huber nico.h@gmx.de --- M payloads/libpayload/arch/x86/head.S 1 file changed, 51 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/48/63748/1
diff --git a/payloads/libpayload/arch/x86/head.S b/payloads/libpayload/arch/x86/head.S index 1052b8c..e1188e7 100644 --- a/payloads/libpayload/arch/x86/head.S +++ b/payloads/libpayload/arch/x86/head.S @@ -60,6 +60,13 @@ #define CB_ARGV 0x08 #define CB_ARGC 0x10
+#define LINUX_CL_MAGIC 0x020 /* u16 */ +#define LINUX_CL_MAGIC_VALUE 0xa33f +#define LINUX_CL_OFFSET 0x022 /* u16 */ +#define LINUX_ALT_MEM_K 0x1e0 /* u32 */ +#define LINUX_LOADER_FLAGS 0x211 /* u8 */ +#define LINUX_KERNEL_START 0x214 /* u32 */ + /* * This function saves off the previous stack and switches us to our * own execution environment. @@ -83,7 +90,51 @@
movl CB_ARGC(%esp), %eax movl %eax, main_argc + jmp 2f + 1: + /* + * Alternatively, see if we are called via Linux Boot Protocol. + * There is no reasonable magic value, so this is a naughty + * heuristic (we check if .kernel_start, .loader_flags and + * .alt_mem_k fields in the zero page make any sense). + * + * If we are loaded this way, we need to clear .bss because the + * loader is not aware of it. + */ + cmpl $_start, LINUX_KERNEL_START(%esi) /* kernel_start is us? */ + jne 2f + + movzbl LINUX_LOADER_FLAGS(%esi), %eax /* load-high flag set? */ + andl $1, %eax + jz 2f + + movl LINUX_ALT_MEM_K(%esi), %ebx /* compute top of memory */ + addl $1024, %ebx + shl $10, %ebx + + lea 0x1000(%esi), %eax /* params struct below TOM? */ + cmpl %eax, %ebx + jg 2f + cmpl $_end, %ebx /* are we below TOM? */ + jg 2f + + /* Now clear .bss: */ + mov $_edata, %edi /* memset(_edata, 0x00, _end - _edata) */ + xor %eax, %eax + mov $_end, %ecx + sub $_edata, %ecx + rep stosb + + /* And optionally use kernel command line as argv[0]: */ + cmpw $LINUX_CL_MAGIC_VALUE, LINUX_CL_MAGIC(%esi) + jne 2f + movl $1, main_argc + movzwl LINUX_CL_OFFSET(%esi), %eax + addl %esi, %eax + movl %eax, main_argv + +2: /* Store current stack pointer and set up new stack. */ movl %esp, %eax movl $_stack, %esp