]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/rm-lld.git/commitdiff
Completed routines for automatically reserving Linux resources
authorJustin Sobota <jsobota@ti.com>
Fri, 14 Dec 2012 00:02:52 +0000 (19:02 -0500)
committerJustin Sobota <jsobota@ti.com>
Fri, 14 Dec 2012 00:02:52 +0000 (19:02 -0500)
include/rm_dtb_utilloc.h
include/rm_loc.h
src/rm.c
src/rm_dtb_util.c
test/rm_test.c

index 3b49c0de4abaabaf9116828d09605dfeb37ea127..7405b782458914d56b3f2cfeeede2495ff097b91 100644 (file)
@@ -93,10 +93,10 @@ typedef enum {
 } Rm_ResourcePropType;
 
 typedef struct {
-    char *pathList;
+    const char *pathList;
     uint32_t pathListLenBytes;
-    uint32_t base;
-    uint32_t length;
+    uint32_t baseOffset;
+    uint32_t lengthOffset;
     void *nextLinuxAlias;
 } Rm_LinuxAlias;
 
@@ -155,6 +155,18 @@ void Rm_policyFreeAllocationSizesPropList(Rm_AllocationSize *allocationSizeList)
 Rm_AssignedNsNames *Rm_policyExtractAssignedNsNames(const void *dtbDataPtr, int32_t dtbDataLen);
 void Rm_policyFreeAssignmentNsNamesList(Rm_AssignedNsNames *assignedNsNamesList);
 
+/**********************************************************************
+ ****************Linux DTB Parsing Defines and Functions***************
+ **********************************************************************/
+
+typedef struct {
+    uint32_t value;
+    void *nextValue;
+} Rm_LinuxValueRange;
+
+Rm_LinuxValueRange *Rm_linuxExtractValues(const void *dtbDataPtr, int32_t dtbDataLen);
+void Rm_linuxFreeValues(Rm_LinuxValueRange *valueList);
+
 #ifdef __cplusplus
 }
 #endif
