1 /******************************************************************************
2 * Copyright (c) 2004, 2011 IBM Corporation
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
10 * IBM Corporation - initial implementation
11 *****************************************************************************/
19 #include <byteorder.h>
55 get_phdr32(void *file_addr)
57 return (struct phdr32 *) (((unsigned char *)file_addr)
58 + ((struct ehdr32 *)file_addr)->e_phoff);
62 load_segment(void *file_addr, struct phdr32 *phdr, signed long offset,
63 int (*pre_load)(void*, long),
64 void (*post_load)(void*, long))
66 unsigned long src = phdr->p_offset + (unsigned long) file_addr;
67 unsigned long destaddr;
69 destaddr = (unsigned long)phdr->p_paddr;
70 destaddr = destaddr + offset;
72 /* check if we're allowed to copy */
73 if (pre_load != NULL) {
74 if (pre_load((void*)destaddr, phdr->p_memsz) != 0)
78 /* copy into storage */
79 memmove((void *)destaddr, (void *)src, phdr->p_filesz);
82 memset((void *)(destaddr + phdr->p_filesz), 0,
83 phdr->p_memsz - phdr->p_filesz);
85 if (phdr->p_memsz && post_load) {
86 post_load((void*)destaddr, phdr->p_memsz);
91 elf_load_segments32(void *file_addr, signed long offset,
92 int (*pre_load)(void*, long),
93 void (*post_load)(void*, long))
95 struct ehdr32 *ehdr = (struct ehdr32 *) file_addr;
96 /* Calculate program header address */
97 struct phdr32 *phdr = get_phdr32(file_addr);
100 /* loop e_phnum times */
101 for (i = 0; i <= ehdr->e_phnum; i++) {
103 if (phdr->p_type == 1) {
104 if (phdr->p_paddr != phdr->p_vaddr) {
105 printf("ELF32: VirtAddr(%lx) != PhysAddr(%lx) not supported, aborting\n",
106 (long)phdr->p_vaddr, (long)phdr->p_paddr);
111 load_segment(file_addr, phdr, offset, pre_load,
114 /* step to next header */
115 phdr = (struct phdr32 *)(((uint8_t *)phdr) + ehdr->e_phentsize);
118 /* Entry point is always a virtual address, so translate it
119 * to physical before returning it */
120 return ehdr->e_entry;
124 * Return the base address for loading (i.e. the address of the first PT_LOAD
126 * @param file_addr pointer to the ELF file in memory
127 * @return the base address
130 elf_get_base_addr32(void *file_addr)
132 struct ehdr32 *ehdr = (struct ehdr32 *) file_addr;
133 struct phdr32 *phdr = get_phdr32(file_addr);
136 /* loop e_phnum times */
137 for (i = 0; i <= ehdr->e_phnum; i++) {
139 if (phdr->p_type == 1) {
140 return phdr->p_paddr;
142 /* step to next header */
143 phdr = (struct phdr32 *)(((uint8_t *)phdr) + ehdr->e_phentsize);
149 uint32_t elf_get_eflags_32(void *file_addr)
151 struct ehdr32 *ehdr = (struct ehdr32 *) file_addr;
153 return ehdr->e_flags;
157 elf_byteswap_header32(void *file_addr)
159 struct ehdr32 *ehdr = (struct ehdr32 *) file_addr;
163 bswap_16p(&ehdr->e_type);
164 bswap_16p(&ehdr->e_machine);
165 bswap_32p(&ehdr->e_version);
166 bswap_32p(&ehdr->e_entry);
167 bswap_32p(&ehdr->e_phoff);
168 bswap_32p(&ehdr->e_shoff);
169 bswap_32p(&ehdr->e_flags);
170 bswap_16p(&ehdr->e_ehsize);
171 bswap_16p(&ehdr->e_phentsize);
172 bswap_16p(&ehdr->e_phnum);
173 bswap_16p(&ehdr->e_shentsize);
174 bswap_16p(&ehdr->e_shnum);
175 bswap_16p(&ehdr->e_shstrndx);
177 phdr = get_phdr32(file_addr);
179 /* loop e_phnum times */
180 for (i = 0; i <= ehdr->e_phnum; i++) {
181 bswap_32p(&phdr->p_type);
182 bswap_32p(&phdr->p_offset);
183 bswap_32p(&phdr->p_vaddr);
184 bswap_32p(&phdr->p_paddr);
185 bswap_32p(&phdr->p_filesz);
186 bswap_32p(&phdr->p_memsz);
187 bswap_32p(&phdr->p_flags);
188 bswap_32p(&phdr->p_align);
190 /* step to next header */
191 phdr = (struct phdr32 *)(((uint8_t *)phdr) + ehdr->e_phentsize);