/* Example template for processing the following interfaces: coyotos.IoStream */ #include #include #include #include #include #include #include /* Utility quasi-syntax */ #define unless(x) if (!(x)) #include typedef union { _IDL_IFUNION_coyotos_IoStream coyotos_IoStream; InvParameterBlock_t pb; InvExceptionParameterBlock_t except; uintptr_t icw; } _IDL_GRAND_SERVER_UNION; /* You should supply a function that selects an interface * type based on the incoming endpoint ID and protected * payload */ extern uint64_t choose_if(uint64_t epID, uint32_t pp); /* The IDL_SERVER_Environment structure type is something * that you should extend to hold any "extra" information * you need to carry around in your handlers. CapIDL code * will pass this pointer along, but knows absolutely * nothing about the contents of the structure. * * The following structure definition is provided as a * starting point. It is generally a good idea to pass the * received protected payload and endpoint ID to handler * functions so that they know what object was invoked and * with what permissions. */ typedef struct IDL_SERVER_Environment { uint32_t pp; uint64_t epID; } IDL_SERVER_Environment; void ProcessRequests(struct IDL_SERVER_Environment *_env) { _IDL_GRAND_SERVER_UNION gsu; gsu.icw = 0; gsu.pb.sndPtr = 0; gsu.pb.sndLen = 0; for(;;) { gsu.icw &= (IPW0_LDW_MASK|IPW0_LSC_MASK |IPW0_SG|IPW0_SP|IPW0_SC|IPW0_EX); gsu.icw |= IPW0_MAKE_NR(sc_InvokeCap)|IPW0_RP|IPW0_AC |IPW0_MAKE_LRC(3)|IPW0_NB|IPW0_CO; gsu.pb.u.invCap = CR_RETURN; gsu.pb.rcvCap[0] = CR_RETURN; gsu.pb.rcvCap[1] = CR_ARG0; gsu.pb.rcvCap[2] = CR_ARG1; gsu.pb.rcvCap[3] = CR_ARG2; gsu.pb.rcvBound = (sizeof(gsu) - sizeof(gsu.pb)); gsu.pb.rcvPtr = ((char *)(&gsu)) + sizeof(gsu.pb); invoke_capability(&gsu.pb); _env->pp = gsu.pb.u.pp; _env->epID = gsu.pb.epID; /* Re-establish defaults. Note we rely on the handler proc * to decide how MANY of these caps will be sent by setting ICW.SC * and ICW.lsc fields properly. */ gsu.pb.sndCap[0] = CR_REPLY0; gsu.pb.sndCap[1] = CR_REPLY1; gsu.pb.sndCap[2] = CR_REPLY2; gsu.pb.sndCap[3] = CR_REPLY3; /* We rely on the (de)marshaling procedures to set sndLen to zero * if no string is to be sent. We cannot zero it preemptively here * because sndLen is an IN parameter telling how many bytes we got. * Set sndPtr to zero so that we will fault if this is mishandled. */ gsu.pb.sndPtr = 0; if ((gsu.icw & IPW0_SC) == 0) { /* Protocol violation -- reply slot unpopulated. */ gsu.icw = 0; gsu.pb.sndLen = 0; continue; } switch(choose_if(gsu.pb.epID, gsu.pb.u.pp)) { case IKT_coyotos_IoStream: _IDL_IFDISPATCH_coyotos_IoStream(&gsu.coyotos_IoStream, _env); break; default: { gsu.except.icw = IPW0_MAKE_LDW((sizeof(gsu.except)/sizeof(uintptr_t))-1) |IPW0_EX|IPW0_SP; gsu.except.exceptionCode = RC_coyotos_Cap_UnknownRequest; gsu.pb.sndLen = 0; break; } } } } static inline bool exit_gracelessly(errcode_t errCode) { return coyotos_SpaceBank_destroyBankAndReturn(CR_SPACEBANK, CR_RETURN, errCode); } bool initialize() { unless( /* Set up our entry capability */ coyotos_Endpoint_makeEntryCap(CR_INITEPT, 1 /* Insert your PP value here */, CR_REPLY0) )exit_gracelessly(IDL_exceptCode); /* Send our entry cap to our caller */ REPLY_create(CR_RETURN, CR_REPLY0); return true; } int main(int argc, char *argv[]) { struct IDL_SERVER_Environment ise; if (!initialize()) return 0; ProcessRequests(&ise); return 0; }