Message ID | 1438713246-1887-9-git-send-email-sjg@chromium.org |
---|---|
State | Accepted |
Delegated to: | Simon Glass |
Headers | show |
On Wed, Aug 5, 2015 at 2:33 AM, 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 v3: > - Move u-boot-app.efi Makefile change to the earlier patch > - Use "BSD-2-Clause" for the SPDX license > > 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 > > 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 +++++++++++++++++++++++++++ > 11 files changed, 319 insertions(+) > 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/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..cd3b0a9 > --- /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 > + * > + * 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; > +} > -- Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
On 5 August 2015 at 01:42, Bin Meng <bmeng.cn@gmail.com> wrote: > On Wed, Aug 5, 2015 at 2:33 AM, 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 v3: >> - Move u-boot-app.efi Makefile change to the earlier patch >> - Use "BSD-2-Clause" for the SPDX license >> >> 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 >> >> 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 +++++++++++++++++++++++++++ >> 11 files changed, 319 insertions(+) >> 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/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..cd3b0a9 >> --- /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 >> + * >> + * 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; >> +} >> -- > > Reviewed-by: Bin Meng <bmeng.cn@gmail.com> Applied to u-boot-x86.
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..cd3b0a9 --- /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 + * + * 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; +}