Annotation of qemu/roms/SLOF/lib/libelf/elf.c, revision 1.1

1.1     ! root        1: /******************************************************************************
        !             2:  * Copyright (c) 2004, 2008 IBM Corporation
        !             3:  * All rights reserved.
        !             4:  * This program and the accompanying materials
        !             5:  * are made available under the terms of the BSD License
        !             6:  * which accompanies this distribution, and is available at
        !             7:  * http://www.opensource.org/licenses/bsd-license.php
        !             8:  *
        !             9:  * Contributors:
        !            10:  *     IBM Corporation - initial implementation
        !            11:  *****************************************************************************/
        !            12: 
        !            13: /* this is elf.fs rewritten in C */
        !            14: 
        !            15: #include <string.h>
        !            16: #include <cpu.h>
        !            17: #include <libelf.h>
        !            18: 
        !            19: struct ehdr {
        !            20:        unsigned int ei_ident;
        !            21:        unsigned char ei_class;
        !            22:        unsigned char ei_data;
        !            23:        unsigned char ei_version;
        !            24:        unsigned char ei_pad[9];
        !            25:        unsigned short e_type;
        !            26:        unsigned short e_machine;
        !            27:        unsigned int e_version;
        !            28:        unsigned int e_entry;
        !            29:        unsigned int e_phoff;
        !            30:        unsigned int e_shoff;
        !            31:        unsigned int e_flags;
        !            32:        unsigned short e_ehsize;
        !            33:        unsigned short e_phentsize;
        !            34:        unsigned short e_phnum;
        !            35:        unsigned short e_shentsize;
        !            36:        unsigned short e_shnum;
        !            37:        unsigned short e_shstrndx;
        !            38: };
        !            39: 
        !            40: struct phdr {
        !            41:        unsigned int p_type;
        !            42:        unsigned int p_offset;
        !            43:        unsigned int p_vaddr;
        !            44:        unsigned int p_paddr;
        !            45:        unsigned int p_filesz;
        !            46:        unsigned int p_memsz;
        !            47:        unsigned int p_flags;
        !            48:        unsigned int p_align;
        !            49: };
        !            50: 
        !            51: struct ehdr64 {
        !            52:        unsigned int ei_ident;
        !            53:        unsigned char ei_class;
        !            54:        unsigned char ei_data;
        !            55:        unsigned char ei_version;
        !            56:        unsigned char ei_pad[9];
        !            57:        unsigned short e_type;
        !            58:        unsigned short e_machine;
        !            59:        unsigned int e_version;
        !            60:        unsigned long e_entry;
        !            61:        unsigned long e_phoff;
        !            62:        unsigned long e_shoff;
        !            63:        unsigned int e_flags;
        !            64:        unsigned short e_ehsize;
        !            65:        unsigned short e_phentsize;
        !            66:        unsigned short e_phnum;
        !            67:        unsigned short e_shentsize;
        !            68:        unsigned short e_shnum;
        !            69:        unsigned short e_shstrndx;
        !            70: };
        !            71: 
        !            72: struct phdr64 {
        !            73:        unsigned int p_type;
        !            74:        unsigned int p_flags;
        !            75:        unsigned long p_offset;
        !            76:        unsigned long p_vaddr;
        !            77:        unsigned long p_paddr;
        !            78:        unsigned long p_filesz;
        !            79:        unsigned long p_memsz;
        !            80:        unsigned long p_align;
        !            81: };
        !            82: 
        !            83: #define VOID(x) (void *)((unsigned long)x)
        !            84: 
        !            85: static void
        !            86: load_segment(unsigned long *file_addr, struct phdr *phdr)
        !            87: {
        !            88:        unsigned long src = phdr->p_offset + (unsigned long) file_addr;
        !            89:        /* copy into storage */
        !            90:        memmove(VOID(phdr->p_vaddr), VOID(src), phdr->p_filesz);
        !            91: 
        !            92:        /* clear bss */
        !            93:        memset(VOID(phdr->p_vaddr + phdr->p_filesz), 0,
        !            94:               phdr->p_memsz - phdr->p_filesz);
        !            95: 
        !            96:        if (phdr->p_memsz) {
        !            97:                flush_cache(VOID(phdr->p_vaddr), phdr->p_memsz);
        !            98:        }
        !            99: }
        !           100: 
        !           101: static unsigned int
        !           102: load_segments(unsigned long *file_addr)
        !           103: {
        !           104:        struct ehdr *ehdr = (struct ehdr *) file_addr;
        !           105:        /* Calculate program header address */
        !           106:        struct phdr *phdr =
        !           107:            (struct phdr *) (((unsigned char *) file_addr) + ehdr->e_phoff);
        !           108:        int i;
        !           109:        /* loop e_phnum times */
        !           110:        for (i = 0; i <= ehdr->e_phnum; i++) {
        !           111:                /* PT_LOAD ? */
        !           112:                if (phdr->p_type == 1) {
        !           113:                        /* copy segment */
        !           114:                        load_segment(file_addr, phdr);
        !           115:                }
        !           116:                /* step to next header */
        !           117:                phdr =
        !           118:                    (struct phdr *) (((unsigned char *) phdr) +
        !           119:                                     ehdr->e_phentsize);
        !           120:        }
        !           121:        return ehdr->e_entry;
        !           122: }
        !           123: 
        !           124: static void
        !           125: load_segment64(unsigned long *file_addr, struct phdr64 *phdr64)
        !           126: {
        !           127:        unsigned long src = phdr64->p_offset + (unsigned long) file_addr;
        !           128:        /* copy into storage */
        !           129:        memmove(VOID(phdr64->p_vaddr), VOID(src), phdr64->p_filesz);
        !           130: 
        !           131:        /* clear bss */
        !           132:        memset(VOID(phdr64->p_vaddr + phdr64->p_filesz), 0,
        !           133:               phdr64->p_memsz - phdr64->p_filesz);
        !           134: 
        !           135:        if (phdr64->p_memsz) {
        !           136:                flush_cache(VOID(phdr64->p_vaddr), phdr64->p_memsz);
        !           137:        }
        !           138: }
        !           139: 
        !           140: static unsigned long
        !           141: load_segments64(unsigned long *file_addr)
        !           142: {
        !           143:        struct ehdr64 *ehdr64 = (struct ehdr64 *) file_addr;
        !           144:        /* Calculate program header address */
        !           145:        struct phdr64 *phdr64 =
        !           146:            (struct phdr64 *) (((unsigned char *) file_addr) + ehdr64->e_phoff);
        !           147:        int i;
        !           148:        /* loop e_phnum times */
        !           149:        for (i = 0; i <= ehdr64->e_phnum; i++) {
        !           150:                /* PT_LOAD ? */
        !           151:                if (phdr64->p_type == 1) {
        !           152:                        /* copy segment */
        !           153:                        load_segment64(file_addr, phdr64);
        !           154:                }
        !           155:                /* step to next header */
        !           156:                phdr64 =
        !           157:                    (struct phdr64 *) (((unsigned char *) phdr64) +
        !           158:                                       ehdr64->e_phentsize);
        !           159:        }
        !           160:        return ehdr64->e_entry;
        !           161: }
        !           162: 
        !           163: #if __BYTE_ORDER == __BIG_ENDIAN
        !           164: #define cpu_to_be32(x)  (x)
        !           165: #else
        !           166: #define cpu_to_be32(x)  bswap_32(x)
        !           167: #endif
        !           168: 
        !           169: /**
        !           170:  * elf_check_file tests if the file at file_addr is
        !           171:  * a correct endian, ELF PPC executable
        !           172:  * @param file_addr  pointer to the start of the ELF file
        !           173:  * @return           the class (1 for 32 bit, 2 for 64 bit)
        !           174:  *                   -1 if it is not an ELF file
        !           175:  *                   -2 if it has the wrong endianess
        !           176:  *                   -3 if it is not an ELF executable
        !           177:  *                   -4 if it is not for PPC
        !           178:  */
        !           179: static int
        !           180: elf_check_file(unsigned long *file_addr)
        !           181: {
        !           182:        struct ehdr *ehdr = (struct ehdr *) file_addr;
        !           183:        /* check if it is an ELF image at all */
        !           184:        if (cpu_to_be32(ehdr->ei_ident) != 0x7f454c46)
        !           185:                return -1;
        !           186: 
        !           187:        /* endian check */
        !           188: #if __BYTE_ORDER == __BIG_ENDIAN
        !           189:        if (ehdr->ei_data != 2)
        !           190:                /* not a big endian image */
        !           191: #else
        !           192:        if (ehdr->ei_data == 2)
        !           193:                /* not a little endian image */
        !           194: #endif
        !           195:                return -2;
        !           196: 
        !           197:        /* check if it is an ELF executable */
        !           198:        if (ehdr->e_type != 2)
        !           199:                return -3;
        !           200: 
        !           201:        /* check if it is a PPC ELF executable */
        !           202:        if (ehdr->e_machine != 0x14 && ehdr->e_machine != 0x15)
        !           203:                return -4;
        !           204: 
        !           205:        return ehdr->ei_class;
        !           206: }
        !           207: 
        !           208: /**
        !           209:  * load_elf_file tries to load the ELF file specified in file_addr
        !           210:  *
        !           211:  * it first checks if the file is a PPC ELF executable and then loads
        !           212:  * the segments depending if it is a 64bit or 32 bit ELF file
        !           213:  *
        !           214:  * @param file_addr  pointer to the start of the elf file
        !           215:  * @param entry      pointer where the ELF loader will store
        !           216:  *                   the entry point
        !           217:  * @return           1 for a 32 bit file
        !           218:  *                   2 for a 64 bit file
        !           219:  *                   anything else means an error during load
        !           220:  */
        !           221: int
        !           222: load_elf_file(unsigned long *file_addr, unsigned long *entry)
        !           223: {
        !           224:        int type = elf_check_file(file_addr);
        !           225:        switch (type) {
        !           226:        case 1:
        !           227:                *entry = load_segments(file_addr);
        !           228:                break;
        !           229:        case 2:
        !           230:                *entry = load_segments64(file_addr);
        !           231:                break;
        !           232:        }
        !           233:        return type;
        !           234: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.