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_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 #include <ti/drv/rm/include/rm_treeloc.h>\r
59 \r
60 /* RM LIBFDT includes */\r
61 #include <ti/drv/rm/util/libfdt/libfdt.h>\r
62 \r
63 /* Tree algorithm includes */\r
64 #include <ti/drv/rm/util/tree.h>\r
65 \r
66 /* RM OSAL layer */\r
67 #include <rm_osal.h>\r
68 \r
69 /**********************************************************************\r
70 ************************** Globals ***********************************\r
71 **********************************************************************/\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 ************************ Local Functions *****************************\r
78 **********************************************************************/\r
79 \r
80 /* FUNCTION PURPOSE: Initializes a RM inst's transaction sequence number\r
81 ***********************************************************************\r
82 * DESCRIPTION: The RM instance transaction sequence number can never\r
83 * have a value of 0 to avoid conflicts with transactions\r
84 * that have a remoteOriginatingId of 0 (transaction ID\r
85 * will be used as the remoteOriginatingId for\r
86 * transactions that are responses to requests).\r
87 */\r
88 static uint32_t transactionInitSequenceNum(void)\r
89 {\r
90 return (1);\r
91 }\r
92 \r
93 /* FUNCTION PURPOSE: Provides a sequence number for new transactions\r
94 ***********************************************************************\r
95 * DESCRIPTION: Returns a sequence number for a new transaction\r
96 * specific to a RM instance. Handles rollover of\r
97 * sequence number.\r
98 */\r
99 static uint32_t transactionGetSequenceNum(Rm_Inst *rmInst)\r
100 {\r
101 uint32_t sequenceNum = 0;\r
102 \r
103 if (rmInst->transactionSeqNum + 1 < rmInst->transactionSeqNum) {\r
104 /* Rollover */\r
105 sequenceNum = rmInst->transactionSeqNum;\r
106 rmInst->transactionSeqNum = transactionInitSequenceNum();\r
107 }\r
108 else {\r
109 sequenceNum = rmInst->transactionSeqNum++;\r
110 } \r
111 return (sequenceNum);\r
112 }\r
113 \r
114 /* FUNCTION PURPOSE: Creates a resource allocator\r
115 ***********************************************************************\r
116 * DESCRIPTION: Returns a newly Created and initialized resource\r
117 * The allocator is also stored in the RM instance\r
118 * allocator list. \r
119 */\r
120 static Rm_Allocator *allocatorAdd(Rm_Inst *rmInst, const char *resourceName)\r
121 {\r
122 Rm_Allocator *allocators = rmInst->allocators;\r
123 Rm_Allocator *newAllocator = NULL;\r
124 \r
125 newAllocator = Rm_osalMalloc(sizeof(Rm_Allocator));\r
126 \r
127 if (newAllocator) {\r
128 memset((void *)newAllocator, 0, sizeof(Rm_Allocator));\r
129 strncpy(newAllocator->resourceName, resourceName, RM_NAME_MAX_CHARS);\r
130 newAllocator->allocatorRootEntry = NULL;\r
131 newAllocator->nextAllocator = NULL; \r
132 \r
133 /* Add allocator to end of list */\r
134 if (allocators) {\r
135 while (allocators->nextAllocator) {\r
136 allocators = allocators->nextAllocator;\r
137 }\r
138 allocators->nextAllocator = newAllocator;\r
139 }\r
140 else {\r
141 rmInst->allocators = newAllocator;\r
142 }\r
143 }\r
144 return (newAllocator);\r
145 }\r
146 \r
147 /* FUNCTION PURPOSE: Deletes a resource allocator\r
148 ***********************************************************************\r
149 * DESCRIPTION: Deletes a resource allocator based on the given\r
150 * resource name. The resource allocator will be\r
151 * removed from the RM instance allocator list.\r
152 */\r
153 static int32_t allocatorDelete(Rm_Inst *rmInst, char *resourceName)\r
154 {\r
155 Rm_Allocator *allocator = rmInst->allocators;\r
156 Rm_Allocator *prevAllocator = NULL;\r
157 int32_t retVal = RM_OK;\r
158 \r
159 while (allocator) {\r
160 if (strncmp(allocator->resourceName, resourceName, RM_NAME_MAX_CHARS) == 0) {\r
161 break; \r
162 }\r
163 prevAllocator = allocator;\r
164 allocator = allocator->nextAllocator;\r
165 }\r
166 \r
167 if (allocator) {\r
168 if (prevAllocator == NULL) {\r
169 rmInst->allocators = allocator->nextAllocator;\r
170 }\r
171 else {\r
172 prevAllocator->nextAllocator = allocator->nextAllocator;\r
173 }\r
174 Rm_osalFree((void *)allocator, sizeof(Rm_Allocator));\r
175 }\r
176 else {\r
177 retVal = RM_ERROR_RES_ALLOCATOR_DOES_NOT_EXIST;\r
178 }\r
179 return (retVal);\r
180 }\r
181 \r
182 /* FUNCTION PURPOSE: Adds an owner to an allocator resource\r
183 ***********************************************************************\r
184 * DESCRIPTION: Adds a RM instance node to a resource node's\r
185 * list of owners.\r
186 */\r
187 static void addOwner(Rm_ResourceNode *node, void *serviceInstNode)\r
188 {\r
189 Rm_Owner *ownerList = node->ownerList;\r
190 Rm_Owner *newOwner = NULL;\r
191 \r
192 newOwner = Rm_osalMalloc(sizeof(Rm_Owner));\r
193 \r
194 if (newOwner) {\r
195 newOwner->instNameNode = serviceInstNode;\r
196 newOwner->nextOwner = NULL; \r
197 \r
198 /* Add owner entry to end of list */\r
199 if (ownerList) {\r
200 while (ownerList->nextOwner) {\r
201 ownerList = ownerList->nextOwner;\r
202 }\r
203 ownerList->nextOwner = newOwner;\r
204 }\r
205 else {\r
206 node->ownerList = newOwner;\r
207 }\r
208 \r
209 node->allocationCount++;\r
210 newOwner->instNameNode->allocRefCount++;\r
211 }\r
212 }\r
213 \r
214 /* FUNCTION PURPOSE: Checks a resource node's ownership\r
215 ***********************************************************************\r
216 * DESCRIPTION: Returns TRUE if the provided instance node is\r
217 * in the list of resource node owners. Otherwise,\r
218 * returns FALSE.\r
219 */\r
220 static bool isOwnedBy(Rm_ResourceNode *node, void *serviceInstNode)\r
221 {\r
222 Rm_Owner *owner = node->ownerList;\r
223 \r
224 while (owner) {\r
225 if (owner->instNameNode == serviceInstNode) {\r
226 return(true); \r
227 }\r
228 owner = owner->nextOwner;\r
229 }\r
230 return(false);\r
231 }\r
232 \r
233 /* FUNCTION PURPOSE: Compares two resource node's owners\r
234 ***********************************************************************\r
235 * DESCRIPTION: Returns TRUE if the owners of two resource nodes \r
236 * are equivalent. Otherwise, returns FALSE.\r
237 */\r
238 static bool compareResourceNodeOwners(Rm_ResourceNode *node1, Rm_ResourceNode *node2)\r
239 {\r
240 Rm_Owner *node1Owners = node1->ownerList;\r
241 Rm_Owner *node2Owners = node2->ownerList;\r
242 bool matchedInst;\r
243 \r
244 if (node1->allocationCount == node2->allocationCount) {\r
245 while (node1Owners) {\r
246 matchedInst = false;\r
247 while (node2Owners) {\r
248 if (node1Owners->instNameNode == node2Owners->instNameNode) {\r
249 matchedInst = true;\r
250 break;\r
251 }\r
252 node2Owners = node2Owners->nextOwner;\r
253 }\r
254 \r
255 if (matchedInst) {\r
256 node2Owners = node2->ownerList;\r
257 node1Owners = node1Owners->nextOwner;\r
258 }\r
259 else {\r
260 return(false);\r
261 } \r
262 }\r
263 }\r
264 else {\r
265 return(false);\r
266 } \r
267 \r
268 return(true);\r
269 }\r
270 \r
271 /* FUNCTION PURPOSE: Deletes an owner from an allocator resource\r
272 ***********************************************************************\r
273 * DESCRIPTION: Removes a RM instance node from a resource node's\r
274 * list of owners.\r
275 */\r
276 static void deleteOwner(Rm_ResourceNode *node, void *serviceInstNode)\r
277 {\r
278 Rm_Owner *owner = node->ownerList;\r
279 Rm_Owner *prevOwner = NULL;\r
280 \r
281 while (owner) {\r
282 if (owner->instNameNode == serviceInstNode) {\r
283 break; \r
284 }\r
285 prevOwner = owner;\r
286 owner = owner->nextOwner;\r
287 }\r
288 \r
289 if (prevOwner == NULL) {\r
290 node->ownerList = owner->nextOwner;\r
291 }\r
292 else {\r
293 prevOwner->nextOwner = owner->nextOwner;\r
294 }\r
295 \r
296 node->allocationCount--;\r
297 owner->instNameNode->allocRefCount--;\r
298 Rm_osalFree((void *)owner, sizeof(Rm_Owner));\r
299 }\r
300 \r
301 /* FUNCTION PURPOSE: Copies the owners of a resource node\r
302 ***********************************************************************\r
303 * DESCRIPTION: Creates a list of resource owners for the destination\r
304 * resource node that is equivalent to the the \r
305 * source resource node's owners\r
306 */\r
307 static void copyOwners(Rm_ResourceNode *dstNode, Rm_ResourceNode *srcNode)\r
308 {\r
309 Rm_Owner *srcOwnerList = srcNode->ownerList;\r
310 Rm_Owner *dstNewOwner;\r
311 Rm_Owner *dstPrevOwner;\r
312 \r
313 dstNode->allocationCount = srcNode->allocationCount;\r
314 \r
315 while (srcOwnerList) {\r
316 dstNewOwner = Rm_osalMalloc(sizeof(Rm_Owner));\r
317 dstNewOwner->instNameNode = srcOwnerList->instNameNode;\r
318 dstNewOwner->nextOwner = NULL;\r
319 \r
320 if (dstNode->ownerList == NULL) {\r
321 dstNode->ownerList = dstNewOwner;\r
322 }\r
323 else {\r
324 dstPrevOwner->nextOwner = dstNewOwner;\r
325 }\r
326 dstPrevOwner = dstNewOwner;\r
327 srcOwnerList = srcOwnerList->nextOwner;\r
328 }\r
329 }\r
330 \r
331 /* FUNCTION PURPOSE: Clears a resource node's owners\r
332 ***********************************************************************\r
333 * DESCRIPTION: Deletes all owners from the owners list of a \r
334 * resource node.\r
335 */\r
336 static void clearOwners(Rm_ResourceNode *node)\r
337 {\r
338 Rm_Owner *owner = node->ownerList;\r
339 Rm_Owner *nextOwner;\r
340 \r
341 while (owner) {\r
342 nextOwner = owner->nextOwner;\r
343 node->allocationCount--;\r
344 Rm_osalFree((void *)owner, sizeof(Rm_Owner));\r
345 owner = nextOwner;\r
346 }\r
347 }\r
348 \r
349 /* FUNCTION PURPOSE: Creates a new resource tree\r
350 ***********************************************************************\r
351 * DESCRIPTION: Creates a new resource tree using the provided\r
352 * resource name and value range. The name and value\r
353 * typically originate from the GRL.\r
354 */\r
355 static int32_t createResourceTree(Rm_Inst *rmInst, const char *resourceName, Rm_ResourceRange *range)\r
356 {\r
357 Rm_Allocator *allocator = NULL;\r
358 Rm_ResourceTree *treeRootEntry = NULL;\r
359 Rm_ResourceNode *treeNode = NULL;\r
360 Rm_ResourceNode *collidingNode = NULL;\r
361 \r
362 allocator = allocatorAdd(rmInst, resourceName);\r
363 treeRootEntry = Rm_osalMalloc(sizeof(Rm_ResourceTree));\r
364 RB_INIT(treeRootEntry);\r
365 \r
366 while (range != NULL) {\r
367 treeNode = rmResourceNodeNew(range->base, range->length);\r
368 collidingNode = RB_INSERT(_Rm_AllocatorResourceTree, treeRootEntry, treeNode);\r
369 \r
370 if (collidingNode) {\r
371 Rm_ResourceNode *nextNode = NULL;\r
372 \r
373 /* Node that was inserted collides with existing node. Destroy tree and return error */\r
374 for (treeNode = RB_MIN(_Rm_AllocatorResourceTree, treeRootEntry); treeNode != NULL; treeNode = nextNode) {\r
375 nextNode = RB_NEXT(_Rm_AllocatorResourceTree, treeRootEntry, treeNode);\r
376 RB_REMOVE(_Rm_AllocatorResourceTree, treeRootEntry, nextNode);\r
377 rmResourceNodeFree(treeNode);\r
378 }\r
379 Rm_osalFree((void *)treeRootEntry, sizeof(Rm_ResourceTree));\r
380 allocatorDelete(rmInst, allocator->resourceName);\r
381 return (RM_ERROR_GRL_RES_SPECIFIED_MORE_THAN_ONCE);\r
382 }\r
383 range = range->nextRange;\r
384 }\r
385 \r
386 allocator->allocatorRootEntry = treeRootEntry;\r
387 return(RM_OK);\r
388 }\r
389 \r
390 /* FUNCTION PURPOSE: Preallocates a resource\r
391 ***********************************************************************\r
392 * DESCRIPTION: Called when an allocate request is made but the base \r
393 * is unspecified. The preallocation algorithm looks at \r
394 * available resources as well as policy permissions to \r
395 * determine a resource range that satisfies the request.\r
396 * If a valid range is found it will be returned for the \r
397 * treeAllocate algorithm to handle.\r
398 */\r
399 static int32_t treePreAllocate(Rm_Inst *rmInst, Rm_Allocator *allocator, int32_t resourcePolicy,\r
400 Rm_AllocatorOpInfo *opInfo)\r
401 {\r
402 Rm_ResourceNode findNode;\r
403 Rm_ResourceNode *matchingNode = NULL;\r
404 uint32_t matchingEnd;\r
405 uint32_t rangeIndex;\r
406 bool resourceFound = false;\r
407 Rm_PolicyCheckType policyCheckType;\r
408 Rm_PolicyCheckCfg policyCheckCfg;\r
409 bool nodePassesPolicy;\r
410 int32_t retVal = RM_SERVICE_PROCESSING; \r
411 \r
412 opInfo->resourceInfo->base = rmPolicyGetResourceBase(rmInst->policy, opInfo->serviceSrcInstNode, \r
413 resourcePolicy, opInfo->allocType, \r
414 &retVal);\r
415 if (retVal != RM_SERVICE_PROCESSING) {\r
416 return (retVal);\r
417 }\r
418 \r
419 if (opInfo->resourceInfo->alignment == RM_RESOURCE_ALIGNMENT_UNSPECIFIED) { \r
420 /* Get alignment from policy */\r
421 opInfo->resourceInfo->alignment = rmPolicyGetResourceAlignment(rmInst->policy, resourcePolicy);\r
422 }\r
423 \r
424 if (opInfo->resourceInfo->alignment == 0) {\r
425 opInfo->resourceInfo->alignment = 1;\r
426 } \r
427 \r
428 memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));\r
429 findNode.base = opInfo->resourceInfo->base;\r
430 findNode.length = opInfo->resourceInfo->length;\r
431 \r
432 /* Configure policy checking structure */\r
433 memset((void *)&policyCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));\r
434 if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_INIT_SHIFT)) {\r
435 policyCheckType = Rm_policyCheck_INIT;\r
436 }\r
437 else if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_USE_SHIFT)) {\r
438 policyCheckType = Rm_policyCheck_USE;\r
439 }\r
440 policyCheckCfg.policyDtb = rmInst->policy;\r
441 policyCheckCfg.resourceOffset = resourcePolicy;\r
442 \r
443 do {\r
444 matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);\r
445 \r
446 if (matchingNode) {\r
447 nodePassesPolicy = false;\r
448 policyCheckCfg.type = policyCheckType;\r
449 policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;\r
450 policyCheckCfg.resourceBase = findNode.base;\r
451 policyCheckCfg.resourceLength = findNode.length;\r
452 nodePassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal); \r
453 \r
454 if (nodePassesPolicy && (matchingNode->allocationCount > 0)) {\r
455 /* Check exclusive privileges of instance requesting resource. Requesting\r
456 * instance with exclusive privileges can't reserve resource if already owned*/\r
457 policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
458 policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;\r
459 nodePassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);\r
460 }\r
461 \r
462 if (nodePassesPolicy && (matchingNode->allocationCount == 1)) {\r
463 /* Check exclusive privileges of instance that currently owns resource */\r
464 policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
465 policyCheckCfg.validInstNode = matchingNode->ownerList->instNameNode;\r
466 nodePassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);\r
467 }\r
468 \r
469 if (retVal != RM_SERVICE_PROCESSING) {\r
470 break;\r
471 }\r
472 \r
473 if (nodePassesPolicy) {\r
474 matchingEnd = matchingNode->base + matchingNode->length - 1;\r
475 /* Initialize indexer to be first resource value that alignment */\r
476 rangeIndex = findNode.base;\r
477 if (rangeIndex % opInfo->resourceInfo->alignment) {\r
478 rangeIndex += (opInfo->resourceInfo->alignment -\r
479 (rangeIndex % opInfo->resourceInfo->alignment));\r
480 }\r
481 \r
482 if ((rangeIndex + opInfo->resourceInfo->length - 1) <= matchingEnd) {\r
483 /* Block of unallocated resources within matchingNode that satisfies\r
484 * allocate requirements */\r
485 opInfo->resourceInfo->base = rangeIndex;\r
486 resourceFound = true;\r
487 } \r
488 }\r
489 \r
490 if (!resourceFound) {\r
491 /* Check next resource node for available resources */\r
492 findNode.base = matchingNode->base + matchingNode->length;\r
493 }\r
494 }\r
495 else {\r
496 retVal = RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET;\r
497 }\r
498 } while ((!resourceFound) && \r
499 (retVal != RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET));\r
500 \r
501 return(retVal); \r
502 }\r
503 \r
504 /* FUNCTION PURPOSE: Allocates a resource\r
505 ***********************************************************************\r
506 * DESCRIPTION: Will attempt to allocate the resource with specified\r
507 * base and length from the resource's allocator. The\r
508 * allocation algorithm will verify the allocation against\r
509 * the policy permissions for the instance requesting the\r
510 * allocation. If the policy allows the allocation the \r
511 * algorithm will allocate the resource then combine any\r
512 * resource nodes that may have become equivalent (in terms\r
513 * of ownership) after the allocation.\r
514 */\r
515 static int32_t treeAllocate(Rm_Inst *rmInst, Rm_Allocator *allocator, int32_t resourcePolicy,\r
516 Rm_AllocatorOpInfo *opInfo)\r
517 {\r
518 Rm_ResourceNode findNode;\r
519 Rm_ResourceNode *matchingNode = NULL;\r
520 Rm_ResourceNode *leftNode = NULL;\r
521 Rm_ResourceNode *rightNode = NULL;\r
522 Rm_PolicyCheckType policyCheckType; \r
523 Rm_PolicyCheckCfg policyCheckCfg;\r
524 bool allocPassesPolicy;\r
525 bool combineLeft = false;\r
526 bool combineRight = false; \r
527 uint32_t findEnd;\r
528 uint32_t matchingEnd; \r
529 int32_t retVal = RM_SERVICE_PROCESSING;\r
530 \r
531 memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));\r
532 findNode.base = opInfo->resourceInfo->base;\r
533 findNode.length = opInfo->resourceInfo->length;\r
534 matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);\r
535 \r
536 /* Prepare privilege checks */\r
537 memset((void *)&policyCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));\r
538 if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_INIT_SHIFT)) {\r
539 policyCheckType = Rm_policyCheck_INIT;\r
540 }\r
541 else if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_USE_SHIFT)) {\r
542 policyCheckType = Rm_policyCheck_USE;\r
543 }\r
544 \r
545 if (matchingNode) {\r
546 findEnd = findNode.base + findNode.length - 1;\r
547 matchingEnd = matchingNode->base + matchingNode->length - 1;\r
548 \r
549 if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {\r
550 if (opInfo->serviceSrcInstNode == rmPolicyGetLinuxInstNode(rmInst->validInstances)) {\r
551 /* Bypass policy checks since Linux Kernel has full privileges */\r
552 allocPassesPolicy = true;\r
553 }\r
554 else {\r
555 policyCheckCfg.policyDtb = rmInst->policy;\r
556 policyCheckCfg.resourceOffset = resourcePolicy; \r
557 policyCheckCfg.type = policyCheckType;\r
558 policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;\r
559 policyCheckCfg.resourceBase = findNode.base;\r
560 policyCheckCfg.resourceLength = findNode.length;\r
561 allocPassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);\r
562 if (!allocPassesPolicy) {\r
563 if (policyCheckType == Rm_policyCheck_INIT) {\r
564 retVal = RM_SERVICE_DENIED_INIT_PERM_NOT_GIVEN;\r
565 }\r
566 else {\r
567 retVal = RM_SERVICE_DENIED_USE_PERM_NOT_GIVEN;\r
568 }\r
569 }\r
570 \r
571 if (allocPassesPolicy && (matchingNode->allocationCount > 0)) {\r
572 /* Check exclusive privileges of instance requesting resource. Requesting\r
573 * instance with exclusive privileges can't reserve resource if already owned*/\r
574 policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
575 policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;\r
576 allocPassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);\r
577 if (!allocPassesPolicy) {\r
578 retVal = RM_SERVICE_DENIED_EXCLUSIVE_RES_ALLOCD;\r
579 }\r
580 }\r
581 if (allocPassesPolicy && (matchingNode->allocationCount == 1)) {\r
582 /* Check exclusive privileges of instance that currently owns resource */\r
583 policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
584 policyCheckCfg.validInstNode = matchingNode->ownerList->instNameNode;\r
585 allocPassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);\r
586 if (!allocPassesPolicy) {\r
587 retVal = RM_SERVICE_DENIED_ALLOCD_TO_EXCLUSIVE_INST;\r
588 } \r
589 } \r
590 }\r
591 \r
592 if (allocPassesPolicy) { \r
593 if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd)) {\r
594 /* findNode range matches matchingNode range\r
595 *\r
596 * |<--left node-->||<--matched node-->||<--right node-->| => existing node\r
597 * |<--alloc request-->| => requested resources\r
598 */ \r
599 leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
600 rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
601 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
602 addOwner(matchingNode, opInfo->serviceSrcInstNode);\r
603 \r
604 if (leftNode && compareResourceNodeOwners(leftNode, matchingNode)) {\r
605 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
606 combineLeft = true;\r
607 }\r
608 if (rightNode && compareResourceNodeOwners(rightNode, matchingNode)) {\r
609 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
610 combineRight = true;\r
611 }\r
612 \r
613 if (combineLeft && combineRight) {\r
614 /* Combine all three nodes into matchingNode */\r
615 matchingNode->base = leftNode->base;\r
616 matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;\r
617 \r
618 clearOwners(leftNode);\r
619 rmResourceNodeFree(leftNode);\r
620 clearOwners(rightNode);\r
621 rmResourceNodeFree(rightNode); \r
622 }\r
623 else if (combineLeft) {\r
624 /* Combine left and matching nodes. Reinsert right. */\r
625 matchingNode->base = leftNode->base;\r
626 matchingNode->length += leftNode->length;\r
627 \r
628 clearOwners(leftNode);\r
629 rmResourceNodeFree(leftNode);\r
630 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode); \r
631 }\r
632 else if (combineRight) {\r
633 /* Combine right and matching nodes. Reinsert left. */\r
634 matchingNode->length += rightNode->length;\r
635 \r
636 clearOwners(rightNode);\r
637 rmResourceNodeFree(rightNode);\r
638 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
639 }\r
640 else {\r
641 /* No combine. */\r
642 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
643 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
644 }\r
645 \r
646 /* Always reinsert matchingNode */ \r
647 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode); \r
648 } \r
649 else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {\r
650 /* findNode range is subset of matchingNode range and neither boundary is\r
651 * equivalent.\r
652 *\r
653 * |<----------matched node---------->|\r
654 * |<---alloc request--->|\r
655 */ \r
656 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
657 leftNode = rmResourceNodeNew(matchingNode->base, findNode.base - matchingNode->base);\r
658 copyOwners(leftNode, matchingNode);\r
659 rightNode = rmResourceNodeNew(findNode.base + findNode.length, matchingEnd - findEnd);\r
660 copyOwners(rightNode, matchingNode);\r
661 \r
662 matchingNode->base = findNode.base; \r
663 matchingNode->length = findNode.length;\r
664 addOwner(matchingNode, opInfo->serviceSrcInstNode);\r
665 \r
666 /* Insert all the nodes */\r
667 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
668 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
669 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
670 } \r
671 else { \r
672 if (findNode.base == matchingNode->base) {\r
673 /* findNode base and matchingNode base are equivalent. May be combine\r
674 * possibilities to the left\r
675 *\r
676 * |<---left node (alloc'd)--->||<----------matched node---------->|\r
677 * |<---findNode (alloc req)--->|\r
678 */ \r
679 leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
680 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
681 /* Add allocating instance to owner list for compare with leftNode */\r
682 addOwner(matchingNode, opInfo->serviceSrcInstNode);\r
683 \r
684 if (leftNode && compareResourceNodeOwners(leftNode, matchingNode)) {\r
685 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
686 /* Combine leftNode and findNode */\r
687 leftNode->length += findNode.length;\r
688 }\r
689 else {\r
690 leftNode = rmResourceNodeNew(findNode.base, findNode.length);\r
691 copyOwners(leftNode, matchingNode);\r
692 }\r
693 \r
694 /* Account for leftNode in matchingNode */\r
695 matchingNode->base = findNode.base + findNode.length;\r
696 matchingNode->length = matchingEnd - findEnd; \r
697 \r
698 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
699 }\r
700 else if (findEnd == matchingEnd) {\r
701 /* findNode end and matchingNode end are equivalent. May be combine\r
702 * possibilities to the right\r
703 *\r
704 * |<----------matched node---------->||<---right node (alloc'd)--->|\r
705 * |<---findNode (alloc req)--->| \r
706 */ \r
707 rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
708 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
709 /* Add allocating instance to owner list for compare with rightNode */\r
710 addOwner(matchingNode, opInfo->serviceSrcInstNode);\r
711 \r
712 if (rightNode && compareResourceNodeOwners(rightNode, matchingNode)) {\r
713 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
714 /* Combine rightNode and findNode */\r
715 rightNode->base = findNode.base;\r
716 rightNode->length += findNode.length;\r
717 }\r
718 else {\r
719 rightNode = rmResourceNodeNew(findNode.base, findNode.length);\r
720 copyOwners(rightNode, matchingNode);\r
721 }\r
722 \r
723 /* Account for rightNode in matchingNode */\r
724 matchingNode->length -= findNode.length; \r
725 \r
726 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
727 }\r
728 /* Remove allocating instance from leftover matchingNode */\r
729 deleteOwner(matchingNode, opInfo->serviceSrcInstNode);\r
730 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
731 }\r
732 retVal = RM_SERVICE_APPROVED;\r
733 }\r
734 }\r
735 else {\r
736 retVal = RM_SERVICE_DENIED_PARTIAL_ALLOCATION;\r
737 }\r
738 }\r
739 else {\r
740 retVal = RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST;\r
741 }\r
742 \r
743 return(retVal); \r
744 }\r
745 \r
746 /* FUNCTION PURPOSE: Frees a resource\r
747 ***********************************************************************\r
748 * DESCRIPTION: Will attempt to free the resource with specified\r
749 * base and length from the resource's allocator. The\r
750 * free algorithm will verify the free request parameters\r
751 * match an allocated range for the resource and that the\r
752 * range is owned by the instance requesting the free. If\r
753 * the free is validated the algorithm will free the \r
754 * resource then combine any resource nodes that may have\r
755 * become equivalent (in terms of ownership) after the\r
756 * allocation.\r
757 */\r
758 static int32_t treeFree(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
759 {\r
760 Rm_ResourceNode findNode;\r
761 Rm_ResourceNode *matchingNode = NULL;\r
762 Rm_ResourceNode *leftNode = NULL;\r
763 Rm_ResourceNode *rightNode = NULL;\r
764 bool combineLeft = false;\r
765 bool combineRight = false;\r
766 uint32_t findEnd;\r
767 uint32_t matchingEnd;\r
768 int32_t retVal;\r
769 \r
770 memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));\r
771 findNode.base = opInfo->resourceInfo->base;\r
772 findNode.length = opInfo->resourceInfo->length;\r
773 matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);\r
774 \r
775 if (matchingNode) {\r
776 findEnd = findNode.base + findNode.length - 1;\r
777 matchingEnd = matchingNode->base + matchingNode->length - 1;\r
778 \r
779 if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) { \r
780 if (matchingNode->allocationCount) {\r
781 if (isOwnedBy(matchingNode, opInfo->serviceSrcInstNode)) {\r
782 if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd))\r
783 {\r
784 /* Case 1: Free range equals allocated matched node exactly. Attempt to combine \r
785 * freed node with nodes to left and right.\r
786 *\r
787 * |<--left node-->||<---matched node--->||<--right node-->|\r
788 * |<---free request--->|\r
789 */ \r
790 leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
791 rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
792 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
793 deleteOwner(matchingNode, opInfo->serviceSrcInstNode);\r
794 \r
795 if (leftNode && compareResourceNodeOwners(leftNode, matchingNode)) {\r
796 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
797 combineLeft = true;\r
798 }\r
799 if (rightNode && compareResourceNodeOwners(rightNode, matchingNode)) {\r
800 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
801 combineRight = true;\r
802 }\r
803 \r
804 if (combineLeft && combineRight) {\r
805 /* Combine all three nodes into matchingNode */\r
806 matchingNode->base = leftNode->base;\r
807 matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;\r
808 \r
809 clearOwners(leftNode);\r
810 rmResourceNodeFree(leftNode);\r
811 clearOwners(rightNode);\r
812 rmResourceNodeFree(rightNode); \r
813 }\r
814 else if (combineLeft) {\r
815 /* Combine left and matching nodes. Reinsert right. */\r
816 matchingNode->base = leftNode->base;\r
817 matchingNode->length += leftNode->length;\r
818 \r
819 clearOwners(leftNode);\r
820 rmResourceNodeFree(leftNode);\r
821 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode); \r
822 }\r
823 else if (combineRight) {\r
824 /* Combine right and matching nodes. Reinsert left. */\r
825 matchingNode->length += rightNode->length;\r
826 \r
827 clearOwners(rightNode);\r
828 rmResourceNodeFree(rightNode);\r
829 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
830 }\r
831 else {\r
832 /* No combine. */\r
833 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
834 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
835 }\r
836 \r
837 /* Always reinsert matchingNode */\r
838 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode); \r
839 }\r
840 else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {\r
841 /* Case 2: Free range is less than range in matched node. Split\r
842 * matched node into three nodes.\r
843 *\r
844 * |<----------matched node---------->|\r
845 * |<---free request--->|\r
846 *\r
847 * Remove instance from AllocatedTo list then add it back in for side nodes for\r
848 * proper accounting of allocations in validInstance list\r
849 */ \r
850 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
851 deleteOwner(matchingNode, opInfo->serviceSrcInstNode);\r
852 \r
853 leftNode = rmResourceNodeNew(matchingNode->base, findNode.base - matchingNode->base);\r
854 copyOwners(leftNode, matchingNode);\r
855 addOwner(leftNode, opInfo->serviceSrcInstNode);\r
856 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
857 \r
858 rightNode = rmResourceNodeNew(findNode.base + findNode.length, matchingEnd - findEnd);\r
859 copyOwners(rightNode, matchingNode);\r
860 addOwner(rightNode, opInfo->serviceSrcInstNode);\r
861 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
862 \r
863 matchingNode->base = findNode.base; \r
864 matchingNode->length = findNode.length;\r
865 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
866 }\r
867 else { \r
868 if (findNode.base == matchingNode->base) {\r
869 /* Case 3: Free range is on left boundary of matched node. Try to \r
870 * combine free range with left node.\r
871 *\r
872 * |<---left node (free)--->||<----------matched node---------->|\r
873 * |<---findNode (free req)--->|\r
874 */ \r
875 \r
876 leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
877 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
878 /* Remove freeing instance from owner list for compare with leftNode */\r
879 deleteOwner(matchingNode, opInfo->serviceSrcInstNode);\r
880 \r
881 if (leftNode && compareResourceNodeOwners(leftNode, matchingNode)) {\r
882 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
883 /* Combine leftNode and findNode */\r
884 leftNode->length += findNode.length;\r
885 }\r
886 else {\r
887 leftNode = rmResourceNodeNew(findNode.base, findNode.length);\r
888 copyOwners(leftNode, matchingNode);\r
889 }\r
890 \r
891 /* Remove leftNode range from matchingNode */\r
892 matchingNode->base = findNode.base + findNode.length;\r
893 matchingNode->length = matchingEnd - findEnd; \r
894 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
895 }\r
896 else if (findEnd == matchingEnd) {\r
897 /* Case 4: Free range is on right boundary of matched node. Try to \r
898 * combine free range with right node.\r
899 *\r
900 * |<----------matched node---------->||<---right node (free)--->|\r
901 * |<---findNode (free req)--->|\r
902 */ \r
903 \r
904 rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
905 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode); \r
906 /* Remove freeing instance from owner list for compare with rightNode */\r
907 deleteOwner(matchingNode, opInfo->serviceSrcInstNode);\r
908 \r
909 if (rightNode && compareResourceNodeOwners(rightNode, matchingNode)) {\r
910 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
911 /* Combine rightNode and findNode */\r
912 rightNode->base = findNode.base;\r
913 rightNode->length += findNode.length;\r
914 }\r
915 else {\r
916 rightNode = rmResourceNodeNew(findNode.base, findNode.length);\r
917 copyOwners(rightNode, matchingNode);\r
918 }\r
919 \r
920 /* Remove rightNode range from matchingNode */\r
921 matchingNode->length -= findNode.length; \r
922 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
923 }\r
924 \r
925 /* Add freeing instance back into matchingNode allocations */\r
926 addOwner(matchingNode, opInfo->serviceSrcInstNode);\r
927 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
928 }\r
929 \r
930 retVal = RM_SERVICE_APPROVED;\r
931 }\r
932 else {\r
933 retVal = RM_SERVICE_DENIED_RES_NOT_ALLOCD_TO_INST;\r
934 }\r
935 }\r
936 else {\r
937 retVal = RM_SERVICE_DENIED_RES_ALREADY_FREE;\r
938 }\r
939 }\r
940 else {\r
941 retVal = RM_SERVICE_DENIED_PARTIAL_FREE;\r
942 }\r
943 }\r
944 else {\r
945 retVal = RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST;\r
946 }\r
947 return(retVal); \r
948 }\r
949 \r
950 /* FUNCTION PURPOSE: Issues a service response to application\r
951 ***********************************************************************\r
952 * DESCRIPTION: Provides a service response back to the application\r
953 * using the service callback function provided to\r
954 * the RM instance at the time of the service request.\r
955 */\r
956 static void serviceResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
957 {\r
958 Rm_ServiceRespInfo serviceResponse;\r
959 \r
960 /* The responseTransaction will contain the resultant state details of\r
961 * the requestTransaction's service request */\r
962 serviceResponse.serviceState = transaction->state;\r
963 /* Pass back the ID that was provided to the component when it requested\r
964 * the service */\r
965 serviceResponse.serviceId = transaction->localId;\r
966 \r
967 /* Service was approved and service was an allocate request. The resource\r
968 * data is passed back to the component */\r
969 if ((serviceResponse.serviceState == RM_SERVICE_APPROVED) &&\r
970 ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||\r
971 (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||\r
972 (transaction->type == Rm_service_RESOURCE_GET_BY_NAME)))\r
973 {\r
974 strncpy(serviceResponse.resourceName, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);\r
975 serviceResponse.resourceBase = transaction->resourceInfo.base;\r
976 serviceResponse.resourceLength = transaction->resourceInfo.length;\r
977 }\r
978 \r
979 /* Issue the callback to the requesting component with the response information */\r
980 transaction->callback.serviceCallback(&serviceResponse);\r
981 \r
982 /* Delete the transaction from the transaction queue */\r
983 rmTransactionQueueDelete(rmInst, transaction->localId);\r
984 return;\r
985 }\r
986 \r
987 /* FUNCTION PURPOSE: Sends RM response packets\r
988 ***********************************************************************\r
989 * DESCRIPTION: Sends RM response packets to RM instance's that sent\r
990 * RM request packets to the RM instance. The response\r
991 * is sent via the RM transport API which is plugged\r
992 * with an application created transport path.\r
993 */\r
994 static void transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
995 {\r
996 Rm_Transport *dstTransport = NULL;\r
997 Rm_PacketHandle pktHandle = NULL;\r
998 \r
999 dstTransport = rmTransportFindRemoteName((Rm_Transport *) rmInst->transports, transaction->pktSrcInstName);\r
1000 \r
1001 switch (transaction->type) {\r
1002 case Rm_service_RESOURCE_ALLOCATE_INIT:\r
1003 case Rm_service_RESOURCE_ALLOCATE_USE:\r
1004 case Rm_service_RESOURCE_FREE:\r
1005 case Rm_service_RESOURCE_GET_BY_NAME:\r
1006 pktHandle = rmTransportCreateResourceResponsePkt(rmInst, dstTransport->appTransportHandle, \r
1007 transaction);\r
1008 break;\r
1009 case Rm_service_RESOURCE_MAP_TO_NAME:\r
1010 case Rm_service_RESOURCE_UNMAP_NAME:\r
1011 pktHandle = rmTransportCreateNsResponsePkt(rmInst, dstTransport->appTransportHandle,\r
1012 transaction);\r
1013 break;\r
1014 }\r
1015 \r
1016 if (pktHandle) {\r
1017 if (rmInst->transportCallouts.rmSendPkt) {\r
1018 if (rmInst->transportCallouts.rmSendPkt(dstTransport->appTransportHandle, pktHandle) < RM_OK) {\r
1019 transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;\r
1020 }\r
1021 }\r
1022 else {\r
1023 transaction->state = RM_ERROR_TRANSPORT_SEND_NOT_REGD;\r
1024 }\r
1025 }\r
1026 rmTransactionQueueDelete(rmInst, transaction->localId);\r
1027 }\r
1028 \r
1029 /* FUNCTION PURPOSE: Sends RM request packets\r
1030 ***********************************************************************\r
1031 * DESCRIPTION: Sends RM request packets to RM instance's that are\r
1032 * capable of forwarding or validating service requests.\r
1033 * The request is sent via the RM transport API which is\r
1034 * plugged with an application created transport path.\r
1035 */\r
1036 static void transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
1037 {\r
1038 Rm_Transport *dstTransport = NULL;\r
1039 Rm_PacketHandle pktHandle = NULL;\r
1040 \r
1041 if (rmInst->registeredWithDelegateOrServer) {\r
1042 if (rmInst->instType == Rm_instType_CLIENT) {\r
1043 dstTransport = rmTransportFindRemoteInstType((Rm_Transport *) rmInst->transports, Rm_instType_CLIENT_DELEGATE);\r
1044 \r
1045 if (!dstTransport) {\r
1046 dstTransport = rmTransportFindRemoteInstType((Rm_Transport *) rmInst->transports, Rm_instType_SERVER);\r
1047 }\r
1048 } \r
1049 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {\r
1050 dstTransport = rmTransportFindRemoteInstType((Rm_Transport *) rmInst->transports, Rm_instType_SERVER);\r
1051 }\r
1052 \r
1053 switch (transaction->type) {\r
1054 case Rm_service_RESOURCE_ALLOCATE_INIT:\r
1055 case Rm_service_RESOURCE_ALLOCATE_USE:\r
1056 case Rm_service_RESOURCE_FREE:\r
1057 case Rm_service_RESOURCE_GET_BY_NAME:\r
1058 pktHandle = rmTransportCreateResourceReqPkt(rmInst, dstTransport->appTransportHandle, transaction);\r
1059 break;\r
1060 case Rm_service_RESOURCE_MAP_TO_NAME:\r
1061 case Rm_service_RESOURCE_UNMAP_NAME:\r
1062 pktHandle = rmTransportCreateNsRequestPkt(rmInst, dstTransport->appTransportHandle, transaction);\r
1063 break;\r
1064 }\r
1065 \r
1066 if (pktHandle) {\r
1067 if (rmInst->transportCallouts.rmSendPkt) { \r
1068 if (rmInst->transportCallouts.rmSendPkt(dstTransport->appTransportHandle, pktHandle) < RM_OK) {\r
1069 transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;\r
1070 }\r
1071 }\r
1072 else {\r
1073 transaction->state = RM_ERROR_TRANSPORT_SEND_NOT_REGD;\r
1074 } \r
1075 }\r
1076 \r
1077 transaction->hasBeenForwarded = true;\r
1078 /* Transaction not deleted. Waiting for response from RM CD or Server */\r
1079 }\r
1080 }\r
1081 \r
1082 /* FUNCTION PURPOSE: Issues an allocator operation\r
1083 ***********************************************************************\r
1084 * DESCRIPTION: Issues an allocator preallocate, allocate, or free\r
1085 * for an RM resource.\r
1086 */\r
1087 static int32_t allocatorOperation(Rm_Inst *rmInst, Rm_AllocatorOpInfo *opInfo)\r
1088 {\r
1089 Rm_Allocator *allocator = NULL;\r
1090 int32_t resourceOffsetInPolicy;\r
1091 int32_t retVal;\r
1092 \r
1093 resourceOffsetInPolicy = rmPolicyGetResourceOffset(rmInst->policy, opInfo->resourceInfo->name);\r
1094 allocator = rmAllocatorFind(rmInst->allocators, opInfo->resourceInfo->name);\r
1095 \r
1096 if ((resourceOffsetInPolicy > 0) && allocator) {\r
1097 if (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE) {\r
1098 retVal = treePreAllocate(rmInst, allocator, resourceOffsetInPolicy, opInfo);\r
1099 } \r
1100 else if (opInfo->operation == Rm_allocatorOp_ALLOCATE) {\r
1101 retVal = treeAllocate(rmInst, allocator, resourceOffsetInPolicy, opInfo);\r
1102 }\r
1103 else if (opInfo->operation == Rm_allocatorOp_FREE) {\r
1104 retVal = treeFree(allocator, opInfo);\r
1105 } \r
1106 }\r
1107 else {\r
1108 /* Resource could not be found in policy and/or allocator */\r
1109 retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;\r
1110 }\r
1111 return(retVal);\r
1112 }\r
1113 \r
1114 /* FUNCTION PURPOSE: Arbitrates allocation service requests\r
1115 ***********************************************************************\r
1116 * DESCRIPTION: Issues a set of allocator operations in order to\r
1117 * handle a received allocation request. Allocation\r
1118 * requests are always forwarded to the Server on Client\r
1119 * CD instances. If a request is made with a NameServer\r
1120 * name the resource base and length parameters are\r
1121 * retrieved from the NameServer prior to the allocation\r
1122 * attempt.\r
1123 */\r
1124 static void allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction, void *validInstNode,\r
1125 uint32_t allocType)\r
1126 {\r
1127 Rm_AllocatorOpInfo opInfo;\r
1128 Rm_NameServerObjCfg nameServerObjCfg;\r
1129 int32_t retVal = transaction->state;\r
1130 \r
1131 memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));\r
1132 \r
1133 if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {\r
1134 /* Forward all allocation requests to Server if transport is up. Otherwise, just queue. */\r
1135 if (rmInst->registeredWithDelegateOrServer) {\r
1136 transactionForwarder(rmInst, transaction); \r
1137 } \r
1138 }\r
1139 else if (rmInst->instType == Rm_instType_SERVER) {\r
1140 opInfo.resourceInfo = &transaction->resourceInfo;\r
1141 opInfo.serviceSrcInstNode = validInstNode;\r
1142 opInfo.allocType = allocType;\r
1143 \r
1144 /* Populated NameServer name has precedence over base */\r
1145 if (strlen(transaction->resourceInfo.nameServerName) > 0) {\r
1146 if ((transaction->resourceInfo.base == 0) &&\r
1147 (transaction->resourceInfo.length == 0) &&\r
1148 (transaction->resourceInfo.alignment == 0)) {\r
1149 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));\r
1150 nameServerObjCfg.nameServerTree = rmInst->nameServer;\r
1151 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;\r
1152 if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {\r
1153 strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);\r
1154 transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;\r
1155 transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;\r
1156 } \r
1157 }\r
1158 else {\r
1159 retVal = RM_ERROR_NS_NAME_AND_RES_VAL_CONFLICT;\r
1160 }\r
1161 }\r
1162 \r
1163 if (retVal == RM_SERVICE_PROCESSING) { \r
1164 if (transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) {\r
1165 opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE;\r
1166 retVal = allocatorOperation(rmInst, &opInfo);\r
1167 }\r
1168 \r
1169 if (retVal == RM_SERVICE_PROCESSING) {\r
1170 opInfo.operation = Rm_allocatorOp_ALLOCATE;\r
1171 retVal = allocatorOperation(rmInst, &opInfo);\r
1172 } \r
1173 }\r
1174 \r
1175 transaction->state = retVal;\r
1176 \r
1177 if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {\r
1178 /* Source of allocation was not the server instance, provide the transaction\r
1179 * to the transaction responder */\r
1180 transactionResponder(rmInst, transaction);\r
1181 }\r
1182 /* Otherwise let the return stack return the transaction to the serviceHandler */ \r
1183 } \r
1184 }\r
1185 \r
1186 /* FUNCTION PURPOSE: Arbitrates free service requests\r
1187 ***********************************************************************\r
1188 * DESCRIPTION: Issues a set of allocator operations in order to\r
1189 * handle a received free request. Free\r
1190 * requests are always forwarded to the Server on Client\r
1191 * CD instances. If a request is made with a NameServer\r
1192 * name the resource base and length parameters are\r
1193 * retrieved from the NameServer prior to the free\r
1194 * attempt.\r
1195 */\r
1196 static void freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction, void *validInstNode)\r
1197 {\r
1198 Rm_AllocatorOpInfo opInfo; \r
1199 Rm_NameServerObjCfg nameServerObjCfg; \r
1200 int32_t retVal = transaction->state;\r
1201 \r
1202 memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));\r
1203 \r
1204 if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {\r
1205 /* Forward all free requests to Server if transport is up. Otherwise, just queue. */\r
1206 if (rmInst->registeredWithDelegateOrServer) {\r
1207 transactionForwarder(rmInst, transaction); \r
1208 }\r
1209 }\r
1210 else if (rmInst->instType == Rm_instType_SERVER) {\r
1211 opInfo.resourceInfo = &transaction->resourceInfo;\r
1212 opInfo.serviceSrcInstNode = validInstNode;\r
1213 \r
1214 /* Populated NameServer name has precedence over base */\r
1215 if (strlen(transaction->resourceInfo.nameServerName) > 0) {\r
1216 if ((transaction->resourceInfo.base == 0) &&\r
1217 (transaction->resourceInfo.length == 0) &&\r
1218 (transaction->resourceInfo.alignment == 0)) {\r
1219 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));\r
1220 nameServerObjCfg.nameServerTree = rmInst->nameServer;\r
1221 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;\r
1222 if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {\r
1223 strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);\r
1224 transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;\r
1225 transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;\r
1226 } \r
1227 }\r
1228 else {\r
1229 retVal = RM_ERROR_NS_NAME_AND_RES_VAL_CONFLICT;\r
1230 } \r
1231 }\r
1232 \r
1233 if(retVal == RM_SERVICE_PROCESSING) { \r
1234 opInfo.operation = Rm_allocatorOp_FREE;\r
1235 retVal = allocatorOperation(rmInst, &opInfo);\r
1236 } \r
1237 \r
1238 transaction->state = retVal;\r
1239 \r
1240 if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {\r
1241 /* Source of allocation was not the server instance, provide the transaction\r
1242 * to the transaction responder */\r
1243 transactionResponder(rmInst, transaction);\r
1244 }\r
1245 /* Otherwise let the return stack return the transaction to the serviceHandler */ \r
1246 } \r
1247 }\r
1248 \r
1249 /* FUNCTION PURPOSE: Reserves a Linux resource\r
1250 ***********************************************************************\r
1251 * DESCRIPTION: Reserves resources for Linux using the base and length\r
1252 * values retrieved from the Linux DTB via the\r
1253 * "linux-dtb-alias" properties within the GRL.\r
1254 */\r
1255 static int32_t reserveLinuxResource(Rm_Inst *rmInst, Rm_LinuxAlias *linuxAlias, \r
1256 Rm_LinuxValueRange *linuxValues, Rm_AllocatorOpInfo *opInfo)\r
1257 {\r
1258 int32_t retVal = RM_OK;\r
1259 bool baseFound = false;\r
1260 bool lengthFound = false;\r
1261 uint32_t valueIndex = 0;\r
1262 \r
1263 while ((linuxValues) && (!baseFound || !lengthFound)) {\r
1264 if (linuxAlias->baseOffset == valueIndex) {\r
1265 opInfo->resourceInfo->base = linuxValues->value;\r
1266 baseFound = true;\r
1267 \r
1268 if (linuxAlias->lengthOffset == RM_DTB_UTIL_LINUX_ALIAS_OFFSET_NOT_SET) {\r
1269 opInfo->resourceInfo->length = 1;\r
1270 lengthFound = true;\r
1271 }\r
1272 }\r
1273 else if (linuxAlias->lengthOffset == valueIndex) {\r
1274 opInfo->resourceInfo->length = linuxValues->value;\r
1275 lengthFound = true;\r
1276 }\r
1277 \r
1278 linuxValues = (Rm_LinuxValueRange *)linuxValues->nextValue;\r
1279 valueIndex++;\r
1280 }\r
1281 \r
1282 if (!baseFound || !lengthFound) {\r
1283 retVal = RM_ERROR_DATA_NOT_FOUND_AT_LINUX_ALIAS;\r
1284 }\r
1285 else {\r
1286 /* Allocate resource to Linux */\r
1287 retVal = allocatorOperation(rmInst, opInfo);\r
1288 }\r
1289 return (retVal);\r
1290 }\r
1291 \r
1292 /* FUNCTION PURPOSE: Finds and reserves Linux resources\r
1293 ***********************************************************************\r
1294 * DESCRIPTION: Parses the Linux DTB for resources consumed by the\r
1295 * Linux kernel. If the resource is found via the\r
1296 * "linux-dtb-alias" property defined in the GRL it is \r
1297 * reserved.\r
1298 */\r
1299 static int32_t findAndReserveLinuxResource(Rm_Inst *rmInst, const char *resourceName, void *linuxDtb, \r
1300 Rm_LinuxAlias *linuxAlias)\r
1301 {\r
1302 Rm_AllocatorOpInfo opInfo;\r
1303 Rm_ResourceInfo resourceInfo;\r
1304 uint32_t pathOffset;\r
1305 uint32_t pathSize;\r
1306 char *spacePtr;\r
1307 int32_t propOffset;\r
1308 int32_t nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;\r
1309 int32_t prevDepth = RM_DTB_UTIL_STARTING_DEPTH;\r
1310 int32_t depth;\r
1311 int32_t propertyLen;\r
1312 const char *propertyName;\r
1313 const void *propertyData; \r
1314 Rm_LinuxValueRange *linuxValueRange;\r
1315 int32_t retVal = RM_OK; \r
1316 \r
1317 memset((void *) &opInfo, 0, sizeof(Rm_AllocatorOpInfo));\r
1318 memset((void *) &resourceInfo, 0, sizeof(Rm_ResourceInfo));\r
1319 \r
1320 strncpy(resourceInfo.name, resourceName, RM_NAME_MAX_CHARS);\r
1321 opInfo.serviceSrcInstNode = rmPolicyGetLinuxInstNode(rmInst->validInstances);\r
1322 opInfo.operation = Rm_allocatorOp_ALLOCATE;\r
1323 opInfo.resourceInfo = &resourceInfo; \r
1324 \r
1325 while(linuxAlias) {\r
1326 /* Reset parsing variables */\r
1327 pathOffset = 0;\r
1328 pathSize = strlen(linuxAlias->path) + 1;\r
1329 nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;\r
1330 prevDepth = RM_DTB_UTIL_STARTING_DEPTH; \r
1331 resourceInfo.base = 0;\r
1332 resourceInfo.length = 0;\r
1333 \r
1334 spacePtr = strpbrk(linuxAlias->path, " ");\r
1335 if (spacePtr) {\r
1336 *spacePtr = '\0';\r
1337 } \r
1338 \r
1339 while(pathOffset < pathSize) {\r
1340 /* Move through DTB nodes until next alias path node found */\r
1341 if (strcmp(linuxAlias->path + pathOffset, fdt_get_name(linuxDtb, nodeOffset, NULL))) {\r
1342 nodeOffset = fdt_next_node(linuxDtb, nodeOffset, &depth);\r
1343 \r
1344 if ((depth < prevDepth) || (nodeOffset == -FDT_ERR_NOTFOUND)) {\r
1345 /* Returning from subnode that matched part of alias path without finding\r
1346 * resource values */\r
1347 retVal = RM_ERROR_DATA_NOT_FOUND_AT_LINUX_ALIAS;\r
1348 break;\r
1349 }\r
1350 }\r
1351 else {\r
1352 /* Found next alias path node. Move to next node name in path string. */\r
1353 pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);\r
1354 spacePtr = strpbrk(linuxAlias->path + pathOffset, " ");\r
1355 if (spacePtr) {\r
1356 *spacePtr = '\0';\r
1357 } \r
1358 \r
1359 prevDepth = fdt_node_depth(linuxDtb, nodeOffset);\r
1360 propOffset = fdt_first_property_offset(linuxDtb, nodeOffset);\r
1361 while ((propOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) &&\r
1362 (pathOffset < pathSize)) {\r
1363 propertyData = fdt_getprop_by_offset(linuxDtb, propOffset, \r
1364 &propertyName, &propertyLen);\r
1365 \r
1366 if (strcmp(linuxAlias->path + pathOffset, propertyName) == 0) {\r
1367 /* Found resource at end of alias path */\r
1368 pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);\r
1369 linuxValueRange = rmDtbUtilLinuxExtractValues(propertyData, propertyLen);\r
1370 retVal = reserveLinuxResource(rmInst, linuxAlias, \r
1371 linuxValueRange, &opInfo);\r
1372 rmDtbUtilLinuxFreeValues(linuxValueRange);\r
1373 }\r
1374 propOffset = fdt_next_property_offset(linuxDtb, propOffset);\r
1375 } \r
1376 \r
1377 if (propOffset < -FDT_ERR_NOTFOUND) {\r
1378 retVal = propOffset;\r
1379 break;\r
1380 }\r
1381 }\r
1382 }\r
1383 \r
1384 if (retVal < RM_OK) {\r
1385 break;\r
1386 }\r
1387 linuxAlias = linuxAlias->nextLinuxAlias;\r
1388 }\r
1389 return (retVal);\r
1390 }\r
1391 \r
1392 /* FUNCTION PURPOSE: Creates and initializes a resource allocator\r
1393 ***********************************************************************\r
1394 * DESCRIPTION: Creates a resource allocator for the provided\r
1395 * resource name and resource properties retrieved\r
1396 * from the GRL. Resources will be reserved for \r
1397 * the Linux kernel if the Linux DTB is provided\r
1398 * and there are "linux-dtb-alias" properties\r
1399 * specified in the GRL.\r
1400 */\r
1401 static int32_t createAndInitAllocator(Rm_Inst *rmInst, const char *resourceName, \r
1402 Rm_ResourceProperties *resourceProperties, void *linuxDtb)\r
1403 {\r
1404 Rm_ResourceRange *range = NULL;\r
1405 Rm_ResourceRange *rangeBasePtr = NULL;\r
1406 Rm_NsAssignment *nsAssignments = NULL;\r
1407 Rm_NsAssignment *nsAssignmentBasePtr = NULL;\r
1408 Rm_LinuxAlias *linuxAlias = NULL;\r
1409 Rm_NameServerObjCfg nameServerObjCfg; \r
1410 int32_t retVal = RM_OK;\r
1411 \r
1412 if (resourceProperties->rangeData && (resourceProperties->rangeLen > 0)) {\r
1413 range = rangeBasePtr = rmDtbUtilResExtractRange(resourceProperties->rangeData, \r
1414 resourceProperties->rangeLen);\r
1415 \r
1416 if ((retVal = createResourceTree(rmInst, resourceName, range)) >= RM_OK) {\r
1417 if (resourceProperties->linuxAliasData && resourceProperties->linuxAliasLen) {\r
1418 if (linuxDtb) {\r
1419 linuxAlias = rmDtbUtilResExtractLinuxAlias(resourceProperties->linuxAliasData,\r
1420 resourceProperties->linuxAliasLen, &retVal);\r
1421 if (linuxAlias) {\r
1422 retVal = findAndReserveLinuxResource(rmInst, resourceName, linuxDtb, linuxAlias); \r
1423 }\r
1424 }\r
1425 else {\r
1426 retVal = RM_ERROR_GRL_LINUX_ALIAS_BUT_NO_DTB;\r
1427 }\r
1428 }\r
1429 }\r
1430 }\r
1431 \r
1432 if (retVal >= RM_OK) {\r
1433 if (resourceProperties->nsAssignData && resourceProperties->nsAssignLen) {\r
1434 nsAssignments = rmDtbUtilResExtractNsAssignment(resourceProperties->nsAssignData, \r
1435 resourceProperties->nsAssignLen, &retVal);\r
1436 if (nsAssignments) {\r
1437 nsAssignmentBasePtr = nsAssignments;\r
1438 while (nsAssignments) {\r
1439 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));\r
1440 nameServerObjCfg.nameServerTree = rmInst->nameServer;\r
1441 nameServerObjCfg.nodeCfg.objName = nsAssignments->nsName;\r
1442 nameServerObjCfg.nodeCfg.resourceName = (char *)resourceName;\r
1443 nameServerObjCfg.nodeCfg.resourceBase= nsAssignments->resourceBase;\r
1444 nameServerObjCfg.nodeCfg.resourceLength = nsAssignments->resourceLength; \r
1445 rmNameServerAddObject(&nameServerObjCfg);\r
1446 nsAssignments = nsAssignments->nextNsAssignment;\r
1447 }\r
1448 rmDtbUtilResFreeNsAssignmentList(nsAssignmentBasePtr);\r
1449 }\r
1450 }\r
1451 }\r
1452 \r
1453 rmDtbUtilResFreeRange(rangeBasePtr);\r
1454 if (linuxAlias) {\r
1455 rmDtbUtilResFreeLinuxAlias(linuxAlias);\r
1456 }\r
1457 return(retVal);\r
1458 }\r
1459 \r
1460 /* FUNCTION PURPOSE: Recursively parses GRL resource properties\r
1461 ***********************************************************************\r
1462 * DESCRIPTION: Recursively parses and stores GRL resource node \r
1463 * properties using the LIBFDT APIs\r
1464 */\r
1465 static int32_t parseResourceProperty(void *globalResourceDtb, int32_t offset, \r
1466 Rm_ResourceProperties *propertyInfo)\r
1467 {\r
1468 int32_t propertyLen;\r
1469 const char *propertyName;\r
1470 const void *propertyData;\r
1471 Rm_ResourcePropType propertyType;\r
1472 int32_t retVal = RM_OK;\r
1473 \r
1474 propertyData = fdt_getprop_by_offset(globalResourceDtb, offset, &propertyName, &propertyLen);\r
1475 propertyType = rmDtbUtilResGetPropertyType(propertyName);\r
1476 if (propertyType == Rm_resourcePropType_RESOURCE_RANGE) {\r
1477 propertyInfo->rangeData = propertyData;\r
1478 propertyInfo->rangeLen = propertyLen;\r
1479 }\r
1480 else if (propertyType == Rm_resourcePropType_NSASSIGNMENT) {\r
1481 propertyInfo->nsAssignData = propertyData;\r
1482 propertyInfo->nsAssignLen = propertyLen;\r
1483 }\r
1484 else if (propertyType == Rm_resourcePropType_RESOURCE_LINUX_ALIAS) {\r
1485 propertyInfo->linuxAliasData = propertyData;\r
1486 propertyInfo->linuxAliasLen = propertyLen;\r
1487 } \r
1488 else {\r
1489 retVal = RM_ERROR_GRL_UNKNOWN_RESOURCE_PROPERTY;\r
1490 }\r
1491 \r
1492 if (retVal == RM_OK) {\r
1493 offset = fdt_next_property_offset(globalResourceDtb, offset);\r
1494 if (offset >= 0) {\r
1495 retVal = parseResourceProperty(globalResourceDtb, offset, propertyInfo);\r
1496 }\r
1497 else if (offset != -FDT_ERR_NOTFOUND) {\r
1498 /* Error returned by LIBFDT */\r
1499 retVal = offset;\r
1500 }\r
1501 }\r
1502 return (retVal);\r
1503 }\r
1504 \r
1505 /* FUNCTION PURPOSE: Recursively parses GRL resource nodes\r
1506 ***********************************************************************\r
1507 * DESCRIPTION: Recursively parses GRL resource nodes looking for\r
1508 * resource properties to create the resource allocators.\r
1509 * The LIBFDT APIs are used to parse the GRL.\r
1510 */\r
1511 static int32_t parseResourceNode(Rm_Inst *rmInst, void *globalResourceDtb, int32_t nodeOffset, int32_t depth,\r
1512 void *linuxDtb)\r
1513 {\r
1514 const char *resourceName = fdt_get_name(globalResourceDtb, nodeOffset, NULL);\r
1515 Rm_ResourceProperties resourceProperties;\r
1516 int32_t retVal = RM_OK;\r
1517 int32_t offset;\r
1518 \r
1519 memset((void *)&resourceProperties, 0, sizeof(Rm_ResourceProperties));\r
1520 /* Get properties of resource node */\r
1521 offset = fdt_first_property_offset(globalResourceDtb, nodeOffset);\r
1522 if (offset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) {\r
1523 retVal = parseResourceProperty(globalResourceDtb, offset, &resourceProperties);\r
1524 if (retVal < -FDT_ERR_NOTFOUND) {\r
1525 return (retVal);\r
1526 }\r
1527 if (retVal = createAndInitAllocator(rmInst, resourceName, &resourceProperties, linuxDtb) < RM_OK) {\r
1528 return (retVal);\r
1529 }\r
1530 }\r
1531 else if (offset != -FDT_ERR_NOTFOUND) {\r
1532 /* Error returned by LIBFDT */\r
1533 return (offset);\r
1534 }\r
1535 \r
1536 offset = fdt_next_node(globalResourceDtb, nodeOffset, &depth);\r
1537 if ((offset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && (depth >= RM_DTB_UTIL_STARTING_DEPTH)) {\r
1538 retVal = parseResourceNode(rmInst, globalResourceDtb, offset, depth, linuxDtb);\r
1539 if (retVal < -FDT_ERR_NOTFOUND) {\r
1540 return (retVal);\r
1541 }\r
1542 }\r
1543 else if (offset != -FDT_ERR_NOTFOUND) {\r
1544 /* Error returned by LIBFDT */\r
1545 return (offset);\r
1546 }\r
1547 return (retVal);\r
1548 }\r
1549 \r
1550 /* FUNCTION PURPOSE: Initializes server allocators\r
1551 ***********************************************************************\r
1552 * DESCRIPTION: Creates and initializes a server instance's\r
1553 * resource allocators using the GRL and, if\r
1554 * provided, Linux DTB.\r
1555 */\r
1556 static int32_t initializeAllocators(Rm_Inst *rmInst, void *globalResourceDtb, void *linuxDtb)\r
1557 {\r
1558 int32_t nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;\r
1559 int32_t startDepth = RM_DTB_UTIL_STARTING_DEPTH;\r
1560 int32_t result = RM_OK;\r
1561 \r
1562 /* Recursively parse the Global Resource List, creating an allocator for\r
1563 * each resource as specified in the node */\r
1564 result = parseResourceNode(rmInst, globalResourceDtb, nodeOffset, startDepth, linuxDtb);\r
1565 \r
1566 return(result);\r
1567 }\r
1568 \r
1569 /**********************************************************************\r
1570 ********************** Internal Functions ****************************\r
1571 **********************************************************************/\r
1572 \r
1573 /* FUNCTION PURPOSE: Adds a transaction\r
1574 ***********************************************************************\r
1575 * DESCRIPTION: Returns a pointer to a newly created transaction.\r
1576 * The transaction is created based on a new service\r
1577 * request received via the service API or the\r
1578 * transport API (service forwarded from another instance)\r
1579 */\r
1580 Rm_Transaction *rmTransactionQueueAdd(Rm_Inst *rmInst)\r
1581 {\r
1582 Rm_Transaction *transactionQueue = rmInst->transactionQueue;\r
1583 Rm_Transaction *newTransaction = NULL;\r
1584 \r
1585 newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction));\r
1586 if (newTransaction) {\r
1587 memset((void *)newTransaction, 0, sizeof(Rm_Transaction));\r
1588 \r
1589 newTransaction->localId = transactionGetSequenceNum(rmInst);\r
1590 newTransaction->nextTransaction = NULL; \r
1591 if (transactionQueue) {\r
1592 while (transactionQueue->nextTransaction) {\r
1593 transactionQueue = transactionQueue->nextTransaction;\r
1594 }\r
1595 transactionQueue->nextTransaction = newTransaction;\r
1596 }\r
1597 else {\r
1598 rmInst->transactionQueue = newTransaction;\r
1599 }\r
1600 }\r
1601 return (newTransaction);\r
1602 }\r
1603 \r
1604 /* FUNCTION PURPOSE: Finds a transaction\r
1605 ***********************************************************************\r
1606 * DESCRIPTION: Returns a pointer to a transaction resident\r
1607 * in the transaction queue that matches the provided\r
1608 * transaction ID.\r
1609 */\r
1610 Rm_Transaction *rmTransactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)\r
1611 {\r
1612 Rm_Transaction *transaction = rmInst->transactionQueue;\r
1613 \r
1614 while (transaction) {\r
1615 if (transaction->localId == transactionId) {\r
1616 break; \r
1617 }\r
1618 transaction = transaction->nextTransaction;\r
1619 }\r
1620 \r
1621 return (transaction);\r
1622 }\r
1623 \r
1624 /* FUNCTION PURPOSE: Deletes a transaction\r
1625 ***********************************************************************\r
1626 * DESCRIPTION: Deletes the transaction with the provided transaction\r
1627 * ID from the instance's transaction queue.\r
1628 */\r
1629 int32_t rmTransactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)\r
1630 {\r
1631 Rm_Transaction *transaction = rmInst->transactionQueue;\r
1632 Rm_Transaction *prevTransaction = NULL;\r
1633 int32_t retVal = RM_OK;\r
1634 \r
1635 while (transaction) {\r
1636 if (transaction->localId == transactionId) {\r
1637 break; \r
1638 }\r
1639 \r
1640 prevTransaction = transaction;\r
1641 transaction = transaction->nextTransaction;\r
1642 }\r
1643 \r
1644 if (transaction) {\r
1645 if (prevTransaction == NULL) {\r
1646 /* Transaction at start of queue. Map second transaction to start of queue \r
1647 * as long as more than one transactions. */\r
1648 rmInst->transactionQueue = transaction->nextTransaction;\r
1649 }\r
1650 else {\r
1651 /* Transaction in middle or end of queue. */\r
1652 prevTransaction->nextTransaction = transaction->nextTransaction;\r
1653 }\r
1654 Rm_osalFree((void *)transaction, sizeof(Rm_Transaction));\r
1655 }\r
1656 else {\r
1657 retVal = RM_ERROR_SERVICE_TRANS_DOES_NOT_EXIST;\r
1658 } \r
1659 return (retVal);\r
1660 }\r
1661 \r
1662 /* FUNCTION PURPOSE: Finds an allocator\r
1663 ***********************************************************************\r
1664 * DESCRIPTION: Returns a pointer to an allocator that matches the \r
1665 * provided resource name.\r
1666 */\r
1667 Rm_Allocator *rmAllocatorFind(Rm_Allocator *allocatorList, char *resourceName)\r
1668 {\r
1669 while (allocatorList) {\r
1670 if (strncmp(allocatorList->resourceName, resourceName, RM_NAME_MAX_CHARS) == 0) {\r
1671 break; \r
1672 }\r
1673 allocatorList = allocatorList->nextAllocator;\r
1674 }\r
1675 \r
1676 return (allocatorList);\r
1677 }\r
1678 \r
1679 /* FUNCTION PURPOSE: Processes a transaction\r
1680 ***********************************************************************\r
1681 * DESCRIPTION: Processes transactions created from services\r
1682 * received via the service handle or the transport.\r
1683 * Transactions will be routed within the RM system\r
1684 * based on the RM instance type and the type of\r
1685 * the transaction.\r
1686 */\r
1687 void rmTransactionProcessor (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
1688 {\r
1689 void *validInstNode;\r
1690 Rm_PolicyCheckCfg privCheckCfg;\r
1691 Rm_NameServerObjCfg nameServerObjCfg; \r
1692 uint32_t allocType = 0; \r
1693 \r
1694 /* Handle static transactions originating on this instance. Any other static transactions will be\r
1695 * stored in transaction queue until all transports are up. */\r
1696 if (((rmInst->instType == Rm_instType_CLIENT) || (rmInst->instType == Rm_instType_CLIENT_DELEGATE)) &&\r
1697 (!rmInst->registeredWithDelegateOrServer) && \r
1698 (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS) == 0)) {\r
1699 if (rmInst->staticInfo.staticPolicy) {\r
1700 if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||\r
1701 (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE)) {\r
1702 /* Check request against startup policy */\r
1703 memset((void *)&privCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));\r
1704 \r
1705 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {\r
1706 privCheckCfg.type = Rm_policyCheck_INIT;\r
1707 }\r
1708 else {\r
1709 privCheckCfg.type = Rm_policyCheck_USE;\r
1710 }\r
1711 privCheckCfg.policyDtb = rmInst->staticInfo.staticPolicy;\r
1712 privCheckCfg.validInstNode = rmPolicyGetValidInstNode(rmInst->staticInfo.staticValidInstTree, \r
1713 rmInst->instName);\r
1714 privCheckCfg.resourceOffset = rmPolicyGetResourceOffset(rmInst->staticInfo.staticPolicy,\r
1715 transaction->resourceInfo.name);\r
1716 privCheckCfg.resourceBase = transaction->resourceInfo.base;\r
1717 privCheckCfg.resourceLength = transaction->resourceInfo.length;\r
1718 \r
1719 if (rmPolicyCheckPrivilege(&privCheckCfg, &transaction->state)) {\r
1720 transaction->state = RM_SERVICE_APPROVED_STATIC;\r
1721 }\r
1722 else if (transaction->state == RM_SERVICE_PROCESSING) {\r
1723 /* Privilege check returned false without error */\r
1724 transaction->state = RM_SERVICE_DENIED_BY_STATIC_POLICY;\r
1725 }\r
1726 }\r
1727 else {\r
1728 transaction->state = RM_SERVICE_DENIED_INVALID_STATIC_REQUEST;\r
1729 }\r
1730 }\r
1731 else {\r
1732 transaction->state = RM_ERROR_REQ_FAILED_NO_STATIC_POLICY;\r
1733 } \r
1734 }\r
1735 else {\r
1736 /* Handle auto-forwarded transactions. These transactions include:\r
1737 * - All request transactions received on Clients are forwarded to the Client Delegate\r
1738 * - NameServer requests received on the Client Delegate are forwarded to the Server */\r
1739 if ((rmInst->instType == Rm_instType_CLIENT) ||\r
1740 ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
1741 ((transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) ||\r
1742 (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) ||\r
1743 (transaction->type == Rm_service_RESOURCE_UNMAP_NAME)))) {\r
1744 \r
1745 if ((transaction->state != RM_SERVICE_PROCESSING) &&\r
1746 (transaction->state != RM_SERVICE_APPROVED_STATIC)) {\r
1747 if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {\r
1748 /* Transaction did not originate on this instance */\r
1749 transactionResponder(rmInst, transaction);\r
1750 }\r
1751 else {\r
1752 /* Transaction originated on this instance */\r
1753 serviceResponder(rmInst, transaction);\r
1754 }\r
1755 }\r
1756 else {\r
1757 /* Forward request if transport is up. Otherwise, just queue. */\r
1758 if (rmInst->registeredWithDelegateOrServer) {\r
1759 transactionForwarder(rmInst, transaction); \r
1760 } \r
1761 }\r
1762 }\r
1763 else {\r
1764 /* Validate service's originating instance name */\r
1765 if (rmInst->instType == Rm_instType_SERVER) {\r
1766 validInstNode = rmPolicyGetValidInstNode(rmInst->validInstances, transaction->serviceSrcInstName);\r
1767 if (validInstNode == NULL) {\r
1768 transaction->state = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;\r
1769 \r
1770 /* Send result via responder if transaction did not originate from this instance */\r
1771 if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {\r
1772 transactionResponder(rmInst, transaction);\r
1773 }\r
1774 }\r
1775 }\r
1776 \r
1777 switch (transaction->type) {\r
1778 case Rm_service_RESOURCE_ALLOCATE_INIT:\r
1779 case Rm_service_RESOURCE_ALLOCATE_USE:\r
1780 case Rm_service_RESOURCE_FREE: \r
1781 if ((transaction->state != RM_SERVICE_PROCESSING) &&\r
1782 (transaction->state != RM_SERVICE_APPROVED_STATIC)) {\r
1783 /* Transaction complete */\r
1784 if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {\r
1785 /* Transaction result not destined for this instance */\r
1786 transactionResponder(rmInst, transaction);\r
1787 }\r
1788 else {\r
1789 /* Transaction result destined for this instance */\r
1790 serviceResponder(rmInst, transaction); \r
1791 }\r
1792 }\r
1793 else {\r
1794 /* Complete allocation/free request */\r
1795 if (transaction->type == Rm_service_RESOURCE_FREE) {\r
1796 freeHandler(rmInst, transaction, validInstNode);\r
1797 }\r
1798 else {\r
1799 switch (transaction->type) {\r
1800 case Rm_service_RESOURCE_ALLOCATE_INIT:\r
1801 RM_policy_SET_PERM(allocType, RM_POLICY_PERM_INIT_SHIFT, 1);\r
1802 break;\r
1803 case Rm_service_RESOURCE_ALLOCATE_USE:\r
1804 RM_policy_SET_PERM(allocType, RM_POLICY_PERM_USE_SHIFT, 1); \r
1805 break;\r
1806 }\r
1807 allocationHandler(rmInst, transaction, validInstNode, allocType);\r
1808 }\r
1809 }\r
1810 break;\r
1811 case Rm_service_RESOURCE_MAP_TO_NAME:\r
1812 case Rm_service_RESOURCE_GET_BY_NAME:\r
1813 case Rm_service_RESOURCE_UNMAP_NAME: \r
1814 /* NameServer resides on server */\r
1815 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));\r
1816 if (rmInst->nameServer) {\r
1817 nameServerObjCfg.nameServerTree = rmInst->nameServer;\r
1818 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;\r
1819 if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {\r
1820 nameServerObjCfg.nodeCfg.resourceName = transaction->resourceInfo.name;\r
1821 nameServerObjCfg.nodeCfg.resourceBase= transaction->resourceInfo.base;\r
1822 nameServerObjCfg.nodeCfg.resourceLength = transaction->resourceInfo.length;\r
1823 transaction->state = rmNameServerAddObject(&nameServerObjCfg);\r
1824 }\r
1825 else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {\r
1826 if ((transaction->state = rmNameServerFindObject(&nameServerObjCfg)) ==\r
1827 RM_SERVICE_PROCESSING) {\r
1828 strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);\r
1829 transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;\r
1830 transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;\r
1831 transaction->state = RM_SERVICE_APPROVED;\r
1832 } \r
1833 }\r
1834 else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {\r
1835 transaction->state = rmNameServerDeleteObject(&nameServerObjCfg);\r
1836 }\r
1837 }\r
1838 else {\r
1839 transaction->state = RM_ERROR_NAMESERVER_DOES_NOT_EXIST;\r
1840 }\r
1841 \r
1842 /* Send result via responder if transaction did not originate from this instance */\r
1843 if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {\r
1844 transactionResponder(rmInst, transaction);\r
1845 }\r
1846 break;\r
1847 }\r
1848 }\r
1849 }\r
1850 \r
1851 /* Forward any queued requests that weren't forwarded yet */\r
1852 if (rmInst->registeredWithDelegateOrServer) {\r
1853 transaction = rmInst->transactionQueue;\r
1854 while(transaction) {\r
1855 if (((transaction->state == RM_SERVICE_PROCESSING) ||\r
1856 (transaction->state == RM_SERVICE_APPROVED_STATIC)) &&\r
1857 !transaction->hasBeenForwarded) {\r
1858 transactionForwarder(rmInst, transaction);\r
1859 }\r
1860 transaction = transaction->nextTransaction;\r
1861 }\r
1862 }\r
1863 }\r
1864 \r
1865 /**********************************************************************\r
1866 ********************** Application visible APIs **********************\r
1867 **********************************************************************/\r
1868 \r
1869 /* FUNCTION PURPOSE: Display status of managed resources\r
1870 ***********************************************************************\r
1871 * DESCRIPTION: Prints the status (allocate/free status, as well as\r
1872 * owners) for all resources managed by the RM \r
1873 * instance network. Also, prints the NameServer name\r
1874 * entries. This function is only available on server\r
1875 * instances.\r
1876 */\r
1877 void Rm_printResourceStatus(Rm_Handle rmServerHandle)\r
1878 {\r
1879 Rm_Inst *rmInst = (Rm_Inst *)rmServerHandle;\r
1880 Rm_Allocator *allocator = rmInst->allocators;\r
1881 Rm_Owner *owners;\r
1882 Rm_ResourceTree *treeRoot;\r
1883 Rm_ResourceNode *treeNode;\r
1884 \r
1885 if (rmInst->instType == Rm_instType_SERVER) {\r
1886 while (allocator != NULL) {\r
1887 Rm_osalLog("Resource: %s\n", allocator->resourceName);\r
1888 \r
1889 treeRoot = allocator->allocatorRootEntry;\r
1890 \r
1891 RB_FOREACH(treeNode, _Rm_AllocatorResourceTree, treeRoot) { \r
1892 Rm_osalLog(" %10d - %10d ", treeNode->base, \r
1893 treeNode->base + treeNode->length -1);\r
1894 \r
1895 if (treeNode->allocationCount == 0) {\r
1896 Rm_osalLog("NOT ALLOCATED\n");\r
1897 }\r
1898 else {\r
1899 owners = treeNode->ownerList;\r
1900 Rm_osalLog("allocated to");\r
1901 while (owners) {\r
1902 Rm_osalLog(" %s", owners->instNameNode->name);\r
1903 owners = owners->nextOwner;\r
1904 }\r
1905 Rm_osalLog("\n");\r
1906 }\r
1907 } \r
1908 allocator = allocator->nextAllocator;\r
1909 }\r
1910 rmNameServerPrintObjects(rmInst->nameServer);\r
1911 }\r
1912 }\r
1913 \r
1914 /* FUNCTION PURPOSE: Display status of a RM instance\r
1915 ***********************************************************************\r
1916 * DESCRIPTION: Prints the current status of various RM instance\r
1917 * properties such as the state of all transactions\r
1918 * in the transaction queue and registered transports\r
1919 */\r
1920 void Rm_printInstanceStatus(Rm_Handle rmHandle)\r
1921 {\r
1922 Rm_Inst *rmInst = (Rm_Inst *)rmHandle;\r
1923 Rm_Transport *transportList = (Rm_Transport *)rmInst->transports;\r
1924 Rm_Transaction *transactionQ = rmInst->transactionQueue;\r
1925 \r
1926 Rm_osalLog("Instance name: %s\n", rmInst->instName);\r
1927 if (rmInst->instType == Rm_instType_SERVER) {\r
1928 Rm_osalLog("Type: Server\n");\r
1929 }\r
1930 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {\r
1931 Rm_osalLog("Type: Client Delegate\n");\r
1932 }\r
1933 else {\r
1934 Rm_osalLog("Type: Client\n");\r
1935 }\r
1936 \r
1937 if (transportList) {\r
1938 Rm_osalLog("\nRegistered Transports:\n");\r
1939 while (transportList) {\r
1940 Rm_osalLog(" Remote instName: %s\n", transportList->remoteInstName);\r
1941 if (transportList->remoteInstType == Rm_instType_SERVER) {\r
1942 Rm_osalLog(" Remote instType: Server\n");\r
1943 }\r
1944 else if (transportList->remoteInstType == Rm_instType_CLIENT_DELEGATE) {\r
1945 Rm_osalLog(" Remote instType: Client Delegate\n");\r
1946 }\r
1947 else {\r
1948 Rm_osalLog(" Remote instType: Client\n");\r
1949 }\r
1950 Rm_osalLog(" appTransportHandle: 0x%08x\n", transportList->appTransportHandle);\r
1951 Rm_osalLog("\n");\r
1952 transportList = transportList->nextTransport;\r
1953 }\r
1954 }\r
1955 \r
1956 if (transactionQ) {\r
1957 Rm_osalLog("\nQueued Service Transactions:\n");\r
1958 while (transactionQ) {\r
1959 Rm_osalLog(" Service type: %d\n", transactionQ->type);\r
1960 Rm_osalLog(" Service ID: %d\n", transactionQ->localId);\r
1961 Rm_osalLog(" Service srcInstName %s\n", transactionQ->serviceSrcInstName);\r
1962 Rm_osalLog(" Service state: %d\n", transactionQ->state);\r
1963 Rm_osalLog(" Resource name: %s\n", transactionQ->resourceInfo.name);\r
1964 Rm_osalLog(" Resource base: %d\n", transactionQ->resourceInfo.base);\r
1965 Rm_osalLog(" Resource length: %d\n", transactionQ->resourceInfo.length);\r
1966 Rm_osalLog(" Resource alignment: %d\n", transactionQ->resourceInfo.alignment);\r
1967 Rm_osalLog(" Resource NS name: %s\n", transactionQ->resourceInfo.nameServerName);\r
1968 Rm_osalLog("\n");\r
1969 transactionQ = transactionQ->nextTransaction;\r
1970 } \r
1971 }\r
1972 }\r
1973 \r
1974 /* FUNCTION PURPOSE: RM instance creation and initialization\r
1975 ***********************************************************************\r
1976 * DESCRIPTION: Returns a new RM instance created and initialized\r
1977 * using the parameters provided via the initCfg\r
1978 * structure.\r
1979 */\r
1980 Rm_Handle Rm_init(Rm_InitCfg *initCfg, int32_t *result)\r
1981 {\r
1982 Rm_Inst *rmInst;\r
1983 void *globalResourceDtb = NULL;\r
1984 void *linuxResourceDtb = NULL;\r
1985 bool addLinux = false;\r
1986 \r
1987 *result = RM_OK;\r
1988 \r
1989 if ((initCfg->instName == NULL) ||\r
1990 ((strlen(initCfg->instName) + 1) > RM_NAME_MAX_CHARS)) {\r
1991 *result = RM_ERROR_INVALID_INST_NAME;\r
1992 return (NULL);\r
1993 }\r
1994 \r
1995 if (initCfg->instType >= Rm_instType_LAST) {\r
1996 *result = RM_ERROR_INVALID_INST_TYPE;\r
1997 }\r
1998 \r
1999 /* Create and initialize instance */\r
2000 rmInst = Rm_osalMalloc (sizeof(Rm_Inst));\r
2001 memset ((void *) rmInst, 0, sizeof(Rm_Inst));\r
2002 rmInst->isLocked = false;\r
2003 rmInst->registeredWithDelegateOrServer = false;\r
2004 rmInst->transactionSeqNum = transactionInitSequenceNum();\r
2005 \r
2006 rmInst->instType = initCfg->instType; \r
2007 strncpy (rmInst->instName, initCfg->instName, RM_NAME_MAX_CHARS);\r
2008 \r
2009 if (rmInst->instType == Rm_instType_SERVER) {\r
2010 if (!initCfg->instCfg.serverCfg.globalResourceList ||\r
2011 !initCfg->instCfg.serverCfg.globalPolicy) {\r
2012 *result = RM_ERROR_INVALID_SERVER_CONFIGURATION;\r
2013 Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));\r
2014 return(NULL);\r
2015 }\r
2016 \r
2017 rmInst->policy = initCfg->instCfg.serverCfg.globalPolicy;\r
2018 fdt_open_into(rmInst->policy, rmInst->policy, fdt_totalsize(rmInst->policy)); \r
2019 \r
2020 if (initCfg->instCfg.serverCfg.linuxDtb) {\r
2021 linuxResourceDtb = initCfg->instCfg.serverCfg.linuxDtb;\r
2022 fdt_open_into(linuxResourceDtb, linuxResourceDtb, fdt_totalsize(linuxResourceDtb));\r
2023 addLinux = true;\r
2024 }\r
2025 \r
2026 /* Create valid instance list from policy. Must be done prior to parsing\r
2027 * GRL so that Linux resources can be reserved correctly */\r
2028 rmInst->validInstances = rmPolicyCreateValidInstTree(rmInst->policy, addLinux, result);\r
2029 /* Validate policy assignment strings */\r
2030 *result = rmPolicyValidatePolicy(rmInst->policy, rmInst->validInstances); \r
2031 \r
2032 rmInst->nameServer = rmNameServerInit();\r
2033 \r
2034 globalResourceDtb = initCfg->instCfg.serverCfg.globalResourceList;\r
2035 fdt_open_into(globalResourceDtb, globalResourceDtb, fdt_totalsize(globalResourceDtb));\r
2036 \r
2037 if ((*result = initializeAllocators(rmInst, globalResourceDtb, linuxResourceDtb)) == RM_OK) { \r
2038 *result = rmPolicyValidatePolicyResourceNames(rmInst->policy, (void *)rmInst->allocators);\r
2039 }\r
2040 if (*result < RM_OK) {\r
2041 Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));\r
2042 return(NULL);\r
2043 }\r
2044 }\r
2045 \r
2046 if ((rmInst->instType == Rm_instType_CLIENT) && \r
2047 (initCfg->instCfg.clientCfg.staticPolicy)) {\r
2048 rmInst->staticInfo.staticPolicy = initCfg->instCfg.clientCfg.staticPolicy; \r
2049 }\r
2050 else if ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
2051 (initCfg->instCfg.cdCfg.staticPolicy)) { \r
2052 rmInst->staticInfo.staticPolicy = initCfg->instCfg.cdCfg.staticPolicy; \r
2053 }\r
2054 if (rmInst->staticInfo.staticPolicy) {\r
2055 fdt_open_into(rmInst->staticInfo.staticPolicy, rmInst->staticInfo.staticPolicy, \r
2056 fdt_totalsize(rmInst->staticInfo.staticPolicy)); \r
2057 rmInst->staticInfo.staticValidInstTree = rmPolicyCreateValidInstTree(rmInst->staticInfo.staticPolicy, \r
2058 addLinux, result); \r
2059 if (*result == RM_OK) {\r
2060 /* Validate policy assignment strings */\r
2061 *result = rmPolicyValidatePolicy(rmInst->staticInfo.staticPolicy, rmInst->staticInfo.staticValidInstTree);\r
2062 }\r
2063 if (*result != RM_OK) {\r
2064 if (rmInst->staticInfo.staticValidInstTree) {\r
2065 rmPolicyFreeValidInstTree(rmInst->staticInfo.staticValidInstTree);\r
2066 }\r
2067 Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));\r
2068 rmInst = NULL;\r
2069 }\r
2070 }\r
2071 return ((Rm_Handle) rmInst);\r
2072 }\r
2073 \r
2074 /* FUNCTION PURPOSE: Returns RM version information\r
2075 ***********************************************************************\r
2076 */\r
2077 uint32_t Rm_getVersion (void)\r
2078 {\r
2079 return RM_VERSION_ID;\r
2080 }\r
2081 \r
2082 /* FUNCTION PURPOSE: Returns RM version string\r
2083 ***********************************************************************\r
2084 */\r
2085 const char* Rm_getVersionStr (void)\r
2086 {\r
2087 return rmVersionStr;\r
2088 }\r
2089 \r