diff --git a/src/rm.c b/src/rm.c
index e14884ba77a56d696f22a3f316fc142479c2e6cc..16b3dd72ebab462338aba2d5934295e6f44de774 100644 (file)
--- a/src/rm.c
+++ b/src/rm.c
/* RM LIBFDT includes */\r
#include <ti/drv/rm/src/libfdt/libfdt.h>\r
\r
+/* AVL BBST includes */\r
+#include <ti/drv/rm/include/tree.h>\r
+\r
/* RM OSAL layer */\r
#include <rm_osal.h>\r
\r
/**********************************************************************\r
************************** Globals ***********************************\r
**********************************************************************/\r
-#if 0\r
-/* Place QMSS PDSP permissions array */\r
-#pragma DATA_SECTION (rmQmssPdspFirmwarePerms, ".rm");\r
-#pragma DATA_ALIGN (rmQmssPdspFirmwarePerms, 128)\r
-Rm_Perms rmQmssPdspFirmwarePerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_QMSS_FIRMWARE_PDSPS, Rm_Perms)];\r
-#endif\r
+char rmIntegerAllocator[] = "integer";\r
+char rmTreeAllocator[] = "tree";\r
+\r
+extern char rmDtbStartingNode[];\r
\r
/** @brief Global Variable which describes the RM Version Information */\r
const char rmVersionStr[] = RM_VERSION_STR ":" __DATE__ ":" __TIME__;\r
\r
+/**********************************************************************\r
+ ************** Red-Black BBST Tree Allocator Functions ***************\r
+ **********************************************************************/\r
+\r
+/* TODO: This needed? */\r
+/* Prototype for function that allocates new tree nodes */\r
+Rm_ResourceTreeNode *Rm_newResourceTreeNode(uint32_t resourceBase, uint32_t resourceLength)\r
+{\r
+ Rm_ResourceTreeNode *newNode = NULL;\r
+\r
+ newNode = Rm_osalMalloc(sizeof(Rm_ResourceTreeNode));\r
+\r
+ /* Populate the RM relevant fields */\r
+ newNode->base = resourceBase;\r
+ newNode->length = resourceLength;\r
+\r
+ return(newNode);\r
+}\r
+\r
+/* TODO: This needed? */\r
+/* Prototype for function that frees new tree nodes */\r
+void Rm_freeResourceTreeNode(Rm_ResourceTreeNode *treeNode)\r
+{\r
+ /* Free the memory associated with the tree node. */\r
+ Rm_osalFree((void *)treeNode, sizeof(Rm_ResourceTreeNode));\r
+}\r
+\r
+/* Prototype for tree node comparison function\r
+ * element1 < element2 --> return < 0\r
+ * element1 = element2 --> return 0\r
+ * element1 > element2 --> return > 0 */\r
+int Rm_ResourceTreeNodeCompare(Rm_ResourceTreeNode *element1, Rm_ResourceTreeNode *element2)\r
+{\r
+ uint32_t element1End = element1->base + element1->length - 1;\r
+ uint32_t element2End = element2->base + element2->length - 1;\r
+\r
+ if (element1End < element2->base)\r
+ {\r
+ /* End of element1 range is less than the start of element2's range. Return a negative\r
+ * value */\r
+ return (-1);\r
+ }\r
+ else if (element1->base > element2End)\r
+ {\r
+ /* Start of element1 range is after end of element2's range. Return a positive value */\r
+ return (1);\r
+ }\r
+ else\r
+ {\r
+ /* If neither of the latter conditions were satisfied there is some overlap between\r
+ * element1 and element2. Return 0 since the application must handle this overlap. */\r
+ return (0);\r
+ }\r
+}\r
+\r
+/* Generate the red-black tree manipulation functions */\r
+RB_GENERATE(_Rm_ResourceTree, _Rm_ResourceTreeNode, linkage, Rm_ResourceTreeNodeCompare);\r
+\r
/**********************************************************************\r
********************** Internal Functions ****************************\r
**********************************************************************/\r
\r
-/* At the very least the transaction ID needs to be provided to create a transaction */\r
Rm_Transaction *Rm_transactionQueueAdd(Rm_Inst *rmInst)\r
{\r
Rm_Transaction *transactionQueue = (Rm_Transaction *)rmInst->transactionQueue;\r
/* Return if the memory allocated for the transaction entry is NULL */\r
if (newTransaction == NULL)\r
{\r
- Rm_osalMtCsExit(key);\r
- return(newTransaction);\r
- }\r
-\r
- /* Clear the transaction */\r
- memset((void *)newTransaction, 0, sizeof(Rm_Transaction));\r
-\r
- /* Create an ID for the new transaction. The ID will be used for two purposes:\r
- * 1) Matching responses from higher level RM agents to requests\r
- * 2) Provided to the component that requested the service so that it can match its\r
- * request with the response it receives via its callback function it provided */\r
- newTransaction->localId = Rm_transactionGetSequenceNum(rmInst);\r
- /* New transaction's nextTransaction pointer will always be NULL */\r
- newTransaction->nextTransaction = NULL; \r
+ /* Clear the transaction */\r
+ memset((void *)newTransaction, 0, sizeof(Rm_Transaction));\r
+\r
+ /* Create an ID for the new transaction. The ID will be used for two purposes:\r
+ * 1) Matching responses from higher level RM agents to requests\r
+ * 2) Provided to the component that requested the service so that it can match its\r
+ * request with the response it receives via its callback function it provided */\r
+ newTransaction->localId = Rm_transactionGetSequenceNum(rmInst);\r
+ /* New transaction's nextTransaction pointer will always be NULL */\r
+ newTransaction->nextTransaction = NULL; \r
+\r
+ /* Check if there are any transactions in the transaction queue */\r
+ if (transactionQueue)\r
+ {\r
+ /* At least one transaction in the transaction queue. Add the new entry to the \r
+ * end of the transaction queue */\r
+ while (transactionQueue->nextTransaction != NULL)\r
+ {\r
+ /* Traverse the list until arriving at the last transaction */\r
+ transactionQueue = transactionQueue->nextTransaction;\r
+ }\r
\r
- /* Check if there are any transactions in the transaction queue */\r
- if (transactionQueue)\r
- {\r
- /* At least one transaction in the transaction queue. Add the new entry to the \r
- * end of the transaction queue */\r
- while (transactionQueue->nextTransaction != NULL)\r
+ /* Add the new transaction to the end of the queue */\r
+ transactionQueue->nextTransaction = newTransaction;\r
+ }\r
+ else\r
{\r
- /* Traverse the list until arriving at the last transaction */\r
- transactionQueue = transactionQueue->nextTransaction;\r
+ /* The transaction queue does not currently exist. The new transaction is the \r
+ * first transaction */\r
+ rmInst->transactionQueue = newTransaction;\r
}\r
-\r
- /* Add the new transaction to the end of the queue */\r
- transactionQueue->nextTransaction = newTransaction;\r
- }\r
- else\r
- {\r
- /* The transaction queue does not currently exist. The new transaction is the \r
- * first transaction */\r
- rmInst->transactionQueue = newTransaction;\r
}\r
\r
Rm_osalMtCsExit(key);\r
else\r
{\r
/* Delete the transaction */\r
- if (prevTransaction == NULL)\r
+ if ((prevTransaction == NULL) && transaction->nextTransaction)\r
{\r
/* Transaction to be deleted exists at start of transaction queue. Map second\r
- * transaction to be start of transaction queue. This covers case where there is\r
- * only one transaction in the queue since the nextTransaction will be NULL */\r
+ * transaction to be start of transaction queue as long as there are more than\r
+ * one transactions. */\r
rmInst->transactionQueue = transaction->nextTransaction;\r
}\r
else\r
Rm_transactionQueueDelete(rmInst, transaction->localId);\r
}\r
\r
-void Rm_allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
+Rm_Allocator *Rm_allocatorAdd(Rm_Inst *rmInst, const char *resourceName, Rm_AllocatorType type)\r
{\r
- if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
+ Rm_Allocator *allocators = (Rm_Allocator *)rmInst->allocators;\r
+ Rm_Allocator *newAllocator = NULL;\r
+ void *key;\r
+\r
+ /* Lock access to the RM instance's allocator list */\r
+ key = Rm_osalMtCsEnter();\r
+\r
+ /* Get memory for a new allocator from local memory */\r
+ newAllocator = Rm_osalMalloc(sizeof(Rm_Allocator));\r
+\r
+ /* Return if the memory allocated for the allocator is NULL */\r
+ if (newAllocator != NULL)\r
{\r
-#if 0 \r
- /* Check local policy to see if the request can be satisfied with the\r
- * resources stored locally */\r
- Rm_policy...API()\r
+ /* Clear the allocator */\r
+ memset((void *)newAllocator, 0, sizeof(Rm_Allocator));\r
+\r
+ /* Populate the allocator */\r
+ newAllocator->type = type;\r
+ strcpy(newAllocator->resourceName, resourceName);\r
+ /* allocator's root entry will be created by the invoking function */\r
+ newAllocator->allocatorRootEntry = NULL;\r
+ /* New allocator's nextAllocator pointer will always be NULL */\r
+ newAllocator->nextAllocator = NULL; \r
+\r
+ /* Check if there are any allocators in the allocator list */\r
+ if (allocators)\r
+ {\r
+ /* At least one allocator in the allocator list. Add the new allocator to the \r
+ * end of the allocator list */\r
+ while (allocators->nextAllocator != NULL)\r
+ {\r
+ /* Traverse the list until arriving at the last allocator */\r
+ allocators = allocators->nextAllocator;\r
+ }\r
\r
- if (policy check approves the resource)\r
+ /* Add the new allocator to the end of the list */\r
+ allocators->nextAllocator = newAllocator;\r
+ }\r
+ else\r
+ {\r
+ /* The allocator list does not currently exist. The new allocator is the \r
+ * first allocator */\r
+ rmInst->allocators = newAllocator;\r
+ }\r
+ }\r
+\r
+ Rm_osalMtCsExit(key);\r
+ return (newAllocator);\r
+}\r
+\r
+Rm_Allocator *Rm_allocatorFind(Rm_Inst *rmInst, char *resourceName)\r
+{\r
+ Rm_Allocator *allocator = (Rm_Allocator *)rmInst->allocators;\r
+\r
+ /* Make sure there is at least one allocator in the allocator list */\r
+ if (allocator != NULL)\r
+ {\r
+ /* Find the resource name within the allocator list. If the end of the\r
+ * allocator list is reached without finding the resource name the \r
+ * allocator pointer will be NULL */\r
+ while (allocator != NULL)\r
{\r
- /* call the allocator to allocate the resource */\r
- if (allocator returns resource)\r
+ if (strcmp(allocator->resourceName, resourceName) == 0)\r
{\r
- /* Populate the transaction with the allocated resources and the result */\r
- transaction->state = approve reason;\r
- return ...\r
+ /* Match: break out of loop and return the allocator */\r
+ break; \r
+ }\r
+ allocator = allocator->nextAllocator;\r
+ }\r
+ }\r
+\r
+ return (allocator);\r
+}\r
+\r
+int32_t Rm_allocatorDelete(Rm_Inst *rmInst, char *resourceName)\r
+{\r
+ Rm_Allocator *allocator = (Rm_Allocator *) rmInst->allocators;\r
+ Rm_Allocator *prevAllocator = NULL;\r
+ int32_t retVal = RM_SERVICE_STATE_OKAY;\r
+ void *key;\r
+\r
+ /* Lock access to the RM instance's allocator list */\r
+ key = Rm_osalMtCsEnter();\r
+\r
+ /* Find the resource within the specified RM instance's allocator list. */\r
+ while (allocator != NULL)\r
+ {\r
+ if (strcmp(allocator->resourceName, resourceName) == 0)\r
+ {\r
+ /* Match: break out of loop and delete the transaction */\r
+ break; \r
+ }\r
+\r
+ prevAllocator = allocator;\r
+ allocator = allocator->nextAllocator;\r
+ }\r
+\r
+ /* Traversed entire list but did not find allocator. */\r
+ if (allocator == NULL)\r
+ {\r
+ retVal = -22; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
+ }\r
+ else\r
+ {\r
+ /* Delete the allocator */\r
+ if ((prevAllocator == NULL) && allocator->nextAllocator)\r
+ {\r
+ /* Allocator to be deleted exists at start of allocator list. Map second\r
+ * allocator to be start of allocator list as long as there are more than\r
+ * one allocators. */\r
+ rmInst->allocators = allocator->nextAllocator;\r
+ }\r
+ else\r
+ {\r
+ /* Allocator to be deleted is in the middle or at end of the list. Adjust \r
+ * adjacent allocator pointers. This covers the case where the allocator to be \r
+ * removed is at the end of the list. */\r
+ prevAllocator->nextAllocator = allocator->nextAllocator;\r
+ }\r
+\r
+ /* Free the memory associated with the allocator. */\r
+ Rm_osalFree((void *)allocator, sizeof(Rm_Allocator));\r
+ }\r
+\r
+ Rm_osalMtCsExit(key);\r
+ return (retVal);\r
+}\r
+\r
+int32_t Rm_createIntegerAllocator(Rm_Inst *rmInst, const char *resourceName, Rm_ResourceRange *range)\r
+{\r
+ Rm_Allocator *allocator = NULL;\r
+ Rm_ResourceRange *rangeBasePtr = range;\r
+ Rm_IntegerAllocatorRootEntry *intRootEntry = NULL;\r
+ uint16_t i, entryIndex;\r
+\r
+ /* Create the new base integer allocator */\r
+ allocator = Rm_allocatorAdd(rmInst, resourceName, Rm_allocatorType_INTEGER);\r
+\r
+ /* Construct the integer allocator root entry */\r
+ intRootEntry = Rm_osalMalloc(sizeof(Rm_IntegerAllocatorRootEntry));\r
+ intRootEntry->numResourceElements = 0;\r
+\r
+ /* Get the number of entries to allocate based on the lengths in the ranges */\r
+ while (range != NULL)\r
+ {\r
+ intRootEntry->numResourceElements += range->length;\r
+ range = range->nextRange;\r
+ }\r
+\r
+ /* Initialize the entries using the range information */\r
+ if (intRootEntry->numResourceElements)\r
+ {\r
+ intRootEntry->resourceArrayBase = Rm_osalMalloc(sizeof(Rm_IntegerEntry) * intRootEntry->numResourceElements);\r
+ memset((void *)intRootEntry->resourceArrayBase, 0, sizeof(Rm_IntegerEntry) * intRootEntry->numResourceElements);\r
+\r
+ /* Reset the range pointer */\r
+ range = rangeBasePtr;\r
+ entryIndex = 0;\r
+\r
+ while (range != NULL)\r
+ {\r
+ /* Initialize each entry */\r
+ for (i = range->base; i < (range->base + range->length); i++, entryIndex++)\r
+ {\r
+ intRootEntry->resourceArrayBase[entryIndex].value = i;\r
+ /* Initialize the allocatedTo field to the NOT_ALLOCATED string */\r
+ strcpy(intRootEntry->resourceArrayBase[entryIndex].allocatedTo, RM_NOT_ALLOCATED_STRING);\r
+ }\r
+ \r
+ range = range->nextRange;\r
+ }\r
+ \r
+ allocator->allocatorRootEntry = intRootEntry;\r
+ }\r
+ else\r
+ {\r
+ /* No resource entries were created. Free the memory associated with the\r
+ * allocator and the root entry */\r
+ Rm_osalFree((void *)intRootEntry, sizeof(Rm_IntegerAllocatorRootEntry));\r
+ Rm_allocatorDelete(rmInst, allocator->resourceName);\r
+ }\r
+\r
+ return(0); /* TODO: FIX THIS RETURN */\r
+}\r
+\r
+int32_t Rm_createTreeAllocator(Rm_Inst *rmInst, const char *resourceName, Rm_ResourceRange *range)\r
+{\r
+ Rm_Allocator *allocator = NULL;\r
+ Rm_ResourceTree *treeRootEntry = NULL;\r
+ Rm_ResourceTreeNode *treeNode = NULL;\r
+ Rm_ResourceTreeNode *collidingNode = NULL;\r
+\r
+ /* Create the new base integer allocator */\r
+ allocator = Rm_allocatorAdd(rmInst, resourceName, Rm_allocatorType_TREE);\r
+\r
+ /* Create the tree root entry and initialize it */\r
+ treeRootEntry = Rm_osalMalloc(sizeof(Rm_ResourceTree));\r
+ RB_INIT(treeRootEntry);\r
+\r
+ /* Create a node in the tree for resource range and insert them into the tree. */\r
+ while (range != NULL)\r
+ {\r
+ treeNode = Rm_osalMalloc(sizeof(Rm_ResourceTreeNode));\r
+ treeNode->base = range->base;\r
+ treeNode->length = range->length;\r
+ /* Initialize the allocatedTo field to the NOT_ALLOCATED string */\r
+ strcpy(treeNode->allocatedTo, RM_NOT_ALLOCATED_STRING);\r
+\r
+ /* Insert the node into the tree */\r
+ collidingNode = RB_INSERT(_Rm_ResourceTree, treeRootEntry, treeNode);\r
+\r
+ if (collidingNode)\r
+ {\r
+ Rm_ResourceTreeNode *nextNode = NULL;\r
+ \r
+ /* Node that was inserted colliding with an existing node. Clean up the tree\r
+ * that's been allocated thus far and return an error since there should be no\r
+ * collisions */\r
+ for (treeNode = RB_MIN(_Rm_ResourceTree, treeRootEntry); treeNode != NULL; treeNode = nextNode)\r
+ {\r
+ nextNode = RB_NEXT(_Rm_ResourceTree, treeRootEntry, treeNode);\r
+ RB_REMOVE(_Rm_ResourceTree, treeRootEntry, nextNode);\r
+ Rm_osalFree((void *)treeNode, sizeof(Rm_ResourceTreeNode));\r
+ }\r
+ /* Delete the tree root entry and the allocator */\r
+ Rm_osalFree((void *)treeRootEntry, sizeof(Rm_ResourceTree));\r
+ Rm_allocatorDelete(rmInst, allocator->resourceName);\r
+ return (-24); /* TODO FIX RETURN */\r
+ }\r
+\r
+ range = range->nextRange;\r
+ }\r
+\r
+ /* Assign the tree's root to the allocator */\r
+ allocator->allocatorRootEntry = treeRootEntry;\r
+\r
+ /* Print the base values as a test */\r
+ RB_FOREACH(treeNode, _Rm_ResourceTree, (Rm_ResourceTree *) allocator->allocatorRootEntry)\r
+ {\r
+ Rm_osalLog("Tree node base: %d length: %d and allocated to: %s\n", treeNode->base, treeNode->length, treeNode->allocatedTo);\r
+ }\r
+\r
+ return(0); /* TODO: FIX THIS RETURN */\r
+}\r
+\r
+int32_t Rm_createAndInitAllocator(Rm_Inst *rmInst, const char *resourceName, \r
+ Rm_ResourceProperties *resourceProperties)\r
+{\r
+ char *allocatorType = NULL;\r
+ Rm_ResourceRange *range = NULL;\r
+ Rm_ResourceRange *rangeBasePtr = NULL;\r
+ Rm_NsAssignment *nsAssignments = NULL;\r
+ Rm_NsAssignment *nsAssignmentBasePtr = NULL;\r
+ int32_t retVal = RM_DTB_UTIL_RESULT_OKAY;\r
+\r
+ /* TODO: NEED CHECKS FOR VALIDITY OF ALL THE resourceProperties FIELDS */\r
+\r
+ /* Extract the resource properties from the DTB */\r
+ allocatorType = Rm_resourceExtractResourceAllocator(resourceProperties->allocatorData, \r
+ resourceProperties->allocatorLen);\r
+ range = rangeBasePtr = Rm_resourceExtractResourceRange(resourceProperties->rangeData, \r
+ resourceProperties->rangeLen);\r
+\r
+ /* Create an allocator based on the allocator type specified */\r
+ if (strcmp(allocatorType, &rmIntegerAllocator[0]) == 0)\r
+ {\r
+ /* Create an integer allocator using the resource properties */\r
+ retVal = Rm_createIntegerAllocator(rmInst, resourceName, range); \r
+ }\r
+ else if (strcmp(allocatorType, &rmTreeAllocator[0]) == 0)\r
+ {\r
+ /* Create a tree allocator using the resource properties */\r
+ retVal = Rm_createTreeAllocator(rmInst, resourceName, range); \r
+ }\r
+ else\r
+ {\r
+ /* Allocator type not recognized. Free the resource properties and return */\r
+ retVal = -21; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
+ }\r
+ \r
+ if (retVal >= RM_DTB_UTIL_RESULT_OKAY)\r
+ {\r
+ /* Create entries in the NameServer if any NameServer assignments were specified */\r
+ if (resourceProperties->nsAssignData && resourceProperties->nsAssignLen)\r
+ {\r
+ nsAssignments = Rm_resourceExtractNsAssignment(resourceProperties->nsAssignData, \r
+ resourceProperties->nsAssignLen);\r
+\r
+ /* Cycle through the list of assignments and add them to the NameServer */\r
+ nsAssignmentBasePtr = nsAssignments;\r
+ while (nsAssignments)\r
+ {\r
+ /* TODO: RETURN IF ANY OF THE ADDS FAIL??? */\r
+ Rm_nsAddObject(rmInst, nsAssignments->nsName, nsAssignments->resourceValue);\r
+ nsAssignments = nsAssignments->nextNsAssignment;\r
+ }\r
+ /* Free the memory allocated for the NameServer assignments */\r
+ Rm_resourceFreeNsAssignmentList(nsAssignmentBasePtr);\r
+ }\r
+ }\r
+\r
+ /* Free the memory allocated for the resource properties */\r
+ Rm_resourceFreeResourceAllocator(allocatorType);\r
+ Rm_resourceFreeResourceRange(rangeBasePtr);\r
+\r
+ return(retVal);\r
+}\r
+\r
+int32_t Rm_parseResourceProperty(void *globalResourceDtb, int32_t offset, Rm_ResourceProperties *propertyInfo)\r
+{\r
+ int32_t propertyLen;\r
+ const char *propertyName;\r
+ const void *propertyData;\r
+ Rm_ResourcePropType propertyType;\r
+ int32_t retVal = RM_DTB_UTIL_RESULT_OKAY;\r
+\r
+ /* Get the property data and store it in the corresponding propertyInfo field */\r
+ propertyData = fdt_getprop_by_offset(globalResourceDtb, offset, &propertyName, &propertyLen);\r
+ if (propertyData)\r
+ {\r
+ propertyType = Rm_resourceGetPropertyType(propertyName);\r
+ if (propertyType == Rm_resourcePropType_RESOURCE_ALLOCATOR)\r
+ {\r
+ if (propertyInfo->allocatorData || propertyInfo->allocatorLen)\r
+ {\r
+ /* The allocator fields have already been populated. Return an error.\r
+ * The resource list has specified a property field more than once\r
+ * for a resource node */\r
+ retVal = -17; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
}\r
else\r
{\r
- /* allocator ran out of resources, need to contact Server for more\r
- * resources */\r
- Rm_resourcePoolModRequest(...);\r
+ propertyInfo->allocatorData = propertyData;\r
+ propertyInfo->allocatorLen = propertyLen;\r
}\r
}\r
- else if (policy check denies resource)\r
+ else if (propertyType == Rm_resourcePropType_RESOURCE_RANGE)\r
{\r
- /* Policy check denied resource. */\r
- transaction->state= deny reason;\r
- return ...\r
+ if (propertyInfo->rangeData || propertyInfo->rangeLen)\r
+ {\r
+ /* The range fields have already been populated. Return an error.\r
+ * The resource list has specified a property field more than once\r
+ * for a resource node */\r
+ retVal = -18; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
+ }\r
+ else\r
+ {\r
+ propertyInfo->rangeData = propertyData;\r
+ propertyInfo->rangeLen = propertyLen;\r
+ }\r
}\r
- else if (policy check says forward to Server for validation)\r
+ else if (propertyType == Rm_resourcePropType_NSASSIGNMENT)\r
{\r
- /* Forward the transaction to the Server */\r
- Rm_transactionForwarder(rmInst, transaction);\r
+ if (propertyInfo->nsAssignData || propertyInfo->nsAssignLen)\r
+ {\r
+ /* The nsAssign fields have already been populated. Return an error.\r
+ * The resource list has specified a property field more than once\r
+ * for a resource node */\r
+ retVal = -19; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
+ }\r
+ else\r
+ {\r
+ propertyInfo->nsAssignData = propertyData;\r
+ propertyInfo->nsAssignLen = propertyLen;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ retVal = -20; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
}\r
-#endif \r
}\r
- else if (rmInst->instType == Rm_instType_SERVER)\r
+ else\r
{\r
-#if 0 \r
- /* Check global policy to see if resource can be allocated. return result\r
- * no matter what */\r
- Rm_policy...API()\r
+ retVal = -16; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
+ }\r
\r
- if (policy approves)\r
+ /* Don't get anymore properties if error occurred */\r
+ if (retVal == RM_DTB_UTIL_RESULT_OKAY)\r
+ {\r
+ offset = fdt_next_property_offset(globalResourceDtb, offset);\r
+ if (offset >= 0)\r
+ {\r
+ retVal = Rm_parseResourceProperty(globalResourceDtb, offset, propertyInfo);\r
+ }\r
+ else if (offset != -FDT_ERR_NOTFOUND)\r
{\r
- /* call allocator to allocate resource */\r
+ /* Error was returned by LIBFDT when parsing the properties */\r
+ retVal = offset;\r
}\r
+ }\r
+ \r
+ return (retVal);\r
+}\r
\r
- transaction->state = approve or deny reason;\r
- transaction->resourceInfo.base = ...;\r
- transaction->resourceInfo.range = ...;\r
+int32_t Rm_parseResourceNode(Rm_Inst *rmInst, void *globalResourceDtb, int32_t nodeOffset, int32_t depth)\r
+{\r
+ const char *resourceName = fdt_get_name(globalResourceDtb, nodeOffset, NULL);\r
+ Rm_ResourceProperties resourceProperties;\r
+ int32_t error = RM_DTB_UTIL_RESULT_OKAY;\r
+ int32_t offset;\r
\r
- /* If source instance name does not match the current instance\r
- * name the allocation request came from a Client. The result\r
- * must be sent back to the Client */\r
- if (strcmp(transaction->sourceInstName, rmInst->name))\r
+ /* Initialize the resource properties structure */\r
+ memset((void *)&resourceProperties, 0, sizeof(Rm_ResourceProperties));\r
+\r
+ /* Ignore properties of the base node */\r
+ if (strcmp(resourceName, rmDtbStartingNode))\r
+ {\r
+ /* Get the properties for the resource node if any exist */\r
+ offset = fdt_first_property_offset(globalResourceDtb, nodeOffset);\r
+ if (offset >= RM_DTB_UTIL_STARTING_NODE_OFFSET)\r
+ {\r
+ /* Since at least one property exists attempt to parse the property nodes and \r
+ * use them to create and initialize a resource allocator */\r
+ error = Rm_parseResourceProperty(globalResourceDtb, offset, &resourceProperties);\r
+ if (error < -FDT_ERR_NOTFOUND)\r
+ {\r
+ return (error);\r
+ }\r
+ \r
+ /* Initialize an allocator with the resource properties if no error was returned */\r
+ Rm_createAndInitAllocator(rmInst, resourceName, &resourceProperties);\r
+ }\r
+ else if (offset != -FDT_ERR_NOTFOUND)\r
{\r
- /* Names don't match. Send the transaction back to the Client */\r
- Rm_transactionResponder(rmInst, transaction);\r
+ /* Error was returned by LIBFDT when parsing the properties */\r
+ return (offset);\r
+ }\r
+ }\r
+ \r
+ /* Get the next resource node */\r
+ offset = fdt_next_node(globalResourceDtb, nodeOffset, &depth);\r
+ /* Check the offset and depth of the next node to make sure the current node\r
+ * wasn't the last node in the Resource List. A depth less than the depth set\r
+ * at the start of the recursion will signal the end of the resource list */\r
+ if ((offset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && (depth >= RM_DTB_UTIL_STARTING_DEPTH))\r
+ {\r
+ error = Rm_parseResourceNode(rmInst, globalResourceDtb, offset, depth);\r
+ if (error < -FDT_ERR_NOTFOUND)\r
+ {\r
+ return (error);\r
+ }\r
+ }\r
+ else if (offset != -FDT_ERR_NOTFOUND)\r
+ {\r
+ /* Error was returned by LIBFDT when parsing the nodes */\r
+ return (offset);\r
+ }\r
+\r
+ return (RM_DTB_UTIL_RESULT_OKAY);\r
+}\r
+\r
+/* Called when an allocate request is made but the base is unspecified. RM must preallocate\r
+ * resources which then must be checked against the RM policy for the instance. If the\r
+ * policy does not agree another resource(s) must be preallocated and tested against the \r
+ * policy. Policy will provide initialize the preallocate with the base that it allows\r
+ * for the rm instance for the specified resource. */\r
+int32_t Rm_integerPreAllocate(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
+{\r
+ \r
+}\r
+\r
+int32_t Rm_integerAllocate(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
+{\r
+ Rm_IntegerAllocatorRootEntry *root = allocator->allocatorRootEntry;\r
+ uint16_t resourceIndex, i, j;\r
+ bool resourcesValidated = TRUE;\r
+ int32_t retVal;\r
+\r
+ /* Find the specified resource base within the allocator */\r
+ for (resourceIndex = 0; resourceIndex < root->numResourceElements; resourceIndex++)\r
+ {\r
+ if (root->resourceArrayBase[resourceIndex].value == opInfo->resourceInfo->base)\r
+ {\r
+ /* Found the resource base in the allocator. Break from the loop */\r
+ break;\r
+ }\r
+ }\r
+\r
+ /* Only execute the allocate operation if the resource base was found in the allocator\r
+ * and the base+range does not exceed the number of entries in the allocator */\r
+ if (resourceIndex + opInfo->resourceInfo->range <= root->numResourceElements)\r
+ {\r
+ /* Verify all resource values from base to base+range exist in the allocator and\r
+ * are not allocated to another instance. */\r
+ for (i = resourceIndex, j = opInfo->resourceInfo->base; \r
+ i < (resourceIndex + opInfo->resourceInfo->range);\r
+ i++, j++)\r
+ {\r
+ if (root->resourceArrayBase[i].value != j)\r
+ {\r
+ /* A value in the range did not match. */\r
+ retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_IN_RANGE_DOES_NOT_EXIST;\r
+ resourcesValidated = FALSE;\r
+ break;\r
+ }\r
+ else if (strcmp(root->resourceArrayBase[i].allocatedTo, RM_NOT_ALLOCATED_STRING) != 0)\r
+ {\r
+ /* A value in the range is already allocated. */\r
+ retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_ALLOCATED;\r
+ resourcesValidated = FALSE;\r
+ break; \r
+ }\r
+ }\r
+\r
+ if (resourcesValidated)\r
+ {\r
+ /* Allocate all resources from base to base+range */\r
+ for (i = resourceIndex; i < (resourceIndex + opInfo->resourceInfo->range); i++)\r
+ {\r
+ strcpy(root->resourceArrayBase[i].allocatedTo, opInfo->srcInstName);\r
+ }\r
+ retVal = RM_SERVICE_APPROVED_AND_COMPLETED;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_IN_RANGE_DOES_NOT_EXIST;\r
+ }\r
+\r
+ return(retVal); \r
+}\r
+\r
+int32_t Rm_integerFree(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
+{\r
+ Rm_IntegerAllocatorRootEntry *root = allocator->allocatorRootEntry;\r
+ uint16_t resourceIndex, i, j;\r
+ bool resourcesValidated = TRUE;\r
+ int32_t retVal;\r
+\r
+ /* Find the specified resource base within the allocator */\r
+ for (resourceIndex = 0; resourceIndex < root->numResourceElements; resourceIndex++)\r
+ {\r
+ if (root->resourceArrayBase[resourceIndex].value == opInfo->resourceInfo->base)\r
+ {\r
+ /* Found the resource base in the allocator. Break from the loop */\r
+ break;\r
+ }\r
+ }\r
+\r
+ /* Only execute the free operation if the resource base was found in the allocator\r
+ * and the base+range does not exceed the number of entries in the allocator */\r
+ if (resourceIndex + opInfo->resourceInfo->range <= root->numResourceElements)\r
+ {\r
+ /* Verify all resource values from base to base+range exist in the allocator,\r
+ * were not already free and were allocated to the instance that is the source\r
+ * of the free request. */\r
+ for (i = resourceIndex, j = opInfo->resourceInfo->base; \r
+ i < (resourceIndex + opInfo->resourceInfo->range);\r
+ i++, j++)\r
+ {\r
+ if (root->resourceArrayBase[i].value != j)\r
+ {\r
+ /* A value in the range did not match. */\r
+ retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_IN_RANGE_DOES_NOT_EXIST;\r
+ resourcesValidated = FALSE;\r
+ break;\r
+ }\r
+ else if (strcmp(root->resourceArrayBase[i].allocatedTo, RM_NOT_ALLOCATED_STRING) == 0)\r
+ {\r
+ /* A value in the range is already free. */\r
+ retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_FREE;\r
+ resourcesValidated = FALSE;\r
+ break; \r
+ } \r
+ else if (strcmp(root->resourceArrayBase[i].allocatedTo, opInfo->srcInstName) != 0)\r
+ {\r
+ /* A value in the range was not allocated to the source of\r
+ * the free request */\r
+ retVal = RM_SERVICE_DENIED_RESOURCE_NOT_ALLOCATED_TO_INSTANCE_REQUESTING_THE_SERVICE;\r
+ resourcesValidated = FALSE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (resourcesValidated)\r
+ {\r
+ /* Free all resources from base to base+range */\r
+ for (i = resourceIndex; i < (resourceIndex + opInfo->resourceInfo->range); i++)\r
+ {\r
+ strcpy(root->resourceArrayBase[i].allocatedTo, RM_NOT_ALLOCATED_STRING);\r
+ }\r
+ retVal = RM_SERVICE_APPROVED_AND_COMPLETED;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_IN_RANGE_DOES_NOT_EXIST;\r
+ }\r
+\r
+ return(retVal);\r
+}\r
+\r
+/* Called when an allocate request is made but the base is unspecified. RM must preallocate\r
+ * resources which then must be checked against the RM policy for the instance. If the\r
+ * policy does not agree another resource(s) must be preallocated and tested against the \r
+ * policy */\r
+int32_t Rm_treePreAllocate(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
+{\r
+\r
+}\r
+\r
+int32_t Rm_treeAllocate(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
+{\r
+ \r
+}\r
+\r
+int32_t Rm_treeFree(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
+{\r
+\r
+}\r
+\r
+int32_t Rm_allocatorOperation(Rm_Inst *rmInst, Rm_AllocatorOpInfo *opInfo)\r
+{\r
+ Rm_Allocator *allocator = NULL;\r
+ int32_t retVal;\r
+ void *key;\r
+\r
+ /* Lock access to the RM instance's transaction queue */\r
+ key = Rm_osalMtCsEnter();\r
+\r
+ /* Get the specified resource's allocator */\r
+ allocator = Rm_allocatorFind(rmInst, opInfo->resourceInfo->name);\r
+\r
+ if (allocator)\r
+ {\r
+ /* Call the allocator's type-based allocation function */\r
+ if(allocator->type == Rm_allocatorType_INTEGER)\r
+ {\r
+ if (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE)\r
+ {\r
+ retVal = Rm_integerPreAllocateUnspecified(allocator, opInfo);\r
+ } \r
+ else if (opInfo->operation == Rm_allocatorOp_ALLOCATE)\r
+ {\r
+ retVal = Rm_integerAllocate(allocator, opInfo);\r
+ }\r
+ else if (opInfo->operation == Rm_allocatorOp_FREE)\r
+ {\r
+ retVal = Rm_integerFree(allocator, opInfo);\r
+ }\r
+ }\r
+ else if (allocator->type == Rm_allocatorType_TREE)\r
+ {\r
+ if (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE)\r
+ {\r
+ retVal = Rm_treePreAllocateUnspecified(allocator, opInfo);\r
+ } \r
+ else if (opInfo->operation == Rm_allocatorOp_ALLOCATE)\r
+ {\r
+ retVal = Rm_treeAllocate(allocator, opInfo);\r
+ }\r
+ else if (opInfo->operation == Rm_allocatorOp_FREE)\r
+ {\r
+ retVal = Rm_treeFree(allocator, opInfo);\r
+ } \r
+ } \r
+ }\r
+ else\r
+ {\r
+ /* Allocator could not be found for resource */\r
+ retVal = RM_SERVICE_DENIED_RESOURCE_DOES_NOT_EXIST;\r
+ }\r
+\r
+ Rm_osalMtCsExit(key);\r
+ return(retVal);\r
+}\r
+\r
+void Rm_allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
+{\r
+ if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
+ {\r
+#if 0 \r
+ if (resourceBase is unspecified)\r
+ {\r
+ while (policy does not approve)\r
+ {\r
+ Rm_policy check get allowed base as starting point for prealloc\r
+ preallocate resource based on the range and alignment\r
+ Rm_policy...check\r
+ }\r
}\r
else\r
{\r
- /* Resource allocation request originated locally on the active\r
- * instance. Send the response via the service responder. */ \r
- Rm_serviceResponder(rmInst, transaction); \r
+ /* Check local policy to see if the request can be satisfied with the\r
+ * resources stored locally */\r
+ Rm_policy...API()\r
+\r
+ if (policy check approves the resource)\r
+ {\r
+ /* call the allocator to allocate the resource */\r
+ if (allocator returns resource)\r
+ {\r
+ /* Populate the transaction with the allocated resources and the result */\r
+ transaction->state = approve reason;\r
+ return ...\r
+ }\r
+ else\r
+ {\r
+ /* allocator ran out of resources, need to contact Server for more\r
+ * resources */\r
+ Rm_resourcePoolModRequest(...);\r
+ }\r
+ }\r
+ else if (policy check denies resource)\r
+ {\r
+ /* Policy check denied resource. */\r
+ transaction->state= deny reason;\r
+ return ...\r
+ }\r
+ else if (policy check says forward to Server for validation)\r
+ {\r
+ /* Forward the transaction to the Server */\r
+ Rm_transactionForwarder(rmInst, transaction);\r
+ }\r
+ }\r
+#endif \r
+ }\r
+ else if (rmInst->instType == Rm_instType_SERVER)\r
+ {\r
+#if 0 \r
+ if (resourceBase is unspecified)\r
+ {\r
+ while (policy does not approve)\r
+ {\r
+ Rm_policy check get allowed base as starting point for prealloc\r
+ preallocate resource based on the range and alignment\r
+ Rm_policy...check\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* Check global policy to see if resource can be allocated. return result\r
+ * no matter what */\r
+ Rm_policy...API()\r
+\r
+ if (policy approves)\r
+ {\r
+ /* call allocator to allocate resource */\r
+ }\r
+\r
+ transaction->state = approve or deny reason;\r
+ transaction->resourceInfo.base = ...;\r
+ transaction->resourceInfo.range = ...;\r
+\r
+ /* If source instance name does not match the current instance\r
+ * name the allocation request came from a Client. The result\r
+ * must be sent back to the Client */\r
+ if (strcmp(transaction->sourceInstName, rmInst->name))\r
+ {\r
+ /* Names don't match. Send the transaction back to the Client */\r
+ Rm_transactionResponder(rmInst, transaction);\r
+ }\r
+ else\r
+ {\r
+ /* Resource allocation request originated locally on the active\r
+ * instance. Send the response via the service responder. */ \r
+ Rm_serviceResponder(rmInst, transaction); \r
+ }\r
}\r
#endif \r
} \r
{\r
/* Create a new NameServer object with the request transaction information.\r
* Transaction will contain the state result of the NameServer addition. */\r
- Rm_nsAddObject(rmInst, transaction);\r
+ if (Rm_nsAddObject(rmInst, transaction->resourceInfo.nsName,\r
+ transaction->resourceInfo.base) == RM_NS_ACTION_APPROVED)\r
+ {\r
+ transaction->state = RM_SERVICE_APPROVED_AND_COMPLETED;\r
+ }\r
+ else\r
+ {\r
+ /* TEMP: UPDATE THIS STATE VALUE */\r
+ transaction->state = RM_SERVICE_DENIED_BEGIN;\r
+ }\r
}\r
else\r
{\r
/* Delete an existing NameServer object with the request transaction information\r
* Transaction will contain the state result of the NameServer addition. */\r
- Rm_nsDeleteObject(rmInst, transaction);\r
+ if (Rm_nsDeleteObject(rmInst, transaction->resourceInfo.nsName) == \r
+ RM_NS_ACTION_APPROVED)\r
+ {\r
+ transaction->state = RM_SERVICE_APPROVED_AND_COMPLETED;\r
+ }\r
+ else\r
+ {\r
+ /* TEMP: UPDATE THIS STATE VALUE */\r
+ transaction->state = RM_SERVICE_DENIED_BEGIN;\r
+ }\r
}\r
\r
/* If source instance name does not match the local instance\r
}\r
}\r
\r
-void reverse_properties(void *fdt, int32_t offset)\r
+int32_t Rm_initializeAllocators(Rm_Inst *rmInst, void *globalResourceDtb)\r
{\r
- int32_t len;\r
- const char *name;\r
- char *resourceName, *allocator;\r
- const void *data;\r
- Rm_ResourceRange *range = NULL;\r
- Rm_ResourceRange *startOfRange = NULL;\r
- Rm_NsAssignment *nsAssignment = NULL;\r
- Rm_NsAssignment *startOfNsAssignment = NULL;\r
- Rm_ResourcePropType propType;\r
-\r
- data = fdt_getprop_by_offset(fdt, offset, &name, &len);\r
- if (!data)\r
- Rm_osalLog("Error traverse_properties fdt_getprop_by_offset: %d\n", len);\r
- else\r
- {\r
- Rm_osalLog("Property name: %s with length: %d offset: %d and address: %x\n", name, len, offset, data);\r
+ int32_t nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;\r
+ int32_t startDepth = RM_DTB_UTIL_STARTING_DEPTH;\r
+ int32_t result = RM_DTB_UTIL_RESULT_OKAY;\r
\r
- propType = Rm_resourceGetPropertyType(name);\r
- if (propType == Rm_resourcePropType_RESOURCE_NAME)\r
- {\r
- Rm_osalLog("Resource Name: %s\n", resourceName = Rm_resourceExtractResourceName(data, len));\r
- Rm_resourceFreeResourceName(resourceName);\r
- }\r
- else if (propType == Rm_resourcePropType_RESOURCE_RANGE)\r
- {\r
- startOfRange = range = Rm_resourceExtractResourceRange(data, len);\r
- while (range != NULL)\r
- {\r
- Rm_osalLog("Resource base: %d and length: %d\n", range->base, range->length);\r
- range = (Rm_ResourceRange *) range->nextRange;\r
- }\r
- Rm_resourceFreeResourceRange(startOfRange);\r
- }\r
- else if (propType == Rm_resourcePropType_NSASSIGNMENT)\r
- {\r
- startOfNsAssignment = nsAssignment = Rm_resourceExtractNsAssignment(data, len);\r
- while (nsAssignment != NULL)\r
- {\r
- Rm_osalLog("NameServer assignment name: %s and value: %d\n", nsAssignment->nsName, nsAssignment->resourceValue);\r
- nsAssignment = (Rm_NsAssignment *) nsAssignment->nextNsAssignment;\r
- }\r
- Rm_resourceFreeNsAssignmentList(startOfNsAssignment);\r
- } \r
- else if (propType == Rm_resourcePropType_RESOURCE_ALLOCATOR)\r
- {\r
- Rm_osalLog("Resource Allocator: %s\n", allocator = Rm_resourceExtractResourceAllocator(data, len));\r
- Rm_resourceFreeResourceAllocator(allocator);\r
- }\r
- }\r
+ /* Recursively parse the Global Resource List, creating an allocator for\r
+ * each resource as specified in the node */\r
+ result = Rm_parseResourceNode(rmInst, globalResourceDtb, nodeOffset, startDepth);\r
\r
- offset = fdt_next_property_offset(fdt, offset);\r
- if (offset >= 0)\r
- reverse_properties(fdt, offset);\r
- else if (offset != -FDT_ERR_NOTFOUND)\r
- Rm_osalLog("Error traverse_properties fdt_next_property_offset: %d\n", offset);\r
+ return(result);\r
}\r
-\r
-void reverse_node(void *fdt, int32_t nodeOffset);\r
-\r
-void reverse_children(void *fdt, int32_t offset)\r
+ \r
+int32_t Rm_reserveLinuxResources(Rm_Inst *rmInst, void *linuxResourceDtb)\r
{\r
- const char *nodeName;\r
- int32_t error;\r
- int32_t nextOffset = offset;\r
- int32_t depth = 1;\r
-\r
- do {\r
- char path[256];\r
-\r
- nodeName = fdt_get_name(fdt, nextOffset, NULL);\r
- error = fdt_get_path(fdt, nextOffset, path, sizeof(path));\r
- if (error)\r
- Rm_osalLog("Error reverse_children fdt_get_path: %d\n", error);\r
- else\r
- Rm_osalLog("Node path: %s with name %s\n", path, nodeName);\r
-\r
+ return(0);\r
\r
- nextOffset = fdt_next_node(fdt, nextOffset, &depth);\r
- if (error < 0)\r
- Rm_osalLog("Error reverse_children fdt_next_node: %d\n", offset);\r
- else\r
- Rm_osalLog("Next node offset: %d with depth: %d\n", nextOffset, depth);\r
- } while ((depth >= 0) && (depth != 1));\r
-\r
- if (depth == 1)\r
- reverse_children(fdt, nextOffset);\r
-\r
- reverse_node(fdt, offset);\r
-}\r
-\r
-void reverse_node(void *fdt, int32_t nodeOffset)\r
-{\r
- const char *nodeName = fdt_get_name(fdt, nodeOffset, NULL);\r
- char path[256];\r
- int32_t error;\r
- int32_t offset;\r
- int32_t depth = 0;\r
-\r
- error = fdt_get_path(fdt, nodeOffset, path, sizeof(path));\r
- if (error)\r
- Rm_osalLog("Error traverse_node fdt_get_path: %d\n", error);\r
- else\r
- Rm_osalLog("Node path: %s with name %s\n", path, nodeName);\r
-\r
- /* Get the properties for the node if any exist */\r
- offset = fdt_first_property_offset(fdt, nodeOffset);\r
- if (offset >= 0)\r
- reverse_properties(fdt, offset);\r
- else if (offset != -FDT_ERR_NOTFOUND)\r
- Rm_osalLog("Error traverse_node fdt_first_property_offset: %d\n", offset);\r
-\r
- /* Get the next node */\r
- offset = fdt_next_node(fdt, nodeOffset, &depth);\r
- if (offset >= 0)\r
- {\r
- Rm_osalLog("Next node offset: %d with depth: %d\n", offset, depth);\r
- }\r
- else if (offset != -FDT_ERR_NOTFOUND)\r
- Rm_osalLog("Error traverse_node fdt_next_node: %d\n", offset);\r
-\r
- if (depth == 1)\r
- reverse_children(fdt, offset);\r
}\r
\r
-void traverseFdt (void *fdt)\r
-{\r
- int32_t nodeOffset = 0; /* offset starts at 0, beginning of tree */\r
-\r
- reverse_node(fdt, nodeOffset);\r
-}\r
-\r
-\r
/**********************************************************************\r
********************** Application visible APIs **********************\r
**********************************************************************/\r
Rm_Handle Rm_init(Rm_InitCfg *initCfg)\r
{\r
Rm_Inst *rmInst;\r
- void *fdt = initCfg->globalResourceList; \r
+ void *globalResourceDtb = NULL;\r
+ void *linuxResourceDtb = NULL;\r
\r
/* Instance creation checks. Add one to strlen calculation for null character */\r
if ((strlen(initCfg->instName) + 1) > RM_INSTANCE_NAME_MAX_CHARS)\r
strcpy (&rmInst->name[0], initCfg->instName);\r
rmInst->instType = initCfg->instType;\r
rmInst->registeredWithDelegateOrServer = false;\r
+ rmInst->policyDtb = NULL;\r
\r
/* Initialize the transport routing map linked list pointer to NULL. The linked list\r
* nodes will be created when the application registers transports */\r
rmInst->routeMap = NULL;\r
\r
+ /* Initialize the allocators linked list pointer to NULL. The linked list nodes will\r
+ * be created on the Server instance when the application reads in the resource list.\r
+ * Nodes will also be created on Client Delegates when blocks of resources are requested\r
+ * for allocation to clients. */\r
+ rmInst->allocators = NULL;\r
+\r
/* Initialize the transaction queue elements. */\r
rmInst->transactionSeqNum = Rm_transactionInitSequenceNum();\r
rmInst->transactionQueue= NULL;\r
/* RM Server specific actions */\r
if (rmInst->instType == Rm_instType_SERVER)\r
{\r
- /* Open the ResourceList file */\r
- fdt_open_into(initCfg->globalResourceList, fdt, fdt_totalsize(initCfg->globalResourceList));\r
+ /* Open the ResourceList file and provide it to the resource initializer. */\r
+ if (initCfg->globalResourceList)\r
+ {\r
+ globalResourceDtb = initCfg->globalResourceList;\r
+ fdt_open_into(globalResourceDtb, globalResourceDtb, fdt_totalsize(globalResourceDtb)); \r
+ Rm_initializeAllocators(rmInst, globalResourceDtb);\r
+ }\r
\r
- /* TEST: Try to parse the entire fdt */\r
- traverseFdt(fdt);\r
+ /* Parse the Linux DTB for the resources reserved by the Linux kernel. These resources\r
+ * will be marked as used in the resource allocators. */\r
+ if (initCfg->linuxDtb)\r
+ {\r
+ linuxResourceDtb = initCfg->linuxDtb;\r
+ fdt_open_into(linuxResourceDtb, linuxResourceDtb, fdt_totalsize(linuxResourceDtb)); \r
+ Rm_reserveLinuxResources(rmInst, linuxResourceDtb);\r
+ }\r
}\r
\r
/* Instance startup policies are only used for Servers and Client Delegates */\r
if (rmInst->instType != Rm_instType_CLIENT)\r
{\r
- rmInst->instPolicy = initCfg->startupPolicy;\r
+ /* Open the instance's policy and store it */\r
+ if (initCfg->startupPolicy)\r
+ {\r
+ rmInst->policyDtb = initCfg->startupPolicy;\r
+ fdt_open_into(rmInst->policyDtb, rmInst->policyDtb, fdt_totalsize(rmInst->policyDtb)); \r
+ }\r
\r
/* Store policy via policy APIs ... */\r
}\r