]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/rm-lld.git/blob - src/rm_allocator.c
Added allocator delete and RM instance delete APIs
[keystone-rtos/rm-lld.git] / src / rm_allocator.c
1 /**
2  *   @file  rm_allocator.c
3  *
4  *   @brief   
5  *      This is the Resource Manager allocator source.
6  *
7  *  \par
8  *  ============================================================================
9  *  @n   (C) Copyright 2012-2013, Texas Instruments, Inc.
10  * 
11  *  Redistribution and use in source and binary forms, with or without 
12  *  modification, are permitted provided that the following conditions 
13  *  are met:
14  *
15  *    Redistributions of source code must retain the above copyright 
16  *    notice, this list of conditions and the following disclaimer.
17  *
18  *    Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the 
20  *    documentation and/or other materials provided with the   
21  *    distribution.
22  *
23  *    Neither the name of Texas Instruments Incorporated nor the names of
24  *    its contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
28  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
29  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
31  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
32  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
33  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
36  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
37  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38  *
39  *  \par
40 */
42 /* RM external includes */
43 #include <ti/drv/rm/rm.h>
45 /* RM internal includes */
46 #include <ti/drv/rm/include/rm_loc.h>
47 #include <ti/drv/rm/include/rm_allocatorloc.h>
48 #include <ti/drv/rm/include/rm_dtb_utilloc.h>
49 #include <ti/drv/rm/include/rm_policyloc.h>
50 #include <ti/drv/rm/include/rm_treeloc.h>
52 /* RM LIBFDT includes */
53 #include <ti/drv/rm/util/libfdt/libfdt.h>
55 /* Tree algorithm includes */
56 #include <ti/drv/rm/util/tree.h>
58 /* RM OSAL layer */
59 #include <rm_osal.h>
61 /**********************************************************************
62  ************************ Local Functions *****************************
63  **********************************************************************/
65 /* FUNCTION PURPOSE: Creates a resource allocator
66  ***********************************************************************
67  * DESCRIPTION: Returns a newly Created and initialized resource
68  *              The allocator is also stored in the RM instance
69  *              allocator list.            
70  */
71 static Rm_Allocator *allocatorAdd(Rm_Handle rmHandle, const char *resourceName)
72 {
73     Rm_Inst      *rmInst = (Rm_Inst *)rmHandle;
74     Rm_Allocator *allocators   = rmInst->u.server.allocators;
75     Rm_Allocator *newAllocator = NULL;
77     newAllocator = Rm_osalMalloc(sizeof(Rm_Allocator));
79     if (newAllocator) {
80         memset((void *)newAllocator, 0, sizeof(Rm_Allocator));
81         strncpy(newAllocator->resourceName, resourceName, RM_NAME_MAX_CHARS);
82         newAllocator->allocatorRootEntry = NULL;
83         newAllocator->nextAllocator = NULL;  
85         /* Add allocator to end of list */
86         if (allocators) {
87             while (allocators->nextAllocator) {
88                 allocators = allocators->nextAllocator;
89             }
90             allocators->nextAllocator = newAllocator;
91         }
92         else {
93             rmInst->u.server.allocators = newAllocator;
94         }
95     }
96     return (newAllocator);
97 }
99 /* FUNCTION PURPOSE: Deletes a resource allocator
100  ***********************************************************************
101  * DESCRIPTION: Deletes a resource allocator based on the given
102  *              resource name.  The resource allocator will be
103  *              removed from the RM instance allocator list.
104  */
105 static int32_t allocatorDelete(Rm_Handle rmHandle, char *resourceName)
107     Rm_Inst      *rmInst = (Rm_Inst *)rmHandle;    
108     Rm_Allocator *allocator = rmInst->u.server.allocators;
109     Rm_Allocator *prevAllocator = NULL;
110     int32_t       retVal = RM_OK;
112     while (allocator) {
113         if (strncmp(allocator->resourceName, resourceName, RM_NAME_MAX_CHARS) == 0) {
114             break;             
115         }
116         prevAllocator = allocator;
117         allocator = allocator->nextAllocator;
118     }
120     if (allocator) {
121         if (prevAllocator == NULL) {
122             rmInst->u.server.allocators = allocator->nextAllocator;
123         }
124         else {
125             prevAllocator->nextAllocator = allocator->nextAllocator;
126         }
127         Rm_osalFree((void *)allocator, sizeof(Rm_Allocator));
128     }
129     else {
130         retVal = RM_ERROR_RES_ALLOCATOR_DOES_NOT_EXIST;
131     }
132     return (retVal);
135 /* FUNCTION PURPOSE: Creates a new resource tree
136  ***********************************************************************
137  * DESCRIPTION: Creates and populates a new resource tree allocator
138  *              using the provided resource name and value range.  The
139  *              name and value originate from the GRL.
140  */
141 static int32_t allocatorCreate(Rm_Handle rmHandle, const char *resourceName, Rm_ResourceRange *range)
143     Rm_Allocator    *allocator = NULL;
144     Rm_ResourceTree *treeRootEntry = NULL;
145     Rm_ResourceNode *treeNode = NULL;
146     Rm_ResourceNode *collidingNode = NULL;
148     allocator = allocatorAdd(rmHandle, resourceName);
149     treeRootEntry = Rm_osalMalloc(sizeof(Rm_ResourceTree));
150     RB_INIT(treeRootEntry);
152     while (range != NULL) {
153         treeNode = rmResourceNodeNew(range->base, range->length);
154         collidingNode = RB_INSERT(_Rm_AllocatorResourceTree, treeRootEntry, treeNode);
156         if (collidingNode) {
157             Rm_ResourceNode *nextNode = NULL;
158             
159             /* Node that was inserted collides with existing node.  Destroy tree and return error */
160             for (treeNode = RB_MIN(_Rm_AllocatorResourceTree, treeRootEntry); treeNode != NULL; treeNode = nextNode) {
161                         nextNode = RB_NEXT(_Rm_AllocatorResourceTree, treeRootEntry, treeNode);
162                         RB_REMOVE(_Rm_AllocatorResourceTree, treeRootEntry, nextNode);
163                 rmResourceNodeFree(treeNode);
164                 }
165             Rm_osalFree((void *)treeRootEntry, sizeof(Rm_ResourceTree));
166             allocatorDelete(rmHandle, allocator->resourceName);
167             return (RM_ERROR_GRL_RES_SPECIFIED_MORE_THAN_ONCE);
168         }
169         range = range->nextRange;
170     }
171     
172     allocator->allocatorRootEntry = treeRootEntry;
173     return(RM_OK);
176 /* FUNCTION PURPOSE: Adds an owner to an allocator resource
177  ***********************************************************************
178  * DESCRIPTION: Adds a RM instance node to a resource node's
179  *              list of owners.
180  */
181 static void allocatorResNodeOwnerAdd(Rm_ResourceNode *node, void *serviceInstNode)
183     Rm_Owner *ownerList = node->ownerList;
184     Rm_Owner *newOwner = NULL;
186     newOwner = Rm_osalMalloc(sizeof(Rm_Owner));
188     if (newOwner) {
189         newOwner->instNameNode = serviceInstNode;
190         newOwner->nextOwner = NULL;  
192         /* Add owner entry to end of list */
193         if (ownerList) {
194             while (ownerList->nextOwner) {
195                 ownerList = ownerList->nextOwner;
196             }
197             ownerList->nextOwner = newOwner;
198         }
199         else {
200             node->ownerList = newOwner;
201         }
203         node->allocationCount++;
204         newOwner->instNameNode->allocRefCount++;
205     }
208 /* FUNCTION PURPOSE: Compares two resource node's owners
209  ***********************************************************************
210  * DESCRIPTION: Returns TRUE if the owners of two resource nodes 
211  *              are equivalent.  Otherwise, returns FALSE.
212  */
213 static bool allocatorResNodeOwnerCompare(Rm_ResourceNode *node1, Rm_ResourceNode *node2)
215     Rm_Owner *node1Owners = node1->ownerList;
216     Rm_Owner *node2Owners = node2->ownerList;
217     bool      matchedInst;
219     if (node1->allocationCount == node2->allocationCount) {
220         while (node1Owners) {
221             matchedInst = false;
222             while (node2Owners) {
223                 if (node1Owners->instNameNode == node2Owners->instNameNode) {
224                     matchedInst = true;
225                     break;
226                 }
227                 node2Owners = node2Owners->nextOwner;
228             }
230             if (matchedInst) {
231                 node2Owners = node2->ownerList;
232                 node1Owners = node1Owners->nextOwner;
233             }
234             else {
235                 return(false);
236             }                
237         }
238     }
239     else {
240         return(false);
241     }  
242     
243     return(true);
246 /* FUNCTION PURPOSE: Deletes an owner from an allocator resource
247  ***********************************************************************
248  * DESCRIPTION: Removes a RM instance node from a resource node's
249  *              list of owners.
250  */
251 static void allocatorResNodeOwnerDelete(Rm_ResourceNode *node, void *serviceInstNode)
253     Rm_Owner *owner = node->ownerList;
254     Rm_Owner *prevOwner = NULL;
256     while (owner) {
257         if (owner->instNameNode == serviceInstNode) {
258             break;             
259         }
260         prevOwner = owner;
261         owner = owner->nextOwner;
262     }
264     if (prevOwner == NULL) {
265         node->ownerList = owner->nextOwner;
266     }
267     else {
268         prevOwner->nextOwner = owner->nextOwner;
269     }
270     
271     node->allocationCount--;
272     owner->instNameNode->allocRefCount--;
273     Rm_osalFree((void *)owner, sizeof(Rm_Owner));
276 /* FUNCTION PURPOSE: Copies the owners of a resource node
277  ***********************************************************************
278  * DESCRIPTION: Creates a list of resource owners for the destination
279  *              resource node that is equivalent to the the 
280  *              source resource node's owners
281  */
282 static void allocatorResNodeOwnerCopy(Rm_ResourceNode *dstNode, Rm_ResourceNode *srcNode)
284     Rm_Owner *srcOwnerList = srcNode->ownerList;
285     Rm_Owner *dstNewOwner;
286     Rm_Owner *dstPrevOwner;
288     dstNode->allocationCount = srcNode->allocationCount;
290     while (srcOwnerList) {
291         dstNewOwner = Rm_osalMalloc(sizeof(Rm_Owner));
292         dstNewOwner->instNameNode = srcOwnerList->instNameNode;
293         dstNewOwner->nextOwner = NULL;
295         if (dstNode->ownerList == NULL) {
296             dstNode->ownerList = dstNewOwner;
297         }
298         else {
299             dstPrevOwner->nextOwner = dstNewOwner;
300         }
301         dstPrevOwner = dstNewOwner;
302         srcOwnerList = srcOwnerList->nextOwner;
303     }
306 /* FUNCTION PURPOSE: Clears a resource node's owners
307  ***********************************************************************
308  * DESCRIPTION: Deletes all owners from the owners list of a 
309  *              resource node.
310  */
311 static void allocatorResNodeOwnerClear(Rm_ResourceNode *node)
313     Rm_Owner *owner = node->ownerList;
314     Rm_Owner *nextOwner;
316     while (owner) {
317         nextOwner = owner->nextOwner;
318         node->allocationCount--;
319         owner->instNameNode->allocRefCount--;
320         Rm_osalFree((void *)owner, sizeof(Rm_Owner));
321         owner = nextOwner;
322     }
325 /* FUNCTION PURPOSE: Checks a resource node's ownership
326  ***********************************************************************
327  * DESCRIPTION: Returns TRUE if the provided instance node is
328  *              in the list of resource node owners.  Otherwise,
329  *              returns FALSE.
330  */
331 static bool allocatorResNodeIsOwnedBy(Rm_ResourceNode *node, void *serviceInstNode)
333     Rm_Owner *owner = node->ownerList;
335     while (owner) {
336         if (owner->instNameNode == serviceInstNode) {
337             return(true);           
338         }
339         owner = owner->nextOwner;
340     }
341     return(false);
344 /* FUNCTION PURPOSE: Preallocates an allocator resource
345  ***********************************************************************
346  * DESCRIPTION: Called when an allocate request is made but the base 
347  *              is unspecified.  The preallocation algorithm looks at 
348  *              available resources as well as policy permissions to 
349  *              determine a resource range that satisfies the request.
350  *              If a valid range is found it will be returned for the 
351  *              treeAllocate algorithm to handle.
352  */
353 static int32_t allocatorPreAllocate(Rm_Handle rmHandle, Rm_Allocator *allocator, int32_t resourcePolicy, 
354                                     Rm_AllocatorOpInfo *opInfo)
356     Rm_Inst           *rmInst = (Rm_Inst *)rmHandle;    
357     Rm_ResourceNode    findNode;
358     Rm_ResourceNode   *matchingNode = NULL;
359     uint32_t           matchingEnd;
360     uint32_t           rangeIndex;
361     bool               resourceFound = false;
362     Rm_PolicyCheckType policyCheckType;
363     Rm_PolicyCheckCfg  policyCheckCfg;
364     bool               nodePassesPolicy;
365     int32_t            retVal = RM_SERVICE_PROCESSING;    
367     opInfo->resourceInfo->base = rmPolicyGetResourceBase(opInfo->policy, opInfo->serviceSrcInstNode, 
368                                                          resourcePolicy, opInfo->allocType, 
369                                                          &retVal);
370     if (retVal != RM_SERVICE_PROCESSING) {
371         return (retVal);
372     }
374     if (opInfo->resourceInfo->alignment == RM_RESOURCE_ALIGNMENT_UNSPECIFIED) {  
375         /* Get alignment from policy */
376         opInfo->resourceInfo->alignment = rmPolicyGetResourceAlignment(opInfo->policy, resourcePolicy);
377     }
378     
379     if (opInfo->resourceInfo->alignment == 0) {
380         opInfo->resourceInfo->alignment = 1;
381     }    
383     memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));
384     findNode.base = opInfo->resourceInfo->base;
385     findNode.length = opInfo->resourceInfo->length;
387     /* Configure policy checking structure */
388     memset((void *)&policyCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));
389     if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_INIT_SHIFT)) {
390         policyCheckType = Rm_policyCheck_INIT;
391     }
392     else if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_USE_SHIFT)) {
393         policyCheckType = Rm_policyCheck_USE;
394     }
395     policyCheckCfg.policyDtb = opInfo->policy;
396     policyCheckCfg.resourceOffset = resourcePolicy;
397     
398     do {
399         matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
400         
401         if (matchingNode) {
402             if (!allocatorResNodeIsOwnedBy(matchingNode, opInfo->serviceSrcInstNode)) {
403                 /* Attempt to preallocate from node only if not owned by instance requesting the allocation */
404                 nodePassesPolicy = false;
405                 policyCheckCfg.type = policyCheckType;
406                 policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
407                 policyCheckCfg.resourceBase = findNode.base;
408                 policyCheckCfg.resourceLength = findNode.length;
409                 nodePassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);    
410                 
411                 if (nodePassesPolicy && (matchingNode->allocationCount > 0)) {
412                     policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
413                     
414                     if (allocatorResNodeIsOwnedBy(matchingNode, rmPolicyGetLinuxInstNode(rmInst->u.server.globalValidInstTree))) {
415                         /* Check if instance requesting resource has privileges to share
416                          * a resource already reserved by Linux */
417                         policyCheckCfg.type = Rm_policyCheck_SHARED_LINUX;
418                         nodePassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
419                     }
421                     if (nodePassesPolicy) {
422                         /* Check exclusive privileges of instance requesting resource.  Requesting
423                          * instance with exclusive privileges can't reserve resource if already owned*/
424                         policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;
425                         nodePassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
426                     }
427                 }
428                 
429                 if (nodePassesPolicy && (matchingNode->allocationCount == 1)) {
430                     /* Check exclusive privileges of instance that currently owns resource */
431                     policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;
432                     policyCheckCfg.validInstNode = matchingNode->ownerList->instNameNode;
433                     nodePassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
434                 }
436                 if (retVal != RM_SERVICE_PROCESSING) {
437                     break;
438                 }
440                 if (nodePassesPolicy) {
441                     matchingEnd = matchingNode->base + matchingNode->length - 1;
442                     /* Initialize indexer to be first resource value that alignment */
443                     rangeIndex = findNode.base;
444                     if (rangeIndex % opInfo->resourceInfo->alignment) {
445                         rangeIndex += (opInfo->resourceInfo->alignment -
446                                       (rangeIndex % opInfo->resourceInfo->alignment));
447                     }
448                     
449                     if ((rangeIndex + opInfo->resourceInfo->length - 1) <= matchingEnd) {
450                         /* Block of unallocated resources within matchingNode that satisfies
451                          * allocate requirements */
452                         opInfo->resourceInfo->base = rangeIndex;
453                         resourceFound = true;
454                     }     
455                 }
456             }
457             
458             if (!resourceFound) {
459                 /* Check next resource node for available resources */
460                 findNode.base = matchingNode->base + matchingNode->length;
461             }
462         }
463         else {
464             retVal = RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET;
465         }
466     } while ((!resourceFound) && 
467              (retVal != RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET));
469     return(retVal); 
472 /* FUNCTION PURPOSE: Allocates an allocator resource
473  ***********************************************************************
474  * DESCRIPTION: Will attempt to allocate the resource with specified
475  *              base and length from the resource's allocator.  The
476  *              allocation algorithm will verify the allocation against
477  *              the policy permissions for the instance requesting the
478  *              allocation.  If the policy allows the allocation the 
479  *              algorithm will allocate the resource then combine any
480  *              resource nodes that may have become equivalent (in terms
481  *              of ownership) after the allocation.
482  */
483 static int32_t allocatorAllocate(Rm_Handle rmHandle, Rm_Allocator *allocator, int32_t resourcePolicy, 
484                                  Rm_AllocatorOpInfo *opInfo)
486     Rm_Inst            *rmInst = (Rm_Inst *)rmHandle;
487     Rm_ResourceNode     findNode;
488     Rm_ResourceNode    *matchingNode = NULL;
489     Rm_ResourceNode    *leftNode = NULL;
490     Rm_ResourceNode    *rightNode = NULL;
491     Rm_PolicyCheckType  policyCheckType;    
492     Rm_PolicyCheckCfg   policyCheckCfg;
493     bool                allocPassesPolicy;
494     bool                combineLeft = false;
495     bool                combineRight = false;    
496     uint32_t            findEnd;
497     uint32_t            matchingEnd;  
498     int32_t             retVal = RM_SERVICE_PROCESSING;
500     memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));
501     findNode.base = opInfo->resourceInfo->base;
502     findNode.length = opInfo->resourceInfo->length;
503     matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
505     /* Prepare privilege checks */
506     memset((void *)&policyCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));
507     if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_INIT_SHIFT)) {
508         policyCheckType = Rm_policyCheck_INIT;
509     }
510     else if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_USE_SHIFT)) {
511         policyCheckType = Rm_policyCheck_USE;
512     }
514     if (matchingNode) {
515         findEnd = findNode.base + findNode.length - 1;
516         matchingEnd = matchingNode->base + matchingNode->length - 1;
517         
518         if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {
519             if (opInfo->serviceSrcInstNode == rmPolicyGetLinuxInstNode(rmInst->u.server.globalValidInstTree)) {
520                 /* Bypass policy checks since Linux Kernel has full privileges */
521                 allocPassesPolicy = true;
522             }
523             else {
524                 policyCheckCfg.policyDtb = opInfo->policy;
525                 policyCheckCfg.resourceOffset = resourcePolicy;    
526                 policyCheckCfg.type = policyCheckType;
527                 policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
528                 policyCheckCfg.resourceBase = findNode.base;
529                 policyCheckCfg.resourceLength = findNode.length;
530                 allocPassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
531                 if (!allocPassesPolicy) {
532                     if (policyCheckType == Rm_policyCheck_INIT) {
533                         retVal = RM_SERVICE_DENIED_INIT_PERM_NOT_GIVEN;
534                     }
535                     else {
536                         retVal = RM_SERVICE_DENIED_USE_PERM_NOT_GIVEN;
537                     }
538                 }
540                 if (!allocatorResNodeIsOwnedBy(matchingNode, opInfo->serviceSrcInstNode)) {
541                     if (allocPassesPolicy && (matchingNode->allocationCount > 0)) {
542                         if (allocatorResNodeIsOwnedBy(matchingNode, rmPolicyGetLinuxInstNode(rmInst->u.server.globalValidInstTree))) {
543                             /* Check if instance requesting resource has privileges to share
544                              * a resource already reserved by Linux */
545                             policyCheckCfg.type = Rm_policyCheck_SHARED_LINUX;
546                             policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
547                             allocPassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
548                             if (!allocPassesPolicy) {
549                                 retVal = RM_SERVICE_DENIED_RES_NOT_SHARED_LINUX;
550                             }
551                         }
552                         if (allocPassesPolicy) {
553                             /* Check exclusive privileges of instance requesting resource.  Requesting
554                              * instance with exclusive privileges can't reserve resource if already owned*/
555                             policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;
556                             policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
557                             allocPassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
558                             if (!allocPassesPolicy) {
559                                 retVal = RM_SERVICE_DENIED_EXCLUSIVE_RES_ALLOCD;
560                             }
561                         }
562                     }
563                     if (allocPassesPolicy && (matchingNode->allocationCount == 1)) {
564                         /* Check exclusive privileges of instance that currently owns resource */
565                         policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;
566                         policyCheckCfg.validInstNode = matchingNode->ownerList->instNameNode;
567                         allocPassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
568                         if (!allocPassesPolicy) {
569                             retVal = RM_SERVICE_DENIED_ALLOCD_TO_EXCLUSIVE_INST;
570                         }                
571                     }  
572                 }
573             }
574             
575             if (allocPassesPolicy) {
576                 if (!allocatorResNodeIsOwnedBy(matchingNode, opInfo->serviceSrcInstNode)) {
577                     /* Handle any possible node combinations if requesting instance is
578                      * not already in resource's owner list.  Automatic approval if requesting
579                      * instance is already in owner list. */
580                     if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd)) {
581                         /* findNode range matches matchingNode range
582                          *
583                          *   |<--left node-->||<--matched  node-->||<--right node-->| => existing node
584                          *                    |<--alloc request-->|  => requested resources
585                          */                     
586                         leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
587                         rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
588                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
589                         allocatorResNodeOwnerAdd(matchingNode, opInfo->serviceSrcInstNode);
591                         if (leftNode && allocatorResNodeOwnerCompare(leftNode, matchingNode)) {
592                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
593                             combineLeft = true;
594                         }
595                         if (rightNode && allocatorResNodeOwnerCompare(rightNode, matchingNode)) {
596                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
597                             combineRight = true;
598                         }
600                         if (combineLeft && combineRight) {
601                             /* Combine all three nodes into matchingNode */
602                             matchingNode->base = leftNode->base;
603                             matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;
605                             allocatorResNodeOwnerClear(leftNode);
606                             rmResourceNodeFree(leftNode);
607                             allocatorResNodeOwnerClear(rightNode);
608                             rmResourceNodeFree(rightNode);                        
609                         }
610                         else if (combineLeft) {
611                             /* Combine left and matching nodes.  Reinsert right. */
612                             matchingNode->base = leftNode->base;
613                             matchingNode->length += leftNode->length;
615                             allocatorResNodeOwnerClear(leftNode);
616                             rmResourceNodeFree(leftNode);
617                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);                        
618                         }
619                         else if (combineRight) {
620                             /* Combine right and matching nodes.  Reinsert left. */
621                             matchingNode->length += rightNode->length;
623                             allocatorResNodeOwnerClear(rightNode);
624                             rmResourceNodeFree(rightNode);
625                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
626                         }
627                         else {
628                             /* No combine. */
629                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
630                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
631                         }
633                         /* Always reinsert matchingNode */                
634                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);   
635                     }   
636                     else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {
637                         /* findNode range is subset of matchingNode range and neither boundary is
638                          * equivalent.
639                          *
640                          * |<----------matched node---------->|
641                          *        |<---alloc request--->|
642                          */ 
643                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
644                         leftNode = rmResourceNodeNew(matchingNode->base, findNode.base - matchingNode->base);
645                         allocatorResNodeOwnerCopy(leftNode, matchingNode);
646                         rightNode = rmResourceNodeNew(findNode.base + findNode.length, matchingEnd - findEnd);
647                         allocatorResNodeOwnerCopy(rightNode, matchingNode);
649                         matchingNode->base = findNode.base;                                    
650                         matchingNode->length = findNode.length;
651                         allocatorResNodeOwnerAdd(matchingNode, opInfo->serviceSrcInstNode);
653                         /* Insert all the nodes */
654                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
655                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
656                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
657                     }  
658                     else {    
659                         if (findNode.base == matchingNode->base) {
660                             /* findNode base and matchingNode base are equivalent.  May be combine
661                              * possibilities to the left
662                              *
663                              * |<---left node (alloc'd)--->||<----------matched node---------->|
664                              *                              |<---findNode (alloc req)--->|
665                              */                         
666                             leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
667                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
668                             /* Add allocating instance to owner list for compare with leftNode */
669                             allocatorResNodeOwnerAdd(matchingNode, opInfo->serviceSrcInstNode);
670                             
671                             if (leftNode && allocatorResNodeOwnerCompare(leftNode, matchingNode)) {
672                                 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
673                                 /* Combine leftNode and findNode */
674                                 leftNode->length += findNode.length;
675                             }
676                             else {
677                                 leftNode = rmResourceNodeNew(findNode.base, findNode.length);
678                                 allocatorResNodeOwnerCopy(leftNode, matchingNode);
679                             }
681                             /* Account for leftNode in matchingNode */
682                             matchingNode->base = findNode.base + findNode.length;
683                             matchingNode->length = matchingEnd - findEnd;  
685                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
686                         }
687                         else if (findEnd == matchingEnd) {
688                             /* findNode end and matchingNode end are equivalent.  May be combine
689                              * possibilities to the right
690                              *
691                              * |<----------matched node---------->||<---right node (alloc'd)--->|
692                              *       |<---findNode (alloc req)--->| 
693                              */                        
694                             rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
695                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
696                             /* Add allocating instance to owner list for compare with rightNode */
697                             allocatorResNodeOwnerAdd(matchingNode, opInfo->serviceSrcInstNode);
698                             
699                             if (rightNode && allocatorResNodeOwnerCompare(rightNode, matchingNode)) {
700                                 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
701                                 /* Combine rightNode and findNode */
702                                 rightNode->base = findNode.base;
703                                 rightNode->length += findNode.length;
704                             }
705                             else {
706                                 rightNode = rmResourceNodeNew(findNode.base, findNode.length);
707                                 allocatorResNodeOwnerCopy(rightNode, matchingNode);
708                             }
710                             /* Account for rightNode in matchingNode */
711                             matchingNode->length -= findNode.length;  
713                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
714                         }
715                         /* Remove allocating instance from leftover matchingNode */
716                         allocatorResNodeOwnerDelete(matchingNode, opInfo->serviceSrcInstNode);
717                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
718                     }
719                 }
720                 retVal = RM_SERVICE_APPROVED;
721             }
722         }
723         else {
724             retVal = RM_SERVICE_DENIED_PARTIAL_ALLOCATION;
725         }
726     }
727     else {
728         retVal = RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST;
729     }
731     return(retVal);        
734 /* FUNCTION PURPOSE: Frees an allocator resource
735  ***********************************************************************
736  * DESCRIPTION: Will attempt to free the resource with specified
737  *              base and length from the resource's allocator.  The
738  *              free algorithm will verify the free request parameters
739  *              match an allocated range for the resource and that the
740  *              range is owned by the instance requesting the free. If
741  *              the free is validated the algorithm will free the 
742  *              resource then combine any resource nodes that may have
743  *              become equivalent (in terms of ownership) after the
744  *              allocation.
745  */
746 static int32_t allocatorFree(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)
748     Rm_ResourceNode  findNode;
749     Rm_ResourceNode *matchingNode = NULL;
750     Rm_ResourceNode *leftNode = NULL;
751     Rm_ResourceNode *rightNode = NULL;
752     bool             combineLeft = false;
753     bool             combineRight = false;
754     uint32_t         findEnd;
755     uint32_t         matchingEnd;
756     int32_t          retVal;
758     memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));
759     findNode.base = opInfo->resourceInfo->base;
760     findNode.length = opInfo->resourceInfo->length;
761     matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
763     if (matchingNode) {
764         findEnd = findNode.base + findNode.length - 1;
765         matchingEnd = matchingNode->base + matchingNode->length - 1;
766         
767         if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {  
768             if (matchingNode->allocationCount) {
769                 if (allocatorResNodeIsOwnedBy(matchingNode, opInfo->serviceSrcInstNode)) {
770                     if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd))
771                     {
772                         /* Case 1: Free range equals allocated matched node exactly. Attempt to combine 
773                          *         freed node with nodes to left and right.
774                          *
775                          * |<--left node-->||<---matched node--->||<--right node-->|
776                          *                  |<---free request--->|
777                          */ 
778                         leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
779                         rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
780                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
781                         allocatorResNodeOwnerDelete(matchingNode, opInfo->serviceSrcInstNode);
783                         if (leftNode && allocatorResNodeOwnerCompare(leftNode, matchingNode)) {
784                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
785                             combineLeft = true;
786                         }
787                         if (rightNode && allocatorResNodeOwnerCompare(rightNode, matchingNode)) {
788                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
789                             combineRight = true;
790                         }
792                         if (combineLeft && combineRight) {
793                             /* Combine all three nodes into matchingNode */
794                             matchingNode->base = leftNode->base;
795                             matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;
797                             allocatorResNodeOwnerClear(leftNode);
798                             rmResourceNodeFree(leftNode);
799                             allocatorResNodeOwnerClear(rightNode);
800                             rmResourceNodeFree(rightNode);                        
801                         }
802                         else if (combineLeft) {
803                             /* Combine left and matching nodes.  Reinsert right. */
804                             matchingNode->base = leftNode->base;
805                             matchingNode->length += leftNode->length;
807                             allocatorResNodeOwnerClear(leftNode);
808                             rmResourceNodeFree(leftNode);
809                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);                        
810                         }
811                         else if (combineRight) {
812                             /* Combine right and matching nodes.  Reinsert left. */
813                             matchingNode->length += rightNode->length;
815                             allocatorResNodeOwnerClear(rightNode);
816                             rmResourceNodeFree(rightNode);
817                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
818                         }
819                         else {
820                             /* No combine. */
821                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
822                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
823                         }
825                         /* Always reinsert matchingNode */
826                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);                    
827                     }
828                     else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {
829                         /* Case 2: Free range is less than range in matched node. Split
830                          *         matched node into three nodes.
831                          *
832                          * |<----------matched node---------->|
833                          *        |<---free request--->|
834                          *
835                          * Remove instance from AllocatedTo list then add it back in for side nodes for
836                          * proper accounting of allocations in validInstance list
837                          */ 
838                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
839                         allocatorResNodeOwnerDelete(matchingNode, opInfo->serviceSrcInstNode);
840                         
841                         leftNode = rmResourceNodeNew(matchingNode->base, findNode.base - matchingNode->base);
842                         allocatorResNodeOwnerCopy(leftNode, matchingNode);
843                         allocatorResNodeOwnerAdd(leftNode, opInfo->serviceSrcInstNode);
844                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
845                         
846                         rightNode = rmResourceNodeNew(findNode.base + findNode.length, matchingEnd - findEnd);
847                         allocatorResNodeOwnerCopy(rightNode, matchingNode);
848                         allocatorResNodeOwnerAdd(rightNode, opInfo->serviceSrcInstNode);
849                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
851                         matchingNode->base = findNode.base;                                    
852                         matchingNode->length = findNode.length;
853                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
854                     }
855                     else {                        
856                         if (findNode.base == matchingNode->base) {
857                             /* Case 3: Free range is on left boundary of matched node. Try to 
858                              *         combine free range with left node.
859                              *
860                              * |<---left node (free)--->||<----------matched node---------->|
861                              *                           |<---findNode (free req)--->|
862                              */ 
864                             leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
865                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
866                             /* Remove freeing instance from owner list for compare with leftNode */
867                             allocatorResNodeOwnerDelete(matchingNode, opInfo->serviceSrcInstNode);
868                             
869                             if (leftNode && allocatorResNodeOwnerCompare(leftNode, matchingNode)) {
870                                 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
871                                 /* Combine leftNode and findNode */
872                                 leftNode->length += findNode.length;
873                             }
874                             else {
875                                 leftNode = rmResourceNodeNew(findNode.base, findNode.length);
876                                 allocatorResNodeOwnerCopy(leftNode, matchingNode);
877                             }
879                             /* Remove leftNode range from matchingNode */
880                             matchingNode->base = findNode.base + findNode.length;
881                             matchingNode->length = matchingEnd - findEnd;  
882                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
883                         }
884                         else if (findEnd == matchingEnd) {
885                             /* Case 4: Free range is on right boundary of matched node. Try to 
886                              *         combine free range with right node.
887                              *
888                              * |<----------matched node---------->||<---right node (free)--->|
889                              *        |<---findNode (free req)--->|
890                              */ 
891                             
892                             rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
893                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode); 
894                             /* Remove freeing instance from owner list for compare with rightNode */
895                             allocatorResNodeOwnerDelete(matchingNode, opInfo->serviceSrcInstNode);
896                             
897                             if (rightNode && allocatorResNodeOwnerCompare(rightNode, matchingNode)) {
898                                 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
899                                 /* Combine rightNode and findNode */
900                                 rightNode->base = findNode.base;
901                                 rightNode->length += findNode.length;
902                             }
903                             else {
904                                 rightNode = rmResourceNodeNew(findNode.base, findNode.length);
905                                 allocatorResNodeOwnerCopy(rightNode, matchingNode);
906                             }
908                             /* Remove rightNode range from matchingNode */
909                             matchingNode->length -= findNode.length;  
910                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
911                         }
913                         /* Add freeing instance back into matchingNode allocations */
914                         allocatorResNodeOwnerAdd(matchingNode, opInfo->serviceSrcInstNode);
915                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
916                     }
918                     retVal = RM_SERVICE_APPROVED;
919                 }
920                 else {
921                     retVal = RM_SERVICE_DENIED_RES_NOT_ALLOCD_TO_INST;
922                 }
923             }
924             else {
925                 retVal = RM_SERVICE_DENIED_RES_ALREADY_FREE;
926             }
927         }
928         else {
929             retVal = RM_SERVICE_DENIED_PARTIAL_FREE;
930         }
931     }
932     else {
933         retVal = RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST;
934     }
935     return(retVal);  
938 /* FUNCTION PURPOSE: Reserves a Linux resource
939  ***********************************************************************
940  * DESCRIPTION: Reserves resources for Linux using the base and length
941  *              values retrieved from the Linux DTB via the
942  *              "linux-dtb-alias" properties within the GRL.
943  */
944 static int32_t allocatorReserveLinuxResource(Rm_Handle rmHandle, Rm_LinuxAlias *linuxAlias, 
945                                              Rm_LinuxValueRange *linuxValues, Rm_AllocatorOpInfo *opInfo)
947     int32_t   retVal = RM_OK;
948     bool      baseFound = false;
949     bool      lengthFound = false;
950     uint32_t  valueIndex = 0;
952     while ((linuxValues) && (!baseFound || !lengthFound)) {
953         if (linuxAlias->baseOffset == valueIndex) {
954             opInfo->resourceInfo->base = linuxValues->value;
955             baseFound = true;
957             if (linuxAlias->lengthOffset == RM_DTB_UTIL_LINUX_ALIAS_OFFSET_NOT_SET) {
958                 opInfo->resourceInfo->length = 1;
959                 lengthFound = true;
960             }
961         }
962         else if (linuxAlias->lengthOffset == valueIndex) {
963             opInfo->resourceInfo->length = linuxValues->value;
964             lengthFound = true;
965         }
967         linuxValues = (Rm_LinuxValueRange *)linuxValues->nextValue;
968         valueIndex++;
969     }
971     if (!baseFound || !lengthFound) {
972         retVal = RM_ERROR_DATA_NOT_FOUND_AT_LINUX_ALIAS;
973     }
974     else {
975         /* Allocate resource to Linux */
976         retVal = rmAllocatorOperation(rmHandle, opInfo);
977         if (retVal == RM_SERVICE_APPROVED) {
978             retVal = RM_OK;
979         }
980     }
981     return (retVal);
984 /* FUNCTION PURPOSE: Finds and reserves Linux resources
985  ***********************************************************************
986  * DESCRIPTION: Parses the Linux DTB for resources consumed by the
987  *              Linux kernel.  If the resource is found via the
988  *              "linux-dtb-alias" property defined in the GRL it is 
989  *              reserved.
990  */
991 static int32_t allocatorFindLinuxResource(Rm_Handle rmHandle, const char *resourceName, void *linuxDtb, 
992                                           Rm_LinuxAlias *linuxAlias)
994     Rm_Inst            *rmInst = (Rm_Inst *)rmHandle;
995     Rm_AllocatorOpInfo  opInfo;
996     Rm_ResourceInfo     resourceInfo;
997     uint32_t            pathOffset;
998     uint32_t            pathSize;
999     char               *spacePtr;
1000     int32_t             propOffset;
1001     int32_t             nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;
1002     int32_t             prevDepth = RM_DTB_UTIL_STARTING_DEPTH;
1003     int32_t             depth;
1004     int32_t             propertyLen;
1005     const char         *propertyName;
1006     const void         *propertyData; 
1007     Rm_LinuxValueRange *linuxValueRange;
1008     int32_t             retVal = RM_OK; 
1010     memset((void *) &opInfo, 0, sizeof(Rm_AllocatorOpInfo));
1011     memset((void *) &resourceInfo, 0, sizeof(Rm_ResourceInfo));
1013     strncpy(resourceInfo.name, resourceName, RM_NAME_MAX_CHARS);
1014     opInfo.policy = rmInst->u.server.globalPolicy;
1015     opInfo.serviceSrcInstNode = rmPolicyGetLinuxInstNode(rmInst->u.server.globalValidInstTree);
1016     opInfo.operation = Rm_allocatorOp_ALLOCATE;
1017     opInfo.resourceInfo = &resourceInfo;    
1019     while(linuxAlias) {
1020         /* Reset parsing variables */
1021         pathOffset = 0;
1022         pathSize = strlen(linuxAlias->path) + 1;
1023         nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;
1024         prevDepth = RM_DTB_UTIL_STARTING_DEPTH;   
1025         resourceInfo.base = 0;
1026         resourceInfo.length = 0;
1028         spacePtr = strpbrk(linuxAlias->path, " ");
1029         if (spacePtr) {
1030             *spacePtr = '\0';
1031         }       
1032         
1033         while(pathOffset < pathSize) {
1034             /* Move through DTB nodes until next alias path node found */
1035             if (strcmp(linuxAlias->path + pathOffset, fdt_get_name(linuxDtb, nodeOffset, NULL))) {
1036                 nodeOffset = fdt_next_node(linuxDtb, nodeOffset, &depth);
1038                 if ((depth < prevDepth) || (nodeOffset == -FDT_ERR_NOTFOUND)) {
1039                     /* Returning from subnode that matched part of alias path without finding
1040                      * resource values */
1041                     retVal = RM_ERROR_DATA_NOT_FOUND_AT_LINUX_ALIAS;
1042                     break;
1043                 }
1044             }
1045             else {
1046                 /* Found next alias path node.  Move to next node name in path string. */
1047                 pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);
1048                 spacePtr = strpbrk(linuxAlias->path + pathOffset, " ");
1049                 if (spacePtr) {
1050                     *spacePtr = '\0';
1051                 }       
1052                 
1053                 prevDepth = fdt_node_depth(linuxDtb, nodeOffset);
1054                 propOffset = fdt_first_property_offset(linuxDtb, nodeOffset);
1055                 while ((propOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) &&
1056                        (pathOffset < pathSize)) {
1057                     propertyData = fdt_getprop_by_offset(linuxDtb, propOffset, 
1058                                                          &propertyName, &propertyLen);
1060                     if (strcmp(linuxAlias->path + pathOffset, propertyName) == 0) {
1061                         /* Found resource at end of alias path */
1062                         pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);
1063                         linuxValueRange = rmDtbUtilLinuxExtractValues(propertyData, propertyLen);
1064                         retVal = allocatorReserveLinuxResource(rmHandle, linuxAlias, 
1065                                                                linuxValueRange, &opInfo);
1066                         rmDtbUtilLinuxFreeValues(linuxValueRange);
1067                     }
1068                     propOffset = fdt_next_property_offset(linuxDtb, propOffset);
1069                 } 
1071                 if (propOffset < -FDT_ERR_NOTFOUND) {
1072                     retVal = propOffset;
1073                     break;
1074                 }
1075             }
1076         }
1078         if (retVal < RM_OK) {
1079             break;
1080         }
1081         linuxAlias = linuxAlias->nextLinuxAlias;
1082     }
1083     return (retVal);
1086 /* FUNCTION PURPOSE: Creates and initializes a resource allocator
1087  ***********************************************************************
1088  * DESCRIPTION: Creates a resource allocator for the provided
1089  *              resource name and resource properties retrieved
1090  *              from the GRL.  Resources will be reserved for 
1091  *              the Linux kernel if the Linux DTB is provided
1092  *              and there are "linux-dtb-alias" properties
1093  *              specified in the GRL.
1094  */
1095 static int32_t allocatorExtractGrlResProps(Rm_Handle rmHandle, const char *resourceName, 
1096                                            Rm_ResourceProperties *resourceProperties, void *linuxDtb)
1098     Rm_Inst             *rmInst = (Rm_Inst *)rmHandle;
1099     Rm_ResourceRange    *range = NULL;
1100     Rm_ResourceRange    *rangeBasePtr = NULL;
1101     Rm_NsAssignment     *nsAssignments = NULL;
1102     Rm_NsAssignment     *nsAssignmentBasePtr = NULL;
1103     Rm_LinuxAlias       *linuxAlias = NULL;
1104     Rm_NameServerObjCfg  nameServerObjCfg;      
1105     int32_t              retVal = RM_OK;
1107     if (resourceProperties->rangeData && (resourceProperties->rangeLen > 0)) {
1108         range = rangeBasePtr = rmDtbUtilResExtractRange(resourceProperties->rangeData, 
1109                                                         resourceProperties->rangeLen);
1110         
1111         if ((retVal = allocatorCreate(rmHandle, resourceName, range)) >= RM_OK) {
1112             if (resourceProperties->linuxAliasData && resourceProperties->linuxAliasLen) {
1113                 if (linuxDtb) {
1114                     linuxAlias = rmDtbUtilResExtractLinuxAlias(resourceProperties->linuxAliasData,
1115                                                                resourceProperties->linuxAliasLen, &retVal);
1116                     if (linuxAlias) {
1117                         retVal = allocatorFindLinuxResource(rmHandle, resourceName, linuxDtb, linuxAlias);            
1118                     }
1119                 }
1120                 else {
1121                     retVal = RM_ERROR_GRL_LINUX_ALIAS_BUT_NO_DTB;
1122                 }
1123             }
1124         }
1125     }
1126     
1127     if (retVal >= RM_OK) {
1128         if (resourceProperties->nsAssignData && resourceProperties->nsAssignLen) {
1129             nsAssignments = rmDtbUtilResExtractNsAssignment(resourceProperties->nsAssignData, 
1130                                                             resourceProperties->nsAssignLen, &retVal);
1131             if (nsAssignments) {
1132                 nsAssignmentBasePtr = nsAssignments;
1133                 while (nsAssignments) {
1134                     memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
1135                     nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
1136                     nameServerObjCfg.nodeCfg.objName = nsAssignments->nsName;
1137                     nameServerObjCfg.nodeCfg.resourceName = (char *)resourceName;
1138                     nameServerObjCfg.nodeCfg.resourceBase= nsAssignments->resourceBase;
1139                     nameServerObjCfg.nodeCfg.resourceLength = nsAssignments->resourceLength;                
1140                     rmNameServerAddObject(&nameServerObjCfg);
1141                     nsAssignments = nsAssignments->nextNsAssignment;
1142                 }
1143                 rmDtbUtilResFreeNsAssignmentList(nsAssignmentBasePtr);
1144             }
1145         }
1146     }
1148     rmDtbUtilResFreeRange(rangeBasePtr);
1149     if (linuxAlias) {
1150         rmDtbUtilResFreeLinuxAlias(linuxAlias);
1151     }
1152     return(retVal);
1155 /**********************************************************************
1156  ********************** Internal Functions ****************************
1157  **********************************************************************/
1159 /* FUNCTION PURPOSE: Finds an allocator
1160  ***********************************************************************
1161  * DESCRIPTION: Returns a pointer to an allocator that matches the 
1162  *              provided resource name.
1163  */
1164 Rm_Allocator *rmAllocatorFind(Rm_Allocator *allocatorList, char *resourceName)
1166     while (allocatorList) {
1167         if (strncmp(allocatorList->resourceName, resourceName, RM_NAME_MAX_CHARS) == 0) {
1168             break;             
1169         }
1170         allocatorList = allocatorList->nextAllocator;
1171     }
1173     return (allocatorList);
1176 /* FUNCTION PURPOSE: Issues an allocator operation
1177  ***********************************************************************
1178  * DESCRIPTION: Issues an allocator preallocate, allocate, or free
1179  *              for an RM resource.
1180  */
1181 int32_t rmAllocatorOperation(Rm_Handle rmHandle, Rm_AllocatorOpInfo *opInfo)
1183     Rm_Inst      *rmInst = (Rm_Inst *)rmHandle;
1184     Rm_Allocator *allocator = NULL;
1185     int32_t       resourceOffsetInPolicy;
1186     int32_t       retVal;
1187     
1188     resourceOffsetInPolicy = rmPolicyGetResourceOffset(opInfo->policy, opInfo->resourceInfo->name);
1189     allocator = rmAllocatorFind(rmInst->u.server.allocators, opInfo->resourceInfo->name);
1190     
1191     if ((resourceOffsetInPolicy > 0) && allocator) {
1192         if (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE) {
1193             retVal = allocatorPreAllocate(rmHandle, allocator, resourceOffsetInPolicy, opInfo);
1194         }               
1195         else if (opInfo->operation == Rm_allocatorOp_ALLOCATE) {
1196             retVal = allocatorAllocate(rmHandle, allocator, resourceOffsetInPolicy, opInfo);
1197         }
1198         else if (opInfo->operation == Rm_allocatorOp_FREE) {
1199             retVal = allocatorFree(allocator, opInfo);
1200         }         
1201     }
1202     else {
1203         /* Resource could not be found in policy and/or allocator */
1204         retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;
1205     }
1206     return(retVal);
1209 /* FUNCTION PURPOSE: Initializes server allocators
1210  ***********************************************************************
1211  * DESCRIPTION: Creates and initializes a server instance's
1212  *              resource allocators using the GRL and, if
1213  *              provided, Linux DTB.
1214  */
1215 int32_t rmAllocatorInitializeResources(Rm_Handle rmHandle, void *globalResourceDtb, void *linuxDtb)
1217     int32_t                nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;
1218     int32_t                nodeDepth = RM_DTB_UTIL_STARTING_DEPTH;
1219     Rm_ResourceProperties  resProperties;    
1220     int32_t                propOffset;
1221     int32_t                propertyLen;
1222     const char            *propertyName;
1223     const void            *propertyData;
1224     Rm_ResourcePropType    propertyType;  
1225     int32_t                retVal = RM_OK;
1227     /* Parse the Global Resource List, creating an allocator for each specified resource node */
1228     while ((nodeOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && (nodeDepth >= RM_DTB_UTIL_STARTING_DEPTH)) {
1229         memset((void *)&resProperties, 0, sizeof(Rm_ResourceProperties));
1230         /* Get properties of resource node */
1231         propOffset = fdt_first_property_offset(globalResourceDtb, nodeOffset);
1232         while (propOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) {
1233             propertyData = fdt_getprop_by_offset(globalResourceDtb, propOffset, &propertyName, &propertyLen);
1234             propertyType = rmDtbUtilResGetPropertyType(propertyName);
1235             if (propertyType == Rm_resourcePropType_RESOURCE_RANGE) {
1236                 resProperties.rangeData = propertyData;
1237                 resProperties.rangeLen = propertyLen;
1238             }
1239             else if (propertyType == Rm_resourcePropType_NSASSIGNMENT) {
1240                 resProperties.nsAssignData = propertyData;
1241                 resProperties.nsAssignLen = propertyLen;
1242             }
1243             else if (propertyType == Rm_resourcePropType_RESOURCE_LINUX_ALIAS) {
1244                 resProperties.linuxAliasData = propertyData;
1245                 resProperties.linuxAliasLen = propertyLen;
1246             }        
1247             else {
1248                 retVal = RM_ERROR_GRL_UNKNOWN_RESOURCE_PROPERTY;
1249                 goto exitAllocInit;
1250             }
1252             propOffset = fdt_next_property_offset(globalResourceDtb, propOffset);
1253             if (propOffset == -FDT_ERR_NOTFOUND) {
1254                 /* No more resource properties but at least one found.  Extract the property values */
1255                 retVal = allocatorExtractGrlResProps(rmHandle, fdt_get_name(globalResourceDtb, nodeOffset, NULL), 
1256                                                      &resProperties, linuxDtb);
1257                 if (retVal < RM_OK) {
1258                     goto exitAllocInit;
1259                 }
1260             }
1261             else if (propOffset < -FDT_ERR_NOTFOUND) {
1262                 /* Error returned by LIBFDT */
1263                 retVal = propOffset;
1264                 goto exitAllocInit;
1265             }
1266         }
1267         if (propOffset < -FDT_ERR_NOTFOUND) {
1268             /* Error returned by LIBFDT */
1269             retVal = propOffset;
1270             goto exitAllocInit;
1271         }
1273         nodeOffset = fdt_next_node(globalResourceDtb, nodeOffset, &nodeDepth);
1274         if (nodeOffset < -FDT_ERR_NOTFOUND) {
1275             /* Error returned by LIBFDT */
1276             retVal = nodeOffset;
1277             goto exitAllocInit;
1278         }
1279     }
1280 exitAllocInit:    
1281     return(retVal);
1284 /* FUNCTION PURPOSE: Deletes server allocators
1285  ***********************************************************************
1286  * DESCRIPTION: Removes all resource nodes for each
1287  *              resource allocator and then deletes the allocator
1288  *              itself.  Used to free all memory consumed
1289  *              by the allocators.
1290  */
1291 void rmAllocatorDeleteResources(Rm_Allocator *allocatorList)
1293     Rm_Allocator    *nextAllocator;
1294     Rm_ResourceTree *resTree;
1295     Rm_ResourceNode *resNode;
1296     Rm_ResourceNode *nextResNode;
1298     while (allocatorList) {
1299         nextAllocator = allocatorList->nextAllocator;
1300         resTree = allocatorList->allocatorRootEntry;
1302         /* Delete each resource node in the allocator */
1303         for (resNode = RB_MIN(_Rm_AllocatorResourceTree, resTree); resNode != NULL; resNode = nextResNode) {
1304             nextResNode = RB_NEXT(_Rm_AllocatorResourceTree, resTree, resNode);
1305             RB_REMOVE(_Rm_AllocatorResourceTree, resTree, resNode);
1306             if (resNode->allocationCount) {
1307                 /* Delete all the owners in the resource's owner list */
1308                 allocatorResNodeOwnerClear(resNode);
1309             }
1310             rmResourceNodeFree(resNode);
1311         }        
1312         if (RB_MIN(_Rm_AllocatorResourceTree, resTree) == NULL) {
1313             /* No more resource nodes in allocator */
1314             Rm_osalFree((void *)resTree, sizeof(Rm_ResourceTree));
1315         }
1316         Rm_osalFree((void *)allocatorList, sizeof(Rm_Allocator));
1317         allocatorList = nextAllocator;
1318     }