* [tip:x86/efi] x86, efi: Fix display detection in EFI boot stub
2013-01-18 12:57 ` David Woodhouse
@ 2013-01-28 4:29 ` tip-bot for David Woodhouse
2013-01-28 4:31 ` [tip:x86/efi] x86, efi: Fix 32-bit EFI handover protocol entry point tip-bot for David Woodhouse
` (2 subsequent siblings)
3 siblings, 0 replies; 7+ messages in thread
From: tip-bot for David Woodhouse @ 2013-01-28 4:29 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, matt.fleming, stable, tglx, hpa,
David.Woodhouse
Commit-ID: 70a479cbe80296d3113e65cc2f713a5101061daf
Gitweb: http://git.kernel.org/tip/70a479cbe80296d3113e65cc2f713a5101061daf
Author: David Woodhouse <David.Woodhouse@intel.com>
AuthorDate: Mon, 7 Jan 2013 21:52:16 +0000
Committer: H. Peter Anvin <hpa@linux.intel.com>
CommitDate: Sun, 27 Jan 2013 20:19:37 -0800
x86, efi: Fix display detection in EFI boot stub
When booting under OVMF we have precisely one GOP device, and it
implements the ConOut protocol.
We break out of the loop when we look at it... and then promptly abort
because 'first_gop' never gets set. We should set first_gop *before*
breaking out of the loop. Yes, it doesn't really mean "first" any more,
but that doesn't matter. It's only a flag to indicate that a suitable
GOP was found.
In fact, we'd do just as well to initialise 'width' to zero in this
function, then just check *that* instead of first_gop. But I'll do the
minimal fix for now (and for stable@).
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Cc: <stable@kernel.org>
Link: http://lkml.kernel.org/r/1358513837.2397.247.camel@shinybook.infradead.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Cc: Matt Fleming <matt.fleming@intel.com>
---
arch/x86/boot/compressed/eboot.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 18e329c..448a86e 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -432,10 +432,9 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
* Once we've found a GOP supporting ConOut,
* don't bother looking any further.
*/
+ first_gop = gop;
if (conout_found)
break;
-
- first_gop = gop;
}
}
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [tip:x86/efi] x86, efi: Fix 32-bit EFI handover protocol entry point
2013-01-18 12:57 ` David Woodhouse
2013-01-28 4:29 ` [tip:x86/efi] x86, efi: Fix display detection in EFI boot stub tip-bot for David Woodhouse
@ 2013-01-28 4:31 ` tip-bot for David Woodhouse
2013-01-28 4:32 ` [tip:x86/efi] x86, efi: Fix PCI ROM handing in EFI boot stub, in 32-bit mode tip-bot for David Woodhouse
2013-01-28 4:33 ` [tip:x86/efi] x86, build: Dynamically find entry points in compressed startup code tip-bot for David Woodhouse
3 siblings, 0 replies; 7+ messages in thread
From: tip-bot for David Woodhouse @ 2013-01-28 4:31 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, matt.fleming, stable, tglx, hpa,
David.Woodhouse
Commit-ID: f791620fa7517e1045742c475a7f005db9a634b8
Gitweb: http://git.kernel.org/tip/f791620fa7517e1045742c475a7f005db9a634b8
Author: David Woodhouse <David.Woodhouse@intel.com>
AuthorDate: Mon, 7 Jan 2013 22:01:50 +0000
Committer: H. Peter Anvin <hpa@linux.intel.com>
CommitDate: Sun, 27 Jan 2013 20:19:37 -0800
x86, efi: Fix 32-bit EFI handover protocol entry point
If the bootloader calls the EFI handover entry point as a standard function
call, then it'll have a return address on the stack. We need to pop that
before calling efi_main(), or the arguments will all be out of position on
the stack.
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Cc: <stable@kernel.org>
Link: http://lkml.kernel.org/r/1358513837.2397.247.camel@shinybook.infradead.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Cc: Matt Fleming <matt.fleming@intel.com>
---
arch/x86/boot/compressed/head_32.S | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
index aa4aaf1..ccb2f4a 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -50,8 +50,10 @@ ENTRY(startup_32)
pushl %eax
pushl %esi
pushl %ecx
+ sub $0x4, %esp
.org 0x30,0x90
+ add $0x4, %esp
call efi_main
cmpl $0, %eax
movl %eax, %esi
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [tip:x86/efi] x86, efi: Fix PCI ROM handing in EFI boot stub, in 32-bit mode
2013-01-18 12:57 ` David Woodhouse
2013-01-28 4:29 ` [tip:x86/efi] x86, efi: Fix display detection in EFI boot stub tip-bot for David Woodhouse
2013-01-28 4:31 ` [tip:x86/efi] x86, efi: Fix 32-bit EFI handover protocol entry point tip-bot for David Woodhouse
@ 2013-01-28 4:32 ` tip-bot for David Woodhouse
2013-01-28 4:33 ` [tip:x86/efi] x86, build: Dynamically find entry points in compressed startup code tip-bot for David Woodhouse
3 siblings, 0 replies; 7+ messages in thread
From: tip-bot for David Woodhouse @ 2013-01-28 4:32 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, matt.fleming, stable, tglx, hpa,
David.Woodhouse
Commit-ID: b607e2126705ca28ecf21aa051172882bbdaae8a
Gitweb: http://git.kernel.org/tip/b607e2126705ca28ecf21aa051172882bbdaae8a
Author: David Woodhouse <David.Woodhouse@intel.com>
AuthorDate: Mon, 7 Jan 2013 22:09:49 +0000
Committer: H. Peter Anvin <hpa@linux.intel.com>
CommitDate: Sun, 27 Jan 2013 20:19:37 -0800
x86, efi: Fix PCI ROM handing in EFI boot stub, in 32-bit mode
The 'Attributes' argument to pci->Attributes() function is 64-bit. So
when invoking in 32-bit mode it takes two registers, not just one.
This fixes memory corruption when booting via the 32-bit EFI boot stub.
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Cc: <stable@kernel.org>
Link: http://lkml.kernel.org/r/1358513837.2397.247.camel@shinybook.infradead.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Cc: Matt Fleming <matt.fleming@intel.com>
---
arch/x86/boot/compressed/eboot.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 448a86e..b7f2208 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -295,10 +295,15 @@ static efi_status_t setup_efi_pci(struct boot_params *params)
if (!pci)
continue;
+#ifdef CONFIG_X86_64
status = efi_call_phys4(pci->attributes, pci,
EfiPciIoAttributeOperationGet, 0,
&attributes);
-
+#else
+ status = efi_call_phys5(pci->attributes, pci,
+ EfiPciIoAttributeOperationGet, 0, 0,
+ &attributes);
+#endif
if (status != EFI_SUCCESS)
continue;
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [tip:x86/efi] x86, build: Dynamically find entry points in compressed startup code
2013-01-18 12:57 ` David Woodhouse
` (2 preceding siblings ...)
2013-01-28 4:32 ` [tip:x86/efi] x86, efi: Fix PCI ROM handing in EFI boot stub, in 32-bit mode tip-bot for David Woodhouse
@ 2013-01-28 4:33 ` tip-bot for David Woodhouse
3 siblings, 0 replies; 7+ messages in thread
From: tip-bot for David Woodhouse @ 2013-01-28 4:33 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, tglx, matt.fleming, hpa, David.Woodhouse
Commit-ID: 99f857db8857aff691c51302f93648263ed07eb1
Gitweb: http://git.kernel.org/tip/99f857db8857aff691c51302f93648263ed07eb1
Author: David Woodhouse <David.Woodhouse@intel.com>
AuthorDate: Thu, 10 Jan 2013 14:31:59 +0000
Committer: H. Peter Anvin <hpa@linux.intel.com>
CommitDate: Sun, 27 Jan 2013 20:19:37 -0800
x86, build: Dynamically find entry points in compressed startup code
We have historically hard-coded entry points in head.S just so it's easy
to build the executable/bzImage headers with references to them.
Unfortunately, this leads to boot loaders abusing these "known" addresses
even when they are *explicitly* told that they "should look at the ELF
header to find this address, as it may change in the future". And even
when the address in question *has* actually been changed in the past,
without fanfare or thought to compatibility.
Thus we have bootloaders doing stunningly broken things like jumping
to offset 0x200 in the kernel startup code in 64-bit mode, *hoping*
that startup_64 is still there (it has moved at least once
before). And hoping that it's actually a 64-bit kernel despite the
fact that we don't give them any indication of that fact.
This patch should hopefully remove the temptation to abuse internal
addresses in future, where sternly worded comments have not sufficed.
Instead of having hard-coded addresses and saying "please don't abuse
these", we actually pull the addresses out of the ELF payload into
zoffset.h, and make build.c shove them back into the right places in
the bzImage header.
Rather than including zoffset.h into build.c and thus having to rebuild
the tool for every kernel build, we parse it instead. The parsing code
is small and simple.
This patch doesn't actually move any of the interesting entry points, so
any offending bootloader will still continue to "work" after this patch
is applied. For some version of "work" which includes jumping into the
compressed payload and crashing, if the bzImage it's given is a 32-bit
kernel. No change there then.
[ hpa: some of the issues in the description are addressed or
retconned by the 2.12 boot protocol. This patch has been edited to
only remove fixed addresses that were *not* thus retconned. ]
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Link: http://lkml.kernel.org/r/1358513837.2397.247.camel@shinybook.infradead.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Cc: Matt Fleming <matt.fleming@intel.com>
---
arch/x86/boot/Makefile | 4 +-
arch/x86/boot/compressed/head_32.S | 6 +--
arch/x86/boot/compressed/head_64.S | 8 ++--
arch/x86/boot/tools/build.c | 81 +++++++++++++++++++++++++++++---------
4 files changed, 72 insertions(+), 27 deletions(-)
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index ccce0ed..379814b 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -71,7 +71,7 @@ GCOV_PROFILE := n
$(obj)/bzImage: asflags-y := $(SVGA_MODE)
quiet_cmd_image = BUILD $@
-cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin > $@
+cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/zoffset.h > $@
$(obj)/bzImage: $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/tools/build FORCE
$(call if_changed,image)
@@ -92,7 +92,7 @@ targets += voffset.h
$(obj)/voffset.h: vmlinux FORCE
$(call if_changed,voffset)
-sed-zoffset := -e 's/^\([0-9a-fA-F]*\) . \(startup_32\|input_data\|_end\|z_.*\)$$/\#define ZO_\2 0x\1/p'
+sed-zoffset := -e 's/^\([0-9a-fA-F]*\) . \(startup_32\|startup_64\|efi_pe_entry\|efi_stub_entry\|input_data\|_end\|z_.*\)$$/\#define ZO_\2 0x\1/p'
quiet_cmd_zoffset = ZOFFSET $@
cmd_zoffset = $(NM) $< | sed -n $(sed-zoffset) > $@
diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
index ccb2f4a..1e3184f 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -35,11 +35,11 @@ ENTRY(startup_32)
#ifdef CONFIG_EFI_STUB
jmp preferred_addr
- .balign 0x10
/*
* We don't need the return address, so set up the stack so
- * efi_main() can find its arugments.
+ * efi_main() can find its arguments.
*/
+ENTRY(efi_pe_entry)
add $0x4, %esp
call make_boot_params
@@ -52,7 +52,7 @@ ENTRY(startup_32)
pushl %ecx
sub $0x4, %esp
- .org 0x30,0x90
+ENTRY(efi_stub_entry)
add $0x4, %esp
call efi_main
cmpl $0, %eax
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index 2c4b171..f5d1aaa 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -201,12 +201,12 @@ ENTRY(startup_64)
*/
#ifdef CONFIG_EFI_STUB
/*
- * The entry point for the PE/COFF executable is 0x210, so only
- * legacy boot loaders will execute this jmp.
+ * The entry point for the PE/COFF executable is efi_pe_entry, so
+ * only legacy boot loaders will execute this jmp.
*/
jmp preferred_addr
- .org 0x210
+ENTRY(efi_pe_entry)
mov %rcx, %rdi
mov %rdx, %rsi
pushq %rdi
@@ -218,7 +218,7 @@ ENTRY(startup_64)
popq %rsi
popq %rdi
- .org 0x230,0x90
+ENTRY(efi_stub_entry)
call efi_main
movq %rax,%rsi
cmpq $0,%rax
diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c
index 4b8e165..94c5446 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);
^ permalink raw reply related [flat|nested] 7+ messages in thread