~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/openhackware/src/libexec/elf.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * <elf.c>
 
3
 *
 
4
 * Open Hack'Ware BIOS ELF executable file loader
 
5
 * 
 
6
 * Copyright (c) 2004-2005 Jocelyn Mayer
 
7
 * 
 
8
 *   This program is free software; you can redistribute it and/or
 
9
 *   modify it under the terms of the GNU General Public License V2
 
10
 *   as published by the Free Software Foundation
 
11
 *
 
12
 *   This program is distributed in the hope that it will be useful,
 
13
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 *   GNU General Public License for more details.
 
16
 *
 
17
 *   You should have received a copy of the GNU General Public License
 
18
 *   along with this program; if not, write to the Free Software
 
19
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
20
 */
 
21
 
 
22
#include <stdlib.h>
 
23
#include <stdio.h>
 
24
#include "bios.h"
 
25
#include "exec.h"
 
26
 
 
27
uint32_t fs_inode_get_size (inode_t *inode);
 
28
 
 
29
/* ELF executable loader */
 
30
typedef uint16_t Elf32_Half;
 
31
typedef uint32_t Elf32_Word;
 
32
typedef uint32_t Elf32_Off;
 
33
typedef uint32_t Elf32_Addr;
 
34
 
 
35
#define EI_NIDENT       16
 
36
 
 
37
typedef struct elf32_hdr_t {
 
38
  unsigned char e_ident[EI_NIDENT];
 
39
  Elf32_Half    e_type;
 
40
  Elf32_Half    e_machine;
 
41
  Elf32_Word    e_version;
 
42
  Elf32_Addr    e_entry;  /* Entry point */
 
43
  Elf32_Off     e_phoff;
 
44
  Elf32_Off     e_shoff;
 
45
  Elf32_Word    e_flags;
 
46
  Elf32_Half    e_ehsize;
 
47
  Elf32_Half    e_phentsize;
 
48
  Elf32_Half    e_phnum;
 
49
  Elf32_Half    e_shentsize;
 
50
  Elf32_Half    e_shnum;
 
51
  Elf32_Half    e_shstrndx;
 
52
} Elf32_Ehdr_t;
 
53
 
 
54
typedef struct elf32_phdr_t {
 
55
  Elf32_Word    p_type;
 
56
  Elf32_Off     p_offset;
 
57
  Elf32_Addr    p_vaddr;
 
58
  Elf32_Addr    p_paddr;
 
59
  Elf32_Word    p_filesz;
 
60
  Elf32_Word    p_memsz;
 
61
  Elf32_Word    p_flags;
 
62
  Elf32_Word    p_align;
 
63
} Elf32_Phdr_t;
 
64
 
 
65
#define EI_MAG0         0               /* e_ident[] indexes */
 
66
#define EI_MAG1         1
 
67
#define EI_MAG2         2
 
68
#define EI_MAG3         3
 
69
#define EI_CLASS        4
 
70
#define EI_DATA         5
 
71
#define EI_VERSION      6
 
72
#define EI_OSABI        7
 
73
#define EI_PAD          8
 
74
 
 
75
#define ELFMAG0         0x7f            /* EI_MAG */
 
76
#define ELFMAG1         'E'
 
77
#define ELFMAG2         'L'
 
78
#define ELFMAG3         'F'
 
79
 
 
80
#define ELFCLASSNONE    0               /* EI_CLASS */
 
81
#define ELFCLASS32      1
 
82
#define ELFCLASS64      2
 
83
#define ELFCLASSNUM     3
 
84
 
 
85
#define ELFDATANONE     0               /* e_ident[EI_DATA] */
 
86
#define ELFDATA2LSB     1
 
87
#define ELFDATA2MSB     2
 
88
 
 
89
#define EV_NONE         0               /* e_version, EI_VERSION */
 
90
#define EV_CURRENT      1
 
91
#define EV_NUM          2
 
92
 
 
93
/* These constants define the different elf file types */
 
94
#define ET_NONE   0
 
95
#define ET_REL    1
 
96
#define ET_EXEC   2
 
97
#define ET_DYN    3
 
98
#define ET_CORE   4
 
99
#define ET_LOPROC 0xff00
 
100
#define ET_HIPROC 0xffff
 
101
 
 
102
/* These constants define the various ELF target machines */
 
103
#define EM_NONE  0
 
104
#define EM_M32   1
 
105
#define EM_SPARC 2
 
106
#define EM_386   3
 
107
#define EM_68K   4
 
108
#define EM_88K   5
 
109
#define EM_486   6   /* Perhaps disused */
 
110
#define EM_860   7
 
111
#define EM_MIPS         8       /* MIPS R3000 (officially, big-endian only) */
 
112
#define EM_MIPS_RS4_BE 10       /* MIPS R4000 big-endian */
 
113
#define EM_PARISC      15       /* HPPA */
 
114
#define EM_SPARC32PLUS 18       /* Sun's "v8plus" */
 
115
#define EM_PPC         20       /* PowerPC */
 
116
#define EM_PPC64       21       /* PowerPC64 */
 
117
#define EM_SH          42       /* SuperH */
 
118
#define EM_SPARCV9     43       /* SPARC v9 64-bit */
 
119
#define EM_IA_64        50      /* HP/Intel IA-64 */
 
120
#define EM_X86_64       62      /* AMD x86-64 */
 
121
#define EM_S390         22      /* IBM S/390 */
 
122
#define EM_CRIS         76      /* Axis Communications 32-bit embedded processor */
 
123
#define EM_V850         87      /* NEC v850 */
 
124
#define EM_H8_300H      47      /* Hitachi H8/300H */
 
