/*! \brief Call from external dataserver asking to be the content initialiser for this dataspace. */ refos_err_t data_have_data_handler(void *rpc_userptr , seL4_CPtr rpc_dspace_fd , seL4_CPtr rpc_faultNotifyEP , uint32_t* rpc_dataID) { struct proc_pcb *pcb = (struct proc_pcb*) rpc_userptr; struct procserv_msg *m = (struct procserv_msg*) pcb->rpcClient.userptr; assert(pcb && pcb->magic == REFOS_PCB_MAGIC); if (!(check_dispatch_caps(m, 0x00000001, 2) || check_dispatch_caps(m, 0x00000001, 1))) { return EINVALIDPARAM; } if (rpc_dataID) { (*rpc_dataID) = 0; } /* Verify and find the RAM dataspace. */ if (!dispatcher_badge_dspace(rpc_dspace_fd)) { ROS_ERROR("EINVALIDPARAM: invalid RAM dataspace badge..\n"); return EINVALIDPARAM; } struct ram_dspace *dspace = ram_dspace_get_badge(&procServ.dspaceList, rpc_dspace_fd); if (!dspace) { ROS_ERROR("EINVALIDPARAM: dataspace not found.\n"); return EINVALIDPARAM; } /* Special case - no fault notify EP, means unset content-init mode. */ if (!rpc_faultNotifyEP) { cspacepath_t path; vka_cspace_make_path(&procServ.vka, 0, &path); return ram_dspace_content_init(dspace, path, PID_NULL); } /* Copyout the content-init fault notify EP. */ seL4_CPtr faultNotifyEP = dispatcher_copyout_cptr(rpc_faultNotifyEP); if (!faultNotifyEP) { dvprintf("could not copy out faultNotifyEP."); return EINVALIDPARAM; } cspacepath_t path; vka_cspace_make_path(&procServ.vka, faultNotifyEP, &path); /* Initialise the dataspace content with given dataserver EP. */ int error = ram_dspace_content_init(dspace, path, pcb->pid); if (error != ESUCCESS) { dispatcher_release_copyout_cptr(faultNotifyEP); return error; } if (rpc_dataID) { (*rpc_dataID) = dspace->ID; } return ESUCCESS; }
/*! @brief Handles client watching syscalls. Most servers would need to call this in order to be notified of client death in order to be able to delete any internal book-keeping for the dead client. */ refos_err_t proc_watch_client_handler(void *rpc_userptr , seL4_CPtr rpc_liveness , seL4_CPtr rpc_deathEP , int32_t* rpc_deathID) { struct proc_pcb *pcb = (struct proc_pcb*) rpc_userptr; struct procserv_msg *m = (struct procserv_msg*) pcb->rpcClient.userptr; assert(pcb->magic == REFOS_PCB_MAGIC); if (!check_dispatch_caps(m, 0x00000001, 2)) { return EINVALIDPARAM; } /* Retrieve the corresponding client's ASID unwrapped from its liveness cap. */ if (!dispatcher_badge_liveness(rpc_liveness)) { return EINVALIDPARAM; } /* Verify the corresponding client. */ struct proc_pcb *client = pid_get_pcb(&procServ.PIDList, rpc_liveness - PID_LIVENESS_BADGE_BASE); if (!client) { return EINVALIDPARAM; } assert(client->magic == REFOS_PCB_MAGIC); /* Copy out the death notification endpoint. */ seL4_CPtr deathNotifyEP = dispatcher_copyout_cptr(rpc_deathEP); if (!deathNotifyEP) { ROS_ERROR("could not copy out deathNotifyEP."); return ENOMEM; } /* Add the new client to the watch list of the calling process. */ int error = client_watch(&pcb->clientWatchList, client->pid, deathNotifyEP); if (error) { ROS_ERROR("failed to add to watch list. Procserv possibly out of memory."); dispatcher_release_copyout_cptr(deathNotifyEP); return error; } if (rpc_deathID) { (*rpc_deathID) = client->pid; } return ESUCCESS; }