xref: /openbmc/u-boot/arch/x86/lib/reloc_x86_64_efi.c (revision fc82e768)
183d290c5STom Rini // SPDX-License-Identifier: BSD-3-Clause
22dcd4e9eSSimon Glass /*
32dcd4e9eSSimon Glass  * reloc_x86_64.c - position independent x86_64 ELF shared object relocator
42dcd4e9eSSimon Glass  * Copyright (C) 1999 Hewlett-Packard Co.
52dcd4e9eSSimon Glass  * Contributed by David Mosberger <davidm@hpl.hp.com>.
62dcd4e9eSSimon Glass  * Copyright (C) 2005 Intel Co.
72dcd4e9eSSimon Glass  * Contributed by Fenghua Yu <fenghua.yu@intel.com>.
82dcd4e9eSSimon Glass  *
92dcd4e9eSSimon Glass  * All rights reserved.
102dcd4e9eSSimon Glass  */
112dcd4e9eSSimon Glass 
122dcd4e9eSSimon Glass #include <common.h>
132dcd4e9eSSimon Glass #include <efi.h>
142dcd4e9eSSimon Glass #include <elf.h>
152dcd4e9eSSimon Glass 
_relocate(long ldbase,Elf64_Dyn * dyn)16*62500986SIvan Gorinov efi_status_t EFIAPI _relocate(long ldbase, Elf64_Dyn *dyn)
172dcd4e9eSSimon Glass {
182dcd4e9eSSimon Glass 	long relsz = 0, relent = 0;
192dcd4e9eSSimon Glass 	Elf64_Rel *rel = 0;
202dcd4e9eSSimon Glass 	unsigned long *addr;
212dcd4e9eSSimon Glass 	int i;
222dcd4e9eSSimon Glass 
232dcd4e9eSSimon Glass 	for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
242dcd4e9eSSimon Glass 		switch (dyn[i].d_tag) {
252dcd4e9eSSimon Glass 		case DT_RELA:
262dcd4e9eSSimon Glass 			rel = (Elf64_Rel *)
272dcd4e9eSSimon Glass 				((unsigned long)dyn[i].d_un.d_ptr + ldbase);
282dcd4e9eSSimon Glass 			break;
292dcd4e9eSSimon Glass 		case DT_RELASZ:
302dcd4e9eSSimon Glass 			relsz = dyn[i].d_un.d_val;
312dcd4e9eSSimon Glass 			break;
322dcd4e9eSSimon Glass 		case DT_RELAENT:
332dcd4e9eSSimon Glass 			relent = dyn[i].d_un.d_val;
342dcd4e9eSSimon Glass 			break;
352dcd4e9eSSimon Glass 		default:
362dcd4e9eSSimon Glass 			break;
372dcd4e9eSSimon Glass 		}
382dcd4e9eSSimon Glass 	}
392dcd4e9eSSimon Glass 
402dcd4e9eSSimon Glass 	if (!rel && relent == 0)
412dcd4e9eSSimon Glass 		return EFI_SUCCESS;
422dcd4e9eSSimon Glass 
432dcd4e9eSSimon Glass 	if (!rel || relent == 0)
442dcd4e9eSSimon Glass 		return EFI_LOAD_ERROR;
452dcd4e9eSSimon Glass 
462dcd4e9eSSimon Glass 	while (relsz > 0) {
472dcd4e9eSSimon Glass 		/* apply the relocs */
482dcd4e9eSSimon Glass 		switch (ELF64_R_TYPE(rel->r_info)) {
492dcd4e9eSSimon Glass 		case R_X86_64_NONE:
502dcd4e9eSSimon Glass 			break;
512dcd4e9eSSimon Glass 		case R_X86_64_RELATIVE:
522dcd4e9eSSimon Glass 			addr = (unsigned long *)(ldbase + rel->r_offset);
532dcd4e9eSSimon Glass 			*addr += ldbase;
542dcd4e9eSSimon Glass 			break;
552dcd4e9eSSimon Glass 		default:
562dcd4e9eSSimon Glass 			break;
572dcd4e9eSSimon Glass 		}
582dcd4e9eSSimon Glass 		rel = (Elf64_Rel *)((char *)rel + relent);
592dcd4e9eSSimon Glass 		relsz -= relent;
602dcd4e9eSSimon Glass 	}
612dcd4e9eSSimon Glass 
622dcd4e9eSSimon Glass 	return EFI_SUCCESS;
632dcd4e9eSSimon Glass }
64