]> Pileus Git - ~andy/linux/blob - drivers/staging/tidspbridge/pmgr/cod.c
staging: ti dspbridge: make variables in prototypes match within functions definitions
[~andy/linux] / drivers / staging / tidspbridge / pmgr / cod.c
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 /*  ----------------------------------- Host OS */
24 #include <dspbridge/host_os.h>
25 #include <linux/fs.h>
26 #include <linux/uaccess.h>
27
28 /*  ----------------------------------- DSP/BIOS Bridge */
29 #include <dspbridge/std.h>
30 #include <dspbridge/dbdefs.h>
31
32 /*  ----------------------------------- Trace & Debug */
33 #include <dspbridge/dbc.h>
34
35 /*  ----------------------------------- OS Adaptation Layer */
36 #include <dspbridge/ldr.h>
37
38 /*  ----------------------------------- Platform Manager */
39 /* Include appropriate loader header file */
40 #include <dspbridge/dbll.h>
41
42 /*  ----------------------------------- This */
43 #include <dspbridge/cod.h>
44
45 /* magic number for handle validation */
46 #define MAGIC    0xc001beef
47
48 /* macro to validate COD manager handles */
49 #define IS_VALID(h)    ((h) != NULL && (h)->ul_magic == MAGIC)
50
51 /*
52  *  ======== cod_manager ========
53  */
54 struct cod_manager {
55         struct dbll_tar_obj *target;
56         struct dbll_library_obj *base_lib;
57         bool loaded;            /* Base library loaded? */
58         u32 ul_entry;
59         struct ldr_module *dll_obj;
60         struct dbll_fxns fxns;
61         struct dbll_attrs attrs;
62         char sz_zl_file[COD_MAXPATHLENGTH];
63         u32 ul_magic;
64 };
65
66 /*
67  *  ======== cod_libraryobj ========
68  */
69 struct cod_libraryobj {
70         struct dbll_library_obj *dbll_lib;
71         struct cod_manager *cod_mgr;
72 };
73
74 static u32 refs = 0L;
75
76 static struct dbll_fxns ldr_fxns = {
77         (dbll_close_fxn) dbll_close,
78         (dbll_create_fxn) dbll_create,
79         (dbll_delete_fxn) dbll_delete,
80         (dbll_exit_fxn) dbll_exit,
81         (dbll_get_attrs_fxn) dbll_get_attrs,
82         (dbll_get_addr_fxn) dbll_get_addr,
83         (dbll_get_c_addr_fxn) dbll_get_c_addr,
84         (dbll_get_sect_fxn) dbll_get_sect,
85         (dbll_init_fxn) dbll_init,
86         (dbll_load_fxn) dbll_load,
87         (dbll_load_sect_fxn) dbll_load_sect,
88         (dbll_open_fxn) dbll_open,
89         (dbll_read_sect_fxn) dbll_read_sect,
90         (dbll_set_attrs_fxn) dbll_set_attrs,
91         (dbll_unload_fxn) dbll_unload,
92         (dbll_unload_sect_fxn) dbll_unload_sect,
93 };
94
95 static bool no_op(void);
96
97 /*
98  * File operations (originally were under kfile.c)
99  */
100 static s32 cod_f_close(struct file *filp)
101 {
102         /* Check for valid handle */
103         if (!filp)
104                 return -EFAULT;
105
106         filp_close(filp, NULL);
107
108         /* we can't use 0 here */
109         return 0;
110 }
111
112 static struct file *cod_f_open(CONST char *psz_file_name, CONST char *sz_mode)
113 {
114         mm_segment_t fs;
115         struct file *filp;
116
117         fs = get_fs();
118         set_fs(get_ds());
119
120         /* ignore given mode and open file as read-only */
121         filp = filp_open(psz_file_name, O_RDONLY, 0);
122
123         if (IS_ERR(filp))
124                 filp = NULL;
125
126         set_fs(fs);
127
128         return filp;
129 }
130
131 static s32 cod_f_read(void __user *pbuffer, s32 size, s32 count,
132                       struct file *filp)
133 {
134         /* check for valid file handle */
135         if (!filp)
136                 return -EFAULT;
137
138         if ((size > 0) && (count > 0) && pbuffer) {
139                 u32 dw_bytes_read;
140                 mm_segment_t fs;
141
142                 /* read from file */
143                 fs = get_fs();
144                 set_fs(get_ds());
145                 dw_bytes_read = filp->f_op->read(filp, pbuffer, size * count,
146                                                  &(filp->f_pos));
147                 set_fs(fs);
148
149                 if (!dw_bytes_read)
150                         return -EBADF;
151
152                 return dw_bytes_read / size;
153         }
154
155         return -EINVAL;
156 }
157
158 static s32 cod_f_seek(struct file *filp, s32 offset, s32 origin)
159 {
160         loff_t dw_cur_pos;
161
162         /* check for valid file handle */
163         if (!filp)
164                 return -EFAULT;
165
166         /* based on the origin flag, move the internal pointer */
167         dw_cur_pos = filp->f_op->llseek(filp, offset, origin);
168
169         if ((s32) dw_cur_pos < 0)
170                 return -EPERM;
171
172         /* we can't use 0 here */
173         return 0;
174 }
175
176 static s32 cod_f_tell(struct file *filp)
177 {
178         loff_t dw_cur_pos;
179
180         if (!filp)
181                 return -EFAULT;
182
183         /* Get current position */
184         dw_cur_pos = filp->f_op->llseek(filp, 0, SEEK_CUR);
185
186         if ((s32) dw_cur_pos < 0)
187                 return -EPERM;
188
189         return dw_cur_pos;
190 }
191
192 /*
193  *  ======== cod_close ========
194  */
195 void cod_close(struct cod_libraryobj *lib)
196 {
197         struct cod_manager *hmgr;
198
199         DBC_REQUIRE(refs > 0);
200         DBC_REQUIRE(lib != NULL);
201         DBC_REQUIRE(IS_VALID(((struct cod_libraryobj *)lib)->cod_mgr));
202
203         hmgr = lib->cod_mgr;
204         hmgr->fxns.close_fxn(lib->dbll_lib);
205
206         kfree(lib);
207 }
208
209 /*
210  *  ======== cod_create ========
211  *  Purpose:
212  *      Create an object to manage code on a DSP system.
213  *      This object can be used to load an initial program image with
214  *      arguments that can later be expanded with
215  *      dynamically loaded object files.
216  *
217  */
218 int cod_create(OUT struct cod_manager **mgr, char *str_zl_file,
219                       IN OPTIONAL CONST struct cod_attrs *attrs)
220 {
221         struct cod_manager *mgr_new;
222         struct dbll_attrs zl_attrs;
223         int status = 0;
224
225         DBC_REQUIRE(refs > 0);
226         DBC_REQUIRE(mgr != NULL);
227
228         /* assume failure */
229         *mgr = NULL;
230
231         /* we don't support non-default attrs yet */
232         if (attrs != NULL)
233                 return -ENOSYS;
234
235         mgr_new = kzalloc(sizeof(struct cod_manager), GFP_KERNEL);
236         if (mgr_new == NULL)
237                 return -ENOMEM;
238
239         mgr_new->ul_magic = MAGIC;
240
241         /* Set up loader functions */
242         mgr_new->fxns = ldr_fxns;
243
244         /* initialize the ZL module */
245         mgr_new->fxns.init_fxn();
246
247         zl_attrs.alloc = (dbll_alloc_fxn) no_op;
248         zl_attrs.free = (dbll_free_fxn) no_op;
249         zl_attrs.fread = (dbll_read_fxn) cod_f_read;
250         zl_attrs.fseek = (dbll_seek_fxn) cod_f_seek;
251         zl_attrs.ftell = (dbll_tell_fxn) cod_f_tell;
252         zl_attrs.fclose = (dbll_f_close_fxn) cod_f_close;
253         zl_attrs.fopen = (dbll_f_open_fxn) cod_f_open;
254         zl_attrs.sym_lookup = NULL;
255         zl_attrs.base_image = true;
256         zl_attrs.log_write = NULL;
257         zl_attrs.log_write_handle = NULL;
258         zl_attrs.write = NULL;
259         zl_attrs.rmm_handle = NULL;
260         zl_attrs.input_params = NULL;
261         zl_attrs.sym_handle = NULL;
262         zl_attrs.sym_arg = NULL;
263
264         mgr_new->attrs = zl_attrs;
265
266         status = mgr_new->fxns.create_fxn(&mgr_new->target, &zl_attrs);
267
268         if (DSP_FAILED(status)) {
269                 cod_delete(mgr_new);
270                 return -ESPIPE;
271         }
272
273         /* return the new manager */
274         *mgr = mgr_new;
275
276         return 0;
277 }
278
279 /*
280  *  ======== cod_delete ========
281  *  Purpose:
282  *      Delete a code manager object.
283  */
284 void cod_delete(struct cod_manager *cod_mgr_obj)
285 {
286         DBC_REQUIRE(refs > 0);
287         DBC_REQUIRE(IS_VALID(cod_mgr_obj));
288
289         if (cod_mgr_obj->base_lib) {
290                 if (cod_mgr_obj->loaded)
291                         cod_mgr_obj->fxns.unload_fxn(cod_mgr_obj->base_lib,
292                                                         &cod_mgr_obj->attrs);
293
294                 cod_mgr_obj->fxns.close_fxn(cod_mgr_obj->base_lib);
295         }
296         if (cod_mgr_obj->target) {
297                 cod_mgr_obj->fxns.delete_fxn(cod_mgr_obj->target);
298                 cod_mgr_obj->fxns.exit_fxn();
299         }
300         cod_mgr_obj->ul_magic = ~MAGIC;
301         kfree(cod_mgr_obj);
302 }
303
304 /*
305  *  ======== cod_exit ========
306  *  Purpose:
307  *      Discontinue usage of the COD module.
308  *
309  */
310 void cod_exit(void)
311 {
312         DBC_REQUIRE(refs > 0);
313
314         refs--;
315
316         DBC_ENSURE(refs >= 0);
317 }
318
319 /*
320  *  ======== cod_get_base_lib ========
321  *  Purpose:
322  *      Get handle to the base image DBL library.
323  */
324 int cod_get_base_lib(struct cod_manager *cod_mgr_obj,
325                             struct dbll_library_obj **plib)
326 {
327         int status = 0;
328
329         DBC_REQUIRE(refs > 0);
330         DBC_REQUIRE(IS_VALID(cod_mgr_obj));
331         DBC_REQUIRE(plib != NULL);
332
333         *plib = (struct dbll_library_obj *)cod_mgr_obj->base_lib;
334
335         return status;
336 }
337
338 /*
339  *  ======== cod_get_base_name ========
340  */
341 int cod_get_base_name(struct cod_manager *cod_mgr_obj, char *sz_name,
342                              u32 usize)
343 {
344         int status = 0;
345
346         DBC_REQUIRE(refs > 0);
347         DBC_REQUIRE(IS_VALID(cod_mgr_obj));
348         DBC_REQUIRE(sz_name != NULL);
349
350         if (usize <= COD_MAXPATHLENGTH)
351                 strncpy(sz_name, cod_mgr_obj->sz_zl_file, usize);
352         else
353                 status = -EPERM;
354
355         return status;
356 }
357
358 /*
359  *  ======== cod_get_entry ========
360  *  Purpose:
361  *      Retrieve the entry point of a loaded DSP program image
362  *
363  */
364 int cod_get_entry(struct cod_manager *cod_mgr_obj, u32 *entry_pt)
365 {
366         DBC_REQUIRE(refs > 0);
367         DBC_REQUIRE(IS_VALID(cod_mgr_obj));
368         DBC_REQUIRE(entry_pt != NULL);
369
370         *entry_pt = cod_mgr_obj->ul_entry;
371
372         return 0;
373 }
374
375 /*
376  *  ======== cod_get_loader ========
377  *  Purpose:
378  *      Get handle to the DBLL loader.
379  */
380 int cod_get_loader(struct cod_manager *cod_mgr_obj,
381                           struct dbll_tar_obj **loader)
382 {
383         int status = 0;
384
385         DBC_REQUIRE(refs > 0);
386         DBC_REQUIRE(IS_VALID(cod_mgr_obj));
387         DBC_REQUIRE(loader != NULL);
388
389         *loader = (struct dbll_tar_obj *)cod_mgr_obj->target;
390
391         return status;
392 }
393
394 /*
395  *  ======== cod_get_section ========
396  *  Purpose:
397  *      Retrieve the starting address and length of a section in the COFF file
398  *      given the section name.
399  */
400 int cod_get_section(struct cod_libraryobj *lib, IN char *str_sect,
401                            OUT u32 *addr, OUT u32 *len)
402 {
403         struct cod_manager *cod_mgr_obj;
404         int status = 0;
405
406         DBC_REQUIRE(refs > 0);
407         DBC_REQUIRE(lib != NULL);
408         DBC_REQUIRE(IS_VALID(lib->cod_mgr));
409         DBC_REQUIRE(str_sect != NULL);
410         DBC_REQUIRE(addr != NULL);
411         DBC_REQUIRE(len != NULL);
412
413         *addr = 0;
414         *len = 0;
415         if (lib != NULL) {
416                 cod_mgr_obj = lib->cod_mgr;
417                 status = cod_mgr_obj->fxns.get_sect_fxn(lib->dbll_lib, str_sect,
418                                                         addr, len);
419         } else {
420                 status = -ESPIPE;
421         }
422
423         DBC_ENSURE(DSP_SUCCEEDED(status) || ((*addr == 0) && (*len == 0)));
424
425         return status;
426 }
427
428 /*
429  *  ======== cod_get_sym_value ========
430  *  Purpose:
431  *      Retrieve the value for the specified symbol. The symbol is first
432  *      searched for literally and then, if not found, searched for as a
433  *      C symbol.
434  *
435  */
436 int cod_get_sym_value(struct cod_manager *cod_mgr_obj, char *str_sym,
437                              u32 *pul_value)
438 {
439         struct dbll_sym_val *dbll_sym;
440
441         DBC_REQUIRE(refs > 0);
442         DBC_REQUIRE(IS_VALID(cod_mgr_obj));
443         DBC_REQUIRE(str_sym != NULL);
444         DBC_REQUIRE(pul_value != NULL);
445
446         dev_dbg(bridge, "%s: cod_mgr_obj: %p str_sym: %s pul_value: %p\n",
447                 __func__, cod_mgr_obj, str_sym, pul_value);
448         if (cod_mgr_obj->base_lib) {
449                 if (!cod_mgr_obj->fxns.
450                     get_addr_fxn(cod_mgr_obj->base_lib, str_sym, &dbll_sym)) {
451                         if (!cod_mgr_obj->fxns.
452                             get_c_addr_fxn(cod_mgr_obj->base_lib, str_sym,
453                                                 &dbll_sym))
454                                 return -ESPIPE;
455                 }
456         } else {
457                 return -ESPIPE;
458         }
459
460         *pul_value = dbll_sym->value;
461
462         return 0;
463 }
464
465 /*
466  *  ======== cod_init ========
467  *  Purpose:
468  *      Initialize the COD module's private state.
469  *
470  */
471 bool cod_init(void)
472 {
473         bool ret = true;
474
475         DBC_REQUIRE(refs >= 0);
476
477         if (ret)
478                 refs++;
479
480         DBC_ENSURE((ret && refs > 0) || (!ret && refs >= 0));
481         return ret;
482 }
483
484 /*
485  *  ======== cod_load_base ========
486  *  Purpose:
487  *      Load the initial program image, optionally with command-line arguments,
488  *      on the DSP system managed by the supplied handle. The program to be
489  *      loaded must be the first element of the args array and must be a fully
490  *      qualified pathname.
491  *  Details:
492  *      if num_argc doesn't match the number of arguments in the args array, the
493  *      args array is searched for a NULL terminating entry, and argc is
494  *      recalculated to reflect this.  In this way, we can support NULL
495  *      terminating args arrays, if num_argc is very large.
496  */
497 int cod_load_base(struct cod_manager *cod_mgr_obj, u32 num_argc, char *args[],
498                          cod_writefxn pfn_write, void *arb, char *envp[])
499 {
500         dbll_flags flags;
501         struct dbll_attrs save_attrs;
502         struct dbll_attrs new_attrs;
503         int status;
504         u32 i;
505
506         DBC_REQUIRE(refs > 0);
507         DBC_REQUIRE(IS_VALID(cod_mgr_obj));
508         DBC_REQUIRE(num_argc > 0);
509         DBC_REQUIRE(args != NULL);
510         DBC_REQUIRE(args[0] != NULL);
511         DBC_REQUIRE(pfn_write != NULL);
512         DBC_REQUIRE(cod_mgr_obj->base_lib != NULL);
513
514         /*
515          *  Make sure every argv[] stated in argc has a value, or change argc to
516          *  reflect true number in NULL terminated argv array.
517          */
518         for (i = 0; i < num_argc; i++) {
519                 if (args[i] == NULL) {
520                         num_argc = i;
521                         break;
522                 }
523         }
524
525         /* set the write function for this operation */
526         cod_mgr_obj->fxns.get_attrs_fxn(cod_mgr_obj->target, &save_attrs);
527
528         new_attrs = save_attrs;
529         new_attrs.write = (dbll_write_fxn) pfn_write;
530         new_attrs.input_params = arb;
531         new_attrs.alloc = (dbll_alloc_fxn) no_op;
532         new_attrs.free = (dbll_free_fxn) no_op;
533         new_attrs.log_write = NULL;
534         new_attrs.log_write_handle = NULL;
535
536         /* Load the image */
537         flags = DBLL_CODE | DBLL_DATA | DBLL_SYMB;
538         status = cod_mgr_obj->fxns.load_fxn(cod_mgr_obj->base_lib, flags,
539                                             &new_attrs,
540                                             &cod_mgr_obj->ul_entry);
541         if (DSP_FAILED(status))
542                 cod_mgr_obj->fxns.close_fxn(cod_mgr_obj->base_lib);
543
544         if (DSP_SUCCEEDED(status))
545                 cod_mgr_obj->loaded = true;
546         else
547                 cod_mgr_obj->base_lib = NULL;
548
549         return status;
550 }
551
552 /*
553  *  ======== cod_open ========
554  *      Open library for reading sections.
555  */
556 int cod_open(struct cod_manager *hmgr, IN char *sz_coff_path,
557                     u32 flags, struct cod_libraryobj **lib_obj)
558 {
559         int status = 0;
560         struct cod_libraryobj *lib = NULL;
561
562         DBC_REQUIRE(refs > 0);
563         DBC_REQUIRE(IS_VALID(hmgr));
564         DBC_REQUIRE(sz_coff_path != NULL);
565         DBC_REQUIRE(flags == COD_NOLOAD || flags == COD_SYMB);
566         DBC_REQUIRE(lib_obj != NULL);
567
568         *lib_obj = NULL;
569
570         lib = kzalloc(sizeof(struct cod_libraryobj), GFP_KERNEL);
571         if (lib == NULL)
572                 status = -ENOMEM;
573
574         if (DSP_SUCCEEDED(status)) {
575                 lib->cod_mgr = hmgr;
576                 status = hmgr->fxns.open_fxn(hmgr->target, sz_coff_path, flags,
577                                              &lib->dbll_lib);
578                 if (DSP_SUCCEEDED(status))
579                         *lib_obj = lib;
580         }
581
582         if (DSP_FAILED(status))
583                 pr_err("%s: error status 0x%x, sz_coff_path: %s flags: 0x%x\n",
584                        __func__, status, sz_coff_path, flags);
585         return status;
586 }
587
588 /*
589  *  ======== cod_open_base ========
590  *  Purpose:
591  *      Open base image for reading sections.
592  */
593 int cod_open_base(struct cod_manager *hmgr, IN char *sz_coff_path,
594                          dbll_flags flags)
595 {
596         int status = 0;
597         struct dbll_library_obj *lib;
598
599         DBC_REQUIRE(refs > 0);
600         DBC_REQUIRE(IS_VALID(hmgr));
601         DBC_REQUIRE(sz_coff_path != NULL);
602
603         /* if we previously opened a base image, close it now */
604         if (hmgr->base_lib) {
605                 if (hmgr->loaded) {
606                         hmgr->fxns.unload_fxn(hmgr->base_lib, &hmgr->attrs);
607                         hmgr->loaded = false;
608                 }
609                 hmgr->fxns.close_fxn(hmgr->base_lib);
610                 hmgr->base_lib = NULL;
611         }
612         status = hmgr->fxns.open_fxn(hmgr->target, sz_coff_path, flags, &lib);
613         if (DSP_SUCCEEDED(status)) {
614                 /* hang onto the library for subsequent sym table usage */
615                 hmgr->base_lib = lib;
616                 strncpy(hmgr->sz_zl_file, sz_coff_path, COD_MAXPATHLENGTH - 1);
617                 hmgr->sz_zl_file[COD_MAXPATHLENGTH - 1] = '\0';
618         }
619
620         if (DSP_FAILED(status))
621                 pr_err("%s: error status 0x%x sz_coff_path: %s\n", __func__,
622                        status, sz_coff_path);
623         return status;
624 }
625
626 /*
627  *  ======== cod_read_section ========
628  *  Purpose:
629  *      Retrieve the content of a code section given the section name.
630  */
631 int cod_read_section(struct cod_libraryobj *lib, IN char *str_sect,
632                             OUT char *str_content, IN u32 content_size)
633 {
634         int status = 0;
635
636         DBC_REQUIRE(refs > 0);
637         DBC_REQUIRE(lib != NULL);
638         DBC_REQUIRE(IS_VALID(lib->cod_mgr));
639         DBC_REQUIRE(str_sect != NULL);
640         DBC_REQUIRE(str_content != NULL);
641
642         if (lib != NULL)
643                 status =
644                     lib->cod_mgr->fxns.read_sect_fxn(lib->dbll_lib, str_sect,
645                                                      str_content, content_size);
646         else
647                 status = -ESPIPE;
648
649         return status;
650 }
651
652 /*
653  *  ======== no_op ========
654  *  Purpose:
655  *      No Operation.
656  *
657  */
658 static bool no_op(void)
659 {
660         return true;
661 }