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