u32 mgrwrap_wait_for_bridge_events(union trapped_args *args, void *pr_ctxt) { int status = 0; struct dsp_notification *anotifications[MAX_EVENTS]; struct dsp_notification notifications[MAX_EVENTS]; u32 index, i; u32 count = args->args_mgr_wait.count; if (count > MAX_EVENTS) status = -EINVAL; CP_FM_USR(anotifications, args->args_mgr_wait.anotifications, status, count); for (i = 0; i < count; i++) { CP_FM_USR(¬ifications[i], anotifications[i], status, 1); if (status || !notifications[i].handle) { status = -EINVAL; break; } anotifications[i] = ¬ifications[i]; } if (!status) { status = mgr_wait_for_bridge_events(anotifications, count, &index, args->args_mgr_wait. timeout); } CP_TO_USR(args->args_mgr_wait.index, &index, status, 1); return status; }
u32 strmwrap_open(union trapped_args *args, void *pr_ctxt) { int status = 0; struct strm_attr attr; struct strm_res_object *strm_res_obj; struct dsp_streamattrin strm_attr_in; struct node_res_object *node_res; int strmid; find_node_handle(&node_res, pr_ctxt, args->args_strm_open.node); if (!node_res) return -EFAULT; CP_FM_USR(&attr, args->args_strm_open.attr_in, status, 1); if (attr.stream_attr_in != NULL) { CP_FM_USR(&strm_attr_in, attr.stream_attr_in, status, 1); if (!status) { attr.stream_attr_in = &strm_attr_in; if (attr.stream_attr_in->strm_mode == STRMMODE_LDMA) return -ENOSYS; } } status = strm_open(node_res->node, args->args_strm_open.direction, args->args_strm_open.index, &attr, &strm_res_obj, pr_ctxt); if (!status) { strmid = strm_res_obj->id + 1; CP_TO_USR(args->args_strm_open.stream, &strmid, status, 1); } return status; }
u32 nodewrap_alloc_msg_buf(union trapped_args *args, void *pr_ctxt) { int status = 0; struct dsp_bufferattr *pattr = NULL; struct dsp_bufferattr attr; u8 *pbuffer = NULL; struct node_res_object *node_res; find_node_handle(&node_res, pr_ctxt, args->args_node_allocmsgbuf.node); if (!node_res) return -EFAULT; if (!args->args_node_allocmsgbuf.size) return -EINVAL; if (args->args_node_allocmsgbuf.attr) { CP_FM_USR(&attr, args->args_node_allocmsgbuf.attr, status, 1); if (!status) pattr = &attr; } CP_FM_USR(&pbuffer, args->args_node_allocmsgbuf.buffer, status, 1); if (!status) { status = node_alloc_msg_buf(node_res->node, args->args_node_allocmsgbuf.size, pattr, &pbuffer); } CP_TO_USR(args->args_node_allocmsgbuf.buffer, &pbuffer, status, 1); return status; }
u32 nodewrap_allocate(union trapped_args *args, void *pr_ctxt) { int status = 0; struct dsp_uuid node_uuid; u32 cb_data_size = 0; u32 __user *psize = (u32 __user *) args->args_node_allocate.args; u8 *pargs = NULL; struct dsp_nodeattrin proc_attr_in, *attr_in = NULL; struct node_res_object *node_res; int nodeid; void *hprocessor = ((struct process_context *)pr_ctxt)->processor; if (psize) { if (get_user(cb_data_size, psize)) status = -EPERM; cb_data_size += sizeof(u32); if (!status) { pargs = kmalloc(cb_data_size, GFP_KERNEL); if (pargs == NULL) status = -ENOMEM; } CP_FM_USR(pargs, args->args_node_allocate.args, status, cb_data_size); } CP_FM_USR(&node_uuid, args->args_node_allocate.node_id_ptr, status, 1); if (status) goto func_cont; if (args->args_node_allocate.attr_in) { CP_FM_USR(&proc_attr_in, args->args_node_allocate.attr_in, status, 1); if (!status) attr_in = &proc_attr_in; else status = -ENOMEM; } if (!status) { status = node_allocate(hprocessor, &node_uuid, (struct dsp_cbdata *)pargs, attr_in, &node_res, pr_ctxt); } if (!status) { nodeid = node_res->id + 1; CP_TO_USR(args->args_node_allocate.node, &nodeid, status, 1); if (status) { status = -EFAULT; node_delete(node_res, pr_ctxt); } } func_cont: kfree(pargs); return status; }
u32 procwrap_ctrl(union trapped_args *args, void *pr_ctxt) { u32 cb_data_size, __user * psize = (u32 __user *) args->args_proc_ctrl.args; u8 *pargs = NULL; int status = 0; void *hprocessor = ((struct process_context *)pr_ctxt)->processor; if (psize) { if (get_user(cb_data_size, psize)) { status = -EPERM; goto func_end; } cb_data_size += sizeof(u32); pargs = kmalloc(cb_data_size, GFP_KERNEL); if (pargs == NULL) { status = -ENOMEM; goto func_end; } CP_FM_USR(pargs, args->args_proc_ctrl.args, status, cb_data_size); } if (!status) { status = proc_ctrl(hprocessor, args->args_proc_ctrl.cmd, (struct dsp_cbdata *)pargs); } kfree(pargs); func_end: return status; }
u32 nodewrap_free_msg_buf(union trapped_args *args, void *pr_ctxt) { int status = 0; struct dsp_bufferattr *pattr = NULL; struct dsp_bufferattr attr; struct node_res_object *node_res; find_node_handle(&node_res, pr_ctxt, args->args_node_freemsgbuf.node); if (!node_res) return -EFAULT; if (args->args_node_freemsgbuf.attr) { CP_FM_USR(&attr, args->args_node_freemsgbuf.attr, status, 1); if (!status) pattr = &attr; } if (!args->args_node_freemsgbuf.buffer) return -EFAULT; if (!status) { status = node_free_msg_buf(node_res->node, args->args_node_freemsgbuf.buffer, pattr); } return status; }
u32 strmwrap_select(union trapped_args *args, void *pr_ctxt) { u32 mask; struct strm_object *strm_tab[MAX_STREAMS]; int status = 0; struct strm_res_object *strm_res; int *ids[MAX_STREAMS]; int i; if (args->args_strm_select.strm_num > MAX_STREAMS) return -EINVAL; CP_FM_USR(ids, args->args_strm_select.stream_tab, status, args->args_strm_select.strm_num); if (status) return status; for (i = 0; i < args->args_strm_select.strm_num; i++) { find_strm_handle(&strm_res, pr_ctxt, ids[i]); if (!strm_res) return -EFAULT; strm_tab[i] = strm_res->stream; } if (!status) { status = strm_select(strm_tab, args->args_strm_select.strm_num, &mask, args->args_strm_select.timeout); } CP_TO_USR(args->args_strm_select.mask, &mask, status, 1); return status; }
u32 strmwrap_get_info(union trapped_args *args, void *pr_ctxt) { int status = 0; struct stream_info strm_info; struct dsp_streaminfo user; struct dsp_streaminfo *temp; struct strm_res_object *strm_res; find_strm_handle(&strm_res, pr_ctxt, args->args_strm_getinfo.stream); if (!strm_res) return -EFAULT; CP_FM_USR(&strm_info, args->args_strm_getinfo.stream_info, status, 1); temp = strm_info.user_strm; strm_info.user_strm = &user; if (!status) { status = strm_get_info(strm_res->stream, &strm_info, args->args_strm_getinfo. stream_info_size); } CP_TO_USR(temp, strm_info.user_strm, status, 1); strm_info.user_strm = temp; CP_TO_USR(args->args_strm_getinfo.stream_info, &strm_info, status, 1); return status; }
u32 strmwrap_free_buffer(union trapped_args *args, void *pr_ctxt) { int status = 0; u8 **ap_buffer = NULL; u32 num_bufs = args->args_strm_freebuffer.num_bufs; struct strm_res_object *strm_res; find_strm_handle(&strm_res, pr_ctxt, args->args_strm_freebuffer.stream); if (!strm_res) return -EFAULT; if (num_bufs > MAX_BUFS) return -EINVAL; ap_buffer = kmalloc((num_bufs * sizeof(u8 *)), GFP_KERNEL); if (ap_buffer == NULL) return -ENOMEM; CP_FM_USR(ap_buffer, args->args_strm_freebuffer.ap_buffer, status, num_bufs); if (!status) status = strm_free_buffer(strm_res, ap_buffer, num_bufs, pr_ctxt); CP_TO_USR(args->args_strm_freebuffer.ap_buffer, ap_buffer, status, num_bufs); kfree(ap_buffer); return status; }
u32 nodewrap_register_notify(union trapped_args *args, void *pr_ctxt) { int status = 0; struct dsp_notification notification; struct node_res_object *node_res; find_node_handle(&node_res, pr_ctxt, args->args_node_registernotify.node); if (!node_res) return -EFAULT; notification.name = NULL; notification.handle = NULL; if (!args->args_proc_register_notify.event_mask) CP_FM_USR(¬ification, args->args_proc_register_notify.notification, status, 1); status = node_register_notify(node_res->node, args->args_node_registernotify.event_mask, args->args_node_registernotify. notify_type, ¬ification); CP_TO_USR(args->args_node_registernotify.notification, ¬ification, status, 1); return status; }
u32 mgrwrap_unregister_object(union trapped_args *args, void *pr_ctxt) { int status = 0; struct dsp_uuid uuid_obj; CP_FM_USR(&uuid_obj, args->args_mgr_registerobject.uuid_obj, status, 1); if (status) goto func_end; status = dcd_unregister_object(&uuid_obj, args->args_mgr_unregisterobject. obj_type); func_end: return status; }
u32 nodewrap_put_message(union trapped_args *args, void *pr_ctxt) { int status = 0; struct dsp_msg msg; struct node_res_object *node_res; find_node_handle(&node_res, pr_ctxt, args->args_node_putmessage.node); if (!node_res) return -EFAULT; CP_FM_USR(&msg, args->args_node_putmessage.message, status, 1); if (!status) { status = node_put_message(node_res->node, &msg, args->args_node_putmessage.timeout); } return status; }
u32 mgrwrap_register_object(union trapped_args *args, void *pr_ctxt) { u32 ret; struct dsp_uuid uuid_obj; u32 path_size = 0; char *psz_path_name = NULL; int status = 0; CP_FM_USR(&uuid_obj, args->args_mgr_registerobject.uuid_obj, status, 1); if (status) goto func_end; path_size = strlen_user((char *) args->args_mgr_registerobject.sz_path_name) + 1; psz_path_name = kmalloc(path_size, GFP_KERNEL); if (!psz_path_name) { status = -ENOMEM; goto func_end; } ret = strncpy_from_user(psz_path_name, (char *)args->args_mgr_registerobject. sz_path_name, path_size); if (!ret) { status = -EFAULT; goto func_end; } if (args->args_mgr_registerobject.obj_type >= DSP_DCDMAXOBJTYPE) { status = -EINVAL; goto func_end; } status = dcd_register_object(&uuid_obj, args->args_mgr_registerobject.obj_type, (char *)psz_path_name); func_end: kfree(psz_path_name); return status; }
u32 procwrap_attach(union trapped_args *args, void *pr_ctxt) { void *processor; int status = 0; struct dsp_processorattrin proc_attr_in, *attr_in = NULL; if (args->args_proc_attach.attr_in) { CP_FM_USR(&proc_attr_in, args->args_proc_attach.attr_in, status, 1); if (!status) attr_in = &proc_attr_in; else goto func_end; } status = proc_attach(args->args_proc_attach.processor_id, attr_in, &processor, pr_ctxt); CP_TO_USR(args->args_proc_attach.ph_processor, &processor, status, 1); func_end: return status; }
u32 nodewrap_get_uuid_props(union trapped_args *args, void *pr_ctxt) { int status = 0; struct dsp_uuid node_uuid; struct dsp_ndbprops *pnode_props = NULL; void *hprocessor = ((struct process_context *)pr_ctxt)->processor; CP_FM_USR(&node_uuid, args->args_node_getuuidprops.node_id_ptr, status, 1); if (status) goto func_cont; pnode_props = kmalloc(sizeof(struct dsp_ndbprops), GFP_KERNEL); if (pnode_props != NULL) { status = node_get_uuid_props(hprocessor, &node_uuid, pnode_props); CP_TO_USR(args->args_node_getuuidprops.node_props, pnode_props, status, 1); } else status = -ENOMEM; func_cont: kfree(pnode_props); return status; }
u32 procwrap_load(union trapped_args *args, void *pr_ctxt) { s32 i, len; int status = 0; char *temp; s32 count = args->args_proc_load.argc_index; u8 **argv = NULL, **envp = NULL; void *hprocessor = ((struct process_context *)pr_ctxt)->processor; if (count <= 0 || count > MAX_LOADARGS) { status = -EINVAL; goto func_cont; } argv = kmalloc(count * sizeof(u8 *), GFP_KERNEL); if (!argv) { status = -ENOMEM; goto func_cont; } CP_FM_USR(argv, args->args_proc_load.user_args, status, count); if (status) { kfree(argv); argv = NULL; goto func_cont; } for (i = 0; i < count; i++) { if (argv[i]) { temp = (char *)argv[i]; len = strlen_user((char *)temp) + 1; argv[i] = kmalloc(len, GFP_KERNEL); if (argv[i]) { CP_FM_USR(argv[i], temp, status, len); if (status) { kfree(argv[i]); argv[i] = NULL; goto func_cont; } } else { status = -ENOMEM; goto func_cont; } } } if (args->args_proc_load.user_envp) { count = 0; do { if (get_user(temp, args->args_proc_load.user_envp + count)) { status = -EFAULT; goto func_cont; } count++; } while (temp); envp = kmalloc(count * sizeof(u8 *), GFP_KERNEL); if (!envp) { status = -ENOMEM; goto func_cont; } CP_FM_USR(envp, args->args_proc_load.user_envp, status, count); if (status) { kfree(envp); envp = NULL; goto func_cont; } for (i = 0; envp[i]; i++) { temp = (char *)envp[i]; len = strlen_user((char *)temp) + 1; envp[i] = kmalloc(len, GFP_KERNEL); if (envp[i]) { CP_FM_USR(envp[i], temp, status, len); if (status) { kfree(envp[i]); envp[i] = NULL; goto func_cont; } } else { status = -ENOMEM; goto func_cont; } } } if (!status) { status = proc_load(hprocessor, args->args_proc_load.argc_index, (const char **)argv, (const char **)envp); } func_cont: if (envp) { i = 0; while (envp[i]) kfree(envp[i++]); kfree(envp); } if (argv) { count = args->args_proc_load.argc_index; for (i = 0; (i < count) && argv[i]; i++) kfree(argv[i]); kfree(argv); } return status; }
u32 nodewrap_connect(union trapped_args *args, void *pr_ctxt) { int status = 0; struct dsp_strmattr attrs; struct dsp_strmattr *pattrs = NULL; u32 cb_data_size; u32 __user *psize = (u32 __user *) args->args_node_connect.conn_param; u8 *pargs = NULL; struct node_res_object *node_res1, *node_res2; struct node_object *node1 = NULL, *node2 = NULL; if ((int)args->args_node_connect.node != DSP_HGPPNODE) { find_node_handle(&node_res1, pr_ctxt, args->args_node_connect.node); if (node_res1) node1 = node_res1->node; } else { node1 = args->args_node_connect.node; } if ((int)args->args_node_connect.other_node != DSP_HGPPNODE) { find_node_handle(&node_res2, pr_ctxt, args->args_node_connect.other_node); if (node_res2) node2 = node_res2->node; } else { node2 = args->args_node_connect.other_node; } if (!node1 || !node2) return -EFAULT; if (psize) { if (get_user(cb_data_size, psize)) status = -EPERM; cb_data_size += sizeof(u32); if (!status) { pargs = kmalloc(cb_data_size, GFP_KERNEL); if (pargs == NULL) { status = -ENOMEM; goto func_cont; } } CP_FM_USR(pargs, args->args_node_connect.conn_param, status, cb_data_size); if (status) goto func_cont; } if (args->args_node_connect.attrs) { CP_FM_USR(&attrs, args->args_node_connect.attrs, status, 1); if (!status) pattrs = &attrs; } if (!status) { status = node_connect(node1, args->args_node_connect.stream_id, node2, args->args_node_connect.other_stream, pattrs, (struct dsp_cbdata *)pargs); } func_cont: kfree(pargs); return status; }
/* * ======== procwrap_load ======== */ u32 procwrap_load(union trapped_args *args, void *pr_ctxt) { s32 i, len; int status = 0; char *temp; s32 count = args->args_proc_load.argc_index; u8 **argv = NULL, **envp = NULL; void *hprocessor = ((struct process_context *)pr_ctxt)->processor; if (count <= 0 || count > MAX_LOADARGS) { status = -EINVAL; goto func_cont; } argv = kmalloc(count * sizeof(u8 *), GFP_KERNEL); if (!argv) { status = -ENOMEM; goto func_cont; } CP_FM_USR(argv, args->args_proc_load.user_args, status, count); if (status) { kfree(argv); argv = NULL; goto func_cont; } for (i = 0; i < count; i++) { if (argv[i]) { /* User space pointer to argument */ temp = (char *)argv[i]; /* len is increased by 1 to accommodate NULL */ len = strlen_user((char *)temp) + 1; /* Kernel space pointer to argument */ argv[i] = kmalloc(len, GFP_KERNEL); if (argv[i]) { CP_FM_USR(argv[i], temp, status, len); if (status) { kfree(argv[i]); argv[i] = NULL; goto func_cont; } } else { status = -ENOMEM; goto func_cont; } } } /* TODO: validate this */ if (args->args_proc_load.user_envp) { /* number of elements in the envp array including NULL */ count = 0; do { if (get_user(temp, args->args_proc_load.user_envp + count)) { status = -EFAULT; goto func_cont; } count++; } while (temp); envp = kmalloc(count * sizeof(u8 *), GFP_KERNEL); if (!envp) { status = -ENOMEM; goto func_cont; } CP_FM_USR(envp, args->args_proc_load.user_envp, status, count); if (status) { kfree(envp); envp = NULL; goto func_cont; } for (i = 0; envp[i]; i++) { /* User space pointer to argument */ temp = (char *)envp[i]; /* len is increased by 1 to accommodate NULL */ len = strlen_user((char *)temp) + 1; /* Kernel space pointer to argument */ envp[i] = kmalloc(len, GFP_KERNEL); if (envp[i]) { CP_FM_USR(envp[i], temp, status, len); if (status) { kfree(envp[i]); envp[i] = NULL; goto func_cont; } } else { status = -ENOMEM; goto func_cont; } } } if (!status) { status = proc_load(hprocessor, args->args_proc_load.argc_index, (const char **)argv, (const char **)envp); } func_cont: if (envp) { i = 0; while (envp[i]) kfree(envp[i++]); kfree(envp); } if (argv) { count = args->args_proc_load.argc_index; for (i = 0; (i < count) && argv[i]; i++) kfree(argv[i]); kfree(argv); } return status; }