Message ID | 1438356724-6561-34-git-send-email-sjg@chromium.org |
---|---|
State | Superseded |
Delegated to: | Simon Glass |
Headers | show |
On Fri, Jul 31, 2015 at 11:31 PM, Simon Glass <sjg@chromium.org> wrote: > Add a linker script and relocation code for building 64-bit EFI > applications. This can be used for the EFI stub. > > Signed-off-by: Simon Glass <sjg@chromium.org> > Improvements to how the payload is built: > Signed-off-by: Bin Meng <bmeng.cn@gmail.com> > --- > > Changes in v2: > - Add a comment as to why .hash has to be first in the linker script > - Change 'link script' to 'linker script' > - Drop . = 0x0; > - Fix reference to elf_ia32_efi instead of elf_x86_64_efi > - Merge in Bin's implementation of adding a U-Boot payload with objcopy > - Remove KEEP in the EFI linker script since garbage collection is not enabled > - Rename ImageBase to image_base > - Update based on the elf.h changes > > arch/x86/cpu/efi/elf_x86_64_efi.lds | 83 +++++++++++++++++++++++++++++++++++++ > arch/x86/lib/efi/reloc_x86_64.c | 66 +++++++++++++++++++++++++++++ > 2 files changed, 149 insertions(+) > create mode 100644 arch/x86/cpu/efi/elf_x86_64_efi.lds > create mode 100644 arch/x86/lib/efi/reloc_x86_64.c > > diff --git a/arch/x86/cpu/efi/elf_x86_64_efi.lds b/arch/x86/cpu/efi/elf_x86_64_efi.lds > new file mode 100644 > index 0000000..667fbe2 > --- /dev/null > +++ b/arch/x86/cpu/efi/elf_x86_64_efi.lds > @@ -0,0 +1,83 @@ > +/* > + * U-Boot EFI linker script > + * > + * SPDX-License-Identifier: bsd-2-clause > + * > + * Modified from usr/lib32/elf_x86_64_efi.lds in gnu-efi > + */ > + > +#include <config.h> > + > +OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") > +OUTPUT_ARCH(i386:x86-64) > +ENTRY(_start) > +SECTIONS > +{ > + image_base = .; > + .hash : { *(.hash) } /* this MUST come first, EFI expects it */ > + . = ALIGN(4096); > + .eh_frame : { > + *(.eh_frame) > + } > + > + . = ALIGN(4096); > + > + .text : { > + *(.text) > + *(.text.*) > + *(.gnu.linkonce.t.*) > + } > + > + . = ALIGN(4096); > + > + .reloc : { > + *(.reloc) > + } > + > + . = ALIGN(4096); > + > + .data : { > + *(.rodata*) > + *(.got.plt) > + *(.got) > + *(.data*) > + *(.sdata) > + /* the EFI loader doesn't seem to like a .bss section, so we stick > + * it all into .data: */ > + *(.sbss) > + *(.scommon) > + *(.dynbss) > + *(.bss) > + *(COMMON) > + *(.rel.local) > + > + /* U-Boot lists and device tree */ > + . = ALIGN(8); > + *(SORT(.u_boot_list*)); > + . = ALIGN(8); > + *(.dtb*); > + } > + > + . = ALIGN(4096); > + .dynamic : { *(.dynamic) } > + . = ALIGN(4096); > + > + .rela : { > + *(.rela.data*) > + *(.rela.got) > + *(.rela.stab) > + } > + > + . = ALIGN(4096); > + .dynsym : { *(.dynsym) } > + . = ALIGN(4096); > + .dynstr : { *(.dynstr) } > + . = ALIGN(4096); > + .ignored.reloc : { > + *(.rela.reloc) > + *(.eh_frame) > + *(.note.GNU-stack) > + } > + > + .comment 0 : { *(.comment) } > +} > diff --git a/arch/x86/lib/efi/reloc_x86_64.c b/arch/x86/lib/efi/reloc_x86_64.c > new file mode 100644 > index 0000000..5f71f2a > --- /dev/null > +++ b/arch/x86/lib/efi/reloc_x86_64.c > @@ -0,0 +1,66 @@ > +/* > + * reloc_x86_64.c - position independent x86_64 ELF shared object relocator > + * Copyright (C) 1999 Hewlett-Packard Co. > + * Contributed by David Mosberger <davidm@hpl.hp.com>. > + * Copyright (C) 2005 Intel Co. > + * Contributed by Fenghua Yu <fenghua.yu@intel.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, Elf64_Dyn *dyn, efi_handle_t image, > + struct efi_system_table *systab) > +{ > + long relsz = 0, relent = 0; > + Elf64_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_RELA: > + rel = (Elf64_Rel *) > + ((unsigned long)dyn[i].d_un.d_ptr + ldbase); > + break; > + case DT_RELASZ: > + relsz = dyn[i].d_un.d_val; > + break; > + case DT_RELAENT: > + relent = dyn[i].d_un.d_val; > + 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 (ELF64_R_TYPE(rel->r_info)) { > + case R_X86_64_NONE: > + break; > + case R_X86_64_RELATIVE: > + addr = (unsigned long *)(ldbase + rel->r_offset); > + *addr += ldbase; > + break; > + default: > + break; > + } > + rel = (Elf64_Rel *)((char *)rel + relent); > + relsz -= relent; > + } > + > + return EFI_SUCCESS; > +} > -- Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
diff --git a/arch/x86/cpu/efi/elf_x86_64_efi.lds b/arch/x86/cpu/efi/elf_x86_64_efi.lds new file mode 100644 index 0000000..667fbe2 --- /dev/null +++ b/arch/x86/cpu/efi/elf_x86_64_efi.lds @@ -0,0 +1,83 @@ +/* + * U-Boot EFI linker script + * + * SPDX-License-Identifier: bsd-2-clause + * + * Modified from usr/lib32/elf_x86_64_efi.lds in gnu-efi + */ + +#include <config.h> + +OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") +OUTPUT_ARCH(i386:x86-64) +ENTRY(_start) +SECTIONS +{ + image_base = .; + .hash : { *(.hash) } /* this MUST come first, EFI expects it */ + . = ALIGN(4096); + .eh_frame : { + *(.eh_frame) + } + + . = ALIGN(4096); + + .text : { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + . = ALIGN(4096); + + .reloc : { + *(.reloc) + } + + . = ALIGN(4096); + + .data : { + *(.rodata*) + *(.got.plt) + *(.got) + *(.data*) + *(.sdata) + /* the EFI loader doesn't seem to like a .bss section, so we stick + * it all into .data: */ + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + *(.rel.local) + + /* U-Boot lists and device tree */ + . = ALIGN(8); + *(SORT(.u_boot_list*)); + . = ALIGN(8); + *(.dtb*); + } + + . = ALIGN(4096); + .dynamic : { *(.dynamic) } + . = ALIGN(4096); + + .rela : { + *(.rela.data*) + *(.rela.got) + *(.rela.stab) + } + + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } + . = ALIGN(4096); + .ignored.reloc : { + *(.rela.reloc) + *(.eh_frame) + *(.note.GNU-stack) + } + + .comment 0 : { *(.comment) } +} diff --git a/arch/x86/lib/efi/reloc_x86_64.c b/arch/x86/lib/efi/reloc_x86_64.c new file mode 100644 index 0000000..5f71f2a --- /dev/null +++ b/arch/x86/lib/efi/reloc_x86_64.c @@ -0,0 +1,66 @@ +/* + * reloc_x86_64.c - position independent x86_64 ELF shared object relocator + * Copyright (C) 1999 Hewlett-Packard Co. + * Contributed by David Mosberger <davidm@hpl.hp.com>. + * Copyright (C) 2005 Intel Co. + * Contributed by Fenghua Yu <fenghua.yu@intel.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, Elf64_Dyn *dyn, efi_handle_t image, + struct efi_system_table *systab) +{ + long relsz = 0, relent = 0; + Elf64_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_RELA: + rel = (Elf64_Rel *) + ((unsigned long)dyn[i].d_un.d_ptr + ldbase); + break; + case DT_RELASZ: + relsz = dyn[i].d_un.d_val; + break; + case DT_RELAENT: + relent = dyn[i].d_un.d_val; + 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 (ELF64_R_TYPE(rel->r_info)) { + case R_X86_64_NONE: + break; + case R_X86_64_RELATIVE: + addr = (unsigned long *)(ldbase + rel->r_offset); + *addr += ldbase; + break; + default: + break; + } + rel = (Elf64_Rel *)((char *)rel + relent); + relsz -= relent; + } + + return EFI_SUCCESS; +}