1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
|
/* Mac-on-Linux ELF loader
Copyright (C) 2001-2003 Samuel Rydh
adapted from yaboot
Copyright (C) 1999 Benjamin Herrenschmidt
portions based on poof
Copyright (C) 1999 Marius Vollmer
portions based on quik
Copyright (C) 1996 Paul Mackerras.
Because this program is derived from the corresponding file in the
silo-0.64 distribution, it is also
Copyright (C) 1996 Pete A. Zaitcev
1996 Maurizio Plaza
1996 David S. Miller
1996 Miguel de Icaza
1996 Jakub Jelinek
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
*/
#include "openbios/config.h"
#include "openbios/bindings.h"
#include "openbios/elfload.h"
#include "libc/diskio.h"
#include "openbios/elf.h"
#define DEBUG 0
#define MAX_HEADERS 32
#define BS 0x100 /* smallest step used when looking for the ELF header */
int
find_elf( int fd )
{
int size, offs;
seek_io( fd, -1 );
size = tell( fd );
if( size > 0x10000 )
size = 0x10000;
for( offs=0; offs < size; offs+= BS )
if( is_elf(fd, offs) )
return offs;
return -1;
}
int
is_elf( int fd, int offs )
{
Elf_ehdr e;
seek_io( fd, offs );
if( read_io(fd, &e, sizeof(e)) != sizeof(e) ) {
printk("\nCan't read ELF image header\n");
return 0;
}
return (e.e_ident[EI_MAG0] == ELFMAG0 &&
e.e_ident[EI_MAG1] == ELFMAG1 &&
e.e_ident[EI_MAG2] == ELFMAG2 &&
e.e_ident[EI_MAG3] == ELFMAG3 &&
e.e_ident[EI_CLASS] == ARCH_ELF_CLASS &&
e.e_ident[EI_DATA] == ARCH_ELF_DATA &&
e.e_type == ET_EXEC &&
ARCH_ELF_MACHINE_OK(e.e_machine));
}
Elf_phdr *
elf_readhdrs( int fd, int offs, Elf_ehdr *e )
{
int size;
Elf_phdr *ph;
if( !is_elf(fd, offs) ) {
printk("Not an ELF image\n");
return NULL;
}
seek_io( fd, offs );
if( read_io(fd, e, sizeof(*e)) != sizeof(*e) ) {
printk("\nCan't read ELF image header\n");
return NULL;
}
#if DEBUG
printk("ELF header:\n");
printk(" e.e_type = %d\n", (int)e->e_type);
printk(" e.e_machine = %d\n", (int)e->e_machine);
printk(" e.e_version = %d\n", (int)e->e_version);
printk(" e.e_entry = 0x%08x\n", (int)e->e_entry);
printk(" e.e_phoff = 0x%08x\n", (int)e->e_phoff);
printk(" e.e_shoff = 0x%08x\n", (int)e->e_shoff);
printk(" e.e_flags = %d\n", (int)e->e_flags);
printk(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
printk(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
printk(" e.e_phnum = %d\n", (int)e->e_phnum);
#endif
if (e->e_phnum > MAX_HEADERS) {
printk ("elfload: too many program headers (MAX_HEADERS)\n");
return NULL;
}
size = sizeof(Elf_phdr) * e->e_phnum;
if( !(ph=(Elf_phdr *)malloc(size)) ) {
printk("malloc error\n");
return NULL;
}
/* Now, we read the section header */
seek_io( fd, offs+e->e_phoff );
if( read_io(fd, (char*)ph, size) != size ) {
printk("read error");
free( ph );
return NULL;
}
return ph;
}
|