19 #include <linux/types.h>
39 #define DYNMEMSECT ".dspbridge_mem"
42 #define DEPLIBSECT ".dspbridge_deplibs"
79 #define MEMINTERNALID 32
80 #define MEMEXTERNALID 33
94 #define DYNM_CODEDATA (DYNM_CODE | DYNM_DATA)
95 #define DYNM_INTERNAL 0x8
96 #define DYNM_EXTERNAL 0x10
108 #define CREATEDATAFLAGBIT 0
109 #define CREATECODEFLAGBIT 1
110 #define EXECUTEDATAFLAGBIT 2
111 #define EXECUTECODEFLAGBIT 3
112 #define DELETEDATAFLAGBIT 4
113 #define DELETECODEFLAGBIT 5
120 #define PCREATE "create"
121 #define PDELETE "delete"
122 #define PEXECUTE "execute"
124 static inline bool is_equal_uuid(
struct dsp_uuid *uuid1,
268 static int add_ovly_node(
struct dsp_uuid *uuid_obj,
270 static int add_ovly_sect(
struct nldr_object *nldr_obj,
273 bool *exists,
u32 addr,
u32 bytes);
274 static s32 fake_ovly_write(
void *handle,
u32 dsp_address,
void *
buf,
u32 bytes,
276 static void free_sects(
struct nldr_object *nldr_obj,
278 static bool get_symbol_value(
void *handle,
void *parg,
void *rmm_handle,
287 static int remote_alloc(
void **ref,
u16 mem_sect,
u32 size,
291 static int remote_free(
void **ref,
u16 space,
u32 dsp_address,
u32 size,
298 static bool find_in_persistent_lib_array(
struct nldr_nodeobject *nldr_node_obj,
307 bool *pf_phase_split)
313 *nldr_nodeobj =
NULL;
317 if (nldr_node_obj ==
NULL) {
389 if (status && nldr_node_obj)
390 kfree(nldr_node_obj);
403 char *psz_coff_buf =
NULL;
436 if (!(nldr_obj->
ldr_fxns.init_fxn()))
463 "segments: 0x%x\n", __func__, status);
466 if (!status && ul_len > 0) {
473 if (!status && ul_len > 0) {
475 dload_segs = (
u16) (*((
u32 *) psz_coff_buf));
480 if (!status && dload_segs > 0) {
481 rmm_segs = kzalloc(
sizeof(
struct rmm_segment) * dload_segs,
491 for (i = 0; i < dload_segs; i++) {
496 (mem_info_obj +
i)->
type;
498 "(proc) DLL MEMSEGMENT: %d, "
499 "Base: 0x%x, Length: 0x%x\n", i,
510 nldr_obj->
ldr_fxns.get_attrs_fxn(nldr_obj->
dbll, &save_attrs);
511 new_attrs = save_attrs;
533 add_ovly_node, (
void *)nldr_obj);
549 save_attrs.
write = fake_ovly_write;
554 &save_attrs, &ul_entry);
591 while (ovly_section) {
598 while (ovly_section) {
605 while (ovly_section) {
610 ovly_section = nldr_obj->
ovly_table[
i].other_sects_list;
611 while (ovly_section) {
626 char *str_fxn,
u32 * addr)
638 switch (nldr_node_obj->
phase) {
653 root = nldr_node_obj->
root;
656 nldr_obj->
ldr_fxns.get_c_addr_fxn(root.
lib, str_fxn, &dbll_sym);
664 for (i = 0; i < root.
dep_libs; i++) {
683 for (i = 0; i < nldr_node_obj->
pers_libs; i++) {
692 [i].lib, str_fxn, &dbll_sym);
702 *addr = dbll_sym->
value;
720 *rmm_mgr = nldr_obj->
rmm;
744 lib_uuid = nldr_node_obj->
uuid;
752 load_lib(nldr_node_obj, &nldr_node_obj->
root, lib_uuid,
753 false, nldr_node_obj->
lib_path, phase, 0);
780 status = load_ovly(nldr_node_obj, phase);
797 if (nldr_node_obj !=
NULL) {
813 unload_lib(nldr_node_obj,
824 root_lib = &nldr_node_obj->
root;
827 unload_lib(nldr_node_obj, root_lib);
830 unload_ovly(nldr_node_obj, phase);
840 static int add_ovly_info(
void *handle,
struct dbll_sect_info *sect_info,
844 char *sect_name = (
char *)sect_info->
name;
845 bool sect_exists =
false;
859 if (
strncmp(node_name, sect_name + 1,
strlen(node_name)) == 0) {
864 if (!(i < nldr_obj->ovly_nodes))
868 for (pch = sect_name + 1; *pch && *pch != seps; pch++)
875 add_ovly_sect(nldr_obj,
877 ovly_table[
i].create_sects_list,
878 sect_info, §_exists, addr, bytes);
879 if (!status && !sect_exists)
884 add_ovly_sect(nldr_obj,
886 ovly_table[
i].delete_sects_list,
887 sect_info, §_exists, addr, bytes);
888 if (!status && !sect_exists)
893 add_ovly_sect(nldr_obj,
895 ovly_table[
i].execute_sects_list,
896 sect_info, §_exists, addr, bytes);
897 if (!status && !sect_exists)
903 add_ovly_sect(nldr_obj,
905 ovly_table[
i].other_sects_list,
906 sect_info, §_exists, addr, bytes);
907 if (!status && !sect_exists)
920 static int add_ovly_node(
struct dsp_uuid *uuid_obj,
924 char *node_name =
NULL;
948 strlen(obj_def.obj_data.node_obj.ndb_props.ac_name);
949 node_name = obj_def.obj_data.node_obj.ndb_props.ac_name;
962 kfree(obj_def.obj_data.node_obj.str_create_phase_fxn);
964 kfree(obj_def.obj_data.node_obj.str_execute_phase_fxn);
966 kfree(obj_def.obj_data.node_obj.str_delete_phase_fxn);
968 kfree(obj_def.obj_data.node_obj.str_i_alg_name);
977 static int add_ovly_sect(
struct nldr_object *nldr_obj,
980 bool *exists,
u32 addr,
u32 bytes)
987 ovly_section = last_sect = *lst;
989 while (ovly_section) {
999 last_sect = ovly_section;
1003 if (!ovly_section) {
1006 if (new_sect ==
NULL) {
1033 static s32 fake_ovly_write(
void *handle,
u32 dsp_address,
void *buf,
u32 bytes,
1042 static void free_sects(
struct nldr_object *nldr_obj,
1045 struct ovly_sect *ovly_section = phase_sects;
1049 while (ovly_section && i < alloc_num) {
1055 ovly_section->
size,
true);
1066 static bool get_symbol_value(
void *handle,
void *parg,
void *rmm_handle,
1074 bool status =
false;
1090 status = nldr_obj->
ldr_fxns.get_addr_fxn(root->
lib, sym_name,
1104 for (i = 0; i < root->
dep_libs; i++) {
1106 nldr_obj->
ldr_fxns.get_addr_fxn(root->
1126 for (i = 0; i < nldr_node_obj->
pers_libs; i++) {
1132 status = nldr_obj->
ldr_fxns.get_c_addr_fxn
1160 u16 nd_libs_loaded = 0;
1166 char *psz_file_name =
NULL;
1168 bool *persistent_dep_libs =
NULL;
1170 bool lib_status =
false;
1179 if (psz_file_name ==
NULL)
1187 dcd_mgr, &uuid, psz_file_name,
1188 &dw_buf_size, phase,
1194 dcd_mgr, &uuid, psz_file_name,
1202 nldr_obj->
ldr_fxns.open_fxn(nldr_obj->
dbll, psz_file_name,
1206 kfree(psz_file_name);
1209 if (!status && root_prstnt) {
1211 find_in_persistent_lib_array(nldr_node_obj, root->
lib);
1220 for (i = 0; i <
depth; i++) {
1221 if (root->
lib == lib_path[i]) {
1235 &uuid, &nd_libs, &np_libs, phase);
1242 root->
dep_libs = nd_libs - np_libs;
1244 dep_lib_uui_ds = kzalloc(
sizeof(
struct dsp_uuid) *
1246 persistent_dep_libs =
1248 if (!dep_lib_uui_ds || !persistent_dep_libs)
1267 nd_libs, dep_lib_uui_ds,
1268 persistent_dep_libs,
1278 for (i = 0; i < nd_libs; i++) {
1282 if (!root_prstnt && persistent_dep_libs[i] &&
1295 persistent_dep_libs[
i] =
true;
1301 status = load_lib(nldr_node_obj, dep_lib,
1303 persistent_dep_libs[i], lib_path,
1307 if ((status != 0) &&
1308 !root_prstnt && persistent_dep_libs[i] &&
1312 if (!persistent_dep_libs[i] ||
1326 new_attrs.sym_arg = root;
1327 new_attrs.rmm_handle = nldr_node_obj;
1328 new_attrs.input_params = nldr_node_obj->
priv_ref;
1329 new_attrs.base_image =
false;
1332 nldr_obj->
ldr_fxns.load_fxn(root->
lib, flags, &new_attrs,
1343 for (i = 0; i < nldr_node_obj->
pers_libs; i++)
1344 unload_lib(nldr_node_obj,
1349 for (i = 0; i < nd_libs_loaded; i++)
1360 kfree(dep_lib_uui_ds);
1361 dep_lib_uui_ds =
NULL;
1363 kfree(persistent_dep_libs);
1364 persistent_dep_libs =
NULL;
1381 u16 other_alloc = 0;
1426 if (ref_count ==
NULL)
1429 if (*ref_count != 0)
1433 ovly_section = phase_sects;
1434 while (ovly_section) {
1446 if (other_ref && *other_ref == 0) {
1450 ovly_section = other_sects_list;
1451 while (ovly_section) {
1456 ovly_section->
size, 0,
1468 if (*ref_count == 0) {
1471 ovly_section = phase_sects;
1472 while (ovly_section && !status) {
1474 (*nldr_obj->
ovly_fxn) (nldr_node_obj->
1481 ovly_section->
page);
1482 if (bytes != ovly_section->
size)
1489 if (other_ref && *other_ref == 0) {
1492 ovly_section = other_sects_list;
1493 while (ovly_section && !status) {
1495 (*nldr_obj->
ovly_fxn) (nldr_node_obj->
1502 ovly_section->
page);
1503 if (bytes != ovly_section->
size)
1512 free_sects(nldr_obj, phase_sects, alloc_num);
1513 free_sects(nldr_obj, other_sects_list, other_alloc);
1516 if (!status && (ref_count !=
NULL)) {
1529 static int remote_alloc(
void **ref,
u16 mem_sect,
u32 size,
1530 u32 align,
u32 *dsp_address,
1543 bool mem_load_req =
false;
1546 rmm = nldr_obj->
rmm;
1553 dev_dbg(bridge,
"%s: memory align to 0x%x\n", __func__, align);
1554 if (segmnt_id != -1) {
1555 rmm_addr_obj->
segid = segmnt_id;
1559 switch (hnode->
phase) {
1576 segid = hnode->
seg_id[mem_phase_bit];
1580 mem_load_req =
true;
1594 rmm_alloc(rmm, segid, word_size, align, dsp_address,
false);
1596 dev_dbg(bridge,
"%s: Unable allocate from segment %d\n",
1606 if ((nldr_obj->
seg_table[i] & mem_sect_type) !=
1610 status =
rmm_alloc(rmm, i, word_size, align,
1611 dsp_address,
false);
1621 if (status == -
ENOMEM && !mem_load_req) {
1622 dev_dbg(bridge,
"%s: Preferred segment unavailable, trying "
1623 "another\n", __func__);
1626 if ((nldr_obj->
seg_table[i] & mem_sect_type) !=
1630 status =
rmm_alloc(rmm, i, word_size, align,
1631 dsp_address,
false);
1643 static int remote_free(
void **ref,
u16 space,
u32 dsp_address,
1644 u32 size,
bool reserve)
1651 rmm = nldr_obj->
rmm;
1658 if (
rmm_free(rmm, space, dsp_address, word_size, reserve))
1676 for (i = 0; i < root->
dep_libs; i++)
1682 new_attrs.rmm_handle = nldr_obj->
rmm;
1683 new_attrs.input_params = nldr_node_obj->
priv_ref;
1684 new_attrs.base_image =
false;
1685 new_attrs.sym_arg = root;
1689 nldr_obj->
ldr_fxns.unload_fxn(root->
lib, &new_attrs);
1710 u16 other_alloc = 0;
1752 if (ref_count && (*ref_count > 0)) {
1759 if (ref_count && *ref_count == 0) {
1761 free_sects(nldr_obj, phase_sects, alloc_num);
1763 if (other_ref && *other_ref == 0)
1764 free_sects(nldr_obj, other_sects_list, other_alloc);
1770 static bool find_in_persistent_lib_array(
struct nldr_nodeobject *nldr_node_obj,
1775 for (i = 0; i < nldr_node_obj->
pers_libs; i++) {
1784 #ifdef CONFIG_TIDSPBRIDGE_BACKTRACE
1799 u32 offset_range,
void *offset_output,
char *sym_name)
1805 pr_debug(
"%s(0x%x, 0x%x, 0x%x, 0x%x, %s)\n", __func__, (
u32) nldr_node,
1806 sym_addr, offset_range, (
u32) offset_output, sym_name);
1808 if (nldr_node->dynamic && *nldr_node->phase_split) {
1809 switch (nldr_node->phase) {
1811 root = nldr_node->create_lib;
1814 root = nldr_node->execute_lib;
1817 root = nldr_node->delete_lib;
1824 root = nldr_node->root;
1827 status1 = dbll_find_dsp_symbol(root.
lib, sym_addr,
1828 offset_range, offset_output, sym_name);
1832 for (i = 0; i < root.
dep_libs; i++) {
1833 status1 = dbll_find_dsp_symbol(
1835 offset_range, offset_output, sym_name);
1842 for (i = 0; i < nldr_node->pers_libs; i++) {
1843 status1 = dbll_find_dsp_symbol(
1844 nldr_node->pers_lib_table[i].lib, sym_addr,
1845 offset_range, offset_output, sym_name);
1852 pr_debug(
"%s: Address 0x%x not found in range %d.\n",
1853 __func__, sym_addr, offset_range);