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>
32 /* ----------------------------------- Trace & Debug */
33 #include <dspbridge/dbc.h>
35 /* ----------------------------------- Platform Manager */
36 #include <dspbridge/cod.h>
38 /* ----------------------------------- Others */
39 #include <dspbridge/uuidutil.h>
41 /* ----------------------------------- This */
42 #include <dspbridge/dbdcd.h>
44 /* ----------------------------------- Global defines. */
45 #define MAX_INT2CHAR_LENGTH 16 /* Max int2char len of 32 bit int */
47 /* Name of section containing dependent libraries */
48 #define DEPLIBSECT ".dspbridge_deplibs"
50 /* DCD specific structures. */
52 struct cod_manager
*cod_mgr
; /* Handle to COD manager object. */
55 /* Pointer to the registry support key */
56 static struct list_head reg_key_list
;
57 static DEFINE_SPINLOCK(dbdcd_lock
);
59 /* Global reference variables. */
63 /* Helper function prototypes. */
64 static s32
atoi(char *psz_buf
);
65 static int get_attrs_from_buf(char *psz_buf
, u32 ul_buf_size
,
66 enum dsp_dcdobjtype obj_type
,
67 struct dcd_genericobj
*gen_obj
);
68 static void compress_buf(char *psz_buf
, u32 ul_buf_size
, s32 char_size
);
69 static char dsp_char2_gpp_char(char *word
, s32 dsp_char_size
);
70 static int get_dep_lib_info(struct dcd_manager
*hdcd_mgr
,
71 struct dsp_uuid
*uuid_obj
,
74 struct dsp_uuid
*dep_lib_uuids
,
75 bool *prstnt_dep_libs
,
76 enum nldr_phase phase
);
79 * ======== dcd_auto_register ========
81 * Parses the supplied image and resigsters with DCD.
83 int dcd_auto_register(struct dcd_manager
*hdcd_mgr
,
88 DBC_REQUIRE(refs
> 0);
91 status
= dcd_get_objects(hdcd_mgr
, sz_coff_path
,
92 (dcd_registerfxn
) dcd_register_object
,
93 (void *)sz_coff_path
);
101 * ======== dcd_auto_unregister ========
103 * Parses the supplied DSP image and unresiters from DCD.
105 int dcd_auto_unregister(struct dcd_manager
*hdcd_mgr
,
110 DBC_REQUIRE(refs
> 0);
113 status
= dcd_get_objects(hdcd_mgr
, sz_coff_path
,
114 (dcd_registerfxn
) dcd_register_object
,
123 * ======== dcd_create_manager ========
125 * Creates DCD manager.
127 int dcd_create_manager(char *sz_zl_dll_name
,
128 struct dcd_manager
**dcd_mgr
)
130 struct cod_manager
*cod_mgr
; /* COD manager handle */
131 struct dcd_manager
*dcd_mgr_obj
= NULL
; /* DCD Manager pointer */
134 DBC_REQUIRE(refs
>= 0);
135 DBC_REQUIRE(dcd_mgr
);
137 status
= cod_create(&cod_mgr
, sz_zl_dll_name
);
141 /* Create a DCD object. */
142 dcd_mgr_obj
= kzalloc(sizeof(struct dcd_manager
), GFP_KERNEL
);
143 if (dcd_mgr_obj
!= NULL
) {
144 /* Fill out the object. */
145 dcd_mgr_obj
->cod_mgr
= cod_mgr
;
147 /* Return handle to this DCD interface. */
148 *dcd_mgr
= dcd_mgr_obj
;
153 * If allocation of DcdManager object failed, delete the
159 DBC_ENSURE((!status
) ||
160 ((dcd_mgr_obj
== NULL
) && (status
== -ENOMEM
)));
167 * ======== dcd_destroy_manager ========
169 * Frees DCD Manager object.
171 int dcd_destroy_manager(struct dcd_manager
*hdcd_mgr
)
173 struct dcd_manager
*dcd_mgr_obj
= hdcd_mgr
;
174 int status
= -EFAULT
;
176 DBC_REQUIRE(refs
>= 0);
179 /* Delete the COD manager. */
180 cod_delete(dcd_mgr_obj
->cod_mgr
);
182 /* Deallocate a DCD manager object. */
192 * ======== dcd_enumerate_object ========
194 * Enumerates objects in the DCD.
196 int dcd_enumerate_object(s32 index
, enum dsp_dcdobjtype obj_type
,
197 struct dsp_uuid
*uuid_obj
)
200 char sz_reg_key
[DCD_MAXPATHLENGTH
];
201 char sz_value
[DCD_MAXPATHLENGTH
];
202 struct dsp_uuid dsp_uuid_obj
;
203 char sz_obj_type
[MAX_INT2CHAR_LENGTH
]; /* str. rep. of obj_type. */
205 struct dcd_key_elem
*dcd_key
;
208 DBC_REQUIRE(refs
>= 0);
209 DBC_REQUIRE(index
>= 0);
210 DBC_REQUIRE(uuid_obj
!= NULL
);
212 if ((index
!= 0) && (enum_refs
== 0)) {
214 * If an enumeration is being performed on an index greater
215 * than zero, then the current enum_refs must have been
216 * incremented to greater than zero.
221 * Pre-determine final key length. It's length of DCD_REGKEY +
222 * "_\0" + length of sz_obj_type string + terminating NULL.
224 dw_key_len
= strlen(DCD_REGKEY
) + 1 + sizeof(sz_obj_type
) + 1;
225 DBC_ASSERT(dw_key_len
< DCD_MAXPATHLENGTH
);
227 /* Create proper REG key; concatenate DCD_REGKEY with
229 strncpy(sz_reg_key
, DCD_REGKEY
, strlen(DCD_REGKEY
) + 1);
230 if ((strlen(sz_reg_key
) + strlen("_\0")) <
232 strncat(sz_reg_key
, "_\0", 2);
237 /* This snprintf is guaranteed not to exceed max size of an
239 status
= snprintf(sz_obj_type
, MAX_INT2CHAR_LENGTH
, "%d",
246 if ((strlen(sz_reg_key
) + strlen(sz_obj_type
)) <
248 strncat(sz_reg_key
, sz_obj_type
,
249 strlen(sz_obj_type
) + 1);
256 len
= strlen(sz_reg_key
);
257 spin_lock(&dbdcd_lock
);
258 list_for_each_entry(dcd_key
, ®_key_list
, link
) {
259 if (!strncmp(dcd_key
->name
, sz_reg_key
, len
)
261 strncpy(sz_value
, &dcd_key
->name
[len
],
262 strlen(&dcd_key
->name
[len
]) + 1);
266 spin_unlock(&dbdcd_lock
);
268 if (&dcd_key
->link
== ®_key_list
)
273 /* Create UUID value using string retrieved from
275 uuid_uuid_from_string(sz_value
, &dsp_uuid_obj
);
277 *uuid_obj
= dsp_uuid_obj
;
279 /* Increment enum_refs to update reference count. */
283 } else if (status
== -ENODATA
) {
284 /* At the end of enumeration. Reset enum_refs. */
288 * TODO: Revisit, this is not an error case but code
289 * expects non-zero value.
297 DBC_ENSURE(uuid_obj
|| (status
== -EPERM
));
303 * ======== dcd_exit ========
305 * Discontinue usage of the DCD module.
309 struct dcd_key_elem
*rv
, *rv_tmp
;
310 DBC_REQUIRE(refs
> 0);
315 list_for_each_entry_safe(rv
, rv_tmp
, ®_key_list
, link
) {
322 DBC_ENSURE(refs
>= 0);
326 * ======== dcd_get_dep_libs ========
328 int dcd_get_dep_libs(struct dcd_manager
*hdcd_mgr
,
329 struct dsp_uuid
*uuid_obj
,
330 u16 num_libs
, struct dsp_uuid
*dep_lib_uuids
,
331 bool *prstnt_dep_libs
,
332 enum nldr_phase phase
)
336 DBC_REQUIRE(refs
> 0);
337 DBC_REQUIRE(hdcd_mgr
);
338 DBC_REQUIRE(uuid_obj
!= NULL
);
339 DBC_REQUIRE(dep_lib_uuids
!= NULL
);
340 DBC_REQUIRE(prstnt_dep_libs
!= NULL
);
343 get_dep_lib_info(hdcd_mgr
, uuid_obj
, &num_libs
, NULL
, dep_lib_uuids
,
344 prstnt_dep_libs
, phase
);
350 * ======== dcd_get_num_dep_libs ========
352 int dcd_get_num_dep_libs(struct dcd_manager
*hdcd_mgr
,
353 struct dsp_uuid
*uuid_obj
,
354 u16
*num_libs
, u16
*num_pers_libs
,
355 enum nldr_phase phase
)
359 DBC_REQUIRE(refs
> 0);
360 DBC_REQUIRE(hdcd_mgr
);
361 DBC_REQUIRE(num_libs
!= NULL
);
362 DBC_REQUIRE(num_pers_libs
!= NULL
);
363 DBC_REQUIRE(uuid_obj
!= NULL
);
365 status
= get_dep_lib_info(hdcd_mgr
, uuid_obj
, num_libs
, num_pers_libs
,
372 * ======== dcd_get_object_def ========
374 * Retrieves the properties of a node or processor based on the UUID and
377 int dcd_get_object_def(struct dcd_manager
*hdcd_mgr
,
378 struct dsp_uuid
*obj_uuid
,
379 enum dsp_dcdobjtype obj_type
,
380 struct dcd_genericobj
*obj_def
)
382 struct dcd_manager
*dcd_mgr_obj
= hdcd_mgr
; /* ptr to DCD mgr */
383 struct cod_libraryobj
*lib
= NULL
;
385 u32 ul_addr
= 0; /* Used by cod_get_section */
386 u32 ul_len
= 0; /* Used by cod_get_section */
387 u32 dw_buf_size
; /* Used by REG functions */
388 char sz_reg_key
[DCD_MAXPATHLENGTH
];
389 char *sz_uuid
; /*[MAXUUIDLEN]; */
390 struct dcd_key_elem
*dcd_key
= NULL
;
391 char sz_sect_name
[MAXUUIDLEN
+ 2]; /* ".[UUID]\0" */
393 u32 dw_key_len
; /* Len of REG key. */
394 char sz_obj_type
[MAX_INT2CHAR_LENGTH
]; /* str. rep. of obj_type. */
396 DBC_REQUIRE(refs
> 0);
397 DBC_REQUIRE(obj_def
!= NULL
);
398 DBC_REQUIRE(obj_uuid
!= NULL
);
400 sz_uuid
= kzalloc(MAXUUIDLEN
, GFP_KERNEL
);
411 /* Pre-determine final key length. It's length of DCD_REGKEY +
412 * "_\0" + length of sz_obj_type string + terminating NULL */
413 dw_key_len
= strlen(DCD_REGKEY
) + 1 + sizeof(sz_obj_type
) + 1;
414 DBC_ASSERT(dw_key_len
< DCD_MAXPATHLENGTH
);
416 /* Create proper REG key; concatenate DCD_REGKEY with obj_type. */
417 strncpy(sz_reg_key
, DCD_REGKEY
, strlen(DCD_REGKEY
) + 1);
419 if ((strlen(sz_reg_key
) + strlen("_\0")) < DCD_MAXPATHLENGTH
)
420 strncat(sz_reg_key
, "_\0", 2);
424 status
= snprintf(sz_obj_type
, MAX_INT2CHAR_LENGTH
, "%d", obj_type
);
430 if ((strlen(sz_reg_key
) + strlen(sz_obj_type
)) <
432 strncat(sz_reg_key
, sz_obj_type
,
433 strlen(sz_obj_type
) + 1);
438 /* Create UUID value to set in registry. */
439 uuid_uuid_to_string(obj_uuid
, sz_uuid
, MAXUUIDLEN
);
441 if ((strlen(sz_reg_key
) + MAXUUIDLEN
) < DCD_MAXPATHLENGTH
)
442 strncat(sz_reg_key
, sz_uuid
, MAXUUIDLEN
);
446 /* Retrieve paths from the registry based on struct dsp_uuid */
447 dw_buf_size
= DCD_MAXPATHLENGTH
;
450 spin_lock(&dbdcd_lock
);
451 list_for_each_entry(dcd_key
, ®_key_list
, link
) {
452 if (!strncmp(dcd_key
->name
, sz_reg_key
,
453 strlen(sz_reg_key
) + 1))
456 spin_unlock(&dbdcd_lock
);
457 if (&dcd_key
->link
== ®_key_list
) {
464 /* Open COFF file. */
465 status
= cod_open(dcd_mgr_obj
->cod_mgr
, dcd_key
->path
,
472 /* Ensure sz_uuid + 1 is not greater than sizeof sz_sect_name. */
473 DBC_ASSERT((strlen(sz_uuid
) + 1) < sizeof(sz_sect_name
));
475 /* Create section name based on node UUID. A period is
476 * pre-pended to the UUID string to form the section name.
477 * I.e. ".24BC8D90_BB45_11d4_B756_006008BDB66F" */
478 strncpy(sz_sect_name
, ".", 2);
479 strncat(sz_sect_name
, sz_uuid
, strlen(sz_uuid
));
481 /* Get section information. */
482 status
= cod_get_section(lib
, sz_sect_name
, &ul_addr
, &ul_len
);
488 /* Allocate zeroed buffer. */
489 psz_coff_buf
= kzalloc(ul_len
+ 4, GFP_KERNEL
);
490 if (psz_coff_buf
== NULL
) {
495 if (strstr(dcd_key
->path
, "iva") == NULL
) {
496 /* Locate section by objectID and read its content. */
498 cod_read_section(lib
, sz_sect_name
, psz_coff_buf
, ul_len
);
501 cod_read_section(lib
, sz_sect_name
, psz_coff_buf
, ul_len
);
502 dev_dbg(bridge
, "%s: Skipped Byte swap for IVA!!\n", __func__
);
505 status
= cod_read_section(lib
, sz_sect_name
, psz_coff_buf
, ul_len
);
508 /* Compres DSP buffer to conform to PC format. */
509 if (strstr(dcd_key
->path
, "iva") == NULL
) {
510 compress_buf(psz_coff_buf
, ul_len
, DSPWORDSIZE
);
512 compress_buf(psz_coff_buf
, ul_len
, 1);
513 dev_dbg(bridge
, "%s: Compressing IVA COFF buffer by 1 "
514 "for IVA!!\n", __func__
);
517 /* Parse the content of the COFF buffer. */
519 get_attrs_from_buf(psz_coff_buf
, ul_len
, obj_type
, obj_def
);
526 /* Free the previously allocated dynamic buffer. */
538 * ======== dcd_get_objects ========
540 int dcd_get_objects(struct dcd_manager
*hdcd_mgr
,
541 char *sz_coff_path
, dcd_registerfxn register_fxn
,
544 struct dcd_manager
*dcd_mgr_obj
= hdcd_mgr
;
548 struct cod_libraryobj
*lib
= NULL
;
549 u32 ul_addr
= 0; /* Used by cod_get_section */
550 u32 ul_len
= 0; /* Used by cod_get_section */
553 struct dsp_uuid dsp_uuid_obj
;
556 DBC_REQUIRE(refs
> 0);
562 /* Open DSP coff file, don't load symbols. */
563 status
= cod_open(dcd_mgr_obj
->cod_mgr
, sz_coff_path
, COD_NOLOAD
, &lib
);
569 /* Get DCD_RESIGER_SECTION section information. */
570 status
= cod_get_section(lib
, DCD_REGISTER_SECTION
, &ul_addr
, &ul_len
);
571 if (status
|| !(ul_len
> 0)) {
576 /* Allocate zeroed buffer. */
577 psz_coff_buf
= kzalloc(ul_len
+ 4, GFP_KERNEL
);
578 if (psz_coff_buf
== NULL
) {
583 if (strstr(sz_coff_path
, "iva") == NULL
) {
584 /* Locate section by objectID and read its content. */
585 status
= cod_read_section(lib
, DCD_REGISTER_SECTION
,
586 psz_coff_buf
, ul_len
);
588 dev_dbg(bridge
, "%s: Skipped Byte swap for IVA!!\n", __func__
);
589 status
= cod_read_section(lib
, DCD_REGISTER_SECTION
,
590 psz_coff_buf
, ul_len
);
594 cod_read_section(lib
, DCD_REGISTER_SECTION
, psz_coff_buf
, ul_len
);
597 /* Compress DSP buffer to conform to PC format. */
598 if (strstr(sz_coff_path
, "iva") == NULL
) {
599 compress_buf(psz_coff_buf
, ul_len
, DSPWORDSIZE
);
601 compress_buf(psz_coff_buf
, ul_len
, 1);
602 dev_dbg(bridge
, "%s: Compress COFF buffer with 1 word "
603 "for IVA!!\n", __func__
);
606 /* Read from buffer and register object in buffer. */
607 psz_cur
= psz_coff_buf
;
608 while ((token
= strsep(&psz_cur
, seps
)) && *token
!= '\0') {
609 /* Retrieve UUID string. */
610 uuid_uuid_from_string(token
, &dsp_uuid_obj
);
612 /* Retrieve object type */
613 token
= strsep(&psz_cur
, seps
);
615 /* Retrieve object type */
616 object_type
= atoi(token
);
619 * Apply register_fxn to the found DCD object.
620 * Possible actions include:
622 * 1) Register found DCD object.
623 * 2) Unregister found DCD object (when handle == NULL)
624 * 3) Add overlay node.
627 register_fxn(&dsp_uuid_obj
, object_type
, handle
);
629 /* if error occurs, break from while loop. */
637 /* Free the previously allocated dynamic buffer. */
648 * ======== dcd_get_library_name ========
650 * Retrieves the library name for the given UUID.
653 int dcd_get_library_name(struct dcd_manager
*hdcd_mgr
,
654 struct dsp_uuid
*uuid_obj
,
657 enum nldr_phase phase
, bool *phase_split
)
659 char sz_reg_key
[DCD_MAXPATHLENGTH
];
660 char sz_uuid
[MAXUUIDLEN
];
661 u32 dw_key_len
; /* Len of REG key. */
662 char sz_obj_type
[MAX_INT2CHAR_LENGTH
]; /* str. rep. of obj_type. */
664 struct dcd_key_elem
*dcd_key
= NULL
;
666 DBC_REQUIRE(uuid_obj
!= NULL
);
667 DBC_REQUIRE(str_lib_name
!= NULL
);
668 DBC_REQUIRE(buff_size
!= NULL
);
669 DBC_REQUIRE(hdcd_mgr
);
671 dev_dbg(bridge
, "%s: hdcd_mgr %p, uuid_obj %p, str_lib_name %p,"
672 " buff_size %p\n", __func__
, hdcd_mgr
, uuid_obj
, str_lib_name
,
676 * Pre-determine final key length. It's length of DCD_REGKEY +
677 * "_\0" + length of sz_obj_type string + terminating NULL.
679 dw_key_len
= strlen(DCD_REGKEY
) + 1 + sizeof(sz_obj_type
) + 1;
680 DBC_ASSERT(dw_key_len
< DCD_MAXPATHLENGTH
);
682 /* Create proper REG key; concatenate DCD_REGKEY with obj_type. */
683 strncpy(sz_reg_key
, DCD_REGKEY
, strlen(DCD_REGKEY
) + 1);
684 if ((strlen(sz_reg_key
) + strlen("_\0")) < DCD_MAXPATHLENGTH
)
685 strncat(sz_reg_key
, "_\0", 2);
691 /* create phase type */
692 sprintf(sz_obj_type
, "%d", DSP_DCDCREATELIBTYPE
);
695 /* execute phase type */
696 sprintf(sz_obj_type
, "%d", DSP_DCDEXECUTELIBTYPE
);
699 /* delete phase type */
700 sprintf(sz_obj_type
, "%d", DSP_DCDDELETELIBTYPE
);
703 /* known to be a dependent library */
704 sprintf(sz_obj_type
, "%d", DSP_DCDLIBRARYTYPE
);
711 if ((strlen(sz_reg_key
) + strlen(sz_obj_type
)) <
713 strncat(sz_reg_key
, sz_obj_type
,
714 strlen(sz_obj_type
) + 1);
718 /* Create UUID value to find match in registry. */
719 uuid_uuid_to_string(uuid_obj
, sz_uuid
, MAXUUIDLEN
);
720 if ((strlen(sz_reg_key
) + MAXUUIDLEN
) < DCD_MAXPATHLENGTH
)
721 strncat(sz_reg_key
, sz_uuid
, MAXUUIDLEN
);
726 spin_lock(&dbdcd_lock
);
727 list_for_each_entry(dcd_key
, ®_key_list
, link
) {
728 /* See if the name matches. */
729 if (!strncmp(dcd_key
->name
, sz_reg_key
,
730 strlen(sz_reg_key
) + 1))
733 spin_unlock(&dbdcd_lock
);
736 if (&dcd_key
->link
== ®_key_list
)
739 /* If can't find, phases might be registered as generic LIBRARYTYPE */
740 if (status
&& phase
!= NLDR_NOPHASE
) {
742 *phase_split
= false;
744 strncpy(sz_reg_key
, DCD_REGKEY
, strlen(DCD_REGKEY
) + 1);
745 if ((strlen(sz_reg_key
) + strlen("_\0")) <
747 strncat(sz_reg_key
, "_\0", 2);
751 sprintf(sz_obj_type
, "%d", DSP_DCDLIBRARYTYPE
);
752 if ((strlen(sz_reg_key
) + strlen(sz_obj_type
))
753 < DCD_MAXPATHLENGTH
) {
754 strncat(sz_reg_key
, sz_obj_type
,
755 strlen(sz_obj_type
) + 1);
759 uuid_uuid_to_string(uuid_obj
, sz_uuid
, MAXUUIDLEN
);
760 if ((strlen(sz_reg_key
) + MAXUUIDLEN
) < DCD_MAXPATHLENGTH
)
761 strncat(sz_reg_key
, sz_uuid
, MAXUUIDLEN
);
765 spin_lock(&dbdcd_lock
);
766 list_for_each_entry(dcd_key
, ®_key_list
, link
) {
767 /* See if the name matches. */
768 if (!strncmp(dcd_key
->name
, sz_reg_key
,
769 strlen(sz_reg_key
) + 1))
772 spin_unlock(&dbdcd_lock
);
774 status
= (&dcd_key
->link
!= ®_key_list
) ?
779 memcpy(str_lib_name
, dcd_key
->path
, strlen(dcd_key
->path
) + 1);
784 * ======== dcd_init ========
786 * Initialize the DCD module.
793 DBC_REQUIRE(refs
>= 0);
796 /* Initialize required modules. */
797 init_cod
= cod_init();
801 /* Exit initialized modules. */
806 INIT_LIST_HEAD(®_key_list
);
812 DBC_ENSURE((ret
&& (refs
> 0)) || (!ret
&& (refs
== 0)));
818 * ======== dcd_register_object ========
820 * Registers a node or a processor with the DCD.
821 * If psz_path_name == NULL, unregister the specified DCD object.
823 int dcd_register_object(struct dsp_uuid
*uuid_obj
,
824 enum dsp_dcdobjtype obj_type
,
828 char sz_reg_key
[DCD_MAXPATHLENGTH
];
829 char sz_uuid
[MAXUUIDLEN
+ 1];
830 u32 dw_path_size
= 0;
831 u32 dw_key_len
; /* Len of REG key. */
832 char sz_obj_type
[MAX_INT2CHAR_LENGTH
]; /* str. rep. of obj_type. */
833 struct dcd_key_elem
*dcd_key
= NULL
;
835 DBC_REQUIRE(refs
> 0);
836 DBC_REQUIRE(uuid_obj
!= NULL
);
837 DBC_REQUIRE((obj_type
== DSP_DCDNODETYPE
) ||
838 (obj_type
== DSP_DCDPROCESSORTYPE
) ||
839 (obj_type
== DSP_DCDLIBRARYTYPE
) ||
840 (obj_type
== DSP_DCDCREATELIBTYPE
) ||
841 (obj_type
== DSP_DCDEXECUTELIBTYPE
) ||
842 (obj_type
== DSP_DCDDELETELIBTYPE
));
844 dev_dbg(bridge
, "%s: object UUID %p, obj_type %d, szPathName %s\n",
845 __func__
, uuid_obj
, obj_type
, psz_path_name
);
848 * Pre-determine final key length. It's length of DCD_REGKEY +
849 * "_\0" + length of sz_obj_type string + terminating NULL.
851 dw_key_len
= strlen(DCD_REGKEY
) + 1 + sizeof(sz_obj_type
) + 1;
852 DBC_ASSERT(dw_key_len
< DCD_MAXPATHLENGTH
);
854 /* Create proper REG key; concatenate DCD_REGKEY with obj_type. */
855 strncpy(sz_reg_key
, DCD_REGKEY
, strlen(DCD_REGKEY
) + 1);
856 if ((strlen(sz_reg_key
) + strlen("_\0")) < DCD_MAXPATHLENGTH
)
857 strncat(sz_reg_key
, "_\0", 2);
863 status
= snprintf(sz_obj_type
, MAX_INT2CHAR_LENGTH
, "%d", obj_type
);
868 if ((strlen(sz_reg_key
) + strlen(sz_obj_type
)) <
870 strncat(sz_reg_key
, sz_obj_type
,
871 strlen(sz_obj_type
) + 1);
875 /* Create UUID value to set in registry. */
876 uuid_uuid_to_string(uuid_obj
, sz_uuid
, MAXUUIDLEN
);
877 if ((strlen(sz_reg_key
) + MAXUUIDLEN
) < DCD_MAXPATHLENGTH
)
878 strncat(sz_reg_key
, sz_uuid
, MAXUUIDLEN
);
887 * If psz_path_name != NULL, perform registration, otherwise,
888 * perform unregistration.
892 dw_path_size
= strlen(psz_path_name
) + 1;
893 spin_lock(&dbdcd_lock
);
894 list_for_each_entry(dcd_key
, ®_key_list
, link
) {
895 /* See if the name matches. */
896 if (!strncmp(dcd_key
->name
, sz_reg_key
,
897 strlen(sz_reg_key
) + 1))
900 spin_unlock(&dbdcd_lock
);
901 if (&dcd_key
->link
== ®_key_list
) {
903 * Add new reg value (UUID+obj_type)
904 * with COFF path info
907 dcd_key
= kmalloc(sizeof(struct dcd_key_elem
),
914 dcd_key
->path
= kmalloc(strlen(sz_reg_key
) + 1,
917 if (!dcd_key
->path
) {
923 strncpy(dcd_key
->name
, sz_reg_key
,
924 strlen(sz_reg_key
) + 1);
925 strncpy(dcd_key
->path
, psz_path_name
,
927 spin_lock(&dbdcd_lock
);
928 list_add_tail(&dcd_key
->link
, ®_key_list
);
929 spin_unlock(&dbdcd_lock
);
931 /* Make sure the new data is the same. */
932 if (strncmp(dcd_key
->path
, psz_path_name
,
934 /* The caller needs a different data size! */
935 kfree(dcd_key
->path
);
936 dcd_key
->path
= kmalloc(dw_path_size
,
938 if (dcd_key
->path
== NULL
) {
944 /* We have a match! Copy out the data. */
945 memcpy(dcd_key
->path
, psz_path_name
, dw_path_size
);
947 dev_dbg(bridge
, "%s: psz_path_name=%s, dw_path_size=%d\n",
948 __func__
, psz_path_name
, dw_path_size
);
950 /* Deregister an existing object */
951 spin_lock(&dbdcd_lock
);
952 list_for_each_entry(dcd_key
, ®_key_list
, link
) {
953 if (!strncmp(dcd_key
->name
, sz_reg_key
,
954 strlen(sz_reg_key
) + 1)) {
955 list_del(&dcd_key
->link
);
956 kfree(dcd_key
->path
);
961 spin_unlock(&dbdcd_lock
);
962 if (&dcd_key
->link
== ®_key_list
)
968 * Because the node database has been updated through a
969 * successful object registration/de-registration operation,
970 * we need to reset the object enumeration counter to allow
971 * current enumerations to reflect this update in the node
981 * ======== dcd_unregister_object ========
982 * Call DCD_Register object with psz_path_name set to NULL to
983 * perform actual object de-registration.
985 int dcd_unregister_object(struct dsp_uuid
*uuid_obj
,
986 enum dsp_dcdobjtype obj_type
)
990 DBC_REQUIRE(refs
> 0);
991 DBC_REQUIRE(uuid_obj
!= NULL
);
992 DBC_REQUIRE((obj_type
== DSP_DCDNODETYPE
) ||
993 (obj_type
== DSP_DCDPROCESSORTYPE
) ||
994 (obj_type
== DSP_DCDLIBRARYTYPE
) ||
995 (obj_type
== DSP_DCDCREATELIBTYPE
) ||
996 (obj_type
== DSP_DCDEXECUTELIBTYPE
) ||
997 (obj_type
== DSP_DCDDELETELIBTYPE
));
1000 * When dcd_register_object is called with NULL as pathname,
1001 * it indicates an unregister object operation.
1003 status
= dcd_register_object(uuid_obj
, obj_type
, NULL
);
1009 **********************************************************************
1010 * DCD Helper Functions
1011 **********************************************************************
1015 * ======== atoi ========
1017 * This function converts strings in decimal or hex format to integers.
1019 static s32
atoi(char *psz_buf
)
1021 char *pch
= psz_buf
;
1024 while (isspace(*pch
))
1027 if (*pch
== '-' || *pch
== '+') {
1030 } else if (*pch
&& tolower(pch
[strlen(pch
) - 1]) == 'h') {
1034 return simple_strtoul(pch
, NULL
, base
);
1038 * ======== get_attrs_from_buf ========
1040 * Parse the content of a buffer filled with DSP-side data and
1041 * retrieve an object's attributes from it. IMPORTANT: Assume the
1042 * buffer has been converted from DSP format to GPP format.
1044 static int get_attrs_from_buf(char *psz_buf
, u32 ul_buf_size
,
1045 enum dsp_dcdobjtype obj_type
,
1046 struct dcd_genericobj
*gen_obj
)
1058 DBC_REQUIRE(psz_buf
!= NULL
);
1059 DBC_REQUIRE(ul_buf_size
!= 0);
1060 DBC_REQUIRE((obj_type
== DSP_DCDNODETYPE
)
1061 || (obj_type
== DSP_DCDPROCESSORTYPE
));
1062 DBC_REQUIRE(gen_obj
!= NULL
);
1065 case DSP_DCDNODETYPE
:
1067 * Parse COFF sect buffer to retrieve individual tokens used
1068 * to fill in object attrs.
1071 token
= strsep(&psz_cur
, seps
);
1074 gen_obj
->obj_data
.node_obj
.ndb_props
.cb_struct
=
1076 token
= strsep(&psz_cur
, seps
);
1078 /* dsp_uuid ui_node_id */
1079 uuid_uuid_from_string(token
,
1080 &gen_obj
->obj_data
.node_obj
.ndb_props
.
1082 token
= strsep(&psz_cur
, seps
);
1086 token_len
= strlen(token
);
1087 if (token_len
> DSP_MAXNAMELEN
- 1)
1088 token_len
= DSP_MAXNAMELEN
- 1;
1090 strncpy(gen_obj
->obj_data
.node_obj
.ndb_props
.ac_name
,
1092 gen_obj
->obj_data
.node_obj
.ndb_props
.ac_name
[token_len
] = '\0';
1093 token
= strsep(&psz_cur
, seps
);
1095 gen_obj
->obj_data
.node_obj
.ndb_props
.ntype
= atoi(token
);
1096 token
= strsep(&psz_cur
, seps
);
1097 /* u32 cache_on_gpp */
1098 gen_obj
->obj_data
.node_obj
.ndb_props
.cache_on_gpp
= atoi(token
);
1099 token
= strsep(&psz_cur
, seps
);
1100 /* dsp_resourcereqmts dsp_resource_reqmts */
1101 gen_obj
->obj_data
.node_obj
.ndb_props
.dsp_resource_reqmts
.
1102 cb_struct
= (u32
) atoi(token
);
1103 token
= strsep(&psz_cur
, seps
);
1105 gen_obj
->obj_data
.node_obj
.ndb_props
.
1106 dsp_resource_reqmts
.static_data_size
= atoi(token
);
1107 token
= strsep(&psz_cur
, seps
);
1108 gen_obj
->obj_data
.node_obj
.ndb_props
.
1109 dsp_resource_reqmts
.global_data_size
= atoi(token
);
1110 token
= strsep(&psz_cur
, seps
);
1111 gen_obj
->obj_data
.node_obj
.ndb_props
.
1112 dsp_resource_reqmts
.program_mem_size
= atoi(token
);
1113 token
= strsep(&psz_cur
, seps
);
1114 gen_obj
->obj_data
.node_obj
.ndb_props
.
1115 dsp_resource_reqmts
.wc_execution_time
= atoi(token
);
1116 token
= strsep(&psz_cur
, seps
);
1117 gen_obj
->obj_data
.node_obj
.ndb_props
.
1118 dsp_resource_reqmts
.wc_period
= atoi(token
);
1119 token
= strsep(&psz_cur
, seps
);
1121 gen_obj
->obj_data
.node_obj
.ndb_props
.
1122 dsp_resource_reqmts
.wc_deadline
= atoi(token
);
1123 token
= strsep(&psz_cur
, seps
);
1125 gen_obj
->obj_data
.node_obj
.ndb_props
.
1126 dsp_resource_reqmts
.avg_exection_time
= atoi(token
);
1127 token
= strsep(&psz_cur
, seps
);
1129 gen_obj
->obj_data
.node_obj
.ndb_props
.
1130 dsp_resource_reqmts
.minimum_period
= atoi(token
);
1131 token
= strsep(&psz_cur
, seps
);
1134 gen_obj
->obj_data
.node_obj
.ndb_props
.prio
= atoi(token
);
1135 token
= strsep(&psz_cur
, seps
);
1137 /* u32 stack_size */
1138 gen_obj
->obj_data
.node_obj
.ndb_props
.stack_size
= atoi(token
);
1139 token
= strsep(&psz_cur
, seps
);
1141 /* u32 sys_stack_size */
1142 gen_obj
->obj_data
.node_obj
.ndb_props
.sys_stack_size
=
1144 token
= strsep(&psz_cur
, seps
);
1147 gen_obj
->obj_data
.node_obj
.ndb_props
.stack_seg
= atoi(token
);
1148 token
= strsep(&psz_cur
, seps
);
1150 /* u32 message_depth */
1151 gen_obj
->obj_data
.node_obj
.ndb_props
.message_depth
=
1153 token
= strsep(&psz_cur
, seps
);
1155 /* u32 num_input_streams */
1156 gen_obj
->obj_data
.node_obj
.ndb_props
.num_input_streams
=
1158 token
= strsep(&psz_cur
, seps
);
1160 /* u32 num_output_streams */
1161 gen_obj
->obj_data
.node_obj
.ndb_props
.num_output_streams
=
1163 token
= strsep(&psz_cur
, seps
);
1166 gen_obj
->obj_data
.node_obj
.ndb_props
.timeout
= atoi(token
);
1167 token
= strsep(&psz_cur
, seps
);
1169 /* char *str_create_phase_fxn */
1171 token_len
= strlen(token
);
1172 gen_obj
->obj_data
.node_obj
.str_create_phase_fxn
=
1173 kzalloc(token_len
+ 1, GFP_KERNEL
);
1174 strncpy(gen_obj
->obj_data
.node_obj
.str_create_phase_fxn
,
1176 gen_obj
->obj_data
.node_obj
.str_create_phase_fxn
[token_len
] =
1178 token
= strsep(&psz_cur
, seps
);
1180 /* char *str_execute_phase_fxn */
1182 token_len
= strlen(token
);
1183 gen_obj
->obj_data
.node_obj
.str_execute_phase_fxn
=
1184 kzalloc(token_len
+ 1, GFP_KERNEL
);
1185 strncpy(gen_obj
->obj_data
.node_obj
.str_execute_phase_fxn
,
1187 gen_obj
->obj_data
.node_obj
.str_execute_phase_fxn
[token_len
] =
1189 token
= strsep(&psz_cur
, seps
);
1191 /* char *str_delete_phase_fxn */
1193 token_len
= strlen(token
);
1194 gen_obj
->obj_data
.node_obj
.str_delete_phase_fxn
=
1195 kzalloc(token_len
+ 1, GFP_KERNEL
);
1196 strncpy(gen_obj
->obj_data
.node_obj
.str_delete_phase_fxn
,
1198 gen_obj
->obj_data
.node_obj
.str_delete_phase_fxn
[token_len
] =
1200 token
= strsep(&psz_cur
, seps
);
1202 /* Segment id for message buffers */
1203 gen_obj
->obj_data
.node_obj
.msg_segid
= atoi(token
);
1204 token
= strsep(&psz_cur
, seps
);
1206 /* Message notification type */
1207 gen_obj
->obj_data
.node_obj
.msg_notify_type
= atoi(token
);
1208 token
= strsep(&psz_cur
, seps
);
1210 /* char *str_i_alg_name */
1212 token_len
= strlen(token
);
1213 gen_obj
->obj_data
.node_obj
.str_i_alg_name
=
1214 kzalloc(token_len
+ 1, GFP_KERNEL
);
1215 strncpy(gen_obj
->obj_data
.node_obj
.str_i_alg_name
,
1217 gen_obj
->obj_data
.node_obj
.str_i_alg_name
[token_len
] =
1219 token
= strsep(&psz_cur
, seps
);
1222 /* Load type (static, dynamic, or overlay) */
1224 gen_obj
->obj_data
.node_obj
.load_type
= atoi(token
);
1225 token
= strsep(&psz_cur
, seps
);
1228 /* Dynamic load data requirements */
1230 gen_obj
->obj_data
.node_obj
.data_mem_seg_mask
=
1232 token
= strsep(&psz_cur
, seps
);
1235 /* Dynamic load code requirements */
1237 gen_obj
->obj_data
.node_obj
.code_mem_seg_mask
=
1239 token
= strsep(&psz_cur
, seps
);
1242 /* Extract node profiles into node properties */
1245 gen_obj
->obj_data
.node_obj
.ndb_props
.count_profiles
=
1249 gen_obj
->obj_data
.node_obj
.
1250 ndb_props
.count_profiles
; i
++) {
1251 token
= strsep(&psz_cur
, seps
);
1253 /* Heap Size for the node */
1254 gen_obj
->obj_data
.node_obj
.
1255 ndb_props
.node_profiles
[i
].
1256 heap_size
= atoi(token
);
1260 token
= strsep(&psz_cur
, seps
);
1262 gen_obj
->obj_data
.node_obj
.ndb_props
.stack_seg_name
=
1268 case DSP_DCDPROCESSORTYPE
:
1270 * Parse COFF sect buffer to retrieve individual tokens used
1271 * to fill in object attrs.
1274 token
= strsep(&psz_cur
, seps
);
1276 gen_obj
->obj_data
.proc_info
.cb_struct
= atoi(token
);
1277 token
= strsep(&psz_cur
, seps
);
1279 gen_obj
->obj_data
.proc_info
.processor_family
= atoi(token
);
1280 token
= strsep(&psz_cur
, seps
);
1282 gen_obj
->obj_data
.proc_info
.processor_type
= atoi(token
);
1283 token
= strsep(&psz_cur
, seps
);
1285 gen_obj
->obj_data
.proc_info
.clock_rate
= atoi(token
);
1286 token
= strsep(&psz_cur
, seps
);
1288 gen_obj
->obj_data
.proc_info
.internal_mem_size
= atoi(token
);
1289 token
= strsep(&psz_cur
, seps
);
1291 gen_obj
->obj_data
.proc_info
.external_mem_size
= atoi(token
);
1292 token
= strsep(&psz_cur
, seps
);
1294 gen_obj
->obj_data
.proc_info
.processor_id
= atoi(token
);
1295 token
= strsep(&psz_cur
, seps
);
1297 gen_obj
->obj_data
.proc_info
.ty_running_rtos
= atoi(token
);
1298 token
= strsep(&psz_cur
, seps
);
1300 gen_obj
->obj_data
.proc_info
.node_min_priority
= atoi(token
);
1301 token
= strsep(&psz_cur
, seps
);
1303 gen_obj
->obj_data
.proc_info
.node_max_priority
= atoi(token
);
1306 /* Proc object may contain additional(extended) attributes. */
1307 /* attr must match proc.hxx */
1308 for (entry_id
= 0; entry_id
< 7; entry_id
++) {
1309 token
= strsep(&psz_cur
, seps
);
1310 gen_obj
->obj_data
.ext_proc_obj
.ty_tlb
[entry_id
].
1311 gpp_phys
= atoi(token
);
1313 token
= strsep(&psz_cur
, seps
);
1314 gen_obj
->obj_data
.ext_proc_obj
.ty_tlb
[entry_id
].
1315 dsp_virt
= atoi(token
);
1330 * ======== CompressBuffer ========
1332 * Compress the DSP buffer, if necessary, to conform to PC format.
1334 static void compress_buf(char *psz_buf
, u32 ul_buf_size
, s32 char_size
)
1344 for (q
= psz_buf
; q
< (psz_buf
+ ul_buf_size
);) {
1345 ch
= dsp_char2_gpp_char(q
, char_size
);
1348 ch
= dsp_char2_gpp_char(q
, char_size
);
1377 /* NULL out remainder of buffer. */
1383 * ======== dsp_char2_gpp_char ========
1385 * Convert DSP char to host GPP char in a portable manner
1387 static char dsp_char2_gpp_char(char *word
, s32 dsp_char_size
)
1393 for (ch_src
= word
, i
= dsp_char_size
; i
> 0; i
--)
1400 * ======== get_dep_lib_info ========
1402 static int get_dep_lib_info(struct dcd_manager
*hdcd_mgr
,
1403 struct dsp_uuid
*uuid_obj
,
1406 struct dsp_uuid
*dep_lib_uuids
,
1407 bool *prstnt_dep_libs
,
1408 enum nldr_phase phase
)
1410 struct dcd_manager
*dcd_mgr_obj
= hdcd_mgr
;
1411 char *psz_coff_buf
= NULL
;
1413 char *psz_file_name
= NULL
;
1414 struct cod_libraryobj
*lib
= NULL
;
1415 u32 ul_addr
= 0; /* Used by cod_get_section */
1416 u32 ul_len
= 0; /* Used by cod_get_section */
1417 u32 dw_data_size
= COD_MAXPATHLENGTH
;
1420 bool get_uuids
= (dep_lib_uuids
!= NULL
);
1424 DBC_REQUIRE(refs
> 0);
1426 DBC_REQUIRE(hdcd_mgr
);
1427 DBC_REQUIRE(num_libs
!= NULL
);
1428 DBC_REQUIRE(uuid_obj
!= NULL
);
1430 /* Initialize to 0 dependent libraries, if only counting number of
1431 * dependent libraries */
1437 /* Allocate a buffer for file name */
1438 psz_file_name
= kzalloc(dw_data_size
, GFP_KERNEL
);
1439 if (psz_file_name
== NULL
) {
1442 /* Get the name of the library */
1443 status
= dcd_get_library_name(hdcd_mgr
, uuid_obj
, psz_file_name
,
1444 &dw_data_size
, phase
, NULL
);
1447 /* Open the library */
1449 status
= cod_open(dcd_mgr_obj
->cod_mgr
, psz_file_name
,
1453 /* Get dependent library section information. */
1454 status
= cod_get_section(lib
, DEPLIBSECT
, &ul_addr
, &ul_len
);
1457 /* Ok, no dependent libraries */
1463 if (status
|| !(ul_len
> 0))
1466 /* Allocate zeroed buffer. */
1467 psz_coff_buf
= kzalloc(ul_len
+ 4, GFP_KERNEL
);
1468 if (psz_coff_buf
== NULL
)
1471 /* Read section contents. */
1472 status
= cod_read_section(lib
, DEPLIBSECT
, psz_coff_buf
, ul_len
);
1476 /* Compress and format DSP buffer to conform to PC format. */
1477 compress_buf(psz_coff_buf
, ul_len
, DSPWORDSIZE
);
1479 /* Read from buffer */
1480 psz_cur
= psz_coff_buf
;
1481 while ((token
= strsep(&psz_cur
, seps
)) && *token
!= '\0') {
1483 if (dep_libs
>= *num_libs
) {
1484 /* Gone beyond the limit */
1487 /* Retrieve UUID string. */
1488 uuid_uuid_from_string(token
,
1491 /* Is this library persistent? */
1492 token
= strsep(&psz_cur
, seps
);
1493 prstnt_dep_libs
[dep_libs
] = atoi(token
);
1497 /* Advanc to next token */
1498 token
= strsep(&psz_cur
, seps
);
1502 /* Just counting number of dependent libraries */
1510 /* Free previously allocated dynamic buffers. */
1511 kfree(psz_file_name
);
1513 kfree(psz_coff_buf
);