/* 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; }