diff options
author | Simon Glass <sjg@chromium.org> | 2015-08-04 18:33:51 (GMT) |
---|---|---|
committer | Simon Glass <sjg@chromium.org> | 2015-08-05 14:44:06 (GMT) |
commit | 465a67cf529bd2f7a5ca871aff3fa63faa142516 (patch) | |
tree | ebce4cf7d0796e4e0c0527d1773710f8c563d971 /arch/x86/lib | |
parent | cd326a32c9fc317af30d682db2ba8f3242bc1221 (diff) | |
download | u-boot-465a67cf529bd2f7a5ca871aff3fa63faa142516.tar.xz |
x86: Add relocation and link script for a 64-bit EFI application
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>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Diffstat (limited to 'arch/x86/lib')
-rw-r--r-- | arch/x86/lib/efi/reloc_x86_64.c | 66 |
1 files changed, 66 insertions, 0 deletions
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; +} |