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