273c1759364e535d3fc4f21255661f245c03af74
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