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