1 /*
2  * dynamic_loader.h
3  *
4  * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5  *
6  * Copyright (C) 2008 Texas Instruments, Inc.
7  *
8  * This package is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  *
12  * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
13  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
14  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15  */
16 
17 #ifndef _DYNAMIC_LOADER_H_
18 #define _DYNAMIC_LOADER_H_
19 #include <linux/kernel.h>
20 #include <linux/types.h>
21 
22 /*
23  * Dynamic Loader
24  *
25  * The function of the dynamic loader is to load a "module" containing
26  * instructions for a "target" processor into that processor.  In the process
27  * it assigns memory for the module, resolves symbol references made by the
28  * module, and remembers symbols defined by the module.
29  *
30  * The dynamic loader is parameterized for a particular system by 4 classes
31  * that supply the module and system specific functions it requires
32  */
33 	/* The read functions for the module image to be loaded */
34 struct dynamic_loader_stream;
35 
36 	/* This class defines "host" symbol and support functions */
37 struct dynamic_loader_sym;
38 
39 	/* This class defines the allocator for "target" memory */
40 struct dynamic_loader_allocate;
41 
42 	/* This class defines the copy-into-target-memory functions */
43 struct dynamic_loader_initialize;
44 
45 /*
46  * Option flags to modify the behavior of module loading
47  */
48 #define DLOAD_INITBSS 0x1	/* initialize BSS sections to zero */
49 
50 /*****************************************************************************
51  * Procedure dynamic_load_module
52  *
53  * Parameters:
54  *  module  The input stream that supplies the module image
55  *  syms    Host-side symbol table and malloc/free functions
56  *  alloc   Target-side memory allocation
57  *  init    Target-side memory initialization, or NULL for symbol read only
58  *  options Option flags DLOAD_*
59  *  mhandle A module handle for use with Dynamic_Unload
60  *
61  * Effect:
62  *  The module image is read using *module.  Target storage for the new image is
63  * obtained from *alloc.  Symbols defined and referenced by the module are
64  * managed using *syms.  The image is then relocated and references resolved
65  * as necessary, and the resulting executable bits are placed into target memory
66  * using *init.
67  *
68  * Returns:
69  *  On a successful load, a module handle is placed in *mhandle, and zero is
70  * returned.  On error, the number of errors detected is returned.  Individual
71  * errors are reported during the load process using syms->error_report().
72  **************************************************************************** */
73 extern int dynamic_load_module(
74 				      /* the source for the module image */
75 				      struct dynamic_loader_stream *module,
76 				      /* host support for symbols and storage */
77 				      struct dynamic_loader_sym *syms,
78 				      /* the target memory allocator */
79 				      struct dynamic_loader_allocate *alloc,
80 				      /* the target memory initializer */
81 				      struct dynamic_loader_initialize *init,
82 				      unsigned options,	/* option flags */
83 				      /* the returned module handle */
84 				      void **mhandle);
85 
86 /*****************************************************************************
87  * Procedure dynamic_open_module
88  *
89  * Parameters:
90  *  module  The input stream that supplies the module image
91  *  syms    Host-side symbol table and malloc/free functions
92  *  alloc   Target-side memory allocation
93  *  init    Target-side memory initialization, or NULL for symbol read only
94  *  options Option flags DLOAD_*
95  *  mhandle A module handle for use with Dynamic_Unload
96  *
97  * Effect:
98  *  The module image is read using *module.  Target storage for the new image is
99  * obtained from *alloc.  Symbols defined and referenced by the module are
100  * managed using *syms.  The image is then relocated and references resolved
101  * as necessary, and the resulting executable bits are placed into target memory
102  * using *init.
103  *
104  * Returns:
105  *  On a successful load, a module handle is placed in *mhandle, and zero is
106  * returned.  On error, the number of errors detected is returned.  Individual
107  * errors are reported during the load process using syms->error_report().
108  **************************************************************************** */
109 extern int dynamic_open_module(
110 				      /* the source for the module image */
111 				      struct dynamic_loader_stream *module,
112 				      /* host support for symbols and storage */
113 				      struct dynamic_loader_sym *syms,
114 				      /* the target memory allocator */
115 				      struct dynamic_loader_allocate *alloc,
116 				      /* the target memory initializer */
117 				      struct dynamic_loader_initialize *init,
118 				      unsigned options,	/* option flags */
119 				      /* the returned module handle */
120 				      void **mhandle);
121 
122 /*****************************************************************************
123  * Procedure dynamic_unload_module
124  *
125  * Parameters:
126  *  mhandle A module handle from dynamic_load_module
127  *  syms    Host-side symbol table and malloc/free functions
128  *  alloc   Target-side memory allocation
129  *
130  * Effect:
131  *  The module specified by mhandle is unloaded.  Unloading causes all
132  * target memory to be deallocated, all symbols defined by the module to
133  * be purged, and any host-side storage used by the dynamic loader for
134  * this module to be released.
135  *
136  * Returns:
137  *  Zero for success. On error, the number of errors detected is returned.
138  * Individual errors are reported using syms->error_report().
139  **************************************************************************** */
140 extern int dynamic_unload_module(void *mhandle,	/* the module
141 							 * handle */
142 				 /* host support for symbols and
143 				  * storage */
144 				 struct dynamic_loader_sym *syms,
145 				 /* the target memory allocator */
146 				 struct dynamic_loader_allocate *alloc,
147 				 /* the target memory initializer */
148 				 struct dynamic_loader_initialize *init);
149 
150 /*****************************************************************************
151  *****************************************************************************
152  * A class used by the dynamic loader for input of the module image
153  *****************************************************************************
154  **************************************************************************** */
155 struct dynamic_loader_stream {
156 /* public: */
157     /*************************************************************************
158      * read_buffer
159      *
160      * PARAMETERS :
161      *  buffer  Pointer to the buffer to fill
162      *  bufsiz  Amount of data desired in sizeof() units
163      *
164      * EFFECT :
165      *  Reads the specified amount of data from the module input stream
166      * into the specified buffer.  Returns the amount of data read in sizeof()
167      * units (which if less than the specification, represents an error).
168      *
169      * NOTES:
170      *  In release 1 increments the file position by the number of bytes read
171      *
172      ************************************************************************ */
173 	int (*read_buffer) (struct dynamic_loader_stream *thisptr,
174 			    void *buffer, unsigned bufsiz);
175 
176     /*************************************************************************
177      * set_file_posn (release 1 only)
178      *
179      * PARAMETERS :
180      *  posn  Desired file position relative to start of file in sizeof() units.
181      *
182      * EFFECT :
183      *  Adjusts the internal state of the stream object so that the next
184      * read_buffer call will begin to read at the specified offset from
185      * the beginning of the input module.  Returns 0 for success, non-zero
186      * for failure.
187      *
188      ************************************************************************ */
189 	int (*set_file_posn) (struct dynamic_loader_stream *thisptr,
190 			      /* to be eliminated in release 2 */
191 			      unsigned int posn);
192 
193 };
194 
195 /*****************************************************************************
196  *****************************************************************************
197  * A class used by the dynamic loader for symbol table support and
198  * miscellaneous host-side functions
199  *****************************************************************************
200  **************************************************************************** */
201 
202 typedef u32 ldr_addr;
203 
204 /*
205  * the structure of a symbol known to the dynamic loader
206  */
207 struct dynload_symbol {
208 	ldr_addr value;
209 };
210 
211 struct dynamic_loader_sym {
212 /* public: */
213     /*************************************************************************
214      * find_matching_symbol
215      *
216      * PARAMETERS :
217      *  name    The name of the desired symbol
218      *
219      * EFFECT :
220      *  Locates a symbol matching the name specified.  A pointer to the
221      * symbol is returned if it exists; 0 is returned if no such symbol is
222      * found.
223      *
224      ************************************************************************ */
225 	struct dynload_symbol *(*find_matching_symbol)
226 	 (struct dynamic_loader_sym *thisptr, const char *name);
227 
228     /*************************************************************************
229      * add_to_symbol_table
230      *
231      * PARAMETERS :
232      *  nname       Pointer to the name of the new symbol
233      *  moduleid    An opaque module id assigned by the dynamic loader
234      *
235      * EFFECT :
236      *  The new symbol is added to the table.  A pointer to the symbol is
237      * returned, or NULL is returned for failure.
238      *
239      * NOTES:
240      *  It is permissible for this function to return NULL; the effect is that
241      * the named symbol will not be available to resolve references in
242      * subsequent loads.  Returning NULL will not cause the current load
243      * to fail.
244      ************************************************************************ */
245 	struct dynload_symbol *(*add_to_symbol_table)
246 	 (struct dynamic_loader_sym *
247 	  thisptr, const char *nname, unsigned moduleid);
248 
249     /*************************************************************************
250      * purge_symbol_table
251      *
252      * PARAMETERS :
253      *  moduleid    An opaque module id assigned by the dynamic loader
254      *
255      * EFFECT :
256      *  Each symbol in the symbol table whose moduleid matches the argument
257      * is removed from the table.
258      ************************************************************************ */
259 	void (*purge_symbol_table) (struct dynamic_loader_sym *thisptr,
260 				    unsigned moduleid);
261 
262     /*************************************************************************
263      * dload_allocate
264      *
265      * PARAMETERS :
266      *  memsiz  size of desired memory in sizeof() units
267      *
268      * EFFECT :
269      *  Returns a pointer to some "host" memory for use by the dynamic
270      * loader, or NULL for failure.
271      * This function is serves as a replaceable form of "malloc" to
272      * allow the user to configure the memory usage of the dynamic loader.
273      ************************************************************************ */
274 	void *(*dload_allocate) (struct dynamic_loader_sym *thisptr,
275 				 unsigned memsiz);
276 
277     /*************************************************************************
278      * dload_deallocate
279      *
280      * PARAMETERS :
281      *  memptr  pointer to previously allocated memory
282      *
283      * EFFECT :
284      *  Releases the previously allocated "host" memory.
285      ************************************************************************ */
286 	void (*dload_deallocate) (struct dynamic_loader_sym *thisptr,
287 				  void *memptr);
288 
289     /*************************************************************************
290      * error_report
291      *
292      * PARAMETERS :
293      *  errstr  pointer to an error string
294      *  args    additional arguments
295      *
296      * EFFECT :
297      *  This function provides an error reporting interface for the dynamic
298      * loader.  The error string and arguments are designed as for the
299      * library function vprintf.
300      ************************************************************************ */
301 	void (*error_report) (struct dynamic_loader_sym *thisptr,
302 			      const char *errstr, va_list args);
303 
304 };				/* class dynamic_loader_sym */
305 
306 /*****************************************************************************
307  *****************************************************************************
308  * A class used by the dynamic loader to allocate and deallocate target memory.
309  *****************************************************************************
310  **************************************************************************** */
311 
312 struct ldr_section_info {
313 	/* Name of the memory section assigned at build time */
314 	const char *name;
315 	ldr_addr run_addr;	/* execution address of the section */
316 	ldr_addr load_addr;	/* load address of the section */
317 	ldr_addr size;		/* size of the section in addressable units */
318 #ifndef _BIG_ENDIAN
319 	u16 page;		/* memory page or view */
320 	u16 type;		/* one of the section types below */
321 #else
322 	u16 type;		/* one of the section types below */
323 	u16 page;		/* memory page or view */
324 #endif
325 	/* a context field for use by dynamic_loader_allocate;
326 	 *   ignored but maintained by the dynamic loader */
327 	u32 context;
328 };
329 
330 /* use this macro to extract type of section from ldr_section_info.type field */
331 #define DLOAD_SECTION_TYPE(typeinfo) (typeinfo & 0xF)
332 
333 /* type of section to be allocated */
334 #define DLOAD_TEXT 0
335 #define DLOAD_DATA 1
336 #define DLOAD_BSS 2
337 	/* internal use only, run-time cinit will be of type DLOAD_DATA */
338 #define DLOAD_CINIT 3
339 
340 struct dynamic_loader_allocate {
341 /* public: */
342 
343     /*************************************************************************
344     * Function allocate
345     *
346     * Parameters:
347     *   info        A pointer to an information block for the section
348     *   align       The alignment of the storage in target AUs
349     *
350     * Effect:
351     *   Allocates target memory for the specified section and fills in the
352     * load_addr and run_addr fields of the section info structure. Returns TRUE
353     * for success, FALSE for failure.
354     *
355     * Notes:
356     *   Frequently load_addr and run_addr are the same, but if they are not
357     * load_addr is used with dynamic_loader_initialize, and run_addr is
358     * used for almost all relocations.  This function should always initialize
359     * both fields.
360     ************************************************************************ */
361 	int (*dload_allocate) (struct dynamic_loader_allocate *thisptr,
362 			       struct ldr_section_info *info, unsigned align);
363 
364     /*************************************************************************
365     * Function deallocate
366     *
367     * Parameters:
368     *   info        A pointer to an information block for the section
369     *
370     * Effect:
371     *   Releases the target memory previously allocated.
372     *
373     * Notes:
374     * The content of the info->name field is undefined on call to this function.
375     ************************************************************************ */
376 	void (*dload_deallocate) (struct dynamic_loader_allocate *thisptr,
377 				  struct ldr_section_info *info);
378 
379 };				/* class dynamic_loader_allocate */
380 
381 /*****************************************************************************
382  *****************************************************************************
383  * A class used by the dynamic loader to load data into a target.  This class
384  * provides the interface-specific functions needed to load data.
385  *****************************************************************************
386  **************************************************************************** */
387 
388 struct dynamic_loader_initialize {
389 /* public: */
390     /*************************************************************************
391     * Function connect
392     *
393     * Parameters:
394     *   none
395     *
396     * Effect:
397     *   Connect to the initialization interface. Returns TRUE for success,
398     * FALSE for failure.
399     *
400     * Notes:
401     *   This function is called prior to use of any other functions in
402     * this interface.
403     ************************************************************************ */
404 	int (*connect) (struct dynamic_loader_initialize *thisptr);
405 
406     /*************************************************************************
407     * Function readmem
408     *
409     * Parameters:
410     *   bufr        Pointer to a word-aligned buffer for the result
411     *   locn        Target address of first data element
412     *   info        Section info for the section in which the address resides
413     *   bytsiz      Size of the data to be read in sizeof() units
414     *
415     * Effect:
416     *   Fills the specified buffer with data from the target.  Returns TRUE for
417     * success, FALSE for failure.
418     ************************************************************************ */
419 	int (*readmem) (struct dynamic_loader_initialize *thisptr,
420 			void *bufr,
421 			ldr_addr locn,
422 			struct ldr_section_info *info, unsigned bytsiz);
423 
424     /*************************************************************************
425     * Function writemem
426     *
427     * Parameters:
428     *   bufr        Pointer to a word-aligned buffer of data
429     *   locn        Target address of first data element to be written
430     *   info        Section info for the section in which the address resides
431     *   bytsiz      Size of the data to be written in sizeof() units
432     *
433     * Effect:
434     *   Writes the specified buffer to the target.  Returns TRUE for success,
435     * FALSE for failure.
436     ************************************************************************ */
437 	int (*writemem) (struct dynamic_loader_initialize *thisptr,
438 			 void *bufr,
439 			 ldr_addr locn,
440 			 struct ldr_section_info *info, unsigned bytsiz);
441 
442     /*************************************************************************
443     * Function fillmem
444     *
445     * Parameters:
446     *   locn        Target address of first data element to be written
447     *   info        Section info for the section in which the address resides
448     *   bytsiz      Size of the data to be written in sizeof() units
449     *   val         Value to be written in each byte
450     * Effect:
451     *   Fills the specified area of target memory.  Returns TRUE for success,
452     * FALSE for failure.
453     ************************************************************************ */
454 	int (*fillmem) (struct dynamic_loader_initialize *thisptr,
455 			ldr_addr locn, struct ldr_section_info *info,
456 			unsigned bytsiz, unsigned val);
457 
458     /*************************************************************************
459     * Function execute
460     *
461     * Parameters:
462     *   start       Starting address
463     *
464     * Effect:
465     *   The target code at the specified starting address is executed.
466     *
467     * Notes:
468     *   This function is called at the end of the dynamic load process
469     * if the input module has specified a starting address.
470     ************************************************************************ */
471 	int (*execute) (struct dynamic_loader_initialize *thisptr,
472 			ldr_addr start);
473 
474     /*************************************************************************
475     * Function release
476     *
477     * Parameters:
478     *   none
479     *
480     * Effect:
481     *   Releases the connection to the load interface.
482     *
483     * Notes:
484     *   This function is called at the end of the dynamic load process.
485     ************************************************************************ */
486 	void (*release) (struct dynamic_loader_initialize *thisptr);
487 
488 };				/* class dynamic_loader_initialize */
489 
490 #endif /* _DYNAMIC_LOADER_H_ */
491