index 4b5f4ebc13a634ad219a839ecf91081a2e266a59..322c7e244c4208369c61ba48421e55f9002b214b 100644 (file)
@@ -56,6 +56,9 @@ extern "C" {
  *  resource is allocated the allocatedTo field will be populated with the RM instance
  *  name it was allocated to. */
 #define RM_NOT_ALLOCATED_STRING "\0"
+/** String stored for resource elements that are reserved by the Linux kernel.  These
+ *  resources will be in use for the lifetime of the system */
+#define RM_ALLOCATED_TO_LINUX "Linux-Kernel"
 
 /** Maximum size of a transmittable RM policy in bytes */
 #define RM_MAX_POLICY_SIZE_BYTES (64)  // Placeholder: This will change 
index 5096e1d485eccb63f4819f9c3b3f2a23b3cdc93c..32be8a8f04fc7508708753bcd4c0267f919304d7 100644 (file)
--- a/src/rm.c
+++ b/src/rm.c
@@ -545,6 +545,228 @@ int32_t Rm_createIntegerAllocator(Rm_Inst *rmInst, const char *resourceName, Rm_
     return(0);  /* TODO: FIX THIS RETURN */\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
+    Rm_IntegerAllocatorRootEntry *root = allocator->allocatorRootEntry;\r
+    Rm_IntegerEntry *resourceArray = root->resourceArrayBase;\r
+    uint16_t index, i;\r
+    bool resourcesValidated;\r
+    int32_t retVal = RM_SERVICE_PROCESSING;\r
+\r
+    /* Find the specified resource base within the allocator */\r
+    for (index = 0; index < root->numResourceElements; index++)\r
+    {\r
+        if (resourceArray[index].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+length does not exceed the number of entries in the allocator */\r
+    if ((index + opInfo->resourceInfo->length) <= root->numResourceElements)\r
+    {\r
+        /* Search for a contiguous block of unallocated resources of length "length"\r
+         * and with the alignment specified */\r
+        while ((index + opInfo->resourceInfo->length) <= root->numResourceElements)\r
+        {\r
+            resourcesValidated = FALSE;            \r
+            \r
+            /* Does the resource base value satisfy the alignment? */\r
+            if ((resourceArray[index].value % opInfo->resourceInfo->alignment) == 0)\r
+            {\r
+                /* Check to see all the resource values in the requested range are free */\r
+                resourcesValidated = TRUE;\r
+                for (i = index; i < opInfo->resourceInfo->length; i++)\r
+                {\r
+                    if (strcmp(resourceArray[i].allocatedTo, RM_NOT_ALLOCATED_STRING) != 0)\r
+                    {\r
+                        /* A resource within the range was already allocated.  Update the\r
+                         * index to the resource after the allocated resource and continue \r
+                         * looking. */\r
+                        index = i + 1;\r
+                        resourcesValidated = FALSE;\r
+                        /* Break out of the for loop */\r
+                        break;\r
+                    }\r
+                }\r
+\r
+                if (resourcesValidated)\r
+                {\r
+                    /* Found a set of resources that satisfies the request requirements.  Return\r
+                     * the results to be tested against the policy.  If the policy approves the\r
+                     * resources will be allocated via the Rm_integerAllocate API. */\r
+                    opInfo->resourceInfo->base = resourceArray[index].value;\r
+                    /* Break out of the while loop */\r
+                    break;\r
+                }\r
+            }\r
+            else\r
+            {\r
+                /* Jump to the next resource value that satisfies the alignment */\r
+                for (; index < root->numResourceElements; index++)\r
+                {\r
+                    if ((resourceArray[index].value % opInfo->resourceInfo->alignment) == 0)\r
+                    {\r
+                        /* Found the next resource value that satisfies the alignment */\r
+                        break;\r
+                    }\r
+                }\r
+            }\r
+        }\r
+\r
+        if (!resourcesValidated)\r
+        {\r
+            retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
+        }\r
+    }\r
+    else\r
+    {\r
+        retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
+    }\r
+\r
+    return(retVal);     \r
+}\r
+\r
+/* Assumes resource range for allocation has already been approved by the policy */\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+length does not exceed the number of entries in the allocator */\r
+    if ((resourceIndex + opInfo->resourceInfo->length) <= root->numResourceElements)\r
+    {\r
+        /* Verify all resource values from base to base+length 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->length);\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_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+length */\r
+            for (i = resourceIndex; i < (resourceIndex + opInfo->resourceInfo->length); 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_RANGE_DOES_NOT_EXIST;\r
+    }\r
+\r
+    return(retVal); \r
+}\r
+\r
+/* Assumes resource range for free has already been approved by the policy */\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+length does not exceed the number of entries in the allocator */\r
+    if ((resourceIndex + opInfo->resourceInfo->length) <= root->numResourceElements)\r
+    {\r
+        /* Verify all resource values from base to base+length 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->length);\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_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+length */\r
+            for (i = resourceIndex; i < (resourceIndex + opInfo->resourceInfo->length); 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_RANGE_DOES_NOT_EXIST;\r
+    }\r
+\r
+    return(retVal);\r
+}\r
+\r
 int32_t Rm_createTreeAllocator(Rm_Inst *rmInst, const char *resourceName, Rm_ResourceRange *range)\r
 {\r
     Rm_Allocator *allocator = NULL;\r
@@ -595,1332 +817,1289 @@ int32_t Rm_createTreeAllocator(Rm_Inst *rmInst, const char *resourceName, Rm_Res
     return(0);   /* TODO: FIX THIS RETURN */\r
 }\r
 \r
-int32_t Rm_createAndInitAllocator(Rm_Inst *rmInst, const char *resourceName, \r
-                                  Rm_ResourceProperties *resourceProperties, void *linuxDtb)\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_treePreAllocate(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\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
-    Rm_LinuxAlias *linuxAlias = NULL;\r
-    Rm_LinuxAlias *linuxAliasBasePtr = NULL;\r
-    int32_t retVal = RM_DTB_UTIL_RESULT_OKAY;\r
-\r
-    /* TODO: NEED CHECKS FOR VALIDITY OF ALL THE resourceProperties FIELDS */\r
+    Rm_ResourceTreeNode findNode;\r
+    Rm_ResourceTreeNode *matchingNode = NULL;\r
+    uint32_t policyRangeEnd = opInfo->policyBase + opInfo->policyLength - 1;\r
+    uint32_t index;\r
+    bool resourceFound = FALSE;\r
+    int32_t retVal = RM_SERVICE_PROCESSING;\r
 \r
-    /* Extract the resource properties from the DTB */\r
-    allocatorType = Rm_resourceExtractAllocator(resourceProperties->allocatorData, \r
-                                                resourceProperties->allocatorLen);\r
-    range = rangeBasePtr = Rm_resourceExtractRange(resourceProperties->rangeData, \r
-                                                   resourceProperties->rangeLen);\r
+    /* Find the tree node that contains the first value in the specified policy range. */\r
+    findNode.base = opInfo->policyBase;\r
+    findNode.length = 1;\r
+    matchingNode = RB_FIND(_Rm_ResourceTree, allocator->allocatorRootEntry, &findNode);\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
-    /* Reserve the resources taken by the Linux kernel specified in the Linux DTB */\r
-    linuxAlias = linuxAliasBasePtr = Rm_resourceExtractLinuxAlias(resourceProperties->linuxAliasData,\r
-                                                                  resourceProperties->linuxAliasLen);\r
-    \r
-    if (retVal >= RM_DTB_UTIL_RESULT_OKAY)\r
+    if (matchingNode != NULL)\r
     {\r
-        /* Create entries in the NameServer if any NameServer assignments were specified */\r
-        if (resourceProperties->nsAssignData && resourceProperties->nsAssignLen)\r
+        /* Begin searching for an available range of resources starting from the\r
+         * matching node */\r
+        for (index = matchingNode->base; index <= policyRangeEnd;)\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
+            /* Is the matchingNode free? */\r
+            if (strcmp(matchingNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0)\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_resourceFreeAllocator(allocatorType);\r
-    Rm_resourceFreeRange(rangeBasePtr);\r
-    Rm_resourceFreeLinuxAlias(linuxAliasBasePtr);\r
-\r
-    return(retVal);\r
-}\r
+                uint32_t matchEnd = matchingNode->base + matchingNode->length - 1;\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
+                /* Move index to the first resource satisfying the alignment property */\r
+                if ((index % opInfo->policyAlignment) != 0)\r
+                {\r
+                    index += (opInfo->policyAlignment - (index % opInfo->policyAlignment));\r
+                }\r
+                \r
+                /* Move through the node's resource range looking for a contiguous set of resources\r
+                 * that satisfy the request. */\r
+                while ((index <= matchEnd) && (index <= policyRangeEnd))\r
+                {\r
+                    if (((index + opInfo->resourceInfo->length - 1) <= matchEnd) &&\r
+                        ((index + opInfo->resourceInfo->length - 1) <= policyRangeEnd))\r
+                    {\r
+                        /* Found a resource range in the node that satisfies the requirements */\r
+                        opInfo->resourceInfo->base = index;\r
+                        resourceFound = TRUE;\r
+                        break;\r
+                    }\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
-                propertyInfo->allocatorData = propertyData;\r
-                propertyInfo->allocatorLen = propertyLen;\r
-            }\r
-        }\r
-        else if (propertyType == Rm_resourcePropType_RESOURCE_RANGE)\r
-        {\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
+                    /* Move index to the next resource value that satisfies the alignment property */\r
+                    index += (opInfo->policyAlignment - (index % opInfo->policyAlignment));\r
+                }\r
             }\r
-        }\r
-        else if (propertyType == Rm_resourcePropType_NSASSIGNMENT)\r
-        {\r
-            if (propertyInfo->nsAssignData || propertyInfo->nsAssignLen)\r
+            \r
+            if (!resourceFound)\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
+                /* Move to the next tree node */\r
+                matchingNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+                if (matchingNode == NULL)\r
+                {\r
+                    /* Reached end of tree.  Resource range does not exist.  Leave the search\r
+                     * loop */\r
+                    break;\r
+                }\r
+                else\r
+                {\r
+                    index = matchingNode->base;\r
+                }\r
             }\r
             else\r
             {\r
-                propertyInfo->nsAssignData = propertyData;\r
-                propertyInfo->nsAssignLen = propertyLen;\r
+                /* Found a resource range that satisfies the request properties.  Break out of the\r
+                 * search loop */\r
+                break;\r
             }\r
         }\r
-        else if (propertyType == Rm_resourcePropType_RESOURCE_LINUX_ALIAS)\r
-        {\r
-            if (propertyInfo->linuxAliasData || propertyInfo->linuxAliasLen)\r
-            {\r
-                /* The linuxAlias 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 = -28; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
-            }\r
-            else\r
-            {\r
-                propertyInfo->linuxAliasData = propertyData;\r
-                propertyInfo->linuxAliasLen = propertyLen;\r
-            }\r
-        }        \r
-        else\r
+\r
+        if (!resourceFound)\r
         {\r
-            retVal = -20; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
+            retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_ALLOCATED;\r
         }\r
     }\r
     else\r
     {\r
-        retVal = -16; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
+        retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
     }\r
 \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
-            /* Error was returned by LIBFDT when parsing the properties */\r
-            retVal = offset;\r
-        }\r
-    }\r
-    \r
-    return (retVal);\r
+    return(retVal); \r
 }\r
 \r
-int32_t Rm_parseResourceNode(Rm_Inst *rmInst, void *globalResourceDtb, int32_t nodeOffset, int32_t depth,\r
-                             void *linuxDtb)\r
+/* Assume the policy has already approved of the allocation */\r
+int32_t Rm_treeAllocate(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\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
+    Rm_ResourceTreeNode findNode;\r
+    Rm_ResourceTreeNode *matchingNode = NULL;\r
+    Rm_ResourceTreeNode *leftNode = NULL;\r
+    Rm_ResourceTreeNode *rightNode = NULL;\r
+    uint32_t findEnd, matchingEnd;\r
+    int32_t retVal;\r
 \r
-    /* Initialize the resource properties structure */\r
-    memset((void *)&resourceProperties, 0, sizeof(Rm_ResourceProperties));\r
+    /* Find the tree node that contains the specified resource range */\r
+    findNode.base = opInfo->resourceInfo->base;\r
+    findNode.length = opInfo->resourceInfo->length;\r
+    matchingNode = RB_FIND(_Rm_ResourceTree, allocator->allocatorRootEntry, &findNode);\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, linuxDtb);\r
-       }\r
-        else if (offset != -FDT_ERR_NOTFOUND)\r
-        {\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
+    if (matchingNode != NULL)\r
     {\r
-        error = Rm_parseResourceNode(rmInst, globalResourceDtb, offset, depth, linuxDtb);\r
-        if (error < -FDT_ERR_NOTFOUND)\r
+        findEnd = findNode.base + findNode.length - 1;\r
+        matchingEnd = matchingNode->base + matchingNode->length - 1;\r
+        \r
+        /* Does the request range fit within the matching nodes entire range? */\r
+        if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd))\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
-    Rm_IntegerAllocatorRootEntry *root = allocator->allocatorRootEntry;\r
-    Rm_IntegerEntry *resourceArray = root->resourceArrayBase;\r
-    uint16_t index, i;\r
-    bool resourcesValidated;\r
-    int32_t retVal = RM_SERVICE_PROCESSING;\r
+            /* Handle requested resource range that is isolated to a single node\r
+             *\r
+             *\r
+             * base0                                  base0+length0-1\r
+             *   |<---------------length0------------------->|  => existing node\r
+             *         |<---------length1---------->|  => requested resources\r
+             *       base1                   base1+length1-1\r
+             */             \r
+            if (strcmp(matchingNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0)\r
+            {\r
+                /* Resources are available - split up the node into potentially\r
+                 * three new nodes:\r
+                 * left node - free resources to left of newly allocated resources\r
+                 * middle node - newly allocated resources that satisfy the request\r
+                 * right node - free resources to the right of newly allocated resources\r
+                 *\r
+                 * There also may be combine possibilities to the left and right of the\r
+                 * matching node.  Need to extract those as well to check */\r
+                leftNode = RB_PREV(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+                rightNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
 \r
-    /* Find the specified resource base within the allocator */\r
-    for (index = 0; index < root->numResourceElements; index++)\r
-    {\r
-        if (resourceArray[index].value == opInfo->resourceInfo->base)\r
-        {\r
-            /* Found the resource base in the allocator.  Break from the loop */\r
-            break;\r
-        }\r
-    } \r
+                /* Remove the matching node from the tree and the nodes to the left and\r
+                 * right of the matching node.  Removing from tree will not\r
+                 * wipe any of the base+length data in the node.  Can reuse since they won't\r
+                 * be freed */\r
+                RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+                if (leftNode)\r
+                {\r
+                    RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+                }\r
+                if (rightNode)\r
+                {\r
+                    RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+                }\r
 \r
-    /* Only execute the allocate operation if the resource base was found in the allocator\r
-     * and the base+length does not exceed the number of entries in the allocator */\r
-    if ((index + opInfo->resourceInfo->length) <= root->numResourceElements)\r
-    {\r
-        /* Search for a contiguous block of unallocated resources of length "length"\r
-         * and with the alignment specified */\r
-        while ((index + opInfo->resourceInfo->length) <= root->numResourceElements)\r
-        {\r
-            resourcesValidated = FALSE;            \r
-            \r
-            /* Does the resource base value satisfy the alignment? */\r
-            if ((resourceArray[index].value % opInfo->resourceInfo->alignment) == 0)\r
-            {\r
-                /* Check to see all the resource values in the requested range are free */\r
-                resourcesValidated = TRUE;\r
-                for (i = index; i < opInfo->resourceInfo->length; i++)\r
+                /* Create the left node if needed.  If the bases are equal the matchingNode can\r
+                 * be reused as the left bound of the range. */\r
+                if (findNode.base > matchingNode->base)\r
                 {\r
-                    if (strcmp(resourceArray[i].allocatedTo, RM_NOT_ALLOCATED_STRING) != 0)\r
+                    /* Can the left node be combined with the node to the left of the matching\r
+                     * node */\r
+                    if (leftNode && (strcmp(leftNode->allocatedTo, opInfo->srcInstName) == 0))\r
                     {\r
-                        /* A resource within the range was already allocated.  Update the\r
-                         * index to the resource after the allocated resource and continue \r
-                         * looking. */\r
-                        index = i + 1;\r
-                        resourcesValidated = FALSE;\r
-                        /* Break out of the for loop */\r
-                        break;\r
+                        /* Combine the left node and what's leftover on the left side of the \r
+                         * matchingNode range after the allocation */\r
+                        leftNode->length += (findNode.base - matchingNode->base);\r
+                    }\r
+                    else\r
+                    {\r
+                        /* Reinsert left node and create a new node to left of range to be allocated */\r
+                        if (leftNode)\r
+                        {\r
+                            RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+                        }\r
+                        \r
+                        /* New left node attributes:\r
+                         * base: base of the matching node\r
+                         * length: base of requested resources - base of matching node */\r
+                        leftNode = Rm_newResourceTreeNode(matchingNode->base, findNode.base - matchingNode->base,\r
+                                                          RM_NOT_ALLOCATED_STRING);\r
                     }\r
-                }\r
 \r
-                if (resourcesValidated)\r
-                {\r
-                    /* Found a set of resources that satisfies the request requirements.  Return\r
-                     * the results to be tested against the policy.  If the policy approves the\r
-                     * resources will be allocated via the Rm_integerAllocate API. */\r
-                    opInfo->resourceInfo->base = resourceArray[index].value;\r
-                    /* Break out of the while loop */\r
-                    break;\r
                 }\r
-            }\r
-            else\r
-            {\r
-                /* Jump to the next resource value that satisfies the alignment */\r
-                for (; index < root->numResourceElements; index++)\r
+\r
+                /* Create the right node if needed.  If the end ranges are equal the matchingNode\r
+                 * can be reused as the right bound of the range */\r
+                if (findEnd < matchingEnd)\r
                 {\r
-                    if ((resourceArray[index].value % opInfo->resourceInfo->alignment) == 0)\r
+                    /* Can the right node be combined with the node to the right of the matching\r
+                     * node */\r
+                    if (rightNode && (strcmp(rightNode->allocatedTo, opInfo->srcInstName) == 0))\r
                     {\r
-                        /* Found the next resource value that satisfies the alignment */\r
-                        break;\r
+                        /* Combine the right node and what's leftover on the right side of the \r
+                         * matchingNode range after the allocation */\r
+                        rightNode->base = findNode.base + findNode.length;\r
+                        rightNode->length += (matchingEnd - findEnd);\r
+                    }\r
+                    else\r
+                    {\r
+                        /* Reinsert right node and create a new node to right of range to be allocated */\r
+                        if (rightNode)\r
+                        {\r
+                            RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+                        }\r
+                                            \r
+                        /* New right node attributes:\r
+                         * base: base of the requested resources + length of requested resources\r
+                         * length: right bound of matching node - right bound of request resources */\r
+                        rightNode = Rm_newResourceTreeNode(findNode.base + findNode.length,\r
+                                                           matchingEnd - findEnd, RM_NOT_ALLOCATED_STRING);\r
                     }\r
                 }\r
-            }\r
-        }\r
-\r
-        if (!resourcesValidated)\r
-        {\r
-            retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
-        }\r
-    }\r
-    else\r
-    {\r
-        retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
-    }\r
 \r
-    return(retVal);     \r
-}\r
-\r
-/* Assumes resource range for allocation has already been approved by the policy */\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
+                /* Reinsert the left node into the tree if it was modified or created. */\r
+                if (leftNode)\r
+                {\r
+                    RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+                }\r
+                /* Reinsert the right node into the tree if it was modified or created. */\r
+                if (rightNode)\r
+                {\r
+                    RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+                }\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
+                /* Base and length of matching node becomes the base and length of the requested resources */\r
+                matchingNode->base = findNode.base;                                    \r
+                matchingNode->length = findNode.length;\r
+                /* Reserve the resources and insert them into the tree */\r
+                strcpy(matchingNode->allocatedTo, opInfo->srcInstName);\r
+                RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
 \r
-    /* Only execute the allocate operation if the resource base was found in the allocator\r
-     * and the base+length does not exceed the number of entries in the allocator */\r
-    if ((resourceIndex + opInfo->resourceInfo->length) <= root->numResourceElements)\r
-    {\r
-        /* Verify all resource values from base to base+length 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->length);\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_RANGE_DOES_NOT_EXIST;\r
-                resourcesValidated = FALSE;\r
-                break;\r
+                retVal = RM_SERVICE_APPROVED_AND_COMPLETED;\r
             }\r
-            else if (strcmp(root->resourceArrayBase[i].allocatedTo, RM_NOT_ALLOCATED_STRING) != 0)\r
+            else\r
             {\r
-                /* A value in the range is already allocated. */\r
+                /* A resource superset containing the requested range has\r
+                 * already been allocated. */\r
                 retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_ALLOCATED;\r
-                resourcesValidated = FALSE;\r
-                break;            \r
             }\r
         }\r
-\r
-        if (resourcesValidated)\r
+        else\r
         {\r
-            /* Allocate all resources from base to base+length */\r
-            for (i = resourceIndex; i < (resourceIndex + opInfo->resourceInfo->length); i++)\r
-            {\r
-                strcpy(root->resourceArrayBase[i].allocatedTo, opInfo->srcInstName);\r
-            }\r
-            retVal = RM_SERVICE_APPROVED_AND_COMPLETED;\r
+            /* Request ranges that span multiple nodes signify resources are\r
+             * not available because nodes are combined into larger contiguous ranges\r
+             * on resource free operations. */\r
+            retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_ALLOCATED;\r
         }\r
     }\r
     else\r
     {\r
+        /* The requested resources could not be found in the allocator */\r
         retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
     }\r
 \r
