11.2Sjmcneill/*	$NetBSD: reloc_aarch64.c,v 1.2 2018/08/20 09:50:18 jmcneill Exp $	*/
21.1Sjmcneill
31.1Sjmcneill/* reloc_aarch64.c - position independent x86 ELF shared object relocator
41.1Sjmcneill   Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
51.1Sjmcneill   Copyright (C) 1999 Hewlett-Packard Co.
61.1Sjmcneill	Contributed by David Mosberger <davidm@hpl.hp.com>.
71.1Sjmcneill
81.1Sjmcneill    All rights reserved.
91.1Sjmcneill
101.1Sjmcneill    Redistribution and use in source and binary forms, with or without
111.1Sjmcneill    modification, are permitted provided that the following conditions
121.1Sjmcneill    are met:
131.1Sjmcneill
141.1Sjmcneill    * Redistributions of source code must retain the above copyright
151.1Sjmcneill      notice, this list of conditions and the following disclaimer.
161.1Sjmcneill    * Redistributions in binary form must reproduce the above
171.1Sjmcneill      copyright notice, this list of conditions and the following
181.1Sjmcneill      disclaimer in the documentation and/or other materials
191.1Sjmcneill      provided with the distribution.
201.1Sjmcneill    * Neither the name of Hewlett-Packard Co. nor the names of its
211.1Sjmcneill      contributors may be used to endorse or promote products derived
221.1Sjmcneill      from this software without specific prior written permission.
231.1Sjmcneill
241.1Sjmcneill    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
251.1Sjmcneill    CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
261.1Sjmcneill    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
271.1Sjmcneill    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
281.1Sjmcneill    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
291.1Sjmcneill    BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
301.1Sjmcneill    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
311.1Sjmcneill    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
321.1Sjmcneill    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
331.1Sjmcneill    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
341.1Sjmcneill    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
351.1Sjmcneill    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
361.1Sjmcneill    SUCH DAMAGE.
371.1Sjmcneill*/
381.1Sjmcneill
391.1Sjmcneill#include <efi.h>
401.1Sjmcneill#include <efilib.h>
411.1Sjmcneill
421.2Sjmcneill#ifdef __NetBSD__
431.2Sjmcneill#include <sys/types.h>
441.2Sjmcneill#include <sys/exec_elf.h>
451.2Sjmcneill#else
461.1Sjmcneill#include <elf.h>
471.2Sjmcneill#endif
481.2Sjmcneill
491.2SjmcneillEFI_STATUS _relocate (long, Elf64_Dyn *, EFI_HANDLE, EFI_SYSTEM_TABLE *);
501.1Sjmcneill
511.1SjmcneillEFI_STATUS _relocate (long ldbase, Elf64_Dyn *dyn,
521.1Sjmcneill		      EFI_HANDLE image EFI_UNUSED,
531.1Sjmcneill		      EFI_SYSTEM_TABLE *systab EFI_UNUSED)
541.1Sjmcneill{
551.1Sjmcneill	long relsz = 0, relent = 0;
561.1Sjmcneill	Elf64_Rela *rel = 0;
571.1Sjmcneill	unsigned long *addr;
581.1Sjmcneill	int i;
591.1Sjmcneill
601.1Sjmcneill	for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
611.1Sjmcneill		switch (dyn[i].d_tag) {
621.1Sjmcneill			case DT_RELA:
631.1Sjmcneill				rel = (Elf64_Rela*)
641.1Sjmcneill					((unsigned long)dyn[i].d_un.d_ptr
651.1Sjmcneill					 + ldbase);
661.1Sjmcneill				break;
671.1Sjmcneill
681.1Sjmcneill			case DT_RELASZ:
691.1Sjmcneill				relsz = dyn[i].d_un.d_val;
701.1Sjmcneill				break;
711.1Sjmcneill
721.1Sjmcneill			case DT_RELAENT:
731.1Sjmcneill				relent = dyn[i].d_un.d_val;
741.1Sjmcneill				break;
751.1Sjmcneill
761.1Sjmcneill			default:
771.1Sjmcneill				break;
781.1Sjmcneill		}
791.1Sjmcneill	}
801.1Sjmcneill
811.1Sjmcneill	if (!rel && relent == 0)
821.1Sjmcneill		return EFI_SUCCESS;
831.1Sjmcneill
841.1Sjmcneill	if (!rel || relent == 0)
851.1Sjmcneill		return EFI_LOAD_ERROR;
861.1Sjmcneill
871.1Sjmcneill	while (relsz > 0) {
881.1Sjmcneill		/* apply the relocs */
891.1Sjmcneill		switch (ELF64_R_TYPE (rel->r_info)) {
901.1Sjmcneill			case R_AARCH64_NONE:
911.1Sjmcneill				break;
921.1Sjmcneill
931.1Sjmcneill			case R_AARCH64_RELATIVE:
941.1Sjmcneill				addr = (unsigned long *)
951.1Sjmcneill					(ldbase + rel->r_offset);
961.1Sjmcneill				*addr = ldbase + rel->r_addend;
971.1Sjmcneill				break;
981.1Sjmcneill
991.1Sjmcneill			default:
1001.1Sjmcneill				break;
1011.1Sjmcneill		}
1021.1Sjmcneill		rel = (Elf64_Rela*) ((char *) rel + relent);
1031.1Sjmcneill		relsz -= relent;
1041.1Sjmcneill	}
1051.1Sjmcneill	return EFI_SUCCESS;
1061.1Sjmcneill}
107