4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
6 * This file contains the implementation of the DSP/BIOS Bridge
7 * Configuration Database (DCD).
10 * The fxn dcd_get_objects can apply a callback fxn to each DCD object
11 * that is located in a specified COFF file. At the moment,
12 * dcd_auto_register, dcd_auto_unregister, and NLDR module all use
15 * Copyright (C) 2005-2006 Texas Instruments, Inc.
17 * This package is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License version 2 as
19 * published by the Free Software Foundation.
21 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
23 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
25 #include <linux/types.h>
27 /* ----------------------------------- Host OS */
28 #include <dspbridge/host_os.h>
30 /* ----------------------------------- DSP/BIOS Bridge */
31 #include <dspbridge/dbdefs.h>
33 /* ----------------------------------- Platform Manager */
34 #include <dspbridge/cod.h>
36 /* ----------------------------------- Others */
37 #include <dspbridge/uuidutil.h>
39 /* ----------------------------------- This */
40 #include <dspbridge/dbdcd.h>
42 /* ----------------------------------- Global defines. */
43 #define MAX_INT2CHAR_LENGTH 16 /* Max int2char len of 32 bit int */
45 /* Name of section containing dependent libraries */
46 #define DEPLIBSECT ".dspbridge_deplibs"
48 /* DCD specific structures. */
50 struct cod_manager
*cod_mgr
; /* Handle to COD manager object. */
53 /* Pointer to the registry support key */
54 static struct list_head reg_key_list
;
55 static DEFINE_SPINLOCK(dbdcd_lock
);
57 /* Global reference variables. */
61 /* Helper function prototypes. */
62 static s32
atoi(char *psz_buf
);
63 static int get_attrs_from_buf(char *psz_buf
, u32 ul_buf_size
,
64 enum dsp_dcdobjtype obj_type
,
65 struct dcd_genericobj
*gen_obj
);
66 static void compress_buf(char *psz_buf
, u32 ul_buf_size
, s32 char_size
);
67 static char dsp_char2_gpp_char(char *word
, s32 dsp_char_size
);
68 static int get_dep_lib_info(struct dcd_manager
*hdcd_mgr
,
69 struct dsp_uuid
*uuid_obj
,
72 struct dsp_uuid
*dep_lib_uuids
,
73 bool *prstnt_dep_libs
,
74 enum nldr_phase phase
);
77 * ======== dcd_auto_register ========
79 * Parses the supplied image and resigsters with DCD.
81 int dcd_auto_register(struct dcd_manager
*hdcd_mgr
,
87 status
= dcd_get_objects(hdcd_mgr
, sz_coff_path
,
88 (dcd_registerfxn
) dcd_register_object
,
89 (void *)sz_coff_path
);
97 * ======== dcd_auto_unregister ========
99 * Parses the supplied DSP image and unresiters from DCD.
101 int dcd_auto_unregister(struct dcd_manager
*hdcd_mgr
,
107 status
= dcd_get_objects(hdcd_mgr
, sz_coff_path
,
108 (dcd_registerfxn
) dcd_register_object
,
117 * ======== dcd_create_manager ========
119 * Creates DCD manager.
121 int dcd_create_manager(char *sz_zl_dll_name
,
122 struct dcd_manager
**dcd_mgr
)
124 struct cod_manager
*cod_mgr
; /* COD manager handle */
125 struct dcd_manager
*dcd_mgr_obj
= NULL
; /* DCD Manager pointer */
128 status
= cod_create(&cod_mgr
, sz_zl_dll_name
);
132 /* Create a DCD object. */
133 dcd_mgr_obj
= kzalloc(sizeof(struct dcd_manager
), GFP_KERNEL
);
134 if (dcd_mgr_obj
!= NULL
) {
135 /* Fill out the object. */
136 dcd_mgr_obj
->cod_mgr
= cod_mgr
;
138 /* Return handle to this DCD interface. */
139 *dcd_mgr
= dcd_mgr_obj
;
144 * If allocation of DcdManager object failed, delete the
155 * ======== dcd_destroy_manager ========
157 * Frees DCD Manager object.
159 int dcd_destroy_manager(struct dcd_manager
*hdcd_mgr
)
161 struct dcd_manager
*dcd_mgr_obj
= hdcd_mgr
;
162 int status
= -EFAULT
;
165 /* Delete the COD manager. */
166 cod_delete(dcd_mgr_obj
->cod_mgr
);
168 /* Deallocate a DCD manager object. */
178 * ======== dcd_enumerate_object ========
180 * Enumerates objects in the DCD.
182 int dcd_enumerate_object(s32 index
, enum dsp_dcdobjtype obj_type
,
183 struct dsp_uuid
*uuid_obj
)
186 char sz_reg_key
[DCD_MAXPATHLENGTH
];
187 char sz_value
[DCD_MAXPATHLENGTH
];
188 struct dsp_uuid dsp_uuid_obj
;
189 char sz_obj_type
[MAX_INT2CHAR_LENGTH
]; /* str. rep. of obj_type. */
191 struct dcd_key_elem
*dcd_key
;
194 if ((index
!= 0) && (enum_refs
== 0)) {
196 * If an enumeration is being performed on an index greater
197 * than zero, then the current enum_refs must have been
198 * incremented to greater than zero.
203 * Pre-determine final key length. It's length of DCD_REGKEY +
204 * "_\0" + length of sz_obj_type string + terminating NULL.
206 dw_key_len
= strlen(DCD_REGKEY
) + 1 + sizeof(sz_obj_type
) + 1;
208 /* Create proper REG key; concatenate DCD_REGKEY with
210 strncpy(sz_reg_key
, DCD_REGKEY
, strlen(DCD_REGKEY
) + 1);
211 if ((strlen(sz_reg_key
) + strlen("_\0")) <
213 strncat(sz_reg_key
, "_\0", 2);
218 /* This snprintf is guaranteed not to exceed max size of an
220 status
= snprintf(sz_obj_type
, MAX_INT2CHAR_LENGTH
, "%d",
227 if ((strlen(sz_reg_key
) + strlen(sz_obj_type
)) <
229 strncat(sz_reg_key
, sz_obj_type
,
230 strlen(sz_obj_type
) + 1);
237 len
= strlen(sz_reg_key
);
238 spin_lock(&dbdcd_lock
);
239 list_for_each_entry(dcd_key
, ®_key_list
, link
) {
240 if (!strncmp(dcd_key
->name
, sz_reg_key
, len
)
242 strncpy(sz_value
, &dcd_key
->name
[len
],
243 strlen(&dcd_key
->name
[len
]) + 1);
247 spin_unlock(&dbdcd_lock
);
249 if (&dcd_key
->link
== ®_key_list
)
254 /* Create UUID value using string retrieved from
256 uuid_uuid_from_string(sz_value
, &dsp_uuid_obj
);
258 *uuid_obj
= dsp_uuid_obj
;
260 /* Increment enum_refs to update reference count. */
264 } else if (status
== -ENODATA
) {
265 /* At the end of enumeration. Reset enum_refs. */
269 * TODO: Revisit, this is not an error case but code
270 * expects non-zero value.
282 * ======== dcd_exit ========
284 * Discontinue usage of the DCD module.
288 struct dcd_key_elem
*rv
, *rv_tmp
;
292 list_for_each_entry_safe(rv
, rv_tmp
, ®_key_list
, link
) {
302 * ======== dcd_get_dep_libs ========
304 int dcd_get_dep_libs(struct dcd_manager
*hdcd_mgr
,
305 struct dsp_uuid
*uuid_obj
,
306 u16 num_libs
, struct dsp_uuid
*dep_lib_uuids
,
307 bool *prstnt_dep_libs
,
308 enum nldr_phase phase
)
313 get_dep_lib_info(hdcd_mgr
, uuid_obj
, &num_libs
, NULL
, dep_lib_uuids
,
314 prstnt_dep_libs
, phase
);
320 * ======== dcd_get_num_dep_libs ========
322 int dcd_get_num_dep_libs(struct dcd_manager
*hdcd_mgr
,
323 struct dsp_uuid
*uuid_obj
,
324 u16
*num_libs
, u16
*num_pers_libs
,
325 enum nldr_phase phase
)
329 status
= get_dep_lib_info(hdcd_mgr
, uuid_obj
, num_libs
, num_pers_libs
,
336 * ======== dcd_get_object_def ========
338 * Retrieves the properties of a node or processor based on the UUID and
341 int dcd_get_object_def(struct dcd_manager
*hdcd_mgr
,
342 struct dsp_uuid
*obj_uuid
,
343 enum dsp_dcdobjtype obj_type
,
344 struct dcd_genericobj
*obj_def
)
346 struct dcd_manager
*dcd_mgr_obj
= hdcd_mgr
; /* ptr to DCD mgr */
347 struct cod_libraryobj
*lib
= NULL
;
350 u32 ul_addr
= 0; /* Used by cod_get_section */
351 u32 ul_len
= 0; /* Used by cod_get_section */
352 u32 dw_buf_size
; /* Used by REG functions */
353 char sz_reg_key
[DCD_MAXPATHLENGTH
];
354 char *sz_uuid
; /*[MAXUUIDLEN]; */
356 struct dcd_key_elem
*dcd_key
= NULL
;
357 char sz_sect_name
[MAXUUIDLEN
+ 2]; /* ".[UUID]\0" */
359 u32 dw_key_len
; /* Len of REG key. */
360 char sz_obj_type
[MAX_INT2CHAR_LENGTH
]; /* str. rep. of obj_type. */
362 sz_uuid
= kzalloc(MAXUUIDLEN
, GFP_KERNEL
);
373 /* Pre-determine final key length. It's length of DCD_REGKEY +
374 * "_\0" + length of sz_obj_type string + terminating NULL */
375 dw_key_len
= strlen(DCD_REGKEY
) + 1 + sizeof(sz_obj_type
) + 1;
377 /* Create proper REG key; concatenate DCD_REGKEY with obj_type. */
378 strncpy(sz_reg_key
, DCD_REGKEY
, strlen(DCD_REGKEY
) + 1);
380 if ((strlen(sz_reg_key
) + strlen("_\0")) < DCD_MAXPATHLENGTH
)
381 strncat(sz_reg_key
, "_\0", 2);
385 status
= snprintf(sz_obj_type
, MAX_INT2CHAR_LENGTH
, "%d", obj_type
);
391 if ((strlen(sz_reg_key
) + strlen(sz_obj_type
)) <
393 strncat(sz_reg_key
, sz_obj_type
,
394 strlen(sz_obj_type
) + 1);
399 /* Create UUID value to set in registry. */
400 snprintf(sz_uuid
, MAXUUIDLEN
, "%pUL", obj_uuid
);
402 if ((strlen(sz_reg_key
) + MAXUUIDLEN
) < DCD_MAXPATHLENGTH
)
403 strncat(sz_reg_key
, sz_uuid
, MAXUUIDLEN
);
407 /* Retrieve paths from the registry based on struct dsp_uuid */
408 dw_buf_size
= DCD_MAXPATHLENGTH
;
411 spin_lock(&dbdcd_lock
);
412 list_for_each_entry(dcd_key
, ®_key_list
, link
) {
413 if (!strncmp(dcd_key
->name
, sz_reg_key
,
414 strlen(sz_reg_key
) + 1))
417 spin_unlock(&dbdcd_lock
);
418 if (&dcd_key
->link
== ®_key_list
) {
425 /* Open COFF file. */
426 status
= cod_open(dcd_mgr_obj
->cod_mgr
, dcd_key
->path
,
433 /* Ensure sz_uuid + 1 is not greater than sizeof sz_sect_name. */
434 len
= strlen(sz_uuid
);
435 if (len
+ 1 > sizeof(sz_sect_name
)) {
440 /* Create section name based on node UUID. A period is
441 * pre-pended to the UUID string to form the section name.
442 * I.e. ".24BC8D90_BB45_11d4_B756_006008BDB66F" */
444 len
-= 4; /* uuid has 4 delimiters '-' */
447 strncpy(sz_sect_name
, ".", 2);
449 char *uuid
= strsep(&tmp
, "-");
453 strncat(sz_sect_name
, uuid
, strlen(uuid
) + 1);
454 } while (len
&& strncat(sz_sect_name
, "_", 2));
456 /* Get section information. */
457 status
= cod_get_section(lib
, sz_sect_name
, &ul_addr
, &ul_len
);
463 /* Allocate zeroed buffer. */
464 psz_coff_buf
= kzalloc(ul_len
+ 4, GFP_KERNEL
);
465 if (psz_coff_buf
== NULL
) {
470 if (strstr(dcd_key
->path
, "iva") == NULL
) {
471 /* Locate section by objectID and read its content. */
473 cod_read_section(lib
, sz_sect_name
, psz_coff_buf
, ul_len
);
476 cod_read_section(lib
, sz_sect_name
, psz_coff_buf
, ul_len
);
477 dev_dbg(bridge
, "%s: Skipped Byte swap for IVA!!\n", __func__
);
480 status
= cod_read_section(lib
, sz_sect_name
, psz_coff_buf
, ul_len
);
483 /* Compress DSP buffer to conform to PC format. */
484 if (strstr(dcd_key
->path
, "iva") == NULL
) {
485 compress_buf(psz_coff_buf
, ul_len
, DSPWORDSIZE
);
487 compress_buf(psz_coff_buf
, ul_len
, 1);
488 dev_dbg(bridge
, "%s: Compressing IVA COFF buffer by 1 "
489 "for IVA!!\n", __func__
);
492 /* Parse the content of the COFF buffer. */
494 get_attrs_from_buf(psz_coff_buf
, ul_len
, obj_type
, obj_def
);
501 /* Free the previously allocated dynamic buffer. */
513 * ======== dcd_get_objects ========
515 int dcd_get_objects(struct dcd_manager
*hdcd_mgr
,
516 char *sz_coff_path
, dcd_registerfxn register_fxn
,
519 struct dcd_manager
*dcd_mgr_obj
= hdcd_mgr
;
523 struct cod_libraryobj
*lib
= NULL
;
524 u32 ul_addr
= 0; /* Used by cod_get_section */
525 u32 ul_len
= 0; /* Used by cod_get_section */
528 struct dsp_uuid dsp_uuid_obj
;
536 /* Open DSP coff file, don't load symbols. */
537 status
= cod_open(dcd_mgr_obj
->cod_mgr
, sz_coff_path
, COD_NOLOAD
, &lib
);
543 /* Get DCD_RESIGER_SECTION section information. */
544 status
= cod_get_section(lib
, DCD_REGISTER_SECTION
, &ul_addr
, &ul_len
);
545 if (status
|| !(ul_len
> 0)) {
550 /* Allocate zeroed buffer. */
551 psz_coff_buf
= kzalloc(ul_len
+ 4, GFP_KERNEL
);
552 if (psz_coff_buf
== NULL
) {
557 if (strstr(sz_coff_path
, "iva") == NULL
) {
558 /* Locate section by objectID and read its content. */
559 status
= cod_read_section(lib
, DCD_REGISTER_SECTION
,
560 psz_coff_buf
, ul_len
);
562 dev_dbg(bridge
, "%s: Skipped Byte swap for IVA!!\n", __func__
);
563 status
= cod_read_section(lib
, DCD_REGISTER_SECTION
,
564 psz_coff_buf
, ul_len
);
568 cod_read_section(lib
, DCD_REGISTER_SECTION
, psz_coff_buf
, ul_len
);
571 /* Compress DSP buffer to conform to PC format. */
572 if (strstr(sz_coff_path
, "iva") == NULL
) {
573 compress_buf(psz_coff_buf
, ul_len
, DSPWORDSIZE
);
575 compress_buf(psz_coff_buf
, ul_len
, 1);
576 dev_dbg(bridge
, "%s: Compress COFF buffer with 1 word "
577 "for IVA!!\n", __func__
);
580 /* Read from buffer and register object in buffer. */
581 psz_cur
= psz_coff_buf
;
582 while ((token
= strsep(&psz_cur
, seps
)) && *token
!= '\0') {
583 /* Retrieve UUID string. */
584 uuid_uuid_from_string(token
, &dsp_uuid_obj
);
586 /* Retrieve object type */
587 token
= strsep(&psz_cur
, seps
);
589 /* Retrieve object type */
590 object_type
= atoi(token
);
593 * Apply register_fxn to the found DCD object.
594 * Possible actions include:
596 * 1) Register found DCD object.
597 * 2) Unregister found DCD object (when handle == NULL)
598 * 3) Add overlay node.
601 register_fxn(&dsp_uuid_obj
, object_type
, handle
);
603 /* if error occurs, break from while loop. */
611 /* Free the previously allocated dynamic buffer. */
622 * ======== dcd_get_library_name ========
624 * Retrieves the library name for the given UUID.
627 int dcd_get_library_name(struct dcd_manager
*hdcd_mgr
,
628 struct dsp_uuid
*uuid_obj
,
631 enum nldr_phase phase
, bool *phase_split
)
633 char sz_reg_key
[DCD_MAXPATHLENGTH
];
634 char sz_uuid
[MAXUUIDLEN
];
635 u32 dw_key_len
; /* Len of REG key. */
636 char sz_obj_type
[MAX_INT2CHAR_LENGTH
]; /* str. rep. of obj_type. */
638 struct dcd_key_elem
*dcd_key
= NULL
;
640 dev_dbg(bridge
, "%s: hdcd_mgr %p, uuid_obj %p, str_lib_name %p,"
641 " buff_size %p\n", __func__
, hdcd_mgr
, uuid_obj
, str_lib_name
,
645 * Pre-determine final key length. It's length of DCD_REGKEY +
646 * "_\0" + length of sz_obj_type string + terminating NULL.
648 dw_key_len
= strlen(DCD_REGKEY
) + 1 + sizeof(sz_obj_type
) + 1;
650 /* Create proper REG key; concatenate DCD_REGKEY with obj_type. */
651 strncpy(sz_reg_key
, DCD_REGKEY
, strlen(DCD_REGKEY
) + 1);
652 if ((strlen(sz_reg_key
) + strlen("_\0")) < DCD_MAXPATHLENGTH
)
653 strncat(sz_reg_key
, "_\0", 2);
659 /* create phase type */
660 sprintf(sz_obj_type
, "%d", DSP_DCDCREATELIBTYPE
);
663 /* execute phase type */
664 sprintf(sz_obj_type
, "%d", DSP_DCDEXECUTELIBTYPE
);
667 /* delete phase type */
668 sprintf(sz_obj_type
, "%d", DSP_DCDDELETELIBTYPE
);
671 /* known to be a dependent library */
672 sprintf(sz_obj_type
, "%d", DSP_DCDLIBRARYTYPE
);
678 if ((strlen(sz_reg_key
) + strlen(sz_obj_type
)) <
680 strncat(sz_reg_key
, sz_obj_type
,
681 strlen(sz_obj_type
) + 1);
685 /* Create UUID value to find match in registry. */
686 snprintf(sz_uuid
, MAXUUIDLEN
, "%pUL", uuid_obj
);
687 if ((strlen(sz_reg_key
) + MAXUUIDLEN
) < DCD_MAXPATHLENGTH
)
688 strncat(sz_reg_key
, sz_uuid
, MAXUUIDLEN
);
693 spin_lock(&dbdcd_lock
);
694 list_for_each_entry(dcd_key
, ®_key_list
, link
) {
695 /* See if the name matches. */
696 if (!strncmp(dcd_key
->name
, sz_reg_key
,
697 strlen(sz_reg_key
) + 1))
700 spin_unlock(&dbdcd_lock
);
703 if (&dcd_key
->link
== ®_key_list
)
706 /* If can't find, phases might be registered as generic LIBRARYTYPE */
707 if (status
&& phase
!= NLDR_NOPHASE
) {
709 *phase_split
= false;
711 strncpy(sz_reg_key
, DCD_REGKEY
, strlen(DCD_REGKEY
) + 1);
712 if ((strlen(sz_reg_key
) + strlen("_\0")) <
714 strncat(sz_reg_key
, "_\0", 2);
718 sprintf(sz_obj_type
, "%d", DSP_DCDLIBRARYTYPE
);
719 if ((strlen(sz_reg_key
) + strlen(sz_obj_type
))
720 < DCD_MAXPATHLENGTH
) {
721 strncat(sz_reg_key
, sz_obj_type
,
722 strlen(sz_obj_type
) + 1);
726 snprintf(sz_uuid
, MAXUUIDLEN
, "%pUL", uuid_obj
);
727 if ((strlen(sz_reg_key
) + MAXUUIDLEN
) < DCD_MAXPATHLENGTH
)
728 strncat(sz_reg_key
, sz_uuid
, MAXUUIDLEN
);
732 spin_lock(&dbdcd_lock
);
733 list_for_each_entry(dcd_key
, ®_key_list
, link
) {
734 /* See if the name matches. */
735 if (!strncmp(dcd_key
->name
, sz_reg_key
,
736 strlen(sz_reg_key
) + 1))
739 spin_unlock(&dbdcd_lock
);
741 status
= (&dcd_key
->link
!= ®_key_list
) ?
746 memcpy(str_lib_name
, dcd_key
->path
, strlen(dcd_key
->path
) + 1);
751 * ======== dcd_init ========
753 * Initialize the DCD module.
760 INIT_LIST_HEAD(®_key_list
);
769 * ======== dcd_register_object ========
771 * Registers a node or a processor with the DCD.
772 * If psz_path_name == NULL, unregister the specified DCD object.
774 int dcd_register_object(struct dsp_uuid
*uuid_obj
,
775 enum dsp_dcdobjtype obj_type
,
779 char sz_reg_key
[DCD_MAXPATHLENGTH
];
780 char sz_uuid
[MAXUUIDLEN
+ 1];
781 u32 dw_path_size
= 0;
782 u32 dw_key_len
; /* Len of REG key. */
783 char sz_obj_type
[MAX_INT2CHAR_LENGTH
]; /* str. rep. of obj_type. */
784 struct dcd_key_elem
*dcd_key
= NULL
;
786 dev_dbg(bridge
, "%s: object UUID %p, obj_type %d, szPathName %s\n",
787 __func__
, uuid_obj
, obj_type
, psz_path_name
);
790 * Pre-determine final key length. It's length of DCD_REGKEY +
791 * "_\0" + length of sz_obj_type string + terminating NULL.
793 dw_key_len
= strlen(DCD_REGKEY
) + 1 + sizeof(sz_obj_type
) + 1;
795 /* Create proper REG key; concatenate DCD_REGKEY with obj_type. */
796 strncpy(sz_reg_key
, DCD_REGKEY
, strlen(DCD_REGKEY
) + 1);
797 if ((strlen(sz_reg_key
) + strlen("_\0")) < DCD_MAXPATHLENGTH
)
798 strncat(sz_reg_key
, "_\0", 2);
804 status
= snprintf(sz_obj_type
, MAX_INT2CHAR_LENGTH
, "%d", obj_type
);
809 if ((strlen(sz_reg_key
) + strlen(sz_obj_type
)) <
811 strncat(sz_reg_key
, sz_obj_type
,
812 strlen(sz_obj_type
) + 1);
816 /* Create UUID value to set in registry. */
817 snprintf(sz_uuid
, MAXUUIDLEN
, "%pUL", uuid_obj
);
818 if ((strlen(sz_reg_key
) + MAXUUIDLEN
) < DCD_MAXPATHLENGTH
)
819 strncat(sz_reg_key
, sz_uuid
, MAXUUIDLEN
);
828 * If psz_path_name != NULL, perform registration, otherwise,
829 * perform unregistration.
833 dw_path_size
= strlen(psz_path_name
) + 1;
834 spin_lock(&dbdcd_lock
);
835 list_for_each_entry(dcd_key
, ®_key_list
, link
) {
836 /* See if the name matches. */
837 if (!strncmp(dcd_key
->name
, sz_reg_key
,
838 strlen(sz_reg_key
) + 1))
841 spin_unlock(&dbdcd_lock
);
842 if (&dcd_key
->link
== ®_key_list
) {
844 * Add new reg value (UUID+obj_type)
845 * with COFF path info
848 dcd_key
= kmalloc(sizeof(struct dcd_key_elem
),
855 dcd_key
->path
= kmalloc(dw_path_size
, GFP_KERNEL
);
857 if (!dcd_key
->path
) {
863 strncpy(dcd_key
->name
, sz_reg_key
,
864 strlen(sz_reg_key
) + 1);
865 strncpy(dcd_key
->path
, psz_path_name
,
867 spin_lock(&dbdcd_lock
);
868 list_add_tail(&dcd_key
->link
, ®_key_list
);
869 spin_unlock(&dbdcd_lock
);
871 /* Make sure the new data is the same. */
872 if (strncmp(dcd_key
->path
, psz_path_name
,
874 /* The caller needs a different data size! */
875 kfree(dcd_key
->path
);
876 dcd_key
->path
= kmalloc(dw_path_size
,
878 if (dcd_key
->path
== NULL
) {
884 /* We have a match! Copy out the data. */
885 memcpy(dcd_key
->path
, psz_path_name
, dw_path_size
);
887 dev_dbg(bridge
, "%s: psz_path_name=%s, dw_path_size=%d\n",
888 __func__
, psz_path_name
, dw_path_size
);
890 /* Deregister an existing object */
891 spin_lock(&dbdcd_lock
);
892 list_for_each_entry(dcd_key
, ®_key_list
, link
) {
893 if (!strncmp(dcd_key
->name
, sz_reg_key
,
894 strlen(sz_reg_key
) + 1)) {
895 list_del(&dcd_key
->link
);
896 kfree(dcd_key
->path
);
901 spin_unlock(&dbdcd_lock
);
902 if (&dcd_key
->link
== ®_key_list
)
908 * Because the node database has been updated through a
909 * successful object registration/de-registration operation,
910 * we need to reset the object enumeration counter to allow
911 * current enumerations to reflect this update in the node
921 * ======== dcd_unregister_object ========
922 * Call DCD_Register object with psz_path_name set to NULL to
923 * perform actual object de-registration.
925 int dcd_unregister_object(struct dsp_uuid
*uuid_obj
,
926 enum dsp_dcdobjtype obj_type
)
931 * When dcd_register_object is called with NULL as pathname,
932 * it indicates an unregister object operation.
934 status
= dcd_register_object(uuid_obj
, obj_type
, NULL
);
940 **********************************************************************
941 * DCD Helper Functions
942 **********************************************************************
946 * ======== atoi ========
948 * This function converts strings in decimal or hex format to integers.
950 static s32
atoi(char *psz_buf
)
955 while (isspace(*pch
))
958 if (*pch
== '-' || *pch
== '+') {
961 } else if (*pch
&& tolower(pch
[strlen(pch
) - 1]) == 'h') {
965 return simple_strtoul(pch
, NULL
, base
);
969 * ======== get_attrs_from_buf ========
971 * Parse the content of a buffer filled with DSP-side data and
972 * retrieve an object's attributes from it. IMPORTANT: Assume the
973 * buffer has been converted from DSP format to GPP format.
975 static int get_attrs_from_buf(char *psz_buf
, u32 ul_buf_size
,
976 enum dsp_dcdobjtype obj_type
,
977 struct dcd_genericobj
*gen_obj
)
990 case DSP_DCDNODETYPE
:
992 * Parse COFF sect buffer to retrieve individual tokens used
993 * to fill in object attrs.
996 token
= strsep(&psz_cur
, seps
);
999 gen_obj
->obj_data
.node_obj
.ndb_props
.cb_struct
=
1001 token
= strsep(&psz_cur
, seps
);
1003 /* dsp_uuid ui_node_id */
1004 uuid_uuid_from_string(token
,
1005 &gen_obj
->obj_data
.node_obj
.ndb_props
.
1007 token
= strsep(&psz_cur
, seps
);
1010 token_len
= strlen(token
);
1011 if (token_len
> DSP_MAXNAMELEN
- 1)
1012 token_len
= DSP_MAXNAMELEN
- 1;
1014 strncpy(gen_obj
->obj_data
.node_obj
.ndb_props
.ac_name
,
1016 gen_obj
->obj_data
.node_obj
.ndb_props
.ac_name
[token_len
] = '\0';
1017 token
= strsep(&psz_cur
, seps
);
1019 gen_obj
->obj_data
.node_obj
.ndb_props
.ntype
= atoi(token
);
1020 token
= strsep(&psz_cur
, seps
);
1021 /* u32 cache_on_gpp */
1022 gen_obj
->obj_data
.node_obj
.ndb_props
.cache_on_gpp
= atoi(token
);
1023 token
= strsep(&psz_cur
, seps
);
1024 /* dsp_resourcereqmts dsp_resource_reqmts */
1025 gen_obj
->obj_data
.node_obj
.ndb_props
.dsp_resource_reqmts
.
1026 cb_struct
= (u32
) atoi(token
);
1027 token
= strsep(&psz_cur
, seps
);
1029 gen_obj
->obj_data
.node_obj
.ndb_props
.
1030 dsp_resource_reqmts
.static_data_size
= atoi(token
);
1031 token
= strsep(&psz_cur
, seps
);
1032 gen_obj
->obj_data
.node_obj
.ndb_props
.
1033 dsp_resource_reqmts
.global_data_size
= atoi(token
);
1034 token
= strsep(&psz_cur
, seps
);
1035 gen_obj
->obj_data
.node_obj
.ndb_props
.
1036 dsp_resource_reqmts
.program_mem_size
= atoi(token
);
1037 token
= strsep(&psz_cur
, seps
);
1038 gen_obj
->obj_data
.node_obj
.ndb_props
.
1039 dsp_resource_reqmts
.wc_execution_time
= atoi(token
);
1040 token
= strsep(&psz_cur
, seps
);
1041 gen_obj
->obj_data
.node_obj
.ndb_props
.
1042 dsp_resource_reqmts
.wc_period
= atoi(token
);
1043 token
= strsep(&psz_cur
, seps
);
1045 gen_obj
->obj_data
.node_obj
.ndb_props
.
1046 dsp_resource_reqmts
.wc_deadline
= atoi(token
);
1047 token
= strsep(&psz_cur
, seps
);
1049 gen_obj
->obj_data
.node_obj
.ndb_props
.
1050 dsp_resource_reqmts
.avg_exection_time
= atoi(token
);
1051 token
= strsep(&psz_cur
, seps
);
1053 gen_obj
->obj_data
.node_obj
.ndb_props
.
1054 dsp_resource_reqmts
.minimum_period
= atoi(token
);
1055 token
= strsep(&psz_cur
, seps
);
1058 gen_obj
->obj_data
.node_obj
.ndb_props
.prio
= atoi(token
);
1059 token
= strsep(&psz_cur
, seps
);
1061 /* u32 stack_size */
1062 gen_obj
->obj_data
.node_obj
.ndb_props
.stack_size
= atoi(token
);
1063 token
= strsep(&psz_cur
, seps
);
1065 /* u32 sys_stack_size */
1066 gen_obj
->obj_data
.node_obj
.ndb_props
.sys_stack_size
=
1068 token
= strsep(&psz_cur
, seps
);
1071 gen_obj
->obj_data
.node_obj
.ndb_props
.stack_seg
= atoi(token
);
1072 token
= strsep(&psz_cur
, seps
);
1074 /* u32 message_depth */
1075 gen_obj
->obj_data
.node_obj
.ndb_props
.message_depth
=
1077 token
= strsep(&psz_cur
, seps
);
1079 /* u32 num_input_streams */
1080 gen_obj
->obj_data
.node_obj
.ndb_props
.num_input_streams
=
1082 token
= strsep(&psz_cur
, seps
);
1084 /* u32 num_output_streams */
1085 gen_obj
->obj_data
.node_obj
.ndb_props
.num_output_streams
=
1087 token
= strsep(&psz_cur
, seps
);
1090 gen_obj
->obj_data
.node_obj
.ndb_props
.timeout
= atoi(token
);
1091 token
= strsep(&psz_cur
, seps
);
1093 /* char *str_create_phase_fxn */
1094 token_len
= strlen(token
);
1095 gen_obj
->obj_data
.node_obj
.str_create_phase_fxn
=
1096 kzalloc(token_len
+ 1, GFP_KERNEL
);
1097 strncpy(gen_obj
->obj_data
.node_obj
.str_create_phase_fxn
,
1099 gen_obj
->obj_data
.node_obj
.str_create_phase_fxn
[token_len
] =
1101 token
= strsep(&psz_cur
, seps
);
1103 /* char *str_execute_phase_fxn */
1104 token_len
= strlen(token
);
1105 gen_obj
->obj_data
.node_obj
.str_execute_phase_fxn
=
1106 kzalloc(token_len
+ 1, GFP_KERNEL
);
1107 strncpy(gen_obj
->obj_data
.node_obj
.str_execute_phase_fxn
,
1109 gen_obj
->obj_data
.node_obj
.str_execute_phase_fxn
[token_len
] =
1111 token
= strsep(&psz_cur
, seps
);
1113 /* char *str_delete_phase_fxn */
1114 token_len
= strlen(token
);
1115 gen_obj
->obj_data
.node_obj
.str_delete_phase_fxn
=
1116 kzalloc(token_len
+ 1, GFP_KERNEL
);
1117 strncpy(gen_obj
->obj_data
.node_obj
.str_delete_phase_fxn
,
1119 gen_obj
->obj_data
.node_obj
.str_delete_phase_fxn
[token_len
] =
1121 token
= strsep(&psz_cur
, seps
);
1123 /* Segment id for message buffers */
1124 gen_obj
->obj_data
.node_obj
.msg_segid
= atoi(token
);
1125 token
= strsep(&psz_cur
, seps
);
1127 /* Message notification type */
1128 gen_obj
->obj_data
.node_obj
.msg_notify_type
= atoi(token
);
1129 token
= strsep(&psz_cur
, seps
);
1131 /* char *str_i_alg_name */
1133 token_len
= strlen(token
);
1134 gen_obj
->obj_data
.node_obj
.str_i_alg_name
=
1135 kzalloc(token_len
+ 1, GFP_KERNEL
);
1136 strncpy(gen_obj
->obj_data
.node_obj
.str_i_alg_name
,
1138 gen_obj
->obj_data
.node_obj
.str_i_alg_name
[token_len
] =
1140 token
= strsep(&psz_cur
, seps
);
1143 /* Load type (static, dynamic, or overlay) */
1145 gen_obj
->obj_data
.node_obj
.load_type
= atoi(token
);
1146 token
= strsep(&psz_cur
, seps
);
1149 /* Dynamic load data requirements */
1151 gen_obj
->obj_data
.node_obj
.data_mem_seg_mask
=
1153 token
= strsep(&psz_cur
, seps
);
1156 /* Dynamic load code requirements */
1158 gen_obj
->obj_data
.node_obj
.code_mem_seg_mask
=
1160 token
= strsep(&psz_cur
, seps
);
1163 /* Extract node profiles into node properties */
1166 gen_obj
->obj_data
.node_obj
.ndb_props
.count_profiles
=
1170 gen_obj
->obj_data
.node_obj
.
1171 ndb_props
.count_profiles
; i
++) {
1172 token
= strsep(&psz_cur
, seps
);
1174 /* Heap Size for the node */
1175 gen_obj
->obj_data
.node_obj
.
1176 ndb_props
.node_profiles
[i
].
1177 heap_size
= atoi(token
);
1181 token
= strsep(&psz_cur
, seps
);
1183 gen_obj
->obj_data
.node_obj
.ndb_props
.stack_seg_name
=
1189 case DSP_DCDPROCESSORTYPE
:
1191 * Parse COFF sect buffer to retrieve individual tokens used
1192 * to fill in object attrs.
1195 token
= strsep(&psz_cur
, seps
);
1197 gen_obj
->obj_data
.proc_info
.cb_struct
= atoi(token
);
1198 token
= strsep(&psz_cur
, seps
);
1200 gen_obj
->obj_data
.proc_info
.processor_family
= atoi(token
);
1201 token
= strsep(&psz_cur
, seps
);
1203 gen_obj
->obj_data
.proc_info
.processor_type
= atoi(token
);
1204 token
= strsep(&psz_cur
, seps
);
1206 gen_obj
->obj_data
.proc_info
.clock_rate
= atoi(token
);
1207 token
= strsep(&psz_cur
, seps
);
1209 gen_obj
->obj_data
.proc_info
.internal_mem_size
= atoi(token
);
1210 token
= strsep(&psz_cur
, seps
);
1212 gen_obj
->obj_data
.proc_info
.external_mem_size
= atoi(token
);
1213 token
= strsep(&psz_cur
, seps
);
1215 gen_obj
->obj_data
.proc_info
.processor_id
= atoi(token
);
1216 token
= strsep(&psz_cur
, seps
);
1218 gen_obj
->obj_data
.proc_info
.ty_running_rtos
= atoi(token
);
1219 token
= strsep(&psz_cur
, seps
);
1221 gen_obj
->obj_data
.proc_info
.node_min_priority
= atoi(token
);
1222 token
= strsep(&psz_cur
, seps
);
1224 gen_obj
->obj_data
.proc_info
.node_max_priority
= atoi(token
);
1227 /* Proc object may contain additional(extended) attributes. */
1228 /* attr must match proc.hxx */
1229 for (entry_id
= 0; entry_id
< 7; entry_id
++) {
1230 token
= strsep(&psz_cur
, seps
);
1231 gen_obj
->obj_data
.ext_proc_obj
.ty_tlb
[entry_id
].
1232 gpp_phys
= atoi(token
);
1234 token
= strsep(&psz_cur
, seps
);
1235 gen_obj
->obj_data
.ext_proc_obj
.ty_tlb
[entry_id
].
1236 dsp_virt
= atoi(token
);
1251 * ======== CompressBuffer ========
1253 * Compress the DSP buffer, if necessary, to conform to PC format.
1255 static void compress_buf(char *psz_buf
, u32 ul_buf_size
, s32 char_size
)
1265 for (q
= psz_buf
; q
< (psz_buf
+ ul_buf_size
);) {
1266 ch
= dsp_char2_gpp_char(q
, char_size
);
1269 ch
= dsp_char2_gpp_char(q
, char_size
);
1298 /* NULL out remainder of buffer. */
1304 * ======== dsp_char2_gpp_char ========
1306 * Convert DSP char to host GPP char in a portable manner
1308 static char dsp_char2_gpp_char(char *word
, s32 dsp_char_size
)
1314 for (ch_src
= word
, i
= dsp_char_size
; i
> 0; i
--)
1321 * ======== get_dep_lib_info ========
1323 static int get_dep_lib_info(struct dcd_manager
*hdcd_mgr
,
1324 struct dsp_uuid
*uuid_obj
,
1327 struct dsp_uuid
*dep_lib_uuids
,
1328 bool *prstnt_dep_libs
,
1329 enum nldr_phase phase
)
1331 struct dcd_manager
*dcd_mgr_obj
= hdcd_mgr
;
1332 char *psz_coff_buf
= NULL
;
1334 char *psz_file_name
= NULL
;
1335 struct cod_libraryobj
*lib
= NULL
;
1336 u32 ul_addr
= 0; /* Used by cod_get_section */
1337 u32 ul_len
= 0; /* Used by cod_get_section */
1338 u32 dw_data_size
= COD_MAXPATHLENGTH
;
1341 bool get_uuids
= (dep_lib_uuids
!= NULL
);
1345 /* Initialize to 0 dependent libraries, if only counting number of
1346 * dependent libraries */
1352 /* Allocate a buffer for file name */
1353 psz_file_name
= kzalloc(dw_data_size
, GFP_KERNEL
);
1354 if (psz_file_name
== NULL
) {
1357 /* Get the name of the library */
1358 status
= dcd_get_library_name(hdcd_mgr
, uuid_obj
, psz_file_name
,
1359 &dw_data_size
, phase
, NULL
);
1362 /* Open the library */
1364 status
= cod_open(dcd_mgr_obj
->cod_mgr
, psz_file_name
,
1368 /* Get dependent library section information. */
1369 status
= cod_get_section(lib
, DEPLIBSECT
, &ul_addr
, &ul_len
);
1372 /* Ok, no dependent libraries */
1378 if (status
|| !(ul_len
> 0))
1381 /* Allocate zeroed buffer. */
1382 psz_coff_buf
= kzalloc(ul_len
+ 4, GFP_KERNEL
);
1383 if (psz_coff_buf
== NULL
)
1386 /* Read section contents. */
1387 status
= cod_read_section(lib
, DEPLIBSECT
, psz_coff_buf
, ul_len
);
1391 /* Compress and format DSP buffer to conform to PC format. */
1392 compress_buf(psz_coff_buf
, ul_len
, DSPWORDSIZE
);
1394 /* Read from buffer */
1395 psz_cur
= psz_coff_buf
;
1396 while ((token
= strsep(&psz_cur
, seps
)) && *token
!= '\0') {
1398 if (dep_libs
>= *num_libs
) {
1399 /* Gone beyond the limit */
1402 /* Retrieve UUID string. */
1403 uuid_uuid_from_string(token
,
1406 /* Is this library persistent? */
1407 token
= strsep(&psz_cur
, seps
);
1408 prstnt_dep_libs
[dep_libs
] = atoi(token
);
1412 /* Advanc to next token */
1413 token
= strsep(&psz_cur
, seps
);
1417 /* Just counting number of dependent libraries */
1425 /* Free previously allocated dynamic buffers. */
1426 kfree(psz_file_name
);
1428 kfree(psz_coff_buf
);