1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - ELF Loader
3   File:     elf.c
4 
5   Copyright 2006-2008 Nintendo. All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law. They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Date:: 2008-09-18#$
14   $Rev: 8573 $
15   $Author: okubata_ryoma $
16  *---------------------------------------------------------------------------*/
17 #include <string.h>
18 
19 #include "types.h"
20 
21 #include "elf.h"
22 #include "stdio.h"
23 #include "stdlib.h"
24 
25 static int endian;
26 //static BOOL load_strndx_done = FALSE;
27 
28 
29 #if 0
30 /*---------------------------------------------------------
31  Read byte data
32  --------------------------------------------------------*/
33 static u8 *load_elf32_byte(u8 *dest, u8 *org, int lsb)
34 {
35   u8 *temp_ptr;
36 
37   temp_ptr = (u8 *)org;
38   *dest = *temp_ptr;
39   temp_ptr++;
40 
41   return temp_ptr;
42 }
43 #endif
44 
45 /*---------------------------------------------------------
46  Read half-word data
47  --------------------------------------------------------*/
load_elf32_half(Elf32_Half * dest,u8 * org,int lsb)48 static u8 *load_elf32_half(Elf32_Half *dest, u8 *org, int lsb)
49 {
50   u8 *temp_ptr;
51 
52   temp_ptr = (u8 *)org;
53   if( lsb == ELFDATA2LSB ) {
54     *dest = (u16)((u16)(*temp_ptr) & 0x00ff);
55     temp_ptr++;
56     *dest |= ((u16)(*temp_ptr) << 8 ) & 0xff00;
57     temp_ptr++;
58   }
59   else /* ELFDATA2MSB*/ {
60     *dest = (u16)(((u16)(*temp_ptr) << 8 ) & 0xff00);
61     temp_ptr++;
62     *dest |= ((u16)(*temp_ptr) & 0x00ff);
63     temp_ptr++;
64   }
65   return (void *)temp_ptr;
66 }
67 
68 #if 0
69 /*---------------------------------------------------------
70  Read word data
71  --------------------------------------------------------*/
72 static u8 *load_elf32_sword(Elf32_Sword *dest, u8 *org, int lsb)
73 {
74   u8 *temp_ptr;
75   u32 temp;
76 
77   temp_ptr = (u8 *)org;
78   if( lsb == ELFDATA2LSB ) {
79     temp = ((u32)(*temp_ptr) & 0x000000ff);
80     temp_ptr++;
81     temp |= (((u32)(*temp_ptr) << 8 ) & 0x0000ff00);
82     temp_ptr++;
83     temp |= (((u32)(*temp_ptr) << 16 ) & 0x00ff0000);
84     temp_ptr++;
85     temp |= (((u32)(*temp_ptr) << 24 ) & 0xff000000);
86     temp_ptr++;
87   }
88   else /* ELFDATA2MSB*/ {
89     temp = (((u32)(*temp_ptr) << 24 ) & 0xff000000);
90     temp_ptr++;
91     temp |= (((u32)(*temp_ptr) << 16 ) & 0x00ff0000);
92     temp_ptr++;
93     temp |= (((u32)(*temp_ptr) << 8 ) & 0x0000ff00);
94     temp_ptr++;
95     temp |= ((u32)(*temp_ptr) & 0x000000ff);
96     temp_ptr++;
97   }
98   *dest = *( (Elf32_Sword *)&temp );
99   return (void *)temp_ptr;
100 }
101 
102 
103 static u8 *load_elf32_word(Elf32_Word *dest, u8 *org, int lsb)
104 {
105   u8 *temp_ptr;
106   temp_ptr = (u8 *)org;
107   if( lsb == ELFDATA2LSB ) {
108     *dest = ((u32)(*temp_ptr) & 0x000000ff);
109     temp_ptr++;
110     *dest |= (((u32)(*temp_ptr) << 8 ) & 0x0000ff00);
111     temp_ptr++;
112     *dest |= (((u32)(*temp_ptr) << 16 ) & 0x00ff0000);
113     temp_ptr++;
114     *dest |= (((u32)(*temp_ptr) << 24 ) & 0xff000000);
115     temp_ptr++;
116   }
117   else /* ELFDATA2MSB*/ {
118     *dest = (((u32)(*temp_ptr) << 24 ) & 0xff000000);
119     temp_ptr++;
120     *dest |= (((u32)(*temp_ptr) << 16 ) & 0x00ff0000);
121     temp_ptr++;
122     *dest |= (((u32)(*temp_ptr) << 8 ) & 0x0000ff00);
123     temp_ptr++;
124     *dest |= ((u32)(*temp_ptr) & 0x000000ff);
125     temp_ptr++;
126   }
127   return (void *)temp_ptr;
128 }
129 #endif
130 
131 /*---------------------------------------------------------
132  Read ELF header
133 
134     buf: Address of ELF header
135     ehdr: Buffer for writing read data
136  --------------------------------------------------------*/
ELF_LoadELFHeader(const void * buf,Elf32_Ehdr * ehdr)137 void *ELF_LoadELFHeader(const void *buf, Elf32_Ehdr *ehdr)
138 {
139 	u8 *file_ptr;
140 
141 	if( !buf ) {
142 		return NULL;
143 	}
144 
145 	file_ptr = (u8 *)buf;
146 
147 	/* Copy to buffer */
148     //MI_CpuCopy8( (void*)file_ptr, ehdr->e_ident, EI_NIDENT);
149     memcpy( (void*)(ehdr->e_ident), (void*)file_ptr, EI_NIDENT);
150 	file_ptr += EI_NIDENT;
151 
152 	/* Magic Number*/
153     if( ehdr->e_ident[EI_MAG0] != ELFMAG0 ) {
154     	return NULL;
155     }
156     if( ehdr->e_ident[EI_MAG1] != ELFMAG1 ) {
157     	return NULL;
158     }
159     if( ehdr->e_ident[EI_MAG2] != ELFMAG2 ) {
160     	return NULL;
161     }
162     if( ehdr->e_ident[EI_MAG3] != ELFMAG3 ) {
163     	return NULL;
164     }
165 
166 	/* CLASS*/
167 	switch( ehdr->e_ident[EI_CLASS] ) {
168       case ELFCLASSNONE:
169 		break;
170       case ELFCLASS32:
171 		break;
172       case ELFCLASS64:
173 		break;
174       default:
175 		break;
176     }
177 
178 	/* DATA*/
179 	switch( ehdr->e_ident[EI_DATA] ) {
180       case ELFDATANONE:
181 		break;
182       case ELFDATA2LSB:
183 		endian = ELFDATA2LSB;
184 		break;
185       case ELFDATA2MSB:
186 		endian = ELFDATA2MSB;
187 		break;
188       default:
189 		break;
190     }
191 
192     /* TYPE*/
193 	file_ptr = load_elf32_half(&(ehdr->e_type), file_ptr, endian);
194 	switch( ehdr->e_type ) {
195       case ET_NONE:
196 	    break;
197       case ET_REL:
198 		break;
199       case ET_EXEC:
200 		break;
201       case ET_DYN:
202 		break;
203       case ET_CORE:
204 		break;
205       case ET_LOPROC:
206 		break;
207       case ET_HIPROC:
208 		break;
209       default:
210 		break;
211     }
212 
213     /*---------- ELF Header Display  ----------*/
214 /*    printf( "\nELF Header:\n");
215 	file_ptr = load_elf32_half(&(ehdr->e_machine), file_ptr, endian);
216 	printf("e_machine = %d\n",ehdr->e_machine);
217 
218 	file_ptr = load_elf32_word(&(ehdr->e_version), file_ptr, endian);
219 	printf("e_version = %d\n",ehdr->e_version);
220 
221 	file_ptr = load_elf32_word(&(ehdr->e_entry), file_ptr, endian);
222 	printf("e_entry(entry point) = 0x%08x\n",ehdr->e_entry);
223 
224 	file_ptr = load_elf32_word(&(ehdr->e_phoff), file_ptr, endian);
225 	printf("e_phoff(program header offset) = 0x%08x\n",ehdr->e_phoff);
226 
227 	file_ptr = load_elf32_word(&(ehdr->e_shoff), file_ptr, endian);
228 	printf("e_shoff(section header offset) = 0x%08x\n",ehdr->e_shoff);
229 
230 	file_ptr = load_elf32_word(&(ehdr->e_flags), file_ptr, endian);
231 	printf("e_flags = 0x%08x\n",ehdr->e_flags);
232 	if( ehdr->e_flags & EF_ARM_HASENTRY ) {
233 		printf("has entry\n");
234 	}
235 	if( ehdr->e_flags & EF_ARM_SYMSARESORTED ) {
236 	    printf("symbols are sorted\n");
237 	}
238 	if( ehdr->e_flags & EF_ARM_DYNSYMSUSESEGIDX ) {
239 		printf("dynamic symbols use segmnet index\n");
240 	}
241 	if( ehdr->e_flags & EF_ARM_MAPSYMSFIRST ) {
242 		printf("map symbols first\n");
243 	}
244 	printf("EABI version %x \n", (ehdr->e_flags & EF_ARM_EABIMASK) >> 24 );
245 
246 
247 	file_ptr = load_elf32_half(&(ehdr->e_ehsize), file_ptr, endian);
248 	printf("e_ehsize = %d\n",ehdr->e_ehsize);
249 
250 	file_ptr = load_elf32_half(&(ehdr->e_phentsize), file_ptr, endian);
251 	printf("e_phentsize = %d\n",ehdr->e_phentsize);
252 
253 	file_ptr = load_elf32_half(&(ehdr->e_phnum), file_ptr, endian);
254 	printf("e_phnum = %d\n",ehdr->e_phnum);
255 
256 	file_ptr = load_elf32_half(&(ehdr->e_shentsize), file_ptr, endian);
257 	printf("e_shentsize = %d\n",ehdr->e_shentsize);
258 
259 	file_ptr = load_elf32_half(&(ehdr->e_shnum), file_ptr, endian);
260 	printf("e_shnum = %d\n",ehdr->e_shnum);
261 
262 	file_ptr = load_elf32_half(&(ehdr->e_shstrndx), file_ptr, endian);
263 	printf("e_shstrndx(section index no. of the section header string table section = %d\n",ehdr->e_shstrndx);
264 	printf("\n");*/
265     /*-----------------------------------*/
266 
267 	return file_ptr;
268 }
269 
270 
271 #if 0
272 /*---------------------------------------------------------
273  Relocation Entry Load
274  --------------------------------------------------------*/
275 static void *ELF_LoadRel(const void *buf, Elf32_Rel *rel)
276 {
277 	u8 *file_ptr;
278 
279 	if( !buf ) {
280 	    return NULL;
281 	}
282 
283 	file_ptr = (u8 *)buf;
284 	file_ptr = load_elf32_word(&(rel->r_offset), file_ptr, endian);
285 	file_ptr = load_elf32_word(&(rel->r_info), file_ptr, endian);
286 
287 	return file_ptr;
288 }
289 
290 static void *ELF_LoadRela(const void *buf, Elf32_Rela *rela)
291 {
292 	u8 *file_ptr;
293 
294 	if( !buf ) {
295 	    return NULL;
296 	}
297 
298 	file_ptr = (u8 *)buf;
299 	file_ptr = load_elf32_word(&(rela->r_offset), file_ptr, endian);
300 	file_ptr = load_elf32_word(&(rela->r_info), file_ptr, endian);
301 	file_ptr = load_elf32_sword(&(rela->r_addend), file_ptr, endian);
302 
303 	return file_ptr;
304 }
305 
306 
307 /*---------------------------------------------------------
308  Symbol Table Entry Load
309     buf: Pointer to buffer to load the symbol entry
310     sym: Header address of load source symbol entry
311  --------------------------------------------------------*/
312 static void *ELF_LoadSymbol(const void *buf, Elf32_Sym *sym)
313 {
314 	u8 *file_ptr;
315 
316 	if( !buf ) {
317 		return NULL;
318 	}
319 
320 	file_ptr = (u8 *)buf;
321 	file_ptr = load_elf32_word(&(sym->st_name), file_ptr, endian);
322 	file_ptr = load_elf32_word(&(sym->st_value), file_ptr, endian);
323 	file_ptr = load_elf32_word(&(sym->st_size), file_ptr, endian);
324 	file_ptr = load_elf32_byte(&(sym->st_info), file_ptr, endian);
325 	file_ptr = load_elf32_byte(&(sym->st_other), file_ptr, endian);
326 	file_ptr = load_elf32_half(&(sym->st_shndx), file_ptr, endian);
327 
328 	return file_ptr;
329 }
330 
331 
332 /*---------------------------------------------------------
333  Section Header Load
334     buf: Pointer to buffer to load the section header
335     shdr: Header address of load source section header
336  --------------------------------------------------------*/
337 static void *ELF_LoadSectionHeader(const void *buf,Elf32_Shdr *shdr)
338 {
339 	u8 *file_ptr;
340 
341 	if( !buf ) {
342 	    return NULL;
343 	}
344 
345 	file_ptr = (u8 *)buf;
346 	file_ptr = load_elf32_word(&(shdr->sh_name), file_ptr, endian);
347 	file_ptr = load_elf32_word(&(shdr->sh_type), file_ptr, endian);
348 	file_ptr = load_elf32_word(&(shdr->sh_flags), file_ptr, endian);
349 	file_ptr = load_elf32_word(&(shdr->sh_addr), file_ptr, endian);
350 	file_ptr = load_elf32_word(&(shdr->sh_offset), file_ptr, endian);
351 	file_ptr = load_elf32_word(&(shdr->sh_size), file_ptr, endian);
352 	file_ptr = load_elf32_word(&(shdr->sh_link), file_ptr, endian);
353 	file_ptr = load_elf32_word(&(shdr->sh_info), file_ptr, endian);
354 	file_ptr = load_elf32_word(&(shdr->sh_addralign), file_ptr, endian);
355 	file_ptr = load_elf32_word(&(shdr->sh_entsize ), file_ptr, endian);
356 
357 	return file_ptr;
358 }
359 #endif
360