125
#define EM_H8S          48      /* Hitachi H8S     */
 
126
/*
 
127
 * This is an interim value that we will use until the committee comes
 
128
 * up with a final number.
 
129
 */
 
130
#define EM_ALPHA        0x9026
 
131
/* Bogus old v850 magic number, used by old tools.  */
 
132
#define EM_CYGNUS_V850  0x9080
 
133
/*
 
134
 * This is the old interim value for S/390 architecture
 
135
 */
 
136
#define EM_S390_OLD     0xA390
 
137
 
 
138
int exec_load_elf (inode_t *file, void **dest, void **entry, void **end,
 
139
                   uint32_t loffset)
 
140
{
 
141
    Elf32_Ehdr_t ehdr;
 
142
    Elf32_Phdr_t phdr;
 
143
    void *address, *first, *last;
 
144
    uint32_t offset, fsize, msize;
 
145
    int i;
 
146
 
 
147
    file_seek(file, loffset);
 
148
    if (fs_read(file, &ehdr, sizeof(Elf32_Ehdr_t)) < 0) {
 
149
        ERROR("Cannot load first bloc of file...\n");
 
150
        return -1;
 
151
    }
 
152
    DPRINTF("Check ELF file\n");
 
153
    /* Check ident */
 
154
    if (ehdr.e_ident[EI_MAG0] != ELFMAG0 ||
 
155
        ehdr.e_ident[EI_MAG1] != ELFMAG1 ||
 
156
        ehdr.e_ident[EI_MAG2] != ELFMAG2 ||
 
157
        ehdr.e_ident[EI_MAG3] != ELFMAG3) {
 
158
        DPRINTF("Not an ELF file %0x\n", *(uint32_t *)ehdr.e_ident);
 
159
        return -2;
 
160
    }
 
161
    if (ehdr.e_ident[EI_CLASS] != ELFCLASS32) {
 
162
        ERROR("Not a 32 bits ELF file\n");
 
163
        return -2;
 
164
    }
 
165
    if (ehdr.e_ident[EI_DATA] != ELFDATA2MSB) {
 
166
        ERROR("Not a big-endian ELF file\n");
 
167
        return -2;
 
168
    }
 
169
    if (ehdr.e_ident[EI_VERSION] != EV_CURRENT /*||
 
170
        ehdr->e_version != EV_CURRENT*/) {
 
171
        ERROR("Invalid ELF executable version %d %08x\n",
 
172
              ehdr.e_ident[EI_VERSION], ehdr.e_version);
 
173
        return -2;
 
174
    }
 
175
    if (ehdr.e_type != ET_EXEC) {
 
176
        ERROR("Not an executable ELF file\n");
 
177
        return -2;
 
178
    }
 
179
    if (ehdr.e_machine != EM_PPC) {
 
180
        ERROR("Not a PPC ELF executable\n");
 
181
        return -2;
 
182
    }
 
183
    /* All right, seems to be a regular ELF program for PPC */
 
184
    *entry = (void *)ehdr.e_entry;
 
185
    DPRINTF("ELF file found entry = %p\n", *entry);
 
186
    last = NULL;
 
187
    first = last - 4;
 
188
    fsize = msize = 0;
 
189
    offset = ehdr.e_phoff;
 
190
    for (i = 0; i < ehdr.e_phnum; i++) {
 
191
#if 0
 
192
        if (offset > fs_inode_get_size(file)) {
 
193
            ERROR("ELF program header %d offset > file size %d %d\n", i,
 
194
                  offset, fs_inode_get_size(file));
 
195
            return -1;
 
196
        }
 
197
#endif
 
198
        DPRINTF("Load program header %d from %08x\n", i, offset);
 
199
        file_seek(file, offset + loffset);
 
200
        if (fs_read(file, &phdr, sizeof(Elf32_Phdr_t)) < 0) {
 
201
            ERROR("Cannot load ELF program header %d...\n", i);
 
202
            return -1;
 
203
        }
 
204
        DPRINTF("Load program header %d %08x %08x %08x %08x\n", i,
 
205
                phdr.p_offset, phdr.p_vaddr, phdr.p_filesz, phdr.p_memsz);
 
206
#if 0
 
207
        if (phdr.p_offset > fs_inode_get_size(file)) {
 
208
            ERROR("ELF program %d offset > file size %d %d\n",
 
209
                  i, phdr.p_offset, fs_inode_get_size(file));
 
210
            return -1;
 
211
        }
 
212
#endif
 
213
        /* As we won't remap memory, load it at it's virtual address (!) */
 
214
        address = (void *)phdr.p_vaddr;
 
215
        if (address < first)
 
216
            first = address;
 
217
        fsize = phdr.p_filesz;
 
218
        msize = phdr.p_memsz;
 
219
        if (address + msize > last)
 
220
            last = address + msize;
 
221
        file_seek(file, phdr.p_offset + loffset);
 
222
        set_loadinfo((void *)first, last - first);
 
223
        if (fs_read(file, address, fsize) < 0) {
 
224
            ERROR("Cannot load ELF program %d...\n", i);
 
225
            return -1;
 
226
        }
 
227
        if (msize > fsize) {
 
228
            memset(address + fsize, 0, msize - fsize);
 
229
        }
 
230
        offset += ehdr.e_phentsize;
 
231
    }
 
232
    *dest = (void *)first;
 
233
    *end = (void *)last;
 
234
    DPRINTF("ELF file loaded at %p => %p fsize %08x msize %08x "
 
235
            "(%08x %08x)\n", *dest, *entry, fsize, msize,
 
236
            *(uint32_t *)entry, *((uint32_t *)entry + 1));
 
237
 
 
238
    return 0;
 
239
}