Home | History | Annotate | Download | only in lib
      1 // SPDX-License-Identifier: BSD-3-Clause
      2 /*
      3  * reloc_x86_64.c - position independent x86_64 ELF shared object relocator
      4  * Copyright (C) 1999 Hewlett-Packard Co.
      5  * Contributed by David Mosberger <davidm (at) hpl.hp.com>.
      6  * Copyright (C) 2005 Intel Co.
      7  * Contributed by Fenghua Yu <fenghua.yu (at) intel.com>.
      8  *
      9  * All rights reserved.
     10  */
     11 
     12 #include <common.h>
     13 #include <efi.h>
     14 #include <elf.h>
     15 #include <asm/elf.h>
     16 
     17 efi_status_t _relocate(long ldbase, Elf64_Dyn *dyn, efi_handle_t image,
     18 		       struct efi_system_table *systab)
     19 {
     20 	long relsz = 0, relent = 0;
     21 	Elf64_Rel *rel = 0;
     22 	unsigned long *addr;
     23 	int i;
     24 
     25 	for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
     26 		switch (dyn[i].d_tag) {
     27 		case DT_RELA:
     28 			rel = (Elf64_Rel *)
     29 				((unsigned long)dyn[i].d_un.d_ptr + ldbase);
     30 			break;
     31 		case DT_RELASZ:
     32 			relsz = dyn[i].d_un.d_val;
     33 			break;
     34 		case DT_RELAENT:
     35 			relent = dyn[i].d_un.d_val;
     36 			break;
     37 		default:
     38 			break;
     39 		}
     40 	}
     41 
     42 	if (!rel && relent == 0)
     43 		return EFI_SUCCESS;
     44 
     45 	if (!rel || relent == 0)
     46 		return EFI_LOAD_ERROR;
     47 
     48 	while (relsz > 0) {
     49 		/* apply the relocs */
     50 		switch (ELF64_R_TYPE(rel->r_info)) {
     51 		case R_X86_64_NONE:
     52 			break;
     53 		case R_X86_64_RELATIVE:
     54 			addr = (unsigned long *)(ldbase + rel->r_offset);
     55 			*addr += ldbase;
     56 			break;
     57 		default:
     58 			break;
     59 		}
     60 		rel = (Elf64_Rel *)((char *)rel + relent);
     61 		relsz -= relent;
     62 	}
     63 
     64 	return EFI_SUCCESS;
     65 }
     66