1 /*
2 * dlw_client.c
3 *
4 * RIDL implementation of client functions required by dynamic loader API.
5 * Please see list of client-required API functions in dload_api.h.
6 *
7 * This implementation of RIDL is expected to run on the DSP. It uses C6x
8 * RTS functions for file I/O and memory management (both host and target
9 * memory).
10 *
11 * A loader that runs on a GPP for the purposes of loading C6x code onto a
12 * DSP will likely need to re-write all of the functions contained in this
13 * module.
14 *
15 * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
20 *
21 * Redistributions of source code must retain the above copyright
22 * notice, this list of conditions and the following disclaimer.
23 *
24 * Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in the
26 * documentation and/or other materials provided with the
27 * distribution.
28 *
29 * Neither the name of Texas Instruments Incorporated nor the names of
30 * its contributors may be used to endorse or promote products derived
31 * from this software without specific prior written permission.
32 *
33 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
34 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
35 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
36 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
37 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
38 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
39 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
40 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
41 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
42 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
43 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44 *
45 */
47 #include "types.h"
48 #include "ewrap.h"
49 #include "ArrayList.h"
50 #include "dload_api.h"
51 #include <stdarg.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include "file_ovr.h"
56 /* Eat printfs. */
57 #define printf mprintf
58 #define vprintf(x,y)
60 #if 0
61 #include "dlw_debug.h"
62 #include "dlw_dsbt.h"
63 #include "dlw_trgmem.h"
64 #endif
66 /*****************************************************************************/
67 /* Client Provided File I/O */
68 /*****************************************************************************/
69 /*****************************************************************************/
70 /* DLIF_FSEEK() - Seek to a position in specified file. */
71 /*****************************************************************************/
72 int DLIF_fseek(LOADER_FILE_DESC *stream, int32_t offset, int origin)
73 {
74 return fseek(stream, offset, origin);
75 }
77 /*****************************************************************************/
78 /* DLIF_FTELL() - Return the current position in the given file. */
79 /*****************************************************************************/
80 int32_t DLIF_ftell(LOADER_FILE_DESC *stream)
81 {
82 return ftell(stream);
83 }
85 /*****************************************************************************/
86 /* DLIF_FREAD() - Read data from file into a host-accessible data buffer */
87 /* that can be accessed through "ptr". */
88 /*****************************************************************************/
89 size_t DLIF_fread(void *ptr, size_t size, size_t nmemb,
90 LOADER_FILE_DESC *stream)
91 {
92 return fread(ptr, size, nmemb, stream);
93 }
95 /*****************************************************************************/
96 /* DLIF_FCLOSE() - Close a file that was opened on behalf of the core */
97 /* loader. Core loader has ownership of the file pointer, but client */
98 /* has access to file system. */
99 /*****************************************************************************/
100 int32_t DLIF_fclose(LOADER_FILE_DESC *fd)
101 {
102 return fclose(fd);
103 }
105 /*****************************************************************************/
106 /* Client Provided Host Memory Management */
107 /*****************************************************************************/
108 /*****************************************************************************/
109 /* DLIF_MALLOC() - Allocate host memory suitable for loader scratch space. */
110 /*****************************************************************************/
111 void* DLIF_malloc(size_t size)
112 {
113 return iblMalloc(size*sizeof(uint8_t));
114 }
116 /*****************************************************************************/
117 /* DLIF_FREE() - Free host memory previously allocated with DLIF_malloc(). */
118 /*****************************************************************************/
119 void DLIF_free(void* ptr)
120 {
121 iblFree(ptr);
122 }
124 /*****************************************************************************/
125 /* Client Provided Target Memory Management */
126 /*****************************************************************************/
128 /*****************************************************************************/
129 /* RIDL-Specific hack to facilitate target memory allocation. */
130 /*****************************************************************************/
131 /*****************************************************************************/
132 /* DLIF_ALLOCATE() - Return the load address of the segment/section */
133 /* described in its parameters and record the run address in */
134 /* run_address field of DLOAD_MEMORY_REQUEST. */
135 /*****************************************************************************/
136 BOOL DLIF_allocate(struct DLOAD_MEMORY_REQUEST *targ_req)
137 {
138 /*------------------------------------------------------------------------*/
139 /* Get pointers to API segment and file descriptors. */
140 /*------------------------------------------------------------------------*/
141 struct DLOAD_MEMORY_SEGMENT* obj_desc = targ_req->segment;
142 LOADER_FILE_DESC* f = targ_req->fp;
144 /*------------------------------------------------------------------------*/
145 /* Request target memory for this segment from the "blob". */
146 /*------------------------------------------------------------------------*/
147 if (!DLTMM_malloc(targ_req, obj_desc))
148 {
149 DLIF_error(DLET_MEMORY, "Failed to allocate target memory for segment.\n");
150 return 0;
151 }
153 /*------------------------------------------------------------------------*/
154 /* As required by API, copy the described segment into memory from file. */
155 /* We're the client, not the loader, so we can use fseek() and fread(). */
156 /*------------------------------------------------------------------------*/
157 /* ??? I don't think we want to do this if we are allocating target */
158 /* memory for the run only placement of this segment. If it is the */
159 /* load placement or both load and run placement, then we can do the */
160 /* copy. */
161 /*------------------------------------------------------------------------*/
162 if (obj_desc->objsz_in_bytes)
163 {
164 /* Do not clear uninitialized data section, so that the section can
165 be mapped to the same region IBL uses */
166 memset(targ_req->host_address, 0, obj_desc->memsz_in_bytes);
167 fseek(f,targ_req->offset,SEEK_SET);
168 fread(targ_req->host_address,obj_desc->objsz_in_bytes,1,f);
169 }
171 /*------------------------------------------------------------------------*/
172 /* Once we have target address for this allocation, add debug information */
173 /* about this segment to the debug record for the module that is */
174 /* currently being loaded. */
175 /*------------------------------------------------------------------------*/
176 if (DLL_debug)
177 {
178 /*---------------------------------------------------------------------*/
179 /* Add information about this segment's location to the segment debug */
180 /* information associated with the module that is currently being */
181 /* loaded. */
182 /*---------------------------------------------------------------------*/
183 /* ??? We need a way to determine whether the target address in the */
184 /* segment applies to the load address of the segment or the */
185 /* run address. For the time being, we assume that it applies */
186 /* to both (that is, the dynamic loader does not support */
187 /* separate load and run placement for a given segment). */
188 /*---------------------------------------------------------------------*/
189 DLDBG_add_segment_record(obj_desc);
190 }
192 #if LOADER_DEBUG
193 if (debugging_on)
194 printf("DLIF_allocate: buffer 0x%x\n", targ_req->host_address);
195 #endif
197 /*------------------------------------------------------------------------*/
198 /* Target memory request was successful. */
199 /*------------------------------------------------------------------------*/
200 return 1;
201 }
203 /*****************************************************************************/
204 /* DLIF_RELEASE() - Unmap or free target memory that was previously */
205 /* allocated by DLIF_allocate(). */
206 /*****************************************************************************/
207 BOOL DLIF_release(struct DLOAD_MEMORY_SEGMENT* ptr)
208 {
209 #if LOADER_DEBUG
210 if (debugging_on)
211 printf("DLIF_free: %d bytes starting at 0x%x\n",
212 ptr->memsz_in_bytes, ptr->target_address);
213 #endif
215 /*------------------------------------------------------------------------*/
216 /* Find the target memory packet associated with this address and mark it */
217 /* as available (will also merge with adjacent free packets). */
218 /*------------------------------------------------------------------------*/
219 DLTMM_free(ptr->target_address);
221 return 1;
222 }
224 /*****************************************************************************/
225 /* DLIF_COPY() - Copy data from file to host-accessible memory. */
226 /* Returns a host pointer to the data in the host_address field of the */
227 /* DLOAD_MEMORY_REQUEST object. */
228 /*****************************************************************************/
229 BOOL DLIF_copy(struct DLOAD_MEMORY_REQUEST* targ_req)
230 {
231 targ_req->host_address = (void*)(targ_req->segment->target_address);
232 return 1;
233 }
235 /*****************************************************************************/
236 /* DLIF_READ() - Read content from target memory address into host- */
237 /* accessible buffer. */
238 /*****************************************************************************/
239 BOOL DLIF_read(void *ptr, size_t size, size_t nmemb, TARGET_ADDRESS src)
240 {
241 if (!memcpy(ptr, (const void *)src, size * nmemb))
242 return 0;
244 return 1;
245 }
247 /*****************************************************************************/
248 /* DLIF_WRITE() - Write updated (relocated) segment contents to target */
249 /* memory. */
250 /*****************************************************************************/
251 BOOL DLIF_write(struct DLOAD_MEMORY_REQUEST* req)
252 {
253 /*------------------------------------------------------------------------*/
254 /* Nothing to do since we are relocating directly into target memory. */
255 /*------------------------------------------------------------------------*/
256 return 1;
257 }
259 /*****************************************************************************/
260 /* DLIF_EXECUTE() - Transfer control to specified target address. */
261 /*****************************************************************************/
262 int32_t DLIF_execute(TARGET_ADDRESS exec_addr)
263 {
264 /*------------------------------------------------------------------------*/
265 /* This call will only work if the host and target are the same instance. */
266 /* The compiler may warn about this conversion from an object to a */
267 /* function pointer. */
268 /*------------------------------------------------------------------------*/
269 return ((int32_t(*)())(exec_addr))();
270 }
273 #if 0
274 /*****************************************************************************/
275 /* Client Provided Communication Mechanisms to assist with creation of */
276 /* DLLView debug information. Client needs to know exactly when a segment */
277 /* is being loaded or unloaded so that it can keep its debug information */
278 /* up to date. */
279 /*****************************************************************************/
280 /*****************************************************************************/
281 /* DLIF_LOAD_DEPENDENT() - Perform whatever maintenance is needed in the */
282 /* client when loading of a dependent file is initiated by the core */
283 /* loader. Open the dependent file on behalf of the core loader, */
284 /* then invoke the core loader to get it into target memory. The core */
285 /* loader assumes ownership of the dependent file pointer and must ask */
286 /* the client to close the file when it is no longer needed. */
287 /* */
288 /* If debug support is needed under the Braveheart model, then create */
289 /* a host version of the debug module record for this object. This */
290 /* version will get updated each time we allocate target memory for a */
291 /* segment that belongs to this module. When the load returns, the */
292 /* client will allocate memory for the debug module from target memory */
293 /* and write the host version of the debug module into target memory */
294 /* at the appropriate location. After this takes place the new debug */
295 /* module needs to be added to the debug module list. The client will */
296 /* need to update the tail of the DLModules list to link the new debug */
297 /* module onto the end of the list. */
298 /* */
299 /*****************************************************************************/
300 int DLIF_load_dependent(const char* so_name)
301 {
302 /*------------------------------------------------------------------------*/
303 /* Find the path and file name associated with the given so_name in the */
304 /* client's file registry. */
305 /*------------------------------------------------------------------------*/
306 /* If we can't find the so_name in the file registry (or if the registry */
307 /* is not implemented yet), we'll open the file using the so_name. */
308 /*------------------------------------------------------------------------*/
309 int to_ret = 0;
310 FILE* fp = fopen(so_name, "rb");
312 /*------------------------------------------------------------------------*/
313 /* We need to make sure that the file was properly opened. */
314 /*------------------------------------------------------------------------*/
315 if (!fp)
316 {
317 DLIF_error(DLET_FILE, "Can't open dependent file '%s'.\n", so_name);
318 return 0;
319 }
321 /*------------------------------------------------------------------------*/
322 /* If the dynamic loader is providing debug support for a DLL View plug- */
323 /* in or script of some sort, then we are going to create a host version */
324 /* of the debug module record for the so_name module. */
325 /*------------------------------------------------------------------------*/
326 /* In the Braveheart view of the world, debug support is only to be */
327 /* provided if the DLModules symbol is defined in the base image. */
328 /* We will set up a DLL_debug flag when the command to load the base */
329 /* image is issued. */
330 /*------------------------------------------------------------------------*/
331 if (DLL_debug)
332 DLDBG_add_host_record(so_name);
334 /*------------------------------------------------------------------------*/
335 /* Tell the core loader to proceed with loading the module. */
336 /*------------------------------------------------------------------------*/
337 /* Note that the client is turning ownership of the file pointer over to */
338 /* the core loader at this point. The core loader will need to ask the */
339 /* client to close the dependent file when it is done using the dependent */
340 /* file pointer. */
341 /*------------------------------------------------------------------------*/
342 to_ret = DLOAD_load(fp, 0, NULL);
344 /*------------------------------------------------------------------------*/
345 /* If the dependent load was successful, update the DLModules list in */
346 /* target memory as needed. */
347 /*------------------------------------------------------------------------*/
348 if (to_ret != 0)
349 {
350 /*---------------------------------------------------------------------*/
351 /* We will need to copy the information from our host version of the */
352 /* debug record into actual target memory. */
353 /*---------------------------------------------------------------------*/
354 if (DLL_debug)
355 {
356 /*---------------------------------------------------------------*/
357 /* Allocate target memory for the module's debug record. Use */
358 /* host version of the debug information to determine how much */
359 /* target memory we need and how it is to be filled in. */
360 /*---------------------------------------------------------------*/
361 /* Note that we don't go through the normal API functions to get */
362 /* target memory and write the debug information since we're not */
363 /* dealing with object file content here. The DLL View debug is */
364 /* supported entirely on the client side. */
365 /*---------------------------------------------------------------*/
366 DLDBG_add_target_record(to_ret);
367 }
368 }
370 /*------------------------------------------------------------------------*/
371 /* Report failure to load dependent. */
372 /*------------------------------------------------------------------------*/
373 else
374 DLIF_error(DLET_MISC, "Failed load of dependent file '%s'.\n", so_name);
376 return to_ret;
377 }
379 #endif
381 #if 0
382 /*****************************************************************************/
383 /* DLIF_UNLOAD_DEPENDENT() - Perform whatever maintenance is needed in the */
384 /* client when unloading of a dependent file is initiated by the core */
385 /* loader. Invoke the DLOAD_unload() function to get the core loader */
386 /* to release any target memory that is associated with the dependent */
387 /* file's segments. */
388 /*****************************************************************************/
389 void DLIF_unload_dependent(uint32_t handle)
390 {
391 /*------------------------------------------------------------------------*/
392 /* If the specified module is no longer needed, DLOAD_load() will spin */
393 /* through the object descriptors associated with the module and free up */
394 /* target memory that was allocated to any segment in the module. */
395 /*------------------------------------------------------------------------*/
396 /* If DLL debugging is enabled, find module debug record associated with */
397 /* this module and remove it from the DLL debug list. */
398 /*------------------------------------------------------------------------*/
399 if (DLOAD_unload(handle))
400 {
401 DSBT_release_entry(handle);
402 if (DLL_debug) DLDBG_rm_target_record(handle);
403 }
404 }
406 #endif
408 /*****************************************************************************/
409 /* Client Provided API Functions to Support Logging Warnings/Errors */
410 /*****************************************************************************/
412 /*****************************************************************************/
413 /* DLIF_WARNING() - Write out a warning message from the core loader. */
414 /*****************************************************************************/
415 void DLIF_warning(LOADER_WARNING_TYPE wtype, const char *fmt, ...)
416 {
417 va_list ap;
418 va_start(ap,fmt);
419 printf("<< D L O A D >> WARNING: ");
420 vprintf(fmt,ap);
421 va_end(ap);
422 }
424 /*****************************************************************************/
425 /* DLIF_ERROR() - Write out an error message from the core loader. */
426 /*****************************************************************************/
427 void DLIF_error(LOADER_ERROR_TYPE etype, const char *fmt, ...)
428 {
429 va_list ap;
430 va_start(ap,fmt);
431 printf("<< D L O A D >> ERROR: ");
432 vprintf(fmt,ap);
433 va_end(ap);
434 }
436 /*****************************************************************************
437 * END API FUNCTION DEFINITIONS
438 *****************************************************************************/