Added pre-main capabilities, cleaned up services and NameServer modules
[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 #include <ti/drv/rm/rm_policy.h>\r
50 \r
51 /* RM internal includes */\r
52 #include <ti/drv/rm/include/rm_loc.h>\r
53 #include <ti/drv/rm/include/rm_transportloc.h>\r
54 #include <ti/drv/rm/include/rm_servicesloc.h>\r
55 #include <ti/drv/rm/include/rm_nameserverloc.h>\r
56 #include <ti/drv/rm/include/rm_dtb_utilloc.h>\r
57 #include <ti/drv/rm/include/rm_policyloc.h>\r
58 \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  ************** Red-Black BBST Tree Allocator Functions ***************\r
78  **********************************************************************/\r
79 \r
80 \r
81 Rm_ResourceNode *Rm_newResourceNode(uint32_t resourceBase, uint32_t resourceLength)\r
82 {\r
83     Rm_ResourceNode *newNode = NULL;\r
84 \r
85     newNode = Rm_osalMalloc(sizeof(Rm_ResourceNode));\r
86     memset((void *)newNode, 0, sizeof(Rm_ResourceNode));\r
87 \r
88     newNode->base = resourceBase;\r
89     newNode->length = resourceLength;\r
90     newNode->allocationCount = 0;\r
91     newNode->allocatedTo = NULL;\r
92 \r
93     return(newNode);\r
94 }\r
95 \r
96 void Rm_freeResourceNode(Rm_ResourceNode *node)\r
97 {\r
98     if (node->allocationCount == 0) {\r
99         Rm_osalFree((void *)node, sizeof(Rm_ResourceNode));\r
100     }\r
101 }\r
102 \r
103 /* Prototype for tree node comparison function\r
104  * element1 < element2 --> return < 0\r
105  * element1 = element2 --> return 0\r
106  * element1 > element2 --> return > 0 */\r
107 int Rm_ResourceNodeCompare(Rm_ResourceNode *element1, Rm_ResourceNode *element2)\r
108 {\r
109     uint32_t element1End = element1->base + element1->length - 1;\r
110     uint32_t element2End = element2->base + element2->length - 1;\r
111 \r
112     if (element1End < element2->base) {\r
113         /* End of element1 range is less than the start of element2's range.  Return a negative\r
114          * value */\r
115         return (-1);\r
116     }\r
117     else if (element1->base > element2End) {\r
118         /* Start of element1 range is after end of element2's range.  Return a positive value */\r
119         return (1);\r
120     }\r
121     else {\r
122         /* If neither of the latter conditions were satisfied there is some overlap between\r
123          * element1 and element2.  Return 0 since the application must handle this overlap. */\r
124         return (0);\r
125     }\r
126 }\r
127 \r
128 /* Generate the red-black tree manipulation functions */\r
129 RB_GENERATE(_Rm_ResourceTree, _Rm_ResourceNode, linkage, Rm_ResourceNodeCompare);\r
130 \r
131 /**********************************************************************\r
132  ********************** Internal Functions ****************************\r
133  **********************************************************************/\r
134 \r
135 Rm_Transaction *Rm_transactionQueueAdd(Rm_Inst *rmInst)\r
136 {\r
137     Rm_Transaction *transactionQueue = (Rm_Transaction *)rmInst->transactionQueue;\r
138     Rm_Transaction *newTransaction   = NULL;\r
139     void           *key;\r
140 \r
141     /* Lock access to the RM instance's transaction queue */\r
142     key = Rm_osalMtCsEnter();\r
143 \r
144     /* Get memory for a new transaction from local memory */\r
145     newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction));\r
146 \r
147     /* Return if the memory allocated for the transaction entry is NULL */\r
148     if (newTransaction != NULL) {\r
149         /* Clear the transaction */\r
150         memset((void *)newTransaction, 0, sizeof(Rm_Transaction));\r
151 \r
152         /* Create an ID for the new transaction.  The ID will be used for two purposes:\r
153          * 1) Matching responses from higher level RM agents to requests\r
154          * 2) Provided to the component that requested the service so that it can match its\r
155          *    request with the response it receives via its callback function it provided */\r
156         newTransaction->localId = Rm_transactionGetSequenceNum(rmInst);\r
157         /* New transaction's nextTransaction pointer will always be NULL */\r
158         newTransaction->nextTransaction = NULL;  \r
159 \r
160         /* Check if there are any transactions in the transaction queue */\r
161         if (transactionQueue) {\r
162             /* At least one transaction in the transaction queue.  Add the new entry to the \r
163              * end of the transaction queue */\r
164             while (transactionQueue->nextTransaction != NULL) {\r
165                 /* Traverse the list until arriving at the last transaction */\r
166                 transactionQueue = transactionQueue->nextTransaction;\r
167             }\r
168 \r
169             /* Add the new transaction to the end of the queue */\r
170             transactionQueue->nextTransaction = newTransaction;\r
171         }\r
172         else {\r
173             /* The transaction queue does not currently exist.  The new transaction is the \r
174              * first transaction */\r
175             rmInst->transactionQueue = newTransaction;\r
176         }\r
177     }\r
178 \r
179     Rm_osalMtCsExit(key);\r
180     return (newTransaction);\r
181 }\r
182 \r
183 Rm_Transaction *Rm_transactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)\r
184 {\r
185     Rm_Transaction *transaction = (Rm_Transaction *)rmInst->transactionQueue;\r
186 \r
187     if (transaction != NULL) {\r
188         while (transaction != NULL) {\r
189             if (transaction->localId == transactionId) {\r
190                 break;             \r
191             }\r
192             transaction = transaction->nextTransaction;\r
193         }\r
194     }\r
195     return (transaction);\r
196 }\r
197 \r
198 int32_t Rm_transactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)\r
199 {\r
200     Rm_Transaction *transaction     = (Rm_Transaction *) rmInst->transactionQueue;\r
201     Rm_Transaction *prevTransaction = NULL;\r
202     int32_t         retVal          = RM_SERVICE_STATE_OKAY;\r
203     void           *key;\r
204 \r
205     /* Lock access to the instance */\r
206     key = Rm_osalMtCsEnter();\r
207 \r
208     /* Find transaction ID within transaction queue. */\r
209     while (transaction) {\r
210         if (transaction->localId == transactionId) {\r
211             break;             \r
212         }\r
213 \r
214         prevTransaction = transaction;\r
215         transaction = transaction->nextTransaction;\r
216     }\r
217 \r
218     if (transaction) {\r
219         if (prevTransaction == NULL) {\r
220             /* Transaction at start of queue. Map second transaction to start of queue \r
221              * as long as more than one transactions. */\r
222             rmInst->transactionQueue = transaction->nextTransaction;\r
223         }\r
224         else {\r
225             /* Transaction in middle or end of queue. */\r
226             prevTransaction->nextTransaction = transaction->nextTransaction;\r
227         }\r
228         Rm_osalFree((void *)transaction, sizeof(Rm_Transaction));\r
229     }\r
230     else {\r
231         retVal = RM_SERVICE_ERROR_SERVICE_TRANSACTION_DOES_NOT_EXIST;\r
232     }    \r
233 \r
234     Rm_osalMtCsExit(key);\r
235     return (retVal);\r
236 }\r
237 \r
238 uint32_t Rm_transactionInitSequenceNum(void)\r
239 {\r
240     /* Sequence number can never have value of 0.  Avoids conflicts\r
241      * with non-response transactions that have remoteOriginatingId of 0 */\r
242     return (1);\r
243 }\r
244 \r
245 uint32_t Rm_transactionGetSequenceNum(Rm_Inst *rmInst)\r
246 {\r
247     uint32_t sequenceNum = 0;\r
248 \r
249     if (rmInst->transactionSeqNum + 1 < rmInst->transactionSeqNum) {\r
250         /* Overflow */\r
251         sequenceNum = rmInst->transactionSeqNum;\r
252         rmInst->transactionSeqNum = Rm_transactionInitSequenceNum();\r
253     }\r
254     else {\r
255         sequenceNum = rmInst->transactionSeqNum++;\r
256     }    \r
257     return (sequenceNum);\r
258 }\r
259 \r
260 Rm_Allocator *Rm_allocatorAdd(Rm_Inst *rmInst, const char *resourceName)\r
261 {\r
262     Rm_Allocator *allocators   = (Rm_Allocator *)rmInst->allocators;\r
263     Rm_Allocator *newAllocator = NULL;\r
264     void         *key;\r
265 \r
266     /* Lock access to the instance */\r
267     key = Rm_osalMtCsEnter();\r
268 \r
269     newAllocator = Rm_osalMalloc(sizeof(Rm_Allocator));\r
270 \r
271     if (newAllocator) {\r
272         memset((void *)newAllocator, 0, sizeof(Rm_Allocator));\r
273         strcpy(newAllocator->resourceName, resourceName);\r
274         newAllocator->allocatorRootEntry = NULL;\r
275         newAllocator->nextAllocator = NULL;  \r
276 \r
277         /* Add allocator to end of list */\r
278         if (allocators) {\r
279             while (allocators->nextAllocator != NULL) {\r
280                 allocators = allocators->nextAllocator;\r
281             }\r
282             allocators->nextAllocator = newAllocator;\r
283         }\r
284         else {\r
285             rmInst->allocators = newAllocator;\r
286         }\r
287     }\r
288 \r
289     Rm_osalMtCsExit(key);\r
290     return (newAllocator);\r
291 }\r
292 \r
293 Rm_Allocator *Rm_allocatorFind(Rm_Allocator *allocatorList, char *resourceName)\r
294 {\r
295     while (allocatorList) {\r
296         if (strcmp(allocatorList->resourceName, resourceName) == 0) {\r
297             break;             \r
298         }\r
299         allocatorList = allocatorList->nextAllocator;\r
300     }\r
301 \r
302     return (allocatorList);\r
303 }\r
304 \r
305 int32_t Rm_allocatorDelete(Rm_Inst *rmInst, char *resourceName)\r
306 {\r
307     Rm_Allocator *allocator = (Rm_Allocator *) rmInst->allocators;\r
308     Rm_Allocator *prevAllocator = NULL;\r
309     int32_t       retVal = RM_SERVICE_STATE_OKAY;\r
310     void         *key;\r
311 \r
312     /* Lock access to instance */\r
313     key = Rm_osalMtCsEnter();\r
314 \r
315     while (allocator) {\r
316         if (strcmp(allocator->resourceName, resourceName) == 0) {\r
317             break;             \r
318         }\r
319         prevAllocator = allocator;\r
320         allocator = allocator->nextAllocator;\r
321     }\r
322 \r
323     if (allocator) {\r
324         if (prevAllocator == NULL) {\r
325             /* Allocator at start of list. Map second allocator to start of list \r
326              * as long as more than one allocators. */\r
327             rmInst->allocators = allocator->nextAllocator;\r
328         }\r
329         else {\r
330             /* Allocator in middle or end of list. */\r
331             prevAllocator->nextAllocator = allocator->nextAllocator;\r
332         }\r
333         Rm_osalFree((void *)allocator, sizeof(Rm_Allocator));\r
334     }\r
335     else {\r
336         retVal = -22; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
337     }\r
338 \r
339     Rm_osalMtCsExit(key);\r
340     return (retVal);\r
341 }\r
342 \r
343 void Rm_addAllocatedTo(Rm_ResourceNode *node, void *serviceInstNode)\r
344 {\r
345     Rm_AllocatedTo *allocatedToList = node->allocatedTo;\r
346     Rm_AllocatedTo *newAllocatedTo = NULL;\r
347 \r
348     newAllocatedTo = Rm_osalMalloc(sizeof(Rm_AllocatedTo));\r
349 \r
350     if (newAllocatedTo) {\r
351         newAllocatedTo->instNameNode = serviceInstNode;\r
352         newAllocatedTo->nextAllocatedTo = NULL;  \r
353 \r
354         /* Add allocatedTo entry to end of list */\r
355         if (allocatedToList) {\r
356             while (allocatedToList->nextAllocatedTo) {\r
357                 allocatedToList = allocatedToList->nextAllocatedTo;\r
358             }\r
359             allocatedToList->nextAllocatedTo = newAllocatedTo;\r
360         }\r
361         else {\r
362             node->allocatedTo = newAllocatedTo;\r
363         }\r
364 \r
365         node->allocationCount++;\r
366         newAllocatedTo->instNameNode->allocRefCount++;\r
367     }\r
368 }\r
369 \r
370 bool Rm_isAllocatedTo(Rm_ResourceNode *node, void *serviceInstNode)\r
371 {\r
372     Rm_AllocatedTo *allocatedTo = node->allocatedTo;\r
373 \r
374     while (allocatedTo) {\r
375         if (allocatedTo->instNameNode == serviceInstNode) {\r
376             return(TRUE);           \r
377         }\r
378         allocatedTo = allocatedTo->nextAllocatedTo;\r
379     }\r
380     return(FALSE);\r
381 }\r
382 \r
383 bool Rm_compareResourceNodeAllocations(Rm_ResourceNode *nodeOne, Rm_ResourceNode *nodeTwo)\r
384 {\r
385     Rm_AllocatedTo *nodeOneAllocs = nodeOne->allocatedTo;\r
386     Rm_AllocatedTo *nodeTwoAllocs = nodeTwo->allocatedTo;\r
387     bool            matchedInst;\r
388 \r
389     if (nodeOne->allocationCount == nodeTwo->allocationCount) {\r
390         while (nodeOneAllocs) {\r
391             matchedInst = FALSE;\r
392             while (nodeTwoAllocs) {\r
393                 if (nodeOneAllocs->instNameNode == nodeTwoAllocs->instNameNode) {\r
394                     matchedInst = TRUE;\r
395                     break;\r
396                 }\r
397                 nodeTwoAllocs = nodeTwoAllocs->nextAllocatedTo;\r
398             }\r
399 \r
400             if (matchedInst) {\r
401                 nodeTwoAllocs = nodeTwo->allocatedTo;\r
402                 nodeOneAllocs = nodeOneAllocs->nextAllocatedTo;\r
403             }\r
404             else {\r
405                 return(FALSE);\r
406             }                \r
407         }\r
408     }\r
409     else {\r
410         return(FALSE);\r
411     }  \r
412     \r
413     return(TRUE);\r
414 }\r
415 \r
416 void Rm_deleteAllocatedTo(Rm_ResourceNode *node, void *serviceInstNode)\r
417 {\r
418     Rm_AllocatedTo *allocatedTo = node->allocatedTo;\r
419     Rm_AllocatedTo *prevAllocatedTo = NULL;\r
420 \r
421     while (allocatedTo) {\r
422         if (allocatedTo->instNameNode == serviceInstNode) {\r
423             break;             \r
424         }\r
425         prevAllocatedTo = allocatedTo;\r
426         allocatedTo = allocatedTo->nextAllocatedTo;\r
427     }\r
428 \r
429     if (prevAllocatedTo == NULL) {\r
430         /* AllocatedTo entry at start of list. Map second allocatedTo entry to start of list \r
431          * as long as more than one allocatedTo entries. */\r
432         node->allocatedTo = allocatedTo->nextAllocatedTo;\r
433     }\r
434     else {\r
435         /* AllocatedTo entry in middle or end of list. */\r
436         prevAllocatedTo->nextAllocatedTo = allocatedTo->nextAllocatedTo;\r
437     }\r
438     \r
439     node->allocationCount--;\r
440     allocatedTo->instNameNode->allocRefCount--;\r
441     Rm_osalFree((void *)allocatedTo, sizeof(Rm_AllocatedTo));\r
442 }\r
443 \r
444 void Rm_copyAllocatedTo(Rm_ResourceNode *dstNode, Rm_ResourceNode *srcNode)\r
445 {\r
446     Rm_AllocatedTo *srcAllocs = srcNode->allocatedTo;\r
447     Rm_AllocatedTo *newDstAlloc;\r
448     Rm_AllocatedTo *prevDstAlloc;\r
449 \r
450     dstNode->allocationCount = srcNode->allocationCount;\r
451 \r
452     while (srcAllocs) {\r
453         newDstAlloc = Rm_osalMalloc(sizeof(Rm_AllocatedTo));\r
454         newDstAlloc->instNameNode = srcAllocs->instNameNode;\r
455         newDstAlloc->nextAllocatedTo = NULL;\r
456 \r
457         if (dstNode->allocatedTo == NULL) {\r
458             dstNode->allocatedTo = newDstAlloc;\r
459         }\r
460         else {\r
461             prevDstAlloc->nextAllocatedTo = newDstAlloc;\r
462         }\r
463         prevDstAlloc = newDstAlloc;\r
464         srcAllocs = srcAllocs->nextAllocatedTo;\r
465     }\r
466 }\r
467 \r
468 void Rm_clearAllocatedTo(Rm_ResourceNode *node)\r
469 {\r
470     Rm_AllocatedTo *allocatedTo = node->allocatedTo;\r
471     Rm_AllocatedTo *nextAllocatedTo;\r
472 \r
473     while (allocatedTo) {\r
474         nextAllocatedTo = allocatedTo->nextAllocatedTo;\r
475         node->allocationCount--;\r
476         Rm_osalFree((void *)allocatedTo, sizeof(Rm_AllocatedTo));\r
477         allocatedTo = nextAllocatedTo;\r
478     }\r
479 }\r
480 \r
481 int32_t Rm_createTreeAllocator(Rm_Inst *rmInst, const char *resourceName, Rm_ResourceRange *range)\r
482 {\r
483     Rm_Allocator    *allocator = NULL;\r
484     Rm_ResourceTree *treeRootEntry = NULL;\r
485     Rm_ResourceNode *treeNode = NULL;\r
486     Rm_ResourceNode *collidingNode = NULL;\r
487 \r
488     allocator = Rm_allocatorAdd(rmInst, resourceName);\r
489     treeRootEntry = Rm_osalMalloc(sizeof(Rm_ResourceTree));\r
490     RB_INIT(treeRootEntry);\r
491 \r
492     while (range != NULL) {\r
493         treeNode = Rm_newResourceNode(range->base, range->length);\r
494         collidingNode = RB_INSERT(_Rm_ResourceTree, treeRootEntry, treeNode);\r
495 \r
496         if (collidingNode) {\r
497             Rm_ResourceNode *nextNode = NULL;\r
498             \r
499             /* Node that was inserted collides with existing node.  Destroy tree and return error */\r
500             for (treeNode = RB_MIN(_Rm_ResourceTree, treeRootEntry); treeNode != NULL; treeNode = nextNode) {\r
501                         nextNode = RB_NEXT(_Rm_ResourceTree, treeRootEntry, treeNode);\r
502                         RB_REMOVE(_Rm_ResourceTree, treeRootEntry, nextNode);\r
503                 Rm_freeResourceNode(treeNode);\r
504                 }\r
505             Rm_osalFree((void *)treeRootEntry, sizeof(Rm_ResourceTree));\r
506             Rm_allocatorDelete(rmInst, allocator->resourceName);\r
507             return (-24); /* TODO FIX RETURN */\r
508         }\r
509         range = range->nextRange;\r
510     }\r
511     \r
512     allocator->allocatorRootEntry = treeRootEntry;\r
513     return(0);   /* TODO: FIX THIS RETURN */\r
514 }\r
515 \r
516 /* Called when an allocate request is made but the base is unspecified.  RM must preallocate\r
517  * resources which then must be checked against the RM policy for the instance.  If the\r
518  * policy does not agree another resource(s) must be preallocated and tested against the \r
519  * policy.  Policy will provide initialize the preallocate with the base that it allows\r
520  * for the rm instance for the specified resource. */\r
521 int32_t Rm_treePreAllocate(Rm_Inst *rmInst, Rm_Allocator *allocator, int32_t resourcePolicy,\r
522                            Rm_AllocatorOpInfo *opInfo)\r
523 {\r
524     Rm_ResourceNode    findNode;\r
525     Rm_ResourceNode   *matchingNode = NULL;\r
526     uint32_t           matchingEnd;\r
527     uint32_t           rangeIndex;\r
528     bool               resourceFound = FALSE;\r
529     Rm_PolicyCheckType policyCheckType;\r
530     Rm_PolicyCheckCfg  policyCheckCfg;\r
531     bool               nodePassesPolicy;\r
532     int32_t            retVal = RM_SERVICE_PROCESSING;    \r
533 \r
534     opInfo->resourceInfo->base = Rm_policyGetResourceBase(rmInst->policy, opInfo->serviceSrcInstNode, \r
535                                                           resourcePolicy, opInfo->allocType, \r
536                                                           &retVal);\r
537     if (retVal != RM_SERVICE_PROCESSING) {\r
538         return (retVal);\r
539     }\r
540 \r
541     if (opInfo->resourceInfo->alignment == RM_RESOURCE_ALIGNMENT_UNSPECIFIED) {  \r
542         /* Get alignment from policy */\r
543         opInfo->resourceInfo->alignment = Rm_policyGetResourceAlignment(rmInst->policy, resourcePolicy);\r
544     }\r
545     \r
546     if (opInfo->resourceInfo->alignment == 0) {\r
547         opInfo->resourceInfo->alignment = 1;\r
548     }    \r
549 \r
550     memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));\r
551     findNode.base = opInfo->resourceInfo->base;\r
552     findNode.length = opInfo->resourceInfo->length;\r
553 \r
554     /* Configure policy checking structure */\r
555     memset((void *)&policyCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));\r
556     if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_INIT_SHIFT)) {\r
557         policyCheckType = Rm_policyCheck_INIT;\r
558     }\r
559     else if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_USE_SHIFT)) {\r
560         policyCheckType = Rm_policyCheck_USE;\r
561     }\r
562     policyCheckCfg.policyDtb = rmInst->policy;\r
563     policyCheckCfg.resourceOffset = resourcePolicy;\r
564     \r
565     do {\r
566         matchingNode = RB_FIND(_Rm_ResourceTree, allocator->allocatorRootEntry, &findNode);\r
567         \r
568         if (matchingNode) {\r
569             nodePassesPolicy = FALSE;\r
570             policyCheckCfg.type = policyCheckType;\r
571             policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;\r
572             policyCheckCfg.resourceBase = findNode.base;\r
573             policyCheckCfg.resourceLength = findNode.length;\r
574             nodePassesPolicy = Rm_policyCheckPrivilege(&policyCheckCfg, &retVal);    \r
575             \r
576             if (nodePassesPolicy && (matchingNode->allocationCount > 0)) {\r
577                 /* Check exclusive privileges of instance requesting resource.  Requesting\r
578                  * instance with exclusive privileges can't reserve resource if already owned*/\r
579                 policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
580                 policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;\r
581                 nodePassesPolicy = !Rm_policyCheckPrivilege(&policyCheckCfg, &retVal);\r
582             }\r
583             \r
584             if (nodePassesPolicy && (matchingNode->allocationCount == 1)) {\r
585                 /* Check exclusive privileges of instance that currently owns resource */\r
586                 policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
587                 policyCheckCfg.validInstNode = matchingNode->allocatedTo->instNameNode;\r
588                 nodePassesPolicy = !Rm_policyCheckPrivilege(&policyCheckCfg, &retVal);\r
589             }\r
590 \r
591             if (retVal != RM_SERVICE_PROCESSING) {\r
592                 break;\r
593             }\r
594 \r
595             if (nodePassesPolicy) {\r
596                 matchingEnd = matchingNode->base + matchingNode->length - 1;\r
597                 /* Initialize indexer to be first resource value that alignment */\r
598                 rangeIndex = findNode.base;\r
599                 if (rangeIndex % opInfo->resourceInfo->alignment) {\r
600                     rangeIndex += (opInfo->resourceInfo->alignment -\r
601                                   (rangeIndex % opInfo->resourceInfo->alignment));\r
602                 }\r
603                 \r
604                 if ((rangeIndex + opInfo->resourceInfo->length - 1) <= matchingEnd) {\r
605                     /* Block of unallocated resources within matchingNode that satisfies\r
606                      * allocate requirements */\r
607                     opInfo->resourceInfo->base = rangeIndex;\r
608                     resourceFound = TRUE;\r
609                 }     \r
610             }\r
611             \r
612             if (!resourceFound) {\r
613                 /* Check next resource node for available resources */\r
614                 findNode.base = matchingNode->base + matchingNode->length;\r
615             }\r
616         }\r
617         else {\r
618             retVal = RM_SERVICE_DENIED_RESOURCE_ALLOCATION_REQUIREMENTS_COULD_NOT_BE_SATISFIED;\r
619         }\r
620     } while ((!resourceFound) && \r
621              (retVal != RM_SERVICE_DENIED_RESOURCE_ALLOCATION_REQUIREMENTS_COULD_NOT_BE_SATISFIED));\r
622 \r
623     return(retVal); \r
624 }\r
625 \r
626 int32_t Rm_treeAllocate(Rm_Inst *rmInst, Rm_Allocator *allocator, int32_t resourcePolicy,\r
627                         Rm_AllocatorOpInfo *opInfo)\r
628 {\r
629     Rm_ResourceNode     findNode;\r
630     Rm_ResourceNode    *matchingNode = NULL;\r
631     Rm_ResourceNode    *leftNode = NULL;\r
632     Rm_ResourceNode    *rightNode = NULL;\r
633     Rm_PolicyCheckType  policyCheckType;    \r
634     Rm_PolicyCheckCfg   policyCheckCfg;\r
635     bool                allocPassesPolicy;\r
636     bool                combineLeft = FALSE;\r
637     bool                combineRight = FALSE;    \r
638     uint32_t            findEnd;\r
639     uint32_t            matchingEnd;  \r
640     int32_t             retVal = RM_SERVICE_PROCESSING;\r
641 \r
642     memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));\r
643     findNode.base = opInfo->resourceInfo->base;\r
644     findNode.length = opInfo->resourceInfo->length;\r
645     matchingNode = RB_FIND(_Rm_ResourceTree, allocator->allocatorRootEntry, &findNode);\r
646 \r
647     /* Prepare privilege checks */\r
648     memset((void *)&policyCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));\r
649     if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_INIT_SHIFT)) {\r
650         policyCheckType = Rm_policyCheck_INIT;\r
651     }\r
652     else if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_USE_SHIFT)) {\r
653         policyCheckType = Rm_policyCheck_USE;\r
654     }\r
655 \r
656     if (matchingNode) {\r
657         findEnd = findNode.base + findNode.length - 1;\r
658         matchingEnd = matchingNode->base + matchingNode->length - 1;\r
659         \r
660         if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {\r
661             if (opInfo->serviceSrcInstNode == Rm_policyGetLinuxInstNode(rmInst->validInstances)) {\r
662                 /* Bypass policy checks since Linux Kernel has full privileges */\r
663                 allocPassesPolicy = TRUE;\r
664             }\r
665             else {\r
666                 allocPassesPolicy = FALSE;\r
667                 policyCheckCfg.policyDtb = rmInst->policy;\r
668                 policyCheckCfg.resourceOffset = resourcePolicy;    \r
669                 policyCheckCfg.type = policyCheckType;\r
670                 policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;\r
671                 policyCheckCfg.resourceBase = findNode.base;\r
672                 policyCheckCfg.resourceLength = findNode.length;\r
673                 allocPassesPolicy = Rm_policyCheckPrivilege(&policyCheckCfg, &retVal);\r
674                 if (!allocPassesPolicy) {\r
675                     retVal = RM_SERVICE_DENIED_INIT_USE_PERMISSION_DENIED;\r
676                 }\r
677                 \r
678                 if (allocPassesPolicy && (matchingNode->allocationCount > 0)) {\r
679                     /* Check exclusive privileges of instance requesting resource.  Requesting\r
680                      * instance with exclusive privileges can't reserve resource if already owned*/\r
681                     policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
682                     policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;\r
683                     allocPassesPolicy = !Rm_policyCheckPrivilege(&policyCheckCfg, &retVal);\r
684                     if (!allocPassesPolicy) {\r
685                         retVal = RM_SERVICE_DENIED_REQUESTER_HAS_EXCLUSIVE_PRIV_BUT_RESOURCE_ALLOCATED;\r
686                     }\r
687                 }\r
688                 if (allocPassesPolicy && (matchingNode->allocationCount == 1)) {\r
689                     /* Check exclusive privileges of instance that currently owns resource */\r
690                     policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
691                     policyCheckCfg.validInstNode = matchingNode->allocatedTo->instNameNode;\r
692                     allocPassesPolicy = !Rm_policyCheckPrivilege(&policyCheckCfg, &retVal);\r
693                     if (!allocPassesPolicy) {\r
694                         retVal = RM_SERVICE_DENIED_RESOURCE_ALLOCATED_TO_INSTANCE_WITH_EXCLUSIVE_PRIV;\r
695                     }                \r
696                 }  \r
697             }\r
698             \r
699             if (allocPassesPolicy) {   \r
700                 if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd)) {\r
701                     /* findNode range matches matchingNode range\r
702                      *\r
703                      *   |<--left node-->||<--matched  node-->||<--right node-->| => existing node\r
704                      *                    |<--alloc request-->|  => requested resources\r
705                      */                     \r
706                     leftNode = RB_PREV(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
707                     rightNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
708                     RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
709                     Rm_addAllocatedTo(matchingNode, opInfo->serviceSrcInstNode);\r
710 \r
711                     if (leftNode && Rm_compareResourceNodeAllocations(leftNode, matchingNode)) {\r
712                         RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
713                         combineLeft = TRUE;\r
714                     }\r
715                     if (rightNode && Rm_compareResourceNodeAllocations(rightNode, matchingNode)) {\r
716                         RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
717                         combineRight = TRUE;\r
718                     }\r
719 \r
720                     if (combineLeft && combineRight) {\r
721                         /* Combine all three nodes into matchingNode */\r
722                         matchingNode->base = leftNode->base;\r
723                         matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;\r
724 \r
725                         Rm_clearAllocatedTo(leftNode);\r
726                         Rm_freeResourceNode(leftNode);\r
727                         Rm_clearAllocatedTo(rightNode);\r
728                         Rm_freeResourceNode(rightNode);                        \r
729                     }\r
730                     else if (combineLeft) {\r
731                         /* Combine left and matching nodes.  Reinsert right. */\r
732                         matchingNode->base = leftNode->base;\r
733                         matchingNode->length += leftNode->length;\r
734 \r
735                         Rm_clearAllocatedTo(leftNode);\r
736                         Rm_freeResourceNode(leftNode);\r
737                         RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);                        \r
738                     }\r
739                     else if (combineRight) {\r
740                         /* Combine right and matching nodes.  Reinsert left. */\r
741                         matchingNode->length += rightNode->length;\r
742 \r
743                         Rm_clearAllocatedTo(rightNode);\r
744                         Rm_freeResourceNode(rightNode);\r
745                         RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
746                     }\r
747                     else {\r
748                         /* No combine. */\r
749                         RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
750                         RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
751                     }\r
752 \r
753                     /* Always reinsert matchingNode */                \r
754                     RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);   \r
755                 }   \r
756                 else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {\r
757                     /* findNode range is subset of matchingNode range and neither boundary is\r
758                      * equivalent.\r
759                      *\r
760                      * |<----------matched node---------->|\r
761                      *        |<---alloc request--->|\r
762                      */ \r
763                     RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
764                     leftNode = Rm_newResourceNode(matchingNode->base, findNode.base - matchingNode->base);\r
765                     Rm_copyAllocatedTo(leftNode, matchingNode);\r
766                     rightNode = Rm_newResourceNode(findNode.base + findNode.length, matchingEnd - findEnd);\r
767                     Rm_copyAllocatedTo(rightNode, matchingNode);\r
768 \r
769                     matchingNode->base = findNode.base;                                    \r
770                     matchingNode->length = findNode.length;\r
771                     Rm_addAllocatedTo(matchingNode, opInfo->serviceSrcInstNode);\r
772 \r
773                     /* Insert all the nodes */\r
774                     RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
775                     RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
776                     RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
777                 }  \r
778                 else {    \r
779                     if (findNode.base == matchingNode->base) {\r
780                         /* findNode base and matchingNode base are equivalent.  May be combine\r
781                          * possibilities to the left\r
782                          *\r
783                          * |<---left node (alloc'd)--->||<----------matched node---------->|\r
784                          *                              |<---findNode (alloc req)--->|\r
785                          */                         \r
786                         leftNode = RB_PREV(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
787                         RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
788                         /* Add allocating instance to allocatedTo list for compare with leftNode */\r
789                         Rm_addAllocatedTo(matchingNode, opInfo->serviceSrcInstNode);\r
790                         \r
791                         if (leftNode && Rm_compareResourceNodeAllocations(leftNode, matchingNode)) {\r
792                             RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
793                             /* Combine leftNode and findNode */\r
794                             leftNode->length += findNode.length;\r
795                         }\r
796                         else {\r
797                             leftNode = Rm_newResourceNode(findNode.base, findNode.length);\r
798                             Rm_copyAllocatedTo(leftNode, matchingNode);\r
799                         }\r
800 \r
801                         /* Account for leftNode in matchingNode */\r
802                         matchingNode->base = findNode.base + findNode.length;\r
803                         matchingNode->length = matchingEnd - findEnd;  \r
804 \r
805                         RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
806                     }\r
807                     else if (findEnd == matchingEnd) {\r
808                         /* findNode end and matchingNode end are equivalent.  May be combine\r
809                          * possibilities to the right\r
810                          *\r
811                          * |<----------matched node---------->||<---right node (alloc'd)--->|\r
812                          *       |<---findNode (alloc req)--->| \r
813                          */                        \r
814                         rightNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
815                         RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
816                         /* Add allocating instance to allocatedTo list for compare with rightNode */\r
817                         Rm_addAllocatedTo(matchingNode, opInfo->serviceSrcInstNode);\r
818                         \r
819                         if (rightNode && Rm_compareResourceNodeAllocations(rightNode, matchingNode)) {\r
820                             RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
821                             /* Combine rightNode and findNode */\r
822                             rightNode->base = findNode.base;\r
823                             rightNode->length += findNode.length;\r
824                         }\r
825                         else {\r
826                             rightNode = Rm_newResourceNode(findNode.base, findNode.length);\r
827                             Rm_copyAllocatedTo(rightNode, matchingNode);\r
828                         }\r
829 \r
830                         /* Account for rightNode in matchingNode */\r
831                         matchingNode->length -= findNode.length;  \r
832 \r
833                         RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
834                     }\r
835                     /* Remove allocating instance from leftover matchingNode */\r
836                     Rm_deleteAllocatedTo(matchingNode, opInfo->serviceSrcInstNode);\r
837                     RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
838                 }\r
839                 retVal = RM_SERVICE_APPROVED_AND_COMPLETED;\r
840             }\r
841         }\r
842         else {\r
843             retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_ALLOCATED;\r
844         }\r
845     }\r
846     else {\r
847         retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
848     }\r
849 \r
850     return(retVal);        \r
851 }\r
852 \r
853 int32_t Rm_treeFree(Rm_Inst *rmInst, Rm_Allocator *allocator, int32_t resourcePolicy, Rm_AllocatorOpInfo *opInfo)\r
854 {\r
855     Rm_ResourceNode  findNode;\r
856     Rm_ResourceNode *matchingNode = NULL;\r
857     Rm_ResourceNode *leftNode = NULL;\r
858     Rm_ResourceNode *rightNode = NULL;\r
859     bool             combineLeft = FALSE;\r
860     bool             combineRight = FALSE;\r
861     uint32_t         findEnd;\r
862     uint32_t         matchingEnd;\r
863     int32_t          retVal;\r
864 \r
865     memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));\r
866     findNode.base = opInfo->resourceInfo->base;\r
867     findNode.length = opInfo->resourceInfo->length;\r
868     matchingNode = RB_FIND(_Rm_ResourceTree, allocator->allocatorRootEntry, &findNode);\r
869 \r
870     if (matchingNode) {\r
871         findEnd = findNode.base + findNode.length - 1;\r
872         matchingEnd = matchingNode->base + matchingNode->length - 1;\r
873         \r
874         if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {  \r
875             if (matchingNode->allocationCount) {\r
876                 if (Rm_isAllocatedTo(matchingNode, opInfo->serviceSrcInstNode)) {\r
877                     if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd))\r
878                     {\r
879                         /* Case 1: Free range equals allocated matched node exactly. Attempt to combine \r
880                          *         freed node with nodes to left and right.\r
881                          *\r
882                          * |<--left node-->||<---matched node--->||<--right node-->|\r
883                          *                  |<---free request--->|\r
884                          */ \r
885                         leftNode = RB_PREV(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
886                         rightNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
887                         RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
888                         Rm_deleteAllocatedTo(matchingNode, opInfo->serviceSrcInstNode);\r
889 \r
890                         if (leftNode && Rm_compareResourceNodeAllocations(leftNode, matchingNode)) {\r
891                             RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
892                             combineLeft = TRUE;\r
893                         }\r
894                         if (rightNode && Rm_compareResourceNodeAllocations(rightNode, matchingNode)) {\r
895                             RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
896                             combineRight = TRUE;\r
897                         }\r
898 \r
899                         if (combineLeft && combineRight) {\r
900                             /* Combine all three nodes into matchingNode */\r
901                             matchingNode->base = leftNode->base;\r
902                             matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;\r
903 \r
904                             Rm_clearAllocatedTo(leftNode);\r
905                             Rm_freeResourceNode(leftNode);\r
906                             Rm_clearAllocatedTo(rightNode);\r
907                             Rm_freeResourceNode(rightNode);                        \r
908                         }\r
909                         else if (combineLeft) {\r
910                             /* Combine left and matching nodes.  Reinsert right. */\r
911                             matchingNode->base = leftNode->base;\r
912                             matchingNode->length += leftNode->length;\r
913 \r
914                             Rm_clearAllocatedTo(leftNode);\r
915                             Rm_freeResourceNode(leftNode);\r
916                             RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);                        \r
917                         }\r
918                         else if (combineRight) {\r
919                             /* Combine right and matching nodes.  Reinsert left. */\r
920                             matchingNode->length += rightNode->length;\r
921 \r
922                             Rm_clearAllocatedTo(rightNode);\r
923                             Rm_freeResourceNode(rightNode);\r
924                             RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
925                         }\r
926                         else {\r
927                             /* No combine. */\r
928                             RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
929                             RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
930                         }\r
931 \r
932                         /* Always reinsert matchingNode */\r
933                         RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);                    \r
934                     }\r
935                     else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {\r
936                         /* Case 2: Free range is less than range in matched node. Split\r
937                          *         matched node into three nodes.\r
938                          *\r
939                          * |<----------matched node---------->|\r
940                          *        |<---free request--->|\r
941                          *\r
942                          * Remove instance from AllocatedTo list then add it back in for side nodes for\r
943                          * proper accounting of allocations in validInstance list\r
944                          */ \r
945                         RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
946                         Rm_deleteAllocatedTo(matchingNode, opInfo->serviceSrcInstNode);\r
947                         \r
948                         leftNode = Rm_newResourceNode(matchingNode->base, findNode.base - matchingNode->base);\r
949                         Rm_copyAllocatedTo(leftNode, matchingNode);\r
950                         Rm_addAllocatedTo(leftNode, opInfo->serviceSrcInstNode);\r
951                         RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
952                         \r
953                         rightNode = Rm_newResourceNode(findNode.base + findNode.length, matchingEnd - findEnd);\r
954                         Rm_copyAllocatedTo(rightNode, matchingNode);\r
955                         Rm_addAllocatedTo(rightNode, opInfo->serviceSrcInstNode);\r
956                         RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
957 \r
958                         matchingNode->base = findNode.base;                                    \r
959                         matchingNode->length = findNode.length;\r
960                         RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
961                     }\r
962                     else {                        \r
963                         if (findNode.base == matchingNode->base) {\r
964                             /* Case 3: Free range is on left boundary of matched node. Try to \r
965                              *         combine free range with left node.\r
966                              *\r
967                              * |<---left node (free)--->||<----------matched node---------->|\r
968                              *                           |<---findNode (free req)--->|\r
969                              */ \r
970 \r
971                             leftNode = RB_PREV(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
972                             RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
973                             /* Remove freeing instance from allocatedTo list for compare with leftNode */\r
974                             Rm_deleteAllocatedTo(matchingNode, opInfo->serviceSrcInstNode);\r
975                             \r
976                             if (leftNode && Rm_compareResourceNodeAllocations(leftNode, matchingNode)) {\r
977                                 RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
978                                 /* Combine leftNode and findNode */\r
979                                 leftNode->length += findNode.length;\r
980                             }\r
981                             else {\r
982                                 leftNode = Rm_newResourceNode(findNode.base, findNode.length);\r
983                                 Rm_copyAllocatedTo(leftNode, matchingNode);\r
984                             }\r
985 \r
986                             /* Remove leftNode range from matchingNode */\r
987                             matchingNode->base = findNode.base + findNode.length;\r
988                             matchingNode->length = matchingEnd - findEnd;  \r
989                             RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
990                         }\r
991                         else if (findEnd == matchingEnd) {\r
992                             /* Case 4: Free range is on right boundary of matched node. Try to \r
993                              *         combine free range with right node.\r
994                              *\r
995                              * |<----------matched node---------->||<---right node (free)--->|\r
996                              *        |<---findNode (free req)--->|\r
997                              */ \r
998                             \r
999                             rightNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
1000                             RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode); \r
1001                             /* Remove freeing instance from allocatedTo list for compare with rightNode */\r
1002                             Rm_deleteAllocatedTo(matchingNode, opInfo->serviceSrcInstNode);\r
1003                             \r
1004                             if (rightNode && Rm_compareResourceNodeAllocations(rightNode, matchingNode)) {\r
1005                                 RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
1006                                 /* Combine rightNode and findNode */\r
1007                                 rightNode->base = findNode.base;\r
1008                                 rightNode->length += findNode.length;\r
1009                             }\r
1010                             else {\r
1011                                 rightNode = Rm_newResourceNode(findNode.base, findNode.length);\r
1012                                 Rm_copyAllocatedTo(rightNode, matchingNode);\r
1013                             }\r
1014 \r
1015                             /* Remove rightNode range from matchingNode */\r
1016                             matchingNode->length -= findNode.length;  \r
1017                             RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
1018                         }\r
1019 \r
1020                         /* Add freeing instance back into matchingNode allocations */\r
1021                         Rm_addAllocatedTo(matchingNode, opInfo->serviceSrcInstNode);\r
1022                         RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
1023                     }\r
1024 \r
1025                     retVal = RM_SERVICE_APPROVED_AND_COMPLETED;\r
1026                 }\r
1027                 else {\r
1028                     retVal = RM_SERVICE_DENIED_RESOURCE_NOT_ALLOCATED_TO_INSTANCE_REQUESTING_THE_SERVICE;\r
1029                 }\r
1030             }\r
1031             else {\r
1032                 retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_FREE;\r
1033             }\r
1034         }\r
1035         else {\r
1036             retVal = RM_SERVICE_DENIED_INVALID_RESOURCE_RANGE;\r
1037         }\r
1038     }\r
1039     else {\r
1040         retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
1041     }\r
1042     return(retVal);  \r
1043 }\r
1044 \r
1045 int32_t Rm_allocatorOperation(Rm_Inst *rmInst, Rm_AllocatorOpInfo *opInfo)\r
1046 {\r
1047     Rm_Allocator *allocator = NULL;\r
1048     int32_t       resourceOffsetInPolicy;\r
1049     int32_t       retVal;\r
1050     void         *key;\r
1051 \r
1052     /* Lock access to the RM instance's transaction queue */\r
1053     key = Rm_osalMtCsEnter();\r
1054     \r
1055     resourceOffsetInPolicy = Rm_policyGetResourceOffset(rmInst->policy, opInfo->resourceInfo->name);\r
1056     allocator = Rm_allocatorFind(rmInst->allocators, opInfo->resourceInfo->name);\r
1057     \r
1058     if ((resourceOffsetInPolicy > 0) && allocator) {\r
1059         if (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE) {\r
1060             retVal = Rm_treePreAllocate(rmInst, allocator, resourceOffsetInPolicy, opInfo);\r
1061         }               \r
1062         else if (opInfo->operation == Rm_allocatorOp_ALLOCATE) {\r
1063             retVal = Rm_treeAllocate(rmInst, allocator, resourceOffsetInPolicy, opInfo);\r
1064         }\r
1065         else if (opInfo->operation == Rm_allocatorOp_FREE) {\r
1066             retVal = Rm_treeFree(rmInst, allocator, resourceOffsetInPolicy, opInfo);\r
1067         }         \r
1068     }\r
1069     else {\r
1070         /* Resource could not be found in policy and/or allocator */\r
1071         retVal = RM_SERVICE_DENIED_RESOURCE_DOES_NOT_EXIST;\r
1072     }\r
1073 \r
1074     Rm_osalMtCsExit(key);\r
1075     return(retVal);\r
1076 }\r
1077 \r
1078 void Rm_allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction, void *validInstNode,\r
1079                            uint32_t allocType)\r
1080 {\r
1081     Rm_AllocatorOpInfo  opInfo;\r
1082     Rm_NameServerObjCfg nameServerObjCfg;\r
1083     int32_t             retVal = transaction->state;\r
1084 \r
1085     memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));\r
1086     \r
1087     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {\r
1088         /* TEMP: For now forward all allocations to the RM Server */\r
1089         Rm_transactionForwarder(rmInst, transaction);\r
1090              \r
1091     }\r
1092     else if (rmInst->instType == Rm_instType_SERVER) {\r
1093         opInfo.resourceInfo = &transaction->resourceInfo;\r
1094         opInfo.serviceSrcInstNode = validInstNode;\r
1095         opInfo.allocType = allocType;\r
1096 \r
1097         if (strlen(transaction->resourceInfo.nameServerName) > 0) {\r
1098             if (transaction->resourceInfo.base != 0) {\r
1099                 /* Both NameServer name and static value cannot be specified for the request */\r
1100                 retVal = RM_SERVICE_ERROR_NAMESERVER_NAME_AND_RESOURCE_RANGE_BOTH_DEFINED;\r
1101             }\r
1102             else {\r
1103                 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));\r
1104                 nameServerObjCfg.nameServerTree = rmInst->nameServer;\r
1105                 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;\r
1106                 if ((retVal = Rm_nameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {\r
1107                     strcpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName);\r
1108                     transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;\r
1109                     transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;\r
1110                 }                \r
1111             }\r
1112         }\r
1113 \r
1114         if (retVal == RM_SERVICE_PROCESSING) {      \r
1115             if (transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) {\r
1116                 opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE;\r
1117                 retVal = Rm_allocatorOperation(rmInst, &opInfo);\r
1118             }\r
1119         \r
1120             if (retVal == RM_SERVICE_PROCESSING) {\r
1121                 opInfo.operation = Rm_allocatorOp_ALLOCATE;\r
1122                 retVal = Rm_allocatorOperation(rmInst, &opInfo);\r
1123             }      \r
1124         }\r
1125         \r
1126         transaction->state = retVal;\r
1127 \r
1128         if (strcmp(transaction->serviceSrcInstName, rmInst->instName)) {\r
1129             /* Source of allocation was not the server instance, provide the transaction\r
1130              * to the transaction responder */\r
1131             Rm_transactionResponder(rmInst, transaction);\r
1132         }\r
1133         /* Otherwise let the return stack return the transaction to the serviceHandler */                   \r
1134     }   \r
1135 }\r
1136 \r
1137 void Rm_freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction, void *validInstNode)\r
1138 {\r
1139     Rm_AllocatorOpInfo  opInfo; \r
1140     Rm_NameServerObjCfg nameServerObjCfg;    \r
1141     int32_t             retVal = transaction->state;\r
1142 \r
1143     memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));\r
1144     \r
1145     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {\r
1146         /* TEMP: Forward all free requests to the Server */\r
1147         Rm_transactionForwarder(rmInst, transaction);        \r
1148     }\r
1149     else if (rmInst->instType == Rm_instType_SERVER) {\r
1150         opInfo.resourceInfo = &transaction->resourceInfo;\r
1151         opInfo.serviceSrcInstNode = validInstNode;\r
1152 \r
1153         if (strlen(transaction->resourceInfo.nameServerName) > 0) {\r
1154             if (transaction->resourceInfo.base != 0) {\r
1155                 /* Both a name and a value cannot be specified for the request */\r
1156                 retVal = RM_SERVICE_ERROR_NAMESERVER_NAME_AND_RESOURCE_RANGE_BOTH_DEFINED;\r
1157             }\r
1158             else {\r
1159                 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));\r
1160                 nameServerObjCfg.nameServerTree = rmInst->nameServer;\r
1161                 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;\r
1162                 if ((retVal = Rm_nameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {\r
1163                     strcpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName);\r
1164                     transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;\r
1165                     transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;\r
1166                 }                \r
1167             }\r
1168 \r
1169         }\r
1170         \r
1171         if(retVal == RM_SERVICE_PROCESSING) {        \r
1172             opInfo.operation = Rm_allocatorOp_FREE;\r
1173             retVal = Rm_allocatorOperation(rmInst, &opInfo);\r
1174         }       \r
1175 \r
1176         transaction->state = retVal;\r
1177 \r
1178         if (strcmp(transaction->serviceSrcInstName, rmInst->instName)) {\r
1179             /* Source of allocation was not the server instance, provide the transaction\r
1180              * to the transaction responder */\r
1181             Rm_transactionResponder(rmInst, transaction);\r
1182         }\r
1183         /* Otherwise let the return stack return the transaction to the serviceHandler */        \r
1184     }   \r
1185 }\r
1186 \r
1187 /* This function is executed when a RM instance receives a response to one of its requests\r
1188  * and the information in the request must be provided to the original requesting component */\r
1189 void Rm_serviceResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
1190 {\r
1191     Rm_ServiceRespInfo serviceResponse;\r
1192 \r
1193     /* The responseTransaction will contain the resultant state details of\r
1194      * the requestTransaction's service request */\r
1195     serviceResponse.serviceState = transaction->state;\r
1196     /* Pass back the ID that was provided to the component when it requested\r
1197      * the service */\r
1198     serviceResponse.serviceId = transaction->localId;\r
1199 \r
1200     /* Service was approved and service was an allocate request.  The resource\r
1201      * data is passed back to the component */\r
1202     if ((serviceResponse.serviceState == RM_SERVICE_APPROVED_AND_COMPLETED) &&\r
1203         ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||\r
1204          (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||\r
1205          (transaction->type == Rm_service_RESOURCE_GET_BY_NAME)))\r
1206     {\r
1207         strcpy(serviceResponse.resourceName, transaction->resourceInfo.name);\r
1208         serviceResponse.resourceBase = transaction->resourceInfo.base;\r
1209         serviceResponse.resourceLength = transaction->resourceInfo.length;\r
1210     }\r
1211 \r
1212     /* Issue the callback to the requesting component with the response information */\r
1213     transaction->callback.serviceCallback(&serviceResponse);\r
1214 \r
1215     /* Delete the transaction from the transaction queue */\r
1216     Rm_transactionQueueDelete(rmInst, transaction->localId);\r
1217     return;\r
1218 }\r
1219 \r
1220 /* Function used to send RM response transactions to lower level agents */\r
1221 void Rm_transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
1222 {\r
1223     Rm_TransportNode *dstTransportNode = NULL;\r
1224     Rm_Packet *rmPkt = NULL;\r
1225 \r
1226     /* Find the transport for the RM instance that sent the request. */\r
1227     dstTransportNode = Rm_transportNodeFindRemoteName(rmInst, transaction->pktSrcInstName);\r
1228 \r
1229     /* Create a RM packet using the service information */\r
1230     switch (transaction->type) {\r
1231         case Rm_service_RESOURCE_ALLOCATE_INIT:\r
1232         case Rm_service_RESOURCE_ALLOCATE_USE:\r
1233         case Rm_service_RESOURCE_FREE:\r
1234         case Rm_service_RESOURCE_GET_BY_NAME:\r
1235             rmPkt = Rm_transportCreateResourceResponsePkt(rmInst, dstTransportNode, \r
1236                                                           transaction);\r
1237             break;\r
1238         case Rm_service_RESOURCE_MAP_TO_NAME:\r
1239         case Rm_service_RESOURCE_UNMAP_NAME:\r
1240             rmPkt = Rm_transportCreateNsResponsePkt(rmInst, dstTransportNode,\r
1241                                                     transaction);\r
1242             break;\r
1243         default:\r
1244             /* Invalid service type.  Flag the error and return */\r
1245             transaction->state = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
1246             break;\r
1247     }\r
1248 \r
1249     if (transaction->state <= RM_SERVICE_ERROR_BASE) {\r
1250         /* Delete the transaction and return immediately because an error occurred \r
1251          * allocating the packet */\r
1252         Rm_transactionQueueDelete(rmInst, transaction->localId);\r
1253         return;\r
1254     }\r
1255 \r
1256     /* Send the RM packet to the application transport */\r
1257     if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt) < RM_TRANSPORT_SUCCESSFUL) {\r
1258         /* Negative value returned by transport send.  An error occurred\r
1259          * in the transport while attempting to send the packet.*/\r
1260         transaction->state = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
1261         /* Clean up the packet */\r
1262         if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt)) {\r
1263             /* Non-NULL value returned by transport packet free. Flag the\r
1264              * error */\r
1265             transaction->state = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
1266         }\r
1267         return;\r
1268     }\r
1269 \r
1270     /* NEED TO DO SOMETHING IF GET AN ERROR IN THE transaction->state FIELD.  CREATE\r
1271      * NEW TRANSACTION WITH DATA FROM ORIGINAL?  THEN TRY TO SEND FAILED REQUEST BACK\r
1272      * TO REQUESTER???  KEEP RETRYING SEND OF RESPONSE??? */\r
1273 \r
1274     /* Delete the transaction */\r
1275     Rm_transactionQueueDelete(rmInst, transaction->localId);\r
1276 }\r
1277 \r
1278 /* Function used to forward RM transactions to higher level agents */\r
1279 void Rm_transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
1280 {\r
1281     Rm_TransportNode *dstTransportNode = NULL;\r
1282     Rm_Packet *rmPkt = NULL;\r
1283 \r
1284     /* Make sure the RM instance has a transport registered with a higher level agent */\r
1285     if (rmInst->registeredWithDelegateOrServer == false) {\r
1286         transaction->state = RM_SERVICE_ERROR_NOT_REGISTERED_WITH_DEL_OR_SERVER;\r
1287         return;\r
1288     }\r
1289 \r
1290     /* Find the transport for the higher level agent.  Check for a connection to a Client Delegate\r
1291      * or a Server.  Clients will be connected to either a Client Delegate or a Server.  Client\r
1292      * Delegates will be connected to a Server. */\r
1293     if (rmInst->instType == Rm_instType_CLIENT) {\r
1294         dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_CLIENT_DELEGATE);\r
1295 \r
1296         if (!dstTransportNode) {\r
1297             /* No Client Delegate connection found.  Check for a Server connection */\r
1298             dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_SERVER);\r
1299         }\r
1300     } \r
1301     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {\r
1302         dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_SERVER);\r
1303     }\r
1304 \r
1305     /* Create a RM packet using the service information */\r
1306     switch (transaction->type) {\r
1307         case Rm_service_RESOURCE_ALLOCATE_INIT:\r
1308         case Rm_service_RESOURCE_ALLOCATE_USE:\r
1309         case Rm_service_RESOURCE_FREE:\r
1310         case Rm_service_RESOURCE_GET_BY_NAME:\r
1311             rmPkt = Rm_transportCreateResourceReqPkt(rmInst, dstTransportNode, \r
1312                                                      transaction);\r
1313             break;\r
1314         case Rm_service_RESOURCE_MAP_TO_NAME:\r
1315         case Rm_service_RESOURCE_UNMAP_NAME:\r
1316             rmPkt = Rm_transportCreateNsRequestPkt(rmInst, dstTransportNode,\r
1317                                                    transaction);\r
1318             break;\r
1319         default:\r
1320             /* Invalid service type.  Flag the error and return */\r
1321             transaction->state = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
1322             break;\r
1323     }\r
1324 \r
1325     if (transaction->state <= RM_SERVICE_ERROR_BASE) {\r
1326         /* Return immediately because an error occurred allocating the packet */\r
1327         return;\r
1328     }\r
1329 \r
1330     /* Send the RM packet to the application transport */\r
1331     if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt) < RM_TRANSPORT_SUCCESSFUL) {\r
1332         /* Negative value returned by transport send.  An error occurred\r
1333          * in the transport while attempting to send the packet.*/\r
1334         transaction->state = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
1335         /* Clean up the packet */\r
1336         if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt)) {\r
1337             /* Non-NULL value returned by transport packet free. Flag the\r
1338              * error */\r
1339             transaction->state = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
1340         }\r
1341         return;\r
1342     }\r
1343 \r
1344     /* Transaction is not deleted because it is awaiting a response from the higher level\r
1345      * RM instance */\r
1346 }\r
1347 \r
1348 void Rm_transactionProcessor (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
1349 {\r
1350     void                *validInstNode;\r
1351     Rm_NameServerObjCfg  nameServerObjCfg;      \r
1352     uint32_t             allocType = 0;\r
1353     \r
1354     /* Handle auto-forwarded transactions.  These transactions include:\r
1355      * - All request transactions received on Clients are forwarded to the Client Delegate\r
1356      * - NameServer requests received on the Client Delegate are forwarded to the Server */\r
1357     if ((rmInst->instType == Rm_instType_CLIENT) ||\r
1358         ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
1359          ((transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) ||\r
1360           (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) ||\r
1361           (transaction->type == Rm_service_RESOURCE_UNMAP_NAME)))) {\r
1362           \r
1363         if (transaction->state != RM_SERVICE_PROCESSING) {\r
1364             if (strcmp(transaction->serviceSrcInstName, rmInst->instName)) {\r
1365                 /* Transaction did not originate on this instance */\r
1366                 Rm_transactionResponder(rmInst, transaction);\r
1367             }\r
1368             else {\r
1369                 /* Transaction originated on this instance */\r
1370                 Rm_serviceResponder(rmInst, transaction);\r
1371             }\r
1372         }\r
1373         else {\r
1374             /* Forward new transaction */\r
1375             Rm_transactionForwarder(rmInst, transaction);\r
1376         }\r
1377     }\r
1378     else {\r
1379         /* Validate service's originating instance name */\r
1380         if (rmInst->instType == Rm_instType_SERVER) {\r
1381             validInstNode = Rm_policyGetValidInstNode(rmInst->validInstances, transaction->serviceSrcInstName);\r
1382             if (validInstNode == NULL) {\r
1383                 transaction->state = RM_SERVICE_DENIED_ORIGINATING_INSTANCE_NAME_NOT_VALID;\r
1384 \r
1385                 /* Send result via responder if transaction did not originate from this instance */\r
1386                 if (strcmp(transaction->serviceSrcInstName, rmInst->instName)) {\r
1387                     Rm_transactionResponder(rmInst, transaction);\r
1388                 }\r
1389             }\r
1390         }\r
1391 \r
1392         switch (transaction->type) {\r
1393             case Rm_service_RESOURCE_ALLOCATE_INIT:\r
1394             case Rm_service_RESOURCE_ALLOCATE_USE:\r
1395             case Rm_service_RESOURCE_FREE:               \r
1396                 if (transaction->state != RM_SERVICE_PROCESSING) {\r
1397                     /* Transaction complete */\r
1398                     if (strcmp(transaction->serviceSrcInstName, rmInst->instName)) {\r
1399                         /* Transaction result not destined for this instance */\r
1400                         Rm_transactionResponder(rmInst, transaction);\r
1401                     }\r
1402                     else {\r
1403                         /* Transaction result destined for this instance */\r
1404                         Rm_serviceResponder(rmInst, transaction);      \r
1405                     }\r
1406                 }\r
1407                 else {\r
1408                     /* Complete allocation/free request */\r
1409                     if (transaction->type == Rm_service_RESOURCE_FREE) {\r
1410                         Rm_freeHandler(rmInst, transaction, validInstNode);\r
1411                     }\r
1412                     else {\r
1413                         switch (transaction->type) {\r
1414                             case Rm_service_RESOURCE_ALLOCATE_INIT:\r
1415                                 RM_policy_SET_PERM(allocType, RM_POLICY_PERM_INIT_SHIFT, 1);\r
1416                                 break;\r
1417                             case Rm_service_RESOURCE_ALLOCATE_USE:\r
1418                                 RM_policy_SET_PERM(allocType, RM_POLICY_PERM_USE_SHIFT, 1);    \r
1419                                 break;\r
1420                         }\r
1421                         Rm_allocationHandler(rmInst, transaction, validInstNode, allocType);\r
1422                     }\r
1423                 }\r
1424                 break;\r
1425             case Rm_service_RESOURCE_MAP_TO_NAME:\r
1426             case Rm_service_RESOURCE_GET_BY_NAME:\r
1427             case Rm_service_RESOURCE_UNMAP_NAME:                \r
1428                 /* NameServer resides on server */\r
1429                 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));\r
1430                 nameServerObjCfg.nameServerTree = rmInst->nameServer;\r
1431                 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;\r
1432                 if (rmInst->instType == Rm_instType_SERVER) {\r
1433                     if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {\r
1434                         nameServerObjCfg.nodeCfg.resourceName = transaction->resourceInfo.name;\r
1435                         nameServerObjCfg.nodeCfg.resourceBase= transaction->resourceInfo.base;\r
1436                         nameServerObjCfg.nodeCfg.resourceLength = transaction->resourceInfo.length;\r
1437                         transaction->state = Rm_nameServerAddObject(&nameServerObjCfg);\r
1438                     }\r
1439                     else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {\r
1440                         if ((transaction->state = Rm_nameServerFindObject(&nameServerObjCfg)) ==\r
1441                             RM_SERVICE_PROCESSING) {\r
1442                             strcpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName);\r
1443                             transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;\r
1444                             transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;\r
1445                             transaction->state = RM_SERVICE_APPROVED_AND_COMPLETED;\r
1446                         } \r
1447                     }\r
1448                     else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {\r
1449                         transaction->state = Rm_nameServerDeleteObject(&nameServerObjCfg);\r
1450                     }\r
1451 \r
1452                     /* Send result via responder if transaction did not originate from this instance */\r
1453                     if (strcmp(transaction->serviceSrcInstName, rmInst->instName)) {\r
1454                         Rm_transactionResponder(rmInst, transaction);\r
1455                     }\r
1456                 }\r
1457                 else {\r
1458                     transaction->state = RM_SERVICE_ERROR_NAMESERVER_OBJECT_MOD_ON_INVALID_INSTANCE;\r
1459                 }\r
1460                 break;\r
1461         }\r
1462     }\r
1463 }\r
1464 \r
1465 int32_t Rm_reserveLinuxResource(Rm_Inst *rmInst, Rm_LinuxAlias *linuxAlias, \r
1466                                 Rm_LinuxValueRange *linuxValues, Rm_AllocatorOpInfo *opInfo)\r
1467 {\r
1468     int32_t  retVal = RM_DTB_UTIL_RESULT_OKAY;\r
1469     bool     baseFound = FALSE;\r
1470     bool     lengthFound = FALSE;\r
1471     uint32_t valueIndex = 0;\r
1472 \r
1473     while ((linuxValues != NULL) && (!baseFound || !lengthFound)) {\r
1474         if (linuxAlias->baseOffset == valueIndex) {\r
1475             opInfo->resourceInfo->base = linuxValues->value;\r
1476             baseFound = TRUE;\r
1477 \r
1478             if (linuxAlias->lengthOffset == RM_DTB_LINUX_ALIAS_OFFSET_NOT_SET) {\r
1479                 opInfo->resourceInfo->length = 1;\r
1480                 lengthFound = TRUE;\r
1481             }\r
1482         }\r
1483         else if (linuxAlias->lengthOffset == valueIndex) {\r
1484             opInfo->resourceInfo->length = linuxValues->value;\r
1485             lengthFound = TRUE;\r
1486         }\r
1487 \r
1488         linuxValues = (Rm_LinuxValueRange *)linuxValues->nextValue;\r
1489         valueIndex++;\r
1490     }\r
1491 \r
1492     if (!baseFound || !lengthFound) {\r
1493         retVal = -33; /* TODO: ERROR BASE OR LENGTH OFFSET IN LINUX DTB WAS INCORRECT */\r
1494     }\r
1495     else {\r
1496         /* Allocate resource to Linux */\r
1497         retVal = Rm_allocatorOperation(rmInst, opInfo);\r
1498     }\r
1499     return (retVal);\r
1500 }\r
1501 \r
1502 int32_t Rm_findAndReserveLinuxResource(Rm_Inst *rmInst, const char *resourceName, void *linuxDtb, \r
1503                                        Rm_LinuxAlias *linuxAlias)\r
1504 {\r
1505     Rm_AllocatorOpInfo  opInfo;\r
1506     Rm_ResourceInfo     resourceInfo;\r
1507     uint32_t            pathOffset;\r
1508     uint32_t            pathSize;\r
1509     char               *spacePtr;\r
1510     int32_t             propOffset;\r
1511     int32_t             nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;\r
1512     int32_t             prevDepth = RM_DTB_UTIL_STARTING_DEPTH;\r
1513     int32_t             depth;\r
1514     int32_t             propertyLen;\r
1515     const char         *propertyName;\r
1516     const void         *propertyData; \r
1517     Rm_LinuxValueRange *linuxValueRange;\r
1518     int32_t             retVal = RM_DTB_UTIL_RESULT_OKAY; \r
1519 \r
1520     memset((void *) &opInfo, 0, sizeof(Rm_AllocatorOpInfo));\r
1521     memset((void *) &resourceInfo, 0, sizeof(Rm_ResourceInfo));\r
1522 \r
1523     strcpy(resourceInfo.name, resourceName);\r
1524     opInfo.serviceSrcInstNode = Rm_policyGetLinuxInstNode(rmInst->validInstances);\r
1525     opInfo.operation = Rm_allocatorOp_ALLOCATE;\r
1526     opInfo.resourceInfo = &resourceInfo;    \r
1527 \r
1528     while(linuxAlias != NULL) {\r
1529         /* Reset parsing variables */\r
1530         pathOffset = 0;\r
1531         pathSize = strlen(linuxAlias->path) + 1;\r
1532         nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;\r
1533         prevDepth = RM_DTB_UTIL_STARTING_DEPTH;   \r
1534         resourceInfo.base = 0;\r
1535         resourceInfo.length = 0;\r
1536 \r
1537         spacePtr = strpbrk(linuxAlias->path, " ");\r
1538         if (spacePtr) {\r
1539             *spacePtr = '\0';\r
1540         }       \r
1541         \r
1542         while(pathOffset < pathSize) {\r
1543             /* Move through DTB nodes until next alias path node found */\r
1544             if (strcmp(linuxAlias->path + pathOffset, fdt_get_name(linuxDtb, nodeOffset, NULL))) {\r
1545                 nodeOffset = fdt_next_node(linuxDtb, nodeOffset, &depth);\r
1546 \r
1547                 if ((depth < prevDepth) || (nodeOffset == -FDT_ERR_NOTFOUND)) {\r
1548                     /* Returning from subnode that matched part of alias path without finding\r
1549                      * resource values */\r
1550                     retVal = (-31); /* TODO: COULD NOT FIND RESOURCE AT ALIAS PATH */\r
1551                     break;\r
1552                 }\r
1553             }\r
1554             else {\r
1555                 /* Found next alias path node.  Move to next node name in path string. */\r
1556                 pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);\r
1557                 spacePtr = strpbrk(linuxAlias->path + pathOffset, " ");\r
1558                 if (spacePtr) {\r
1559                     *spacePtr = '\0';\r
1560                 }       \r
1561                 \r
1562                 prevDepth = fdt_node_depth(linuxDtb, nodeOffset);\r
1563                 propOffset = fdt_first_property_offset(linuxDtb, nodeOffset);\r
1564                 while ((propOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) &&\r
1565                        (pathOffset < pathSize)) {\r
1566                     propertyData = fdt_getprop_by_offset(linuxDtb, propOffset, \r
1567                                                          &propertyName, &propertyLen);\r
1568 \r
1569                     if (strcmp(linuxAlias->path + pathOffset, propertyName) == 0) {\r
1570                         /* Found resource at end of alias path */\r
1571                         pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);\r
1572                         linuxValueRange = Rm_linuxExtractValues(propertyData, propertyLen);\r
1573                         retVal = Rm_reserveLinuxResource(rmInst, linuxAlias, \r
1574                                                          linuxValueRange, &opInfo);\r
1575                         Rm_linuxFreeValues(linuxValueRange);\r
1576                     }\r
1577                     propOffset = fdt_next_property_offset(linuxDtb, propOffset);\r
1578                 } \r
1579 \r
1580                 if (propOffset < -FDT_ERR_NOTFOUND) {\r
1581                     retVal = propOffset;\r
1582                     break;\r
1583                 }\r
1584             }\r
1585         }\r
1586 \r
1587         if (retVal < RM_DTB_UTIL_RESULT_OKAY) {\r
1588             break;\r
1589         }\r
1590         linuxAlias = (Rm_LinuxAlias *) linuxAlias->nextLinuxAlias;\r
1591     }\r
1592     return (retVal);\r
1593 }\r
1594 \r
1595 int32_t Rm_createAndInitAllocator(Rm_Inst *rmInst, const char *resourceName, \r
1596                                   Rm_ResourceProperties *resourceProperties, void *linuxDtb)\r
1597 {\r
1598     Rm_ResourceRange *range = NULL;\r
1599     Rm_ResourceRange *rangeBasePtr = NULL;\r
1600     Rm_NsAssignment *nsAssignments = NULL;\r
1601     Rm_NsAssignment *nsAssignmentBasePtr = NULL;\r
1602     Rm_LinuxAlias *linuxAlias = NULL;\r
1603     Rm_NameServerObjCfg  nameServerObjCfg;      \r
1604     int32_t retVal = RM_DTB_UTIL_RESULT_OKAY;\r
1605 \r
1606     if (resourceProperties->rangeData && (resourceProperties->rangeLen > 0))\r
1607     {\r
1608         /* Extract the resource properties from the DTB */\r
1609         range = rangeBasePtr = Rm_resourceExtractRange(resourceProperties->rangeData, \r
1610                                                        resourceProperties->rangeLen);\r
1611 \r
1612         /* Create a tree allocator using the resource properties */\r
1613         retVal = Rm_createTreeAllocator(rmInst, resourceName, range); \r
1614 \r
1615         if (retVal >= RM_DTB_UTIL_RESULT_OKAY)\r
1616         {\r
1617             if (resourceProperties->linuxAliasData && resourceProperties->linuxAliasLen)\r
1618             {\r
1619                 /* Reserve the resources taken by the Linux kernel specified in the Linux DTB */\r
1620                 linuxAlias = Rm_resourceExtractLinuxAlias(resourceProperties->linuxAliasData,\r
1621                                                           resourceProperties->linuxAliasLen);\r
1622 \r
1623                 retVal = Rm_findAndReserveLinuxResource(rmInst, resourceName, linuxDtb, linuxAlias);            \r
1624             }\r
1625         }\r
1626     }\r
1627     \r
1628     if (retVal >= RM_DTB_UTIL_RESULT_OKAY)\r
1629     {\r
1630         /* Create entries in the NameServer if any NameServer assignments were specified */\r
1631         if (resourceProperties->nsAssignData && resourceProperties->nsAssignLen)\r
1632         {\r
1633             nsAssignments = Rm_resourceExtractNsAssignment(resourceProperties->nsAssignData, \r
1634                                                            resourceProperties->nsAssignLen);\r
1635 \r
1636             /* Cycle through the list of assignments and add them to the NameServer */\r
1637             nsAssignmentBasePtr = nsAssignments;\r
1638             while (nsAssignments)\r
1639             {\r
1640                 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));\r
1641                 nameServerObjCfg.nameServerTree = rmInst->nameServer;\r
1642                 nameServerObjCfg.nodeCfg.objName = nsAssignments->nsName;\r
1643                 nameServerObjCfg.nodeCfg.resourceName = (char *)resourceName;\r
1644                 nameServerObjCfg.nodeCfg.resourceBase= nsAssignments->resourceBase;\r
1645                 nameServerObjCfg.nodeCfg.resourceLength = nsAssignments->resourceLength;                \r
1646                 \r
1647                 /* TODO: RETURN IF ANY OF THE ADDS FAIL??? */\r
1648                 Rm_nameServerAddObject(&nameServerObjCfg);\r
1649                 nsAssignments = nsAssignments->nextNsAssignment;\r
1650             }\r
1651             /* Free the memory allocated for the NameServer assignments */\r
1652             Rm_resourceFreeNsAssignmentList(nsAssignmentBasePtr);\r
1653         }\r
1654     }\r
1655 \r
1656     /* Free the memory allocated for the resource properties */\r
1657     Rm_resourceFreeRange(rangeBasePtr);\r
1658     Rm_resourceFreeLinuxAlias(linuxAlias);\r
1659 \r
1660     return(retVal);\r
1661 }\r
1662 \r
1663 int32_t Rm_parseResourceProperty(void *globalResourceDtb, int32_t offset, Rm_ResourceProperties *propertyInfo)\r
1664 {\r
1665         int32_t propertyLen;\r
1666         const char *propertyName;\r
1667         const void *propertyData;\r
1668     Rm_ResourcePropType propertyType;\r
1669     int32_t retVal = RM_DTB_UTIL_RESULT_OKAY;\r
1670 \r
1671     /* Get the property data and store it in the corresponding propertyInfo field */\r
1672         propertyData = fdt_getprop_by_offset(globalResourceDtb, offset, &propertyName, &propertyLen);\r
1673     if (propertyData)\r
1674     {\r
1675         propertyType = Rm_resourceGetPropertyType(propertyName);\r
1676         if (propertyType == Rm_resourcePropType_RESOURCE_RANGE)\r
1677         {\r
1678             if (propertyInfo->rangeData || propertyInfo->rangeLen)\r
1679             {\r
1680                 /* The range fields have already been populated.  Return an error.\r
1681                  * The resource list has specified a property field more than once\r
1682                  * for a resource node */\r
1683                 retVal = -18; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
1684             }\r
1685             else\r
1686             {\r
1687                 propertyInfo->rangeData = propertyData;\r
1688                 propertyInfo->rangeLen = propertyLen;\r
1689             }\r
1690         }\r
1691         else if (propertyType == Rm_resourcePropType_NSASSIGNMENT)\r
1692         {\r
1693             if (propertyInfo->nsAssignData || propertyInfo->nsAssignLen)\r
1694             {\r
1695                 /* The nsAssign fields have already been populated.  Return an error.\r
1696                  * The resource list has specified a property field more than once\r
1697                  * for a resource node */\r
1698                 retVal = -19; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
1699             }\r
1700             else\r
1701             {\r
1702                 propertyInfo->nsAssignData = propertyData;\r
1703                 propertyInfo->nsAssignLen = propertyLen;\r
1704             }\r
1705         }\r
1706         else if (propertyType == Rm_resourcePropType_RESOURCE_LINUX_ALIAS)\r
1707         {\r
1708             if (propertyInfo->linuxAliasData || propertyInfo->linuxAliasLen)\r
1709             {\r
1710                 /* The linuxAlias fields have already been populated.  Return an error.\r
1711                  * The resource list has specified a property field more than once\r
1712                  * for a resource node */\r
1713                 retVal = -28; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
1714             }\r
1715             else\r
1716             {\r
1717                 propertyInfo->linuxAliasData = propertyData;\r
1718                 propertyInfo->linuxAliasLen = propertyLen;\r
1719             }\r
1720         }        \r
1721         else\r
1722         {\r
1723             retVal = -20; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
1724         }\r
1725     }\r
1726     else\r
1727     {\r
1728         retVal = -16; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
1729     }\r
1730 \r
1731     /* Don't get anymore properties if error occurred */\r
1732     if (retVal == RM_DTB_UTIL_RESULT_OKAY)\r
1733     {\r
1734         offset = fdt_next_property_offset(globalResourceDtb, offset);\r
1735         if (offset >= 0)\r
1736         {\r
1737             retVal = Rm_parseResourceProperty(globalResourceDtb, offset, propertyInfo);\r
1738         }\r
1739         else if (offset != -FDT_ERR_NOTFOUND)\r
1740         {\r
1741             /* Error was returned by LIBFDT when parsing the properties */\r
1742             retVal = offset;\r
1743         }\r
1744     }\r
1745     \r
1746     return (retVal);\r
1747 }\r
1748 \r
1749 int32_t Rm_parseResourceNode(Rm_Inst *rmInst, void *globalResourceDtb, int32_t nodeOffset, int32_t depth,\r
1750                              void *linuxDtb)\r
1751 {\r
1752         const char *resourceName = fdt_get_name(globalResourceDtb, nodeOffset, NULL);\r
1753     Rm_ResourceProperties resourceProperties;\r
1754         int32_t error = RM_DTB_UTIL_RESULT_OKAY;\r
1755         int32_t offset;\r
1756 \r
1757     /* Initialize the resource properties structure */\r
1758     memset((void *)&resourceProperties, 0, sizeof(Rm_ResourceProperties));\r
1759 \r
1760     /* Ignore properties of the base node */\r
1761     if (strcmp(resourceName, rmDtbStartingNode))\r
1762     {\r
1763         /* Get the properties for the resource node if any exist */\r
1764         offset = fdt_first_property_offset(globalResourceDtb, nodeOffset);\r
1765         if (offset >= RM_DTB_UTIL_STARTING_NODE_OFFSET)\r
1766         {\r
1767             /* Since at least one property exists attempt to parse the property nodes and \r
1768              * use them to create and initialize a resource allocator */\r
1769                 error =  Rm_parseResourceProperty(globalResourceDtb, offset, &resourceProperties);\r
1770             if (error < -FDT_ERR_NOTFOUND)\r
1771             {\r
1772                 return (error);\r
1773             }\r
1774             \r
1775             /* Initialize an allocator with the resource properties if no error was returned */\r
1776             Rm_createAndInitAllocator(rmInst, resourceName, &resourceProperties, linuxDtb);\r
1777         }\r
1778         else if (offset != -FDT_ERR_NOTFOUND)\r
1779         {\r
1780                 /* Error was returned by LIBFDT when parsing the properties */\r
1781             return (offset);\r
1782         }\r
1783     }\r
1784     \r
1785     /* Get the next resource node */\r
1786         offset = fdt_next_node(globalResourceDtb, nodeOffset, &depth);\r
1787     /* Check the offset and depth of the next node to make sure the current node\r
1788      * wasn't the last node in the Resource List.  A depth less than the depth set\r
1789      * at the start of the recursion will signal the end of the resource list */\r
1790     if ((offset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && (depth >= RM_DTB_UTIL_STARTING_DEPTH))\r
1791     {\r
1792         error = Rm_parseResourceNode(rmInst, globalResourceDtb, offset, depth, linuxDtb);\r
1793         if (error < -FDT_ERR_NOTFOUND)\r
1794         {\r
1795             return (error);\r
1796         }\r
1797     }\r
1798     else if (offset != -FDT_ERR_NOTFOUND)\r
1799     {\r
1800         /* Error was returned by LIBFDT when parsing the nodes */\r
1801         return (offset);\r
1802     }\r
1803 \r
1804     return (RM_DTB_UTIL_RESULT_OKAY);\r
1805 }\r
1806 \r
1807 int32_t Rm_initializeAllocators(Rm_Inst *rmInst, void *globalResourceDtb, void *linuxDtb)\r
1808 {\r
1809     int32_t nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;\r
1810     int32_t startDepth = RM_DTB_UTIL_STARTING_DEPTH;\r
1811     int32_t result = RM_DTB_UTIL_RESULT_OKAY;\r
1812 \r
1813     /* Recursively parse the Global Resource List, creating an allocator for\r
1814      * each resource as specified in the node */\r
1815     result = Rm_parseResourceNode(rmInst, globalResourceDtb, nodeOffset, startDepth, linuxDtb);\r
1816 \r
1817     return(result);\r
1818 }\r
1819      \r
1820 /**********************************************************************\r
1821  ********************** Application visible APIs **********************\r
1822  **********************************************************************/\r
1823 \r
1824 /* Server Only */\r
1825 void Rm_printResourceStatus(Rm_Handle *rmHandle)\r
1826 {\r
1827     Rm_Inst         *rmInst = (Rm_Inst *) rmHandle;\r
1828     Rm_Allocator    *allocator = rmInst->allocators;\r
1829     Rm_AllocatedTo  *allocatedTo;\r
1830     Rm_ResourceTree *treeRoot;\r
1831     Rm_ResourceNode *treeNode;\r
1832 \r
1833     while (allocator != NULL) {\r
1834         Rm_osalLog("Resource: %s\n", allocator->resourceName);\r
1835 \r
1836         treeRoot = allocator->allocatorRootEntry;\r
1837 \r
1838         RB_FOREACH(treeNode, _Rm_ResourceTree, treeRoot) {               \r
1839             Rm_osalLog("          %10d - %10d ", treeNode->base, \r
1840                                                  treeNode->base + treeNode->length -1);\r
1841             \r
1842             if (treeNode->allocationCount == 0) {\r
1843                 Rm_osalLog("NOT ALLOCATED\n");\r
1844             }\r
1845             else {\r
1846                 allocatedTo = treeNode->allocatedTo;\r
1847                 Rm_osalLog("allocated to ");\r
1848                 while (allocatedTo) {\r
1849                     Rm_osalLog(" %s", allocatedTo->instNameNode->name);\r
1850                     allocatedTo = allocatedTo->nextAllocatedTo;\r
1851                 }\r
1852                 Rm_osalLog("\n");\r
1853             }\r
1854         }        \r
1855         allocator = allocator->nextAllocator;\r
1856     }\r
1857 \r
1858     Rm_nameServerPrintObjects(rmInst->nameServer);\r
1859 }\r
1860 \r
1861 Rm_PreMainHandle Rm_preMainInit(Rm_PreMainInitCfg *preMainInitCfg, int32_t *result)\r
1862 {\r
1863     Rm_PreMainInst *preMainInst;\r
1864 \r
1865     if ((strlen(preMainInitCfg->instName) + 1) > RM_INSTANCE_NAME_MAX_CHARS) {\r
1866         *result = RM_INIT_ERROR_INSTANCE_NAME_TOO_BIG;\r
1867         return (NULL);\r
1868     }\r
1869 \r
1870     preMainInst = (Rm_PreMainInst *) Rm_osalMalloc (sizeof(Rm_PreMainInst));\r
1871     fdt_open_into(preMainInitCfg->startupPolicyDtb, preMainInitCfg->startupPolicyDtb,\r
1872                   fdt_totalsize(preMainInitCfg->startupPolicyDtb));\r
1873     preMainInst->startupDtb = preMainInitCfg->startupPolicyDtb;\r
1874 \r
1875     preMainInst->validInstTree = Rm_policyCreateValidInstTree(preMainInst->startupDtb, result);\r
1876     if (*result == RM_INIT_OK) {\r
1877         /* Validate policy assignment strings */\r
1878         *result = Rm_policyValidatePolicy(preMainInitCfg->startupPolicyDtb, preMainInst->validInstTree);\r
1879     }\r
1880 \r
1881     if (*result != RM_INIT_OK) {\r
1882         if (preMainInst->validInstTree) {\r
1883             Rm_policyFreeValidInstTree(preMainInst->validInstTree);\r
1884         }\r
1885         Rm_osalFree((void *)preMainInst, sizeof(Rm_PreMainInst));\r
1886         preMainInst = NULL;\r
1887     }\r
1888     else {\r
1889         strcpy(preMainInst->instName, preMainInitCfg->instName);\r
1890         preMainInst->requestCount = 0;\r
1891         preMainInst->preMainReqList = NULL;\r
1892     }\r
1893 \r
1894     return((Rm_PreMainHandle)preMainInst);\r
1895 }\r
1896 \r
1897 int32_t Rm_preMainHandleValidateAndDelete(Rm_Handle rmHandle, Rm_PreMainHandle rmPreMainHandle)\r
1898 {\r
1899     Rm_Inst              *rmInst = (Rm_Inst *)rmHandle;\r
1900     Rm_PreMainInst       *preMainInst = (Rm_PreMainInst *)rmPreMainHandle;\r
1901     Rm_ServicePreMainReq *serviceReq = preMainInst->preMainReqList;\r
1902     Rm_ServicePreMainReq *nextServiceReq;\r
1903     int32_t retVal = RM_INIT_OK;\r
1904 \r
1905     if (strcmp(rmInst->instName, preMainInst->instName) == 0) {\r
1906         /* TODO: Validate the requests against the global policyDtb */\r
1907 \r
1908         /* Free all memory associated with the pre-main instance */\r
1909         Rm_policyFreeValidInstTree(preMainInst->validInstTree);\r
1910         while(serviceReq) {\r
1911             nextServiceReq = serviceReq->nextPreMainReq;\r
1912             Rm_osalFree((void *)serviceReq->preMainReq, sizeof(Rm_ServiceReqInfo));\r
1913             Rm_osalFree((void *)serviceReq, sizeof(Rm_ServicePreMainReq));\r
1914             serviceReq = nextServiceReq;\r
1915         }\r
1916         Rm_osalFree((void *)preMainInst, sizeof(Rm_PreMainInst));\r
1917     }\r
1918     else {\r
1919         retVal = RM_INIT_ERROR_PREMAIN_INST_AND_POSTMAIN_INST_NAMES_DONT_MATCH;\r
1920     }\r
1921     return(retVal);\r
1922 }\r
1923 \r
1924 Rm_Handle Rm_init(Rm_InitCfg *initCfg, int32_t *result)\r
1925 {\r
1926     Rm_Inst *rmInst;\r
1927     void    *globalResourceDtb = NULL;\r
1928     void    *linuxResourceDtb = NULL;\r
1929     void    *policyDtb = NULL;\r
1930 \r
1931     *result = RM_INIT_OK;\r
1932     \r
1933     if ((strlen(initCfg->instName) + 1) > RM_INSTANCE_NAME_MAX_CHARS) {\r
1934         *result = RM_INIT_ERROR_INSTANCE_NAME_TOO_BIG;\r
1935         return (NULL);\r
1936     }\r
1937 \r
1938     /* Create and initialize instance */\r
1939     rmInst = Rm_osalMalloc (sizeof(Rm_Inst));\r
1940     memset ((void *) rmInst, 0, sizeof(Rm_Inst));\r
1941     strcpy (rmInst->instName, initCfg->instName);\r
1942     rmInst->instType = initCfg->instType;\r
1943     rmInst->registeredWithDelegateOrServer = false;\r
1944     rmInst->routeMap = NULL;\r
1945     rmInst->allocators = NULL;\r
1946     rmInst->nameServer = NULL;\r
1947     rmInst->policy = NULL;\r
1948     rmInst->validInstances = NULL;\r
1949     rmInst->transactionSeqNum = Rm_transactionInitSequenceNum();\r
1950     rmInst->transactionQueue= NULL;\r
1951 \r
1952     if ((rmInst->instType != Rm_instType_CLIENT) && initCfg->policy) {\r
1953         policyDtb = initCfg->policy;\r
1954         fdt_open_into(policyDtb, policyDtb, fdt_totalsize(policyDtb)); \r
1955 \r
1956         /* Create valid instance list from policy.  Must be done prior to parsing\r
1957          * GRL so that Linux resources can be reserved correctly */\r
1958         rmInst->validInstances = Rm_policyCreateValidInstTree(policyDtb, result);\r
1959         /* Validate policy assignment strings */\r
1960         *result = Rm_policyValidatePolicy(rmInst, policyDtb);\r
1961         rmInst->policy = policyDtb;\r
1962     }\r
1963 \r
1964     /* RM Server specific actions */\r
1965     if (rmInst->instType == Rm_instType_SERVER) {\r
1966         Rm_nameServerInit();\r
1967 \r
1968         if (initCfg->globalResourceList) {\r
1969             globalResourceDtb = initCfg->globalResourceList;\r
1970             fdt_open_into(globalResourceDtb, globalResourceDtb, fdt_totalsize(globalResourceDtb));\r
1971 \r
1972             if (initCfg->linuxDtb) {\r
1973                 linuxResourceDtb = initCfg->linuxDtb;\r
1974                 fdt_open_into(linuxResourceDtb, linuxResourceDtb, fdt_totalsize(linuxResourceDtb));   \r
1975             }\r
1976             Rm_initializeAllocators(rmInst, globalResourceDtb, linuxResourceDtb);\r
1977         }\r
1978     }\r
1979 \r
1980     if ((rmInst->instType != Rm_instType_CLIENT) && initCfg->policy) {\r
1981         *result = Rm_policyValidatePolicyResourceNames(rmInst, policyDtb);\r
1982     }    \r
1983 \r
1984     return ((Rm_Handle) rmInst);\r
1985 }\r
1986 \r
1987 uint32_t Rm_getVersion (void)\r
1988 {\r
1989     return RM_VERSION_ID;\r
1990 }\r
1991 \r
1992 \r
1993 const char* Rm_getVersionStr (void)\r
1994 {\r
1995     return rmVersionStr;\r
1996 }\r
1997 \r
1998 /**\r
1999 @}\r
2000 */\r