diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-01-31 17:10:36 +1100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-01-31 17:10:36 +1100 |
commit | 04c2eee5b9dfcb13f3cd07a5537fb8c785f2751a (patch) | |
tree | a70cf1df64b3715c502211233dc307abacaed7da /arch/x86/boot/tools/build.c | |
parent | bdb0ae6a767ef2622eb282e06fc225e855341653 (diff) | |
parent | becbd6608026c15afd88fd3d0c893dfb7b8c7845 (diff) |
Merge branch 'x86-efi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 EFI fixes from Peter Anvin:
"This is a collection of fixes for the EFI support. The controversial
bit here is a set of patches which bumps the boot protocol version as
part of fixing some serious problems with the EFI handover protocol,
used when booting under EFI using a bootloader as opposed to directly
from EFI. These changes should also make it a lot saner to support
cross-mode 32/64-bit EFI booting in the future. Getting these changes
into 3.8 means we avoid presenting an inconsistent ABI to bootloaders.
Other changes are display detection and fixing efivarfs."
* 'x86-efi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86, efi: remove attribute check from setup_efi_pci
x86, build: Dynamically find entry points in compressed startup code
x86, efi: Fix PCI ROM handing in EFI boot stub, in 32-bit mode
x86, efi: Fix 32-bit EFI handover protocol entry point
x86, efi: Fix display detection in EFI boot stub
x86, boot: Define the 2.12 bzImage boot protocol
x86/boot: Fix minor fd leakage in tools/relocs.c
x86, efi: Set runtime_version to the EFI spec revision
x86, efi: fix 32-bit warnings in setup_efi_pci()
efivarfs: Delete dentry from dcache in efivarfs_file_write()
efivarfs: Never return ENOENT from firmware
efi, x86: Pass a proper identity mapping in efi_call_phys_prelog
efivarfs: Drop link count of the right inode
Diffstat (limited to 'arch/x86/boot/tools/build.c')
-rw-r--r-- | arch/x86/boot/tools/build.c | 81 |
1 files changed, 63 insertions, 18 deletions
diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c index 4b8e165ee57..94c54465002 100644 --- a/arch/x86/boot/tools/build.c +++ b/arch/x86/boot/tools/build.c @@ -52,6 +52,10 @@ int is_big_kernel; #define PECOFF_RELOC_RESERVE 0x20 +unsigned long efi_stub_entry; +unsigned long efi_pe_entry; +unsigned long startup_64; + /*----------------------------------------------------------------------*/ static const u32 crctab32[] = { @@ -132,7 +136,7 @@ static void die(const char * str, ...) static void usage(void) { - die("Usage: build setup system [> image]"); + die("Usage: build setup system [zoffset.h] [> image]"); } #ifdef CONFIG_EFI_STUB @@ -206,30 +210,54 @@ static void update_pecoff_text(unsigned int text_start, unsigned int file_sz) */ put_unaligned_le32(file_sz - 512, &buf[pe_header + 0x1c]); -#ifdef CONFIG_X86_32 /* - * Address of entry point. - * - * The EFI stub entry point is +16 bytes from the start of - * the .text section. + * Address of entry point for PE/COFF executable */ - put_unaligned_le32(text_start + 16, &buf[pe_header + 0x28]); -#else - /* - * Address of entry point. startup_32 is at the beginning and - * the 64-bit entry point (startup_64) is always 512 bytes - * after. The EFI stub entry point is 16 bytes after that, as - * the first instruction allows legacy loaders to jump over - * the EFI stub initialisation - */ - put_unaligned_le32(text_start + 528, &buf[pe_header + 0x28]); -#endif /* CONFIG_X86_32 */ + put_unaligned_le32(text_start + efi_pe_entry, &buf[pe_header + 0x28]); update_pecoff_section_header(".text", text_start, text_sz); } #endif /* CONFIG_EFI_STUB */ + +/* + * Parse zoffset.h and find the entry points. We could just #include zoffset.h + * but that would mean tools/build would have to be rebuilt every time. It's + * not as if parsing it is hard... + */ +#define PARSE_ZOFS(p, sym) do { \ + if (!strncmp(p, "#define ZO_" #sym " ", 11+sizeof(#sym))) \ + sym = strtoul(p + 11 + sizeof(#sym), NULL, 16); \ +} while (0) + +static void parse_zoffset(char *fname) +{ + FILE *file; + char *p; + int c; + + file = fopen(fname, "r"); + if (!file) + die("Unable to open `%s': %m", fname); + c = fread(buf, 1, sizeof(buf) - 1, file); + if (ferror(file)) + die("read-error on `zoffset.h'"); + buf[c] = 0; + + p = (char *)buf; + + while (p && *p) { + PARSE_ZOFS(p, efi_stub_entry); + PARSE_ZOFS(p, efi_pe_entry); + PARSE_ZOFS(p, startup_64); + + p = strchr(p, '\n'); + while (p && (*p == '\r' || *p == '\n')) + p++; + } +} + int main(int argc, char ** argv) { unsigned int i, sz, setup_sectors; @@ -241,7 +269,19 @@ int main(int argc, char ** argv) void *kernel; u32 crc = 0xffffffffUL; - if (argc != 3) + /* Defaults for old kernel */ +#ifdef CONFIG_X86_32 + efi_pe_entry = 0x10; + efi_stub_entry = 0x30; +#else + efi_pe_entry = 0x210; + efi_stub_entry = 0x230; + startup_64 = 0x200; +#endif + + if (argc == 4) + parse_zoffset(argv[3]); + else if (argc != 3) usage(); /* Copy the setup code */ @@ -299,6 +339,11 @@ int main(int argc, char ** argv) #ifdef CONFIG_EFI_STUB update_pecoff_text(setup_sectors * 512, sz + i + ((sys_size * 16) - sz)); + +#ifdef CONFIG_X86_64 /* Yes, this is really how we defined it :( */ + efi_stub_entry -= 0x200; +#endif + put_unaligned_le32(efi_stub_entry, &buf[0x264]); #endif crc = partial_crc32(buf, i, crc); |