1/* SPDX-License-Identifier: BSD-3-Clause */
2
3/*
4 * reloc_aarch64.c - position independent x86 ELF shared object relocator
5 * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
6 * Copyright (C) 1999 Hewlett-Packard Co.
7 * Contributed by David Mosberger <davidm@hpl.hp.com>.
8 *
9 *    All rights reserved.
10 *
11 *    Redistribution and use in source and binary forms, with or without
12 *    modification, are permitted provided that the following conditions
13 *    are met:
14 *
15 *    * Redistributions of source code must retain the above copyright
16 *      notice, this list of conditions and the following disclaimer.
17 *    * Redistributions in binary form must reproduce the above
18 *      copyright notice, this list of conditions and the following
19 *      disclaimer in the documentation and/or other materials
20 *      provided with the distribution.
21 *    * Neither the name of Hewlett-Packard Co. nor the names of its
22 *      contributors may be used to endorse or promote products derived
23 *      from this software without specific prior written permission.
24 *
25 *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
26 *    CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
27 *    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
28 *    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29 *    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
30 *    BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
31 *    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 *    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 *    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 *    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
35 *    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
36 *    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 *    SUCH DAMAGE.
38 */
39
40#include <elfloader_common.h>
41#include <binaries/efi/efi.h>
42
43#include <binaries/elf/elf.h>
44#include <binaries/elf/elf64.h>
45
46long unsigned int _relocate(unsigned long ldbase, struct Elf64_Dyn *dyn,
47                            void *image UNUSED,
48                            void *systab UNUSED)
49{
50    long relsz = 0, relent = 0;
51    struct Elf64_Rela *rel = 0;
52    unsigned long *addr;
53    int i;
54
55    for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
56        switch (dyn[i].d_tag) {
57        case DT_RELA:
58            rel = (struct Elf64_Rela *)
59                  ((unsigned long)dyn[i].d_un.d_ptr
60                   + ldbase);
61            break;
62
63        case DT_RELASZ:
64            relsz = dyn[i].d_un.d_val;
65            break;
66
67        case DT_RELAENT:
68            relent = dyn[i].d_un.d_val;
69            break;
70
71        default:
72            break;
73        }
74    }
75
76    if (!rel && relent == 0) {
77        return EFI_SUCCESS;
78    }
79
80    if (!rel || relent == 0) {
81        return EFI_LOAD_ERROR;
82    }
83
84    while (relsz > 0) {
85        /* apply the relocs */
86        switch (ELF64_R_TYPE(rel->r_info)) {
87        case R_AARCH64_NONE:
88            break;
89
90        case R_AARCH64_RELATIVE:
91            addr = (unsigned long *)
92                   (ldbase + rel->r_offset);
93            *addr = ldbase + rel->r_addend;
94            break;
95
96        default:
97            break;
98        }
99        rel = (struct Elf64_Rela *)((char *) rel + relent);
100        relsz -= relent;
101    }
102    return EFI_SUCCESS;
103}
104