1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - ELF Loader
3   File:     el.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-12-15#$
14   $Rev: 9650 $
15   $Author: kitase_hirotake $
16  *---------------------------------------------------------------------------*/
17 
18 #include "el_config.h"
19 
20 #include <twl/el.h>
21 
22 
23 #include "elf.h"
24 #include "arch.h"
25 #include "elf_loader.h"
26 #include "loader_subset.h"
27 
28 
29 /*------------------------------------------------------
30   External Variables
31  -----------------------------------------------------*/
32 extern ELAlloc     i_elAlloc;
33 extern ELFree      i_elFree;
34 
35 
36 /*------------------------------------------------------
37   External Functions
38  -----------------------------------------------------*/
39 extern BOOL elRemoveObjEntry( ELObject** StartEnt, ELObject* ObjEnt);
40 
41 
42 /*------------------------------------------------------
43   Global Variables
44  -----------------------------------------------------*/
45 ELDesc* i_eldesc     = NULL;    // for Link
46 ELDesc* i_eldesc_sim = NULL;    // for simulation link
47 
48 
49 /*---------------------------------------------------------------------------*
50   Name:         EL_Init
51 
52   Description:  Initialize the dynamic link system
53 
54   Arguments:    alloc    Heap getting function
55                 free     Heap deallocation function
56 
57   Returns:      0 if successful; -1 if failed
58  *---------------------------------------------------------------------------*/
EL_Init(ELAlloc alloc,ELFree free)59 s32 EL_Init( ELAlloc alloc, ELFree free)
60 {
61     if( i_eldesc != NULL) {
62         return( -1);    //Initialized
63     }
64 
65     ELi_Init( alloc, free);
66 
67     i_eldesc = ELi_Malloc( NULL, NULL, ((sizeof( ELDesc))*2)); //for link and simulation-link
68     if( i_eldesc == NULL) {
69         return( -1);
70     }
71 
72     (void)ELi_InitDesc( i_eldesc);
73     i_eldesc_sim = &(i_eldesc[1]);
74     (void)ELi_InitDesc( i_eldesc_sim);
75 
76     return( 0);
77 }
78 
79 #if 1
80 /*---------------------------------------------------------------------------*
81   Name:         EL_CalcEnoughBufferSizeforLink*
82 
83   Description:  Returns an buffer size sufficient to test and relocate the dynamic link.
84                 Return a slightly larger size when the dynamic object is referencing externally.
85 
86 
87   Arguments:    FilePath    Path name of the dynamic object
88                 buf         Buffer address for the relocating destination (writing is not actually performed)
89                 readfunc	Read function prepared by the application
90                 len         Size of the dynamic object
91                 obj_image   Address on the memory where the dynamic object exists
92                 obj_len    Size of the dynamic object
93                 link_mode   Mode for testing dynamic links
94 
95   Returns:      Buffer size when successful; -1 if failed
96  *---------------------------------------------------------------------------*/
EL_CalcEnoughBufferSizeforLinkFile(const char * FilePath,const void * buf,ELLinkMode link_mode)97 s32 EL_CalcEnoughBufferSizeforLinkFile( const char* FilePath, const void* buf, ELLinkMode link_mode)
98 {
99     ELDlld dlld;
100     u32    size;
101 
102     if( link_mode != EL_LINKMODE_ONESHOT) {
103         return( -1);
104     }
105     dlld = EL_LoadLibraryfromFile( i_eldesc_sim, FilePath, (void*)buf);
106     if( dlld) {
107         if( ELi_ResolveAllLibrary( i_eldesc_sim) != EL_PROC_RELOCATED) {
108             return( -1);
109         }
110         size = ((ELObject*)dlld)->lib_size; //Veneer-included size because after ELi_ResolveAllLibrary
111 
112         (void)ELi_Unlink( i_eldesc, dlld);
113         (void)elRemoveObjEntry( &(i_eldesc_sim->ELObjectStart), (ELObject*)dlld);
114         return( (s32)size);
115     }
116     return( -1);
117 }
118 
119 /*------------------------------------------------------*/
EL_CalcEnoughBufferSizeforLink(ELReadImage readfunc,u32 len,const void * buf,ELLinkMode link_mode)120 s32 EL_CalcEnoughBufferSizeforLink( ELReadImage readfunc, u32 len, const void* buf, ELLinkMode link_mode)
121 {
122     ELDlld dlld;
123     u32    size;
124 
125     if( link_mode != EL_LINKMODE_ONESHOT) {
126         return( -1);
127     }
128     dlld = EL_LoadLibrary( i_eldesc_sim, readfunc, len, (void*)buf);
129     if( dlld) {
130         if( ELi_ResolveAllLibrary( i_eldesc_sim) != EL_PROC_RELOCATED) {
131             return( -1);
132         }
133         size = ((ELObject*)dlld)->lib_size; //Veneer-included size because after ELi_ResolveAllLibrary
134 
135         (void)ELi_Unlink( i_eldesc, dlld);
136         (void)elRemoveObjEntry( &(i_eldesc_sim->ELObjectStart), (ELObject*)dlld);
137         return( (s32)size);
138     }
139     return( -1);
140 }
141 
142 /*------------------------------------------------------*/
EL_CalcEnoughBufferSizeforLinkImage(void * obj_image,u32 obj_len,const void * buf,ELLinkMode link_mode)143 s32 EL_CalcEnoughBufferSizeforLinkImage( void* obj_image, u32 obj_len, const void* buf, ELLinkMode link_mode)
144 {
145     ELDlld dlld;
146     u32    size;
147 
148     if( link_mode != EL_LINKMODE_ONESHOT) {
149         return( -1);
150     }
151     dlld = EL_LoadLibraryfromMem( i_eldesc_sim, obj_image, obj_len, (void*)buf);
152     if( dlld) {
153         if( ELi_ResolveAllLibrary( i_eldesc_sim) != EL_PROC_RELOCATED) {
154             return( -1);
155         }
156         size = ((ELObject*)dlld)->lib_size; //Veneer-included size because after ELi_ResolveAllLibrary
157 
158         (void)ELi_Unlink( i_eldesc, dlld);
159         (void)elRemoveObjEntry( &(i_eldesc_sim->ELObjectStart), (ELObject*)dlld);
160         return( (s32)size);
161     }
162     return( -1);
163 }
164 #endif
165 
166 
167 /*---------------------------------------------------------------------------*
168   Name:         EL_Link*
169 
170   Description:  Relocates dynamic objects (files/user API/from memory)
171 
172   Arguments:    FilePath    Path name of the dynamic object
173                 readfunc	Read function prepared by the application
174                 len         Size of the dynamic object
175                 obj_image   Address on the memory where the dynamic object exists
176                 obj_len    Size of the dynamic object
177                 buf         Buffer address for the relocation destination
178 
179   Returns:      Dynamic module hande when successful, 0 if failed
180  *---------------------------------------------------------------------------*/
EL_LinkFile(const char * FilePath,void * buf)181 ELDlld EL_LinkFile( const char* FilePath, void* buf)
182 {
183     return( EL_LoadLibraryfromFile( i_eldesc, FilePath, buf));
184 }
185 
186 /*------------------------------------------------------*/
EL_Link(ELReadImage readfunc,u32 len,void * buf)187 ELDlld EL_Link( ELReadImage readfunc, u32 len, void* buf)
188 {
189     return( EL_LoadLibrary( i_eldesc, readfunc, len, buf));
190 }
191 
192 /*------------------------------------------------------*/
EL_LinkImage(void * obj_image,u32 obj_len,void * buf)193 ELDlld EL_LinkImage( void* obj_image, u32 obj_len, void* buf)
194 {
195     return( EL_LoadLibraryfromMem( i_eldesc, obj_image, obj_len, buf));
196 }
197 
198 
199 /*---------------------------------------------------------------------------*
200   Name:         EL_ResolveAll
201 
202   Description:  Resolves unresolved symbols
203 
204   Arguments:    None.
205 
206   Returns:      EL_RELOCATED when successful, EL_FAILED if failed
207  *---------------------------------------------------------------------------*/
EL_ResolveAll(void)208 u16 EL_ResolveAll( void)
209 {
210     if( ELi_ResolveAllLibrary( i_eldesc) == EL_PROC_RELOCATED) {
211         return( EL_RELOCATED);
212     }
213     return( EL_FAILED);
214 }
215 
216 
217 /*---------------------------------------------------------------------------*
218   Name:         EL_Export
219 
220   Description:  Registers symbol information to the DLL system
221 
222   Arguments:    None.
223 
224   Returns:      If successful, TRUE.
225  *---------------------------------------------------------------------------*/
EL_Export(ELAdrEntry * AdrEnt)226 BOOL EL_Export( ELAdrEntry* AdrEnt)
227 {
228     /* (TODO) Do not apply to simulation because not added to i_eldesc_sim */
229     return ELi_Export( i_eldesc, AdrEnt);
230 }
231 
232 
233 /*---------------------------------------------------------------------------*
234   Name:         EL_GetGlobalAdr
235 
236   Description:  Searches a symbol from the dynamic module and returns the address
237 
238   Arguments:    my_dlld     Handle of dynamic module targeted for the search
239                 ent_name    Symbol name
240 
241   Returns:      Address of symbol when successful, 0 if failed
242  *---------------------------------------------------------------------------*/
EL_GetGlobalAdr(ELDlld my_dlld,const char * ent_name)243 void* EL_GetGlobalAdr( ELDlld my_dlld, const char* ent_name)
244 {
245     return( ELi_GetGlobalAdr( i_eldesc, my_dlld, ent_name));
246 }
247 
248 
249 /*---------------------------------------------------------------------------*
250   Name:         EL_Unlink
251 
252   Description:  Unlinks the dynamic module.
253 
254   Arguments:    my_dlld     Handle of dynamic module to unlink
255 
256   Returns:      EL_SUCCESS when successful, EL_FAILED if failed
257  *---------------------------------------------------------------------------*/
EL_Unlink(ELDlld my_dlld)258 u16 EL_Unlink( ELDlld my_dlld)
259 {
260     if( ELi_Unlink( i_eldesc, my_dlld) == TRUE) {
261         /* ReLink not possible because corresponding object structure is destroyed */
262         (void)elRemoveObjEntry( &(i_eldesc->ELObjectStart), (ELObject*)my_dlld); // No problem if it fails
263         return( EL_SUCCESS);
264     }
265     return( EL_FAILED);
266 }
267 
268 
269 /*---------------------------------------------------------------------------*
270   Name:         EL_GetResultCode
271 
272   Description:  Returns detailed results of final processes
273 
274   Arguments:    None.
275 
276   Returns:      Error code of type ELResult
277  *---------------------------------------------------------------------------*/
EL_GetResultCode(void)278 ELResult EL_GetResultCode( void)
279 {
280     if( i_eldesc == NULL) {
281         return( EL_RESULT_FAILURE);
282     }
283     return( (ELResult)(i_eldesc->result));
284 }
285 
286 #if 0
287 ELResult EL_GetResultCode( ELDlld my_dlld)
288 {
289     ELObject*      MYObject;
290 
291     if( my_dlld == 0) {
292         return( EL_RESULT_INVALID_PARAMETER);
293     }
294 
295     // Object that references results
296     MYObject = (ELObject*)my_dlld;
297 
298     return( MYObject->result);
299 }
300 #endif
301