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