Added and tested static policy feature. Continued cleanup of API
[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  ********************** Internal Functions ****************************\r
78  **********************************************************************/\r
79 \r
80 Rm_Transaction *rmTransactionQueueAdd(Rm_Inst *rmInst)\r
81 {\r
82     Rm_Transaction *transactionQueue = rmInst->transactionQueue;\r
83     Rm_Transaction *newTransaction   = NULL;\r
84 \r
85     newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction));\r
86     if (newTransaction) {\r
87         memset((void *)newTransaction, 0, sizeof(Rm_Transaction));\r
88 \r
89         newTransaction->localId = rmTransactionGetSequenceNum(rmInst);\r
90         newTransaction->nextTransaction = NULL;  \r
91         if (transactionQueue) {\r
92             while (transactionQueue->nextTransaction) {\r
93                 transactionQueue = transactionQueue->nextTransaction;\r
94             }\r
95             transactionQueue->nextTransaction = newTransaction;\r
96         }\r
97         else {\r
98             rmInst->transactionQueue = newTransaction;\r
99         }\r
100     }\r
101     return (newTransaction);\r
102 }\r
103 \r
104 Rm_Transaction *rmTransactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)\r
105 {\r
106     Rm_Transaction *transaction = rmInst->transactionQueue;\r
107 \r
108     while (transaction) {\r
109         if (transaction->localId == transactionId) {\r
110             break;             \r
111         }\r
112         transaction = transaction->nextTransaction;\r
113     }\r
114 \r
115     return (transaction);\r
116 }\r
117 \r
118 int32_t rmTransactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)\r
119 {\r
120     Rm_Transaction *transaction     = rmInst->transactionQueue;\r
121     Rm_Transaction *prevTransaction = NULL;\r
122     int32_t         retVal          = RM_OK;\r
123 \r
124     while (transaction) {\r
125         if (transaction->localId == transactionId) {\r
126             break;             \r
127         }\r
128 \r
129         prevTransaction = transaction;\r
130         transaction = transaction->nextTransaction;\r
131     }\r
132 \r
133     if (transaction) {\r
134         if (prevTransaction == NULL) {\r
135             /* Transaction at start of queue. Map second transaction to start of queue \r
136              * as long as more than one transactions. */\r
137             rmInst->transactionQueue = transaction->nextTransaction;\r
138         }\r
139         else {\r
140             /* Transaction in middle or end of queue. */\r
141             prevTransaction->nextTransaction = transaction->nextTransaction;\r
142         }\r
143         Rm_osalFree((void *)transaction, sizeof(Rm_Transaction));\r
144     }\r
145     else {\r
146         retVal = RM_ERROR_SERVICE_TRANS_DOES_NOT_EXIST;\r
147     }    \r
148     return (retVal);\r
149 }\r
150 \r
151 uint32_t rmTransactionInitSequenceNum(void)\r
152 {\r
153     /* Sequence number can never have value of 0.  Avoids conflicts\r
154      * with non-response transactions that have remoteOriginatingId of 0 */\r
155     return (1);\r
156 }\r
157 \r
158 uint32_t rmTransactionGetSequenceNum(Rm_Inst *rmInst)\r
159 {\r
160     uint32_t sequenceNum = 0;\r
161 \r
162     if (rmInst->transactionSeqNum + 1 < rmInst->transactionSeqNum) {\r
163         /* Overflow */\r
164         sequenceNum = rmInst->transactionSeqNum;\r
165         rmInst->transactionSeqNum = rmTransactionInitSequenceNum();\r
166     }\r
167     else {\r
168         sequenceNum = rmInst->transactionSeqNum++;\r
169     }    \r
170     return (sequenceNum);\r
171 }\r
172 \r
173 Rm_Allocator *rmAllocatorAdd(Rm_Inst *rmInst, const char *resourceName)\r
174 {\r
175     Rm_Allocator *allocators   = rmInst->allocators;\r
176     Rm_Allocator *newAllocator = NULL;\r
177 \r
178     newAllocator = Rm_osalMalloc(sizeof(Rm_Allocator));\r
179 \r
180     if (newAllocator) {\r
181         memset((void *)newAllocator, 0, sizeof(Rm_Allocator));\r
182         strncpy(newAllocator->resourceName, resourceName, RM_NAME_MAX_CHARS);\r
183         newAllocator->allocatorRootEntry = NULL;\r
184         newAllocator->nextAllocator = NULL;  \r
185 \r
186         /* Add allocator to end of list */\r
187         if (allocators) {\r
188             while (allocators->nextAllocator) {\r
189                 allocators = allocators->nextAllocator;\r
190             }\r
191             allocators->nextAllocator = newAllocator;\r
192         }\r
193         else {\r
194             rmInst->allocators = newAllocator;\r
195         }\r
196     }\r
197     return (newAllocator);\r
198 }\r
199 \r
200 Rm_Allocator *rmAllocatorFind(Rm_Allocator *allocatorList, char *resourceName)\r
201 {\r
202     while (allocatorList) {\r
203         if (strncmp(allocatorList->resourceName, resourceName, RM_NAME_MAX_CHARS) == 0) {\r
204             break;             \r
205         }\r
206         allocatorList = allocatorList->nextAllocator;\r
207     }\r
208 \r
209     return (allocatorList);\r
210 }\r
211 \r
212 int32_t rmAllocatorDelete(Rm_Inst *rmInst, char *resourceName)\r
213 {\r
214     Rm_Allocator *allocator = rmInst->allocators;\r
215     Rm_Allocator *prevAllocator = NULL;\r
216     int32_t       retVal = RM_OK;\r
217 \r
218     while (allocator) {\r
219         if (strncmp(allocator->resourceName, resourceName, RM_NAME_MAX_CHARS) == 0) {\r
220             break;             \r
221         }\r
222         prevAllocator = allocator;\r
223         allocator = allocator->nextAllocator;\r
224     }\r
225 \r
226     if (allocator) {\r
227         if (prevAllocator == NULL) {\r
228             rmInst->allocators = allocator->nextAllocator;\r
229         }\r
230         else {\r
231             prevAllocator->nextAllocator = allocator->nextAllocator;\r
232         }\r
233         Rm_osalFree((void *)allocator, sizeof(Rm_Allocator));\r
234     }\r
235     else {\r
236         retVal = RM_ERROR_RES_ALLOCATOR_DOES_NOT_EXIST;\r
237     }\r
238     return (retVal);\r
239 }\r
240 \r
241 void rmAddOwner(Rm_ResourceNode *node, void *serviceInstNode)\r
242 {\r
243     Rm_Owner *ownerList = node->ownerList;\r
244     Rm_Owner *newOwner = NULL;\r
245 \r
246     newOwner = Rm_osalMalloc(sizeof(Rm_Owner));\r
247 \r
248     if (newOwner) {\r
249         newOwner->instNameNode = serviceInstNode;\r
250         newOwner->nextOwner = NULL;  \r
251 \r
252         /* Add owner entry to end of list */\r
253         if (ownerList) {\r
254             while (ownerList->nextOwner) {\r
255                 ownerList = ownerList->nextOwner;\r
256             }\r
257             ownerList->nextOwner = newOwner;\r
258         }\r
259         else {\r
260             node->ownerList = newOwner;\r
261         }\r
262 \r
263         node->allocationCount++;\r
264         newOwner->instNameNode->allocRefCount++;\r
265     }\r
266 }\r
267 \r
268 bool rmIsOwnedBy(Rm_ResourceNode *node, void *serviceInstNode)\r
269 {\r
270     Rm_Owner *owner = node->ownerList;\r
271 \r
272     while (owner) {\r
273         if (owner->instNameNode == serviceInstNode) {\r
274             return(true);           \r
275         }\r
276         owner = owner->nextOwner;\r
277     }\r
278     return(false);\r
279 }\r
280 \r
281 bool rmCompareResourceNodeOwners(Rm_ResourceNode *node1, Rm_ResourceNode *node2)\r
282 {\r
283     Rm_Owner *node1Owners = node1->ownerList;\r
284     Rm_Owner *node2Owners = node2->ownerList;\r
285     bool      matchedInst;\r
286 \r
287     if (node1->allocationCount == node2->allocationCount) {\r
288         while (node1Owners) {\r
289             matchedInst = false;\r
290             while (node2Owners) {\r
291                 if (node1Owners->instNameNode == node2Owners->instNameNode) {\r
292                     matchedInst = true;\r
293                     break;\r
294                 }\r
295                 node2Owners = node2Owners->nextOwner;\r
296             }\r
297 \r
298             if (matchedInst) {\r
299                 node2Owners = node2->ownerList;\r
300                 node1Owners = node1Owners->nextOwner;\r
301             }\r
302             else {\r
303                 return(false);\r
304             }                \r
305         }\r
306     }\r
307     else {\r
308         return(false);\r
309     }  \r
310     \r
311     return(true);\r
312 }\r
313 \r
314 void rmDeleteOwner(Rm_ResourceNode *node, void *serviceInstNode)\r
315 {\r
316     Rm_Owner *owner = node->ownerList;\r
317     Rm_Owner *prevOwner = NULL;\r
318 \r
319     while (owner) {\r
320         if (owner->instNameNode == serviceInstNode) {\r
321             break;             \r
322         }\r
323         prevOwner = owner;\r
324         owner = owner->nextOwner;\r
325     }\r
326 \r
327     if (prevOwner == NULL) {\r
328         node->ownerList = owner->nextOwner;\r
329     }\r
330     else {\r
331         prevOwner->nextOwner = owner->nextOwner;\r
332     }\r
333     \r
334     node->allocationCount--;\r
335     owner->instNameNode->allocRefCount--;\r
336     Rm_osalFree((void *)owner, sizeof(Rm_Owner));\r
337 }\r
338 \r
339 void rmCopyOwners(Rm_ResourceNode *dstNode, Rm_ResourceNode *srcNode)\r
340 {\r
341     Rm_Owner *srcOwnerList = srcNode->ownerList;\r
342     Rm_Owner *dstNewOwner;\r
343     Rm_Owner *dstPrevOwner;\r
344 \r
345     dstNode->allocationCount = srcNode->allocationCount;\r
346 \r
347     while (srcOwnerList) {\r
348         dstNewOwner = Rm_osalMalloc(sizeof(Rm_Owner));\r
349         dstNewOwner->instNameNode = srcOwnerList->instNameNode;\r
350         dstNewOwner->nextOwner = NULL;\r
351 \r
352         if (dstNode->ownerList == NULL) {\r
353             dstNode->ownerList = dstNewOwner;\r
354         }\r
355         else {\r
356             dstPrevOwner->nextOwner = dstNewOwner;\r
357         }\r
358         dstPrevOwner = dstNewOwner;\r
359         srcOwnerList = srcOwnerList->nextOwner;\r
360     }\r
361 }\r
362 \r
363 void rmClearOwners(Rm_ResourceNode *node)\r
364 {\r
365     Rm_Owner *owner = node->ownerList;\r
366     Rm_Owner *nextOwner;\r
367 \r
368     while (owner) {\r
369         nextOwner = owner->nextOwner;\r
370         node->allocationCount--;\r
371         Rm_osalFree((void *)owner, sizeof(Rm_Owner));\r
372         owner = nextOwner;\r
373     }\r
374 }\r
375 \r
376 int32_t rmCreateTreeAllocator(Rm_Inst *rmInst, const char *resourceName, Rm_ResourceRange *range)\r
377 {\r
378     Rm_Allocator    *allocator = NULL;\r
379     Rm_ResourceTree *treeRootEntry = NULL;\r
380     Rm_ResourceNode *treeNode = NULL;\r
381     Rm_ResourceNode *collidingNode = NULL;\r
382 \r
383     allocator = rmAllocatorAdd(rmInst, resourceName);\r
384     treeRootEntry = Rm_osalMalloc(sizeof(Rm_ResourceTree));\r
385     RB_INIT(treeRootEntry);\r
386 \r
387     while (range != NULL) {\r
388         treeNode = rmResourceNodeNew(range->base, range->length);\r
389         collidingNode = RB_INSERT(_Rm_AllocatorResourceTree, treeRootEntry, treeNode);\r
390 \r
391         if (collidingNode) {\r
392             Rm_ResourceNode *nextNode = NULL;\r
393             \r
394             /* Node that was inserted collides with existing node.  Destroy tree and return error */\r
395             for (treeNode = RB_MIN(_Rm_AllocatorResourceTree, treeRootEntry); treeNode != NULL; treeNode = nextNode) {\r
396                         nextNode = RB_NEXT(_Rm_AllocatorResourceTree, treeRootEntry, treeNode);\r
397                         RB_REMOVE(_Rm_AllocatorResourceTree, treeRootEntry, nextNode);\r
398                 rmResourceNodeFree(treeNode);\r
399                 }\r
400             Rm_osalFree((void *)treeRootEntry, sizeof(Rm_ResourceTree));\r
401             rmAllocatorDelete(rmInst, allocator->resourceName);\r
402             return (RM_ERROR_GRL_RES_SPECIFIED_MORE_THAN_ONCE);\r
403         }\r
404         range = range->nextRange;\r
405     }\r
406     \r
407     allocator->allocatorRootEntry = treeRootEntry;\r
408     return(RM_OK);\r
409 }\r
410 \r
411 /* Called when an allocate request is made but the base is unspecified.  RM must preallocate\r
412  * resources which then must be checked against the RM policy for the instance.  If the\r
413  * policy does not agree another resource(s) must be preallocated and tested against the \r
414  * policy.  Policy will provide initialize the preallocate with the base that it allows\r
415  * for the rm instance for the specified resource. */\r
416 int32_t rmTreePreAllocate(Rm_Inst *rmInst, Rm_Allocator *allocator, int32_t resourcePolicy,\r
417                           Rm_AllocatorOpInfo *opInfo)\r
418 {\r
419     Rm_ResourceNode    findNode;\r
420     Rm_ResourceNode   *matchingNode = NULL;\r
421     uint32_t           matchingEnd;\r
422     uint32_t           rangeIndex;\r
423     bool               resourceFound = false;\r
424     Rm_PolicyCheckType policyCheckType;\r
425     Rm_PolicyCheckCfg  policyCheckCfg;\r
426     bool               nodePassesPolicy;\r
427     int32_t            retVal = RM_SERVICE_PROCESSING;    \r
428 \r
429     opInfo->resourceInfo->base = rmPolicyGetResourceBase(rmInst->policy, opInfo->serviceSrcInstNode, \r
430                                                           resourcePolicy, opInfo->allocType, \r
431                                                           &retVal);\r
432     if (retVal != RM_SERVICE_PROCESSING) {\r
433         return (retVal);\r
434     }\r
435 \r
436     if (opInfo->resourceInfo->alignment == RM_RESOURCE_ALIGNMENT_UNSPECIFIED) {  \r
437         /* Get alignment from policy */\r
438         opInfo->resourceInfo->alignment = rmPolicyGetResourceAlignment(rmInst->policy, resourcePolicy);\r
439     }\r
440     \r
441     if (opInfo->resourceInfo->alignment == 0) {\r
442         opInfo->resourceInfo->alignment = 1;\r
443     }    \r
444 \r
445     memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));\r
446     findNode.base = opInfo->resourceInfo->base;\r
447     findNode.length = opInfo->resourceInfo->length;\r
448 \r
449     /* Configure policy checking structure */\r
450     memset((void *)&policyCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));\r
451     if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_INIT_SHIFT)) {\r
452         policyCheckType = Rm_policyCheck_INIT;\r
453     }\r
454     else if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_USE_SHIFT)) {\r
455         policyCheckType = Rm_policyCheck_USE;\r
456     }\r
457     policyCheckCfg.policyDtb = rmInst->policy;\r
458     policyCheckCfg.resourceOffset = resourcePolicy;\r
459     \r
460     do {\r
461         matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);\r
462         \r
463         if (matchingNode) {\r
464             nodePassesPolicy = false;\r
465             policyCheckCfg.type = policyCheckType;\r
466             policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;\r
467             policyCheckCfg.resourceBase = findNode.base;\r
468             policyCheckCfg.resourceLength = findNode.length;\r
469             nodePassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);    \r
470             \r
471             if (nodePassesPolicy && (matchingNode->allocationCount > 0)) {\r
472                 /* Check exclusive privileges of instance requesting resource.  Requesting\r
473                  * instance with exclusive privileges can't reserve resource if already owned*/\r
474                 policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
475                 policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;\r
476                 nodePassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);\r
477             }\r
478             \r
479             if (nodePassesPolicy && (matchingNode->allocationCount == 1)) {\r
480                 /* Check exclusive privileges of instance that currently owns resource */\r
481                 policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
482                 policyCheckCfg.validInstNode = matchingNode->ownerList->instNameNode;\r
483                 nodePassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);\r
484             }\r
485 \r
486             if (retVal != RM_SERVICE_PROCESSING) {\r
487                 break;\r
488             }\r
489 \r
490             if (nodePassesPolicy) {\r
491                 matchingEnd = matchingNode->base + matchingNode->length - 1;\r
492                 /* Initialize indexer to be first resource value that alignment */\r
493                 rangeIndex = findNode.base;\r
494                 if (rangeIndex % opInfo->resourceInfo->alignment) {\r
495                     rangeIndex += (opInfo->resourceInfo->alignment -\r
496                                   (rangeIndex % opInfo->resourceInfo->alignment));\r
497                 }\r
498                 \r
499                 if ((rangeIndex + opInfo->resourceInfo->length - 1) <= matchingEnd) {\r
500                     /* Block of unallocated resources within matchingNode that satisfies\r
501                      * allocate requirements */\r
502                     opInfo->resourceInfo->base = rangeIndex;\r
503                     resourceFound = true;\r
504                 }     \r
505             }\r
506             \r
507             if (!resourceFound) {\r
508                 /* Check next resource node for available resources */\r
509                 findNode.base = matchingNode->base + matchingNode->length;\r
510             }\r
511         }\r
512         else {\r
513             retVal = RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET;\r
514         }\r
515     } while ((!resourceFound) && \r
516              (retVal != RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET));\r
517 \r
518     return(retVal); \r
519 }\r
520 \r
521 int32_t rmTreeAllocate(Rm_Inst *rmInst, Rm_Allocator *allocator, int32_t resourcePolicy,\r
522                        Rm_AllocatorOpInfo *opInfo)\r
523 {\r
524     Rm_ResourceNode     findNode;\r
525     Rm_ResourceNode    *matchingNode = NULL;\r
526     Rm_ResourceNode    *leftNode = NULL;\r
527     Rm_ResourceNode    *rightNode = NULL;\r
528     Rm_PolicyCheckType  policyCheckType;    \r
529     Rm_PolicyCheckCfg   policyCheckCfg;\r
530     bool                allocPassesPolicy;\r
531     bool                combineLeft = false;\r
532     bool                combineRight = false;    \r
533     uint32_t            findEnd;\r
534     uint32_t            matchingEnd;  \r
535     int32_t             retVal = RM_SERVICE_PROCESSING;\r
536 \r
537     memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));\r
538     findNode.base = opInfo->resourceInfo->base;\r
539     findNode.length = opInfo->resourceInfo->length;\r
540     matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);\r
541 \r
542     /* Prepare privilege checks */\r
543     memset((void *)&policyCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));\r
544     if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_INIT_SHIFT)) {\r
545         policyCheckType = Rm_policyCheck_INIT;\r
546     }\r
547     else if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_USE_SHIFT)) {\r
548         policyCheckType = Rm_policyCheck_USE;\r
549     }\r
550 \r
551     if (matchingNode) {\r
552         findEnd = findNode.base + findNode.length - 1;\r
553         matchingEnd = matchingNode->base + matchingNode->length - 1;\r
554         \r
555         if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {\r
556             if (opInfo->serviceSrcInstNode == rmPolicyGetLinuxInstNode(rmInst->validInstances)) {\r
557                 /* Bypass policy checks since Linux Kernel has full privileges */\r
558                 allocPassesPolicy = true;\r
559             }\r
560             else {\r
561                 policyCheckCfg.policyDtb = rmInst->policy;\r
562                 policyCheckCfg.resourceOffset = resourcePolicy;    \r
563                 policyCheckCfg.type = policyCheckType;\r
564                 policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;\r
565                 policyCheckCfg.resourceBase = findNode.base;\r
566                 policyCheckCfg.resourceLength = findNode.length;\r
567                 allocPassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);\r
568                 if (!allocPassesPolicy) {\r
569                     if (policyCheckType == Rm_policyCheck_INIT) {\r
570                         retVal = RM_SERVICE_DENIED_INIT_PERM_NOT_GIVEN;\r
571                     }\r
572                     else {\r
573                         retVal = RM_SERVICE_DENIED_USE_PERM_NOT_GIVEN;\r
574                     }\r
575                 }\r
576                 \r
577                 if (allocPassesPolicy && (matchingNode->allocationCount > 0)) {\r
578                     /* Check exclusive privileges of instance requesting resource.  Requesting\r
579                      * instance with exclusive privileges can't reserve resource if already owned*/\r
580                     policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
581                     policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;\r
582                     allocPassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);\r
583                     if (!allocPassesPolicy) {\r
584                         retVal = RM_SERVICE_DENIED_EXCLUSIVE_RES_ALLOCD;\r
585                     }\r
586                 }\r
587                 if (allocPassesPolicy && (matchingNode->allocationCount == 1)) {\r
588                     /* Check exclusive privileges of instance that currently owns resource */\r
589                     policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
590                     policyCheckCfg.validInstNode = matchingNode->ownerList->instNameNode;\r
591                     allocPassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);\r
592                     if (!allocPassesPolicy) {\r
593                         retVal = RM_SERVICE_DENIED_ALLOCD_TO_EXCLUSIVE_INST;\r
594                     }                \r
595                 }  \r
596             }\r
597             \r
598             if (allocPassesPolicy) {   \r
599                 if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd)) {\r
600                     /* findNode range matches matchingNode range\r
601                      *\r
602                      *   |<--left node-->||<--matched  node-->||<--right node-->| => existing node\r
603                      *                    |<--alloc request-->|  => requested resources\r
604                      */                     \r
605                     leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
606                     rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
607                     RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
608                     rmAddOwner(matchingNode, opInfo->serviceSrcInstNode);\r
609 \r
610                     if (leftNode && rmCompareResourceNodeOwners(leftNode, matchingNode)) {\r
611                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
612                         combineLeft = true;\r
613                     }\r
614                     if (rightNode && rmCompareResourceNodeOwners(rightNode, matchingNode)) {\r
615                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
616                         combineRight = true;\r
617                     }\r
618 \r
619                     if (combineLeft && combineRight) {\r
620                         /* Combine all three nodes into matchingNode */\r
621                         matchingNode->base = leftNode->base;\r
622                         matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;\r
623 \r
624                         rmClearOwners(leftNode);\r
625                         rmResourceNodeFree(leftNode);\r
626                         rmClearOwners(rightNode);\r
627                         rmResourceNodeFree(rightNode);                        \r
628                     }\r
629                     else if (combineLeft) {\r
630                         /* Combine left and matching nodes.  Reinsert right. */\r
631                         matchingNode->base = leftNode->base;\r
632                         matchingNode->length += leftNode->length;\r
633 \r
634                         rmClearOwners(leftNode);\r
635                         rmResourceNodeFree(leftNode);\r
636                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);                        \r
637                     }\r
638                     else if (combineRight) {\r
639                         /* Combine right and matching nodes.  Reinsert left. */\r
640                         matchingNode->length += rightNode->length;\r
641 \r
642                         rmClearOwners(rightNode);\r
643                         rmResourceNodeFree(rightNode);\r
644                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
645                     }\r
646                     else {\r
647                         /* No combine. */\r
648                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
649                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
650                     }\r
651 \r
652                     /* Always reinsert matchingNode */                \r
653                     RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);   \r
654                 }   \r
655                 else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {\r
656                     /* findNode range is subset of matchingNode range and neither boundary is\r
657                      * equivalent.\r
658                      *\r
659                      * |<----------matched node---------->|\r
660                      *        |<---alloc request--->|\r
661                      */ \r
662                     RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
663                     leftNode = rmResourceNodeNew(matchingNode->base, findNode.base - matchingNode->base);\r
664                     rmCopyOwners(leftNode, matchingNode);\r
665                     rightNode = rmResourceNodeNew(findNode.base + findNode.length, matchingEnd - findEnd);\r
666                     rmCopyOwners(rightNode, matchingNode);\r
667 \r
668                     matchingNode->base = findNode.base;                                    \r
669                     matchingNode->length = findNode.length;\r
670                     rmAddOwner(matchingNode, opInfo->serviceSrcInstNode);\r
671 \r
672                     /* Insert all the nodes */\r
673                     RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
674                     RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
675                     RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
676                 }  \r
677                 else {    \r
678                     if (findNode.base == matchingNode->base) {\r
679                         /* findNode base and matchingNode base are equivalent.  May be combine\r
680                          * possibilities to the left\r
681                          *\r
682                          * |<---left node (alloc'd)--->||<----------matched node---------->|\r
683                          *                              |<---findNode (alloc req)--->|\r
684                          */                         \r
685                         leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
686                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
687                         /* Add allocating instance to owner list for compare with leftNode */\r
688                         rmAddOwner(matchingNode, opInfo->serviceSrcInstNode);\r
689                         \r
690                         if (leftNode && rmCompareResourceNodeOwners(leftNode, matchingNode)) {\r
691                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
692                             /* Combine leftNode and findNode */\r
693                             leftNode->length += findNode.length;\r
694                         }\r
695                         else {\r
696                             leftNode = rmResourceNodeNew(findNode.base, findNode.length);\r
697                             rmCopyOwners(leftNode, matchingNode);\r
698                         }\r
699 \r
700                         /* Account for leftNode in matchingNode */\r
701                         matchingNode->base = findNode.base + findNode.length;\r
702                         matchingNode->length = matchingEnd - findEnd;  \r
703 \r
704                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
705                     }\r
706                     else if (findEnd == matchingEnd) {\r
707                         /* findNode end and matchingNode end are equivalent.  May be combine\r
708                          * possibilities to the right\r
709                          *\r
710                          * |<----------matched node---------->||<---right node (alloc'd)--->|\r
711                          *       |<---findNode (alloc req)--->| \r
712                          */                        \r
713                         rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
714                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
715                         /* Add allocating instance to owner list for compare with rightNode */\r
716                         rmAddOwner(matchingNode, opInfo->serviceSrcInstNode);\r
717                         \r
718                         if (rightNode && rmCompareResourceNodeOwners(rightNode, matchingNode)) {\r
719                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
720                             /* Combine rightNode and findNode */\r
721                             rightNode->base = findNode.base;\r
722                             rightNode->length += findNode.length;\r
723                         }\r
724                         else {\r
725                             rightNode = rmResourceNodeNew(findNode.base, findNode.length);\r
726                             rmCopyOwners(rightNode, matchingNode);\r
727                         }\r
728 \r
729                         /* Account for rightNode in matchingNode */\r
730                         matchingNode->length -= findNode.length;  \r
731 \r
732                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
733                     }\r
734                     /* Remove allocating instance from leftover matchingNode */\r
735                     rmDeleteOwner(matchingNode, opInfo->serviceSrcInstNode);\r
736                     RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
737                 }\r
738                 retVal = RM_SERVICE_APPROVED;\r
739             }\r
740         }\r
741         else {\r
742             retVal = RM_SERVICE_DENIED_PARTIAL_ALLOCATION;\r
743         }\r
744     }\r
745     else {\r
746         retVal = RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST;\r
747     }\r
748 \r
749     return(retVal);        \r
750 }\r
751 \r
752 int32_t rmTreeFree(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
753 {\r
754     Rm_ResourceNode  findNode;\r
755     Rm_ResourceNode *matchingNode = NULL;\r
756     Rm_ResourceNode *leftNode = NULL;\r
757     Rm_ResourceNode *rightNode = NULL;\r
758     bool             combineLeft = false;\r
759     bool             combineRight = false;\r
760     uint32_t         findEnd;\r
761     uint32_t         matchingEnd;\r
762     int32_t          retVal;\r
763 \r
764     memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));\r
765     findNode.base = opInfo->resourceInfo->base;\r
766     findNode.length = opInfo->resourceInfo->length;\r
767     matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);\r
768 \r
769     if (matchingNode) {\r
770         findEnd = findNode.base + findNode.length - 1;\r
771         matchingEnd = matchingNode->base + matchingNode->length - 1;\r
772         \r
773         if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {  \r
774             if (matchingNode->allocationCount) {\r
775                 if (rmIsOwnedBy(matchingNode, opInfo->serviceSrcInstNode)) {\r
776                     if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd))\r
777                     {\r
778                         /* Case 1: Free range equals allocated matched node exactly. Attempt to combine \r
779                          *         freed node with nodes to left and right.\r
780                          *\r
781                          * |<--left node-->||<---matched node--->||<--right node-->|\r
782                          *                  |<---free request--->|\r
783                          */ \r
784                         leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
785                         rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
786                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
787                         rmDeleteOwner(matchingNode, opInfo->serviceSrcInstNode);\r
788 \r
789                         if (leftNode && rmCompareResourceNodeOwners(leftNode, matchingNode)) {\r
790                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
791                             combineLeft = true;\r
792                         }\r
793                         if (rightNode && rmCompareResourceNodeOwners(rightNode, matchingNode)) {\r
794                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
795                             combineRight = true;\r
796                         }\r
797 \r
798                         if (combineLeft && combineRight) {\r
799                             /* Combine all three nodes into matchingNode */\r
800                             matchingNode->base = leftNode->base;\r
801                             matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;\r
802 \r
803                             rmClearOwners(leftNode);\r
804                             rmResourceNodeFree(leftNode);\r
805                             rmClearOwners(rightNode);\r
806                             rmResourceNodeFree(rightNode);                        \r
807                         }\r
808                         else if (combineLeft) {\r
809                             /* Combine left and matching nodes.  Reinsert right. */\r
810                             matchingNode->base = leftNode->base;\r
811                             matchingNode->length += leftNode->length;\r
812 \r
813                             rmClearOwners(leftNode);\r
814                             rmResourceNodeFree(leftNode);\r
815                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);                        \r
816                         }\r
817                         else if (combineRight) {\r
818                             /* Combine right and matching nodes.  Reinsert left. */\r
819                             matchingNode->length += rightNode->length;\r
820 \r
821                             rmClearOwners(rightNode);\r
822                             rmResourceNodeFree(rightNode);\r
823                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
824                         }\r
825                         else {\r
826                             /* No combine. */\r
827                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
828                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
829                         }\r
830 \r
831                         /* Always reinsert matchingNode */\r
832                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);                    \r
833                     }\r
834                     else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {\r
835                         /* Case 2: Free range is less than range in matched node. Split\r
836                          *         matched node into three nodes.\r
837                          *\r
838                          * |<----------matched node---------->|\r
839                          *        |<---free request--->|\r
840                          *\r
841                          * Remove instance from AllocatedTo list then add it back in for side nodes for\r
842                          * proper accounting of allocations in validInstance list\r
843                          */ \r
844                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
845                         rmDeleteOwner(matchingNode, opInfo->serviceSrcInstNode);\r
846                         \r
847                         leftNode = rmResourceNodeNew(matchingNode->base, findNode.base - matchingNode->base);\r
848                         rmCopyOwners(leftNode, matchingNode);\r
849                         rmAddOwner(leftNode, opInfo->serviceSrcInstNode);\r
850                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
851                         \r
852                         rightNode = rmResourceNodeNew(findNode.base + findNode.length, matchingEnd - findEnd);\r
853                         rmCopyOwners(rightNode, matchingNode);\r
854                         rmAddOwner(rightNode, opInfo->serviceSrcInstNode);\r
855                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
856 \r
857                         matchingNode->base = findNode.base;                                    \r
858                         matchingNode->length = findNode.length;\r
859                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
860                     }\r
861                     else {                        \r
862                         if (findNode.base == matchingNode->base) {\r
863                             /* Case 3: Free range is on left boundary of matched node. Try to \r
864                              *         combine free range with left node.\r
865                              *\r
866                              * |<---left node (free)--->||<----------matched node---------->|\r
867                              *                           |<---findNode (free req)--->|\r
868                              */ \r
869 \r
870                             leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
871                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
872                             /* Remove freeing instance from owner list for compare with leftNode */\r
873                             rmDeleteOwner(matchingNode, opInfo->serviceSrcInstNode);\r
874                             \r
875                             if (leftNode && rmCompareResourceNodeOwners(leftNode, matchingNode)) {\r
876                                 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
877                                 /* Combine leftNode and findNode */\r
878                                 leftNode->length += findNode.length;\r
879                             }\r
880                             else {\r
881                                 leftNode = rmResourceNodeNew(findNode.base, findNode.length);\r
882                                 rmCopyOwners(leftNode, matchingNode);\r
883                             }\r
884 \r
885                             /* Remove leftNode range from matchingNode */\r
886                             matchingNode->base = findNode.base + findNode.length;\r
887                             matchingNode->length = matchingEnd - findEnd;  \r
888                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
889                         }\r
890                         else if (findEnd == matchingEnd) {\r
891                             /* Case 4: Free range is on right boundary of matched node. Try to \r
892                              *         combine free range with right node.\r
893                              *\r
894                              * |<----------matched node---------->||<---right node (free)--->|\r
895                              *        |<---findNode (free req)--->|\r
896                              */ \r
897                             \r
898                             rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
899                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode); \r
900                             /* Remove freeing instance from owner list for compare with rightNode */\r
901                             rmDeleteOwner(matchingNode, opInfo->serviceSrcInstNode);\r
902                             \r
903                             if (rightNode && rmCompareResourceNodeOwners(rightNode, matchingNode)) {\r
904                                 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
905                                 /* Combine rightNode and findNode */\r
906                                 rightNode->base = findNode.base;\r
907                                 rightNode->length += findNode.length;\r
908                             }\r
909                             else {\r
910                                 rightNode = rmResourceNodeNew(findNode.base, findNode.length);\r
911                                 rmCopyOwners(rightNode, matchingNode);\r
912                             }\r
913 \r
914                             /* Remove rightNode range from matchingNode */\r
915                             matchingNode->length -= findNode.length;  \r
916                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
917                         }\r
918 \r
919                         /* Add freeing instance back into matchingNode allocations */\r
920                         rmAddOwner(matchingNode, opInfo->serviceSrcInstNode);\r
921                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
922                     }\r
923 \r
924                     retVal = RM_SERVICE_APPROVED;\r
925                 }\r
926                 else {\r
927                     retVal = RM_SERVICE_DENIED_RES_NOT_ALLOCD_TO_INST;\r
928                 }\r
929             }\r
930             else {\r
931                 retVal = RM_SERVICE_DENIED_RES_ALREADY_FREE;\r
932             }\r
933         }\r
934         else {\r
935             retVal = RM_SERVICE_DENIED_PARTIAL_FREE;\r
936         }\r
937     }\r
938     else {\r
939         retVal = RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST;\r
940     }\r
941     return(retVal);  \r
942 }\r
943 \r
944 int32_t rmAllocatorOperation(Rm_Inst *rmInst, Rm_AllocatorOpInfo *opInfo)\r
945 {\r
946     Rm_Allocator *allocator = NULL;\r
947     int32_t       resourceOffsetInPolicy;\r
948     int32_t       retVal;\r
949     \r
950     resourceOffsetInPolicy = rmPolicyGetResourceOffset(rmInst->policy, opInfo->resourceInfo->name);\r
951     allocator = rmAllocatorFind(rmInst->allocators, opInfo->resourceInfo->name);\r
952     \r
953     if ((resourceOffsetInPolicy > 0) && allocator) {\r
954         if (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE) {\r
955             retVal = rmTreePreAllocate(rmInst, allocator, resourceOffsetInPolicy, opInfo);\r
956         }               \r
957         else if (opInfo->operation == Rm_allocatorOp_ALLOCATE) {\r
958             retVal = rmTreeAllocate(rmInst, allocator, resourceOffsetInPolicy, opInfo);\r
959         }\r
960         else if (opInfo->operation == Rm_allocatorOp_FREE) {\r
961             retVal = rmTreeFree(allocator, opInfo);\r
962         }         \r
963     }\r
964     else {\r
965         /* Resource could not be found in policy and/or allocator */\r
966         retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;\r
967     }\r
968     return(retVal);\r
969 }\r
970 \r
971 void rmAllocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction, void *validInstNode,\r
972                           uint32_t allocType)\r
973 {\r
974     Rm_AllocatorOpInfo  opInfo;\r
975     Rm_NameServerObjCfg nameServerObjCfg;\r
976     int32_t             retVal = transaction->state;\r
977 \r
978     memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));\r
979     \r
980     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {\r
981         /* Forward all allocation requests to Server if transport is up.  Otherwise, just queue. */\r
982         if (rmInst->registeredWithDelegateOrServer) {\r
983             rmTransactionForwarder(rmInst, transaction);   \r
984         }  \r
985     }\r
986     else if (rmInst->instType == Rm_instType_SERVER) {\r
987         opInfo.resourceInfo = &transaction->resourceInfo;\r
988         opInfo.serviceSrcInstNode = validInstNode;\r
989         opInfo.allocType = allocType;\r
990 \r
991         /* Populated NameServer name has precedence over base */\r
992         if (strlen(transaction->resourceInfo.nameServerName) > 0) {\r
993             if ((transaction->resourceInfo.base == 0) &&\r
994                 (transaction->resourceInfo.length == 0) &&\r
995                 (transaction->resourceInfo.alignment == 0)) {\r
996                 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));\r
997                 nameServerObjCfg.nameServerTree = rmInst->nameServer;\r
998                 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;\r
999                 if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {\r
1000                     strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);\r
1001                     transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;\r
1002                     transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;\r
1003                 }                \r
1004             }\r
1005             else {\r
1006                 retVal = RM_ERROR_NS_NAME_AND_RES_VAL_CONFLICT;\r
1007             }\r
1008         }\r
1009 \r
1010         if (retVal == RM_SERVICE_PROCESSING) {      \r
1011             if (transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) {\r
1012                 opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE;\r
1013                 retVal = rmAllocatorOperation(rmInst, &opInfo);\r
1014             }\r
1015         \r
1016             if (retVal == RM_SERVICE_PROCESSING) {\r
1017                 opInfo.operation = Rm_allocatorOp_ALLOCATE;\r
1018                 retVal = rmAllocatorOperation(rmInst, &opInfo);\r
1019             }      \r
1020         }\r
1021         \r
1022         transaction->state = retVal;\r
1023 \r
1024         if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {\r
1025             /* Source of allocation was not the server instance, provide the transaction\r
1026              * to the transaction responder */\r
1027             rmTransactionResponder(rmInst, transaction);\r
1028         }\r
1029         /* Otherwise let the return stack return the transaction to the serviceHandler */                   \r
1030     }   \r
1031 }\r
1032 \r
1033 void rmFreeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction, void *validInstNode)\r
1034 {\r
1035     Rm_AllocatorOpInfo  opInfo; \r
1036     Rm_NameServerObjCfg nameServerObjCfg;    \r
1037     int32_t             retVal = transaction->state;\r
1038 \r
1039     memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));\r
1040     \r
1041     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {\r
1042         /* Forward all free requests to Server if transport is up.  Otherwise, just queue. */\r
1043         if (rmInst->registeredWithDelegateOrServer) {\r
1044             rmTransactionForwarder(rmInst, transaction);   \r
1045         }\r
1046     }\r
1047     else if (rmInst->instType == Rm_instType_SERVER) {\r
1048         opInfo.resourceInfo = &transaction->resourceInfo;\r
1049         opInfo.serviceSrcInstNode = validInstNode;\r
1050 \r
1051         /* Populated NameServer name has precedence over base */\r
1052         if (strlen(transaction->resourceInfo.nameServerName) > 0) {\r
1053             if ((transaction->resourceInfo.base == 0) &&\r
1054                 (transaction->resourceInfo.length == 0) &&\r
1055                 (transaction->resourceInfo.alignment == 0)) {\r
1056                 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));\r
1057                 nameServerObjCfg.nameServerTree = rmInst->nameServer;\r
1058                 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;\r
1059                 if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {\r
1060                     strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);\r
1061                     transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;\r
1062                     transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;\r
1063                 } \r
1064             }\r
1065             else {\r
1066                 retVal = RM_ERROR_NS_NAME_AND_RES_VAL_CONFLICT;\r
1067             }                \r
1068         }\r
1069         \r
1070         if(retVal == RM_SERVICE_PROCESSING) {        \r
1071             opInfo.operation = Rm_allocatorOp_FREE;\r
1072             retVal = rmAllocatorOperation(rmInst, &opInfo);\r
1073         }       \r
1074 \r
1075         transaction->state = retVal;\r
1076 \r
1077         if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {\r
1078             /* Source of allocation was not the server instance, provide the transaction\r
1079              * to the transaction responder */\r
1080             rmTransactionResponder(rmInst, transaction);\r
1081         }\r
1082         /* Otherwise let the return stack return the transaction to the serviceHandler */        \r
1083     }   \r
1084 }\r
1085 \r
1086 /* This function is executed when a RM instance receives a response to one of its requests\r
1087  * and the information in the request must be provided to the original requesting component */\r
1088 void rmServiceResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
1089 {\r
1090     Rm_ServiceRespInfo serviceResponse;\r
1091 \r
1092     /* The responseTransaction will contain the resultant state details of\r
1093      * the requestTransaction's service request */\r
1094     serviceResponse.serviceState = transaction->state;\r
1095     /* Pass back the ID that was provided to the component when it requested\r
1096      * the service */\r
1097     serviceResponse.serviceId = transaction->localId;\r
1098 \r
1099     /* Service was approved and service was an allocate request.  The resource\r
1100      * data is passed back to the component */\r
1101     if ((serviceResponse.serviceState == RM_SERVICE_APPROVED) &&\r
1102         ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||\r
1103          (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||\r
1104          (transaction->type == Rm_service_RESOURCE_GET_BY_NAME)))\r
1105     {\r
1106         strncpy(serviceResponse.resourceName, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);\r
1107         serviceResponse.resourceBase = transaction->resourceInfo.base;\r
1108         serviceResponse.resourceLength = transaction->resourceInfo.length;\r
1109     }\r
1110 \r
1111     /* Issue the callback to the requesting component with the response information */\r
1112     transaction->callback.serviceCallback(&serviceResponse);\r
1113 \r
1114     /* Delete the transaction from the transaction queue */\r
1115     rmTransactionQueueDelete(rmInst, transaction->localId);\r
1116     return;\r
1117 }\r
1118 \r
1119 /* Function used to send RM response transactions to lower level agents */\r
1120 void rmTransactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
1121 {\r
1122     Rm_Transport    *dstTransport = NULL;\r
1123     Rm_PacketHandle  pktHandle = NULL;\r
1124 \r
1125     dstTransport = rmTransportFindRemoteName((Rm_Transport *) rmInst->transports, transaction->pktSrcInstName);\r
1126 \r
1127     switch (transaction->type) {\r
1128         case Rm_service_RESOURCE_ALLOCATE_INIT:\r
1129         case Rm_service_RESOURCE_ALLOCATE_USE:\r
1130         case Rm_service_RESOURCE_FREE:\r
1131         case Rm_service_RESOURCE_GET_BY_NAME:\r
1132             pktHandle = rmTransportCreateResourceResponsePkt(rmInst, dstTransport->appTransportHandle, \r
1133                                                              transaction);\r
1134             break;\r
1135         case Rm_service_RESOURCE_MAP_TO_NAME:\r
1136         case Rm_service_RESOURCE_UNMAP_NAME:\r
1137             pktHandle = rmTransportCreateNsResponsePkt(rmInst, dstTransport->appTransportHandle,\r
1138                                                        transaction);\r
1139             break;\r
1140     }\r
1141 \r
1142     if (pktHandle) {\r
1143         if (rmInst->transportCallouts.rmSendPkt(dstTransport->appTransportHandle, pktHandle) < RM_OK) {\r
1144             transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;\r
1145         }\r
1146     }\r
1147     rmTransactionQueueDelete(rmInst, transaction->localId);\r
1148 }\r
1149 \r
1150 /* Function used to forward RM transactions to higher level agents */\r
1151 void rmTransactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
1152 {\r
1153     Rm_Transport    *dstTransport = NULL;\r
1154     Rm_PacketHandle  pktHandle = NULL;\r
1155 \r
1156     if (rmInst->registeredWithDelegateOrServer) {\r
1157         if (rmInst->instType == Rm_instType_CLIENT) {\r
1158             dstTransport = rmTransportFindRemoteInstType((Rm_Transport *) rmInst->transports, Rm_instType_CLIENT_DELEGATE);\r
1159 \r
1160             if (!dstTransport) {\r
1161                 dstTransport = rmTransportFindRemoteInstType((Rm_Transport *) rmInst->transports, Rm_instType_SERVER);\r
1162             }\r
1163         } \r
1164         else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {\r
1165             dstTransport = rmTransportFindRemoteInstType((Rm_Transport *) rmInst->transports, Rm_instType_SERVER);\r
1166         }\r
1167 \r
1168         switch (transaction->type) {\r
1169             case Rm_service_RESOURCE_ALLOCATE_INIT:\r
1170             case Rm_service_RESOURCE_ALLOCATE_USE:\r
1171             case Rm_service_RESOURCE_FREE:\r
1172             case Rm_service_RESOURCE_GET_BY_NAME:\r
1173                 pktHandle = rmTransportCreateResourceReqPkt(rmInst, dstTransport->appTransportHandle, transaction);\r
1174                 break;\r
1175             case Rm_service_RESOURCE_MAP_TO_NAME:\r
1176             case Rm_service_RESOURCE_UNMAP_NAME:\r
1177                 pktHandle = rmTransportCreateNsRequestPkt(rmInst, dstTransport->appTransportHandle, transaction);\r
1178                 break;\r
1179         }\r
1180 \r
1181         if (pktHandle) {\r
1182             if (rmInst->transportCallouts.rmSendPkt(dstTransport->appTransportHandle, pktHandle) < RM_OK) {\r
1183                 transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;\r
1184             }\r
1185         }\r
1186 \r
1187         transaction->hasBeenForwarded = true;\r
1188         /* Transaction not deleted.  Waiting for response from RM CD or Server */\r
1189     }\r
1190 }\r
1191 \r
1192 void rmTransactionProcessor (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
1193 {\r
1194     void                *validInstNode;\r
1195     Rm_PolicyCheckCfg    privCheckCfg;\r
1196     Rm_NameServerObjCfg  nameServerObjCfg;      \r
1197     uint32_t             allocType = 0;    \r
1198 \r
1199     /* Handle static transactions originating on this instance.  Any other static transactions will be\r
1200      * stored in transaction queue until all transports are up. */\r
1201     if (((rmInst->instType == Rm_instType_CLIENT) || (rmInst->instType == Rm_instType_CLIENT_DELEGATE)) &&\r
1202         (!rmInst->registeredWithDelegateOrServer) && \r
1203         (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS) == 0)) {\r
1204         if (rmInst->staticInfo.staticPolicy) {\r
1205             if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||\r
1206                 (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE)) {\r
1207                 /* Check request against startup policy */\r
1208                 memset((void *)&privCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));\r
1209 \r
1210                 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {\r
1211                     privCheckCfg.type = Rm_policyCheck_INIT;\r
1212                 }\r
1213                 else {\r
1214                     privCheckCfg.type = Rm_policyCheck_USE;\r
1215                 }\r
1216                 privCheckCfg.policyDtb = rmInst->staticInfo.staticPolicy;\r
1217                 privCheckCfg.validInstNode = rmPolicyGetValidInstNode(rmInst->staticInfo.staticValidInstTree, \r
1218                                                                       rmInst->instName);\r
1219                 privCheckCfg.resourceOffset = rmPolicyGetResourceOffset(rmInst->staticInfo.staticPolicy,\r
1220                                                                         transaction->resourceInfo.name);\r
1221                 privCheckCfg.resourceBase = transaction->resourceInfo.base;\r
1222                 privCheckCfg.resourceLength = transaction->resourceInfo.length;\r
1223 \r
1224                 if (rmPolicyCheckPrivilege(&privCheckCfg, &transaction->state)) {\r
1225                     transaction->state = RM_SERVICE_APPROVED_STATIC;\r
1226                 }\r
1227                 else if (transaction->state == RM_SERVICE_PROCESSING) {\r
1228                     /* Privilege check returned false without error */\r
1229                     transaction->state = RM_SERVICE_DENIED_BY_STATIC_POLICY;\r
1230                 }\r
1231             }\r
1232             else {\r
1233                 transaction->state = RM_SERVICE_DENIED_INVALID_STATIC_REQUEST;\r
1234             }\r
1235         }\r
1236         else {\r
1237             transaction->state = RM_ERROR_REQ_FAILED_NO_STATIC_POLICY;\r
1238         }        \r
1239     }\r
1240     else {\r
1241         /* Handle auto-forwarded transactions.  These transactions include:\r
1242          * - All request transactions received on Clients are forwarded to the Client Delegate\r
1243          * - NameServer requests received on the Client Delegate are forwarded to the Server */\r
1244         if ((rmInst->instType == Rm_instType_CLIENT) ||\r
1245             ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
1246              ((transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) ||\r
1247               (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) ||\r
1248               (transaction->type == Rm_service_RESOURCE_UNMAP_NAME)))) {\r
1249               \r
1250             if ((transaction->state != RM_SERVICE_PROCESSING) &&\r
1251                 (transaction->state != RM_SERVICE_APPROVED_STATIC)) {\r
1252                 if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {\r
1253                     /* Transaction did not originate on this instance */\r
1254                     rmTransactionResponder(rmInst, transaction);\r
1255                 }\r
1256                 else {\r
1257                     /* Transaction originated on this instance */\r
1258                     rmServiceResponder(rmInst, transaction);\r
1259                 }\r
1260             }\r
1261             else {\r
1262                 /* Forward request if transport is up.  Otherwise, just queue. */\r
1263                 if (rmInst->registeredWithDelegateOrServer) {\r
1264                     rmTransactionForwarder(rmInst, transaction);   \r
1265                 } \r
1266             }\r
1267         }\r
1268         else {\r
1269             /* Validate service's originating instance name */\r
1270             if (rmInst->instType == Rm_instType_SERVER) {\r
1271                 validInstNode = rmPolicyGetValidInstNode(rmInst->validInstances, transaction->serviceSrcInstName);\r
1272                 if (validInstNode == NULL) {\r
1273                     transaction->state = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;\r
1274 \r
1275                     /* Send result via responder if transaction did not originate from this instance */\r
1276                     if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {\r
1277                         rmTransactionResponder(rmInst, transaction);\r
1278                     }\r
1279                 }\r
1280             }\r
1281 \r
1282             switch (transaction->type) {\r
1283                 case Rm_service_RESOURCE_ALLOCATE_INIT:\r
1284                 case Rm_service_RESOURCE_ALLOCATE_USE:\r
1285                 case Rm_service_RESOURCE_FREE:               \r
1286                     if ((transaction->state != RM_SERVICE_PROCESSING) &&\r
1287                         (transaction->state != RM_SERVICE_APPROVED_STATIC)) {\r
1288                         /* Transaction complete */\r
1289                         if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {\r
1290                             /* Transaction result not destined for this instance */\r
1291                             rmTransactionResponder(rmInst, transaction);\r
1292                         }\r
1293                         else {\r
1294                             /* Transaction result destined for this instance */\r
1295                             rmServiceResponder(rmInst, transaction);      \r
1296                         }\r
1297                     }\r
1298                     else {\r
1299                         /* Complete allocation/free request */\r
1300                         if (transaction->type == Rm_service_RESOURCE_FREE) {\r
1301                             rmFreeHandler(rmInst, transaction, validInstNode);\r
1302                         }\r
1303                         else {\r
1304                             switch (transaction->type) {\r
1305                                 case Rm_service_RESOURCE_ALLOCATE_INIT:\r
1306                                     RM_policy_SET_PERM(allocType, RM_POLICY_PERM_INIT_SHIFT, 1);\r
1307                                     break;\r
1308                                 case Rm_service_RESOURCE_ALLOCATE_USE:\r
1309                                     RM_policy_SET_PERM(allocType, RM_POLICY_PERM_USE_SHIFT, 1);    \r
1310                                     break;\r
1311                             }\r
1312                             rmAllocationHandler(rmInst, transaction, validInstNode, allocType);\r
1313                         }\r
1314                     }\r
1315                     break;\r
1316                 case Rm_service_RESOURCE_MAP_TO_NAME:\r
1317                 case Rm_service_RESOURCE_GET_BY_NAME:\r
1318                 case Rm_service_RESOURCE_UNMAP_NAME:                \r
1319                     /* NameServer resides on server */\r
1320                     memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));\r
1321                     if (rmInst->nameServer) {\r
1322                         nameServerObjCfg.nameServerTree = rmInst->nameServer;\r
1323                         nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;\r
1324                         if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {\r
1325                             nameServerObjCfg.nodeCfg.resourceName = transaction->resourceInfo.name;\r
1326                             nameServerObjCfg.nodeCfg.resourceBase= transaction->resourceInfo.base;\r
1327                             nameServerObjCfg.nodeCfg.resourceLength = transaction->resourceInfo.length;\r
1328                             transaction->state = rmNameServerAddObject(&nameServerObjCfg);\r
1329                         }\r
1330                         else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {\r
1331                             if ((transaction->state = rmNameServerFindObject(&nameServerObjCfg)) ==\r
1332                                 RM_SERVICE_PROCESSING) {\r
1333                                 strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);\r
1334                                 transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;\r
1335                                 transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;\r
1336                                 transaction->state = RM_SERVICE_APPROVED;\r
1337                             } \r
1338                         }\r
1339                         else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {\r
1340                             transaction->state = rmNameServerDeleteObject(&nameServerObjCfg);\r
1341                         }\r
1342                     }\r
1343                     else {\r
1344                         transaction->state = RM_ERROR_NAMESERVER_DOES_NOT_EXIST;\r
1345                     }\r
1346 \r
1347                     /* Send result via responder if transaction did not originate from this instance */\r
1348                     if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {\r
1349                         rmTransactionResponder(rmInst, transaction);\r
1350                     }\r
1351                     break;\r
1352             }\r
1353         }\r
1354     }\r
1355 \r
1356     /* Forward any queued requests that weren't forwarded yet */\r
1357     if (rmInst->registeredWithDelegateOrServer) {\r
1358         transaction = rmInst->transactionQueue;\r
1359         while(transaction) {\r
1360             if (((transaction->state == RM_SERVICE_PROCESSING) ||\r
1361                  (transaction->state == RM_SERVICE_APPROVED_STATIC)) &&\r
1362                 !transaction->hasBeenForwarded) {\r
1363                 rmTransactionForwarder(rmInst, transaction);\r
1364             }\r
1365             transaction = transaction->nextTransaction;\r
1366         }\r
1367     }\r
1368 }\r
1369 \r
1370 int32_t rmReserveLinuxResource(Rm_Inst *rmInst, Rm_LinuxAlias *linuxAlias, \r
1371                                Rm_LinuxValueRange *linuxValues, Rm_AllocatorOpInfo *opInfo)\r
1372 {\r
1373     int32_t  retVal = RM_OK;\r
1374     bool     baseFound = false;\r
1375     bool     lengthFound = false;\r
1376     uint32_t valueIndex = 0;\r
1377 \r
1378     while ((linuxValues) && (!baseFound || !lengthFound)) {\r
1379         if (linuxAlias->baseOffset == valueIndex) {\r
1380             opInfo->resourceInfo->base = linuxValues->value;\r
1381             baseFound = true;\r
1382 \r
1383             if (linuxAlias->lengthOffset == RM_DTB_LINUX_ALIAS_OFFSET_NOT_SET) {\r
1384                 opInfo->resourceInfo->length = 1;\r
1385                 lengthFound = true;\r
1386             }\r
1387         }\r
1388         else if (linuxAlias->lengthOffset == valueIndex) {\r
1389             opInfo->resourceInfo->length = linuxValues->value;\r
1390             lengthFound = true;\r
1391         }\r
1392 \r
1393         linuxValues = (Rm_LinuxValueRange *)linuxValues->nextValue;\r
1394         valueIndex++;\r
1395     }\r
1396 \r
1397     if (!baseFound || !lengthFound) {\r
1398         retVal = RM_ERROR_DATA_NOT_FOUND_AT_LINUX_ALIAS;\r
1399     }\r
1400     else {\r
1401         /* Allocate resource to Linux */\r
1402         retVal = rmAllocatorOperation(rmInst, opInfo);\r
1403     }\r
1404     return (retVal);\r
1405 }\r
1406 \r
1407 int32_t rmFindAndReserveLinuxResource(Rm_Inst *rmInst, const char *resourceName, void *linuxDtb, \r
1408                                       Rm_LinuxAlias *linuxAlias)\r
1409 {\r
1410     Rm_AllocatorOpInfo  opInfo;\r
1411     Rm_ResourceInfo     resourceInfo;\r
1412     uint32_t            pathOffset;\r
1413     uint32_t            pathSize;\r
1414     char               *spacePtr;\r
1415     int32_t             propOffset;\r
1416     int32_t             nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;\r
1417     int32_t             prevDepth = RM_DTB_UTIL_STARTING_DEPTH;\r
1418     int32_t             depth;\r
1419     int32_t             propertyLen;\r
1420     const char         *propertyName;\r
1421     const void         *propertyData; \r
1422     Rm_LinuxValueRange *linuxValueRange;\r
1423     int32_t             retVal = RM_OK; \r
1424 \r
1425     memset((void *) &opInfo, 0, sizeof(Rm_AllocatorOpInfo));\r
1426     memset((void *) &resourceInfo, 0, sizeof(Rm_ResourceInfo));\r
1427 \r
1428     strncpy(resourceInfo.name, resourceName, RM_NAME_MAX_CHARS);\r
1429     opInfo.serviceSrcInstNode = rmPolicyGetLinuxInstNode(rmInst->validInstances);\r
1430     opInfo.operation = Rm_allocatorOp_ALLOCATE;\r
1431     opInfo.resourceInfo = &resourceInfo;    \r
1432 \r
1433     while(linuxAlias) {\r
1434         /* Reset parsing variables */\r
1435         pathOffset = 0;\r
1436         pathSize = strlen(linuxAlias->path) + 1;\r
1437         nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;\r
1438         prevDepth = RM_DTB_UTIL_STARTING_DEPTH;   \r
1439         resourceInfo.base = 0;\r
1440         resourceInfo.length = 0;\r
1441 \r
1442         spacePtr = strpbrk(linuxAlias->path, " ");\r
1443         if (spacePtr) {\r
1444             *spacePtr = '\0';\r
1445         }       \r
1446         \r
1447         while(pathOffset < pathSize) {\r
1448             /* Move through DTB nodes until next alias path node found */\r
1449             if (strcmp(linuxAlias->path + pathOffset, fdt_get_name(linuxDtb, nodeOffset, NULL))) {\r
1450                 nodeOffset = fdt_next_node(linuxDtb, nodeOffset, &depth);\r
1451 \r
1452                 if ((depth < prevDepth) || (nodeOffset == -FDT_ERR_NOTFOUND)) {\r
1453                     /* Returning from subnode that matched part of alias path without finding\r
1454                      * resource values */\r
1455                     retVal = RM_ERROR_DATA_NOT_FOUND_AT_LINUX_ALIAS;\r
1456                     break;\r
1457                 }\r
1458             }\r
1459             else {\r
1460                 /* Found next alias path node.  Move to next node name in path string. */\r
1461                 pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);\r
1462                 spacePtr = strpbrk(linuxAlias->path + pathOffset, " ");\r
1463                 if (spacePtr) {\r
1464                     *spacePtr = '\0';\r
1465                 }       \r
1466                 \r
1467                 prevDepth = fdt_node_depth(linuxDtb, nodeOffset);\r
1468                 propOffset = fdt_first_property_offset(linuxDtb, nodeOffset);\r
1469                 while ((propOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) &&\r
1470                        (pathOffset < pathSize)) {\r
1471                     propertyData = fdt_getprop_by_offset(linuxDtb, propOffset, \r
1472                                                          &propertyName, &propertyLen);\r
1473 \r
1474                     if (strcmp(linuxAlias->path + pathOffset, propertyName) == 0) {\r
1475                         /* Found resource at end of alias path */\r
1476                         pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);\r
1477                         linuxValueRange = rmDtbUtilLinuxExtractValues(propertyData, propertyLen);\r
1478                         retVal = rmReserveLinuxResource(rmInst, linuxAlias, \r
1479                                                          linuxValueRange, &opInfo);\r
1480                         rmDtbUtilLinuxFreeValues(linuxValueRange);\r
1481                     }\r
1482                     propOffset = fdt_next_property_offset(linuxDtb, propOffset);\r
1483                 } \r
1484 \r
1485                 if (propOffset < -FDT_ERR_NOTFOUND) {\r
1486                     retVal = propOffset;\r
1487                     break;\r
1488                 }\r
1489             }\r
1490         }\r
1491 \r
1492         if (retVal < RM_OK) {\r
1493             break;\r
1494         }\r
1495         linuxAlias = (Rm_LinuxAlias *) linuxAlias->nextLinuxAlias;\r
1496     }\r
1497     return (retVal);\r
1498 }\r
1499 \r
1500 int32_t rmCreateAndInitAllocator(Rm_Inst *rmInst, const char *resourceName, \r
1501                                  Rm_ResourceProperties *resourceProperties, void *linuxDtb)\r
1502 {\r
1503     Rm_ResourceRange    *range = NULL;\r
1504     Rm_ResourceRange    *rangeBasePtr = NULL;\r
1505     Rm_NsAssignment     *nsAssignments = NULL;\r
1506     Rm_NsAssignment     *nsAssignmentBasePtr = NULL;\r
1507     Rm_LinuxAlias       *linuxAlias = NULL;\r
1508     Rm_NameServerObjCfg  nameServerObjCfg;      \r
1509     int32_t              retVal = RM_OK;\r
1510 \r
1511     if (resourceProperties->rangeData && (resourceProperties->rangeLen > 0)) {\r
1512         range = rangeBasePtr = rmDtbUtilResExtractRange(resourceProperties->rangeData, \r
1513                                                         resourceProperties->rangeLen);\r
1514         \r
1515         if ((retVal = rmCreateTreeAllocator(rmInst, resourceName, range)) >= RM_OK) {\r
1516             if (resourceProperties->linuxAliasData && resourceProperties->linuxAliasLen) {\r
1517                 if (linuxDtb) {\r
1518                     linuxAlias = rmDtbUtilResExtractLinuxAlias(resourceProperties->linuxAliasData,\r
1519                                                                resourceProperties->linuxAliasLen, &retVal);\r
1520                     if (linuxAlias) {\r
1521                         retVal = rmFindAndReserveLinuxResource(rmInst, resourceName, linuxDtb, linuxAlias);            \r
1522                     }\r
1523                 }\r
1524                 else {\r
1525                     retVal = RM_ERROR_GRL_LINUX_ALIAS_BUT_NO_DTB;\r
1526                 }\r
1527             }\r
1528         }\r
1529     }\r
1530     \r
1531     if (retVal >= RM_OK) {\r
1532         if (resourceProperties->nsAssignData && resourceProperties->nsAssignLen) {\r
1533             nsAssignments = rmDtbUtilResExtractNsAssignment(resourceProperties->nsAssignData, \r
1534                                                             resourceProperties->nsAssignLen, &retVal);\r
1535             if (nsAssignments) {\r
1536                 nsAssignmentBasePtr = nsAssignments;\r
1537                 while (nsAssignments) {\r
1538                     memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));\r
1539                     nameServerObjCfg.nameServerTree = rmInst->nameServer;\r
1540                     nameServerObjCfg.nodeCfg.objName = nsAssignments->nsName;\r
1541                     nameServerObjCfg.nodeCfg.resourceName = (char *)resourceName;\r
1542                     nameServerObjCfg.nodeCfg.resourceBase= nsAssignments->resourceBase;\r
1543                     nameServerObjCfg.nodeCfg.resourceLength = nsAssignments->resourceLength;                \r
1544                     rmNameServerAddObject(&nameServerObjCfg);\r
1545                     nsAssignments = nsAssignments->nextNsAssignment;\r
1546                 }\r
1547                 rmDtbUtilResFreeNsAssignmentList(nsAssignmentBasePtr);\r
1548             }\r
1549         }\r
1550     }\r
1551 \r
1552     rmDtbUtilResFreeRange(rangeBasePtr);\r
1553     if (linuxAlias) {\r
1554         rmDtbUtilResFreeLinuxAlias(linuxAlias);\r
1555     }\r
1556     return(retVal);\r
1557 }\r
1558 \r
1559 int32_t rmParseResourceProperty(void *globalResourceDtb, int32_t offset, Rm_ResourceProperties *propertyInfo)\r
1560 {\r
1561         int32_t              propertyLen;\r
1562         const char          *propertyName;\r
1563         const void          *propertyData;\r
1564     Rm_ResourcePropType  propertyType;\r
1565     int32_t              retVal = RM_OK;\r
1566 \r
1567         propertyData = fdt_getprop_by_offset(globalResourceDtb, offset, &propertyName, &propertyLen);\r
1568     propertyType = rmDtbUtilResGetPropertyType(propertyName);\r
1569     if (propertyType == Rm_resourcePropType_RESOURCE_RANGE) {\r
1570         propertyInfo->rangeData = propertyData;\r
1571         propertyInfo->rangeLen = propertyLen;\r
1572     }\r
1573     else if (propertyType == Rm_resourcePropType_NSASSIGNMENT) {\r
1574         propertyInfo->nsAssignData = propertyData;\r
1575         propertyInfo->nsAssignLen = propertyLen;\r
1576     }\r
1577     else if (propertyType == Rm_resourcePropType_RESOURCE_LINUX_ALIAS) {\r
1578         propertyInfo->linuxAliasData = propertyData;\r
1579         propertyInfo->linuxAliasLen = propertyLen;\r
1580     }        \r
1581     else {\r
1582         retVal = RM_ERROR_GRL_UNKNOWN_RESOURCE_PROPERTY;\r
1583     }\r
1584 \r
1585     if (retVal == RM_OK) {\r
1586         offset = fdt_next_property_offset(globalResourceDtb, offset);\r
1587         if (offset >= 0) {\r
1588             retVal = rmParseResourceProperty(globalResourceDtb, offset, propertyInfo);\r
1589         }\r
1590         else if (offset != -FDT_ERR_NOTFOUND) {\r
1591             /* Error returned by LIBFDT */\r
1592             retVal = offset;\r
1593         }\r
1594     }\r
1595     return (retVal);\r
1596 }\r
1597 \r
1598 int32_t rmParseResourceNode(Rm_Inst *rmInst, void *globalResourceDtb, int32_t nodeOffset, int32_t depth,\r
1599                             void *linuxDtb)\r
1600 {\r
1601         const char            *resourceName = fdt_get_name(globalResourceDtb, nodeOffset, NULL);\r
1602     Rm_ResourceProperties  resourceProperties;\r
1603         int32_t                retVal = RM_OK;\r
1604         int32_t                offset;\r
1605 \r
1606     memset((void *)&resourceProperties, 0, sizeof(Rm_ResourceProperties));\r
1607     /* Get properties of resource node */\r
1608         offset = fdt_first_property_offset(globalResourceDtb, nodeOffset);\r
1609         if (offset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) {\r
1610                 retVal =  rmParseResourceProperty(globalResourceDtb, offset, &resourceProperties);\r
1611         if (retVal < -FDT_ERR_NOTFOUND) {\r
1612             return (retVal);\r
1613         }\r
1614         if (retVal = rmCreateAndInitAllocator(rmInst, resourceName, &resourceProperties, linuxDtb) < RM_OK) {\r
1615             return (retVal);\r
1616         }\r
1617         }\r
1618     else if (offset != -FDT_ERR_NOTFOUND) {\r
1619                 /* Error returned by LIBFDT */\r
1620         return (offset);\r
1621     }\r
1622     \r
1623         offset = fdt_next_node(globalResourceDtb, nodeOffset, &depth);\r
1624     if ((offset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && (depth >= RM_DTB_UTIL_STARTING_DEPTH)) {\r
1625         retVal = rmParseResourceNode(rmInst, globalResourceDtb, offset, depth, linuxDtb);\r
1626         if (retVal < -FDT_ERR_NOTFOUND) {\r
1627             return (retVal);\r
1628         }\r
1629     }\r
1630     else if (offset != -FDT_ERR_NOTFOUND) {\r
1631         /* Error returned by LIBFDT */\r
1632         return (offset);\r
1633     }\r
1634     return (retVal);\r
1635 }\r
1636 \r
1637 int32_t rmInitializeAllocators(Rm_Inst *rmInst, void *globalResourceDtb, void *linuxDtb)\r
1638 {\r
1639     int32_t nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;\r
1640     int32_t startDepth = RM_DTB_UTIL_STARTING_DEPTH;\r
1641     int32_t result = RM_OK;\r
1642 \r
1643     /* Recursively parse the Global Resource List, creating an allocator for\r
1644      * each resource as specified in the node */\r
1645     result = rmParseResourceNode(rmInst, globalResourceDtb, nodeOffset, startDepth, linuxDtb);\r
1646 \r
1647     return(result);\r
1648 }\r
1649      \r
1650 /**********************************************************************\r
1651  ********************** Application visible APIs **********************\r
1652  **********************************************************************/\r
1653 \r
1654 /* Server Only */\r
1655 void Rm_printResourceStatus(Rm_Handle *rmHandle)\r
1656 {\r
1657     Rm_Inst         *rmInst = (Rm_Inst *) rmHandle;\r
1658     Rm_Allocator    *allocator = rmInst->allocators;\r
1659     Rm_Owner        *owners;\r
1660     Rm_ResourceTree *treeRoot;\r
1661     Rm_ResourceNode *treeNode;\r
1662 \r
1663     if (rmInst->instType == Rm_instType_SERVER) {\r
1664         while (allocator != NULL) {\r
1665             Rm_osalLog("Resource: %s\n", allocator->resourceName);\r
1666 \r
1667             treeRoot = allocator->allocatorRootEntry;\r
1668 \r
1669             RB_FOREACH(treeNode, _Rm_AllocatorResourceTree, treeRoot) {               \r
1670                 Rm_osalLog("          %10d - %10d ", treeNode->base, \r
1671                                                      treeNode->base + treeNode->length -1);\r
1672                 \r
1673                 if (treeNode->allocationCount == 0) {\r
1674                     Rm_osalLog("NOT ALLOCATED\n");\r
1675                 }\r
1676                 else {\r
1677                     owners = treeNode->ownerList;\r
1678                     Rm_osalLog("allocated to");\r
1679                     while (owners) {\r
1680                         Rm_osalLog(" %s", owners->instNameNode->name);\r
1681                         owners = owners->nextOwner;\r
1682                     }\r
1683                     Rm_osalLog("\n");\r
1684                 }\r
1685             }        \r
1686             allocator = allocator->nextAllocator;\r
1687         }\r
1688         rmNameServerPrintObjects(rmInst->nameServer);\r
1689     }\r
1690 }\r
1691 \r
1692 /**\r
1693  *  @b Description\r
1694  *  @n  \r
1695  *      This function initializes a RM instance.\r
1696  * \r
1697  *      IMPORTANT: Rm_init must be called prior to any other component startup\r
1698  *                 APIs (BIOS_start, Ipc_start, etc).\r
1699  *\r
1700  *  @param[in]  *initCfg\r
1701  *      Pointer to structure containing the initialization information for\r
1702  *      this RM instance.\r
1703  *\r
1704  *  @param[in]  *result\r
1705  *      Pointer to a uint32_t that will contain the result of the RM \r
1706  *      intialization and handle creation.  Any errors encountered will be \r
1707  *      returned via this pointer.\r
1708  *\r
1709  *  @retval\r
1710  *      Success - non-zero Rm_Handle returned.\r
1711  *  @retval\r
1712  *      Failure - NULL Rm_handle returned.\r
1713  */\r
1714 Rm_Handle Rm_init(Rm_InitCfg *initCfg, int32_t *result)\r
1715 {\r
1716     Rm_Inst *rmInst;\r
1717     void    *globalResourceDtb = NULL;\r
1718     void    *linuxResourceDtb = NULL;\r
1719     bool     addLinux = false;\r
1720 \r
1721     *result = RM_OK;\r
1722     \r
1723     if ((initCfg->instName == NULL) ||\r
1724         ((strlen(initCfg->instName) + 1) > RM_NAME_MAX_CHARS)) {\r
1725         *result = RM_ERROR_INVALID_INST_NAME;\r
1726         return (NULL);\r
1727     }\r
1728 \r
1729     if (initCfg->instType >= Rm_instType_LAST) {\r
1730         *result = RM_ERROR_INVALID_INST_TYPE;\r
1731     }\r
1732 \r
1733     /* Create and initialize instance */\r
1734     rmInst = Rm_osalMalloc (sizeof(Rm_Inst));\r
1735     memset ((void *) rmInst, 0, sizeof(Rm_Inst));\r
1736     rmInst->isLocked = false;\r
1737     rmInst->registeredWithDelegateOrServer = false;\r
1738     rmInst->transactionSeqNum = rmTransactionInitSequenceNum();\r
1739 \r
1740     rmInst->instType = initCfg->instType;    \r
1741     strncpy (rmInst->instName, initCfg->instName, RM_NAME_MAX_CHARS);\r
1742 \r
1743     if (rmInst->instType == Rm_instType_SERVER) {\r
1744         if (!initCfg->instCfg.serverCfg.globalResourceList ||\r
1745             !initCfg->instCfg.serverCfg.globalPolicy) {\r
1746             *result = RM_ERROR_INVALID_SERVER_CONFIGURATION;\r
1747             return(NULL);\r
1748         }\r
1749 \r
1750         rmInst->policy = initCfg->instCfg.serverCfg.globalPolicy;\r
1751         fdt_open_into(rmInst->policy, rmInst->policy, fdt_totalsize(rmInst->policy)); \r
1752 \r
1753         if (initCfg->instCfg.serverCfg.linuxDtb) {\r
1754             linuxResourceDtb = initCfg->instCfg.serverCfg.linuxDtb;\r
1755             fdt_open_into(linuxResourceDtb, linuxResourceDtb, fdt_totalsize(linuxResourceDtb));\r
1756             addLinux = true;\r
1757         }\r
1758 \r
1759         /* Create valid instance list from policy.  Must be done prior to parsing\r
1760          * GRL so that Linux resources can be reserved correctly */\r
1761         rmInst->validInstances = rmPolicyCreateValidInstTree(rmInst->policy, addLinux, result);\r
1762         /* Validate policy assignment strings */\r
1763         *result = rmPolicyValidatePolicy(rmInst->policy, rmInst->validInstances);  \r
1764 \r
1765         rmInst->nameServer = rmNameServerInit();\r
1766 \r
1767         globalResourceDtb = initCfg->instCfg.serverCfg.globalResourceList;\r
1768         fdt_open_into(globalResourceDtb, globalResourceDtb, fdt_totalsize(globalResourceDtb));\r
1769 \r
1770         rmInitializeAllocators(rmInst, globalResourceDtb, linuxResourceDtb);  \r
1771 \r
1772         if ((*result = rmPolicyValidatePolicyResourceNames(rmInst->policy, (void *)rmInst->allocators)) !=\r
1773             RM_OK) {\r
1774             return(NULL);\r
1775         }\r
1776     }\r
1777 \r
1778     if ((rmInst->instType == Rm_instType_CLIENT) && \r
1779         (initCfg->instCfg.clientCfg.staticPolicy)) {\r
1780         rmInst->staticInfo.staticPolicy = initCfg->instCfg.clientCfg.staticPolicy; \r
1781     }\r
1782     else if ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
1783              (initCfg->instCfg.cdCfg.staticPolicy)) { \r
1784         rmInst->staticInfo.staticPolicy = initCfg->instCfg.cdCfg.staticPolicy; \r
1785     }\r
1786     if (rmInst->staticInfo.staticPolicy) {\r
1787         fdt_open_into(rmInst->staticInfo.staticPolicy, rmInst->staticInfo.staticPolicy, \r
1788                       fdt_totalsize(rmInst->staticInfo.staticPolicy));       \r
1789         rmInst->staticInfo.staticValidInstTree = rmPolicyCreateValidInstTree(rmInst->staticInfo.staticPolicy, \r
1790                                                                              addLinux, result);        \r
1791         if (*result == RM_OK) {\r
1792             /* Validate policy assignment strings */\r
1793             *result = rmPolicyValidatePolicy(rmInst->staticInfo.staticPolicy, rmInst->staticInfo.staticValidInstTree);\r
1794         }\r
1795         if (*result != RM_OK) {\r
1796             if (rmInst->staticInfo.staticValidInstTree) {\r
1797                 rmPolicyFreeValidInstTree(rmInst->staticInfo.staticValidInstTree);\r
1798             }\r
1799             Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));\r
1800             rmInst = NULL;\r
1801         }\r
1802     }\r
1803     return ((Rm_Handle) rmInst);\r
1804 }\r
1805 \r
1806 /**\r
1807  *  @b Description\r
1808  *  @n  \r
1809  *      The function is used to get the version information of the RM.\r
1810  *\r
1811  *  @retval\r
1812  *      Version Information.\r
1813  */\r
1814 uint32_t Rm_getVersion (void)\r
1815 {\r
1816     return RM_VERSION_ID;\r
1817 }\r
1818 \r
1819 /**\r
1820  *  @b Description\r
1821  *  @n  \r
1822  *      The function is used to get the version string for the RM.\r
1823  *\r
1824  *  @retval\r
1825  *      Version String.\r
1826  */\r
1827 const char* Rm_getVersionStr (void)\r
1828 {\r
1829     return rmVersionStr;\r
1830 }\r
1831 \r