1/* 2 * Copyright 2016, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(D61_BSD) 11 */ 12 13#include <stdio.h> 14#include <assert.h> 15#include "dispatcher.h" 16#include "../system/process/process.h" 17#include <refos/refos.h> 18 19 /*! @file 20 @brief Common Process server dispatcher helper functions. */ 21 22#define PROCSERV_SYSCALL_PARAM_SIZE_MAX (REFOS_PAGE_SIZE * 8) 23static char _paramBuffer[PROCSERV_SYSCALL_PARAM_SIZE_MAX]; 24 25seL4_MessageInfo_t _dispatcherEmptyReply; 26 27int 28check_dispatch_interface(struct procserv_msg *m, void **userptr, int labelMin, int labelMax) 29{ 30 assert(userptr); 31 if (seL4_MessageInfo_get_label(m->message) != seL4_Fault_NullFault || 32 !dispatcher_badge_PID(m->badge)) { 33 /* Not a Syscall, pass onto next dispatcher. */ 34 return DISPATCH_PASS; 35 } 36 37 struct proc_pcb *pcb = pid_get_pcb_from_badge(&procServ.PIDList, m->badge); 38 if (!pcb) { 39 ROS_WARNING("Unknown client."); 40 return DISPATCH_ERROR; 41 } 42 43 seL4_Word syscallFunc = seL4_GetMR(0); 44 if (syscallFunc <= labelMin || syscallFunc >= labelMax) { 45 /* Not our type of syscall to handle. */ 46 return DISPATCH_PASS; 47 } 48 49 pcb->rpcClient.userptr = (void*) m; 50 pcb->rpcClient.minfo = m->message; 51 (*userptr) = (void*) pcb; 52 53 return DISPATCH_SUCCESS; 54} 55 56bool 57check_dispatch_caps(struct procserv_msg *m, seL4_Word unwrappedMask, int numExtraCaps) 58{ 59 assert(m); 60 if (seL4_MessageInfo_get_capsUnwrapped(m->message) != unwrappedMask || 61 seL4_MessageInfo_get_extraCaps(m->message) != numExtraCaps) { 62 return false; 63 } 64 return true; 65} 66 67seL4_CPtr 68dispatcher_copyout_cptr(seL4_CPtr c) 69{ 70 cspacepath_t cslot; 71 int error = vka_cspace_alloc_path(&procServ.vka, &cslot); 72 if (error || cslot.capPtr == 0) { 73 return (seL4_CPtr) 0; 74 } 75 cspacepath_t src; 76 vka_cspace_make_path(&procServ.vka, c, &src); 77 error = vka_cnode_copy(&cslot, &src, seL4_AllRights); 78 if (error) { 79 assert(!"dispatcher_copyout_cptr could not copy cap. Most likely a procserv bug."); 80 vka_cspace_free(&procServ.vka, cslot.capPtr); 81 return (seL4_CPtr) 0; 82 } 83 return cslot.capPtr; 84} 85 86void 87dispatcher_release_copyout_cptr(seL4_CPtr c) 88{ 89 if (!c) { 90 /* No capability here, nothing to do. */ 91 return; 92 } 93 cspacepath_t cslot; 94 vka_cspace_make_path(&procServ.vka, c, &cslot); 95 vka_cnode_revoke(&cslot); 96 vka_cnode_delete(&cslot); 97 vka_cspace_free(&procServ.vka, cslot.capPtr); 98} 99 100char* 101dispatcher_read_param(struct proc_pcb *pcb, uint32_t readLen) 102{ 103 assert(pcb && pcb->magic == REFOS_PCB_MAGIC); 104 105 /* Check that client actually has a paramBuffer set. */ 106 if (!pcb->paramBuffer && readLen) { 107 dvprintf("WARNING: no param buffer exists.") 108 return NULL; 109 } 110 111 /* Check readLen is not too big. */ 112 if (readLen > PROCSERV_SYSCALL_PARAM_SIZE_MAX) { 113 ROS_ERROR("Parameter buffer too large to be read.") 114 return NULL; 115 } 116 117 /* Reset the static temp buffer. */ 118 char *tempBuffer = _paramBuffer; 119 memset(tempBuffer, 0, PROCSERV_SYSCALL_PARAM_SIZE_MAX); 120 121 /* Read bytes out of the paramBuffer dataspace. */ 122 if (readLen > 0) { 123 int error = ram_dspace_read(tempBuffer, readLen, pcb->paramBuffer, 0); 124 if (error != ESUCCESS) { 125 ROS_ERROR("Parameter buffer failed to read from parameter buffer."); 126 assert(!"Failed to read from parameter buffer. This shouldn't happen; Procserv OOM."); 127 return NULL; 128 } 129 } 130 131 return tempBuffer; 132} 133 134