|
|
1.1 root 1: /****************************************************************************** 1.1.1.2 ! root 2: * Copyright (c) 2004, 2011 IBM Corporation 1.1 root 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: 1.1.1.2 ! root 13: /* ! 14: * ELF loader ! 15: */ 1.1 root 16: 17: #include <string.h> 1.1.1.2 ! root 18: #include <cache.h> 1.1 root 19: #include <libelf.h> 1.1.1.2 ! root 20: #include <byteorder.h> 1.1 root 21: 22: /** 23: * elf_check_file tests if the file at file_addr is 24: * a correct endian, ELF PPC executable 25: * @param file_addr pointer to the start of the ELF file 26: * @return the class (1 for 32 bit, 2 for 64 bit) 27: * -1 if it is not an ELF file 28: * -2 if it has the wrong endianess 29: * -3 if it is not an ELF executable 30: * -4 if it is not for PPC 31: */ 32: static int 33: elf_check_file(unsigned long *file_addr) 34: { 35: struct ehdr *ehdr = (struct ehdr *) file_addr; 36: /* check if it is an ELF image at all */ 37: if (cpu_to_be32(ehdr->ei_ident) != 0x7f454c46) 38: return -1; 39: 40: /* endian check */ 1.1.1.2 ! root 41: #ifdef __BIG_ENDIAN__ 1.1 root 42: if (ehdr->ei_data != 2) 43: /* not a big endian image */ 44: #else 45: if (ehdr->ei_data == 2) 46: /* not a little endian image */ 47: #endif 48: return -2; 49: 1.1.1.2 ! root 50: /* check if it is an ELF executable ... and also ! 51: * allow DYN files, since this is specified by ePAPR */ ! 52: if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) 1.1 root 53: return -3; 54: 55: /* check if it is a PPC ELF executable */ 56: if (ehdr->e_machine != 0x14 && ehdr->e_machine != 0x15) 57: return -4; 58: 59: return ehdr->ei_class; 60: } 61: 62: /** 63: * load_elf_file tries to load the ELF file specified in file_addr 64: * 65: * it first checks if the file is a PPC ELF executable and then loads 66: * the segments depending if it is a 64bit or 32 bit ELF file 67: * 68: * @param file_addr pointer to the start of the elf file 69: * @param entry pointer where the ELF loader will store 70: * the entry point 1.1.1.2 ! root 71: * @param pre_load handler that is called before copying a segment ! 72: * @param post_load handler that is called after copying a segment 1.1 root 73: * @return 1 for a 32 bit file 74: * 2 for a 64 bit file 75: * anything else means an error during load 76: */ 77: int 1.1.1.2 ! root 78: elf_load_file(void *file_addr, unsigned long *entry, ! 79: int (*pre_load)(void*, long), ! 80: void (*post_load)(void*, long)) 1.1 root 81: { 82: int type = elf_check_file(file_addr); 1.1.1.2 ! root 83: ! 84: switch (type) { ! 85: case 1: ! 86: *entry = elf_load_segments32(file_addr, 0, pre_load, post_load); ! 87: break; ! 88: case 2: ! 89: *entry = elf_load_segments64(file_addr, 0, pre_load, post_load); ! 90: break; ! 91: } ! 92: ! 93: return type; ! 94: } ! 95: ! 96: ! 97: /** ! 98: * load_elf_file_to_addr loads an ELF file to given address. ! 99: * This is useful for 64-bit vmlinux images that use the virtual entry ! 100: * point address in their headers, and thereby need a special treatment. ! 101: * ! 102: * @param file_addr pointer to the start of the elf file ! 103: * @param entry pointer where the ELF loader will store ! 104: * the entry point ! 105: * @param pre_load handler that is called before copying a segment ! 106: * @param post_load handler that is called after copying a segment ! 107: * @return 1 for a 32 bit file ! 108: * 2 for a 64 bit file ! 109: * anything else means an error during load ! 110: */ ! 111: int ! 112: elf_load_file_to_addr(void *file_addr, void *addr, unsigned long *entry, ! 113: int (*pre_load)(void*, long), ! 114: void (*post_load)(void*, long)) ! 115: { ! 116: int type; ! 117: long offset; ! 118: ! 119: type = elf_check_file(file_addr); ! 120: 1.1 root 121: switch (type) { 122: case 1: 1.1.1.2 ! root 123: /* Parse 32-bit image */ ! 124: offset = (long)addr - elf_get_base_addr32(file_addr); ! 125: *entry = elf_load_segments32(file_addr, offset, pre_load, ! 126: post_load) + offset; ! 127: // TODO: elf_relocate32(...) 1.1 root 128: break; 129: case 2: 1.1.1.2 ! root 130: /* Parse 64-bit image */ ! 131: offset = (long)addr - elf_get_base_addr64(file_addr); ! 132: *entry = elf_load_segments64(file_addr, offset, pre_load, ! 133: post_load) + offset; ! 134: elf_relocate64(file_addr, offset); 1.1 root 135: break; 136: } 1.1.1.2 ! root 137: 1.1 root 138: return type; 139: } 1.1.1.2 ! root 140: ! 141: ! 142: /** ! 143: * Get the base load address of the ELF image ! 144: * @return The base address or -1 for error ! 145: */ ! 146: long ! 147: elf_get_base_addr(void *file_addr) ! 148: { ! 149: int type; ! 150: ! 151: type = elf_check_file(file_addr); ! 152: ! 153: switch (type) { ! 154: case 1: ! 155: /* Return 32-bit image base address */ ! 156: return elf_get_base_addr32(file_addr); ! 157: break; ! 158: case 2: ! 159: /* Return 64-bit image base address */ ! 160: return elf_get_base_addr64(file_addr); ! 161: break; ! 162: } ! 163: ! 164: return -1; ! 165: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.