-    return(retVal); \r
+    return(retVal);        \r
 }\r
 \r
-/* Assumes resource range for free has already been approved by the policy */\r
-int32_t Rm_integerFree(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
+/* Assume policy has already approved of the free */\r
+int32_t Rm_treeFree(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
 {\r
-    Rm_IntegerAllocatorRootEntry *root = allocator->allocatorRootEntry;\r
-    uint16_t resourceIndex, i, j;\r
-    bool resourcesValidated = TRUE;\r
+    Rm_ResourceTreeNode findNode;\r
+    Rm_ResourceTreeNode *matchingNode = NULL;\r
+    Rm_ResourceTreeNode *leftNode = NULL;\r
+    Rm_ResourceTreeNode *rightNode = NULL;\r
+    bool combineLeft = FALSE;\r
+    bool combineRight = FALSE;\r
+    uint32_t findEnd, matchingEnd;\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
+    /* Find the tree node that contains the specified resource range */\r
+    findNode.base = opInfo->resourceInfo->base;\r
+    findNode.length = opInfo->resourceInfo->length;\r
+    matchingNode = RB_FIND(_Rm_ResourceTree, allocator->allocatorRootEntry, &findNode);\r
 \r
-    /* Only execute the free operation if the resource base was found in the allocator\r
-     * and the base+length does not exceed the number of entries in the allocator */\r
-    if ((resourceIndex + opInfo->resourceInfo->length) <= root->numResourceElements)\r
+    if (matchingNode != NULL)\r
     {\r
-        /* Verify all resource values from base to base+length 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->length);\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_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
+        findEnd = findNode.base + findNode.length - 1;\r
+        matchingEnd = matchingNode->base + matchingNode->length - 1;\r
+        \r
+        /* Does the free range fit within the matching nodes entire range?  It should\r
+         * either be the entire range or a subset set of the found range. (the latter\r
+         * satisfies the case where an entity allocated a contiguous block of resources\r
+         * then attempts to free a contiguous subset of the allocated block. */\r
+        if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd))\r
+        {            \r
+            if (strcmp(matchingNode->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
+                /* Resources can be freed */\r
 \r
-        if (resourcesValidated)\r
-        {\r
-            /* Free all resources from base to base+length */\r
-            for (i = resourceIndex; i < (resourceIndex + opInfo->resourceInfo->length); 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_RANGE_DOES_NOT_EXIST;\r
-    }\r
+                if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd))\r
+                {\r
+                    /* Case 1: free range equals allocated matched node exactly. Attempt to combine \r
+                     *         the range to be freed with the resource nodes to the left and\r
+                     *         right of the free range.\r
+                     *\r
+                     * |<--left node-->||<---matched node--->||<--right node-->|\r
+                     *                  |<---free request--->|\r
+                     */ \r
 \r
-    return(retVal);\r
-}\r
+                    leftNode = RB_PREV(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+                    rightNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\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_treePreAllocate(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
-{\r
-    Rm_ResourceTreeNode findNode;\r
-    Rm_ResourceTreeNode *matchingNode = NULL;\r
-    uint32_t policyRangeEnd = opInfo->policyBase + opInfo->policyLength - 1;\r
-    uint32_t index;\r
-    bool resourceFound = FALSE;\r
-    int32_t retVal = RM_SERVICE_PROCESSING;\r
+                    /* Remove the matching node from the tree and the nodes to the left and\r
+                     * right of the matching node.  Removing from tree will not\r
+                     * wipe any of the base+length data in the node.  Can reuse since they won't\r
+                     * be freed */\r
+                    RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+                    if (leftNode)\r
+                    {\r
+                        RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+                    }\r
+                    if (rightNode)\r
+                    {\r
+                        RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+                    }\r
 \r
-    /* Find the tree node that contains the first value in the specified policy range. */\r
-    findNode.base = opInfo->policyBase;\r
-    findNode.length = 1;\r
-    matchingNode = RB_FIND(_Rm_ResourceTree, allocator->allocatorRootEntry, &findNode);\r
+                    /* See if the left or right or both nodes can be combined with the matching\r
+                     * node that will be freed. */\r
+                    if (leftNode && (strcmp(leftNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0))\r
+                    {\r
+                        /* Combine the left node and the matching node */\r
+                        combineLeft = TRUE;\r
+                    }\r
+                    if (rightNode && (strcmp(rightNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0))\r
+                    {\r
+                        /* Combine the right node and the matching node */\r
+                        combineRight = TRUE;\r
+                    }\r
 \r
-    if (matchingNode != NULL)\r
-    {\r
-        /* Begin searching for an available range of resources starting from the\r
-         * matching node */\r
-        for (index = matchingNode->base; index <= policyRangeEnd;)\r
-        {\r
-            /* Is the matchingNode free? */\r
-            if (strcmp(matchingNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0)\r
-            {\r
-                uint32_t matchEnd = matchingNode->base + matchingNode->length - 1;\r
+                    /* Perform any combines, insert the leftover nodes, and free any memory associated\r
+                     * with any nodes that weren't reinserted into the tree */\r
+                    if (combineLeft && combineRight)\r
+                    {\r
+                        /* Combine all three nodes into the matchingNode.  Insert the freed cumulative\r
+                         * matching node and delete the memory for the old left and right nodes */\r
+                        matchingNode->base = leftNode->base;\r
+                        matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;\r
 \r
-                /* Move index to the first resource satisfying the alignment property */\r
-                if ((index % opInfo->policyAlignment) != 0)\r
-                {\r
-                    index += (opInfo->policyAlignment - (index % opInfo->policyAlignment));\r
-                }\r
-                \r
-                /* Move through the node's resource range looking for a contiguous set of resources\r
-                 * that satisfy the request. */\r
-                while ((index <= matchEnd) && (index <= policyRangeEnd))\r
-                {\r
-                    if (((index + opInfo->resourceInfo->length - 1) <= matchEnd) &&\r
-                        ((index + opInfo->resourceInfo->length - 1) <= policyRangeEnd))\r
+                        Rm_freeResourceTreeNode(leftNode);\r
+                        Rm_freeResourceTreeNode(rightNode);                        \r
+                    }\r
+                    else if (combineLeft)\r
                     {\r
-                        /* Found a resource range in the node that satisfies the requirements */\r
-                        opInfo->resourceInfo->base = index;\r
-                        resourceFound = TRUE;\r
-                        break;\r
+                        /* Combine the left and matching nodes.  Reinsert the right. */\r
+                        matchingNode->base = leftNode->base;\r
+                        matchingNode->length += leftNode->length;\r
+                        \r
+                        Rm_freeResourceTreeNode(leftNode);\r
+                        RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);                        \r
+                    }\r
+                    else if (combineRight)\r
+                    {\r
+                        /* Combine the right and matching nodes.  Reinsert the left. */\r
+                        matchingNode->length += rightNode->length;\r
+                        \r
+                        Rm_freeResourceTreeNode(rightNode);\r
+                        RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+                    }\r
+                    else\r
+                    {\r
+                        /* Combine cannot be performed.  Reinsert the left and right nodes then\r
+                         * free the matching node and reinsert it */\r
+                        RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+                        RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
                     }\r
 \r
-                    /* Move index to the next resource value that satisfies the alignment property */\r
-                    index += (opInfo->policyAlignment - (index % opInfo->policyAlignment));\r
-                }\r
-            }\r
-            \r
-            if (!resourceFound)\r
-            {\r
-                /* Move to the next tree node */\r
-                matchingNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
-                if (matchingNode == NULL)\r
-                {\r
-                    /* Reached end of tree.  Resource range does not exist.  Leave the search\r
-                     * loop */\r
-                    break;\r
+                    /* No matter the combine route taken the matching node will always be declared\r
+                     * free and reinserted */\r
+                    strcpy(matchingNode->allocatedTo, RM_NOT_ALLOCATED_STRING);\r
+                    RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);                    \r
                 }\r
                 else\r
                 {\r
-                    index = matchingNode->base;\r
+                    /* Case 2: free range is less than range in matched node. Need to split\r
+                     *         the matched node into three nodes.\r
+                     *\r
+                     * |<----------matched node---------->|\r
+                     *        |<---free request--->|\r
+                     */ \r
+\r
+                    /* Create the left node if needed.  If the bases are equal the matchingNode can\r
+                     * be reused as the left bound of the range. */\r
+                    if (findNode.base > matchingNode->base)\r
+                    {\r
+                        /* New left node attributes:\r
+                         * base: base of the matching node\r
+                         * length: base of requested resources - base of matching node */\r
+                        leftNode = Rm_newResourceTreeNode(matchingNode->base, findNode.base - matchingNode->base,\r
+                                                          matchingNode->allocatedTo); \r
+                    }\r
+\r
+                    /* Create the right node if needed.  If the end ranges are equal the matchingNode\r
+                     * can be reused as the right bound of the range */\r
+                    if (findEnd < matchingEnd)\r
+                    {                       \r
+                        /* New right node attributes:\r
+                         * base: base of the requested resources + length of requested resources\r
+                         * length: right bound of matching node - right bound of request resources */\r
+                        rightNode = Rm_newResourceTreeNode(findNode.base + findNode.length,\r
+                                                           matchingEnd - findEnd, matchingNode->allocatedTo);\r
+                    }\r
+\r
+                    /* Insert the left node into the tree if it was created. */\r
+                    if (leftNode)\r
+                    {\r
+                        RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+                    }\r
+                    /* Insert the right node into the tree if it was created. */\r
+                    if (rightNode)\r
+                    {\r
+                        RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+                    }\r
+\r
+                    /* Base and length of matching node becomes the base and length of the freed resources */\r
+                    matchingNode->base = findNode.base;                                    \r
+                    matchingNode->length = findNode.length;\r
+                    /* Free the resources and insert them into the tree */\r
+                    strcpy(matchingNode->allocatedTo, RM_NOT_ALLOCATED_STRING);\r
+                    RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
                 }\r
+\r
+                retVal = RM_SERVICE_APPROVED_AND_COMPLETED;\r
             }\r
             else\r
             {\r
-                /* Found a resource range that satisfies the request properties.  Break out of the\r
-                 * search loop */\r
-                break;\r
+                /* The matching allocated range to be freed was allocated to a different instance. */\r
+                retVal = RM_SERVICE_DENIED_RESOURCE_NOT_ALLOCATED_TO_INSTANCE_REQUESTING_THE_SERVICE;\r
             }\r
-        }\r
 \r
-        if (!resourceFound)\r
+        }\r
+        else\r
         {\r
-            retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_ALLOCATED;\r
+            /* Free resource range crosses over node boundaries.  This signifies a\r
+             * free of both allocated and unallocated resources since nodes are combined\r
+             * on allocate and free operations if possible. */\r
+            retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_FREE;\r
         }\r
     }\r
     else\r
     {\r
+        /* The free resources could not be found in the allocator */\r
         retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
     }\r
 \r
-    return(retVal); \r
+    return(retVal);  \r
 }\r
 \r
-/* Assume the policy has already approved of the allocation */\r
-int32_t Rm_treeAllocate(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
+int32_t Rm_allocatorOperation(Rm_Inst *rmInst, Rm_AllocatorOpInfo *opInfo)\r
 {\r
-    Rm_ResourceTreeNode findNode;\r
-    Rm_ResourceTreeNode *matchingNode = NULL;\r
-    Rm_ResourceTreeNode *leftNode = NULL;\r
-    Rm_ResourceTreeNode *rightNode = NULL;\r
-    uint32_t findEnd, matchingEnd;\r
+    Rm_Allocator *allocator = NULL;\r
     int32_t retVal;\r
+    void *key;\r
 \r
-    /* Find the tree node that contains the specified resource range */\r
-    findNode.base = opInfo->resourceInfo->base;\r
-    findNode.length = opInfo->resourceInfo->length;\r
-    matchingNode = RB_FIND(_Rm_ResourceTree, allocator->allocatorRootEntry, &findNode);\r
+    /* Lock access to the RM instance's transaction queue */\r
+    key = Rm_osalMtCsEnter();\r
 \r
-    if (matchingNode != NULL)\r
+    /* Get the specified resource's allocator */\r
+    allocator = Rm_allocatorFind(rmInst, opInfo->resourceInfo->name);\r
+\r
+    if (allocator)\r
     {\r
-        findEnd = findNode.base + findNode.length - 1;\r
-        matchingEnd = matchingNode->base + matchingNode->length - 1;\r
-        \r
-        /* Does the request range fit within the matching nodes entire range? */\r
-        if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd))\r
+        /* Call the allocator's type-based allocation function */\r
+        if(allocator->type == Rm_allocatorType_INTEGER)\r
         {\r
-            /* Handle requested resource range that is isolated to a single node\r
-             *\r
-             *\r
-             * base0                                  base0+length0-1\r
-             *   |<---------------length0------------------->|  => existing node\r
-             *         |<---------length1---------->|  => requested resources\r
-             *       base1                   base1+length1-1\r
-             */             \r
-            if (strcmp(matchingNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0)\r
+            if (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE)\r
             {\r
-                /* Resources are available - split up the node into potentially\r
-                 * three new nodes:\r
-                 * left node - free resources to left of newly allocated resources\r
-                 * middle node - newly allocated resources that satisfy the request\r
-                 * right node - free resources to the right of newly allocated resources\r
-                 *\r
-                 * There also may be combine possibilities to the left and right of the\r
-                 * matching node.  Need to extract those as well to check */\r
-                leftNode = RB_PREV(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
-                rightNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+                retVal = Rm_integerPreAllocate(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_treePreAllocate(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
-                /* Remove the matching node from the tree and the nodes to the left and\r
-                 * right of the matching node.  Removing from tree will not\r
-                 * wipe any of the base+length data in the node.  Can reuse since they won't\r
-                 * be freed */\r
-                RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
-                if (leftNode)\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
+            /* 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
-                    RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+                    /* Populate the transaction with the allocated resources and the result */\r
+                    transaction->state = approve reason;\r
+                    return ...\r
                 }\r
-                if (rightNode)\r
+                else\r
                 {\r
-                    RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\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
-                /* Create the left node if needed.  If the bases are equal the matchingNode can\r
-                 * be reused as the left bound of the range. */\r
-                if (findNode.base > matchingNode->base)\r
-                {\r
-                    /* Can the left node be combined with the node to the left of the matching\r
-                     * node */\r
-                    if (leftNode && (strcmp(leftNode->allocatedTo, opInfo->srcInstName) == 0))\r
-                    {\r
-                        /* Combine the left node and what's leftover on the left side of the \r
-                         * matchingNode range after the allocation */\r
-                        leftNode->length += (findNode.base - matchingNode->base);\r
-                    }\r
-                    else\r
-                    {\r
-                        /* Reinsert left node and create a new node to left of range to be allocated */\r
-                        if (leftNode)\r
-                        {\r
-                            RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
-                        }\r
-                        \r
-                        /* New left node attributes:\r
-                         * base: base of the matching node\r
-                         * length: base of requested resources - base of matching node */\r
-                        leftNode = Rm_newResourceTreeNode(matchingNode->base, findNode.base - matchingNode->base,\r
-                                                          RM_NOT_ALLOCATED_STRING);\r
-                    }\r
-\r
-                }\r
+            if (policy approves)\r
+            {\r
+                /* call allocator to allocate resource */\r
+            }\r
 \r
-                /* Create the right node if needed.  If the end ranges are equal the matchingNode\r
-                 * can be reused as the right bound of the range */\r
-                if (findEnd < matchingEnd)\r
-                {\r
-                    /* Can the right node be combined with the node to the right of the matching\r
-                     * node */\r
-                    if (rightNode && (strcmp(rightNode->allocatedTo, opInfo->srcInstName) == 0))\r
-                    {\r
-                        /* Combine the right node and what's leftover on the right side of the \r
-                         * matchingNode range after the allocation */\r
-                        rightNode->base = findNode.base + findNode.length;\r
-                        rightNode->length += (matchingEnd - findEnd);\r
-                    }\r
-                    else\r
-                    {\r
-                        /* Reinsert right node and create a new node to right of range to be allocated */\r
-                        if (rightNode)\r
-                        {\r
-                            RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
-                        }\r
-                                            \r
-                        /* New right node attributes:\r
-                         * base: base of the requested resources + length of requested resources\r
-                         * length: right bound of matching node - right bound of request resources */\r
-                        rightNode = Rm_newResourceTreeNode(findNode.base + findNode.length,\r
-                                                           matchingEnd - findEnd, RM_NOT_ALLOCATED_STRING);\r
-                    }\r
-                }\r
+            transaction->state = approve or deny reason;\r
+            transaction->resourceInfo.base = ...;\r
+            transaction->resourceInfo.length = ...;\r
 \r
-                /* Reinsert the left node into the tree if it was modified or created. */\r
-                if (leftNode)\r
-                {\r
-                    RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
-                }\r
-                /* Reinsert the right node into the tree if it was modified or created. */\r
-                if (rightNode)\r
-                {\r
-                    RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\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
 \r
-                /* Base and length of matching node becomes the base and length of the requested resources */\r
-                matchingNode->base = findNode.base;                                    \r
-                matchingNode->length = findNode.length;\r
-                /* Reserve the resources and insert them into the tree */\r
-                strcpy(matchingNode->allocatedTo, opInfo->srcInstName);\r
-                RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+void Rm_freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
+{\r
+    if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\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
 \r
-                retVal = RM_SERVICE_APPROVED_AND_COMPLETED;\r
+        if (policy check approves the free)\r
+        {\r
+            /* call the allocator to free the resource */\r
+            /* Run a resource pool check to see if the free combined a resource block\r
+             * that can be returned to the server */\r
+            if (resource block has been combined)\r
+            {\r
+                  /* allocator ran out of resources, need to contact Server for more\r
+                 * resources */\r
+                Rm_resourcePoolModRequest(free pool block to server...);\r
             }\r
             else\r
             {\r
-                /* A resource superset containing the requested range has\r
-                 * already been allocated. */\r
-                retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_ALLOCATED;\r
+                /* Populate the receipt with the freed resources and the result */\r
+                transaction->state = approve reason;\r
+                return ...\r
             }\r
         }\r
-        else\r
+        else if (policy check denies resource free)\r
         {\r
-            /* Request ranges that span multiple nodes signify resources are\r
-             * not available because nodes are combined into larger contiguous ranges\r
-             * on resource free operations. */\r
-            retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_ALLOCATED;\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
+#endif         \r
     }\r
-    else\r
+    else if (rmInst->instType == Rm_instType_SERVER)\r
     {\r
-        /* The requested resources could not be found in the allocator */\r
-        retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
-    }\r
+#if 0        \r
+        /* Check global policy to see if resource can be freed. return result\r
+         * no matter what */\r
+        Rm_policy...API()\r
+        if (policy approves)\r
+        {\r
+            /* call allocator to free resources */\r
+        }\r
+            \r
+        transaction->state = approve or deny reason;\r
+        transaction->resourceInfo.base = ...;\r
+        transaction->resourceInfo.length = ...;\r
 \r
-    return(retVal);        \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 Delegate or 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
+#endif        \r
+    }   \r
 }\r
 \r
-/* Assume policy has already approved of the free */\r
-int32_t Rm_treeFree(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
+/* Function used to forward RM transactions to higher level agents */\r
+void Rm_transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
 {\r
-    Rm_ResourceTreeNode findNode;\r
-    Rm_ResourceTreeNode *matchingNode = NULL;\r
-    Rm_ResourceTreeNode *leftNode = NULL;\r
-    Rm_ResourceTreeNode *rightNode = NULL;\r
-    bool combineLeft = FALSE;\r
-    bool combineRight = FALSE;\r
-    uint32_t findEnd, matchingEnd;\r
-    int32_t retVal;\r
+    Rm_TransportNode *dstTransportNode = NULL;\r
+    Rm_Packet *rmPkt = NULL;\r
 \r
-    /* Find the tree node that contains the specified resource range */\r
-    findNode.base = opInfo->resourceInfo->base;\r
-    findNode.length = opInfo->resourceInfo->length;\r
-    matchingNode = RB_FIND(_Rm_ResourceTree, allocator->allocatorRootEntry, &findNode);\r
+    /* Make sure the RM instance has a transport registered with a higher level agent */\r
+    if (rmInst->registeredWithDelegateOrServer == false)\r
+    {\r
+        transaction->state = RM_SERVICE_ERROR_NOT_REGISTERED_WITH_DEL_OR_SERVER;\r
+        return;\r
+    }\r
 \r
-    if (matchingNode != NULL)\r
+    /* Find the transport for the higher level agent.  Check for a connection to a Client Delegate\r
+     * or a Server.  Clients will be connected to either a Client Delegate or a Server.  Client\r
+     * Delegates will be connected to a Server. */\r
+    if (rmInst->instType == Rm_instType_CLIENT)\r
     {\r
-        findEnd = findNode.base + findNode.length - 1;\r
-        matchingEnd = matchingNode->base + matchingNode->length - 1;\r
-        \r
-        /* Does the free range fit within the matching nodes entire range?  It should\r
-         * either be the entire range or a subset set of the found range. (the latter\r
-         * satisfies the case where an entity allocated a contiguous block of resources\r
-         * then attempts to free a contiguous subset of the allocated block. */\r
-        if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd))\r
-        {            \r
-            if (strcmp(matchingNode->allocatedTo, opInfo->srcInstName) == 0)\r
-            {\r
-                /* Resources can be freed */\r
+        dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_CLIENT_DELEGATE);\r
+    } \r
+    else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
+    {\r
+        dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_SERVER);\r
+    }\r
 \r
-                if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd))\r
-                {\r
-                    /* Case 1: free range equals allocated matched node exactly. Attempt to combine \r
-                     *         the range to be freed with the resource nodes to the left and\r
-                     *         right of the free range.\r
-                     *\r
-                     * |<--left node-->||<---matched node--->||<--right node-->|\r
-                     *                  |<---free request--->|\r
-                     */ \r
+    /* Create a RM packet using the service information */\r
+    switch (transaction->type)\r
+    {\r
+        case Rm_service_RESOURCE_ALLOCATE:\r
+        case Rm_service_RESOURCE_BLOCK_ALLOCATE:\r
+        case Rm_service_RESOURCE_ALLOCATE_BY_NAME:\r
+        case Rm_service_RESOURCE_FREE:\r
+        case Rm_service_RESOURCE_BLOCK_FREE:\r
+        case Rm_service_RESOURCE_FREE_BY_NAME:\r
+            rmPkt = Rm_transportCreateResourceReqPkt(rmInst, dstTransportNode, \r
+                                                     transaction);\r
+            break;\r
+        case Rm_service_RESOURCE_MAP_TO_NAME:\r
+        case Rm_service_RESOURCE_UNMAP_NAME:\r
+            rmPkt = Rm_transportCreateNsRequestPkt(rmInst, dstTransportNode,\r
+                                                   transaction);\r
+            break;\r
+        default:\r
+            /* Invalid service type.  Flag the error and return */\r
+            transaction->state = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
+            break;\r
+    }\r
 \r
-                    leftNode = RB_PREV(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
-                    rightNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+    if (transaction->state <= RM_SERVICE_ERROR_BASE)\r
+    {\r
+        /* Return immediately because an error occurred allocating the packet */\r
+        return;\r
+    }\r
 \r
-                    /* Remove the matching node from the tree and the nodes to the left and\r
-                     * right of the matching node.  Removing from tree will not\r
-                     * wipe any of the base+length data in the node.  Can reuse since they won't\r
-                     * be freed */\r
-                    RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
-                    if (leftNode)\r
-                    {\r
-                        RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
-                    }\r
-                    if (rightNode)\r
-                    {\r
-                        RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
-                    }\r
+    /* Send the RM packet to the application transport */\r
+    if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt) < RM_TRANSPORT_SUCCESSFUL)\r
+    {\r
+        /* Negative value returned by transport send.  An error occurred\r
+         * in the transport while attempting to send the packet.*/\r
+        transaction->state = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
+        /* Clean up the packet */\r
+        if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt))\r
+        {\r
+            /* Non-NULL value returned by transport packet free. Flag the\r
+             * error */\r
+            transaction->state = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
+        }\r
+        return;\r
+    }\r
 \r
-                    /* See if the left or right or both nodes can be combined with the matching\r
-                     * node that will be freed. */\r
-                    if (leftNode && (strcmp(leftNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0))\r
-                    {\r
-                        /* Combine the left node and the matching node */\r
-                        combineLeft = TRUE;\r
-                    }\r
-                    if (rightNode && (strcmp(rightNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0))\r
-                    {\r
-                        /* Combine the right node and the matching node */\r
-                        combineRight = TRUE;\r
-                    }\r
+    /* Transaction is not deleted because it is awaiting a response from the higher level\r
+     * RM instance */\r
+}\r
 \r
-                    /* Perform any combines, insert the leftover nodes, and free any memory associated\r
-                     * with any nodes that weren't reinserted into the tree */\r
-                    if (combineLeft && combineRight)\r
-                    {\r
-                        /* Combine all three nodes into the matchingNode.  Insert the freed cumulative\r
-                         * matching node and delete the memory for the old left and right nodes */\r
-                        matchingNode->base = leftNode->base;\r
-                        matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;\r
+void Rm_transactionProcessor (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
+{\r
+    /* Handle auto-forwarded transactions.  These transactions include:\r
+     * - All request transactions received on Clients are forwarded to the Client Delegate\r
+     * - NameServer requests received on the Client Delegate are forwarded to the Server */\r
+    if ((rmInst->instType == Rm_instType_CLIENT) ||\r
+        ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
+         (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) ||\r
+         (transaction->type == Rm_service_RESOURCE_UNMAP_NAME)))\r
+    {\r
+        /* Check if the transaction is a transaction that received a response to its\r
+         * request. */\r
+        if (transaction->state != RM_SERVICE_PROCESSING)\r
+        {\r
 \r
-                        Rm_freeResourceTreeNode(leftNode);\r
-                        Rm_freeResourceTreeNode(rightNode);                        \r
-                    }\r
-                    else if (combineLeft)\r
-                    {\r
-                        /* Combine the left and matching nodes.  Reinsert the right. */\r
-                        matchingNode->base = leftNode->base;\r
-                        matchingNode->length += leftNode->length;\r
-                        \r
-                        Rm_freeResourceTreeNode(leftNode);\r
-                        RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);                        \r
-                    }\r
-                    else if (combineRight)\r
+            /* A transaction has received a response. Send the response to either the \r
+             * transaction or service responder based on the source instance */\r
+            if (strcmp(transaction->sourceInstName, rmInst->name))\r
+            {\r
+                /* Transaction originated from another instance.  Use the \r
+                 * transaction responder to send the result to the source instance.  This\r
+                 * is not possible on RM Clients since they can't forward RM services */\r
+                Rm_transactionResponder(rmInst, transaction);\r
+            }\r
+            else\r
+            {\r
+                /* Transaction originated on this instance.  Send to the\r
+                 * service responder */\r
+                Rm_serviceResponder(rmInst, transaction);\r
+            }\r
+        }\r
+        else\r
+        {\r
+            /* This is a new transaction that must be forwarded to a higher level RM instance. */\r
+            Rm_transactionForwarder(rmInst, transaction);\r
+        }\r
+    }\r
+    else\r
+    {\r
+        /* Client Delegate and Server transaction processors. */\r
+        switch (transaction->type)\r
+        {\r
+            case Rm_service_RESOURCE_ALLOCATE:\r
+            case Rm_service_RESOURCE_BLOCK_ALLOCATE:\r
+            case Rm_service_RESOURCE_ALLOCATE_BY_NAME:\r
+            case Rm_service_RESOURCE_FREE:\r
+            case Rm_service_RESOURCE_BLOCK_FREE:\r
+            case Rm_service_RESOURCE_FREE_BY_NAME:                \r
+                /* Check if the transaction is fulfilled request */\r
+                if (transaction->state != RM_SERVICE_PROCESSING)\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
-                        /* Combine the right and matching nodes.  Reinsert the left. */\r
-                        matchingNode->length += rightNode->length;\r
-                        \r
-                        Rm_freeResourceTreeNode(rightNode);\r
-                        RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+                        Rm_transactionResponder(rmInst, transaction);\r
                     }\r
                     else\r
                     {\r
-                        /* Combine cannot be performed.  Reinsert the left and right nodes then\r
-                         * free the matching node and reinsert it */\r
-                        RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
-                        RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+                        /* Resource allocation request originated locally.  Send the response\r
+                         * via the service responder. */\r
+                        Rm_serviceResponder(rmInst, transaction);      \r
                     }\r
-\r
-                    /* No matter the combine route taken the matching node will always be declared\r
-                     * free and reinserted */\r
-                    strcpy(matchingNode->allocatedTo, RM_NOT_ALLOCATED_STRING);\r
-                    RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);                    \r
                 }\r
                 else\r
                 {\r
-                    /* Case 2: free range is less than range in matched node. Need to split\r
-                     *         the matched node into three nodes.\r
-                     *\r
-                     * |<----------matched node---------->|\r
-                     *        |<---free request--->|\r
-                     */ \r
-\r
-                    /* Create the left node if needed.  If the bases are equal the matchingNode can\r
-                     * be reused as the left bound of the range. */\r
-                    if (findNode.base > matchingNode->base)\r
+                    /* This is a new transaction request originating from an RM instance with fewer\r
+                     * allocate/free privileges.  Run the allocation or free handler to see if the resource\r
+                     * request can be handled locally or if it needs to be forwarded to a higher level\r
+                     * agent */\r
+                    if ((transaction->type == Rm_service_RESOURCE_ALLOCATE) ||\r
+                        (transaction->type == Rm_service_RESOURCE_BLOCK_ALLOCATE) ||\r
+                        (transaction->type == Rm_service_RESOURCE_ALLOCATE_BY_NAME))\r
                     {\r
-                        /* New left node attributes:\r
-                         * base: base of the matching node\r
-                         * length: base of requested resources - base of matching node */\r
-                        leftNode = Rm_newResourceTreeNode(matchingNode->base, findNode.base - matchingNode->base,\r
-                                                          matchingNode->allocatedTo); \r
+                        Rm_allocationHandler(rmInst, transaction);\r
                     }\r
-\r
-                    /* Create the right node if needed.  If the end ranges are equal the matchingNode\r
-                     * can be reused as the right bound of the range */\r
-                    if (findEnd < matchingEnd)\r
-                    {                       \r
-                        /* New right node attributes:\r
-                         * base: base of the requested resources + length of requested resources\r
-                         * length: right bound of matching node - right bound of request resources */\r
-                        rightNode = Rm_newResourceTreeNode(findNode.base + findNode.length,\r
-                                                           matchingEnd - findEnd, matchingNode->allocatedTo);\r
+                    else\r
+                    {\r
+                        Rm_freeHandler(rmInst, transaction);\r
                     }\r
-\r
-                    /* Insert the left node into the tree if it was created. */\r
-                    if (leftNode)\r
+                }\r
+                break;\r
+            case Rm_service_RESOURCE_MAP_TO_NAME:\r
+            case Rm_service_RESOURCE_UNMAP_NAME:                \r
+                /* Server is the only RM instance capable of adding NameServer objects */\r
+                if (rmInst->instType == Rm_instType_SERVER)\r
+                {\r
+                    if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME)\r
                     {\r
-                        RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+                        /* Create a new NameServer object with the request transaction information.\r
+                         * Transaction will contain the state result of the NameServer addition. */\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
-                    /* Insert the right node into the tree if it was created. */\r
-                    if (rightNode)\r
+                    else\r
                     {\r
-                        RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+                        /* Delete an existing NameServer object with the request transaction information\r
+                         * Transaction will contain the state result of the NameServer addition. */\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
-                    /* Base and length of matching node becomes the base and length of the freed resources */\r
-                    matchingNode->base = findNode.base;                                    \r
-                    matchingNode->length = findNode.length;\r
-                    /* Free the resources and insert them into the tree */\r
-                    strcpy(matchingNode->allocatedTo, RM_NOT_ALLOCATED_STRING);\r
-                    RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+                    /* If source instance name does not match the local instance\r
+                     * name the NameServer request came from a Client or Client Delegate.  The \r
+                     * result must be sent back to the Client or Client Delegate.  Just return if it does\r
+                     * match since the NameServer transaction result can be returned immediately by the\r
+                     * Rm_serviceHandler. */\r
+                    if (strcmp(transaction->sourceInstName, rmInst->name))\r
+                    {\r
+                        Rm_transactionResponder(rmInst, transaction);\r
+                    }\r
                 }\r
-\r
-                retVal = RM_SERVICE_APPROVED_AND_COMPLETED;\r
-            }\r
-            else\r
-            {\r
-                /* The matching allocated range to be freed was allocated to a different instance. */\r
-                retVal = RM_SERVICE_DENIED_RESOURCE_NOT_ALLOCATED_TO_INSTANCE_REQUESTING_THE_SERVICE;\r
-            }\r
-\r
-        }\r
-        else\r
-        {\r
-            /* Free resource range crosses over node boundaries.  This signifies a\r
-             * free of both allocated and unallocated resources since nodes are combined\r
-             * on allocate and free operations if possible. */\r
-            retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_FREE;\r
+                else\r
+                {\r
+                    transaction->state = RM_SERVICE_ERROR_NAMESERVER_OBJECT_MOD_ON_INVALID_INSTANCE;\r
+                }\r
+                break;\r
         }\r
     }\r
-    else\r
-    {\r
-        /* The free resources could not be found in the allocator */\r
-        retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
-    }\r
-\r
-    return(retVal);  \r
 }\r
 \r
-int32_t Rm_allocatorOperation(Rm_Inst *rmInst, Rm_AllocatorOpInfo *opInfo)\r
+int32_t Rm_reserveLinuxResource(Rm_Inst *rmInst, Rm_LinuxAlias *linuxAlias, \r
+                                Rm_LinuxValueRange *linuxValues, 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
+    int32_t retVal = RM_DTB_UTIL_RESULT_OKAY;\r
+    bool baseFound = FALSE;\r
+    bool lengthFound = FALSE;\r
+    uint32_t valueIndex = 0;\r
 \r
-    if (allocator)\r
+    while ((linuxValues != NULL) && (!baseFound || !lengthFound))\r
     {\r
-        /* Call the allocator's type-based allocation function */\r
-        if(allocator->type == Rm_allocatorType_INTEGER)\r
+        if (linuxAlias->baseOffset == valueIndex)\r
         {\r
-            if (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE)\r
-            {\r
-                retVal = Rm_integerPreAllocate(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
+            /* Found the resource base.  Store it in the operation info structure */\r
+            opInfo->resourceInfo->base = linuxValues->value;\r
+            baseFound = TRUE;\r
+\r
+            /* length will always be 1 if there is no length specified in the Linux DTB */\r
+            if (linuxAlias->lengthOffset == RM_DTB_LINUX_ALIAS_OFFSET_NOT_SET)\r
             {\r
-                retVal = Rm_integerFree(allocator, opInfo);\r
+                opInfo->resourceInfo->length = 1;\r
+                lengthFound = TRUE;\r
             }\r
         }\r
-        else if (allocator->type == Rm_allocatorType_TREE)\r
+        else if (linuxAlias->lengthOffset == valueIndex)\r
         {\r
-            if (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE)\r
-            {\r
-                retVal = Rm_treePreAllocate(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
+            /* Found the resource length.  Store it in the operation info structure */\r
+            opInfo->resourceInfo->length = linuxValues->value;\r
+            lengthFound = TRUE;\r
+        }\r
+\r
+        linuxValues = (Rm_LinuxValueRange *)linuxValues->nextValue;\r
+        valueIndex++;\r
+    }\r
+\r
+    if (!baseFound || !lengthFound)\r
+    {\r
+        retVal = -33; /* TODO: ERROR BASE OR LENGTH OFFSET IN LINUX DTB WAS INCORRECT */\r
     }\r
     else\r
     {\r
-        /* Allocator could not be found for resource */\r
-        retVal = RM_SERVICE_DENIED_RESOURCE_DOES_NOT_EXIST;\r
+        /* Allocate the resource to Linux */\r
+        retVal = Rm_allocatorOperation(rmInst, opInfo);\r
     }\r
 \r
-    Rm_osalMtCsExit(key);\r
-    return(retVal);\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
+int32_t Rm_findAndReserveLinuxResource(Rm_Inst *rmInst, const char *resourceName, void *linuxDtb, \r
+                                       Rm_LinuxAlias *linuxAlias)\r
+{\r
+    Rm_AllocatorOpInfo opInfo;\r
+    Rm_ResourceInfo resourceInfo;\r
+    uint32_t pathOffset;\r
+    int32_t propOffset;\r
+    int32_t nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;\r
+    int32_t prevDepth = RM_DTB_UTIL_STARTING_DEPTH;\r
+    int32_t depth;\r
+    int32_t propertyLen;\r
+    const char *propertyName;\r
+    const void *propertyData; \r
+    Rm_LinuxValueRange *linuxValueRange;\r
+    bool foundResource;\r
+    int32_t retVal = RM_DTB_UTIL_RESULT_OKAY; \r
+\r
+    /* Initialize the allocator opInfo and resourceInfo structures that will be used to \r
+     * reserve the resources taken by the Linux kernel */\r
+    memset((void *) &opInfo, 0, sizeof(Rm_AllocatorOpInfo));\r
+    memset((void *) &resourceInfo, 0, sizeof(Rm_ResourceInfo));\r
+\r
+    strcpy(resourceInfo.name, resourceName);\r
+\r
+    opInfo.srcInstName = RM_ALLOCATED_TO_LINUX;\r
+    opInfo.operation = Rm_allocatorOp_ALLOCATE;\r
+    opInfo.resourceInfo = &resourceInfo;    \r
+\r
+    /* Find each resource specified in the Linux resource alias list and reserve that \r
+     * resource as used */\r
+    while(linuxAlias != NULL)\r
+    {\r
+        /* Reset the parsing variables */\r
+        foundResource = FALSE;\r
+        pathOffset = 0;\r
+        nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;\r
+        prevDepth = RM_DTB_UTIL_STARTING_DEPTH;   \r
+        resourceInfo.base = 0;\r
+        resourceInfo.length = 0;\r
+        \r
+        while(1)\r
         {\r
-            /* Check local policy to see if the request can be satisfied with the\r
-             * resources stored locally */\r
-            Rm_policy...API()\r
+            /* Move through the DTB nodes until the next alias path node is found */\r
+            if (strcmp(linuxAlias->pathList + pathOffset, fdt_get_name(linuxDtb, nodeOffset, NULL)))\r
+            {\r
+                nodeOffset = fdt_next_node(linuxDtb, nodeOffset, &depth);\r
 \r
-            if (policy check approves the resource)\r
+                if (depth < prevDepth)\r
+                {\r
+                    /* Returning from subnode that matched part of alias path without finding\r
+                     * the resource values */\r
+                    retVal = (-31); /* TODO: COULD NOT HAVE RESOURCE AT ALIAS PATH */\r
+                    break;\r
+                }\r
+            }\r
+            else\r
             {\r
-                /* call the allocator to allocate the resource */\r
-                if (allocator returns resource)\r
+                /* Found the next alias path node */\r
+                pathOffset += (strlen(linuxAlias->pathList + pathOffset) + 1);\r
+                prevDepth = fdt_node_depth(linuxDtb, nodeOffset);\r
+\r
+                /* Check the properties of the node to see if they match the next alias\r
+                 * path string */\r
+               propOffset = fdt_first_property_offset(linuxDtb, nodeOffset);\r
+                if (propOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET)\r
+                {             \r
+                    /* Search the properties for the next alias path string */\r
+                    while (propOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET)\r
+                    {\r
+                        propertyData = fdt_getprop_by_offset(linuxDtb, propOffset, \r
+                                                             &propertyName, &propertyLen);\r
+\r
+                        if (strcmp(linuxAlias->pathList + pathOffset, propertyName) == 0)\r
+                        {\r
+                            /* Found the alias property.  Extract the values that will\r
+                             * contain the resource information that must be reserved. */\r
+                            linuxValueRange = Rm_linuxExtractValues(propertyData, propertyLen);\r
+                            /* Use the values to reserve resources for the Linux kernel */\r
+                            retVal = Rm_reserveLinuxResource(rmInst, linuxAlias, \r
+                                                             linuxValueRange, &opInfo);\r
+                            \r
+                            /* Free the memory used to store the values */\r
+                            Rm_linuxFreeValues(linuxValueRange);\r
+\r
+                            foundResource = TRUE;\r
+                            break;\r
+                        }\r
+                        \r
+                        propOffset = fdt_next_property_offset(linuxDtb, propOffset);\r
+                        if (propOffset < -FDT_ERR_NOTFOUND)\r
+                        {\r
+                            /* Error was returned by LIBFDT when parsing the properties */\r
+                            retVal = propOffset;\r
+                            break;\r
+                        }                        \r
+                    } \r
+                }\r
+\r
+                if (propOffset < -FDT_ERR_NOTFOUND)\r
                 {\r
-                    /* Populate the transaction with the allocated resources and the result */\r
-                    transaction->state = approve reason;\r
-                    return ...\r
+                       /* Error was returned by LIBFDT when parsing the properties */\r
+                    retVal = propOffset;\r
+                    break;\r
                 }\r
-                else\r
+\r
+                if (foundResource)\r
                 {\r
-                    /* allocator ran out of resources, need to contact Server for more\r
-                     * resources */\r
-                    Rm_resourcePoolModRequest(...);\r
+                    /* Found the resource and reserved it or there was an error\r
+                     * trying to reserve it.  Break out of the while(1) loop */\r
+                    break;\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
+        if (retVal < RM_DTB_UTIL_RESULT_OKAY)\r
+        {\r
+            /* Error occurred during parsing of Linux DTB.  Return the error */\r
+            break;\r
+        }\r
+        linuxAlias = (Rm_LinuxAlias *) linuxAlias->nextLinuxAlias;\r
     }\r
-    else if (rmInst->instType == Rm_instType_SERVER)\r
+\r
+    return (retVal);\r
+}\r
+\r
+int32_t Rm_createAndInitAllocator(Rm_Inst *rmInst, const char *resourceName, \r
+                                  Rm_ResourceProperties *resourceProperties, void *linuxDtb)\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
+    Rm_LinuxAlias *linuxAlias = 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_resourceExtractAllocator(resourceProperties->allocatorData, \r
+                                                resourceProperties->allocatorLen);\r
+    range = rangeBasePtr = Rm_resourceExtractRange(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
-#if 0       \r
-        if (resourceBase is unspecified)\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
+        if (resourceProperties->linuxAliasData && resourceProperties->linuxAliasLen)\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
+            /* Reserve the resources taken by the Linux kernel specified in the Linux DTB */\r
+            linuxAlias = Rm_resourceExtractLinuxAlias(resourceProperties->linuxAliasData,\r
+                                                      resourceProperties->linuxAliasLen);\r
+\r
+            retVal = Rm_findAndReserveLinuxResource(rmInst, resourceName, linuxDtb, linuxAlias);            \r
         }\r
-        else\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
-            /* Check global policy to see if resource can be allocated. return result\r
-             * no matter what */\r
-            Rm_policy...API()\r
+            nsAssignments = Rm_resourceExtractNsAssignment(resourceProperties->nsAssignData, \r
+                                                           resourceProperties->nsAssignLen);\r
 \r
-            if (policy approves)\r
+            /* Cycle through the list of assignments and add them to the NameServer */\r
+            nsAssignmentBasePtr = nsAssignments;\r
+            while (nsAssignments)\r
             {\r
-                /* call allocator to allocate resource */\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
-            transaction->state = approve or deny reason;\r
-            transaction->resourceInfo.base = ...;\r
-            transaction->resourceInfo.length = ...;\r
+    /* Free the memory allocated for the resource properties */\r
+    Rm_resourceFreeAllocator(allocatorType);\r
+    Rm_resourceFreeRange(rangeBasePtr);\r
+    Rm_resourceFreeLinuxAlias(linuxAlias);\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
+    return(retVal);\r
 }\r
 \r
-void Rm_freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
+int32_t Rm_parseResourceProperty(void *globalResourceDtb, int32_t offset, Rm_ResourceProperties *propertyInfo)\r
 {\r
-    if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\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
+       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
-        if (policy check approves the free)\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
-            /* call the allocator to free the resource */\r
-            /* Run a resource pool check to see if the free combined a resource block\r
-             * that can be returned to the server */\r
-            if (resource block has been combined)\r
+            if (propertyInfo->allocatorData || propertyInfo->allocatorLen)\r
             {\r
-                  /* allocator ran out of resources, need to contact Server for more\r
-                 * resources */\r
-                Rm_resourcePoolModRequest(free pool block to server...);\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
-                /* Populate the receipt with the freed resources and the result */\r
-                transaction->state = approve reason;\r
-                return ...\r
+                propertyInfo->allocatorData = propertyData;\r
+                propertyInfo->allocatorLen = propertyLen;\r
             }\r
         }\r
-        else if (policy check denies resource free)\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
+        else if (propertyType == Rm_resourcePropType_RESOURCE_RANGE)\r
         {\r
-            /* Forward the transaction to the Server */\r
-            Rm_transactionForwarder(rmInst, transaction);\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
-#endif         \r
-    }\r
-    else if (rmInst->instType == Rm_instType_SERVER)\r
-    {\r
-#if 0        \r
-        /* Check global policy to see if resource can be freed. return result\r
-         * no matter what */\r
-        Rm_policy...API()\r
-        if (policy approves)\r
+        else if (propertyType == Rm_resourcePropType_NSASSIGNMENT)\r
         {\r
-            /* call allocator to free resources */\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
-            \r
-        transaction->state = approve or deny reason;\r
-        transaction->resourceInfo.base = ...;\r
-        transaction->resourceInfo.length = ...;\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
+        else if (propertyType == Rm_resourcePropType_RESOURCE_LINUX_ALIAS)\r
         {\r
-            /* Names don't match.  Send the transaction back to the Client Delegate or Client */\r
-            Rm_transactionResponder(rmInst, transaction);\r
-        }\r
+            if (propertyInfo->linuxAliasData || propertyInfo->linuxAliasLen)\r
+            {\r
+                /* The linuxAlias 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 = -28; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
+            }\r
+            else\r
+            {\r
+                propertyInfo->linuxAliasData = propertyData;\r
+                propertyInfo->linuxAliasLen = propertyLen;\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
+            retVal = -20; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
         }\r
-#endif        \r
-    }   \r
-}\r
-\r
-/* Function used to forward RM transactions to higher level agents */\r
-void Rm_transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
-{\r
-    Rm_TransportNode *dstTransportNode = NULL;\r
-    Rm_Packet *rmPkt = NULL;\r
-\r
-    /* Make sure the RM instance has a transport registered with a higher level agent */\r
-    if (rmInst->registeredWithDelegateOrServer == false)\r
-    {\r
-        transaction->state = RM_SERVICE_ERROR_NOT_REGISTERED_WITH_DEL_OR_SERVER;\r
-        return;\r
-    }\r
-\r
-    /* Find the transport for the higher level agent.  Check for a connection to a Client Delegate\r
-     * or a Server.  Clients will be connected to either a Client Delegate or a Server.  Client\r
-     * Delegates will be connected to a Server. */\r
-    if (rmInst->instType == Rm_instType_CLIENT)\r
-    {\r
-        dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_CLIENT_DELEGATE);\r
-    } \r
-    else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
-    {\r
-        dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_SERVER);\r
-    }\r
-\r
-    /* Create a RM packet using the service information */\r
-    switch (transaction->type)\r
-    {\r
-        case Rm_service_RESOURCE_ALLOCATE:\r
-        case Rm_service_RESOURCE_BLOCK_ALLOCATE:\r
-        case Rm_service_RESOURCE_ALLOCATE_BY_NAME:\r
-        case Rm_service_RESOURCE_FREE:\r
-        case Rm_service_RESOURCE_BLOCK_FREE:\r
-        case Rm_service_RESOURCE_FREE_BY_NAME:\r
-            rmPkt = Rm_transportCreateResourceReqPkt(rmInst, dstTransportNode, \r
-                                                     transaction);\r
-            break;\r
-        case Rm_service_RESOURCE_MAP_TO_NAME:\r
-        case Rm_service_RESOURCE_UNMAP_NAME:\r
-            rmPkt = Rm_transportCreateNsRequestPkt(rmInst, dstTransportNode,\r
-                                                   transaction);\r
-            break;\r
-        default:\r
-            /* Invalid service type.  Flag the error and return */\r
-            transaction->state = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
-            break;\r
     }\r
-\r
-    if (transaction->state <= RM_SERVICE_ERROR_BASE)\r
+    else\r
     {\r
-        /* Return immediately because an error occurred allocating the packet */\r
-        return;\r
+        retVal = -16; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
     }\r
 \r
-    /* Send the RM packet to the application transport */\r
-    if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt) < RM_TRANSPORT_SUCCESSFUL)\r
+    /* Don't get anymore properties if error occurred */\r
+    if (retVal == RM_DTB_UTIL_RESULT_OKAY)\r
     {\r
-        /* Negative value returned by transport send.  An error occurred\r
-         * in the transport while attempting to send the packet.*/\r
-        transaction->state = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
-        /* Clean up the packet */\r
-        if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt))\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
-            /* Non-NULL value returned by transport packet free. Flag the\r
-             * error */\r
-            transaction->state = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
+            /* Error was returned by LIBFDT when parsing the properties */\r
+            retVal = offset;\r
         }\r
-        return;\r
     }\r
-\r
-    /* Transaction is not deleted because it is awaiting a response from the higher level\r
-     * RM instance */\r
+    \r
+    return (retVal);\r
 }\r
 \r
-void Rm_transactionProcessor (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
+int32_t Rm_parseResourceNode(Rm_Inst *rmInst, void *globalResourceDtb, int32_t nodeOffset, int32_t depth,\r
+                             void *linuxDtb)\r
 {\r
-    /* Handle auto-forwarded transactions.  These transactions include:\r
-     * - All request transactions received on Clients are forwarded to the Client Delegate\r
-     * - NameServer requests received on the Client Delegate are forwarded to the Server */\r
-    if ((rmInst->instType == Rm_instType_CLIENT) ||\r
-        ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
-         (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) ||\r
-         (transaction->type == Rm_service_RESOURCE_UNMAP_NAME)))\r
-    {\r
-        /* Check if the transaction is a transaction that received a response to its\r
-         * request. */\r
-        if (transaction->state != RM_SERVICE_PROCESSING)\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
-            /* A transaction has received a response. Send the response to either the \r
-             * transaction or service responder based on the source instance */\r
-            if (strcmp(transaction->sourceInstName, rmInst->name))\r
-            {\r
-                /* Transaction originated from another instance.  Use the \r
-                 * transaction responder to send the result to the source instance.  This\r
-                 * is not possible on RM Clients since they can't forward RM services */\r
-                Rm_transactionResponder(rmInst, transaction);\r
-            }\r
-            else\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
-                /* Transaction originated on this instance.  Send to the\r
-                 * service responder */\r
-                Rm_serviceResponder(rmInst, transaction);\r
+                return (error);\r
             }\r
-        }\r
-        else\r
+            \r
+            /* Initialize an allocator with the resource properties if no error was returned */\r
+            Rm_createAndInitAllocator(rmInst, resourceName, &resourceProperties, linuxDtb);\r
+       }\r
+        else if (offset != -FDT_ERR_NOTFOUND)\r
         {\r
-            /* This is a new transaction that must be forwarded to a higher level RM instance. */\r
-            Rm_transactionForwarder(rmInst, transaction);\r
+               /* Error was returned by LIBFDT when parsing the properties */\r
+            return (offset);\r
         }\r
     }\r
-    else\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
-        /* Client Delegate and Server transaction processors. */\r
-        switch (transaction->type)\r
+        error = Rm_parseResourceNode(rmInst, globalResourceDtb, offset, depth, linuxDtb);\r
+        if (error < -FDT_ERR_NOTFOUND)\r
         {\r
-            case Rm_service_RESOURCE_ALLOCATE:\r
-            case Rm_service_RESOURCE_BLOCK_ALLOCATE:\r
-            case Rm_service_RESOURCE_ALLOCATE_BY_NAME:\r
-            case Rm_service_RESOURCE_FREE:\r
-            case Rm_service_RESOURCE_BLOCK_FREE:\r
-            case Rm_service_RESOURCE_FREE_BY_NAME:                \r
-                /* Check if the transaction is fulfilled request */\r
-                if (transaction->state != RM_SERVICE_PROCESSING)\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
-                        Rm_transactionResponder(rmInst, transaction);\r
-                    }\r
-                    else\r
-                    {\r
-                        /* Resource allocation request originated locally.  Send the response\r
-                         * via the service responder. */\r
-                        Rm_serviceResponder(rmInst, transaction);      \r
-                    }\r
-                }\r
-                else\r
-                {\r
-                    /* This is a new transaction request originating from an RM instance with fewer\r
-                     * allocate/free privileges.  Run the allocation or free handler to see if the resource\r
-                     * request can be handled locally or if it needs to be forwarded to a higher level\r
-                     * agent */\r
-                    if ((transaction->type == Rm_service_RESOURCE_ALLOCATE) ||\r
-                        (transaction->type == Rm_service_RESOURCE_BLOCK_ALLOCATE) ||\r
-                        (transaction->type == Rm_service_RESOURCE_ALLOCATE_BY_NAME))\r
-                    {\r
-                        Rm_allocationHandler(rmInst, transaction);\r
-                    }\r
-                    else\r
-                    {\r
-                        Rm_freeHandler(rmInst, transaction);\r
-                    }\r
-                }\r
-                break;\r
-            case Rm_service_RESOURCE_MAP_TO_NAME:\r
-            case Rm_service_RESOURCE_UNMAP_NAME:                \r
-                /* Server is the only RM instance capable of adding NameServer objects */\r
-                if (rmInst->instType == Rm_instType_SERVER)\r
-                {\r
-                    if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME)\r
-                    {\r
-                        /* Create a new NameServer object with the request transaction information.\r
-                         * Transaction will contain the state result of the NameServer addition. */\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
-                        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
-                     * name the NameServer request came from a Client or Client Delegate.  The \r
-                     * result must be sent back to the Client or Client Delegate.  Just return if it does\r
-                     * match since the NameServer transaction result can be returned immediately by the\r
-                     * Rm_serviceHandler. */\r
-                    if (strcmp(transaction->sourceInstName, rmInst->name))\r
-                    {\r
-                        Rm_transactionResponder(rmInst, transaction);\r
-                    }\r
-                }\r
-                else\r
-                {\r
-                    transaction->state = RM_SERVICE_ERROR_NAMESERVER_OBJECT_MOD_ON_INVALID_INSTANCE;\r
-                }\r
-                break;\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
 int32_t Rm_initializeAllocators(Rm_Inst *rmInst, void *globalResourceDtb, void *linuxDtb)\r
index 3334df2733b96f28baa1050cc0fa27571e185fe1..1c381dc42d7e4187f391130f9fdeab6f6291e85d 100644 (file)
@@ -204,7 +204,7 @@ Rm_ResourceRange *Rm_resourceExtractRange(const void *dtbDataPtr, int32_t dtbDat
     return(Rm_commonExtractRange(dtbDataPtr, dtbDataLen));
 }
 
-void Rm_resourceFreeResourceRange(Rm_ResourceRange *rangeList)
+void Rm_resourceFreeRange(Rm_ResourceRange *rangeList)
 {
     Rm_commonFreeRangeList(rangeList);
 }
@@ -215,7 +215,7 @@ char *Rm_resourceExtractAllocator(const void *dtbDataPtr, int32_t dtbDataLen)
     return(Rm_commonExtractName(dtbDataPtr, dtbDataLen));
 }
 
-void Rm_resourceFreeResourceAllocator(char *resourceAllocatorType)
+void Rm_resourceFreeAllocator(char *resourceAllocatorType)
 {
     Rm_commonFreeName(resourceAllocatorType);
 }
@@ -225,13 +225,13 @@ Rm_LinuxAlias *Rm_resourceExtractLinuxAlias(const void *dtbDataPtr, int32_t dtbD
     uint8_t *aliasData = (uint8_t *)dtbDataPtr;
     uint8_t *pathStart = NULL;
     uint32_t pathLenBytes;
-    uint32_t nameLenBytes;
+    uint32_t stringLenBytes;
     uint32_t extractedValue;
     uint8_t *extractedValueBytePtr;        
     Rm_LinuxAlias *startAlias = NULL;
     Rm_LinuxAlias *newAlias = NULL;
     Rm_LinuxAlias *prevAlias = NULL;
-    int8_t i = 0;
+    uint32_t i = 0;
     uint16_t j;
     
     /* Linux aliases are stored in the DTB as a list of null-terminated character
@@ -254,18 +254,18 @@ Rm_LinuxAlias *Rm_resourceExtractLinuxAlias(const void *dtbDataPtr, int32_t dtbD
          * path string (adding one for each null character). */
         pathStart = aliasData + i;
         pathLenBytes = 0;
-        while (strcmp((char *)aliasData[i], rmResourceLinuxAliasCompletionString) != 0)
+        while (strcmp((char *)(aliasData + i), rmResourceLinuxAliasCompletionString) != 0)
         {
-            nameLenBytes = strlen((char *) aliasData[i]) + 1;
-            pathLenBytes += nameLenBytes;
-            i += nameLenBytes;
+            stringLenBytes = strlen((char *) (aliasData + i)) + 1;
+            pathLenBytes += stringLenBytes;
+            i += stringLenBytes;
         }
         newAlias->pathList = (char *) Rm_osalMalloc(pathLenBytes);
         newAlias->pathListLenBytes = pathLenBytes;
         memcpy((void *) newAlias->pathList, (void *)pathStart, pathLenBytes);
 
         /* Skip past the first "end" string */
-        i += (strlen((char *) aliasData[i]) + 1);       
+        i += (strlen((char *) (aliasData + i)) + 1);       
         
         /* Extract the first 32-bit offset */
         extractedValueBytePtr = (uint8_t *)&extractedValue;
@@ -274,10 +274,10 @@ Rm_LinuxAlias *Rm_resourceExtractLinuxAlias(const void *dtbDataPtr, int32_t dtbD
             extractedValueBytePtr[j] = aliasData[i];
         }
         /* flip the endianness */
-        newAlias->base = fdt32_to_cpu(extractedValue);
+        newAlias->baseOffset = fdt32_to_cpu(extractedValue);
 
         /* Check for the "end" string. Extract the second offset if it isn't there */
-        if (strcmp((char *) aliasData[i], rmResourceLinuxAliasCompletionString) != 0)
+        if (strcmp((char *) (aliasData + i), rmResourceLinuxAliasCompletionString) != 0)
         {
             /* Extract the second 32-bit offset */
             extractedValueBytePtr = (uint8_t *)&extractedValue;
@@ -286,15 +286,15 @@ Rm_LinuxAlias *Rm_resourceExtractLinuxAlias(const void *dtbDataPtr, int32_t dtbD
                 extractedValueBytePtr[j] = aliasData[i];
             }
             /* flip the endianness */
-            newAlias->base = fdt32_to_cpu(extractedValue);
+            newAlias->lengthOffset = fdt32_to_cpu(extractedValue);
         }
         else
         {
-            newAlias->length = RM_DTB_LINUX_ALIAS_OFFSET_NOT_SET;
+            newAlias->lengthOffset = RM_DTB_LINUX_ALIAS_OFFSET_NOT_SET;
         }
 
         /* Skip past the second "end" string */
-        i += (strlen((char *) aliasData[i]) + 1);   
+        i += (strlen((char *) (aliasData + i)) + 1);   
 
         newAlias->nextLinuxAlias = NULL;
 
@@ -588,6 +588,61 @@ void Rm_policyFreeAssignmentNsNamesList (Rm_AssignedNsNames *assignedNsNamesList
     }
 }
 
+/**********************************************************************
+ ****************Linux DTB Parsing Defines and Functions***************
+ **********************************************************************/
+
+Rm_LinuxValueRange *Rm_linuxExtractValues(const void *dtbDataPtr, int32_t dtbDataLen)
+{
+    uint32_t *dtbValueData = (uint32_t *)dtbDataPtr;
+    Rm_LinuxValueRange *startValue = NULL;
+    Rm_LinuxValueRange *newValue = NULL;
+    Rm_LinuxValueRange *prevValue = NULL;
+    uint32_t i;
+    
+    /* Values are stored in the Linux DTB as a list of 32-bit words.  The number of 32-bit
+     * words in the value field can differ.  depending on the number of values specified. */
+
+    /* Extract the value data from the Linux DTB */
+    for (i = 0; i < (dtbDataLen / sizeof(uint32_t)); i++)
+    {
+        /* Creat a new value entry */
+        newValue = (Rm_LinuxValueRange *) Rm_osalMalloc(sizeof(Rm_LinuxValueRange));
+        /* Populate the new value entry.  The endianness of the value extracted must
+         * be flipped */
+        newValue->value = fdt32_to_cpu(dtbValueData[i]);
+        newValue->nextValue = NULL;
+        
+        /* Value linked list pointer accounting */
+        if (prevValue == NULL)
+        {
+            /* Save the first entry so it can be returned */
+            startValue = newValue;
+        }
+        else
+        {
+            prevValue->nextValue = (void *) newValue;
+        }
+
+        prevValue = newValue;
+    }
+
+    /* Return a pointer to the start of the value list */
+    return (startValue);
+}
+
+void Rm_linuxFreeValues(Rm_LinuxValueRange *valueList)
+{
+    Rm_LinuxValueRange *nextValue;
+    
+    while (valueList != NULL)
+    {
+        nextValue = valueList->nextValue;
+        Rm_osalFree((void *)valueList, sizeof(Rm_LinuxValueRange));
+        valueList = nextValue;
+    }
+}
+
 /**
 @}
 */
index 855986c2d67b475debf77db11dd009c3c1ea9d7a..9cc693696f0811d6daa0dbe134ae8555d3c88595 100644 (file)
@@ -351,7 +351,7 @@ Void testRmTsk(UArg arg0, UArg arg1)
         requestInfo.type = Rm_service_RESOURCE_MAP_TO_NAME;
         requestInfo.resourceName = &resourceName[0];
         requestInfo.resourceBase = 1;
-        requestInfo.resourceRange = 2;
+        requestInfo.resourceLength = 2;
         requestInfo.resourceNsName = &resourceNsName[0];
         requestInfo.callback.serviceCallback = testServiceCallback;
         
@@ -367,7 +367,7 @@ Void testRmTsk(UArg arg0, UArg arg1)
         requestInfo.type = Rm_service_RESOURCE_MAP_TO_NAME;
         requestInfo.resourceName = &resourceName[0];
         requestInfo.resourceBase = 2;
-        requestInfo.resourceRange = 3;
+        requestInfo.resourceLength = 3;
         requestInfo.resourceNsName = &resourceNsName[0];
         requestInfo.callback.serviceCallback = testServiceCallback;