
Hi Simon,
On Fri, Jul 31, 2015 at 11:31 PM, Simon Glass sjg@chromium.org wrote:
From: Ben Stoltz stoltz@google.com
Add the required x86 glue code. This includes the initial start-up, relocation and jumping to efi_main(). We also need to avoid fiddling with interrupts.
Signed-off-by: Ben Stoltz stoltz@google.com Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Add ALIGN() before .dynamic in the linker script
- Add a blank line before return in the _relocate() function
- Add a comment as to why .hash has to be first in the linker script
- Add a comment as to why interrupt_init() must be skipped for EFI
- Drop unused DECLARE_GLOBAL_DATA_INIT
- Drop unused board_eth_init()
- Drop use of CONFIG_X86_64 since we don't support a 64-bit EFI application yet
- Fix spacing around operators
- Move 64-bit crt0 to a later patch
- Move crt0 and reloc files into arch/x86/lib/efi/
- Remove KEEP in the EFI linker script since garbage collection is not enabled
- Rename CONFIG_ARCH_EFI to CONFIG_EFI_APP
- Rename ImageBase to image_base
- Use SPDX for the EFI start and relocation code
- Use u-boot-app.efi instead of u-boot.efi
Makefile | 6 +-- arch/x86/Kconfig | 3 ++ arch/x86/Makefile | 2 + arch/x86/cpu/Makefile | 1 + arch/x86/cpu/efi/Makefile | 8 +++ arch/x86/cpu/efi/efi.c | 42 ++++++++++++++++ arch/x86/cpu/efi/elf_ia32_efi.lds | 94 ++++++++++++++++++++++++++++++++++++ arch/x86/cpu/efi/sdram.c | 29 +++++++++++ arch/x86/cpu/interrupts.c | 6 +++ arch/x86/include/asm/arch-efi/gpio.h | 10 ++++ arch/x86/lib/efi/crt0-efi-ia32.S | 52 ++++++++++++++++++++ arch/x86/lib/efi/reloc_ia32.c | 72 +++++++++++++++++++++++++++ 12 files changed, 322 insertions(+), 3 deletions(-) create mode 100644 arch/x86/cpu/efi/Makefile create mode 100644 arch/x86/cpu/efi/efi.c create mode 100644 arch/x86/cpu/efi/elf_ia32_efi.lds create mode 100644 arch/x86/cpu/efi/sdram.c create mode 100644 arch/x86/include/asm/arch-efi/gpio.h create mode 100644 arch/x86/lib/efi/crt0-efi-ia32.S create mode 100644 arch/x86/lib/efi/reloc_ia32.c
diff --git a/Makefile b/Makefile index 3fb006b..6da9224 100644 --- a/Makefile +++ b/Makefile @@ -750,7 +750,7 @@ ifneq ($(CONFIG_SPL_TARGET),) ALL-$(CONFIG_SPL) += $(CONFIG_SPL_TARGET:"%"=%) endif ALL-$(CONFIG_REMAKE_ELF) += u-boot.elf -ALL-$(CONFIG_EFI_APP) += u-boot.efi +ALL-$(CONFIG_EFI_APP) += u-boot-app.efi
Can we move this change to http://patchwork.ozlabs.org/patch/502642/?
ifneq ($(BUILD_ROM),) ALL-$(CONFIG_X86_RESET_VECTOR) += u-boot.rom @@ -1079,8 +1079,8 @@ u-boot-dtb-tegra.bin: u-boot-nodtb-tegra.bin dts/dt.dtb FORCE endif endif
-OBJCOPYFLAGS_u-boot.efi := $(OBJCOPYFLAGS_EFI) -u-boot.efi: u-boot FORCE +OBJCOPYFLAGS_u-boot-app.efi := $(OBJCOPYFLAGS_EFI) +u-boot-app.efi: u-boot FORCE $(call if_changed,zobjcopy)
Ditto.
u-boot-img.bin: spl/u-boot-spl.bin u-boot.img FORCE diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index e8968a7..7e6e89c 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -11,6 +11,9 @@ choice config VENDOR_COREBOOT bool "coreboot"
+config VENDOR_EFI
bool "efi"
config VENDOR_EMULATION bool "emulation"
diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 36a6018..d104a49 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -2,7 +2,9 @@ # SPDX-License-Identifier: GPL-2.0+ #
+ifeq ($(CONFIG_EFI_APP),) head-y := arch/x86/cpu/start.o +endif ifeq ($(CONFIG_SPL_BUILD),y) head-y += arch/x86/cpu/start16.o head-y += arch/x86/cpu/resetvec.o diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile index 8a8e63e..5e058c0 100644 --- a/arch/x86/cpu/Makefile +++ b/arch/x86/cpu/Makefile @@ -14,6 +14,7 @@ obj-y += interrupts.o cpu.o cpu_x86.o call64.o
obj-$(CONFIG_INTEL_BAYTRAIL) += baytrail/ obj-$(CONFIG_SYS_COREBOOT) += coreboot/ +obj-$(CONFIG_EFI_APP) += efi/ obj-$(CONFIG_QEMU) += qemu/ obj-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += ivybridge/ obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/ diff --git a/arch/x86/cpu/efi/Makefile b/arch/x86/cpu/efi/Makefile new file mode 100644 index 0000000..e091637 --- /dev/null +++ b/arch/x86/cpu/efi/Makefile @@ -0,0 +1,8 @@ +# +# Copyright (c) 2015 Google, Inc +# +# SPDX-License-Identifier: GPL-2.0+ +#
+obj-y += efi.o +obj-y += sdram.o diff --git a/arch/x86/cpu/efi/efi.c b/arch/x86/cpu/efi/efi.c new file mode 100644 index 0000000..75ba0d4 --- /dev/null +++ b/arch/x86/cpu/efi/efi.c @@ -0,0 +1,42 @@ +/*
- Copyright (c) 2015 Google, Inc
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <fdtdec.h> +#include <netdev.h>
+int arch_cpu_init(void) +{ +#ifdef CONFIG_SYS_X86_TSC_TIMER
timer_set_base(rdtsc());
+#endif
return 0;
+}
+int board_early_init_f(void) +{
return 0;
+}
+int print_cpuinfo(void) +{
return default_print_cpuinfo();
+}
+void board_final_cleanup(void) +{ +}
+int misc_init_r(void) +{
return 0;
+}
+int arch_misc_init(void) +{
return 0;
+} diff --git a/arch/x86/cpu/efi/elf_ia32_efi.lds b/arch/x86/cpu/efi/elf_ia32_efi.lds new file mode 100644 index 0000000..a83ddd0 --- /dev/null +++ b/arch/x86/cpu/efi/elf_ia32_efi.lds @@ -0,0 +1,94 @@ +/*
- U-Boot EFI linker script
- SPDX-License-Identifier: bsd-2-clause
Should be "BSD-2-Clause" (per http://spdx.org/licenses/)
- Modified from usr/lib32/elf_ia32_efi.lds in gnu-efi
- */
+#include <config.h>
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) +ENTRY(_start) +SECTIONS +{
image_base = .;
.hash : { *(.hash) } /* this MUST come first, EFI expects it */
. = ALIGN(4096);
.text :
{
*(.text)
*(.text.*)
*(.gnu.linkonce.t.*)
}
. = ALIGN(4096);
.sdata :
{
*(.got.plt)
*(.got)
*(.srodata)
*(.sdata)
*(.sbss)
*(.scommon)
}
. = ALIGN(4096);
.data :
{
*(.rodata*)
*(.data)
*(.data1)
*(.data.*)
*(.sdata)
*(.got.plt)
*(.got)
/*
* the EFI loader doesn't seem to like a .bss section, so we
* stick it all into .data:
*/
*(.sbss)
*(.scommon)
*(.dynbss)
*(.bss)
*(COMMON)
/* U-Boot lists and device tree */
. = ALIGN(8);
*(SORT(.u_boot_list*));
. = ALIGN(8);
*(.dtb*);
}
. = ALIGN(4096);
.dynamic : { *(.dynamic) }
. = ALIGN(4096);
.rel :
{
*(.rel.data)
*(.rel.data.*)
*(.rel.got)
*(.rel.stab)
*(.data.rel.ro.local)
*(.data.rel.local)
*(.data.rel.ro)
*(.data.rel*)
*(.rel.u_boot_list*)
}
. = ALIGN(4096);
.reloc : /* This is the PECOFF .reloc section! */
{
*(.reloc)
}
. = ALIGN(4096);
.dynsym : { *(.dynsym) }
. = ALIGN(4096);
.dynstr : { *(.dynstr) }
. = ALIGN(4096);
/DISCARD/ :
{
*(.rel.reloc)
*(.eh_frame)
*(.note.GNU-stack)
}
.comment 0 : { *(.comment) }
+} diff --git a/arch/x86/cpu/efi/sdram.c b/arch/x86/cpu/efi/sdram.c new file mode 100644 index 0000000..5159944 --- /dev/null +++ b/arch/x86/cpu/efi/sdram.c @@ -0,0 +1,29 @@ +/*
- Copyright (c) 2015 Google, Inc
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <efi.h> +#include <asm/u-boot-x86.h>
+DECLARE_GLOBAL_DATA_PTR;
+ulong board_get_usable_ram_top(ulong total_size) +{
return (ulong)efi_get_ram_base() + gd->ram_size;
+}
+int dram_init(void) +{
/* gd->ram_size is set as part of EFI init */
return 0;
+}
+void dram_init_banksize(void) +{
gd->bd->bi_dram[0].start = efi_get_ram_base();
gd->bd->bi_dram[0].size = CONFIG_EFI_RAM_SIZE;
+} diff --git a/arch/x86/cpu/interrupts.c b/arch/x86/cpu/interrupts.c index 3a9c2d4..a112938 100644 --- a/arch/x86/cpu/interrupts.c +++ b/arch/x86/cpu/interrupts.c @@ -242,6 +242,11 @@ int disable_interrupts(void)
int interrupt_init(void) {
/*
* When running as an EFI application we are not in control of
* interrupts and should leave them alone.
*/
+#ifndef CONFIG_EFI_APP /* Just in case... */ disable_interrupts();
@@ -255,6 +260,7 @@ int interrupt_init(void)
/* It is now safe to enable interrupts */ enable_interrupts();
+#endif
return 0;
} diff --git a/arch/x86/include/asm/arch-efi/gpio.h b/arch/x86/include/asm/arch-efi/gpio.h new file mode 100644 index 0000000..f044f07 --- /dev/null +++ b/arch/x86/include/asm/arch-efi/gpio.h @@ -0,0 +1,10 @@ +/*
- Copyright (c) 2015 Google, Inc.
- SPDX-License-Identifier: GPL-2.0+
- */
+#ifndef _X86_ARCH_GPIO_H_ +#define _X86_ARCH_GPIO_H_
+#endif /* _X86_ARCH_GPIO_H_ */ diff --git a/arch/x86/lib/efi/crt0-efi-ia32.S b/arch/x86/lib/efi/crt0-efi-ia32.S new file mode 100644 index 0000000..30e5eb0 --- /dev/null +++ b/arch/x86/lib/efi/crt0-efi-ia32.S @@ -0,0 +1,52 @@ +/*
- crt0-efi-ia32.S - x86 EFI startup code.
- Copyright (C) 1999 Hewlett-Packard Co.
- Contributed by David Mosberger davidm@hpl.hp.com.
- All rights reserved.
- SPDX-License-Identifier: BSD-3-Clause
- */
.text
.align 4
.globl _start
+_start:
pushl %ebp
movl %esp,%ebp
pushl 12(%ebp) # copy "image" argument
pushl 8(%ebp) # copy "systab" argument
call 0f
+0: popl %eax
movl %eax,%ebx
addl $image_base-0b,%eax # %eax = ldbase
addl $_DYNAMIC-0b,%ebx # %ebx = _DYNAMIC
pushl %ebx # pass _DYNAMIC as second argument
pushl %eax # pass ldbase as first argument
call _relocate
popl %ebx
popl %ebx
testl %eax,%eax
jne .exit
call efi_main # call app with "image" and "systab" argument
+.exit: leave
ret
/*
* hand-craft a dummy .reloc section so EFI knows it's a relocatable
* executable:
*/
.data
+dummy: .long 0
+#define IMAGE_REL_ABSOLUTE 0
.section .reloc
.long dummy /* Page RVA */
.long 10 /* Block Size (2*4+2) */
.word (IMAGE_REL_ABSOLUTE << 12) + 0 /* reloc for dummy */
diff --git a/arch/x86/lib/efi/reloc_ia32.c b/arch/x86/lib/efi/reloc_ia32.c new file mode 100644 index 0000000..4d68255 --- /dev/null +++ b/arch/x86/lib/efi/reloc_ia32.c @@ -0,0 +1,72 @@ +/*
- reloc_ia32.c - position independent x86 ELF shared object relocator
- Copyright (C) 1999 Hewlett-Packard Co.
- Contributed by David Mosberger davidm@hpl.hp.com.
- All rights reserved.
- SPDX-License-Identifier: BSD-3-Clause
- */
+#include <common.h> +#include <efi.h> +#include <elf.h> +#include <asm/elf.h>
+efi_status_t _relocate(long ldbase, Elf32_Dyn *dyn, efi_handle_t image,
struct efi_system_table *systab)
+{
long relsz = 0, relent = 0;
Elf32_Rel *rel = 0;
unsigned long *addr;
int i;
for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
switch (dyn[i].d_tag) {
case DT_REL:
rel = (Elf32_Rel *)((unsigned long)dyn[i].d_un.d_ptr +
ldbase);
break;
case DT_RELSZ:
relsz = dyn[i].d_un.d_val;
break;
case DT_RELENT:
relent = dyn[i].d_un.d_val;
break;
case DT_RELA:
break;
default:
break;
}
}
if (!rel && relent == 0)
return EFI_SUCCESS;
if (!rel || relent == 0)
return EFI_LOAD_ERROR;
while (relsz > 0) {
/* apply the relocs */
switch (ELF32_R_TYPE(rel->r_info)) {
case R_386_NONE:
break;
case R_386_RELATIVE:
addr = (unsigned long *)(ldbase + rel->r_offset);
*addr += ldbase;
break;
default:
break;
}
rel = (Elf32_Rel *)((char *)rel + relent);
relsz -= relent;
}
return EFI_SUCCESS;
+}
Regards, Bin