Completed API documentation and Doxygen
[keystone-rtos/rm-lld.git] / src / rm.c
1 /**\r
2  *   @file  rm.c\r
3  *\r
4  *   @brief   \r
5  *      This is the Resource Manager source.\r
6  *\r
7  *  \par\r
8  *  ============================================================================\r
9  *  @n   (C) Copyright 2012-2013, Texas Instruments, Inc.\r
10  * \r
11  *  Redistribution and use in source and binary forms, with or without \r
12  *  modification, are permitted provided that the following conditions \r
13  *  are met:\r
14  *\r
15  *    Redistributions of source code must retain the above copyright \r
16  *    notice, this list of conditions and the following disclaimer.\r
17  *\r
18  *    Redistributions in binary form must reproduce the above copyright\r
19  *    notice, this list of conditions and the following disclaimer in the \r
20  *    documentation and/or other materials provided with the   \r
21  *    distribution.\r
22  *\r
23  *    Neither the name of Texas Instruments Incorporated nor the names of\r
24  *    its contributors may be used to endorse or promote products derived\r
25  *    from this software without specific prior written permission.\r
26  *\r
27  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
28  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
29  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
30  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT \r
31  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \r
32  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \r
33  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
34  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
35  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
36  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
37  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
38  *\r
39  *  \par\r
40 */\r
41 \r
42 /* Standard includes */\r
43 #include <stdint.h>\r
44 #include <string.h>\r
45 #include <stdbool.h>\r
46 \r
47 /* RM external includes */\r
48 #include <ti/drv/rm/rm.h>\r
49 #include <ti/drv/rm/rm_services.h>\r
50 #include <ti/drv/rm/rm_transport.h>\r
51 \r
52 /* RM internal includes */\r
53 #include <ti/drv/rm/include/rm_loc.h>\r
54 #include <ti/drv/rm/include/rm_transportloc.h>\r
55 #include <ti/drv/rm/include/rm_nameserverloc.h>\r
56 #include <ti/drv/rm/include/rm_dtb_utilloc.h>\r
57 #include <ti/drv/rm/include/rm_policyloc.h>\r
58 #include <ti/drv/rm/include/rm_treeloc.h>\r
59 \r
60 /* RM LIBFDT includes */\r
61 #include <ti/drv/rm/util/libfdt/libfdt.h>\r
62 \r
63 /* Tree algorithm includes */\r
64 #include <ti/drv/rm/util/tree.h>\r
65 \r
66 /* RM OSAL layer */\r
67 #include <rm_osal.h>\r
68 \r
69 /**********************************************************************\r
70  ************************** Globals ***********************************\r
71  **********************************************************************/\r
72 \r
73 /** @brief Global Variable which describes the RM Version Information */\r
74 const char  rmVersionStr[] = RM_VERSION_STR ":" __DATE__  ":" __TIME__;\r
75 \r
76 /**********************************************************************\r
77  ************************ Local Functions *****************************\r
78  **********************************************************************/\r
79 \r
80 /* FUNCTION PURPOSE: Initializes a RM inst's transaction sequence number\r
81  ***********************************************************************\r
82  * DESCRIPTION: The RM instance transaction sequence number can never\r
83  *              have a value of 0 to avoid conflicts with transactions\r
84  *              that have a remoteOriginatingId of 0 (transaction ID\r
85  *              will be used as the remoteOriginatingId for\r
86  *              transactions that are responses to requests).\r
87  */\r
88 static uint32_t transactionInitSequenceNum(void)\r
89 {\r
90     return (1);\r
91 }\r
92 \r
93 /* FUNCTION PURPOSE: Provides a sequence number for new transactions\r
94  ***********************************************************************\r
95  * DESCRIPTION: Returns a sequence number for a new transaction\r
96  *              specific to a RM instance.  Handles rollover of\r
97  *              sequence number.\r
98  */\r
99 static uint32_t transactionGetSequenceNum(Rm_Inst *rmInst)\r
100 {\r
101     uint32_t sequenceNum = 0;\r
102 \r
103     if (rmInst->transactionSeqNum + 1 < rmInst->transactionSeqNum) {\r
104         /* Rollover */\r
105         sequenceNum = rmInst->transactionSeqNum;\r
106         rmInst->transactionSeqNum = transactionInitSequenceNum();\r
107     }\r
108     else {\r
109         sequenceNum = rmInst->transactionSeqNum++;\r
110     }    \r
111     return (sequenceNum);\r
112 }\r
113 \r
114 /* FUNCTION PURPOSE: Creates a resource allocator\r
115  ***********************************************************************\r
116  * DESCRIPTION: Returns a newly Created and initialized resource\r
117  *              The allocator is also stored in the RM instance\r
118  *              allocator list.            \r
119  */\r
120 static Rm_Allocator *allocatorAdd(Rm_Inst *rmInst, const char *resourceName)\r
121 {\r
122     Rm_Allocator *allocators   = rmInst->allocators;\r
123     Rm_Allocator *newAllocator = NULL;\r
124 \r
125     newAllocator = Rm_osalMalloc(sizeof(Rm_Allocator));\r
126 \r
127     if (newAllocator) {\r
128         memset((void *)newAllocator, 0, sizeof(Rm_Allocator));\r
129         strncpy(newAllocator->resourceName, resourceName, RM_NAME_MAX_CHARS);\r
130         newAllocator->allocatorRootEntry = NULL;\r
131         newAllocator->nextAllocator = NULL;  \r
132 \r
133         /* Add allocator to end of list */\r
134         if (allocators) {\r
135             while (allocators->nextAllocator) {\r
136                 allocators = allocators->nextAllocator;\r
137             }\r
138             allocators->nextAllocator = newAllocator;\r
139         }\r
140         else {\r
141             rmInst->allocators = newAllocator;\r
142         }\r
143     }\r
144     return (newAllocator);\r
145 }\r
146 \r
147 /* FUNCTION PURPOSE: Deletes a resource allocator\r
148  ***********************************************************************\r
149  * DESCRIPTION: Deletes a resource allocator based on the given\r
150  *              resource name.  The resource allocator will be\r
151  *              removed from the RM instance allocator list.\r
152  */\r
153 static int32_t allocatorDelete(Rm_Inst *rmInst, char *resourceName)\r
154 {\r
155     Rm_Allocator *allocator = rmInst->allocators;\r
156     Rm_Allocator *prevAllocator = NULL;\r
157     int32_t       retVal = RM_OK;\r
158 \r
159     while (allocator) {\r
160         if (strncmp(allocator->resourceName, resourceName, RM_NAME_MAX_CHARS) == 0) {\r
161             break;             \r
162         }\r
163         prevAllocator = allocator;\r
164         allocator = allocator->nextAllocator;\r
165     }\r
166 \r
167     if (allocator) {\r
168         if (prevAllocator == NULL) {\r
169             rmInst->allocators = allocator->nextAllocator;\r
170         }\r
171         else {\r
172             prevAllocator->nextAllocator = allocator->nextAllocator;\r
173         }\r
174         Rm_osalFree((void *)allocator, sizeof(Rm_Allocator));\r
175     }\r
176     else {\r
177         retVal = RM_ERROR_RES_ALLOCATOR_DOES_NOT_EXIST;\r
178     }\r
179     return (retVal);\r
180 }\r
181 \r
182 /* FUNCTION PURPOSE: Adds an owner to an allocator resource\r
183  ***********************************************************************\r
184  * DESCRIPTION: Adds a RM instance node to a resource node's\r
185  *              list of owners.\r
186  */\r
187 static void addOwner(Rm_ResourceNode *node, void *serviceInstNode)\r
188 {\r
189     Rm_Owner *ownerList = node->ownerList;\r
190     Rm_Owner *newOwner = NULL;\r
191 \r
192     newOwner = Rm_osalMalloc(sizeof(Rm_Owner));\r
193 \r
194     if (newOwner) {\r
195         newOwner->instNameNode = serviceInstNode;\r
196         newOwner->nextOwner = NULL;  \r
197 \r
198         /* Add owner entry to end of list */\r
199         if (ownerList) {\r
200             while (ownerList->nextOwner) {\r
201                 ownerList = ownerList->nextOwner;\r
202             }\r
203             ownerList->nextOwner = newOwner;\r
204         }\r
205         else {\r
206             node->ownerList = newOwner;\r
207         }\r
208 \r
209         node->allocationCount++;\r
210         newOwner->instNameNode->allocRefCount++;\r
211     }\r
212 }\r
213 \r
214 /* FUNCTION PURPOSE: Checks a resource node's ownership\r
215  ***********************************************************************\r
216  * DESCRIPTION: Returns TRUE if the provided instance node is\r
217  *              in the list of resource node owners.  Otherwise,\r
218  *              returns FALSE.\r
219  */\r
220 static bool isOwnedBy(Rm_ResourceNode *node, void *serviceInstNode)\r
221 {\r
222     Rm_Owner *owner = node->ownerList;\r
223 \r
224     while (owner) {\r
225         if (owner->instNameNode == serviceInstNode) {\r
226             return(true);           \r
227         }\r
228         owner = owner->nextOwner;\r
229     }\r
230     return(false);\r
231 }\r
232 \r
233 /* FUNCTION PURPOSE: Compares two resource node's owners\r
234  ***********************************************************************\r
235  * DESCRIPTION: Returns TRUE if the owners of two resource nodes \r
236  *              are equivalent.  Otherwise, returns FALSE.\r
237  */\r
238 static bool compareResourceNodeOwners(Rm_ResourceNode *node1, Rm_ResourceNode *node2)\r
239 {\r
240     Rm_Owner *node1Owners = node1->ownerList;\r
241     Rm_Owner *node2Owners = node2->ownerList;\r
242     bool      matchedInst;\r
243 \r
244     if (node1->allocationCount == node2->allocationCount) {\r
245         while (node1Owners) {\r
246             matchedInst = false;\r
247             while (node2Owners) {\r
248                 if (node1Owners->instNameNode == node2Owners->instNameNode) {\r
249                     matchedInst = true;\r
250                     break;\r
251                 }\r
252                 node2Owners = node2Owners->nextOwner;\r
253             }\r
254 \r
255             if (matchedInst) {\r
256                 node2Owners = node2->ownerList;\r
257                 node1Owners = node1Owners->nextOwner;\r
258             }\r
259             else {\r
260                 return(false);\r
261             }                \r
262         }\r
263     }\r
264     else {\r
265         return(false);\r
266     }  \r
267     \r
268     return(true);\r
269 }\r
270 \r
271 /* FUNCTION PURPOSE: Deletes an owner from an allocator resource\r
272  ***********************************************************************\r
273  * DESCRIPTION: Removes a RM instance node from a resource node's\r
274  *              list of owners.\r
275  */\r
276 static void deleteOwner(Rm_ResourceNode *node, void *serviceInstNode)\r
277 {\r
278     Rm_Owner *owner = node->ownerList;\r
279     Rm_Owner *prevOwner = NULL;\r
280 \r
281     while (owner) {\r
282         if (owner->instNameNode == serviceInstNode) {\r
283             break;             \r
284         }\r
285         prevOwner = owner;\r
286         owner = owner->nextOwner;\r
287     }\r
288 \r
289     if (prevOwner == NULL) {\r
290         node->ownerList = owner->nextOwner;\r
291     }\r
292     else {\r
293         prevOwner->nextOwner = owner->nextOwner;\r
294     }\r
295     \r
296     node->allocationCount--;\r
297     owner->instNameNode->allocRefCount--;\r
298     Rm_osalFree((void *)owner, sizeof(Rm_Owner));\r
299 }\r
300 \r
301 /* FUNCTION PURPOSE: Copies the owners of a resource node\r
302  ***********************************************************************\r
303  * DESCRIPTION: Creates a list of resource owners for the destination\r
304  *              resource node that is equivalent to the the \r
305  *              source resource node's owners\r
306  */\r
307 static void copyOwners(Rm_ResourceNode *dstNode, Rm_ResourceNode *srcNode)\r
308 {\r
309     Rm_Owner *srcOwnerList = srcNode->ownerList;\r
310     Rm_Owner *dstNewOwner;\r
311     Rm_Owner *dstPrevOwner;\r
312 \r
313     dstNode->allocationCount = srcNode->allocationCount;\r
314 \r
315     while (srcOwnerList) {\r
316         dstNewOwner = Rm_osalMalloc(sizeof(Rm_Owner));\r
317         dstNewOwner->instNameNode = srcOwnerList->instNameNode;\r
318         dstNewOwner->nextOwner = NULL;\r
319 \r
320         if (dstNode->ownerList == NULL) {\r
321             dstNode->ownerList = dstNewOwner;\r
322         }\r
323         else {\r
324             dstPrevOwner->nextOwner = dstNewOwner;\r
325         }\r
326         dstPrevOwner = dstNewOwner;\r
327         srcOwnerList = srcOwnerList->nextOwner;\r
328     }\r
329 }\r
330 \r
331 /* FUNCTION PURPOSE: Clears a resource node's owners\r
332  ***********************************************************************\r
333  * DESCRIPTION: Deletes all owners from the owners list of a \r
334  *              resource node.\r
335  */\r
336 static void clearOwners(Rm_ResourceNode *node)\r
337 {\r
338     Rm_Owner *owner = node->ownerList;\r
339     Rm_Owner *nextOwner;\r
340 \r
341     while (owner) {\r
342         nextOwner = owner->nextOwner;\r
343         node->allocationCount--;\r
344         Rm_osalFree((void *)owner, sizeof(Rm_Owner));\r
345         owner = nextOwner;\r
346     }\r
347 }\r
348 \r
349 /* FUNCTION PURPOSE: Creates a new resource tree\r
350  ***********************************************************************\r
351  * DESCRIPTION: Creates a new resource tree using the provided\r
352  *              resource name and value range.  The name and value\r
353  *              typically originate from the GRL.\r
354  */\r
355 static int32_t createResourceTree(Rm_Inst *rmInst, const char *resourceName, Rm_ResourceRange *range)\r
356 {\r
357     Rm_Allocator    *allocator = NULL;\r
358     Rm_ResourceTree *treeRootEntry = NULL;\r
359     Rm_ResourceNode *treeNode = NULL;\r
360     Rm_ResourceNode *collidingNode = NULL;\r
361 \r
362     allocator = allocatorAdd(rmInst, resourceName);\r
363     treeRootEntry = Rm_osalMalloc(sizeof(Rm_ResourceTree));\r
364     RB_INIT(treeRootEntry);\r
365 \r
366     while (range != NULL) {\r
367         treeNode = rmResourceNodeNew(range->base, range->length);\r
368         collidingNode = RB_INSERT(_Rm_AllocatorResourceTree, treeRootEntry, treeNode);\r
369 \r
370         if (collidingNode) {\r
371             Rm_ResourceNode *nextNode = NULL;\r
372             \r
373             /* Node that was inserted collides with existing node.  Destroy tree and return error */\r
374             for (treeNode = RB_MIN(_Rm_AllocatorResourceTree, treeRootEntry); treeNode != NULL; treeNode = nextNode) {\r
375                         nextNode = RB_NEXT(_Rm_AllocatorResourceTree, treeRootEntry, treeNode);\r
376                         RB_REMOVE(_Rm_AllocatorResourceTree, treeRootEntry, nextNode);\r
377                 rmResourceNodeFree(treeNode);\r
378                 }\r
379             Rm_osalFree((void *)treeRootEntry, sizeof(Rm_ResourceTree));\r
380             allocatorDelete(rmInst, allocator->resourceName);\r
381             return (RM_ERROR_GRL_RES_SPECIFIED_MORE_THAN_ONCE);\r
382         }\r
383         range = range->nextRange;\r
384     }\r
385     \r
386     allocator->allocatorRootEntry = treeRootEntry;\r
387     return(RM_OK);\r
388 }\r
389 \r
390 /* FUNCTION PURPOSE: Preallocates a resource\r
391  ***********************************************************************\r
392  * DESCRIPTION: Called when an allocate request is made but the base \r
393  *              is unspecified.  The preallocation algorithm looks at \r
394  *              available resources as well as policy permissions to \r
395  *              determine a resource range that satisfies the request.\r
396  *              If a valid range is found it will be returned for the \r
397  *              treeAllocate algorithm to handle.\r
398  */\r
399 static int32_t treePreAllocate(Rm_Inst *rmInst, Rm_Allocator *allocator, int32_t resourcePolicy,\r
400                                Rm_AllocatorOpInfo *opInfo)\r
401 {\r
402     Rm_ResourceNode    findNode;\r
403     Rm_ResourceNode   *matchingNode = NULL;\r
404     uint32_t           matchingEnd;\r
405     uint32_t           rangeIndex;\r
406     bool               resourceFound = false;\r
407     Rm_PolicyCheckType policyCheckType;\r
408     Rm_PolicyCheckCfg  policyCheckCfg;\r
409     bool               nodePassesPolicy;\r
410     int32_t            retVal = RM_SERVICE_PROCESSING;    \r
411 \r
412     opInfo->resourceInfo->base = rmPolicyGetResourceBase(rmInst->policy, opInfo->serviceSrcInstNode, \r
413                                                           resourcePolicy, opInfo->allocType, \r
414                                                           &retVal);\r
415     if (retVal != RM_SERVICE_PROCESSING) {\r
416         return (retVal);\r
417     }\r
418 \r
419     if (opInfo->resourceInfo->alignment == RM_RESOURCE_ALIGNMENT_UNSPECIFIED) {  \r
420         /* Get alignment from policy */\r
421         opInfo->resourceInfo->alignment = rmPolicyGetResourceAlignment(rmInst->policy, resourcePolicy);\r
422     }\r
423     \r
424     if (opInfo->resourceInfo->alignment == 0) {\r
425         opInfo->resourceInfo->alignment = 1;\r
426     }    \r
427 \r
428     memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));\r
429     findNode.base = opInfo->resourceInfo->base;\r
430     findNode.length = opInfo->resourceInfo->length;\r
431 \r
432     /* Configure policy checking structure */\r
433     memset((void *)&policyCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));\r
434     if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_INIT_SHIFT)) {\r
435         policyCheckType = Rm_policyCheck_INIT;\r
436     }\r
437     else if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_USE_SHIFT)) {\r
438         policyCheckType = Rm_policyCheck_USE;\r
439     }\r
440     policyCheckCfg.policyDtb = rmInst->policy;\r
441     policyCheckCfg.resourceOffset = resourcePolicy;\r
442     \r
443     do {\r
444         matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);\r
445         \r
446         if (matchingNode) {\r
447             nodePassesPolicy = false;\r
448             policyCheckCfg.type = policyCheckType;\r
449             policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;\r
450             policyCheckCfg.resourceBase = findNode.base;\r
451             policyCheckCfg.resourceLength = findNode.length;\r
452             nodePassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);    \r
453             \r
454             if (nodePassesPolicy && (matchingNode->allocationCount > 0)) {\r
455                 /* Check exclusive privileges of instance requesting resource.  Requesting\r
456                  * instance with exclusive privileges can't reserve resource if already owned*/\r
457                 policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
458                 policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;\r
459                 nodePassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);\r
460             }\r
461             \r
462             if (nodePassesPolicy && (matchingNode->allocationCount == 1)) {\r
463                 /* Check exclusive privileges of instance that currently owns resource */\r
464                 policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
465                 policyCheckCfg.validInstNode = matchingNode->ownerList->instNameNode;\r
466                 nodePassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);\r
467             }\r
468 \r
469             if (retVal != RM_SERVICE_PROCESSING) {\r
470                 break;\r
471             }\r
472 \r
473             if (nodePassesPolicy) {\r
474                 matchingEnd = matchingNode->base + matchingNode->length - 1;\r
475                 /* Initialize indexer to be first resource value that alignment */\r
476                 rangeIndex = findNode.base;\r
477                 if (rangeIndex % opInfo->resourceInfo->alignment) {\r
478                     rangeIndex += (opInfo->resourceInfo->alignment -\r
479                                   (rangeIndex % opInfo->resourceInfo->alignment));\r
480                 }\r
481                 \r
482                 if ((rangeIndex + opInfo->resourceInfo->length - 1) <= matchingEnd) {\r
483                     /* Block of unallocated resources within matchingNode that satisfies\r
484                      * allocate requirements */\r
485                     opInfo->resourceInfo->base = rangeIndex;\r
486                     resourceFound = true;\r
487                 }     \r
488             }\r
489             \r
490             if (!resourceFound) {\r
491                 /* Check next resource node for available resources */\r
492                 findNode.base = matchingNode->base + matchingNode->length;\r
493             }\r
494         }\r
495         else {\r
496             retVal = RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET;\r
497         }\r
498     } while ((!resourceFound) && \r
499              (retVal != RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET));\r
500 \r
501     return(retVal); \r
502 }\r
503 \r
504 /* FUNCTION PURPOSE: Allocates a resource\r
505  ***********************************************************************\r
506  * DESCRIPTION: Will attempt to allocate the resource with specified\r
507  *              base and length from the resource's allocator.  The\r
508  *              allocation algorithm will verify the allocation against\r
509  *              the policy permissions for the instance requesting the\r
510  *              allocation.  If the policy allows the allocation the \r
511  *              algorithm will allocate the resource then combine any\r
512  *              resource nodes that may have become equivalent (in terms\r
513  *              of ownership) after the allocation.\r
514  */\r
515 static int32_t treeAllocate(Rm_Inst *rmInst, Rm_Allocator *allocator, int32_t resourcePolicy,\r
516                             Rm_AllocatorOpInfo *opInfo)\r
517 {\r
518     Rm_ResourceNode     findNode;\r
519     Rm_ResourceNode    *matchingNode = NULL;\r
520     Rm_ResourceNode    *leftNode = NULL;\r
521     Rm_ResourceNode    *rightNode = NULL;\r
522     Rm_PolicyCheckType  policyCheckType;    \r
523     Rm_PolicyCheckCfg   policyCheckCfg;\r
524     bool                allocPassesPolicy;\r
525     bool                combineLeft = false;\r
526     bool                combineRight = false;    \r
527     uint32_t            findEnd;\r
528     uint32_t            matchingEnd;  \r
529     int32_t             retVal = RM_SERVICE_PROCESSING;\r
530 \r
531     memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));\r
532     findNode.base = opInfo->resourceInfo->base;\r
533     findNode.length = opInfo->resourceInfo->length;\r
534     matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);\r
535 \r
536     /* Prepare privilege checks */\r
537     memset((void *)&policyCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));\r
538     if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_INIT_SHIFT)) {\r
539         policyCheckType = Rm_policyCheck_INIT;\r
540     }\r
541     else if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_USE_SHIFT)) {\r
542         policyCheckType = Rm_policyCheck_USE;\r
543     }\r
544 \r
545     if (matchingNode) {\r
546         findEnd = findNode.base + findNode.length - 1;\r
547         matchingEnd = matchingNode->base + matchingNode->length - 1;\r
548         \r
549         if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {\r
550             if (opInfo->serviceSrcInstNode == rmPolicyGetLinuxInstNode(rmInst->validInstances)) {\r
551                 /* Bypass policy checks since Linux Kernel has full privileges */\r
552                 allocPassesPolicy = true;\r
553             }\r
554             else {\r
555                 policyCheckCfg.policyDtb = rmInst->policy;\r
556                 policyCheckCfg.resourceOffset = resourcePolicy;    \r
557                 policyCheckCfg.type = policyCheckType;\r
558                 policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;\r
559                 policyCheckCfg.resourceBase = findNode.base;\r
560                 policyCheckCfg.resourceLength = findNode.length;\r
561                 allocPassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);\r
562                 if (!allocPassesPolicy) {\r
563                     if (policyCheckType == Rm_policyCheck_INIT) {\r
564                         retVal = RM_SERVICE_DENIED_INIT_PERM_NOT_GIVEN;\r
565                     }\r
566                     else {\r
567                         retVal = RM_SERVICE_DENIED_USE_PERM_NOT_GIVEN;\r
568                     }\r
569                 }\r
570                 \r
571                 if (allocPassesPolicy && (matchingNode->allocationCount > 0)) {\r
572                     /* Check exclusive privileges of instance requesting resource.  Requesting\r
573                      * instance with exclusive privileges can't reserve resource if already owned*/\r
574                     policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
575                     policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;\r
576                     allocPassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);\r
577                     if (!allocPassesPolicy) {\r
578                         retVal = RM_SERVICE_DENIED_EXCLUSIVE_RES_ALLOCD;\r
579                     }\r
580                 }\r
581                 if (allocPassesPolicy && (matchingNode->allocationCount == 1)) {\r
582                     /* Check exclusive privileges of instance that currently owns resource */\r
583                     policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
584                     policyCheckCfg.validInstNode = matchingNode->ownerList->instNameNode;\r
585                     allocPassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);\r
586                     if (!allocPassesPolicy) {\r
587                         retVal = RM_SERVICE_DENIED_ALLOCD_TO_EXCLUSIVE_INST;\r
588                     }                \r
589                 }  \r
590             }\r
591             \r
592             if (allocPassesPolicy) {   \r
593                 if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd)) {\r
594                     /* findNode range matches matchingNode range\r
595                      *\r
596                      *   |<--left node-->||<--matched  node-->||<--right node-->| => existing node\r
597                      *                    |<--alloc request-->|  => requested resources\r
598                      */                     \r
599                     leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
600                     rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
601                     RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
602                     addOwner(matchingNode, opInfo->serviceSrcInstNode);\r
603 \r
604                     if (leftNode && compareResourceNodeOwners(leftNode, matchingNode)) {\r
605                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
606                         combineLeft = true;\r
607                     }\r
608                     if (rightNode && compareResourceNodeOwners(rightNode, matchingNode)) {\r
609                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
610                         combineRight = true;\r
611                     }\r
612 \r
613                     if (combineLeft && combineRight) {\r
614                         /* Combine all three nodes into matchingNode */\r
615                         matchingNode->base = leftNode->base;\r
616                         matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;\r
617 \r
618                         clearOwners(leftNode);\r
619                         rmResourceNodeFree(leftNode);\r
620                         clearOwners(rightNode);\r
621                         rmResourceNodeFree(rightNode);                        \r
622                     }\r
623                     else if (combineLeft) {\r
624                         /* Combine left and matching nodes.  Reinsert right. */\r
625                         matchingNode->base = leftNode->base;\r
626                         matchingNode->length += leftNode->length;\r
627 \r
628                         clearOwners(leftNode);\r
629                         rmResourceNodeFree(leftNode);\r
630                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);                        \r
631                     }\r
632                     else if (combineRight) {\r
633                         /* Combine right and matching nodes.  Reinsert left. */\r
634                         matchingNode->length += rightNode->length;\r
635 \r
636                         clearOwners(rightNode);\r
637                         rmResourceNodeFree(rightNode);\r
638                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
639                     }\r
640                     else {\r
641                         /* No combine. */\r
642                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
643                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
644                     }\r
645 \r
646                     /* Always reinsert matchingNode */                \r
647                     RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);   \r
648                 }   \r
649                 else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {\r
650                     /* findNode range is subset of matchingNode range and neither boundary is\r
651                      * equivalent.\r
652                      *\r
653                      * |<----------matched node---------->|\r
654                      *        |<---alloc request--->|\r
655                      */ \r
656                     RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
657                     leftNode = rmResourceNodeNew(matchingNode->base, findNode.base - matchingNode->base);\r
658                     copyOwners(leftNode, matchingNode);\r
659                     rightNode = rmResourceNodeNew(findNode.base + findNode.length, matchingEnd - findEnd);\r
660                     copyOwners(rightNode, matchingNode);\r
661 \r
662                     matchingNode->base = findNode.base;                                    \r
663                     matchingNode->length = findNode.length;\r
664                     addOwner(matchingNode, opInfo->serviceSrcInstNode);\r
665 \r
666                     /* Insert all the nodes */\r
667                     RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
668                     RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
669                     RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
670                 }  \r
671                 else {    \r
672                     if (findNode.base == matchingNode->base) {\r
673                         /* findNode base and matchingNode base are equivalent.  May be combine\r
674                          * possibilities to the left\r
675                          *\r
676                          * |<---left node (alloc'd)--->||<----------matched node---------->|\r
677                          *                              |<---findNode (alloc req)--->|\r
678                          */                         \r
679                         leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
680                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
681                         /* Add allocating instance to owner list for compare with leftNode */\r
682                         addOwner(matchingNode, opInfo->serviceSrcInstNode);\r
683                         \r
684                         if (leftNode && compareResourceNodeOwners(leftNode, matchingNode)) {\r
685                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
686                             /* Combine leftNode and findNode */\r
687                             leftNode->length += findNode.length;\r
688                         }\r
689                         else {\r
690                             leftNode = rmResourceNodeNew(findNode.base, findNode.length);\r
691                             copyOwners(leftNode, matchingNode);\r
692                         }\r
693 \r
694                         /* Account for leftNode in matchingNode */\r
695                         matchingNode->base = findNode.base + findNode.length;\r
696                         matchingNode->length = matchingEnd - findEnd;  \r
697 \r
698                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
699                     }\r
700                     else if (findEnd == matchingEnd) {\r
701                         /* findNode end and matchingNode end are equivalent.  May be combine\r
702                          * possibilities to the right\r
703                          *\r
704                          * |<----------matched node---------->||<---right node (alloc'd)--->|\r
705                          *       |<---findNode (alloc req)--->| \r
706                          */                        \r
707                         rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
708                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
709                         /* Add allocating instance to owner list for compare with rightNode */\r
710                         addOwner(matchingNode, opInfo->serviceSrcInstNode);\r
711                         \r
712                         if (rightNode && compareResourceNodeOwners(rightNode, matchingNode)) {\r
713                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
714                             /* Combine rightNode and findNode */\r
715                             rightNode->base = findNode.base;\r
716                             rightNode->length += findNode.length;\r
717                         }\r
718                         else {\r
719                             rightNode = rmResourceNodeNew(findNode.base, findNode.length);\r
720                             copyOwners(rightNode, matchingNode);\r
721                         }\r
722 \r
723                         /* Account for rightNode in matchingNode */\r
724                         matchingNode->length -= findNode.length;  \r
725 \r
726                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
727                     }\r
728                     /* Remove allocating instance from leftover matchingNode */\r
729                     deleteOwner(matchingNode, opInfo->serviceSrcInstNode);\r
730                     RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
731                 }\r
732                 retVal = RM_SERVICE_APPROVED;\r
733             }\r
734         }\r
735         else {\r
736             retVal = RM_SERVICE_DENIED_PARTIAL_ALLOCATION;\r
737         }\r
738     }\r
739     else {\r
740         retVal = RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST;\r
741     }\r
742 \r
743     return(retVal);        \r
744 }\r
745 \r
746 /* FUNCTION PURPOSE: Frees a resource\r
747  ***********************************************************************\r
748  * DESCRIPTION: Will attempt to free the resource with specified\r
749  *              base and length from the resource's allocator.  The\r
750  *              free algorithm will verify the free request parameters\r
751  *              match an allocated range for the resource and that the\r
752  *              range is owned by the instance requesting the free. If\r
753  *              the free is validated the algorithm will free the \r
754  *              resource then combine any resource nodes that may have\r
755  *              become equivalent (in terms of ownership) after the\r
756  *              allocation.\r
757  */\r
758 static int32_t treeFree(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
759 {\r
760     Rm_ResourceNode  findNode;\r
761     Rm_ResourceNode *matchingNode = NULL;\r
762     Rm_ResourceNode *leftNode = NULL;\r
763     Rm_ResourceNode *rightNode = NULL;\r
764     bool             combineLeft = false;\r
765     bool             combineRight = false;\r
766     uint32_t         findEnd;\r
767     uint32_t         matchingEnd;\r
768     int32_t          retVal;\r
769 \r
770     memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));\r
771     findNode.base = opInfo->resourceInfo->base;\r
772     findNode.length = opInfo->resourceInfo->length;\r
773     matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);\r
774 \r
775     if (matchingNode) {\r
776         findEnd = findNode.base + findNode.length - 1;\r
777         matchingEnd = matchingNode->base + matchingNode->length - 1;\r
778         \r
779         if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {  \r
780             if (matchingNode->allocationCount) {\r
781                 if (isOwnedBy(matchingNode, opInfo->serviceSrcInstNode)) {\r
782                     if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd))\r
783                     {\r
784                         /* Case 1: Free range equals allocated matched node exactly. Attempt to combine \r
785                          *         freed node with nodes to left and right.\r
786                          *\r
787                          * |<--left node-->||<---matched node--->||<--right node-->|\r
788                          *                  |<---free request--->|\r
789                          */ \r
790                         leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
791                         rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
792                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
793                         deleteOwner(matchingNode, opInfo->serviceSrcInstNode);\r
794 \r
795                         if (leftNode && compareResourceNodeOwners(leftNode, matchingNode)) {\r
796                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
797                             combineLeft = true;\r
798                         }\r
799                         if (rightNode && compareResourceNodeOwners(rightNode, matchingNode)) {\r
800                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
801                             combineRight = true;\r
802                         }\r
803 \r
804                         if (combineLeft && combineRight) {\r
805                             /* Combine all three nodes into matchingNode */\r
806                             matchingNode->base = leftNode->base;\r
807                             matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;\r
808 \r
809                             clearOwners(leftNode);\r
810                             rmResourceNodeFree(leftNode);\r
811                             clearOwners(rightNode);\r
812                             rmResourceNodeFree(rightNode);                        \r
813                         }\r
814                         else if (combineLeft) {\r
815                             /* Combine left and matching nodes.  Reinsert right. */\r
816                             matchingNode->base = leftNode->base;\r
817                             matchingNode->length += leftNode->length;\r
818 \r
819                             clearOwners(leftNode);\r
820                             rmResourceNodeFree(leftNode);\r
821                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);                        \r
822                         }\r
823                         else if (combineRight) {\r
824                             /* Combine right and matching nodes.  Reinsert left. */\r
825                             matchingNode->length += rightNode->length;\r
826 \r
827                             clearOwners(rightNode);\r
828                             rmResourceNodeFree(rightNode);\r
829                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
830                         }\r
831                         else {\r
832                             /* No combine. */\r
833                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
834                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
835                         }\r
836 \r
837                         /* Always reinsert matchingNode */\r
838                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);                    \r
839                     }\r
840                     else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {\r
841                         /* Case 2: Free range is less than range in matched node. Split\r
842                          *         matched node into three nodes.\r
843                          *\r
844                          * |<----------matched node---------->|\r
845                          *        |<---free request--->|\r
846                          *\r
847                          * Remove instance from AllocatedTo list then add it back in for side nodes for\r
848                          * proper accounting of allocations in validInstance list\r
849                          */ \r
850                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
851                         deleteOwner(matchingNode, opInfo->serviceSrcInstNode);\r
852                         \r
853                         leftNode = rmResourceNodeNew(matchingNode->base, findNode.base - matchingNode->base);\r
854                         copyOwners(leftNode, matchingNode);\r
855                         addOwner(leftNode, opInfo->serviceSrcInstNode);\r
856                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
857                         \r
858                         rightNode = rmResourceNodeNew(findNode.base + findNode.length, matchingEnd - findEnd);\r
859                         copyOwners(rightNode, matchingNode);\r
860                         addOwner(rightNode, opInfo->serviceSrcInstNode);\r
861                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
862 \r
863                         matchingNode->base = findNode.base;                                    \r
864                         matchingNode->length = findNode.length;\r
865                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
866                     }\r
867                     else {                        \r
868                         if (findNode.base == matchingNode->base) {\r
869                             /* Case 3: Free range is on left boundary of matched node. Try to \r
870                              *         combine free range with left node.\r
871                              *\r
872                              * |<---left node (free)--->||<----------matched node---------->|\r
873                              *                           |<---findNode (free req)--->|\r
874                              */ \r
875 \r
876                             leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
877                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
878                             /* Remove freeing instance from owner list for compare with leftNode */\r
879                             deleteOwner(matchingNode, opInfo->serviceSrcInstNode);\r
880                             \r
881                             if (leftNode && compareResourceNodeOwners(leftNode, matchingNode)) {\r
882                                 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
883                                 /* Combine leftNode and findNode */\r
884                                 leftNode->length += findNode.length;\r
885                             }\r
886                             else {\r
887                                 leftNode = rmResourceNodeNew(findNode.base, findNode.length);\r
888                                 copyOwners(leftNode, matchingNode);\r
889                             }\r
890 \r
891                             /* Remove leftNode range from matchingNode */\r
892                             matchingNode->base = findNode.base + findNode.length;\r
893                             matchingNode->length = matchingEnd - findEnd;  \r
894                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
895                         }\r
896                         else if (findEnd == matchingEnd) {\r
897                             /* Case 4: Free range is on right boundary of matched node. Try to \r
898                              *         combine free range with right node.\r
899                              *\r
900                              * |<----------matched node---------->||<---right node (free)--->|\r
901                              *        |<---findNode (free req)--->|\r
902                              */ \r
903                             \r
904                             rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
905                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode); \r
906                             /* Remove freeing instance from owner list for compare with rightNode */\r
907                             deleteOwner(matchingNode, opInfo->serviceSrcInstNode);\r
908                             \r
909                             if (rightNode && compareResourceNodeOwners(rightNode, matchingNode)) {\r
910                                 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
911                                 /* Combine rightNode and findNode */\r
912                                 rightNode->base = findNode.base;\r
913                                 rightNode->length += findNode.length;\r
914                             }\r
915                             else {\r
916                                 rightNode = rmResourceNodeNew(findNode.base, findNode.length);\r
917                                 copyOwners(rightNode, matchingNode);\r
918                             }\r
919 \r
920                             /* Remove rightNode range from matchingNode */\r
921                             matchingNode->length -= findNode.length;  \r
922                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
923                         }\r
924 \r
925                         /* Add freeing instance back into matchingNode allocations */\r
926                         addOwner(matchingNode, opInfo->serviceSrcInstNode);\r
927                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
928                     }\r
929 \r
930                     retVal = RM_SERVICE_APPROVED;\r
931                 }\r
932                 else {\r
933                     retVal = RM_SERVICE_DENIED_RES_NOT_ALLOCD_TO_INST;\r
934                 }\r
935             }\r
936             else {\r
937                 retVal = RM_SERVICE_DENIED_RES_ALREADY_FREE;\r
938             }\r
939         }\r
940         else {\r
941             retVal = RM_SERVICE_DENIED_PARTIAL_FREE;\r
942         }\r
943     }\r
944     else {\r
945         retVal = RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST;\r
946     }\r
947     return(retVal);  \r
948 }\r
949 \r
950 /* FUNCTION PURPOSE: Issues a service response to application\r
951  ***********************************************************************\r
952  * DESCRIPTION: Provides a service response back to the application\r
953  *              using the service callback function provided to\r
954  *              the RM instance at the time of the service request.\r
955  */\r
956 static void serviceResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
957 {\r
958     Rm_ServiceRespInfo serviceResponse;\r
959 \r
960     /* The responseTransaction will contain the resultant state details of\r
961      * the requestTransaction's service request */\r
962     serviceResponse.serviceState = transaction->state;\r
963     /* Pass back the ID that was provided to the component when it requested\r
964      * the service */\r
965     serviceResponse.serviceId = transaction->localId;\r
966 \r
967     /* Service was approved and service was an allocate request.  The resource\r
968      * data is passed back to the component */\r
969     if ((serviceResponse.serviceState == RM_SERVICE_APPROVED) &&\r
970         ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||\r
971          (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||\r
972          (transaction->type == Rm_service_RESOURCE_GET_BY_NAME)))\r
973     {\r
974         strncpy(serviceResponse.resourceName, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);\r
975         serviceResponse.resourceBase = transaction->resourceInfo.base;\r
976         serviceResponse.resourceLength = transaction->resourceInfo.length;\r
977     }\r
978 \r
979     /* Issue the callback to the requesting component with the response information */\r
980     transaction->callback.serviceCallback(&serviceResponse);\r
981 \r
982     /* Delete the transaction from the transaction queue */\r
983     rmTransactionQueueDelete(rmInst, transaction->localId);\r
984     return;\r
985 }\r
986 \r
987 /* FUNCTION PURPOSE: Sends RM response packets\r
988  ***********************************************************************\r
989  * DESCRIPTION: Sends RM response packets to RM instance's that sent\r
990  *              RM request packets to the RM instance.  The response\r
991  *              is sent via the RM transport API which is plugged\r
992  *              with an application created transport path.\r
993  */\r
994 static void transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
995 {\r
996     Rm_Transport    *dstTransport = NULL;\r
997     Rm_PacketHandle  pktHandle = NULL;\r
998 \r
999     dstTransport = rmTransportFindRemoteName((Rm_Transport *) rmInst->transports, transaction->pktSrcInstName);\r
1000 \r
1001     switch (transaction->type) {\r
1002         case Rm_service_RESOURCE_ALLOCATE_INIT:\r
1003         case Rm_service_RESOURCE_ALLOCATE_USE:\r
1004         case Rm_service_RESOURCE_FREE:\r
1005         case Rm_service_RESOURCE_GET_BY_NAME:\r
1006             pktHandle = rmTransportCreateResourceResponsePkt(rmInst, dstTransport->appTransportHandle, \r
1007                                                              transaction);\r
1008             break;\r
1009         case Rm_service_RESOURCE_MAP_TO_NAME:\r
1010         case Rm_service_RESOURCE_UNMAP_NAME:\r
1011             pktHandle = rmTransportCreateNsResponsePkt(rmInst, dstTransport->appTransportHandle,\r
1012                                                        transaction);\r
1013             break;\r
1014     }\r
1015 \r
1016     if (pktHandle) {\r
1017         if (rmInst->transportCallouts.rmSendPkt) {\r
1018             if (rmInst->transportCallouts.rmSendPkt(dstTransport->appTransportHandle, pktHandle) < RM_OK) {\r
1019                 transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;\r
1020             }\r
1021         }\r
1022         else {\r
1023             transaction->state = RM_ERROR_TRANSPORT_SEND_NOT_REGD;\r
1024         }\r
1025     }\r
1026     rmTransactionQueueDelete(rmInst, transaction->localId);\r
1027 }\r
1028 \r
1029 /* FUNCTION PURPOSE: Sends RM request packets\r
1030  ***********************************************************************\r
1031  * DESCRIPTION: Sends RM request packets to RM instance's that are\r
1032  *              capable of forwarding or validating service requests.\r
1033  *              The request is sent via the RM transport API which is\r
1034  *              plugged with an application created transport path.\r
1035  */\r
1036 static void transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
1037 {\r
1038     Rm_Transport    *dstTransport = NULL;\r
1039     Rm_PacketHandle  pktHandle = NULL;\r
1040 \r
1041     if (rmInst->registeredWithDelegateOrServer) {\r
1042         if (rmInst->instType == Rm_instType_CLIENT) {\r
1043             dstTransport = rmTransportFindRemoteInstType((Rm_Transport *) rmInst->transports, Rm_instType_CLIENT_DELEGATE);\r
1044 \r
1045             if (!dstTransport) {\r
1046                 dstTransport = rmTransportFindRemoteInstType((Rm_Transport *) rmInst->transports, Rm_instType_SERVER);\r
1047             }\r
1048         } \r
1049         else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {\r
1050             dstTransport = rmTransportFindRemoteInstType((Rm_Transport *) rmInst->transports, Rm_instType_SERVER);\r
1051         }\r
1052 \r
1053         switch (transaction->type) {\r
1054             case Rm_service_RESOURCE_ALLOCATE_INIT:\r
1055             case Rm_service_RESOURCE_ALLOCATE_USE:\r
1056             case Rm_service_RESOURCE_FREE:\r
1057             case Rm_service_RESOURCE_GET_BY_NAME:\r
1058                 pktHandle = rmTransportCreateResourceReqPkt(rmInst, dstTransport->appTransportHandle, transaction);\r
1059                 break;\r
1060             case Rm_service_RESOURCE_MAP_TO_NAME:\r
1061             case Rm_service_RESOURCE_UNMAP_NAME:\r
1062                 pktHandle = rmTransportCreateNsRequestPkt(rmInst, dstTransport->appTransportHandle, transaction);\r
1063                 break;\r
1064         }\r
1065 \r
1066         if (pktHandle) {\r
1067             if (rmInst->transportCallouts.rmSendPkt) {            \r
1068                 if (rmInst->transportCallouts.rmSendPkt(dstTransport->appTransportHandle, pktHandle) < RM_OK) {\r
1069                     transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;\r
1070                 }\r
1071             }\r
1072             else {\r
1073                 transaction->state = RM_ERROR_TRANSPORT_SEND_NOT_REGD;\r
1074             }                \r
1075         }\r
1076 \r
1077         transaction->hasBeenForwarded = true;\r
1078         /* Transaction not deleted.  Waiting for response from RM CD or Server */\r
1079     }\r
1080 }\r
1081 \r
1082 /* FUNCTION PURPOSE: Issues an allocator operation\r
1083  ***********************************************************************\r
1084  * DESCRIPTION: Issues an allocator preallocate, allocate, or free\r
1085  *              for an RM resource.\r
1086  */\r
1087 static int32_t allocatorOperation(Rm_Inst *rmInst, Rm_AllocatorOpInfo *opInfo)\r
1088 {\r
1089     Rm_Allocator *allocator = NULL;\r
1090     int32_t       resourceOffsetInPolicy;\r
1091     int32_t       retVal;\r
1092     \r
1093     resourceOffsetInPolicy = rmPolicyGetResourceOffset(rmInst->policy, opInfo->resourceInfo->name);\r
1094     allocator = rmAllocatorFind(rmInst->allocators, opInfo->resourceInfo->name);\r
1095     \r
1096     if ((resourceOffsetInPolicy > 0) && allocator) {\r
1097         if (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE) {\r
1098             retVal = treePreAllocate(rmInst, allocator, resourceOffsetInPolicy, opInfo);\r
1099         }               \r
1100         else if (opInfo->operation == Rm_allocatorOp_ALLOCATE) {\r
1101             retVal = treeAllocate(rmInst, allocator, resourceOffsetInPolicy, opInfo);\r
1102         }\r
1103         else if (opInfo->operation == Rm_allocatorOp_FREE) {\r
1104             retVal = treeFree(allocator, opInfo);\r
1105         }         \r
1106     }\r
1107     else {\r
1108         /* Resource could not be found in policy and/or allocator */\r
1109         retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;\r
1110     }\r
1111     return(retVal);\r
1112 }\r
1113 \r
1114 /* FUNCTION PURPOSE: Arbitrates allocation service requests\r
1115  ***********************************************************************\r
1116  * DESCRIPTION: Issues a set of allocator operations in order to\r
1117  *              handle a received allocation request.  Allocation\r
1118  *              requests are always forwarded to the Server on Client\r
1119  *              CD instances.  If a request is made with a NameServer\r
1120  *              name the resource base and length parameters are\r
1121  *              retrieved from the NameServer prior to the allocation\r
1122  *              attempt.\r
1123  */\r
1124 static void allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction, void *validInstNode,\r
1125                                uint32_t allocType)\r
1126 {\r
1127     Rm_AllocatorOpInfo  opInfo;\r
1128     Rm_NameServerObjCfg nameServerObjCfg;\r
1129     int32_t             retVal = transaction->state;\r
1130 \r
1131     memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));\r
1132     \r
1133     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {\r
1134         /* Forward all allocation requests to Server if transport is up.  Otherwise, just queue. */\r
1135         if (rmInst->registeredWithDelegateOrServer) {\r
1136             transactionForwarder(rmInst, transaction);   \r
1137         }  \r
1138     }\r
1139     else if (rmInst->instType == Rm_instType_SERVER) {\r
1140         opInfo.resourceInfo = &transaction->resourceInfo;\r
1141         opInfo.serviceSrcInstNode = validInstNode;\r
1142         opInfo.allocType = allocType;\r
1143 \r
1144         /* Populated NameServer name has precedence over base */\r
1145         if (strlen(transaction->resourceInfo.nameServerName) > 0) {\r
1146             if ((transaction->resourceInfo.base == 0) &&\r
1147                 (transaction->resourceInfo.length == 0) &&\r
1148                 (transaction->resourceInfo.alignment == 0)) {\r
1149                 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));\r
1150                 nameServerObjCfg.nameServerTree = rmInst->nameServer;\r
1151                 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;\r
1152                 if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {\r
1153                     strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);\r
1154                     transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;\r
1155                     transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;\r
1156                 }                \r
1157             }\r
1158             else {\r
1159                 retVal = RM_ERROR_NS_NAME_AND_RES_VAL_CONFLICT;\r
1160             }\r
1161         }\r
1162 \r
1163         if (retVal == RM_SERVICE_PROCESSING) {      \r
1164             if (transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) {\r
1165                 opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE;\r
1166                 retVal = allocatorOperation(rmInst, &opInfo);\r
1167             }\r
1168         \r
1169             if (retVal == RM_SERVICE_PROCESSING) {\r
1170                 opInfo.operation = Rm_allocatorOp_ALLOCATE;\r
1171                 retVal = allocatorOperation(rmInst, &opInfo);\r
1172             }      \r
1173         }\r
1174         \r
1175         transaction->state = retVal;\r
1176 \r
1177         if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {\r
1178             /* Source of allocation was not the server instance, provide the transaction\r
1179              * to the transaction responder */\r
1180             transactionResponder(rmInst, transaction);\r
1181         }\r
1182         /* Otherwise let the return stack return the transaction to the serviceHandler */                   \r
1183     }   \r
1184 }\r
1185 \r
1186 /* FUNCTION PURPOSE: Arbitrates free service requests\r
1187  ***********************************************************************\r
1188  * DESCRIPTION: Issues a set of allocator operations in order to\r
1189  *              handle a received free request.  Free\r
1190  *              requests are always forwarded to the Server on Client\r
1191  *              CD instances.  If a request is made with a NameServer\r
1192  *              name the resource base and length parameters are\r
1193  *              retrieved from the NameServer prior to the free\r
1194  *              attempt.\r
1195  */\r
1196 static void freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction, void *validInstNode)\r
1197 {\r
1198     Rm_AllocatorOpInfo  opInfo; \r
1199     Rm_NameServerObjCfg nameServerObjCfg;    \r
1200     int32_t             retVal = transaction->state;\r
1201 \r
1202     memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));\r
1203     \r
1204     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {\r
1205         /* Forward all free requests to Server if transport is up.  Otherwise, just queue. */\r
1206         if (rmInst->registeredWithDelegateOrServer) {\r
1207             transactionForwarder(rmInst, transaction);   \r
1208         }\r
1209     }\r
1210     else if (rmInst->instType == Rm_instType_SERVER) {\r
1211         opInfo.resourceInfo = &transaction->resourceInfo;\r
1212         opInfo.serviceSrcInstNode = validInstNode;\r
1213 \r
1214         /* Populated NameServer name has precedence over base */\r
1215         if (strlen(transaction->resourceInfo.nameServerName) > 0) {\r
1216             if ((transaction->resourceInfo.base == 0) &&\r
1217                 (transaction->resourceInfo.length == 0) &&\r
1218                 (transaction->resourceInfo.alignment == 0)) {\r
1219                 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));\r
1220                 nameServerObjCfg.nameServerTree = rmInst->nameServer;\r
1221                 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;\r
1222                 if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {\r
1223                     strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);\r
1224                     transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;\r
1225                     transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;\r
1226                 } \r
1227             }\r
1228             else {\r
1229                 retVal = RM_ERROR_NS_NAME_AND_RES_VAL_CONFLICT;\r
1230             }                \r
1231         }\r
1232         \r
1233         if(retVal == RM_SERVICE_PROCESSING) {        \r
1234             opInfo.operation = Rm_allocatorOp_FREE;\r
1235             retVal = allocatorOperation(rmInst, &opInfo);\r
1236         }       \r
1237 \r
1238         transaction->state = retVal;\r
1239 \r
1240         if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {\r
1241             /* Source of allocation was not the server instance, provide the transaction\r
1242              * to the transaction responder */\r
1243             transactionResponder(rmInst, transaction);\r
1244         }\r
1245         /* Otherwise let the return stack return the transaction to the serviceHandler */        \r
1246     }   \r
1247 }\r
1248 \r
1249 /* FUNCTION PURPOSE: Reserves a Linux resource\r
1250  ***********************************************************************\r
1251  * DESCRIPTION: Reserves resources for Linux using the base and length\r
1252  *              values retrieved from the Linux DTB via the\r
1253  *              "linux-dtb-alias" properties within the GRL.\r
1254  */\r
1255 static int32_t reserveLinuxResource(Rm_Inst *rmInst, Rm_LinuxAlias *linuxAlias, \r
1256                                     Rm_LinuxValueRange *linuxValues, Rm_AllocatorOpInfo *opInfo)\r
1257 {\r
1258     int32_t  retVal = RM_OK;\r
1259     bool     baseFound = false;\r
1260     bool     lengthFound = false;\r
1261     uint32_t valueIndex = 0;\r
1262 \r
1263     while ((linuxValues) && (!baseFound || !lengthFound)) {\r
1264         if (linuxAlias->baseOffset == valueIndex) {\r
1265             opInfo->resourceInfo->base = linuxValues->value;\r
1266             baseFound = true;\r
1267 \r
1268             if (linuxAlias->lengthOffset == RM_DTB_UTIL_LINUX_ALIAS_OFFSET_NOT_SET) {\r
1269                 opInfo->resourceInfo->length = 1;\r
1270                 lengthFound = true;\r
1271             }\r
1272         }\r
1273         else if (linuxAlias->lengthOffset == valueIndex) {\r
1274             opInfo->resourceInfo->length = linuxValues->value;\r
1275             lengthFound = true;\r
1276         }\r
1277 \r
1278         linuxValues = (Rm_LinuxValueRange *)linuxValues->nextValue;\r
1279         valueIndex++;\r
1280     }\r
1281 \r
1282     if (!baseFound || !lengthFound) {\r
1283         retVal = RM_ERROR_DATA_NOT_FOUND_AT_LINUX_ALIAS;\r
1284     }\r
1285     else {\r
1286         /* Allocate resource to Linux */\r
1287         retVal = allocatorOperation(rmInst, opInfo);\r
1288     }\r
1289     return (retVal);\r
1290 }\r
1291 \r
1292 /* FUNCTION PURPOSE: Finds and reserves Linux resources\r
1293  ***********************************************************************\r
1294  * DESCRIPTION: Parses the Linux DTB for resources consumed by the\r
1295  *              Linux kernel.  If the resource is found via the\r
1296  *              "linux-dtb-alias" property defined in the GRL it is \r
1297  *              reserved.\r
1298  */\r
1299 static int32_t findAndReserveLinuxResource(Rm_Inst *rmInst, const char *resourceName, void *linuxDtb, \r
1300                                            Rm_LinuxAlias *linuxAlias)\r
1301 {\r
1302     Rm_AllocatorOpInfo  opInfo;\r
1303     Rm_ResourceInfo     resourceInfo;\r
1304     uint32_t            pathOffset;\r
1305     uint32_t            pathSize;\r
1306     char               *spacePtr;\r
1307     int32_t             propOffset;\r
1308     int32_t             nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;\r
1309     int32_t             prevDepth = RM_DTB_UTIL_STARTING_DEPTH;\r
1310     int32_t             depth;\r
1311     int32_t             propertyLen;\r
1312     const char         *propertyName;\r
1313     const void         *propertyData; \r
1314     Rm_LinuxValueRange *linuxValueRange;\r
1315     int32_t             retVal = RM_OK; \r
1316 \r
1317     memset((void *) &opInfo, 0, sizeof(Rm_AllocatorOpInfo));\r
1318     memset((void *) &resourceInfo, 0, sizeof(Rm_ResourceInfo));\r
1319 \r
1320     strncpy(resourceInfo.name, resourceName, RM_NAME_MAX_CHARS);\r
1321     opInfo.serviceSrcInstNode = rmPolicyGetLinuxInstNode(rmInst->validInstances);\r
1322     opInfo.operation = Rm_allocatorOp_ALLOCATE;\r
1323     opInfo.resourceInfo = &resourceInfo;    \r
1324 \r
1325     while(linuxAlias) {\r
1326         /* Reset parsing variables */\r
1327         pathOffset = 0;\r
1328         pathSize = strlen(linuxAlias->path) + 1;\r
1329         nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;\r
1330         prevDepth = RM_DTB_UTIL_STARTING_DEPTH;   \r
1331         resourceInfo.base = 0;\r
1332         resourceInfo.length = 0;\r
1333 \r
1334         spacePtr = strpbrk(linuxAlias->path, " ");\r
1335         if (spacePtr) {\r
1336             *spacePtr = '\0';\r
1337         }       \r
1338         \r
1339         while(pathOffset < pathSize) {\r
1340             /* Move through DTB nodes until next alias path node found */\r
1341             if (strcmp(linuxAlias->path + pathOffset, fdt_get_name(linuxDtb, nodeOffset, NULL))) {\r
1342                 nodeOffset = fdt_next_node(linuxDtb, nodeOffset, &depth);\r
1343 \r
1344                 if ((depth < prevDepth) || (nodeOffset == -FDT_ERR_NOTFOUND)) {\r
1345                     /* Returning from subnode that matched part of alias path without finding\r
1346                      * resource values */\r
1347                     retVal = RM_ERROR_DATA_NOT_FOUND_AT_LINUX_ALIAS;\r
1348                     break;\r
1349                 }\r
1350             }\r
1351             else {\r
1352                 /* Found next alias path node.  Move to next node name in path string. */\r
1353                 pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);\r
1354                 spacePtr = strpbrk(linuxAlias->path + pathOffset, " ");\r
1355                 if (spacePtr) {\r
1356                     *spacePtr = '\0';\r
1357                 }       \r
1358                 \r
1359                 prevDepth = fdt_node_depth(linuxDtb, nodeOffset);\r
1360                 propOffset = fdt_first_property_offset(linuxDtb, nodeOffset);\r
1361                 while ((propOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) &&\r
1362                        (pathOffset < pathSize)) {\r
1363                     propertyData = fdt_getprop_by_offset(linuxDtb, propOffset, \r
1364                                                          &propertyName, &propertyLen);\r
1365 \r
1366                     if (strcmp(linuxAlias->path + pathOffset, propertyName) == 0) {\r
1367                         /* Found resource at end of alias path */\r
1368                         pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);\r
1369                         linuxValueRange = rmDtbUtilLinuxExtractValues(propertyData, propertyLen);\r
1370                         retVal = reserveLinuxResource(rmInst, linuxAlias, \r
1371                                                       linuxValueRange, &opInfo);\r
1372                         rmDtbUtilLinuxFreeValues(linuxValueRange);\r
1373                     }\r
1374                     propOffset = fdt_next_property_offset(linuxDtb, propOffset);\r
1375                 } \r
1376 \r
1377                 if (propOffset < -FDT_ERR_NOTFOUND) {\r
1378                     retVal = propOffset;\r
1379                     break;\r
1380                 }\r
1381             }\r
1382         }\r
1383 \r
1384         if (retVal < RM_OK) {\r
1385             break;\r
1386         }\r
1387         linuxAlias = linuxAlias->nextLinuxAlias;\r
1388     }\r
1389     return (retVal);\r
1390 }\r
1391 \r
1392 /* FUNCTION PURPOSE: Creates and initializes a resource allocator\r
1393  ***********************************************************************\r
1394  * DESCRIPTION: Creates a resource allocator for the provided\r
1395  *              resource name and resource properties retrieved\r
1396  *              from the GRL.  Resources will be reserved for \r
1397  *              the Linux kernel if the Linux DTB is provided\r
1398  *              and there are "linux-dtb-alias" properties\r
1399  *              specified in the GRL.\r
1400  */\r
1401 static int32_t createAndInitAllocator(Rm_Inst *rmInst, const char *resourceName, \r
1402                                       Rm_ResourceProperties *resourceProperties, void *linuxDtb)\r
1403 {\r
1404     Rm_ResourceRange    *range = NULL;\r
1405     Rm_ResourceRange    *rangeBasePtr = NULL;\r
1406     Rm_NsAssignment     *nsAssignments = NULL;\r
1407     Rm_NsAssignment     *nsAssignmentBasePtr = NULL;\r
1408     Rm_LinuxAlias       *linuxAlias = NULL;\r
1409     Rm_NameServerObjCfg  nameServerObjCfg;      \r
1410     int32_t              retVal = RM_OK;\r
1411 \r
1412     if (resourceProperties->rangeData && (resourceProperties->rangeLen > 0)) {\r
1413         range = rangeBasePtr = rmDtbUtilResExtractRange(resourceProperties->rangeData, \r
1414                                                         resourceProperties->rangeLen);\r
1415         \r
1416         if ((retVal = createResourceTree(rmInst, resourceName, range)) >= RM_OK) {\r
1417             if (resourceProperties->linuxAliasData && resourceProperties->linuxAliasLen) {\r
1418                 if (linuxDtb) {\r
1419                     linuxAlias = rmDtbUtilResExtractLinuxAlias(resourceProperties->linuxAliasData,\r
1420                                                                resourceProperties->linuxAliasLen, &retVal);\r
1421                     if (linuxAlias) {\r
1422                         retVal = findAndReserveLinuxResource(rmInst, resourceName, linuxDtb, linuxAlias);            \r
1423                     }\r
1424                 }\r
1425                 else {\r
1426                     retVal = RM_ERROR_GRL_LINUX_ALIAS_BUT_NO_DTB;\r
1427                 }\r
1428             }\r
1429         }\r
1430     }\r
1431     \r
1432     if (retVal >= RM_OK) {\r
1433         if (resourceProperties->nsAssignData && resourceProperties->nsAssignLen) {\r
1434             nsAssignments = rmDtbUtilResExtractNsAssignment(resourceProperties->nsAssignData, \r
1435                                                             resourceProperties->nsAssignLen, &retVal);\r
1436             if (nsAssignments) {\r
1437                 nsAssignmentBasePtr = nsAssignments;\r
1438                 while (nsAssignments) {\r
1439                     memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));\r
1440                     nameServerObjCfg.nameServerTree = rmInst->nameServer;\r
1441                     nameServerObjCfg.nodeCfg.objName = nsAssignments->nsName;\r
1442                     nameServerObjCfg.nodeCfg.resourceName = (char *)resourceName;\r
1443                     nameServerObjCfg.nodeCfg.resourceBase= nsAssignments->resourceBase;\r
1444                     nameServerObjCfg.nodeCfg.resourceLength = nsAssignments->resourceLength;                \r
1445                     rmNameServerAddObject(&nameServerObjCfg);\r
1446                     nsAssignments = nsAssignments->nextNsAssignment;\r
1447                 }\r
1448                 rmDtbUtilResFreeNsAssignmentList(nsAssignmentBasePtr);\r
1449             }\r
1450         }\r
1451     }\r
1452 \r
1453     rmDtbUtilResFreeRange(rangeBasePtr);\r
1454     if (linuxAlias) {\r
1455         rmDtbUtilResFreeLinuxAlias(linuxAlias);\r
1456     }\r
1457     return(retVal);\r
1458 }\r
1459 \r
1460 /* FUNCTION PURPOSE: Recursively parses GRL resource properties\r
1461  ***********************************************************************\r
1462  * DESCRIPTION: Recursively parses and stores GRL resource node \r
1463  *              properties using the LIBFDT APIs\r
1464  */\r
1465 static int32_t parseResourceProperty(void *globalResourceDtb, int32_t offset, \r
1466                                      Rm_ResourceProperties *propertyInfo)\r
1467 {\r
1468         int32_t              propertyLen;\r
1469         const char          *propertyName;\r
1470         const void          *propertyData;\r
1471     Rm_ResourcePropType  propertyType;\r
1472     int32_t              retVal = RM_OK;\r
1473 \r
1474         propertyData = fdt_getprop_by_offset(globalResourceDtb, offset, &propertyName, &propertyLen);\r
1475     propertyType = rmDtbUtilResGetPropertyType(propertyName);\r
1476     if (propertyType == Rm_resourcePropType_RESOURCE_RANGE) {\r
1477         propertyInfo->rangeData = propertyData;\r
1478         propertyInfo->rangeLen = propertyLen;\r
1479     }\r
1480     else if (propertyType == Rm_resourcePropType_NSASSIGNMENT) {\r
1481         propertyInfo->nsAssignData = propertyData;\r
1482         propertyInfo->nsAssignLen = propertyLen;\r
1483     }\r
1484     else if (propertyType == Rm_resourcePropType_RESOURCE_LINUX_ALIAS) {\r
1485         propertyInfo->linuxAliasData = propertyData;\r
1486         propertyInfo->linuxAliasLen = propertyLen;\r
1487     }        \r
1488     else {\r
1489         retVal = RM_ERROR_GRL_UNKNOWN_RESOURCE_PROPERTY;\r
1490     }\r
1491 \r
1492     if (retVal == RM_OK) {\r
1493         offset = fdt_next_property_offset(globalResourceDtb, offset);\r
1494         if (offset >= 0) {\r
1495             retVal = parseResourceProperty(globalResourceDtb, offset, propertyInfo);\r
1496         }\r
1497         else if (offset != -FDT_ERR_NOTFOUND) {\r
1498             /* Error returned by LIBFDT */\r
1499             retVal = offset;\r
1500         }\r
1501     }\r
1502     return (retVal);\r
1503 }\r
1504 \r
1505 /* FUNCTION PURPOSE: Recursively parses GRL resource nodes\r
1506  ***********************************************************************\r
1507  * DESCRIPTION: Recursively parses GRL resource nodes looking for\r
1508  *              resource properties to create the resource allocators.\r
1509  *              The LIBFDT APIs are used to parse the GRL.\r
1510  */\r
1511 static int32_t parseResourceNode(Rm_Inst *rmInst, void *globalResourceDtb, int32_t nodeOffset, int32_t depth,\r
1512                                  void *linuxDtb)\r
1513 {\r
1514         const char            *resourceName = fdt_get_name(globalResourceDtb, nodeOffset, NULL);\r
1515     Rm_ResourceProperties  resourceProperties;\r
1516         int32_t                retVal = RM_OK;\r
1517         int32_t                offset;\r
1518 \r
1519     memset((void *)&resourceProperties, 0, sizeof(Rm_ResourceProperties));\r
1520     /* Get properties of resource node */\r
1521         offset = fdt_first_property_offset(globalResourceDtb, nodeOffset);\r
1522         if (offset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) {\r
1523                 retVal =  parseResourceProperty(globalResourceDtb, offset, &resourceProperties);\r
1524         if (retVal < -FDT_ERR_NOTFOUND) {\r
1525             return (retVal);\r
1526         }\r
1527         if (retVal = createAndInitAllocator(rmInst, resourceName, &resourceProperties, linuxDtb) < RM_OK) {\r
1528             return (retVal);\r
1529         }\r
1530         }\r
1531     else if (offset != -FDT_ERR_NOTFOUND) {\r
1532                 /* Error returned by LIBFDT */\r
1533         return (offset);\r
1534     }\r
1535     \r
1536         offset = fdt_next_node(globalResourceDtb, nodeOffset, &depth);\r
1537     if ((offset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && (depth >= RM_DTB_UTIL_STARTING_DEPTH)) {\r
1538         retVal = parseResourceNode(rmInst, globalResourceDtb, offset, depth, linuxDtb);\r
1539         if (retVal < -FDT_ERR_NOTFOUND) {\r
1540             return (retVal);\r
1541         }\r
1542     }\r
1543     else if (offset != -FDT_ERR_NOTFOUND) {\r
1544         /* Error returned by LIBFDT */\r
1545         return (offset);\r
1546     }\r
1547     return (retVal);\r
1548 }\r
1549 \r
1550 /* FUNCTION PURPOSE: Initializes server allocators\r
1551  ***********************************************************************\r
1552  * DESCRIPTION: Creates and initializes a server instance's\r
1553  *              resource allocators using the GRL and, if\r
1554  *              provided, Linux DTB.\r
1555  */\r
1556 static int32_t initializeAllocators(Rm_Inst *rmInst, void *globalResourceDtb, void *linuxDtb)\r
1557 {\r
1558     int32_t nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;\r
1559     int32_t startDepth = RM_DTB_UTIL_STARTING_DEPTH;\r
1560     int32_t result = RM_OK;\r
1561 \r
1562     /* Recursively parse the Global Resource List, creating an allocator for\r
1563      * each resource as specified in the node */\r
1564     result = parseResourceNode(rmInst, globalResourceDtb, nodeOffset, startDepth, linuxDtb);\r
1565 \r
1566     return(result);\r
1567 }\r
1568 \r
1569 /**********************************************************************\r
1570  ********************** Internal Functions ****************************\r
1571  **********************************************************************/\r
1572 \r
1573 /* FUNCTION PURPOSE: Adds a transaction\r
1574  ***********************************************************************\r
1575  * DESCRIPTION: Returns a pointer to a newly created transaction.\r
1576  *              The transaction is created based on a new service\r
1577  *              request received via the service API or the\r
1578  *              transport API (service forwarded from another instance)\r
1579  */\r
1580 Rm_Transaction *rmTransactionQueueAdd(Rm_Inst *rmInst)\r
1581 {\r
1582     Rm_Transaction *transactionQueue = rmInst->transactionQueue;\r
1583     Rm_Transaction *newTransaction   = NULL;\r
1584 \r
1585     newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction));\r
1586     if (newTransaction) {\r
1587         memset((void *)newTransaction, 0, sizeof(Rm_Transaction));\r
1588 \r
1589         newTransaction->localId = transactionGetSequenceNum(rmInst);\r
1590         newTransaction->nextTransaction = NULL;  \r
1591         if (transactionQueue) {\r
1592             while (transactionQueue->nextTransaction) {\r
1593                 transactionQueue = transactionQueue->nextTransaction;\r
1594             }\r
1595             transactionQueue->nextTransaction = newTransaction;\r
1596         }\r
1597         else {\r
1598             rmInst->transactionQueue = newTransaction;\r
1599         }\r
1600     }\r
1601     return (newTransaction);\r
1602 }\r
1603 \r
1604 /* FUNCTION PURPOSE: Finds a transaction\r
1605  ***********************************************************************\r
1606  * DESCRIPTION: Returns a pointer to a transaction resident\r
1607  *              in the transaction queue that matches the provided\r
1608  *              transaction ID.\r
1609  */\r
1610 Rm_Transaction *rmTransactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)\r
1611 {\r
1612     Rm_Transaction *transaction = rmInst->transactionQueue;\r
1613 \r
1614     while (transaction) {\r
1615         if (transaction->localId == transactionId) {\r
1616             break;             \r
1617         }\r
1618         transaction = transaction->nextTransaction;\r
1619     }\r
1620 \r
1621     return (transaction);\r
1622 }\r
1623 \r
1624 /* FUNCTION PURPOSE: Deletes a transaction\r
1625  ***********************************************************************\r
1626  * DESCRIPTION: Deletes the transaction with the provided transaction\r
1627  *              ID from the instance's transaction queue.\r
1628  */\r
1629 int32_t rmTransactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)\r
1630 {\r
1631     Rm_Transaction *transaction     = rmInst->transactionQueue;\r
1632     Rm_Transaction *prevTransaction = NULL;\r
1633     int32_t         retVal          = RM_OK;\r
1634 \r
1635     while (transaction) {\r
1636         if (transaction->localId == transactionId) {\r
1637             break;             \r
1638         }\r
1639 \r
1640         prevTransaction = transaction;\r
1641         transaction = transaction->nextTransaction;\r
1642     }\r
1643 \r
1644     if (transaction) {\r
1645         if (prevTransaction == NULL) {\r
1646             /* Transaction at start of queue. Map second transaction to start of queue \r
1647              * as long as more than one transactions. */\r
1648             rmInst->transactionQueue = transaction->nextTransaction;\r
1649         }\r
1650         else {\r
1651             /* Transaction in middle or end of queue. */\r
1652             prevTransaction->nextTransaction = transaction->nextTransaction;\r
1653         }\r
1654         Rm_osalFree((void *)transaction, sizeof(Rm_Transaction));\r
1655     }\r
1656     else {\r
1657         retVal = RM_ERROR_SERVICE_TRANS_DOES_NOT_EXIST;\r
1658     }    \r
1659     return (retVal);\r
1660 }\r
1661 \r
1662 /* FUNCTION PURPOSE: Finds an allocator\r
1663  ***********************************************************************\r
1664  * DESCRIPTION: Returns a pointer to an allocator that matches the \r
1665  *              provided resource name.\r
1666  */\r
1667 Rm_Allocator *rmAllocatorFind(Rm_Allocator *allocatorList, char *resourceName)\r
1668 {\r
1669     while (allocatorList) {\r
1670         if (strncmp(allocatorList->resourceName, resourceName, RM_NAME_MAX_CHARS) == 0) {\r
1671             break;             \r
1672         }\r
1673         allocatorList = allocatorList->nextAllocator;\r
1674     }\r
1675 \r
1676     return (allocatorList);\r
1677 }\r
1678 \r
1679 /* FUNCTION PURPOSE: Processes a transaction\r
1680  ***********************************************************************\r
1681  * DESCRIPTION: Processes transactions created from services\r
1682  *              received via the service handle or the transport.\r
1683  *              Transactions will be routed within the RM system\r
1684  *              based on the RM instance type and the type of\r
1685  *              the transaction.\r
1686  */\r
1687 void rmTransactionProcessor (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
1688 {\r
1689     void                *validInstNode;\r
1690     Rm_PolicyCheckCfg    privCheckCfg;\r
1691     Rm_NameServerObjCfg  nameServerObjCfg;      \r
1692     uint32_t             allocType = 0;    \r
1693 \r
1694     /* Handle static transactions originating on this instance.  Any other static transactions will be\r
1695      * stored in transaction queue until all transports are up. */\r
1696     if (((rmInst->instType == Rm_instType_CLIENT) || (rmInst->instType == Rm_instType_CLIENT_DELEGATE)) &&\r
1697         (!rmInst->registeredWithDelegateOrServer) && \r
1698         (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS) == 0)) {\r
1699         if (rmInst->staticInfo.staticPolicy) {\r
1700             if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||\r
1701                 (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE)) {\r
1702                 /* Check request against startup policy */\r
1703                 memset((void *)&privCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));\r
1704 \r
1705                 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {\r
1706                     privCheckCfg.type = Rm_policyCheck_INIT;\r
1707                 }\r
1708                 else {\r
1709                     privCheckCfg.type = Rm_policyCheck_USE;\r
1710                 }\r
1711                 privCheckCfg.policyDtb = rmInst->staticInfo.staticPolicy;\r
1712                 privCheckCfg.validInstNode = rmPolicyGetValidInstNode(rmInst->staticInfo.staticValidInstTree, \r
1713                                                                       rmInst->instName);\r
1714                 privCheckCfg.resourceOffset = rmPolicyGetResourceOffset(rmInst->staticInfo.staticPolicy,\r
1715                                                                         transaction->resourceInfo.name);\r
1716                 privCheckCfg.resourceBase = transaction->resourceInfo.base;\r
1717                 privCheckCfg.resourceLength = transaction->resourceInfo.length;\r
1718 \r
1719                 if (rmPolicyCheckPrivilege(&privCheckCfg, &transaction->state)) {\r
1720                     transaction->state = RM_SERVICE_APPROVED_STATIC;\r
1721                 }\r
1722                 else if (transaction->state == RM_SERVICE_PROCESSING) {\r
1723                     /* Privilege check returned false without error */\r
1724                     transaction->state = RM_SERVICE_DENIED_BY_STATIC_POLICY;\r
1725                 }\r
1726             }\r
1727             else {\r
1728                 transaction->state = RM_SERVICE_DENIED_INVALID_STATIC_REQUEST;\r
1729             }\r
1730         }\r
1731         else {\r
1732             transaction->state = RM_ERROR_REQ_FAILED_NO_STATIC_POLICY;\r
1733         }        \r
1734     }\r
1735     else {\r
1736         /* Handle auto-forwarded transactions.  These transactions include:\r
1737          * - All request transactions received on Clients are forwarded to the Client Delegate\r
1738          * - NameServer requests received on the Client Delegate are forwarded to the Server */\r
1739         if ((rmInst->instType == Rm_instType_CLIENT) ||\r
1740             ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
1741              ((transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) ||\r
1742               (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) ||\r
1743               (transaction->type == Rm_service_RESOURCE_UNMAP_NAME)))) {\r
1744               \r
1745             if ((transaction->state != RM_SERVICE_PROCESSING) &&\r
1746                 (transaction->state != RM_SERVICE_APPROVED_STATIC)) {\r
1747                 if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {\r
1748                     /* Transaction did not originate on this instance */\r
1749                     transactionResponder(rmInst, transaction);\r
1750                 }\r
1751                 else {\r
1752                     /* Transaction originated on this instance */\r
1753                     serviceResponder(rmInst, transaction);\r
1754                 }\r
1755             }\r
1756             else {\r
1757                 /* Forward request if transport is up.  Otherwise, just queue. */\r
1758                 if (rmInst->registeredWithDelegateOrServer) {\r
1759                     transactionForwarder(rmInst, transaction);   \r
1760                 } \r
1761             }\r
1762         }\r
1763         else {\r
1764             /* Validate service's originating instance name */\r
1765             if (rmInst->instType == Rm_instType_SERVER) {\r
1766                 validInstNode = rmPolicyGetValidInstNode(rmInst->validInstances, transaction->serviceSrcInstName);\r
1767                 if (validInstNode == NULL) {\r
1768                     transaction->state = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;\r
1769 \r
1770                     /* Send result via responder if transaction did not originate from this instance */\r
1771                     if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {\r
1772                         transactionResponder(rmInst, transaction);\r
1773                     }\r
1774                 }\r
1775             }\r
1776 \r
1777             switch (transaction->type) {\r
1778                 case Rm_service_RESOURCE_ALLOCATE_INIT:\r
1779                 case Rm_service_RESOURCE_ALLOCATE_USE:\r
1780                 case Rm_service_RESOURCE_FREE:               \r
1781                     if ((transaction->state != RM_SERVICE_PROCESSING) &&\r
1782                         (transaction->state != RM_SERVICE_APPROVED_STATIC)) {\r
1783                         /* Transaction complete */\r
1784                         if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {\r
1785                             /* Transaction result not destined for this instance */\r
1786                             transactionResponder(rmInst, transaction);\r
1787                         }\r
1788                         else {\r
1789                             /* Transaction result destined for this instance */\r
1790                             serviceResponder(rmInst, transaction);      \r
1791                         }\r
1792                     }\r
1793                     else {\r
1794                         /* Complete allocation/free request */\r
1795                         if (transaction->type == Rm_service_RESOURCE_FREE) {\r
1796                             freeHandler(rmInst, transaction, validInstNode);\r
1797                         }\r
1798                         else {\r
1799                             switch (transaction->type) {\r
1800                                 case Rm_service_RESOURCE_ALLOCATE_INIT:\r
1801                                     RM_policy_SET_PERM(allocType, RM_POLICY_PERM_INIT_SHIFT, 1);\r
1802                                     break;\r
1803                                 case Rm_service_RESOURCE_ALLOCATE_USE:\r
1804                                     RM_policy_SET_PERM(allocType, RM_POLICY_PERM_USE_SHIFT, 1);    \r
1805                                     break;\r
1806                             }\r
1807                             allocationHandler(rmInst, transaction, validInstNode, allocType);\r
1808                         }\r
1809                     }\r
1810                     break;\r
1811                 case Rm_service_RESOURCE_MAP_TO_NAME:\r
1812                 case Rm_service_RESOURCE_GET_BY_NAME:\r
1813                 case Rm_service_RESOURCE_UNMAP_NAME:                \r
1814                     /* NameServer resides on server */\r
1815                     memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));\r
1816                     if (rmInst->nameServer) {\r
1817                         nameServerObjCfg.nameServerTree = rmInst->nameServer;\r
1818                         nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;\r
1819                         if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {\r
1820                             nameServerObjCfg.nodeCfg.resourceName = transaction->resourceInfo.name;\r
1821                             nameServerObjCfg.nodeCfg.resourceBase= transaction->resourceInfo.base;\r
1822                             nameServerObjCfg.nodeCfg.resourceLength = transaction->resourceInfo.length;\r
1823                             transaction->state = rmNameServerAddObject(&nameServerObjCfg);\r
1824                         }\r
1825                         else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {\r
1826                             if ((transaction->state = rmNameServerFindObject(&nameServerObjCfg)) ==\r
1827                                 RM_SERVICE_PROCESSING) {\r
1828                                 strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);\r
1829                                 transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;\r
1830                                 transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;\r
1831                                 transaction->state = RM_SERVICE_APPROVED;\r
1832                             } \r
1833                         }\r
1834                         else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {\r
1835                             transaction->state = rmNameServerDeleteObject(&nameServerObjCfg);\r
1836                         }\r
1837                     }\r
1838                     else {\r
1839                         transaction->state = RM_ERROR_NAMESERVER_DOES_NOT_EXIST;\r
1840                     }\r
1841 \r
1842                     /* Send result via responder if transaction did not originate from this instance */\r
1843                     if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {\r
1844                         transactionResponder(rmInst, transaction);\r
1845                     }\r
1846                     break;\r
1847             }\r
1848         }\r
1849     }\r
1850 \r
1851     /* Forward any queued requests that weren't forwarded yet */\r
1852     if (rmInst->registeredWithDelegateOrServer) {\r
1853         transaction = rmInst->transactionQueue;\r
1854         while(transaction) {\r
1855             if (((transaction->state == RM_SERVICE_PROCESSING) ||\r
1856                  (transaction->state == RM_SERVICE_APPROVED_STATIC)) &&\r
1857                 !transaction->hasBeenForwarded) {\r
1858                 transactionForwarder(rmInst, transaction);\r
1859             }\r
1860             transaction = transaction->nextTransaction;\r
1861         }\r
1862     }\r
1863 }\r
1864      \r
1865 /**********************************************************************\r
1866  ********************** Application visible APIs **********************\r
1867  **********************************************************************/\r
1868 \r
1869 /* FUNCTION PURPOSE: Display status of managed resources\r
1870  ***********************************************************************\r
1871  * DESCRIPTION: Prints the status (allocate/free status, as well as\r
1872  *              owners) for all resources managed by the RM \r
1873  *              instance network.  Also, prints the NameServer name\r
1874  *              entries.  This function is only available on server\r
1875  *              instances.\r
1876  */\r
1877 void Rm_printResourceStatus(Rm_Handle rmServerHandle)\r
1878 {\r
1879     Rm_Inst         *rmInst = (Rm_Inst *)rmServerHandle;\r
1880     Rm_Allocator    *allocator = rmInst->allocators;\r
1881     Rm_Owner        *owners;\r
1882     Rm_ResourceTree *treeRoot;\r
1883     Rm_ResourceNode *treeNode;\r
1884 \r
1885     if (rmInst->instType == Rm_instType_SERVER) {\r
1886         while (allocator != NULL) {\r
1887             Rm_osalLog("Resource: %s\n", allocator->resourceName);\r
1888 \r
1889             treeRoot = allocator->allocatorRootEntry;\r
1890 \r
1891             RB_FOREACH(treeNode, _Rm_AllocatorResourceTree, treeRoot) {               \r
1892                 Rm_osalLog("          %10d - %10d ", treeNode->base, \r
1893                                                      treeNode->base + treeNode->length -1);\r
1894                 \r
1895                 if (treeNode->allocationCount == 0) {\r
1896                     Rm_osalLog("NOT ALLOCATED\n");\r
1897                 }\r
1898                 else {\r
1899                     owners = treeNode->ownerList;\r
1900                     Rm_osalLog("allocated to");\r
1901                     while (owners) {\r
1902                         Rm_osalLog(" %s", owners->instNameNode->name);\r
1903                         owners = owners->nextOwner;\r
1904                     }\r
1905                     Rm_osalLog("\n");\r
1906                 }\r
1907             }        \r
1908             allocator = allocator->nextAllocator;\r
1909         }\r
1910         rmNameServerPrintObjects(rmInst->nameServer);\r
1911     }\r
1912 }\r
1913 \r
1914 /* FUNCTION PURPOSE: Display status of a RM instance\r
1915  ***********************************************************************\r
1916  * DESCRIPTION: Prints the current status of various RM instance\r
1917  *              properties such as the state of all transactions\r
1918  *              in the transaction queue and registered transports\r
1919  */\r
1920 void Rm_printInstanceStatus(Rm_Handle rmHandle)\r
1921 {\r
1922     Rm_Inst        *rmInst = (Rm_Inst *)rmHandle;\r
1923     Rm_Transport   *transportList = (Rm_Transport *)rmInst->transports;\r
1924     Rm_Transaction *transactionQ = rmInst->transactionQueue;\r
1925 \r
1926     Rm_osalLog("Instance name: %s\n", rmInst->instName);\r
1927     if (rmInst->instType == Rm_instType_SERVER) {\r
1928         Rm_osalLog("Type: Server\n");\r
1929     }\r
1930     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {\r
1931         Rm_osalLog("Type: Client Delegate\n");\r
1932     }\r
1933     else {\r
1934         Rm_osalLog("Type: Client\n");\r
1935     }\r
1936 \r
1937     if (transportList) {\r
1938         Rm_osalLog("\nRegistered Transports:\n");\r
1939         while (transportList) {\r
1940             Rm_osalLog("    Remote instName:    %s\n", transportList->remoteInstName);\r
1941             if (transportList->remoteInstType == Rm_instType_SERVER) {\r
1942                 Rm_osalLog("    Remote instType:    Server\n");\r
1943             }\r
1944             else if (transportList->remoteInstType == Rm_instType_CLIENT_DELEGATE) {\r
1945                 Rm_osalLog("    Remote instType:    Client Delegate\n");\r
1946             }\r
1947             else {\r
1948                 Rm_osalLog("    Remote instType:    Client\n");\r
1949             }\r
1950             Rm_osalLog("    appTransportHandle: 0x%08x\n", transportList->appTransportHandle);\r
1951             Rm_osalLog("\n");\r
1952             transportList = transportList->nextTransport;\r
1953         }\r
1954     }\r
1955 \r
1956     if (transactionQ) {\r
1957         Rm_osalLog("\nQueued Service Transactions:\n");\r
1958         while (transactionQ) {\r
1959             Rm_osalLog("    Service type:       %d\n", transactionQ->type);\r
1960             Rm_osalLog("    Service ID:         %d\n", transactionQ->localId);\r
1961             Rm_osalLog("    Service srcInstName %s\n", transactionQ->serviceSrcInstName);\r
1962             Rm_osalLog("    Service state:      %d\n", transactionQ->state);\r
1963             Rm_osalLog("    Resource name:      %s\n", transactionQ->resourceInfo.name);\r
1964             Rm_osalLog("    Resource base:      %d\n", transactionQ->resourceInfo.base);\r
1965             Rm_osalLog("    Resource length:    %d\n", transactionQ->resourceInfo.length);\r
1966             Rm_osalLog("    Resource alignment: %d\n", transactionQ->resourceInfo.alignment);\r
1967             Rm_osalLog("    Resource NS name:   %s\n", transactionQ->resourceInfo.nameServerName);\r
1968             Rm_osalLog("\n");\r
1969             transactionQ = transactionQ->nextTransaction;\r
1970         }    \r
1971     }\r
1972 }\r
1973 \r
1974 /* FUNCTION PURPOSE: RM instance creation and initialization\r
1975  ***********************************************************************\r
1976  * DESCRIPTION: Returns a new RM instance created and initialized\r
1977  *              using the parameters provided via the initCfg\r
1978  *              structure.\r
1979  */\r
1980 Rm_Handle Rm_init(Rm_InitCfg *initCfg, int32_t *result)\r
1981 {\r
1982     Rm_Inst *rmInst;\r
1983     void    *globalResourceDtb = NULL;\r
1984     void    *linuxResourceDtb = NULL;\r
1985     bool     addLinux = false;\r
1986 \r
1987     *result = RM_OK;\r
1988     \r
1989     if ((initCfg->instName == NULL) ||\r
1990         ((strlen(initCfg->instName) + 1) > RM_NAME_MAX_CHARS)) {\r
1991         *result = RM_ERROR_INVALID_INST_NAME;\r
1992         return (NULL);\r
1993     }\r
1994 \r
1995     if (initCfg->instType >= Rm_instType_LAST) {\r
1996         *result = RM_ERROR_INVALID_INST_TYPE;\r
1997     }\r
1998 \r
1999     /* Create and initialize instance */\r
2000     rmInst = Rm_osalMalloc (sizeof(Rm_Inst));\r
2001     memset ((void *) rmInst, 0, sizeof(Rm_Inst));\r
2002     rmInst->isLocked = false;\r
2003     rmInst->registeredWithDelegateOrServer = false;\r
2004     rmInst->transactionSeqNum = transactionInitSequenceNum();\r
2005 \r
2006     rmInst->instType = initCfg->instType;    \r
2007     strncpy (rmInst->instName, initCfg->instName, RM_NAME_MAX_CHARS);\r
2008 \r
2009     if (rmInst->instType == Rm_instType_SERVER) {\r
2010         if (!initCfg->instCfg.serverCfg.globalResourceList ||\r
2011             !initCfg->instCfg.serverCfg.globalPolicy) {\r
2012             *result = RM_ERROR_INVALID_SERVER_CONFIGURATION;\r
2013             Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));\r
2014             return(NULL);\r
2015         }\r
2016 \r
2017         rmInst->policy = initCfg->instCfg.serverCfg.globalPolicy;\r
2018         fdt_open_into(rmInst->policy, rmInst->policy, fdt_totalsize(rmInst->policy)); \r
2019 \r
2020         if (initCfg->instCfg.serverCfg.linuxDtb) {\r
2021             linuxResourceDtb = initCfg->instCfg.serverCfg.linuxDtb;\r
2022             fdt_open_into(linuxResourceDtb, linuxResourceDtb, fdt_totalsize(linuxResourceDtb));\r
2023             addLinux = true;\r
2024         }\r
2025 \r
2026         /* Create valid instance list from policy.  Must be done prior to parsing\r
2027          * GRL so that Linux resources can be reserved correctly */\r
2028         rmInst->validInstances = rmPolicyCreateValidInstTree(rmInst->policy, addLinux, result);\r
2029         /* Validate policy assignment strings */\r
2030         *result = rmPolicyValidatePolicy(rmInst->policy, rmInst->validInstances);  \r
2031 \r
2032         rmInst->nameServer = rmNameServerInit();\r
2033 \r
2034         globalResourceDtb = initCfg->instCfg.serverCfg.globalResourceList;\r
2035         fdt_open_into(globalResourceDtb, globalResourceDtb, fdt_totalsize(globalResourceDtb));\r
2036 \r
2037         if ((*result = initializeAllocators(rmInst, globalResourceDtb, linuxResourceDtb)) == RM_OK) {  \r
2038             *result = rmPolicyValidatePolicyResourceNames(rmInst->policy, (void *)rmInst->allocators);\r
2039         }\r
2040         if (*result < RM_OK) {\r
2041             Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));\r
2042             return(NULL);\r
2043         }\r
2044     }\r
2045 \r
2046     if ((rmInst->instType == Rm_instType_CLIENT) && \r
2047         (initCfg->instCfg.clientCfg.staticPolicy)) {\r
2048         rmInst->staticInfo.staticPolicy = initCfg->instCfg.clientCfg.staticPolicy; \r
2049     }\r
2050     else if ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
2051              (initCfg->instCfg.cdCfg.staticPolicy)) { \r
2052         rmInst->staticInfo.staticPolicy = initCfg->instCfg.cdCfg.staticPolicy; \r
2053     }\r
2054     if (rmInst->staticInfo.staticPolicy) {\r
2055         fdt_open_into(rmInst->staticInfo.staticPolicy, rmInst->staticInfo.staticPolicy, \r
2056                       fdt_totalsize(rmInst->staticInfo.staticPolicy));       \r
2057         rmInst->staticInfo.staticValidInstTree = rmPolicyCreateValidInstTree(rmInst->staticInfo.staticPolicy, \r
2058                                                                              addLinux, result);        \r
2059         if (*result == RM_OK) {\r
2060             /* Validate policy assignment strings */\r
2061             *result = rmPolicyValidatePolicy(rmInst->staticInfo.staticPolicy, rmInst->staticInfo.staticValidInstTree);\r
2062         }\r
2063         if (*result != RM_OK) {\r
2064             if (rmInst->staticInfo.staticValidInstTree) {\r
2065                 rmPolicyFreeValidInstTree(rmInst->staticInfo.staticValidInstTree);\r
2066             }\r
2067             Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));\r
2068             rmInst = NULL;\r
2069         }\r
2070     }\r
2071     return ((Rm_Handle) rmInst);\r
2072 }\r
2073 \r
2074 /* FUNCTION PURPOSE: Returns RM version information\r
2075  ***********************************************************************\r
2076  */\r
2077 uint32_t Rm_getVersion (void)\r
2078 {\r
2079     return RM_VERSION_ID;\r
2080 }\r
2081 \r
2082 /* FUNCTION PURPOSE: Returns RM version string\r
2083  ***********************************************************************\r
2084  */\r
2085 const char* Rm_getVersionStr (void)\r
2086 {\r
2087     return rmVersionStr;\r
2088 }\r
2089 \r