|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.