staging: tidspbridge: remove OPTIONAL
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / tidspbridge / pmgr / cod.c
blobd25f8ce75e43dca2a7996f7a4f211f8108801e21
1 /*
2 * cod.c
4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
6 * This module implements DSP code management for the DSP/BIOS Bridge
7 * environment. It is mostly a thin wrapper.
9 * This module provides an interface for loading both static and
10 * dynamic code objects onto DSP systems.
12 * Copyright (C) 2005-2006 Texas Instruments, Inc.
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.
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.
23 #include <linux/types.h>
25 /* ----------------------------------- Host OS */
26 #include <dspbridge/host_os.h>
27 #include <linux/fs.h>
28 #include <linux/uaccess.h>
30 /* ----------------------------------- DSP/BIOS Bridge */
31 #include <dspbridge/dbdefs.h>
33 /* ----------------------------------- Trace & Debug */
34 #include <dspbridge/dbc.h>
36 /* ----------------------------------- OS Adaptation Layer */
37 #include <dspbridge/ldr.h>
39 /* ----------------------------------- Platform Manager */
40 /* Include appropriate loader header file */
41 #include <dspbridge/dbll.h>
43 /* ----------------------------------- This */
44 #include <dspbridge/cod.h>
46 /* magic number for handle validation */
47 #define MAGIC 0xc001beef
49 /* macro to validate COD manager handles */
50 #define IS_VALID(h) ((h) != NULL && (h)->ul_magic == MAGIC)
53 * ======== cod_manager ========
55 struct cod_manager {
56 struct dbll_tar_obj *target;
57 struct dbll_library_obj *base_lib;
58 bool loaded; /* Base library loaded? */
59 u32 ul_entry;
60 struct ldr_module *dll_obj;
61 struct dbll_fxns fxns;
62 struct dbll_attrs attrs;
63 char sz_zl_file[COD_MAXPATHLENGTH];
64 u32 ul_magic;
68 * ======== cod_libraryobj ========
70 struct cod_libraryobj {
71 struct dbll_library_obj *dbll_lib;
72 struct cod_manager *cod_mgr;
75 static u32 refs = 0L;
77 static struct dbll_fxns ldr_fxns = {
78 (dbll_close_fxn) dbll_close,
79 (dbll_create_fxn) dbll_create,
80 (dbll_delete_fxn) dbll_delete,
81 (dbll_exit_fxn) dbll_exit,
82 (dbll_get_attrs_fxn) dbll_get_attrs,
83 (dbll_get_addr_fxn) dbll_get_addr,
84 (dbll_get_c_addr_fxn) dbll_get_c_addr,
85 (dbll_get_sect_fxn) dbll_get_sect,
86 (dbll_init_fxn) dbll_init,
87 (dbll_load_fxn) dbll_load,
88 (dbll_load_sect_fxn) dbll_load_sect,
89 (dbll_open_fxn) dbll_open,
90 (dbll_read_sect_fxn) dbll_read_sect,
91 (dbll_set_attrs_fxn) dbll_set_attrs,
92 (dbll_unload_fxn) dbll_unload,
93 (dbll_unload_sect_fxn) dbll_unload_sect,
96 static bool no_op(void);
99 * File operations (originally were under kfile.c)
101 static s32 cod_f_close(struct file *filp)
103 /* Check for valid handle */
104 if (!filp)
105 return -EFAULT;
107 filp_close(filp, NULL);
109 /* we can't use 0 here */
110 return 0;
113 static struct file *cod_f_open(const char *psz_file_name, const char *sz_mode)
115 mm_segment_t fs;
116 struct file *filp;
118 fs = get_fs();
119 set_fs(get_ds());
121 /* ignore given mode and open file as read-only */
122 filp = filp_open(psz_file_name, O_RDONLY, 0);
124 if (IS_ERR(filp))
125 filp = NULL;
127 set_fs(fs);
129 return filp;
132 static s32 cod_f_read(void __user *pbuffer, s32 size, s32 count,
133 struct file *filp)
135 /* check for valid file handle */
136 if (!filp)
137 return -EFAULT;
139 if ((size > 0) && (count > 0) && pbuffer) {
140 u32 dw_bytes_read;
141 mm_segment_t fs;
143 /* read from file */
144 fs = get_fs();
145 set_fs(get_ds());
146 dw_bytes_read = filp->f_op->read(filp, pbuffer, size * count,
147 &(filp->f_pos));
148 set_fs(fs);
150 if (!dw_bytes_read)
151 return -EBADF;
153 return dw_bytes_read / size;
156 return -EINVAL;
159 static s32 cod_f_seek(struct file *filp, s32 offset, s32 origin)
161 loff_t dw_cur_pos;
163 /* check for valid file handle */
164 if (!filp)
165 return -EFAULT;
167 /* based on the origin flag, move the internal pointer */
168 dw_cur_pos = filp->f_op->llseek(filp, offset, origin);
170 if ((s32) dw_cur_pos < 0)
171 return -EPERM;
173 /* we can't use 0 here */
174 return 0;
177 static s32 cod_f_tell(struct file *filp)
179 loff_t dw_cur_pos;
181 if (!filp)
182 return -EFAULT;
184 /* Get current position */
185 dw_cur_pos = filp->f_op->llseek(filp, 0, SEEK_CUR);
187 if ((s32) dw_cur_pos < 0)
188 return -EPERM;
190 return dw_cur_pos;
194 * ======== cod_close ========
196 void cod_close(struct cod_libraryobj *lib)
198 struct cod_manager *hmgr;
200 DBC_REQUIRE(refs > 0);
201 DBC_REQUIRE(lib != NULL);
202 DBC_REQUIRE(IS_VALID(((struct cod_libraryobj *)lib)->cod_mgr));
204 hmgr = lib->cod_mgr;
205 hmgr->fxns.close_fxn(lib->dbll_lib);
207 kfree(lib);
211 * ======== cod_create ========
212 * Purpose:
213 * Create an object to manage code on a DSP system.
214 * This object can be used to load an initial program image with
215 * arguments that can later be expanded with
216 * dynamically loaded object files.
219 int cod_create(OUT struct cod_manager **mgr, char *str_zl_file,
220 const struct cod_attrs *attrs)
222 struct cod_manager *mgr_new;
223 struct dbll_attrs zl_attrs;
224 int status = 0;
226 DBC_REQUIRE(refs > 0);
227 DBC_REQUIRE(mgr != NULL);
229 /* assume failure */
230 *mgr = NULL;
232 /* we don't support non-default attrs yet */
233 if (attrs != NULL)
234 return -ENOSYS;
236 mgr_new = kzalloc(sizeof(struct cod_manager), GFP_KERNEL);
237 if (mgr_new == NULL)
238 return -ENOMEM;
240 mgr_new->ul_magic = MAGIC;
242 /* Set up loader functions */
243 mgr_new->fxns = ldr_fxns;
245 /* initialize the ZL module */
246 mgr_new->fxns.init_fxn();
248 zl_attrs.alloc = (dbll_alloc_fxn) no_op;
249 zl_attrs.free = (dbll_free_fxn) no_op;
250 zl_attrs.fread = (dbll_read_fxn) cod_f_read;
251 zl_attrs.fseek = (dbll_seek_fxn) cod_f_seek;
252 zl_attrs.ftell = (dbll_tell_fxn) cod_f_tell;
253 zl_attrs.fclose = (dbll_f_close_fxn) cod_f_close;
254 zl_attrs.fopen = (dbll_f_open_fxn) cod_f_open;
255 zl_attrs.sym_lookup = NULL;
256 zl_attrs.base_image = true;
257 zl_attrs.log_write = NULL;
258 zl_attrs.log_write_handle = NULL;
259 zl_attrs.write = NULL;
260 zl_attrs.rmm_handle = NULL;
261 zl_attrs.input_params = NULL;
262 zl_attrs.sym_handle = NULL;
263 zl_attrs.sym_arg = NULL;
265 mgr_new->attrs = zl_attrs;
267 status = mgr_new->fxns.create_fxn(&mgr_new->target, &zl_attrs);
269 if (DSP_FAILED(status)) {
270 cod_delete(mgr_new);
271 return -ESPIPE;
274 /* return the new manager */
275 *mgr = mgr_new;
277 return 0;
281 * ======== cod_delete ========
282 * Purpose:
283 * Delete a code manager object.
285 void cod_delete(struct cod_manager *cod_mgr_obj)
287 DBC_REQUIRE(refs > 0);
288 DBC_REQUIRE(IS_VALID(cod_mgr_obj));
290 if (cod_mgr_obj->base_lib) {
291 if (cod_mgr_obj->loaded)
292 cod_mgr_obj->fxns.unload_fxn(cod_mgr_obj->base_lib,
293 &cod_mgr_obj->attrs);
295 cod_mgr_obj->fxns.close_fxn(cod_mgr_obj->base_lib);
297 if (cod_mgr_obj->target) {
298 cod_mgr_obj->fxns.delete_fxn(cod_mgr_obj->target);
299 cod_mgr_obj->fxns.exit_fxn();
301 cod_mgr_obj->ul_magic = ~MAGIC;
302 kfree(cod_mgr_obj);
306 * ======== cod_exit ========
307 * Purpose:
308 * Discontinue usage of the COD module.
311 void cod_exit(void)
313 DBC_REQUIRE(refs > 0);
315 refs--;
317 DBC_ENSURE(refs >= 0);
321 * ======== cod_get_base_lib ========
322 * Purpose:
323 * Get handle to the base image DBL library.
325 int cod_get_base_lib(struct cod_manager *cod_mgr_obj,
326 struct dbll_library_obj **plib)
328 int status = 0;
330 DBC_REQUIRE(refs > 0);
331 DBC_REQUIRE(IS_VALID(cod_mgr_obj));
332 DBC_REQUIRE(plib != NULL);
334 *plib = (struct dbll_library_obj *)cod_mgr_obj->base_lib;
336 return status;
340 * ======== cod_get_base_name ========
342 int cod_get_base_name(struct cod_manager *cod_mgr_obj, char *sz_name,
343 u32 usize)
345 int status = 0;
347 DBC_REQUIRE(refs > 0);
348 DBC_REQUIRE(IS_VALID(cod_mgr_obj));
349 DBC_REQUIRE(sz_name != NULL);
351 if (usize <= COD_MAXPATHLENGTH)
352 strncpy(sz_name, cod_mgr_obj->sz_zl_file, usize);
353 else
354 status = -EPERM;
356 return status;
360 * ======== cod_get_entry ========
361 * Purpose:
362 * Retrieve the entry point of a loaded DSP program image
365 int cod_get_entry(struct cod_manager *cod_mgr_obj, u32 *entry_pt)
367 DBC_REQUIRE(refs > 0);
368 DBC_REQUIRE(IS_VALID(cod_mgr_obj));
369 DBC_REQUIRE(entry_pt != NULL);
371 *entry_pt = cod_mgr_obj->ul_entry;
373 return 0;
377 * ======== cod_get_loader ========
378 * Purpose:
379 * Get handle to the DBLL loader.
381 int cod_get_loader(struct cod_manager *cod_mgr_obj,
382 struct dbll_tar_obj **loader)
384 int status = 0;
386 DBC_REQUIRE(refs > 0);
387 DBC_REQUIRE(IS_VALID(cod_mgr_obj));
388 DBC_REQUIRE(loader != NULL);
390 *loader = (struct dbll_tar_obj *)cod_mgr_obj->target;
392 return status;
396 * ======== cod_get_section ========
397 * Purpose:
398 * Retrieve the starting address and length of a section in the COFF file
399 * given the section name.
401 int cod_get_section(struct cod_libraryobj *lib, char *str_sect,
402 OUT u32 *addr, OUT u32 *len)
404 struct cod_manager *cod_mgr_obj;
405 int status = 0;
407 DBC_REQUIRE(refs > 0);
408 DBC_REQUIRE(lib != NULL);
409 DBC_REQUIRE(IS_VALID(lib->cod_mgr));
410 DBC_REQUIRE(str_sect != NULL);
411 DBC_REQUIRE(addr != NULL);
412 DBC_REQUIRE(len != NULL);
414 *addr = 0;
415 *len = 0;
416 if (lib != NULL) {
417 cod_mgr_obj = lib->cod_mgr;
418 status = cod_mgr_obj->fxns.get_sect_fxn(lib->dbll_lib, str_sect,
419 addr, len);
420 } else {
421 status = -ESPIPE;
424 DBC_ENSURE(DSP_SUCCEEDED(status) || ((*addr == 0) && (*len == 0)));
426 return status;
430 * ======== cod_get_sym_value ========
431 * Purpose:
432 * Retrieve the value for the specified symbol. The symbol is first
433 * searched for literally and then, if not found, searched for as a
434 * C symbol.
437 int cod_get_sym_value(struct cod_manager *cod_mgr_obj, char *str_sym,
438 u32 *pul_value)
440 struct dbll_sym_val *dbll_sym;
442 DBC_REQUIRE(refs > 0);
443 DBC_REQUIRE(IS_VALID(cod_mgr_obj));
444 DBC_REQUIRE(str_sym != NULL);
445 DBC_REQUIRE(pul_value != NULL);
447 dev_dbg(bridge, "%s: cod_mgr_obj: %p str_sym: %s pul_value: %p\n",
448 __func__, cod_mgr_obj, str_sym, pul_value);
449 if (cod_mgr_obj->base_lib) {
450 if (!cod_mgr_obj->fxns.
451 get_addr_fxn(cod_mgr_obj->base_lib, str_sym, &dbll_sym)) {
452 if (!cod_mgr_obj->fxns.
453 get_c_addr_fxn(cod_mgr_obj->base_lib, str_sym,
454 &dbll_sym))
455 return -ESPIPE;
457 } else {
458 return -ESPIPE;
461 *pul_value = dbll_sym->value;
463 return 0;
467 * ======== cod_init ========
468 * Purpose:
469 * Initialize the COD module's private state.
472 bool cod_init(void)
474 bool ret = true;
476 DBC_REQUIRE(refs >= 0);
478 if (ret)
479 refs++;
481 DBC_ENSURE((ret && refs > 0) || (!ret && refs >= 0));
482 return ret;
486 * ======== cod_load_base ========
487 * Purpose:
488 * Load the initial program image, optionally with command-line arguments,
489 * on the DSP system managed by the supplied handle. The program to be
490 * loaded must be the first element of the args array and must be a fully
491 * qualified pathname.
492 * Details:
493 * if num_argc doesn't match the number of arguments in the args array, the
494 * args array is searched for a NULL terminating entry, and argc is
495 * recalculated to reflect this. In this way, we can support NULL
496 * terminating args arrays, if num_argc is very large.
498 int cod_load_base(struct cod_manager *cod_mgr_obj, u32 num_argc, char *args[],
499 cod_writefxn pfn_write, void *arb, char *envp[])
501 dbll_flags flags;
502 struct dbll_attrs save_attrs;
503 struct dbll_attrs new_attrs;
504 int status;
505 u32 i;
507 DBC_REQUIRE(refs > 0);
508 DBC_REQUIRE(IS_VALID(cod_mgr_obj));
509 DBC_REQUIRE(num_argc > 0);
510 DBC_REQUIRE(args != NULL);
511 DBC_REQUIRE(args[0] != NULL);
512 DBC_REQUIRE(pfn_write != NULL);
513 DBC_REQUIRE(cod_mgr_obj->base_lib != NULL);
516 * Make sure every argv[] stated in argc has a value, or change argc to
517 * reflect true number in NULL terminated argv array.
519 for (i = 0; i < num_argc; i++) {
520 if (args[i] == NULL) {
521 num_argc = i;
522 break;
526 /* set the write function for this operation */
527 cod_mgr_obj->fxns.get_attrs_fxn(cod_mgr_obj->target, &save_attrs);
529 new_attrs = save_attrs;
530 new_attrs.write = (dbll_write_fxn) pfn_write;
531 new_attrs.input_params = arb;
532 new_attrs.alloc = (dbll_alloc_fxn) no_op;
533 new_attrs.free = (dbll_free_fxn) no_op;
534 new_attrs.log_write = NULL;
535 new_attrs.log_write_handle = NULL;
537 /* Load the image */
538 flags = DBLL_CODE | DBLL_DATA | DBLL_SYMB;
539 status = cod_mgr_obj->fxns.load_fxn(cod_mgr_obj->base_lib, flags,
540 &new_attrs,
541 &cod_mgr_obj->ul_entry);
542 if (DSP_FAILED(status))
543 cod_mgr_obj->fxns.close_fxn(cod_mgr_obj->base_lib);
545 if (DSP_SUCCEEDED(status))
546 cod_mgr_obj->loaded = true;
547 else
548 cod_mgr_obj->base_lib = NULL;
550 return status;
554 * ======== cod_open ========
555 * Open library for reading sections.
557 int cod_open(struct cod_manager *hmgr, char *sz_coff_path,
558 u32 flags, struct cod_libraryobj **lib_obj)
560 int status = 0;
561 struct cod_libraryobj *lib = NULL;
563 DBC_REQUIRE(refs > 0);
564 DBC_REQUIRE(IS_VALID(hmgr));
565 DBC_REQUIRE(sz_coff_path != NULL);
566 DBC_REQUIRE(flags == COD_NOLOAD || flags == COD_SYMB);
567 DBC_REQUIRE(lib_obj != NULL);
569 *lib_obj = NULL;
571 lib = kzalloc(sizeof(struct cod_libraryobj), GFP_KERNEL);
572 if (lib == NULL)
573 status = -ENOMEM;
575 if (DSP_SUCCEEDED(status)) {
576 lib->cod_mgr = hmgr;
577 status = hmgr->fxns.open_fxn(hmgr->target, sz_coff_path, flags,
578 &lib->dbll_lib);
579 if (DSP_SUCCEEDED(status))
580 *lib_obj = lib;
583 if (DSP_FAILED(status))
584 pr_err("%s: error status 0x%x, sz_coff_path: %s flags: 0x%x\n",
585 __func__, status, sz_coff_path, flags);
586 return status;
590 * ======== cod_open_base ========
591 * Purpose:
592 * Open base image for reading sections.
594 int cod_open_base(struct cod_manager *hmgr, char *sz_coff_path,
595 dbll_flags flags)
597 int status = 0;
598 struct dbll_library_obj *lib;
600 DBC_REQUIRE(refs > 0);
601 DBC_REQUIRE(IS_VALID(hmgr));
602 DBC_REQUIRE(sz_coff_path != NULL);
604 /* if we previously opened a base image, close it now */
605 if (hmgr->base_lib) {
606 if (hmgr->loaded) {
607 hmgr->fxns.unload_fxn(hmgr->base_lib, &hmgr->attrs);
608 hmgr->loaded = false;
610 hmgr->fxns.close_fxn(hmgr->base_lib);
611 hmgr->base_lib = NULL;
613 status = hmgr->fxns.open_fxn(hmgr->target, sz_coff_path, flags, &lib);
614 if (DSP_SUCCEEDED(status)) {
615 /* hang onto the library for subsequent sym table usage */
616 hmgr->base_lib = lib;
617 strncpy(hmgr->sz_zl_file, sz_coff_path, COD_MAXPATHLENGTH - 1);
618 hmgr->sz_zl_file[COD_MAXPATHLENGTH - 1] = '\0';
621 if (DSP_FAILED(status))
622 pr_err("%s: error status 0x%x sz_coff_path: %s\n", __func__,
623 status, sz_coff_path);
624 return status;
628 * ======== cod_read_section ========
629 * Purpose:
630 * Retrieve the content of a code section given the section name.
632 int cod_read_section(struct cod_libraryobj *lib, char *str_sect,
633 OUT char *str_content, u32 content_size)
635 int status = 0;
637 DBC_REQUIRE(refs > 0);
638 DBC_REQUIRE(lib != NULL);
639 DBC_REQUIRE(IS_VALID(lib->cod_mgr));
640 DBC_REQUIRE(str_sect != NULL);
641 DBC_REQUIRE(str_content != NULL);
643 if (lib != NULL)
644 status =
645 lib->cod_mgr->fxns.read_sect_fxn(lib->dbll_lib, str_sect,
646 str_content, content_size);
647 else
648 status = -ESPIPE;
650 return status;
654 * ======== no_op ========
655 * Purpose:
656 * No Operation.
659 static bool no_op(void)
661 return true;