diff options
author | Matt Fleming <matt.fleming@intel.com> | 2012-06-27 18:34:57 +0100 |
---|---|---|
committer | Matt Fleming <matt.fleming@intel.com> | 2012-08-08 11:21:09 +0100 |
commit | aa925098a5887a2925e7b6396b3483ed86c69cc0 (patch) | |
tree | 61a9a5782defb6453819c680a8ae883b634b88dc | |
parent | e056a22a2c933068616b2e0250d2a2c29602dd23 (diff) | |
download | efilinux-aa925098a5887a2925e7b6396b3483ed86c69cc0.tar.gz |
bzimage: Hand off initialisation to the EFI boot stubnext
Linux kernel v3.6-rc1 support an "EFI handover protocol" that allows
most of the initialisation necessary for booting a kernel under EFI to
be performed by a boot stub in the kernel image itself.
Use the boot stub if it is supported by the kernel.
Signed-off-by: Matt Fleming <matt.fleming@intel.com>
-rw-r--r-- | loaders/bzimage/bzimage.c | 9 | ||||
-rw-r--r-- | loaders/bzimage/bzimage.h | 1 | ||||
-rw-r--r-- | loaders/bzimage/i386.h | 15 | ||||
-rw-r--r-- | loaders/bzimage/x86_64.h | 16 |
4 files changed, 41 insertions, 0 deletions
diff --git a/loaders/bzimage/bzimage.c b/loaders/bzimage/bzimage.c index 3b9c560..efdb884 100644 --- a/loaders/bzimage/bzimage.c +++ b/loaders/bzimage/bzimage.c @@ -323,6 +323,15 @@ load_kernel(EFI_HANDLE image, CHAR16 *name, char *_cmdline) memcpy((char *)boot_params, (char *)buf, 2 * 512); boot_params->hdr.code32_start = (UINT32)((UINT64)kernel_start); + /* + * Use the kernel's EFI boot stub by invoking the handover + * protocol. + */ + if (buf->hdr.version >= 0x20b) { + handover_jump(image, boot_params, kernel_start); + goto out; + } + err = setup_graphics(buf); if (err != EFI_SUCCESS) goto out; diff --git a/loaders/bzimage/bzimage.h b/loaders/bzimage/bzimage.h index 9d84725..cd11fd3 100644 --- a/loaders/bzimage/bzimage.h +++ b/loaders/bzimage/bzimage.h @@ -78,6 +78,7 @@ struct setup_header { UINT64 setup_data; UINT64 pref_address; UINT32 init_size; + UINT32 handover_offset; } __attribute__((packed)); struct efi_info { diff --git a/loaders/bzimage/i386.h b/loaders/bzimage/i386.h index 6f1cf8f..593e2af 100644 --- a/loaders/bzimage/i386.h +++ b/loaders/bzimage/i386.h @@ -42,4 +42,19 @@ static inline void kernel_jump(EFI_PHYSICAL_ADDRESS kernel_start, :: "m" (boot_params), "m" (kernel_start)); } +static inline void handover_jump(EFI_HANDLE image, struct boot_params *bp, + EFI_PHYSICAL_ADDRESS kernel_start) +{ + kernel_start += bp->hdr.handover_offset; + + asm volatile ("cli \n" + "pushl %0 \n" + "pushl %1 \n" + "pushl %2 \n" + "movl %3, %%ecx \n" + "jmp *%%ecx \n" + :: "m" (bp), "m" (ST), + "m" (image), "m" (kernel_start)); +} + #endif /* __I386_H__ */ diff --git a/loaders/bzimage/x86_64.h b/loaders/bzimage/x86_64.h index a7ba3af..b63710e 100644 --- a/loaders/bzimage/x86_64.h +++ b/loaders/bzimage/x86_64.h @@ -33,6 +33,7 @@ #define EFI_LOADER_SIGNATURE "EL64" typedef void(*kernel_func)(void *, struct boot_params *); +typedef void(*handover_func)(void *, EFI_SYSTEM_TABLE *, struct boot_params *); static inline void kernel_jump(EFI_PHYSICAL_ADDRESS kernel_start, struct boot_params *boot_params) @@ -51,4 +52,19 @@ static inline void kernel_jump(EFI_PHYSICAL_ADDRESS kernel_start, kf(NULL, boot_params); } +static inline void handover_jump(EFI_HANDLE image, struct boot_params *bp, + EFI_PHYSICAL_ADDRESS kernel_start) +{ + UINT32 offset = bp->hdr.handover_offset; + handover_func hf; + + asm volatile ("cli"); + + /* The 64-bit kernel entry is 512 bytes after the start. */ + kernel_start += 512; + + hf = (handover_func)(kernel_start + offset); + hf(image, ST, bp); +} + #endif /* __X86_64_H__ */ |