1/* SPDX-License-Identifier: BSD-3-Clause */
2
3/*
4 * reloc_arm.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/elf32.h>
45
46unsigned int _relocate(unsigned long ldbase, struct Elf32_Dyn *dyn,
47                       void *image,
48                       void *systab)
49{
50    long relsz = 0, relent = 0;
51    struct Elf32_Rel *rel = 0;
52    unsigned long *addr;
53    int i;
54
55
56    unsigned long total_offs = ldbase;
57    if (!systab) {
58        total_offs = ((unsigned long)image);
59    }
60    for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
61        switch (dyn[i].d_tag) {
62        case DT_REL:
63            rel = (struct Elf32_Rel *)
64                  ((unsigned long)dyn[i].d_un.d_ptr
65                   + total_offs);
66            break;
67
68        case DT_RELSZ:
69            relsz = dyn[i].d_un.d_val;
70            break;
71
72        case DT_RELENT:
73            relent = dyn[i].d_un.d_val;
74            break;
75
76        default:
77            break;
78        }
79    }
80
81    if (!rel && relent == 0) {
82        return EFI_SUCCESS;
83    }
84
85    if (!rel || relent == 0) {
86        return EFI_LOAD_ERROR;
87    }
88
89    while (relsz > 0) {
90        /* apply the relocs */
91        switch (ELF32_R_TYPE(rel->r_info)) {
92        case R_ARM_NONE:
93            break;
94
95        case R_ARM_RELATIVE:
96            addr = (unsigned long *)
97                   (total_offs + rel->r_offset);
98            if (!systab) {
99                *addr -= ldbase;
100                *addr += total_offs;
101            } else {
102                *addr += ldbase;
103            }
104            break;
105
106        default:
107            break;
108        }
109        rel = (struct Elf32_Rel *)((char *) rel + relent);
110        relsz -= relent;
111    }
112    return EFI_SUCCESS;
113}
114