Coverity fixes
[keystone-rtos/rm-lld.git] / src / rm.c
1 /**
2  *   @file  rm.c
3  *
4  *   @brief   
5  *      This is the Resource Manager source.
6  *
7  *  \par
8  *  ============================================================================
9  *  @n   (C) Copyright 2012-2013, Texas Instruments, Inc.
10  * 
11  *  Redistribution and use in source and binary forms, with or without 
12  *  modification, are permitted provided that the following conditions 
13  *  are met:
14  *
15  *    Redistributions of source code must retain the above copyright 
16  *    notice, this list of conditions and the following disclaimer.
17  *
18  *    Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the 
20  *    documentation and/or other materials provided with the   
21  *    distribution.
22  *
23  *    Neither the name of Texas Instruments Incorporated nor the names of
24  *    its contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
28  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
29  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
31  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
32  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
33  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
36  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
37  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38  *
39  *  \par
40 */
42 /* Standard includes */
43 #include <stdint.h>
44 #include <string.h>
46 /* RM external includes */
47 #include <ti/drv/rm/rm.h>
48 #include <ti/drv/rm/rmver.h>
49 #include <ti/drv/rm/rm_services.h>
50 #include <ti/drv/rm/rm_transport.h>
52 /* RM internal includes */
53 #include <ti/drv/rm/include/rm_internal.h>
54 #include <ti/drv/rm/include/rm_loc.h>
55 #include <ti/drv/rm/include/rm_allocatorloc.h>
56 #include <ti/drv/rm/include/rm_transportloc.h>
57 #include <ti/drv/rm/include/rm_nameserverloc.h>
58 #include <ti/drv/rm/include/rm_servicesloc.h>
60 /* RM LIBFDT includes */
61 #include <ti/drv/rm/util/libfdt/libfdt.h>
63 /* RM OSAL layer */
64 #include <rm_osal.h>
66 /**********************************************************************
67  ************************** Globals ***********************************
68  **********************************************************************/
70 /* Global Variable which describes the RM Version Information */
71 const char  rmVersionStr[] = RM_VERSION_STR ":" __DATE__  ":" __TIME__;
73 /**********************************************************************
74  ************************ Local Functions *****************************
75  **********************************************************************/
77 /* FUNCTION PURPOSE: Initializes a RM inst's transaction sequence number
78  ***********************************************************************
79  * DESCRIPTION: The RM instance transaction sequence number can never
80  *              have a value of 0 to avoid conflicts with transactions
81  *              that have a remoteOriginatingId of 0 (transaction ID
82  *              will be used as the remoteOriginatingId for
83  *              transactions that are responses to requests).
84  */
85 static uint32_t transactionInitSequenceNum(void)
86 {
87     return (1);
88 }
90 /* FUNCTION PURPOSE: Provides a sequence number for new transactions
91  ***********************************************************************
92  * DESCRIPTION: Returns a sequence number for a new transaction
93  *              specific to a RM instance.  Handles rollover of
94  *              sequence number.
95  */
96 static uint32_t transactionGetSequenceNum(Rm_Inst *rmInst)
97 {
98     rmInst->transactionSeqNum++;
99     if (!rmInst->transactionSeqNum) {
100         rmInst->transactionSeqNum++;
101     }    
102     return (rmInst->transactionSeqNum);
105 /* FUNCTION PURPOSE: Creates a resource request packet
106  ***********************************************************************
107  * DESCRIPTION: Returns a RM packet handle that points to a RM
108  *              resource request packet that has been prepared
109  *              for sending to another RM instance.  The packet
110  *              is allocated via the rmAllocPkt API using the
111  *              appTransport handle provided by the application
112  */
113 void createResourceReqPkt(Rm_Packet *rmPkt, char *localInstName, Rm_Transaction *transaction)
115     Rm_ResourceRequestPkt *resourceReqPkt = NULL;
116        
117     rmPkt->pktType = Rm_pktType_RESOURCE_REQUEST;
118     resourceReqPkt = (Rm_ResourceRequestPkt *) rmPkt->data;
119     resourceReqPkt->requestId = transaction->localId;
120     if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
121         resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE_INIT;
122     }
123     else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
124         resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE_USE;
125     }    
126     else if (transaction->type == Rm_service_RESOURCE_FREE) {
127         resourceReqPkt->resourceReqType = Rm_resReqPktType_FREE;
128     }
129     else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {
130         resourceReqPkt->resourceReqType = Rm_resReqPktType_GET_NAMED;
131     }
132     strncpy(resourceReqPkt->pktSrcInstName, localInstName, RM_NAME_MAX_CHARS);
133     strncpy(resourceReqPkt->serviceSrcInstName, transaction->serviceSrcInstName, RM_NAME_MAX_CHARS);
134     memcpy ((void *)&(resourceReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),
135             sizeof(Rm_ResourceInfo));
138 /* FUNCTION PURPOSE: Creates a resource response packet
139  ***********************************************************************
140  * DESCRIPTION: Returns a RM packet handle that points to a RM
141  *              resource response packet that has been prepared
142  *              for sending to another RM instance.  The packet
143  *              is allocated via the rmAllocPkt API using the
144  *              appTransport handle provided by the application
145  */
146 void createResourceResponsePkt(Rm_Packet *rmPkt, Rm_Transaction *transaction)
148     Rm_ResourceResponsePkt *resourceRespPkt = NULL;
149      
150     rmPkt->pktType = Rm_pktType_RESOURCE_RESPONSE;                 
151     resourceRespPkt = (Rm_ResourceResponsePkt *)rmPkt->data;
152     resourceRespPkt->responseId = transaction->remoteOriginatingId;
153     resourceRespPkt->requestState = transaction->state;
154     memcpy ((void *)&(resourceRespPkt->resourceInfo), (void *)&(transaction->resourceInfo),
155             sizeof(Rm_ResourceInfo));
158 /* FUNCTION PURPOSE: Creates a NameServer request packet
159  ***********************************************************************
160  * DESCRIPTION: Returns a RM packet handle that points to a RM
161  *              NameServer request packet that has been prepared
162  *              for sending to another RM instance.  The packet
163  *              is allocated via the rmAllocPkt API using the
164  *              appTransport handle provided by the application
165  */
166 void createNsRequestPkt(Rm_Packet *rmPkt, char *localInstName, Rm_Transaction *transaction)
167
168     Rm_NsRequestPkt *nsReqPkt = NULL;
170     rmPkt->pktType = Rm_pktType_NAMESERVER_REQUEST;                   
171     nsReqPkt = (Rm_NsRequestPkt *)rmPkt->data;
172     nsReqPkt->requestId = transaction->localId;
173     if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {
174         nsReqPkt->nsRequestType = Rm_nsReqPktType_MAP_RESOURCE;
175     }
176     else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {
177         nsReqPkt->nsRequestType = Rm_nsReqPktType_UNMAP_RESOURCE;
178     }
179     strncpy(nsReqPkt->pktSrcInstName, localInstName, RM_NAME_MAX_CHARS);
180     strncpy(nsReqPkt->serviceSrcInstName, transaction->serviceSrcInstName, RM_NAME_MAX_CHARS);
181     memcpy ((void *)&(nsReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),
182             sizeof(Rm_ResourceInfo));
185 /* FUNCTION PURPOSE: Creates a NameServer response packet
186  ***********************************************************************
187  * DESCRIPTION: Returns a RM packet handle that points to a RM
188  *              NameServer response packet that has been prepared
189  *              for sending to another RM instance.  The packet
190  *              is allocated via the rmAllocPkt API using the
191  *              appTransport handle provided by the application
192  */
193 void createNsResponsePkt(Rm_Packet *rmPkt, Rm_Transaction *transaction)
195     Rm_NsResponsePkt *nsRespPkt = NULL;
197     rmPkt->pktType = Rm_pktType_NAMESERVER_RESPONSE;                
198     nsRespPkt = (Rm_NsResponsePkt *)rmPkt->data;
199     nsRespPkt->responseId = transaction->remoteOriginatingId;
200     nsRespPkt->requestState = transaction->state;
203 /* FUNCTION PURPOSE: Issues a service response to application
204  ***********************************************************************
205  * DESCRIPTION: Provides a service response back to the application
206  *              using the service callback function provided to
207  *              the RM instance at the time of the service request.
208  */
209 static void serviceResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)
211     Rm_ServiceRespInfo serviceResponse;
213     serviceResponse.rmHandle = (Rm_Handle)rmInst;
214     /* The responseTransaction will contain the resultant state details of
215      * the requestTransaction's service request */
216     serviceResponse.serviceState = transaction->state;
217     /* Pass back the ID that was provided to the component when it requested
218      * the service */
219     serviceResponse.serviceId = transaction->localId;
221     /* Service was approved and service was an allocate request.  The resource
222      * data is passed back to the component */
223     if ((serviceResponse.serviceState == RM_SERVICE_APPROVED) &&
224         ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
225          (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||
226          (transaction->type == Rm_service_RESOURCE_GET_BY_NAME)))
227     {
228         strncpy(serviceResponse.resourceName, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
229         serviceResponse.resourceBase = transaction->resourceInfo.base;
230         serviceResponse.resourceLength = transaction->resourceInfo.length;
231     }
233     if (transaction->callback.serviceCallback) {
234         /* Issue the callback to the requesting component with the response information */
235         transaction->callback.serviceCallback(&serviceResponse);
236         /* Delete the transaction from the transaction queue */
237         rmTransactionQueueDelete(rmInst, transaction->localId);
238     }
239     else {
240         rmServiceInternalCallback((Rm_Handle)rmInst);
241     }
242     
243     return;
246 /* FUNCTION PURPOSE: Sends RM response packets
247  ***********************************************************************
248  * DESCRIPTION: Sends RM response packets to RM instance's that sent
249  *              RM request packets to the RM instance.  The response
250  *              is sent via the RM transport API which is plugged
251  *              with an application created transport path.
252  */
253 static void transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)
255     Rm_Transport    *dstTransport = NULL;
256     Rm_Packet       *rmPkt = NULL;
257     Rm_PacketHandle  pktHandle = NULL;
259     if (dstTransport = rmTransportFindRemoteName(rmInst->transports, transaction->pktSrcInstName)) {
260         rmPkt = dstTransport->callouts.rmAllocPkt(dstTransport->appTransportHandle, 
261                                                   sizeof(Rm_Packet), &pktHandle);
262         if (!rmPkt || !pktHandle) {
263             transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;
264             goto errorExit;
265         }
267         switch (transaction->type) {
268             case Rm_service_RESOURCE_ALLOCATE_INIT:
269             case Rm_service_RESOURCE_ALLOCATE_USE:
270             case Rm_service_RESOURCE_FREE:
271             case Rm_service_RESOURCE_GET_BY_NAME:
272                 createResourceResponsePkt(rmPkt, transaction);
273                 break;
274             case Rm_service_RESOURCE_MAP_TO_NAME:
275             case Rm_service_RESOURCE_UNMAP_NAME:
276                 createNsResponsePkt(rmPkt, transaction);
277                 break;
278         }
279         if (dstTransport->callouts.rmSendPkt(dstTransport->appTransportHandle, pktHandle) < RM_OK) {
280             transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;
281             goto errorExit;
282         }
283         
284         /* Response packet sent: Delete transaction from queue */
285         rmTransactionQueueDelete(rmInst, transaction->localId);
286     }
287     else {
288         transaction->state = RM_ERROR_TRANSPORT_REMOTE_HNDL_NOT_REGD;
289     }
290 errorExit:
291     /* Do not delete transaction on transport error.  Transport rrror transactions should be visible
292      * from Rm_printInstanceStatus() */
293     return;
296 /* FUNCTION PURPOSE: Sends RM request packets
297  ***********************************************************************
298  * DESCRIPTION: Sends RM request packets to RM instance's that are
299  *              capable of forwarding or validating service requests.
300  *              The request is sent via the RM transport API which is
301  *              plugged with an application created transport path.
302  */
303 static void transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction)
305     Rm_Transport    *dstTransport = NULL;
306     Rm_Packet       *rmPkt = NULL;    
307     Rm_PacketHandle  pktHandle = NULL;
309     if (rmInst->instType == Rm_instType_CLIENT) {
310         dstTransport = rmTransportFindRemoteInstType(rmInst->transports, Rm_instType_CLIENT_DELEGATE);
312         if (!dstTransport) {
313             dstTransport = rmTransportFindRemoteInstType(rmInst->transports, Rm_instType_SERVER);
314         }
315     } 
316     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
317         dstTransport = rmTransportFindRemoteInstType(rmInst->transports, Rm_instType_SERVER);
318     }
320     /* Just queue transaction if transport hasn't been registered.  Do not return error */
321     if (dstTransport) {            
322         rmPkt = dstTransport->callouts.rmAllocPkt(dstTransport->appTransportHandle, 
323                                                   sizeof(Rm_Packet), &pktHandle);
324         if (!rmPkt || !pktHandle) {
325             transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;
326             goto errorExit;
327         }
329         switch (transaction->type) {
330             case Rm_service_RESOURCE_ALLOCATE_INIT:
331             case Rm_service_RESOURCE_ALLOCATE_USE:
332             case Rm_service_RESOURCE_FREE:
333             case Rm_service_RESOURCE_GET_BY_NAME:
334                 createResourceReqPkt(rmPkt, rmInst->instName, transaction);
335                 break;
336             case Rm_service_RESOURCE_MAP_TO_NAME:
337             case Rm_service_RESOURCE_UNMAP_NAME:
338                 createNsRequestPkt(rmPkt, rmInst->instName, transaction);
339                 break;
340         }
341   
342         if (dstTransport->callouts.rmSendPkt(dstTransport->appTransportHandle, pktHandle) < RM_OK) {
343             transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;
344             goto errorExit;
345         }              
346         transaction->hasBeenForwarded = RM_TRUE;
347         /* Transaction not deleted.  Waiting for response from RM CD or Server */
348     }
349 errorExit: 
350     /* Do not delete transaction on transport error.  Transport error transactions should be visible
351      * from Rm_printInstanceStatus() */               
352     return;
355 /* FUNCTION PURPOSE: Handles static allocation requests
356  ***********************************************************************
357  * DESCRIPTION: Validates allocation requests received on CDs and
358  *              Clients prior to the instance's registering
359  *              with a Server.  The allocation request is validated
360  *              against a static policy.
361  */
362 static void staticAllocationHandler (Rm_Handle rmHandle, Rm_Transaction *transaction)
364     Rm_Inst           *rmInst = (Rm_Inst *)rmHandle;
365     void              *staticPolicy = rmPolicyGetPolicy(rmHandle);
366     Rm_PolicyCheckCfg  privCheckCfg;
367     int32_t            result;
368     
369     if (staticPolicy) {
370         if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
371             (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE)) {
372             /* Check request against static policy */
373             memset((void *)&privCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));
374     
375             if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
376                 privCheckCfg.type = Rm_policyCheck_INIT;
377             }
378             else {
379                 privCheckCfg.type = Rm_policyCheck_USE;
380             }
381             privCheckCfg.policyDtb = staticPolicy;
382             privCheckCfg.validInstNode = rmPolicyGetValidInstNode(rmHandle, rmInst->instName);
383             privCheckCfg.resourceOffset = rmPolicyGetResourceOffset(staticPolicy,
384                                                                     transaction->resourceInfo.name);
385             privCheckCfg.resourceBase = transaction->resourceInfo.base;
386             privCheckCfg.resourceLength = transaction->resourceInfo.length;
387     
388             if (rmPolicyCheckPrivilege(&privCheckCfg, &result)) {
389                 transaction->state = RM_SERVICE_APPROVED_STATIC;
390             }
391             else if (result == RM_OK) {
392                 /* Privilege check returned false without error */
393                 transaction->state = RM_SERVICE_DENIED_BY_STATIC_POLICY;
394             }
395             else {
396                 /* Privilege check returned false with error */
397                 transaction->state = result;
398             }
399         }
400         else {
401             transaction->state = RM_SERVICE_DENIED_INVALID_STATIC_REQUEST;
402         }
403     }
404     else {
405         transaction->state = RM_ERROR_REQ_FAILED_NO_STATIC_POLICY;
406     } 
409 /* FUNCTION PURPOSE: Arbitrates allocation service requests
410  ***********************************************************************
411  * DESCRIPTION: Issues a set of allocator operations in order to
412  *              handle a received allocation request.  Allocation
413  *              requests are always forwarded to the Server on Client
414  *              CD instances.  If a request is made with a NameServer
415  *              name the resource base and length parameters are
416  *              retrieved from the NameServer prior to the allocation
417  *              attempt.
418  */
419 static void allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)
421     Rm_AllocatorOpInfo  opInfo;
422     
423     Rm_NameServerObjCfg nameServerObjCfg;
424     int32_t             retVal = transaction->state;
426     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
427         /* Fill in allocation logic for CDs */  
428     }
429     else if ((rmInst->instType == Rm_instType_SERVER)||
430              (rmInst->instType == Rm_instType_SHARED_SERVER)) {
431         memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
432         
433         opInfo.policy = rmInst->u.server.globalPolicy;
434         opInfo.resourceInfo = &transaction->resourceInfo;
435         opInfo.serviceSrcInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst, transaction->serviceSrcInstName);
436         if (opInfo.serviceSrcInstNode) {
437             /* Populated NameServer name has precedence over base */
438             if (strlen(transaction->resourceInfo.nameServerName) > 0) {
439                 if ((transaction->resourceInfo.base == 0) &&
440                     (transaction->resourceInfo.length == 0) &&
441                     (transaction->resourceInfo.alignment == 0)) {
442                     if (rmInst->instType == Rm_instType_SHARED_SERVER) {
443                         rmNameServerTreeInv(rmInst->u.server.nameServer);
444                     }
445                     memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
446                     nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
447                     nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
448                     if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {
449                         strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
450                         transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
451                         transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
452                     }                
453                 }
454                 else {
455                     retVal = RM_ERROR_NS_NAME_AND_RES_VAL_CONFLICT;
456                     goto errorExit;
457                 }
458             }
460             if (transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) {
461                 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
462                     opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE_INIT;
463                 }
464                 else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
465                     opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE_USE;
466                 }
467                 else {
468                     retVal = RM_ERROR_INVALID_SERVICE_TYPE;
469                     goto errorExit;
470                 }
471                 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
472             }
473         
474             if (retVal == RM_SERVICE_PROCESSING) {
475                 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
476                     opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
477                 }
478                 else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
479                     opInfo.operation = Rm_allocatorOp_ALLOCATE_USE;
480                 }
481                 else {
482                     retVal = RM_ERROR_INVALID_SERVICE_TYPE;
483                     goto errorExit;
484                 }
485                 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
486             }      
487         }
488         else {
489             retVal = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;
490         }
491 errorExit:        
492         transaction->state = retVal;                 
493     }   
496 /* FUNCTION PURPOSE: Arbitrates free service requests
497  ***********************************************************************
498  * DESCRIPTION: Issues a set of allocator operations in order to
499  *              handle a received free request.  Free
500  *              requests are always forwarded to the Server on Client
501  *              CD instances.  If a request is made with a NameServer
502  *              name the resource base and length parameters are
503  *              retrieved from the NameServer prior to the free
504  *              attempt.
505  */
506 static void freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)
508     Rm_AllocatorOpInfo  opInfo; 
509     Rm_NameServerObjCfg nameServerObjCfg;    
510     int32_t             retVal = transaction->state;
511     
512     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
513         /* Fill in free logic for CDs */    
514     }
515     else if ((rmInst->instType == Rm_instType_SERVER) ||
516              (rmInst->instType == Rm_instType_SHARED_SERVER)) {
517         memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
518         
519         opInfo.policy = rmInst->u.server.globalPolicy;
520         opInfo.resourceInfo = &transaction->resourceInfo;
521         opInfo.serviceSrcInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst, transaction->serviceSrcInstName);
522         if (opInfo.serviceSrcInstNode) {
523             /* Populated NameServer name has precedence over base */
524             if (strlen(transaction->resourceInfo.nameServerName) > 0) {
525                 if ((transaction->resourceInfo.base == 0) &&
526                     (transaction->resourceInfo.length == 0) &&
527                     (transaction->resourceInfo.alignment == 0)) {
528                     if (rmInst->instType == Rm_instType_SHARED_SERVER) {
529                         rmNameServerTreeInv(rmInst->u.server.nameServer);
530                     }                    
531                     memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
532                     nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
533                     nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
534                     if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {
535                         strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
536                         transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
537                         transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
538                     } 
539                 }
540                 else {
541                     retVal = RM_ERROR_NS_NAME_AND_RES_VAL_CONFLICT;
542                 }                
543             }
544             
545             if(retVal == RM_SERVICE_PROCESSING) {        
546                 opInfo.operation = Rm_allocatorOp_FREE;
547                 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
548             }    
549         }
550         else {
551             retVal = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;
552         }
554         transaction->state = retVal;       
555     }   
558 /* FUNCTION PURPOSE: Client transaction handling process
559  ***********************************************************************
560  * DESCRIPTION: Client process for handling transactions created
561  *              from services received via the service handle or the
562  *              transport.  The Client process:
563  *                  - Performs static allocations if no transport
564  *                    to CD or Server has been registered
565  *                  - Forwards all service requests to CD or Server
566  *                    once transport has been registered
567  */
568 static void clientProcess (Rm_Inst *rmInst, Rm_Transaction *transaction)
570     Rm_Transaction    *transQ = rmInst->transactionQueue;
571     
572     if (!rmInst->registeredWithDelegateOrServer) {
573         staticAllocationHandler((Rm_Handle)rmInst, transaction);
574     }
575     else {
576         if (transaction->state == RM_SERVICE_PROCESSING) {
577             /* Forward all new transactions to CD or Server */
578             transactionForwarder(rmInst, transaction);                
579         }
580         else {
581             /* Transaction validated.  Return result. */
582             serviceResponder(rmInst, transaction);
583         }
585         /* Forward any queued static requests that weren't forwarded */
586         while(transQ) {
587             if ((transQ->state == RM_SERVICE_APPROVED_STATIC) &&
588                 (!transQ->hasBeenForwarded)) {
589                 transactionForwarder(rmInst, transQ);
590             }
591             transQ = transQ->nextTransaction;
592         }        
593     }
594     /* Let call stack return transaction result app via Rm_serviceHandler */
597 /* FUNCTION PURPOSE: Client Delegate transaction handling process
598  ***********************************************************************
599  * DESCRIPTION: Client Delegate process for handling transactions created
600  *              from services received via the service handle or the
601  *              transport.  The Client Delegate process:
602  *                  - Performs static allocations if no transport
603  *                    to Server has been registered
604  *                  - Forwards all NameServer related service requests 
605  *                    to Server once transport has been registered
606  *                  - Attempts to complete resource service requests
607  *                    received from registered Clients
608  */
609 static void cdProcess (Rm_Inst *rmInst, Rm_Transaction *transaction)
610 {        
611     Rm_Transaction *transQ = rmInst->transactionQueue;    
613     if (!rmInst->registeredWithDelegateOrServer) {
614         if ((transaction->state == RM_SERVICE_PROCESSING) &&
615             (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS) == 0)) {
616             /* Attempt static allocation of requests originating from CD inst */
617             staticAllocationHandler((Rm_Handle)rmInst, transaction);
618         }
619         /* Everything else left in transaction queue for forwarding once transport to
620          * Server is registered */
621     }
622     else {
623         if ((transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) ||
624             (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) ||
625             (transaction->type == Rm_service_RESOURCE_UNMAP_NAME)) {
626             if (transaction->state == RM_SERVICE_PROCESSING) {
627                 /* Forward all NameServer requests. */
628                 transactionForwarder(rmInst, transaction);
629             }
630             else {
631                 /* NameServer transaction validated.  Return result. */
632                 if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
633                     /* Transaction did not originate on this instance */
634                     transactionResponder(rmInst, transaction);
635                 }
636                 else {
637                     /* Transaction originated on this instance */
638                     serviceResponder(rmInst, transaction);
639                 }
640             }
641         }        
642         else if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
643                  (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE)) {
644             if ((transaction->state == RM_SERVICE_PROCESSING) ||
645                 (transaction->state == RM_SERVICE_APPROVED_STATIC)) {   
646                 transactionForwarder(rmInst, transaction);
647             }
648             else {
649                 /* Transaction validated.  Return result. */
650                 if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
651                     /* Transaction did not originate on this instance */
652                     transactionResponder(rmInst, transaction);
653                 }
654                 else {
655                     /* Transaction originated on this instance */
656                     serviceResponder(rmInst, transaction);
657                 }
658             }
659         }
660         else if (transaction->type == Rm_service_RESOURCE_FREE) {     
661             if (transaction->state == RM_SERVICE_PROCESSING) {
662                 freeHandler(rmInst, transaction);
664                 if (transaction->state == RM_SERVICE_PROCESSING) {
665                     /* CD could not handle free.  Forward to Server */
666                     transactionForwarder(rmInst, transaction);
667                 }
668                 else {
669                     /* Free validated by CD.  Return result */
670                     if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
671                         /* Transaction did not originate on this instance */
672                         transactionResponder(rmInst, transaction);
673                     }
674                     else {
675                         /* Transaction originated on this instance */
676                         serviceResponder(rmInst, transaction);
677                     }                    
678                 }
679             }
680             else {
681                 /* Transaction validated.  Return result. */
682                 if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
683                     /* Transaction did not originate on this instance */
684                     transactionResponder(rmInst, transaction);
685                 }
686                 else {
687                     /* Transaction originated on this instance */
688                     serviceResponder(rmInst, transaction);
689                 }
690             }
691         }
693         /* Attempt allocation of any queued static requests:
694          * RM_SERVICE_APPROVED_STATIC - Originated locally
695          * RM_SERVICE_PROCESSING - Received from any registered Clients */
696         while(transQ) {
697             if (((transQ->state == RM_SERVICE_PROCESSING) ||
698                  (transQ->state == RM_SERVICE_APPROVED_STATIC)) &&
699                 (!transQ->hasBeenForwarded)) {
700                 transactionForwarder(rmInst, transQ);
701             }
702             transQ = transQ->nextTransaction;
703         }        
704     }
707 /* FUNCTION PURPOSE: Server transaction handling process
708  ***********************************************************************
709  * DESCRIPTION: Server process for handling transactions created
710  *              from services received via the service handle or the
711  *              transport.  The Server process:
712  *                  - Validates all service requests received from
713  *                    the service handle and registered CDs and
714  *                    Clients
715  */
716 static void serverProcess (Rm_Inst *rmInst, Rm_Transaction *transaction)
718     Rm_NameServerObjCfg  nameServerObjCfg;        
720     switch (transaction->type) {
721         case Rm_service_RESOURCE_ALLOCATE_INIT:
722         case Rm_service_RESOURCE_ALLOCATE_USE:
723             allocationHandler(rmInst, transaction);
724             break;
725         case Rm_service_RESOURCE_FREE:               
726             freeHandler(rmInst, transaction);
727             break;
728         case Rm_service_RESOURCE_MAP_TO_NAME:
729         case Rm_service_RESOURCE_GET_BY_NAME:
730         case Rm_service_RESOURCE_UNMAP_NAME:             
731             if (rmInst->u.server.nameServer) {
732                 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
733                     rmNameServerTreeInv(rmInst->u.server.nameServer);
734                 }                
735                 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
736                 nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
737                 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
738                 if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {
739                     nameServerObjCfg.nodeCfg.resourceName = transaction->resourceInfo.name;
740                     nameServerObjCfg.nodeCfg.resourceBase= transaction->resourceInfo.base;
741                     nameServerObjCfg.nodeCfg.resourceLength = transaction->resourceInfo.length;
742                     transaction->state = rmNameServerAddObject(&nameServerObjCfg);
743                 }
744                 else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {
745                     if ((transaction->state = rmNameServerFindObject(&nameServerObjCfg)) ==
746                         RM_SERVICE_PROCESSING) {
747                         strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
748                         transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
749                         transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
750                         transaction->state = RM_SERVICE_APPROVED;
751                     } 
752                 }
753                 else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {
754                     transaction->state = rmNameServerDeleteObject(&nameServerObjCfg);
755                 }
756                 
757                 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
758                     rmNameServerTreeWb(rmInst->u.server.nameServer);
759                 }
760             }
761             else {
762                 transaction->state = RM_ERROR_NAMESERVER_DOES_NOT_EXIST;
763             }
764             break;
765     }
767     /* Source of shared server transaction will always be local. */
768     if (rmInst->instType != Rm_instType_SHARED_SERVER) {
769         if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
770             /* Source of transaction was not Server, return transaction via responder */
771             transactionResponder(rmInst, transaction);
772         }
773     }
774     /* Otherwise let call stack return transaction result app via Rm_serviceHandler */ 
777 /**********************************************************************
778  ********************** Internal Functions ****************************
779  **********************************************************************/
781 /* FUNCTION PURPOSE: Adds a transaction
782  ***********************************************************************
783  * DESCRIPTION: Returns a pointer to a newly created transaction.
784  *              The transaction is created based on a new service
785  *              request received via the service API or the
786  *              transport API (service forwarded from another instance)
787  */
788 Rm_Transaction *rmTransactionQueueAdd(Rm_Inst *rmInst)
790     Rm_Transaction *transactionQueue = rmInst->transactionQueue;
791     Rm_Transaction *newTransaction   = NULL;
793     newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction));
794     if (newTransaction) {
795         memset((void *)newTransaction, 0, sizeof(Rm_Transaction));
797         newTransaction->localId = transactionGetSequenceNum(rmInst);
798         newTransaction->nextTransaction = NULL;  
799         if (transactionQueue) {
800             while (transactionQueue->nextTransaction) {
801                 transactionQueue = transactionQueue->nextTransaction;
802             }
803             transactionQueue->nextTransaction = newTransaction;
804         }
805         else {
806             rmInst->transactionQueue = newTransaction;
807         }
808     }
809     return (newTransaction);
812 /* FUNCTION PURPOSE: Finds a transaction
813  ***********************************************************************
814  * DESCRIPTION: Returns a pointer to a transaction resident
815  *              in the transaction queue that matches the provided
816  *              transaction ID.
817  */
818 Rm_Transaction *rmTransactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)
820     Rm_Transaction *transaction = rmInst->transactionQueue;
822     while (transaction) {
823         if (transaction->localId == transactionId) {
824             break;             
825         }
826         transaction = transaction->nextTransaction;
827     }
829     return (transaction);
832 /* FUNCTION PURPOSE: Deletes a transaction
833  ***********************************************************************
834  * DESCRIPTION: Deletes the transaction with the provided transaction
835  *              ID from the instance's transaction queue.
836  */
837 int32_t rmTransactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)
839     Rm_Transaction *transaction     = rmInst->transactionQueue;
840     Rm_Transaction *prevTransaction = NULL;
841     int32_t         retVal          = RM_OK;
843     while (transaction) {
844         if (transaction->localId == transactionId) {
845             break;             
846         }
848         prevTransaction = transaction;
849         transaction = transaction->nextTransaction;
850     }
852     if (transaction) {
853         if (prevTransaction == NULL) {
854             /* Transaction at start of queue. Map second transaction to start of queue 
855              * as long as more than one transactions. */
856             rmInst->transactionQueue = transaction->nextTransaction;
857         }
858         else {
859             /* Transaction in middle or end of queue. */
860             prevTransaction->nextTransaction = transaction->nextTransaction;
861         }
862         Rm_osalFree((void *)transaction, sizeof(Rm_Transaction));
863     }
864     else {
865         retVal = RM_ERROR_SERVICE_TRANS_DOES_NOT_EXIST;
866     }    
867     return (retVal);
870 /* FUNCTION PURPOSE: Routes a transaction for processing
871  ***********************************************************************
872  * DESCRIPTION: Routes a received transaction to the appropriate
873  *              instance processing routine
874  */
875 void rmProcessRouter (Rm_Inst *rmInst, Rm_Transaction *transaction)
877     if (rmInst->instType == Rm_instType_CLIENT) {
878         clientProcess(rmInst, transaction);
879     }
880     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
881         cdProcess(rmInst, transaction);
882     }
883     else if ((rmInst->instType == Rm_instType_SERVER) ||
884              (rmInst->instType == Rm_instType_SHARED_SERVER)) {
885         serverProcess(rmInst, transaction);
886     } 
888      
889 /**********************************************************************
890  ********************** Application visible APIs **********************
891  **********************************************************************/
893 /* FUNCTION PURPOSE: Display status of managed resources
894  ***********************************************************************
895  * DESCRIPTION: Prints the status (allocate/free status, as well as
896  *              owners) for all resources managed by the RM 
897  *              instance network.  Also, prints the NameServer name
898  *              entries.  The number of resource range owners is
899  *              returned as well.  This function is only available on
900  *              server instances.
901  */
902 int32_t Rm_resourceStatus(Rm_Handle rmServerHandle, int printResources)
904     Rm_Inst         *rmInst = (Rm_Inst *)rmServerHandle;
905     Rm_Allocator    *allocator = NULL;
906     Rm_Owner        *owners;
907     Rm_ResourceTree *treeRoot;
908     Rm_ResourceNode *treeNode;
909     int32_t          totalResOwners = 0;
910     void            *key; 
912     RM_SS_INST_INV_ENTER_CS(key);
913     RM_SC_INST_INV_ENTER_CS(key);
915     if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
916         /* Transfer control to shared server instance */
917         rmInst = rmInst->u.sharedClient.sharedServerHandle;
918     }
920     if ((rmInst->instType == Rm_instType_SERVER) ||
921         (rmInst->instType == Rm_instType_SHARED_SERVER)) {
922         allocator = rmInst->u.server.allocators;
923         while (allocator) {
924             RM_SS_OBJ_INV(allocator, Rm_Allocator);
925             if (printResources) {
926                 Rm_osalLog("Resource: %s\n", allocator->resourceName);
927             }
929             treeRoot = allocator->allocatorRootEntry;
930             if (rmInst->instType == Rm_instType_SHARED_SERVER) {
931                 rmResourceTreeInv(treeRoot);
932             }
933             RB_FOREACH(treeNode, _Rm_AllocatorResourceTree, treeRoot) {
934                 if (printResources) {
935                     if ((treeNode->base >= 65536) ||
936                         ((treeNode->base + treeNode->length - 1) >= 65536)) {
937                         /* Print in hex if number is very large */
938                         Rm_osalLog("          0x%08x - 0x%08x ", treeNode->base, 
939                                                                  treeNode->base + treeNode->length - 1);
940                     }
941                     else {
942                         Rm_osalLog("          %10d - %10d ", treeNode->base, 
943                                                              treeNode->base + treeNode->length - 1);
944                     }
945                 }
946                 
947                 if (treeNode->allocationCount == 0) {
948                     if (printResources) {
949                         Rm_osalLog("FREE\n");
950                     }
951                 }
952                 else {
953                     owners = treeNode->ownerList;
954                     while (owners) {
955                         RM_SS_OBJ_INV(owners, Rm_Owner);
956                         if (printResources) {
957                             Rm_osalLog("%s ", owners->instNameNode->name);
958                         }
959                         totalResOwners++;
960                         owners = owners->nextOwner;
961                     }
962                     if (printResources) {
963                         Rm_osalLog("\n");
964                     }
965                 }
966             }        
967             allocator = allocator->nextAllocator; 
968         }
969         if (printResources) {
970             rmNameServerPrintObjects((Rm_Handle)rmInst);
971         }
972     }
973     else {
974         totalResOwners = RM_ERROR_INVALID_RES_STATUS_INSTANCE;
975     }  
977     RM_SS_INST_WB_EXIT_CS(key);
978     return(totalResOwners);
981 /* FUNCTION PURPOSE: Display status of a RM instance
982  ***********************************************************************
983  * DESCRIPTION: Prints the current status of various RM instance
984  *              properties such as the state of all transactions
985  *              in the transaction queue and registered transports
986  */
987 void Rm_instanceStatus(Rm_Handle rmHandle)
989     Rm_Inst        *rmInst = (Rm_Inst *)rmHandle;
990     Rm_Transport   *transportList = NULL;
991     Rm_Transaction *transactionQ = NULL;
992     void           *key; 
994     RM_SS_INST_INV_ENTER_CS(key);
995     RM_SC_INST_INV_ENTER_CS(key);
997     Rm_osalLog("Instance name: %s\n", rmInst->instName);
998     Rm_osalLog("Handle: 0x%08x\n", rmHandle);    
999     if (rmInst->instType == Rm_instType_SERVER) {
1000         Rm_osalLog("Type:   Server\n");
1001     }
1002     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1003         Rm_osalLog("Type:   Client Delegate\n");
1004     }
1005     else if (rmInst->instType == Rm_instType_CLIENT) {
1006         Rm_osalLog("Type:   Client\n");
1007     }
1008     else if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1009         Rm_osalLog("Type:   Shared Server\n");
1010     }
1011     else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1012         Rm_osalLog("Type:   Shared Client\n");
1014         Rm_osalLog("\nShared Server Properties:\n");
1015         /* Transfer to Shared Server instance to print out transport and
1016          * transaction status */
1017         rmInst = rmInst->u.sharedClient.sharedServerHandle;
1018         Rm_osalLog("Instance name: %s\n", rmInst->instName);
1019         Rm_osalLog("Handle: 0x%08x\n", rmHandle);
1020     }
1021     
1022     transportList = rmInst->transports;
1023     if (transportList) {
1024         Rm_osalLog("\nRegistered Transports:\n");
1025         while (transportList) {
1026             RM_SS_OBJ_INV(transportList, Rm_Transport);
1027             Rm_osalLog("    Remote instName:    %s\n", transportList->remoteInstName);
1028             if (transportList->remoteInstType == Rm_instType_SERVER) {
1029                 Rm_osalLog("    Remote instType:    Server\n");
1030             }
1031             else if (transportList->remoteInstType == Rm_instType_CLIENT_DELEGATE) {
1032                 Rm_osalLog("    Remote instType:    Client Delegate\n");
1033             }
1034             else {
1035                 Rm_osalLog("    Remote instType:    Client\n");
1036             }
1037             Rm_osalLog("    appTransportHandle: 0x%08x\n", transportList->appTransportHandle);
1038             Rm_osalLog("\n");
1039             transportList = transportList->nextTransport;
1040         }
1041     }
1043     transactionQ = rmInst->transactionQueue;
1044     if (transactionQ) {
1045         Rm_osalLog("\nQueued Service Transactions:\n");
1046         while (transactionQ) {
1047             RM_SS_OBJ_INV(transactionQ, Rm_Transaction);
1048             Rm_osalLog("    Service type:       %d\n", transactionQ->type);
1049             Rm_osalLog("    Service ID:         %d\n", transactionQ->localId);
1050             Rm_osalLog("    Service srcInstName %s\n", transactionQ->serviceSrcInstName);
1051             Rm_osalLog("    Service state:      %d\n", transactionQ->state);
1052             Rm_osalLog("    Resource name:      %s\n", transactionQ->resourceInfo.name);
1053             Rm_osalLog("    Resource base:      %d\n", transactionQ->resourceInfo.base);
1054             Rm_osalLog("    Resource length:    %d\n", transactionQ->resourceInfo.length);
1055             Rm_osalLog("    Resource alignment: %d\n", transactionQ->resourceInfo.alignment);
1056             Rm_osalLog("    Resource NS name:   %s\n", transactionQ->resourceInfo.nameServerName);
1057             Rm_osalLog("\n");
1058             transactionQ = transactionQ->nextTransaction;
1059         }    
1060     }
1061     RM_SS_INST_WB_EXIT_CS(key);    
1064 /* FUNCTION PURPOSE: RM instance creation and initialization
1065  ***********************************************************************
1066  * DESCRIPTION: Returns a new RM instance created and initialized
1067  *              using the parameters provided via the initCfg
1068  *              structure.
1069  */
1070 Rm_Handle Rm_init(const Rm_InitCfg *initCfg, int32_t *result)
1072     Rm_Inst  *rmInst = NULL;
1073     Rm_Inst  *sharedServerInst = NULL;
1074     uint32_t  policySize;
1075     void     *globalResourceDtb = NULL;
1076     void     *linuxResourceDtb = NULL;
1077     int       addLinux = RM_FALSE;   
1078     void     *key;     
1080     *result = RM_OK;
1081     
1082     if ((initCfg->instName == NULL) ||
1083         ((strlen(initCfg->instName) + 1) > RM_NAME_MAX_CHARS)) {
1084         *result = RM_ERROR_INVALID_INST_NAME;
1085         goto errorExit;
1086     }
1088     if (initCfg->instType >= Rm_instType_LAST) {
1089         *result = RM_ERROR_INVALID_INST_TYPE;
1090         goto errorExit;
1091     }
1093     /* Create and initialize instance */
1094     rmInst = Rm_osalMalloc(sizeof(*rmInst));
1095     memset ((void *)rmInst, 0, sizeof(*rmInst));
1096     rmInst->isLocked = RM_FALSE;
1097     rmInst->registeredWithDelegateOrServer = RM_FALSE;
1098     rmInst->transactionSeqNum = transactionInitSequenceNum();
1100     rmInst->instType = initCfg->instType;    
1101     strncpy (rmInst->instName, initCfg->instName, RM_NAME_MAX_CHARS);
1103     if ((rmInst->instType == Rm_instType_SERVER) ||
1104         (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1105         if (!initCfg->instCfg.serverCfg.globalResourceList ||
1106             !initCfg->instCfg.serverCfg.globalPolicy) {
1107             *result = RM_ERROR_INVALID_SERVER_CONFIGURATION;
1108             goto errorExit;
1109         }
1111         if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1112             /* Shared Server makes copy of policy in shared memory for Shared Clients
1113              * on other cores */
1114             policySize = fdt_totalsize(initCfg->instCfg.serverCfg.globalPolicy);
1115             /* Align policy size to cache boundary */
1116             if (policySize % RM_MAX_CACHE_ALIGN) {
1117                 policySize += (RM_MAX_CACHE_ALIGN - (policySize % RM_MAX_CACHE_ALIGN));
1118             }
1119             rmInst->u.server.policySize = policySize;
1120             rmInst->u.server.globalPolicy = Rm_osalMalloc(rmInst->u.server.policySize);
1121             memcpy(rmInst->u.server.globalPolicy, initCfg->instCfg.serverCfg.globalPolicy, rmInst->u.server.policySize);
1122         }
1123         else {
1124             rmInst->u.server.globalPolicy = initCfg->instCfg.serverCfg.globalPolicy;
1125         }
1127         if (initCfg->instCfg.serverCfg.linuxDtb) {
1128             linuxResourceDtb = initCfg->instCfg.serverCfg.linuxDtb;
1129             addLinux = RM_TRUE;
1130         }
1132         /* Create valid instance list from policy.  Must be done prior to parsing
1133          * GRL so that Linux resources can be reserved correctly */
1134         rmInst->u.server.globalValidInstTree = rmPolicyCreateValidInstTree((Rm_Handle)rmInst, addLinux, result);
1135         if (*result == RM_OK) {
1136             *result = rmPolicyValidatePolicy((Rm_Handle)rmInst);  
1137         }
1138         
1139         if (*result != RM_OK) {
1140             if (rmInst->u.server.globalValidInstTree) {
1141                 rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1142             }
1143             goto errorExit;
1144         }
1145         else {
1146             rmNameServerInit((Rm_Handle)rmInst);
1148             globalResourceDtb = initCfg->instCfg.serverCfg.globalResourceList;
1150             if ((*result = rmAllocatorInitializeResources((Rm_Handle) rmInst, globalResourceDtb, linuxResourceDtb)) == RM_OK) {  
1151                 *result = rmPolicyValidatePolicyResourceNames((Rm_Handle)rmInst);
1152             }
1154             if (*result != RM_OK) {
1155                 rmAllocatorDeleteResources((Rm_Handle)rmInst);
1156                 rmNameServerDelete((Rm_Handle)rmInst);
1157                 goto errorExit;
1158             }
1159         }
1160     }
1161     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1162         if (initCfg->instCfg.cdCfg.cdPolicy) {
1163             rmInst->u.cd.cdPolicy = initCfg->instCfg.cdCfg.cdPolicy;
1164             rmInst->u.cd.cdValidInstTree = rmPolicyCreateValidInstTree((Rm_Handle)rmInst, addLinux, result);        
1165             if (*result == RM_OK) {
1166                 *result = rmPolicyValidatePolicy((Rm_Handle)rmInst);
1167             }
1169             if (*result != RM_OK) {
1170                 if (rmInst->u.cd.cdValidInstTree) {
1171                     rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1172                 }
1173                 goto errorExit;
1174             }
1175         }
1177         rmInst->u.cd.allocators = NULL;
1178     }
1179     else if (rmInst->instType == Rm_instType_CLIENT) {
1180         if (initCfg->instCfg.clientCfg.staticPolicy) { 
1181             rmInst->u.client.staticPolicy = initCfg->instCfg.clientCfg.staticPolicy;
1182             rmInst->u.client.staticValidInstTree = rmPolicyCreateValidInstTree((Rm_Handle)rmInst, addLinux, result);        
1183             if (*result == RM_OK) {
1184                 *result = rmPolicyValidatePolicy((Rm_Handle)rmInst);
1185             }
1186             
1187             if (*result != RM_OK) {
1188                 if (rmInst->u.client.staticValidInstTree) {
1189                     rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1190                 }
1191                 goto errorExit;
1192             }
1193         }
1194     }
1195     else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1196         if (initCfg->instCfg.sharedClientCfg.sharedServerHandle) {
1197             rmInst->u.sharedClient.sharedServerHandle = initCfg->instCfg.sharedClientCfg.sharedServerHandle;
1198             /* Invalidate the Shared server instance structure on this core to get the latest
1199              * instance data. */
1200             key = Rm_osalCsEnter();
1201             Rm_osalBeginMemAccess((void *)rmInst->u.sharedClient.sharedServerHandle, sizeof(Rm_Inst));
1202             sharedServerInst = rmInst->u.sharedClient.sharedServerHandle;
1203             if (sharedServerInst->instType != Rm_instType_SHARED_SERVER) {
1204                 *result = RM_ERROR_INVALID_SHARED_SERVER_HANDLE;
1205                 Rm_osalCsExit(key);
1206                 goto errorExit;
1207             }
1208             else {
1209                 /* Invalidate the policy */
1210                 Rm_osalBeginMemAccess((void *)sharedServerInst->u.server.globalPolicy, 
1211                                       sharedServerInst->u.server.policySize);
1212             }
1213             Rm_osalCsExit(key);
1214         }
1215         else {
1216             *result = RM_ERROR_INVALID_SHARED_SERVER_HANDLE;
1217             goto errorExit;
1218         }
1219     }
1221     if (initCfg->instType == Rm_instType_SHARED_SERVER) {
1222         /* Writeback the instance and policy for other cores */
1223         Rm_osalEndMemAccess ((void *)rmInst, sizeof(Rm_Inst));
1224         Rm_osalEndMemAccess ((void *)rmInst->u.server.globalPolicy, rmInst->u.server.policySize);
1225     }
1226     else if (rmInst->instType != Rm_instType_SHARED_CLIENT) {
1227         /* Create the instance's task blocking mechanism */
1228         rmInst->blockHandle = Rm_osalTaskBlockCreate();
1229     }
1231     return ((Rm_Handle) rmInst);
1232 errorExit:
1233     if (rmInst) {
1234         Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
1235     }
1236     return (NULL); 
1239 /* FUNCTION PURPOSE: Deletes an RM instance
1240  ***********************************************************************
1241  * DESCRIPTION: Frees all memory associated with an RM instance
1242  *              as long as all transports have been unregistered
1243  *              and the service handle has been closed
1244  */
1245 int32_t Rm_delete(Rm_Handle rmHandle, int ignorePendingServices)
1247     Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
1248     void    *key; 
1250     key = Rm_osalCsEnter();
1251     if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1252         Rm_osalBeginMemAccess((void *)rmInst, sizeof(Rm_Inst));
1253     }
1255     if (rmInst->serviceHandle) {
1256         return (RM_ERROR_CANT_DELETE_WITH_OPEN_SERV_HNDL);
1257     }
1258     else if (rmInst->transports) {
1259         return (RM_ERROR_CANT_DELETE_WITH_REGD_TRANSPORT);
1260     }
1261     else if (rmInst->transactionQueue && !ignorePendingServices) {
1262         return (RM_ERROR_CANT_DELETE_PENDING_TRANSACTIONS);
1263     }
1265     if ((rmInst->instType == Rm_instType_SERVER) ||
1266         (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1267         rmAllocatorDeleteResources(rmHandle);
1268         rmNameServerDelete(rmHandle);
1269         rmInst->u.server.allocators = NULL;
1271         if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1272             Rm_osalFree((void *)rmInst->u.server.globalPolicy, rmInst->u.server.policySize);
1273         }
1274     }
1275     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1276         rmAllocatorDeleteResources(rmHandle);
1277         rmInst->u.cd.allocators = NULL;
1278     }
1280     if (rmInst->instType != Rm_instType_SHARED_CLIENT) {
1281         /* Delete valid instance tree */
1282         rmPolicyFreeValidInstTree(rmHandle);
1284         /* Delete any transactions */
1285         while(rmInst->transactionQueue) {
1286             rmTransactionQueueDelete(rmInst, rmInst->transactionQueue->localId);
1287         }
1289         if (rmInst->instType != Rm_instType_SHARED_SERVER) {
1290             /* Delete the instance's task blocking mechanism */
1291             Rm_osalTaskBlockDelete(rmInst->blockHandle);
1292         }
1293         else {
1294             Rm_osalEndMemAccess((void *)rmInst, sizeof(Rm_Inst));
1295         }
1296     }
1298     Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
1299    
1300     Rm_osalCsExit(key);   
1301     return (RM_OK);
1304 /* FUNCTION PURPOSE: Returns RM version information
1305  ***********************************************************************
1306  */
1307 uint32_t Rm_getVersion(void)
1309     return RM_VERSION_ID;
1312 /* FUNCTION PURPOSE: Returns RM version string
1313  ***********************************************************************
1314  */
1315 const char* Rm_getVersionStr(void)
1317     return rmVersionStr;