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