Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cod.c
Go to the documentation of this file.
1 /*
2  * cod.c
3  *
4  * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5  *
6  * This module implements DSP code management for the DSP/BIOS Bridge
7  * environment. It is mostly a thin wrapper.
8  *
9  * This module provides an interface for loading both static and
10  * dynamic code objects onto DSP systems.
11  *
12  * Copyright (C) 2005-2006 Texas Instruments, Inc.
13  *
14  * This package is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License version 2 as
16  * published by the Free Software Foundation.
17  *
18  * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21  */
22 
23 #include <linux/types.h>
24 
25 /* ----------------------------------- Host OS */
26 #include <dspbridge/host_os.h>
27 #include <linux/fs.h>
28 #include <linux/uaccess.h>
29 
30 /* ----------------------------------- DSP/BIOS Bridge */
31 #include <dspbridge/dbdefs.h>
32 
33 /* ----------------------------------- Platform Manager */
34 /* Include appropriate loader header file */
35 #include <dspbridge/dbll.h>
36 
37 /* ----------------------------------- This */
38 #include <dspbridge/cod.h>
39 
40 /*
41  * ======== cod_manager ========
42  */
43 struct cod_manager {
46  bool loaded; /* Base library loaded? */
48  struct dbll_fxns fxns;
49  struct dbll_attrs attrs;
51 };
52 
53 /*
54  * ======== cod_libraryobj ========
55  */
59 };
60 
61 static struct dbll_fxns ldr_fxns = {
75 };
76 
77 static bool no_op(void);
78 
79 /*
80  * File operations (originally were under kfile.c)
81  */
82 static s32 cod_f_close(struct file *filp)
83 {
84  /* Check for valid handle */
85  if (!filp)
86  return -EFAULT;
87 
88  filp_close(filp, NULL);
89 
90  /* we can't use 0 here */
91  return 0;
92 }
93 
94 static struct file *cod_f_open(const char *psz_file_name, const char *sz_mode)
95 {
97  struct file *filp;
98 
99  fs = get_fs();
100  set_fs(get_ds());
101 
102  /* ignore given mode and open file as read-only */
103  filp = filp_open(psz_file_name, O_RDONLY, 0);
104 
105  if (IS_ERR(filp))
106  filp = NULL;
107 
108  set_fs(fs);
109 
110  return filp;
111 }
112 
113 static s32 cod_f_read(void __user *pbuffer, s32 size, s32 count,
114  struct file *filp)
115 {
116  /* check for valid file handle */
117  if (!filp)
118  return -EFAULT;
119 
120  if ((size > 0) && (count > 0) && pbuffer) {
121  u32 dw_bytes_read;
123 
124  /* read from file */
125  fs = get_fs();
126  set_fs(get_ds());
127  dw_bytes_read = filp->f_op->read(filp, pbuffer, size * count,
128  &(filp->f_pos));
129  set_fs(fs);
130 
131  if (!dw_bytes_read)
132  return -EBADF;
133 
134  return dw_bytes_read / size;
135  }
136 
137  return -EINVAL;
138 }
139 
140 static s32 cod_f_seek(struct file *filp, s32 offset, s32 origin)
141 {
142  loff_t dw_cur_pos;
143 
144  /* check for valid file handle */
145  if (!filp)
146  return -EFAULT;
147 
148  /* based on the origin flag, move the internal pointer */
149  dw_cur_pos = filp->f_op->llseek(filp, offset, origin);
150 
151  if ((s32) dw_cur_pos < 0)
152  return -EPERM;
153 
154  /* we can't use 0 here */
155  return 0;
156 }
157 
158 static s32 cod_f_tell(struct file *filp)
159 {
160  loff_t dw_cur_pos;
161 
162  if (!filp)
163  return -EFAULT;
164 
165  /* Get current position */
166  dw_cur_pos = filp->f_op->llseek(filp, 0, SEEK_CUR);
167 
168  if ((s32) dw_cur_pos < 0)
169  return -EPERM;
170 
171  return dw_cur_pos;
172 }
173 
174 /*
175  * ======== cod_close ========
176  */
177 void cod_close(struct cod_libraryobj *lib)
178 {
179  struct cod_manager *hmgr;
180 
181  hmgr = lib->cod_mgr;
182  hmgr->fxns.close_fxn(lib->dbll_lib);
183 
184  kfree(lib);
185 }
186 
187 /*
188  * ======== cod_create ========
189  * Purpose:
190  * Create an object to manage code on a DSP system.
191  * This object can be used to load an initial program image with
192  * arguments that can later be expanded with
193  * dynamically loaded object files.
194  *
195  */
196 int cod_create(struct cod_manager **mgr, char *str_zl_file)
197 {
198  struct cod_manager *mgr_new;
199  struct dbll_attrs zl_attrs;
200  int status = 0;
201 
202  /* assume failure */
203  *mgr = NULL;
204 
205  mgr_new = kzalloc(sizeof(struct cod_manager), GFP_KERNEL);
206  if (mgr_new == NULL)
207  return -ENOMEM;
208 
209  /* Set up loader functions */
210  mgr_new->fxns = ldr_fxns;
211 
212  /* initialize the ZL module */
213  mgr_new->fxns.init_fxn();
214 
215  zl_attrs.alloc = (dbll_alloc_fxn) no_op;
216  zl_attrs.free = (dbll_free_fxn) no_op;
217  zl_attrs.fread = (dbll_read_fxn) cod_f_read;
218  zl_attrs.fseek = (dbll_seek_fxn) cod_f_seek;
219  zl_attrs.ftell = (dbll_tell_fxn) cod_f_tell;
220  zl_attrs.fclose = (dbll_f_close_fxn) cod_f_close;
221  zl_attrs.fopen = (dbll_f_open_fxn) cod_f_open;
222  zl_attrs.sym_lookup = NULL;
223  zl_attrs.base_image = true;
224  zl_attrs.log_write = NULL;
225  zl_attrs.log_write_handle = NULL;
226  zl_attrs.write = NULL;
227  zl_attrs.rmm_handle = NULL;
228  zl_attrs.input_params = NULL;
229  zl_attrs.sym_handle = NULL;
230  zl_attrs.sym_arg = NULL;
231 
232  mgr_new->attrs = zl_attrs;
233 
234  status = mgr_new->fxns.create_fxn(&mgr_new->target, &zl_attrs);
235 
236  if (status) {
237  cod_delete(mgr_new);
238  return -ESPIPE;
239  }
240 
241  /* return the new manager */
242  *mgr = mgr_new;
243 
244  return 0;
245 }
246 
247 /*
248  * ======== cod_delete ========
249  * Purpose:
250  * Delete a code manager object.
251  */
252 void cod_delete(struct cod_manager *cod_mgr_obj)
253 {
254  if (cod_mgr_obj->base_lib) {
255  if (cod_mgr_obj->loaded)
256  cod_mgr_obj->fxns.unload_fxn(cod_mgr_obj->base_lib,
257  &cod_mgr_obj->attrs);
258 
259  cod_mgr_obj->fxns.close_fxn(cod_mgr_obj->base_lib);
260  }
261  if (cod_mgr_obj->target) {
262  cod_mgr_obj->fxns.delete_fxn(cod_mgr_obj->target);
263  cod_mgr_obj->fxns.exit_fxn();
264  }
265  kfree(cod_mgr_obj);
266 }
267 
268 /*
269  * ======== cod_get_base_lib ========
270  * Purpose:
271  * Get handle to the base image DBL library.
272  */
273 int cod_get_base_lib(struct cod_manager *cod_mgr_obj,
274  struct dbll_library_obj **plib)
275 {
276  int status = 0;
277 
278  *plib = (struct dbll_library_obj *)cod_mgr_obj->base_lib;
279 
280  return status;
281 }
282 
283 /*
284  * ======== cod_get_base_name ========
285  */
286 int cod_get_base_name(struct cod_manager *cod_mgr_obj, char *sz_name,
287  u32 usize)
288 {
289  int status = 0;
290 
291  if (usize <= COD_MAXPATHLENGTH)
292  strncpy(sz_name, cod_mgr_obj->sz_zl_file, usize);
293  else
294  status = -EPERM;
295 
296  return status;
297 }
298 
299 /*
300  * ======== cod_get_entry ========
301  * Purpose:
302  * Retrieve the entry point of a loaded DSP program image
303  *
304  */
305 int cod_get_entry(struct cod_manager *cod_mgr_obj, u32 *entry_pt)
306 {
307  *entry_pt = cod_mgr_obj->entry;
308 
309  return 0;
310 }
311 
312 /*
313  * ======== cod_get_loader ========
314  * Purpose:
315  * Get handle to the DBLL loader.
316  */
317 int cod_get_loader(struct cod_manager *cod_mgr_obj,
318  struct dbll_tar_obj **loader)
319 {
320  int status = 0;
321 
322  *loader = (struct dbll_tar_obj *)cod_mgr_obj->target;
323 
324  return status;
325 }
326 
327 /*
328  * ======== cod_get_section ========
329  * Purpose:
330  * Retrieve the starting address and length of a section in the COFF file
331  * given the section name.
332  */
333 int cod_get_section(struct cod_libraryobj *lib, char *str_sect,
334  u32 *addr, u32 *len)
335 {
336  struct cod_manager *cod_mgr_obj;
337  int status = 0;
338 
339  *addr = 0;
340  *len = 0;
341  if (lib != NULL) {
342  cod_mgr_obj = lib->cod_mgr;
343  status = cod_mgr_obj->fxns.get_sect_fxn(lib->dbll_lib, str_sect,
344  addr, len);
345  } else {
346  status = -ESPIPE;
347  }
348 
349  return status;
350 }
351 
352 /*
353  * ======== cod_get_sym_value ========
354  * Purpose:
355  * Retrieve the value for the specified symbol. The symbol is first
356  * searched for literally and then, if not found, searched for as a
357  * C symbol.
358  *
359  */
360 int cod_get_sym_value(struct cod_manager *cod_mgr_obj, char *str_sym,
361  u32 *pul_value)
362 {
363  struct dbll_sym_val *dbll_sym;
364 
365  dev_dbg(bridge, "%s: cod_mgr_obj: %p str_sym: %s pul_value: %p\n",
366  __func__, cod_mgr_obj, str_sym, pul_value);
367  if (cod_mgr_obj->base_lib) {
368  if (!cod_mgr_obj->fxns.
369  get_addr_fxn(cod_mgr_obj->base_lib, str_sym, &dbll_sym)) {
370  if (!cod_mgr_obj->fxns.
371  get_c_addr_fxn(cod_mgr_obj->base_lib, str_sym,
372  &dbll_sym))
373  return -ESPIPE;
374  }
375  } else {
376  return -ESPIPE;
377  }
378 
379  *pul_value = dbll_sym->value;
380 
381  return 0;
382 }
383 
384 /*
385  * ======== cod_load_base ========
386  * Purpose:
387  * Load the initial program image, optionally with command-line arguments,
388  * on the DSP system managed by the supplied handle. The program to be
389  * loaded must be the first element of the args array and must be a fully
390  * qualified pathname.
391  * Details:
392  * if num_argc doesn't match the number of arguments in the args array, the
393  * args array is searched for a NULL terminating entry, and argc is
394  * recalculated to reflect this. In this way, we can support NULL
395  * terminating args arrays, if num_argc is very large.
396  */
397 int cod_load_base(struct cod_manager *cod_mgr_obj, u32 num_argc, char *args[],
398  cod_writefxn pfn_write, void *arb, char *envp[])
399 {
401  struct dbll_attrs save_attrs;
402  struct dbll_attrs new_attrs;
403  int status;
404  u32 i;
405 
406  /*
407  * Make sure every argv[] stated in argc has a value, or change argc to
408  * reflect true number in NULL terminated argv array.
409  */
410  for (i = 0; i < num_argc; i++) {
411  if (args[i] == NULL) {
412  num_argc = i;
413  break;
414  }
415  }
416 
417  /* set the write function for this operation */
418  cod_mgr_obj->fxns.get_attrs_fxn(cod_mgr_obj->target, &save_attrs);
419 
420  new_attrs = save_attrs;
421  new_attrs.write = (dbll_write_fxn) pfn_write;
422  new_attrs.input_params = arb;
423  new_attrs.alloc = (dbll_alloc_fxn) no_op;
424  new_attrs.free = (dbll_free_fxn) no_op;
425  new_attrs.log_write = NULL;
426  new_attrs.log_write_handle = NULL;
427 
428  /* Load the image */
429  flags = DBLL_CODE | DBLL_DATA | DBLL_SYMB;
430  status = cod_mgr_obj->fxns.load_fxn(cod_mgr_obj->base_lib, flags,
431  &new_attrs,
432  &cod_mgr_obj->entry);
433  if (status)
434  cod_mgr_obj->fxns.close_fxn(cod_mgr_obj->base_lib);
435 
436  if (!status)
437  cod_mgr_obj->loaded = true;
438  else
439  cod_mgr_obj->base_lib = NULL;
440 
441  return status;
442 }
443 
444 /*
445  * ======== cod_open ========
446  * Open library for reading sections.
447  */
448 int cod_open(struct cod_manager *hmgr, char *sz_coff_path,
449  u32 flags, struct cod_libraryobj **lib_obj)
450 {
451  int status = 0;
452  struct cod_libraryobj *lib = NULL;
453 
454  *lib_obj = NULL;
455 
456  lib = kzalloc(sizeof(struct cod_libraryobj), GFP_KERNEL);
457  if (lib == NULL)
458  status = -ENOMEM;
459 
460  if (!status) {
461  lib->cod_mgr = hmgr;
462  status = hmgr->fxns.open_fxn(hmgr->target, sz_coff_path, flags,
463  &lib->dbll_lib);
464  if (!status)
465  *lib_obj = lib;
466  }
467 
468  if (status)
469  pr_err("%s: error status 0x%x, sz_coff_path: %s flags: 0x%x\n",
470  __func__, status, sz_coff_path, flags);
471  return status;
472 }
473 
474 /*
475  * ======== cod_open_base ========
476  * Purpose:
477  * Open base image for reading sections.
478  */
479 int cod_open_base(struct cod_manager *hmgr, char *sz_coff_path,
481 {
482  int status = 0;
483  struct dbll_library_obj *lib;
484 
485  /* if we previously opened a base image, close it now */
486  if (hmgr->base_lib) {
487  if (hmgr->loaded) {
488  hmgr->fxns.unload_fxn(hmgr->base_lib, &hmgr->attrs);
489  hmgr->loaded = false;
490  }
491  hmgr->fxns.close_fxn(hmgr->base_lib);
492  hmgr->base_lib = NULL;
493  }
494  status = hmgr->fxns.open_fxn(hmgr->target, sz_coff_path, flags, &lib);
495  if (!status) {
496  /* hang onto the library for subsequent sym table usage */
497  hmgr->base_lib = lib;
498  strncpy(hmgr->sz_zl_file, sz_coff_path, COD_MAXPATHLENGTH - 1);
499  hmgr->sz_zl_file[COD_MAXPATHLENGTH - 1] = '\0';
500  }
501 
502  if (status)
503  pr_err("%s: error status 0x%x sz_coff_path: %s\n", __func__,
504  status, sz_coff_path);
505  return status;
506 }
507 
508 /*
509  * ======== cod_read_section ========
510  * Purpose:
511  * Retrieve the content of a code section given the section name.
512  */
513 int cod_read_section(struct cod_libraryobj *lib, char *str_sect,
514  char *str_content, u32 content_size)
515 {
516  int status = 0;
517 
518  if (lib != NULL)
519  status =
520  lib->cod_mgr->fxns.read_sect_fxn(lib->dbll_lib, str_sect,
521  str_content, content_size);
522  else
523  status = -ESPIPE;
524 
525  return status;
526 }
527 
528 /*
529  * ======== no_op ========
530  * Purpose:
531  * No Operation.
532  *
533  */
534 static bool no_op(void)
535 {
536  return true;
537 }