]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/rm-lld.git/blobdiff - src/rm.c
Bug fixes, cleanup, expanded test code
[keystone-rtos/rm-lld.git] / src / rm.c
index 28e58fcb1349c6b32a95f2c18fa2e44e5f98ac6a..d3ab4932ba66e2c1677bf1b3d2d905dae3133c12 100644 (file)
--- a/src/rm.c
+++ b/src/rm.c
 #include <ti/drv/rm/include/rm_transportloc.h>\r
 #include <ti/drv/rm/include/rm_servicesloc.h>\r
 #include <ti/drv/rm/include/rm_nameserverloc.h>\r
+#include <ti/drv/rm/include/rm_dtb_utilloc.h>\r
+\r
+/* RM LIBFDT includes */\r
+#include <ti/drv/rm/src/libfdt/libfdt.h>\r
+\r
+/* AVL BBST includes */\r
+#include <ti/drv/rm/include/tree.h>\r
 \r
 /* RM OSAL layer */\r
 #include <rm_osal.h>\r
 /**********************************************************************\r
  ************************** Globals ***********************************\r
  **********************************************************************/\r
-#if 0\r
-/* Place QMSS PDSP permissions array */\r
-#pragma DATA_SECTION (rmQmssPdspFirmwarePerms, ".rm");\r
-#pragma DATA_ALIGN (rmQmssPdspFirmwarePerms, 128)\r
-Rm_Perms rmQmssPdspFirmwarePerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_QMSS_FIRMWARE_PDSPS, Rm_Perms)];\r
-#endif\r
+char rmIntegerAllocator[] = "integer";\r
+char rmTreeAllocator[] = "tree";\r
+\r
+extern char rmDtbStartingNode[];\r
 \r
 /** @brief Global Variable which describes the RM Version Information */\r
 const char   rmVersionStr[] = RM_VERSION_STR ":" __DATE__  ":" __TIME__;\r
 \r
+/**********************************************************************\r
+ ************** Red-Black BBST Tree Allocator Functions ***************\r
+ **********************************************************************/\r
+\r
+/* Prototype for function that allocates new tree nodes */\r
+Rm_ResourceTreeNode *Rm_newResourceTreeNode(uint32_t resourceBase, uint32_t resourceLength, \r
+                                            char *allocatedTo)\r
+{\r
+    Rm_ResourceTreeNode *newNode = NULL;\r
+\r
+    newNode = Rm_osalMalloc(sizeof(Rm_ResourceTreeNode));\r
+\r
+    /* Populate the RM relevant fields */\r
+    newNode->base = resourceBase;\r
+    newNode->length = resourceLength;\r
+    strcpy(newNode->allocatedTo, allocatedTo);\r
+\r
+    return(newNode);\r
+}\r
+\r
+/* Prototype for function that frees new tree nodes */\r
+void Rm_freeResourceTreeNode(Rm_ResourceTreeNode *treeNode)\r
+{\r
+    /* Free the memory associated with the tree node. */\r
+    Rm_osalFree((void *)treeNode, sizeof(Rm_ResourceTreeNode));\r
+}\r
+\r
+/* Prototype for tree node comparison function\r
+ * element1 < element2 --> return < 0\r
+ * element1 = element2 --> return 0\r
+ * element1 > element2 --> return > 0 */\r
+int Rm_ResourceTreeNodeCompare(Rm_ResourceTreeNode *element1, Rm_ResourceTreeNode *element2)\r
+{\r
+    uint32_t element1End = element1->base + element1->length - 1;\r
+    uint32_t element2End = element2->base + element2->length - 1;\r
+\r
+    if (element1End < element2->base)\r
+    {\r
+        /* End of element1 range is less than the start of element2's range.  Return a negative\r
+         * value */\r
+        return (-1);\r
+    }\r
+    else if (element1->base > element2End)\r
+    {\r
+        /* Start of element1 range is after end of element2's range.  Return a positive value */\r
+        return (1);\r
+    }\r
+    else\r
+    {\r
+        /* If neither of the latter conditions were satisfied there is some overlap between\r
+         * element1 and element2.  Return 0 since the application must handle this overlap. */\r
+        return (0);\r
+    }\r
+}\r
+\r
+/* Generate the red-black tree manipulation functions */\r
+RB_GENERATE(_Rm_ResourceTree, _Rm_ResourceTreeNode, linkage, Rm_ResourceTreeNodeCompare);\r
+\r
 /**********************************************************************\r
  ********************** Internal Functions ****************************\r
  **********************************************************************/\r
 \r
-/* At the very least the transaction ID needs to be provided to create a transaction */\r
-Rm_Transaction *Rm_transactionQueueAdd(Rm_Inst *rmInst, uint32_t transactionId)\r
+Rm_Transaction *Rm_transactionQueueAdd(Rm_Inst *rmInst)\r
 {\r
     Rm_Transaction *transactionQueue = (Rm_Transaction *)rmInst->transactionQueue;\r
     Rm_Transaction *newTransaction = NULL;\r
     void *key;\r
 \r
     /* Lock access to the RM instance's transaction queue */\r
-    key = Rm_osalCsEnter();\r
+    key = Rm_osalMtCsEnter();\r
 \r
     /* Get memory for a new transaction from local memory */\r
-    newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction), false);\r
+    newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction));\r
 \r
     /* Return if the memory allocated for the transaction entry is NULL */\r
-    if (newTransaction == NULL)\r
+    if (newTransaction != NULL)\r
     {\r
-        Rm_osalCsExit(key);\r
-        return(newTransaction);\r
-    }\r
-\r
-    /* Clear the transaction */\r
-    memset((void *)newTransaction, 0, sizeof(Rm_Transaction));\r
-\r
-    /* Populate transaction with the provided ID */\r
-    newTransaction->id = transactionId;\r
-    /* New transaction's nextTransaction pointer will always be NULL */\r
-    newTransaction->nextTransaction = NULL;  \r
+        /* Clear the transaction */\r
+        memset((void *)newTransaction, 0, sizeof(Rm_Transaction));\r
+\r
+        /* Create an ID for the new transaction.  The ID will be used for two purposes:\r
+         * 1) Matching responses from higher level RM agents to requests\r
+         * 2) Provided to the component that requested the service so that it can match its\r
+         *    request with the response it receives via its callback function it provided */\r
+        newTransaction->localId = Rm_transactionGetSequenceNum(rmInst);\r
+        /* New transaction's nextTransaction pointer will always be NULL */\r
+        newTransaction->nextTransaction = NULL;  \r
+\r
+        /* Check if there are any transactions in the transaction queue */\r
+        if (transactionQueue)\r
+        {\r
+            /* At least one transaction in the transaction queue.  Add the new entry to the \r
+             * end of the transaction queue */\r
+            while (transactionQueue->nextTransaction != NULL)\r
+            {\r
+                /* Traverse the list until arriving at the last transaction */\r
+                transactionQueue = transactionQueue->nextTransaction;\r
+            }\r
 \r
-    /* Check if there are any transactions in the transaction queue */\r
-    if (transactionQueue)\r
-    {\r
-        /* At least one transaction in the transaction queue.  Add the new entry to the \r
-         * end of the transaction queue */\r
-        while (transactionQueue->nextTransaction != NULL)\r
+            /* Add the new transaction to the end of the queue */\r
+            transactionQueue->nextTransaction = newTransaction;\r
+        }\r
+        else\r
         {\r
-            /* Traverse the list until arriving at the last transaction */\r
-            transactionQueue = transactionQueue->nextTransaction;\r
+            /* The transaction queue does not currently exist.  The new transaction is the \r
+             * first transaction */\r
+            rmInst->transactionQueue = newTransaction;\r
         }\r
-\r
-        /* Add the new transaction to the end of the queue */\r
-        transactionQueue->nextTransaction = newTransaction;\r
-    }\r
-    else\r
-    {\r
-        /* The transaction queue does not currently exist.  The new transaction is the \r
-         * first transaction */\r
-        rmInst->transactionQueue = newTransaction;\r
     }\r
 \r
-    Rm_osalCsExit(key);\r
+    Rm_osalMtCsExit(key);\r
     return (newTransaction);\r
 }\r
 \r
@@ -139,7 +201,7 @@ Rm_Transaction *Rm_transactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)
          * transaction pointer will be NULL */\r
         while (transaction != NULL)\r
         {\r
-            if (transaction->id == transactionId)\r
+            if (transaction->localId == transactionId)\r
             {\r
                 /* Match: break out of loop and return the transaction */\r
                 break;             \r
@@ -155,22 +217,16 @@ int32_t Rm_transactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)
 {\r
     Rm_Transaction *transaction = (Rm_Transaction *) rmInst->transactionQueue;\r
     Rm_Transaction *prevTransaction = NULL;\r
+    int32_t retVal = RM_SERVICE_STATE_OKAY;\r
     void *key;\r
 \r
     /* Lock access to the RM instance's transaction queue */\r
-    key = Rm_osalCsEnter();\r
-\r
-    /* Make sure there is at least one entry in the transaction queue */\r
-    if (transaction == NULL)\r
-    {\r
-        Rm_osalCsExit(key);\r
-        return (RM_SERVICE_ERROR_NO_TRANSACTIONS_IN_QUEUE);\r
-    }\r
+    key = Rm_osalMtCsEnter();\r
 \r
     /* Find the transaction ID within the specified RM instance's transaction queue. */\r
     while (transaction != NULL)\r
     {\r
-        if (transaction->id == transactionId)\r
+        if (transaction->localId == transactionId)\r
         {\r
             /* Match: break out of loop and delete the transaction */\r
             break;             \r
@@ -183,17 +239,16 @@ int32_t Rm_transactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)
     /* Traversed entire queue but did not find transaction */\r
     if (transaction == NULL)\r
     {\r
-        Rm_osalCsExit(key);\r
-        return (RM_SERVICE_ERROR_SERVICE_TRANSACTION_DOES_NOT_EXIST);\r
+        retVal = RM_SERVICE_ERROR_SERVICE_TRANSACTION_DOES_NOT_EXIST;\r
     }\r
     else\r
     {\r
         /* Delete the transaction */\r
-        if ((prevTransaction == NULL) && transaction->nextTransaction)\r
+        if (prevTransaction == NULL)\r
         {\r
             /* Transaction to be deleted exists at start of transaction queue.  Map second\r
              * transaction to be start of transaction queue as long as there are more than\r
-             * one transactions */\r
+             * one transactions. */\r
             rmInst->transactionQueue = transaction->nextTransaction;\r
         }\r
         else\r
@@ -205,183 +260,984 @@ int32_t Rm_transactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)
         }\r
 \r
         /* Free the memory associated with the transaction. */\r
-        Rm_osalFree((void *)transaction, sizeof(Rm_Transaction), false);\r
+        Rm_osalFree((void *)transaction, sizeof(Rm_Transaction));\r
     }\r
 \r
-    Rm_osalCsExit(key);\r
-    return (RM_SERVICE_ACTION_OKAY);\r
+    Rm_osalMtCsExit(key);\r
+    return (retVal);\r
+}\r
+\r
+uint32_t Rm_transactionInitSequenceNum(void)\r
+{\r
+    /* Sequence number can never have a value of zero so that there are no conflicts\r
+     * with transactions that have a remoteOriginatingId of zero */\r
+    return (1);\r
 }\r
 \r
 uint32_t Rm_transactionGetSequenceNum(Rm_Inst *rmInst)\r
 {\r
     uint32_t sequenceNum = 0;\r
+\r
+    /* Get the next sequence number and then increment.  If there's an overflow\r
+     * assign the initial value instead of incrementing. */\r
+    if (rmInst->transactionSeqNum + 1 < rmInst->transactionSeqNum)\r
+    {\r
+        /* Overflow */\r
+        sequenceNum = rmInst->transactionSeqNum;\r
+        rmInst->transactionSeqNum = Rm_transactionInitSequenceNum();\r
+    }\r
+    else\r
+    {\r
+        sequenceNum = rmInst->transactionSeqNum++;\r
+    }    \r
+\r
+    return (sequenceNum);\r
+}\r
+\r
+Rm_Allocator *Rm_allocatorAdd(Rm_Inst *rmInst, const char *resourceName)\r
+{\r
+    Rm_Allocator *allocators = (Rm_Allocator *)rmInst->allocators;\r
+    Rm_Allocator *newAllocator = NULL;\r
     void *key;\r
 \r
-    /* Lock access to the RM instance */\r
-    key = Rm_osalCsEnter();\r
+    /* Lock access to the RM instance's allocator list */\r
+    key = Rm_osalMtCsEnter();\r
 \r
-    /* Get the next sequence number and then incement.  Overflow is okay since\r
-     * it just restarts the sequence number count. */\r
-    sequenceNum = rmInst->transactionSeqNum++;\r
+    /* Get memory for a new allocator from local memory */\r
+    newAllocator = Rm_osalMalloc(sizeof(Rm_Allocator));\r
 \r
-    Rm_osalCsExit(key);\r
-    return (sequenceNum);\r
+    /* Return if the memory allocated for the allocator is NULL */\r
+    if (newAllocator != NULL)\r
+    {\r
+        /* Clear the allocator */\r
+        memset((void *)newAllocator, 0, sizeof(Rm_Allocator));\r
+\r
+        /* Populate the allocator */\r
+        strcpy(newAllocator->resourceName, resourceName);\r
+        /* allocator's root entry will be created by the invoking function */\r
+        newAllocator->allocatorRootEntry = NULL;\r
+        /* New allocator's nextAllocator pointer will always be NULL */\r
+        newAllocator->nextAllocator = NULL;  \r
+\r
+        /* Check if there are any allocators in the allocator list */\r
+        if (allocators)\r
+        {\r
+            /* At least one allocator in the allocator list.  Add the new allocator to the \r
+             * end of the allocator list */\r
+            while (allocators->nextAllocator != NULL)\r
+            {\r
+                /* Traverse the list until arriving at the last allocator */\r
+                allocators = allocators->nextAllocator;\r
+            }\r
+\r
+            /* Add the new allocator to the end of the list */\r
+            allocators->nextAllocator = newAllocator;\r
+        }\r
+        else\r
+        {\r
+            /* The allocator list does not currently exist.  The new allocator is the \r
+             * first allocator */\r
+            rmInst->allocators = newAllocator;\r
+        }\r
+    }\r
+\r
+    Rm_osalMtCsExit(key);\r
+    return (newAllocator);\r
 }\r
 \r
-/* Function used to send RM response transactions to lower level agents */\r
-void Rm_transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction,\r
-                              Rm_TransactionReceipt *receipt)\r
+Rm_Allocator *Rm_allocatorFind(Rm_Inst *rmInst, char *resourceName)\r
 {\r
-    Rm_TransportNode *dstTransportNode = NULL;\r
-    Rm_Packet *rmPkt = NULL;\r
+    Rm_Allocator *allocator = (Rm_Allocator *)rmInst->allocators;\r
 \r
-    /* Find the transport for the RM instance that sent the request. */\r
-    dstTransportNode = Rm_transportNodeFindRemoteName(rmInst, transaction->sourceInstName);\r
+    /* Make sure there is at least one allocator in the allocator list */\r
+    if (allocator != NULL)\r
+    {\r
+        /* Find the resource name within the allocator list.  If the end of the\r
+         * allocator list is reached without finding the resource name the \r
+         * allocator pointer will be NULL */\r
+        while (allocator != NULL)\r
+        {\r
+            if (strcmp(allocator->resourceName, resourceName) == 0)\r
+            {\r
+                /* Match: break out of loop and return the allocator */\r
+                break;             \r
+            }\r
+            allocator = allocator->nextAllocator;\r
+        }\r
+    }\r
 \r
-    /* Create a RM packet using the service information */\r
-    switch (transaction->type)\r
+    return (allocator);\r
+}\r
+\r
+int32_t Rm_allocatorDelete(Rm_Inst *rmInst, char *resourceName)\r
+{\r
+    Rm_Allocator *allocator = (Rm_Allocator *) rmInst->allocators;\r
+    Rm_Allocator *prevAllocator = NULL;\r
+    int32_t retVal = RM_SERVICE_STATE_OKAY;\r
+    void *key;\r
+\r
+    /* Lock access to the RM instance's allocator list */\r
+    key = Rm_osalMtCsEnter();\r
+\r
+    /* Find the resource within the specified RM instance's allocator list. */\r
+    while (allocator != NULL)\r
     {\r
-        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_transportCreateResourceResponsePkt(rmInst, dstTransportNode, \r
-                                                          transaction, receipt);\r
-            break;\r
-        case Rm_service_RESOURCE_MAP_TO_NAME:\r
-        case Rm_service_RESOURCE_UNMAP_NAME:\r
-            rmPkt = Rm_transportCreateNsResponsePkt(rmInst, dstTransportNode,\r
-                                                    transaction, receipt);\r
-            break;\r
-        default:\r
-            /* Invalid service type.  Flag the error and return */\r
-            receipt->serviceResult = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
-            break;\r
+        if (strcmp(allocator->resourceName, resourceName) == 0)\r
+        {\r
+            /* Match: break out of loop and delete the transaction */\r
+            break;             \r
+        }\r
+\r
+        prevAllocator = allocator;\r
+        allocator = allocator->nextAllocator;\r
     }\r
 \r
-    if (receipt->serviceResult <= RM_SERVICE_ERROR_BASE)\r
+    /* Traversed entire list but did not find allocator. */\r
+    if (allocator == NULL)\r
     {\r
-        /* Delete the transaction and return immediately because an error occurred \r
-         * allocating the packet */\r
-        Rm_transactionQueueDelete(rmInst, transaction->id);\r
-        return;\r
+        retVal = -22; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
     }\r
+    else\r
+    {\r
+        /* Delete the allocator */\r
+        if (prevAllocator == NULL)\r
+        {\r
+            /* Allocator to be deleted exists at start of allocator list.  Map second\r
+             * allocator to be start of allocator list as long as there are more than\r
+             * one allocators. */\r
+            rmInst->allocators = allocator->nextAllocator;\r
+        }\r
+        else\r
+        {\r
+            /* Allocator to be deleted is in the middle or at end of the list.  Adjust \r
+             * adjacent allocator pointers.  This covers the case where the allocator to be \r
+             * removed is at the end of the list. */\r
+            prevAllocator->nextAllocator = allocator->nextAllocator;\r
+        }\r
 \r
-    /* Send the RM packet to the application transport */\r
-    if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt) < RM_TRANSPORT_SUCCESSFUL)\r
+        /* Free the memory associated with the allocator. */\r
+        Rm_osalFree((void *)allocator, sizeof(Rm_Allocator));\r
+    }\r
+\r
+    Rm_osalMtCsExit(key);\r
+    return (retVal);\r
+}\r
+\r
+int32_t Rm_createTreeAllocator(Rm_Inst *rmInst, const char *resourceName, Rm_ResourceRange *range)\r
+{\r
+    Rm_Allocator *allocator = NULL;\r
+    Rm_ResourceTree *treeRootEntry = NULL;\r
+    Rm_ResourceTreeNode *treeNode = NULL;\r
+    Rm_ResourceTreeNode *collidingNode = NULL;\r
+\r
+    /* Create the new base integer allocator */\r
+    allocator = Rm_allocatorAdd(rmInst, resourceName);\r
+\r
+    /* Create the tree root entry and initialize it */\r
+    treeRootEntry = Rm_osalMalloc(sizeof(Rm_ResourceTree));\r
+    RB_INIT(treeRootEntry);\r
+\r
+    /* Create a node in the tree for resource range and insert them into the tree. */\r
+    while (range != NULL)\r
     {\r
-        /* Negative value returned by transport send.  An error occurred\r
-         * in the transport while attempting to send the packet.*/\r
-        receipt->serviceResult = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
-        /* Clean up the packet */\r
-        if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt))\r
+        treeNode = Rm_newResourceTreeNode(range->base, range->length, RM_NOT_ALLOCATED_STRING);\r
+\r
+        /* Insert the node into the tree */\r
+        collidingNode = RB_INSERT(_Rm_ResourceTree, treeRootEntry, treeNode);\r
+\r
+        if (collidingNode)\r
         {\r
-            /* Non-NULL value returned by transport packet free. Flag the\r
-             * error */\r
-             receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
+            Rm_ResourceTreeNode *nextNode = NULL;\r
+            \r
+            /* Node that was inserted colliding with an existing node.  Clean up the tree\r
+             * that's been allocated thus far and return an error since there should be no\r
+             * collisions */\r
+            for (treeNode = RB_MIN(_Rm_ResourceTree, treeRootEntry); treeNode != NULL; treeNode = nextNode)\r
+            {\r
+                       nextNode = RB_NEXT(_Rm_ResourceTree, treeRootEntry, treeNode);\r
+                       RB_REMOVE(_Rm_ResourceTree, treeRootEntry, nextNode);\r
+                Rm_freeResourceTreeNode(treeNode);\r
+               }\r
+            /* Delete the tree root entry and the allocator */\r
+            Rm_osalFree((void *)treeRootEntry, sizeof(Rm_ResourceTree));\r
+            Rm_allocatorDelete(rmInst, allocator->resourceName);\r
+            return (-24); /* TODO FIX RETURN */\r
         }\r
-        return;\r
+\r
+        range = range->nextRange;\r
     }\r
 \r
-    /* Fill out the receipt information and delete the transaction */\r
-    receipt->serviceResult = transaction->details;\r
-    Rm_transactionQueueDelete(rmInst, transaction->id);\r
+    /* Assign the tree's root to the allocator */\r
+    allocator->allocatorRootEntry = treeRootEntry;\r
+\r
+    return(0);   /* TODO: FIX THIS RETURN */\r
 }\r
 \r
-void Rm_allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction,\r
-                           Rm_TransactionReceipt *receipt)\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
-    if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\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
+    /* Find the tree node that contains the first value in the specified policy range. */\r
+    if (opInfo->policyBase)\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
+        findNode.base = opInfo->policyBase;\r
+    }\r
+    else\r
+    {\r
+        matchingNode = RB_MIN(_Rm_ResourceTree, allocator->allocatorRootEntry);\r
+        findNode.base = matchingNode->base;\r
+    }\r
+    \r
+    findNode.length = 1;\r
+    matchingNode = RB_FIND(_Rm_ResourceTree, allocator->allocatorRootEntry, &findNode);\r
 \r
-        if (policy check approves the resource)\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
-            /* call the allocator to allocate the resource */\r
-            if (allocator returns resource)\r
+            /* Is the matchingNode free? */\r
+            if (strcmp(matchingNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0)\r
             {\r
-                /* Populate the receipt with the allocated resources and the result */\r
-                receipt->serviceResult = approve reason;\r
-                receipt->serviceId = transaction->id;\r
-                return ...\r
+                uint32_t matchEnd = matchingNode->base + matchingNode->length - 1;\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
+                    {\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
+                    /* 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
+                }\r
+                else\r
+                {\r
+                    index = matchingNode->base;\r
+                }\r
             }\r
             else\r
             {\r
-                /* allocator ran out of resources, need to contact Server for more\r
-                 * resources */\r
-                Rm_resourcePoolModRequest(...);\r
+                /* Found a resource range that satisfies the request properties.  Break out of the\r
+                 * search loop */\r
+                break;\r
             }\r
         }\r
-        else if (policy check denies resource)\r
+\r
+        if (!resourceFound)\r
         {\r
-            /* Policy check denied resource. */\r
-            receipt->serviceResult = deny reason;\r
-            receipt->serviceId = transaction->id;\r
-            return ...\r
+            retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_ALLOCATED;\r
         }\r
-        else if (policy check says forward to Server for validation)\r
+    }\r
+    else\r
+    {\r
+        retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
+    }\r
+\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
+{\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
+    /* 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
+    if (matchingNode != NULL)\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
         {\r
-            /* Forward the transaction to the Server */\r
-            Rm_transactionForwarder(rmInst, transaction, receipt);\r
+            /* Handle node create, combine, deletion based on the request range if\r
+             * resources are available. */\r
+            if (strcmp(matchingNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0)\r
+            {\r
+                /* Handle case where the findNode range matches the matchingNode\r
+                 * range exactly.\r
+                 *\r
+                 * base0                                  base0+length0-1\r
+                 *   |<---------------length0------------------->|  => existing node\r
+                 *   |<---------------length1------------------->|  => requested resources\r
+                 * base1                                  base1+length1-1\r
+                 */    \r
+                if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd))\r
+                {\r
+                    /* Can reserve matchingNode's resources in-place */\r
+                    strcpy(matchingNode->allocatedTo, opInfo->srcInstName);\r
+                }\r
+                /* Handle case where the findNode range is a subset of the matchingNode\r
+                 * range and neither of the boundaries of the two ranges are equivalent.\r
+                 *\r
+                 * base0                                  base0+length0-1\r
+                 *   |<---------------length0------------------->|  => existing node\r
+                 *         |<---------length1---------->|  => requested resources\r
+                 *       base1                   base1+length1-1\r
+                 */    \r
+                else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd))\r
+                {\r
+                    /* Split the matching node into three 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
+                    /* Remove the matching node from the tree for modification. */\r
+                    RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\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
+                    /* 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
+                    /* Base and length of matching node become the base and length of the\r
+                     * requested resources */\r
+                    matchingNode->base = findNode.base;                                    \r
+                    matchingNode->length = findNode.length;\r
+                    /* Reserve the resources */\r
+                    strcpy(matchingNode->allocatedTo, opInfo->srcInstName);\r
+\r
+                    /* Insert all the nodes */\r
+                    RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+                    RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+                    RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+                }\r
+                /* Handle cases where one of findNode range boundaries is equivalent to\r
+                 * one of the matchingNode range boundaries.\r
+                 *\r
+                 * base0                                  base0+length0-1\r
+                 *   |<---------------length0------------------->|  => existing node\r
+                 *   |<---------length1---------->|  => requested resources\r
+                 * base1                   base1+length1-1\r
+                 *\r
+                 * OR\r
+                 *\r
+                 * base0                                  base0+length0-1\r
+                 *   |<---------------length0------------------->|  => existing node\r
+                 *                  |<---------length1---------->|  => requested resources\r
+                 *                base1                   base1+length1-1                 \r
+                 */    \r
+                else\r
+                {     \r
+                    /* Remove the matchingNode from the tree since it will be edited */\r
+                    RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+                    \r
+                    if (findNode.base == matchingNode->base)\r
+                    {\r
+                        /* There may be a combine possibility to the left. Extract leftNode to check */\r
+                        leftNode = RB_PREV(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+                        \r
+                        /* Can the node to the left of the matchingNode be combined with the \r
+                         * findNode's range? */\r
+                        if (leftNode && (strcmp(leftNode->allocatedTo, opInfo->srcInstName) == 0))\r
+                        {\r
+                            /* Remove the leftNode from the tree for editing */\r
+                            RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+\r
+                            /* Combine the leftNode and the findNode */\r
+                            leftNode->length += findNode.length;\r
+                        }\r
+                        else\r
+                        {\r
+                            /* Allocate a new leftNode that will take the place of the findNode\r
+                             * range in tree. */\r
+                            leftNode = Rm_newResourceTreeNode(findNode.base, findNode.length,\r
+                                                              opInfo->srcInstName);\r
+                        }\r
+\r
+                        /* Account for the leftNode in the matchingNode */\r
+                        matchingNode->base = findNode.base + findNode.length;\r
+                        matchingNode->length = matchingEnd - findEnd;  \r
+\r
+                        /* Insert the left node */\r
+                        RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+                    }\r
+                    else if (findEnd == matchingEnd)\r
+                    {\r
+                        /* There may be a combine possibility to the right. Extract rightNode to check */\r
+                        rightNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+                        \r
+                        /* Can the node to the right of the matchingNode be combined with the \r
+                         * findNode's range? */\r
+                        if (rightNode && (strcmp(rightNode->allocatedTo, opInfo->srcInstName) == 0))\r
+                        {\r
+                            /* Remove the rightNode from the tree for editing */\r
+                            RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+\r
+                            /* Combine the rightNode and the findNode */\r
+                            rightNode->base = findNode.base;\r
+                            rightNode->length += findNode.length;\r
+                        }\r
+                        else\r
+                        {\r
+                            /* Allocate a new rightNode that will take the place of the findNode\r
+                             * range in tree. */\r
+                            rightNode = Rm_newResourceTreeNode(findNode.base, findNode.length,\r
+                                                               opInfo->srcInstName);\r
+                        }\r
+\r
+                        /* Account for the rightNode in the matchingNode */\r
+                        matchingNode->length -= findNode.length;  \r
+\r
+                        /* Insert the right node */\r
+                        RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+                    }\r
+\r
+                    /* Reinsert the edited matching node */\r
+                    RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+                }\r
+                \r
+                retVal = RM_SERVICE_APPROVED_AND_COMPLETED;\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
+            }\r
+        }\r
+        else\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
+        }\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
+}\r
+\r
+/* Assume policy has already approved of the free */\r
+int32_t Rm_treeFree(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\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
+\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
+    if (matchingNode != NULL)\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
+\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
+                    leftNode = RB_PREV(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+                    rightNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\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
+\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
+                        RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\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
+                        RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+                        combineRight = TRUE;\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
+\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
+                    {\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
+                    /* 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 if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd))\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
+                    /* Remove matching node for editing. */\r
+                    RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\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
+                    /* 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
+                    /* Insert the left and right nodes into the tree. */\r
+                    RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+                    RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+\r
+                    /* Base and length of matching node become 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
+                else\r
+                {\r
+                    /* Remove the matchingNode from the tree since it will be edited */\r
+                    RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+                    \r
+                    if (findNode.base == matchingNode->base)\r
+                    {\r
+                        /* Case 3: Free range is on left boundary of matched node. Try to \r
+                         *         combine the free range with the left node if free.\r
+                         *\r
+                         * |<---left node (free)--->||<----------matched node---------->|\r
+                         *                           |<---findNode (free req)--->|\r
+                         */ \r
+                   \r
+                        /* There may be a combine possibility to the left. Extract leftNode to check */\r
+                        leftNode = RB_PREV(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+                        \r
+                        /* Can the node to the left of the matchingNode be combined with the \r
+                         * findNode's range? */\r
+                        if (leftNode && (strcmp(leftNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0))\r
+                        {\r
+                            /* Remove the leftNode from the tree for editing */\r
+                            RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+\r
+                            /* Combine the leftNode and the findNode */\r
+                            leftNode->length += findNode.length;\r
+                        }\r
+                        else\r
+                        {\r
+                            /* Allocate a new leftNode that will take the place of the findNode\r
+                             * range in tree. */\r
+                            leftNode = Rm_newResourceTreeNode(findNode.base, findNode.length,\r
+                                                              RM_NOT_ALLOCATED_STRING);\r
+                        }\r
+\r
+                        /* Account for the leftNode in the matchingNode */\r
+                        matchingNode->base = findNode.base + findNode.length;\r
+                        matchingNode->length = matchingEnd - findEnd;  \r
+\r
+                        /* Insert the left node */\r
+                        RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
+                    }\r
+                    else if (findEnd == matchingEnd)\r
+                    {\r
+                        /* Case 4: Free range is on right boundary of matched node. Try to \r
+                         *         combine the free range with the right node if free.\r
+                         *\r
+                         * |<----------matched node---------->||<---right node (free)--->|\r
+                         *        |<---findNode (free req)--->|\r
+                         */ \r
+                        \r
+                        /* There may be a combine possibility to the right. Extract rightNode to check */\r
+                        rightNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
+                        \r
+                        /* Can the node to the right of the matchingNode be combined with the \r
+                         * findNode's range? */\r
+                        if (rightNode && (strcmp(rightNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0))\r
+                        {\r
+                            /* Remove the rightNode from the tree for editing */\r
+                            RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+\r
+                            /* Combine the rightNode and the findNode */\r
+                            rightNode->base = findNode.base;\r
+                            rightNode->length += findNode.length;\r
+                        }\r
+                        else\r
+                        {\r
+                            /* Allocate a new rightNode that will take the place of the findNode\r
+                             * range in tree. */\r
+                            rightNode = Rm_newResourceTreeNode(findNode.base, findNode.length,\r
+                                                               RM_NOT_ALLOCATED_STRING);\r
+                        }\r
+\r
+                        /* Account for the rightNode in the matchingNode */\r
+                        matchingNode->length -= findNode.length;  \r
+\r
+                        /* Insert the right node */\r
+                        RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
+                    }\r
+\r
+                    /* Reinsert the edited matching node */\r
+                    RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\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
+        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
+        }\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
+{\r
+    Rm_Allocator *allocator = NULL;\r
+    int32_t retVal;\r
+    void *key;\r
+\r
+    /* Lock access to the RM instance's transaction queue */\r
+    key = Rm_osalMtCsEnter();\r
+\r
+    /* Get the specified resource's allocator */\r
+    allocator = Rm_allocatorFind(rmInst, opInfo->resourceInfo->name);\r
+\r
+    if (allocator)\r
+    {\r
+        /* Call the allocator's function */\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
+    else\r
+    {\r
+        /* Allocator could not be found for resource */\r
+        retVal = RM_SERVICE_DENIED_RESOURCE_DOES_NOT_EXIST;\r
+    }\r
+\r
+    Rm_osalMtCsExit(key);\r
+    return(retVal);\r
+}\r
+\r
+void Rm_allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
+{\r
+    Rm_AllocatorOpInfo opInfo;\r
+    int32_t retVal = transaction->state;\r
+\r
+    /* Initialize the opInfo structure */\r
+    memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));\r
+    \r
+    if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
+    {\r
+        /* TEMP: For now forward all allocations to the RM Server */\r
+        Rm_transactionForwarder(rmInst, transaction);\r
+        \r
+#if 0  /* Policy psuedo-code.  Will be implemented after basic allocate functionality is ready and tested */   \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
+                    /* Populate the transaction with the allocated resources and the result */\r
+                    transaction->state = approve reason;\r
+                    return ...\r
+                }\r
+                else\r
+                {\r
+                    /* allocator ran out of resources, need to contact Server for more\r
+                     * resources */\r
+                    Rm_resourcePoolModRequest(...);\r
+                }\r
+            }\r
+            else if (policy check denies resource)\r
+            {\r
+                /* Policy check denied resource. */\r
+                transaction->state= deny reason;\r
+                return ...\r
+            }\r
+            else if (policy check says forward to Server for validation)\r
+            {\r
+                /* Forward the transaction to the Server */\r
+                Rm_transactionForwarder(rmInst, transaction);\r
+            }\r
         }\r
 #endif         \r
     }\r
     else if (rmInst->instType == Rm_instType_SERVER)\r
     {\r
-#if 0        \r
-        /* Check global policy to see if resource can be allocated. return result\r
-         * no matter what */\r
-        Rm_policy...API()\r
+        /* TEMP: If resource properties are unspecified allocate the next available.\r
+         *       If resource properties are specified allocate if they are available. */\r
 \r
-        if (policy approves)\r
+        /* Fill out the allocator operation general information */\r
+        opInfo.resourceInfo = &transaction->resourceInfo;\r
+        opInfo.srcInstName = transaction->sourceInstName;\r
+\r
+        if (strlen(transaction->resourceInfo.nsName) > 0)\r
         {\r
-            /* call allocator to allocate resource */\r
+            /* See if a NameServer name is being used to allocate a resource */\r
+            if (transaction->resourceInfo.base != 0)\r
+            {\r
+                /* A name and a value cannot be specified for the request.  It's one\r
+                 * or the other. */\r
+                retVal = RM_SERVICE_ERROR_NAMESERVER_NAME_AND_RESOURCE_RANGE_BOTH_DEFINED;\r
+            }\r
+            else\r
+            {\r
+                /* Get the resource information from the NameServer */\r
+                retVal = Rm_nsFindObject(rmInst, opInfo.resourceInfo);\r
+            }\r
         }\r
+        else if (transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED)\r
+        {\r
+            /* Execute the allocator pre-allocate operation to get the next available resources.\r
+             * NORMALLY CHECKED AGAINST THE POLICY */\r
+            opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE;\r
+                \r
+            if (transaction->resourceInfo.alignment == RM_RESOURCE_ALIGNMENT_UNSPECIFIED)\r
+            {   \r
+                /* TEMP: Default resource alignment of 1 if the resource alignment is not\r
+                 *       specified */\r
+                opInfo.policyAlignment = 1;\r
+            }\r
+            else\r
+            {\r
+                opInfo.policyAlignment = transaction->resourceInfo.alignment;\r
+            }\r
 \r
-        receipt->serviceResult = approve or deny reason;\r
-        receipt->serviceId = transaction->id;\r
-        receipt->resourceBase = ...;\r
-        receipt->resourceRange = ...;\r
+            /* opInfo.policyBase = comes from policy once implemented */\r
+            opInfo.policyLength = transaction->resourceInfo.length;\r
+\r
+            /* If the pre-allocate operation succeeds the resourceInfo field pointed to\r
+             * by opInfo will contain the next available resources taht satisfy the\r
+             * resource properties */\r
+            retVal = Rm_allocatorOperation(rmInst, &opInfo);\r
+        }\r
+\r
+        /* Call allocator as long as an error or denial hasn't occurred */\r
+        if (retVal == RM_SERVICE_PROCESSING)\r
+        {\r
+            opInfo.operation = Rm_allocatorOp_ALLOCATE;\r
+\r
+            retVal = Rm_allocatorOperation(rmInst, &opInfo);\r
+        }\r
+\r
+        transaction->state = retVal;\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.  Copy the allocation response resource data \r
-             * into the original transaction and send it back to the Client */\r
-            transaction->details = transaction->details;\r
-            transaction->resourceInfo.base = receipt->resourceBase;\r
-            transaction->resourceInfo.range = receipt->resourceRange;\r
-            Rm_transactionResponder(rmInst, transaction, receipt);\r
+            /* Source of allocation was not the server instance, provide the transaction\r
+             * to the transaction responder */\r
+            Rm_transactionResponder(rmInst, transaction);\r
+        }\r
+        /* Otherwise let the return stack return the transaction to the serviceHandler */           \r
+\r
+#if 0  /* Policy psuedo-code.  Will be implemented after basic allocate functionality is ready and tested */        \r
+        if (resourceBase is unspecified)\r
+        {\r
+           while (policy does not approve)\r
+           {\r
+               Rm_policy check get allowed base as starting point for prealloc\r
+               preallocate resource based on the range and alignment\r
+               Rm_policy...check\r
+           }\r
         }\r
         else\r
         {\r
-            /* Resource allocation request originated locally on the active\r
-             * instance. Send the response via the service responder. */\r
-            transaction->details = transaction->details;\r
-            transaction->resourceInfo.base = receipt->resourceBase;\r
-            transaction->resourceInfo.range = receipt->resourceRange;             \r
-            Rm_serviceResponder(rmInst, transaction, NULL, receipt);                            \r
+            /* Check global policy to see if resource can be allocated. return result\r
+             * no matter what */\r
+            Rm_policy...API()\r
+\r
+            if (policy approves)\r
+            {\r
+                /* call allocator to allocate resource */\r
+            }\r
+\r
+            transaction->state = approve or deny reason;\r
+            transaction->resourceInfo.base = ...;\r
+            transaction->resourceInfo.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
+            {\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
-void Rm_freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction,\r
-                     Rm_TransactionReceipt *receipt)\r
+void Rm_freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
 {\r
+    Rm_AllocatorOpInfo opInfo;\r
+    int32_t retVal = transaction->state;\r
+    \r
     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
     {\r
-#if 0        \r
+        /* TEMP: Forward all free requests to the Server */\r
+        Rm_transactionForwarder(rmInst, transaction);\r
+        \r
+#if 0  /* Policy psuedo-code.  Will be implemented after basic allocate functionality is ready and tested */      \r
         /* Check local policy to see if the request can be satisfied with the\r
          * resources stored locally */\r
-         Rm_policy...API()\r
+        Rm_policy...API()\r
 \r
         if (policy check approves the free)\r
         {\r
@@ -397,28 +1253,66 @@ void Rm_freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction,
             else\r
             {\r
                 /* Populate the receipt with the freed resources and the result */\r
-                receipt->serviceResult = approve reason;\r
-                receipt->serviceId = transaction->id;\r
+                transaction->state = approve reason;\r
                 return ...\r
             }\r
         }\r
         else if (policy check denies resource free)\r
         {\r
             /* Policy check denied resource. */\r
-            receipt->serviceResult = deny reason;\r
-            receipt->serviceId = transaction->id;\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, receipt);\r
+            Rm_transactionForwarder(rmInst, transaction);\r
         }\r
 #endif         \r
     }\r
     else if (rmInst->instType == Rm_instType_SERVER)\r
     {\r
-#if 0        \r
+        /* TEMP: Free the resources if resources are allocated to the source instance. */\r
+\r
+        /* Fill out the allocator operation general information */\r
+        opInfo.resourceInfo = &transaction->resourceInfo;\r
+        opInfo.srcInstName = transaction->sourceInstName;\r
+\r
+        if (strlen(transaction->resourceInfo.nsName) > 0)\r
+        {\r
+            /* See if a NameServer name is being used to allocate a resource */\r
+            if (transaction->resourceInfo.base != 0)\r
+            {\r
+                /* A name and a value cannot be specified for the request.  It's one\r
+                 * or the other. */\r
+                retVal = RM_SERVICE_ERROR_NAMESERVER_NAME_AND_RESOURCE_RANGE_BOTH_DEFINED;\r
+            }\r
+            else\r
+            {\r
+                /* Get the resource information from the NameServer */\r
+                retVal = Rm_nsFindObject(rmInst, opInfo.resourceInfo);\r
+            }\r
+        }\r
+        \r
+        /* Call allocator as long as an error or denial hasn't occurred */\r
+        if (retVal == RM_SERVICE_PROCESSING)\r
+        {\r
+            opInfo.operation = Rm_allocatorOp_FREE;\r
+\r
+            retVal = Rm_allocatorOperation(rmInst, &opInfo);\r
+        }\r
+\r
+        transaction->state = retVal;\r
+\r
+        if (strcmp(transaction->sourceInstName, rmInst->name))\r
+        {\r
+            /* Source of allocation was not the server instance, provide the transaction\r
+             * to the transaction responder */\r
+            Rm_transactionResponder(rmInst, transaction);\r
+        }\r
+        /* Otherwise let the return stack return the transaction to the serviceHandler */  \r
+        \r
+#if 0  /* Policy psuedo-code.  Will be implemented after basic allocate functionality is ready and tested */ \r
         /* Check global policy to see if resource can be freed. return result\r
          * no matter what */\r
         Rm_policy...API()\r
@@ -427,39 +1321,91 @@ void Rm_freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction,
             /* call allocator to free resources */\r
         }\r
             \r
-        receipt->serviceResult = approve or deny reason;\r
-        receipt->serviceId = transaction->id;\r
-        receipt->resourceBase = ...;\r
-        receipt->resourceRange = ...;\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
+        {\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
+/* Function used to send RM response transactions to lower level agents */\r
+void Rm_transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
+{\r
+    Rm_TransportNode *dstTransportNode = NULL;\r
+    Rm_Packet *rmPkt = NULL;\r
+\r
+    /* Find the transport for the RM instance that sent the request. */\r
+    dstTransportNode = Rm_transportNodeFindRemoteName(rmInst, transaction->sourceInstName);\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_FREE:\r
+        case Rm_service_RESOURCE_GET_BY_NAME:\r
+            rmPkt = Rm_transportCreateResourceResponsePkt(rmInst, dstTransportNode, \r
+                                                          transaction);\r
+            break;\r
+        case Rm_service_RESOURCE_MAP_TO_NAME:\r
+        case Rm_service_RESOURCE_UNMAP_NAME:\r
+            rmPkt = Rm_transportCreateNsResponsePkt(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
+    {\r
+        /* Delete the transaction and return immediately because an error occurred \r
+         * allocating the packet */\r
+        Rm_transactionQueueDelete(rmInst, transaction->localId);\r
+        return;\r
+    }\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.  Copy the free response resource data \r
-             * into the original transaction and send it back to the Client Delegate or Client */\r
-            transaction->details = transaction->details;\r
-            transaction->resourceInfo.base = receipt->resourceBase;\r
-            transaction->resourceInfo.range = receipt->resourceRange;\r
-            Rm_transactionResponder(rmInst, transaction, receipt);\r
-        }\r
-        else\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
-            /* Resource allocation request originated locally on the active\r
-             * instance. Send the response via the service responder. */\r
-            transaction->details = transaction->details;\r
-            transaction->resourceInfo.base = receipt->resourceBase;\r
-            transaction->resourceInfo.range = receipt->resourceRange;\r
-            Rm_serviceResponder(rmInst, transaction, NULL, receipt);                            \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
-#endif        \r
-    }   \r
+        return;\r
+    }\r
+\r
+    /* NEED TO DO SOMETHING IF GET AN ERROR IN THE transaction->state FIELD.  CREATE\r
+     * NEW TRANSACTION WITH DATA FROM ORIGINAL?  THEN TRY TO SEND FAILED REQUEST BACK\r
+     * TO REQUESTER???  KEEP RETRYING SEND OF RESPONSE??? */\r
+\r
+    /* Delete the transaction */\r
+    Rm_transactionQueueDelete(rmInst, transaction->localId);\r
 }\r
 \r
 /* Function used to forward RM transactions to higher level agents */\r
-void Rm_transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction,\r
-                              Rm_TransactionReceipt *receipt)\r
+void Rm_transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
 {\r
     Rm_TransportNode *dstTransportNode = NULL;\r
     Rm_Packet *rmPkt = NULL;\r
@@ -467,7 +1413,7 @@ void Rm_transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction,
     /* Make sure the RM instance has a transport registered with a higher level agent */\r
     if (rmInst->registeredWithDelegateOrServer == false)\r
     {\r
-        receipt->serviceResult = RM_SERVICE_ERROR_NOT_REGISTERED_WITH_DEL_OR_SERVER;\r
+        transaction->state = RM_SERVICE_ERROR_NOT_REGISTERED_WITH_DEL_OR_SERVER;\r
         return;\r
     }\r
 \r
@@ -477,6 +1423,12 @@ void Rm_transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction,
     if (rmInst->instType == Rm_instType_CLIENT)\r
     {\r
         dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_CLIENT_DELEGATE);\r
+\r
+        if (!dstTransportNode)\r
+        {\r
+            /* No Client Delegate connection found.  Check for a Server connection */\r
+            dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_SERVER);\r
+        }\r
     } \r
     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
     {\r
@@ -487,132 +1439,84 @@ void Rm_transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction,
     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
+        case Rm_service_RESOURCE_GET_BY_NAME:\r
             rmPkt = Rm_transportCreateResourceReqPkt(rmInst, dstTransportNode, \r
-                                                     transaction, receipt);\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, receipt);\r
+                                                   transaction);\r
             break;\r
         default:\r
             /* Invalid service type.  Flag the error and return */\r
-            receipt->serviceResult = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
+            transaction->state = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
             break;\r
     }\r
 \r
-    if (receipt->serviceResult <= RM_SERVICE_ERROR_BASE)\r
+    if (transaction->state <= RM_SERVICE_ERROR_BASE)\r
     {\r
         /* Return immediately because an error occurred allocating the packet */\r
         return;\r
     }\r
 \r
-    /* Switch the queued transaction to the awaiting response state */\r
-    transaction->state = Rm_transactionState_AWAITING_RESPONSE;\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
-        receipt->serviceResult = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\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
-             receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
+            transaction->state = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
         }\r
         return;\r
     }\r
 \r
-    /* Inform requesting component that the service is being forwarded to a higher lever\r
-     * RM agent for processing.  The result of the service will be provided to the \r
-     * component via the specified callback function */\r
-    receipt->serviceResult = RM_SERVICE_PROCESSING;\r
-    receipt->serviceId = transaction->id;\r
+    /* Transaction is not deleted because it is awaiting a response from the higher level\r
+     * RM instance */\r
 }\r
 \r
-void Rm_transactionProcessor (Rm_Inst *rmInst, Rm_Transaction *transaction, \r
-                              Rm_TransactionReceipt *receipt)\r
+void Rm_transactionProcessor (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
 {\r
-    Rm_Transaction *queuedTransaction = NULL;\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 new transaction's ID matches any transactions waiting for\r
-         * responses.  A transaction received as a response will have an ID that \r
-         * matches the transaction that originated the request packet */\r
-        if (queuedTransaction = Rm_transactionQueueFind(rmInst, transaction->id))\r
+         ((transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) ||\r
+          (transaction->type == Rm_service_RESOURCE_GET_BY_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
-            if (queuedTransaction->state == Rm_transactionState_AWAITING_RESPONSE)\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
-                if (rmInst->instType == Rm_instType_CLIENT)\r
-                {\r
-                    /* Client found a transaction awaiting a response.  Pass both transactions\r
-                     * to the service responder for response processing */\r
-                    Rm_serviceResponder(rmInst, transaction, queuedTransaction, receipt);\r
-                }\r
-                else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
-                {\r
-                    /* Client Delegate found a NameServer transaction awaiting a response. Send the \r
-                     * response to either the transaction or service responder based on the \r
-                     * source instance */\r
-                    if (strcmp(queuedTransaction->sourceInstName, rmInst->name))\r
-                    {\r
-                        /* NameServer transaction originated from another instance.  Use the \r
-                         * transaction responder to send the NameServer result to the source instance.\r
-                         * Need to transfer the NameServer result details to the request transaction \r
-                         * which will be reused for the response. */\r
-                        queuedTransaction->details = transaction->details;\r
-                        Rm_transactionResponder(rmInst, queuedTransaction, receipt);\r
-                        /* Delete the response transaction */\r
-                        Rm_transactionQueueDelete(rmInst, transaction->id);                        \r
-                    }\r
-                    else\r
-                    {\r
-                        /* NameServer request originated on the Client Delegate instance.  Send to the\r
-                         * service responder */\r
-                        Rm_serviceResponder(rmInst, transaction, queuedTransaction,\r
-                                            receipt);\r
-                    }\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
-                /* Request transaction was not in the awaiting response state.  Flag the\r
-                 * error in the receipt and return */\r
-                receipt->serviceResult = RM_SERVICE_ERROR_INVALID_REQUEST_TRANSACTION_STATE_UPON_RESPONSE;\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.  Make sure the transaction is not a \r
-             * response transaction sent to the wrong RM instance */\r
-            if ((transaction->state == Rm_transactionState_RESOURCE_APPROVED) ||\r
-                (transaction->state == Rm_transactionState_RESOURCE_DENIED))\r
-            {\r
-                /* No matching request transaction.  This transaction result was sent to the\r
-                 * wrong RM instance.  Flag the error in the receipt and return */\r
-                receipt->serviceResult = RM_SERVICE_ERROR_INVALID_TRANSACTION_RECEIVED_ON_CLIENT;\r
-            }\r
-            else\r
-            {\r
-                /* All service requests on Clients are forwarded to the higher level RM Client \r
-                 * Delegate.  NameServer requests on Client Delegates are forwarded to the Server. */\r
-                Rm_transactionForwarder(rmInst, transaction, receipt);\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
@@ -621,177 +1525,542 @@ void Rm_transactionProcessor (Rm_Inst *rmInst, Rm_Transaction *transaction,
         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
-                /* Run the transaction through the response handler to take care of any\r
-                 * transactions that are responses to sent allocation requests. */\r
-                if (queuedTransaction = Rm_transactionQueueFind(rmInst, transaction->id))\r
+            case Rm_service_RESOURCE_FREE:               \r
+                /* Check if the transaction is fulfilled request */\r
+                if (transaction->state != RM_SERVICE_PROCESSING)\r
                 {\r
-                    if (queuedTransaction->state == Rm_transactionState_AWAITING_RESPONSE)\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
-                        /* 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(queuedTransaction->sourceInstName, rmInst->name))\r
-                        {\r
-                            /* Names don't match.  Copy the allocation response resource data \r
-                             * into the original transaction and send it back to the Client */\r
-                            queuedTransaction->details = transaction->details;\r
-                            memcpy ((void *)&(queuedTransaction->resourceInfo), \r
-                                    (void *)&(transaction->resourceInfo), sizeof(Rm_ResourceInfo));\r
-                            Rm_transactionResponder(rmInst, queuedTransaction, receipt);\r
-                            /* Delete the response transaction */\r
-                            Rm_transactionQueueDelete(rmInst, transaction->id);\r
-                        }\r
-                        else\r
-                        {\r
-                            /* Resource allocation request originated locally on Client Delegate\r
-                             * instance. Send the response via the service responder. */\r
-                            Rm_serviceResponder(rmInst, transaction, queuedTransaction,\r
-                                                receipt);                            \r
-                        }\r
+                        Rm_transactionResponder(rmInst, transaction);\r
                     }\r
                     else\r
                     {\r
-                        /* Request transaction was not in the awaiting response state.  Flag the\r
-                         * error in the receipt and return */\r
-                        receipt->serviceResult = RM_SERVICE_ERROR_INVALID_REQUEST_TRANSACTION_STATE_UPON_RESPONSE;\r
+                        /* Resource allocation request originated locally.  Send the response\r
+                         * via the service responder. */\r
+                        Rm_serviceResponder(rmInst, transaction);      \r
                     }\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 handler to see if the resource\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
-                     Rm_allocationHandler(rmInst, transaction, receipt);\r
+                    if (transaction->type == Rm_service_RESOURCE_ALLOCATE)\r
+                    {\r
+                        Rm_allocationHandler(rmInst, transaction);\r
+                    }\r
+                    else\r
+                    {\r
+                        Rm_freeHandler(rmInst, transaction);\r
+                    }\r
                 }\r
                 break;\r
-            case Rm_service_RESOURCE_FREE:\r
-            case Rm_service_RESOURCE_BLOCK_FREE:\r
-            case Rm_service_RESOURCE_FREE_BY_NAME:\r
-                /* Run the transaction through the response handler to take care of any\r
-                 * transactions that are responses to sent free requests. */\r
-                if (queuedTransaction = Rm_transactionQueueFind(rmInst, transaction->id))\r
+            case Rm_service_RESOURCE_MAP_TO_NAME:\r
+            case Rm_service_RESOURCE_GET_BY_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 (queuedTransaction->state == Rm_transactionState_AWAITING_RESPONSE)\r
+                    if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME)\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(queuedTransaction->sourceInstName, rmInst->name))\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) == RM_NS_ACTION_APPROVED)\r
                         {\r
-                            /* Names don't match.  Copy the free response resource data \r
-                             * into the original transaction and send it back to the Client */\r
-                            queuedTransaction->details = transaction->details;\r
-                            memcpy ((void *)&(queuedTransaction->resourceInfo), \r
-                                    (void *)&(transaction->resourceInfo), sizeof(Rm_ResourceInfo));\r
-                            Rm_transactionResponder(rmInst, queuedTransaction, receipt);\r
-                            /* Delete the response transaction */\r
-                            Rm_transactionQueueDelete(rmInst, transaction->id);\r
+                            transaction->state = RM_SERVICE_APPROVED_AND_COMPLETED;\r
                         }\r
                         else\r
                         {\r
-                            /* Resource free request originated locally on Client Delegate\r
-                             * instance. Send the response via the service responder. */\r
-                            Rm_serviceResponder(rmInst, transaction, queuedTransaction,\r
-                                                receipt);                            \r
+                            /* TEMP: UPDATE THIS STATE VALUE */\r
+                            transaction->state = RM_SERVICE_DENIED_BEGIN;\r
+                        }\r
+                    }\r
+                    else if (transaction->type == Rm_service_RESOURCE_GET_BY_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_nsFindObject(rmInst, &transaction->resourceInfo) == 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
-                        /* Request transaction was not in the awaiting response state.  Flag the\r
-                         * error in the receipt and return */\r
-                        receipt->serviceResult = RM_SERVICE_ERROR_INVALID_REQUEST_TRANSACTION_STATE_UPON_RESPONSE;\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) == \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
-                }\r
-                else\r
-                {\r
-                    /* This is a new transaction request originating from an RM instance with fewer\r
-                     * allocate/free privileges.  Run the 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
-                     Rm_freeHandler(rmInst, transaction, receipt);\r
-                }\r
-\r
-                break;\r
-            case Rm_service_RESOURCE_MAP_TO_NAME:\r
-                /* Server is the only RM instance capable of adding NameServer objects */\r
-                if (rmInst->instType == Rm_instType_SERVER)\r
-                {\r
-                    /* Create a new NameServer object with the request transaction information */\r
-                    Rm_nsAddObject(rmInst, transaction, receipt);\r
-\r
-                    /* Return the result of the NameServer addition to the RM instance\r
-                     * that requested it */\r
-                    transaction->details = receipt->serviceResult;\r
-\r
-                    /* If source instance name does not match the current instance\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 */\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, queuedTransaction, receipt);\r
-                    }\r
-                    else\r
-                    {\r
-                        /* NameServer addition request originated locally on Server\r
-                         * instance. Send the response via the service responder.  In this case\r
-                         * the request transaction will be passed as NULL since the request\r
-                         * is being reused as the response */\r
-                        Rm_serviceResponder(rmInst, transaction, NULL, receipt);                            \r
+                        Rm_transactionResponder(rmInst, transaction);\r
                     }\r
                 }\r
                 else\r
                 {\r
-                    receipt->serviceResult = RM_SERVICE_ERROR_NAMESERVER_OBJECT_CREATE_ON_INVALID_INSTANCE;\r
+                    transaction->state = RM_SERVICE_ERROR_NAMESERVER_OBJECT_MOD_ON_INVALID_INSTANCE;\r
                 }\r
                 break;\r
-            case Rm_service_RESOURCE_UNMAP_NAME:\r
-                /* Server is the only RM instance capable of deleting NameServer objects */\r
-                if (rmInst->instType == Rm_instType_SERVER)\r
-                {\r
-                    /* Delete an existing NameServer object with the request transaction information */\r
-                    Rm_nsDeleteObject(rmInst, transaction, receipt);\r
+        }\r
+    }\r
+}\r
 \r
-                    /* Return the result of the NameServer deletion to the RM instance\r
-                     * that requested it */\r
-                    transaction->details = receipt->serviceResult;\r
+int32_t Rm_reserveLinuxResource(Rm_Inst *rmInst, Rm_LinuxAlias *linuxAlias, \r
+                                Rm_LinuxValueRange *linuxValues, Rm_AllocatorOpInfo *opInfo)\r
+{\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 source instance name does not match the current 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 */\r
-                    if (strcmp(transaction->sourceInstName, rmInst->name))\r
+    while ((linuxValues != NULL) && (!baseFound || !lengthFound))\r
+    {\r
+        if (linuxAlias->baseOffset == valueIndex)\r
+        {\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
+                opInfo->resourceInfo->length = 1;\r
+                lengthFound = TRUE;\r
+            }\r
+        }\r
+        else if (linuxAlias->lengthOffset == valueIndex)\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
+        /* Allocate the resource to Linux */\r
+        retVal = Rm_allocatorOperation(rmInst, opInfo);\r
+    }\r
+\r
+    return (retVal);\r
+}\r
+\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
+    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
+    /* Set the source instance name for allocation to be the Linux Kernel */\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
+        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(pathOffset < linuxAlias->pathListLenBytes)\r
+        {\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 (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 FIND RESOURCE AT ALIAS PATH */\r
+                    break;\r
+                }\r
+            }\r
+            else\r
+            {\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
+           \r
+                /* Search the properties for the next alias path string */\r
+                while ((propOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) &&\r
+                       (pathOffset < linuxAlias->pathListLenBytes))\r
+                {\r
+                    propertyData = fdt_getprop_by_offset(linuxDtb, propOffset, \r
+                                                         &propertyName, &propertyLen);\r
+\r
+                    if (strcmp(linuxAlias->pathList + pathOffset, propertyName) == 0)\r
                     {\r
-                        Rm_transactionResponder(rmInst, queuedTransaction, receipt);\r
+                        pathOffset += (strlen(linuxAlias->pathList + pathOffset) + 1);\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
-                    else\r
-                    {\r
-                        /* NameServer delete request originated locally on Server\r
-                         * instance. Send the response via the service responder.  In this case\r
-                         * the request transaction will be passed as NULL since the request\r
-                         * is being reused as the response */\r
-                        Rm_serviceResponder(rmInst, transaction, NULL, receipt);                            \r
-                    }                    \r
-                }\r
-                else\r
+                    \r
+                    propOffset = fdt_next_property_offset(linuxDtb, propOffset);\r
+                } \r
+\r
+                if (propOffset < -FDT_ERR_NOTFOUND)\r
                 {\r
-                    receipt->serviceResult = RM_SERVICE_ERROR_NAMESERVER_OBJECT_DELETE_ON_INVALID_INSTANCE;\r
+                       /* Error was returned by LIBFDT when parsing the properties */\r
+                    retVal = propOffset;\r
+                    break;\r
                 }\r
-                break;\r
+            }\r
+        }\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
+\r
+    return (retVal);\r
+}\r
+\r
+int32_t Rm_createAndInitAllocator(Rm_Inst *rmInst, const char *resourceName, \r
+                                  Rm_ResourceProperties *resourceProperties, void *linuxDtb)\r
+{\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_ResourceInfo resourceInfo;\r
+    int32_t retVal = RM_DTB_UTIL_RESULT_OKAY;\r
+\r
+    if (resourceProperties->rangeData && (resourceProperties->rangeLen > 0))\r
+    {\r
+        /* Extract the resource properties from the DTB */\r
+        range = rangeBasePtr = Rm_resourceExtractRange(resourceProperties->rangeData, \r
+                                                       resourceProperties->rangeLen);\r
+\r
+        /* Create a tree allocator using the resource properties */\r
+        retVal = Rm_createTreeAllocator(rmInst, resourceName, range); \r
+\r
+        if (retVal >= RM_DTB_UTIL_RESULT_OKAY)\r
+        {\r
+            if (resourceProperties->linuxAliasData && resourceProperties->linuxAliasLen)\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
+        }\r
+    }\r
+    \r
+    if (retVal >= RM_DTB_UTIL_RESULT_OKAY)\r
+    {\r
+        /* Create entries in the NameServer if any NameServer assignments were specified */\r
+        if (resourceProperties->nsAssignData && resourceProperties->nsAssignLen)\r
+        {\r
+            nsAssignments = Rm_resourceExtractNsAssignment(resourceProperties->nsAssignData, \r
+                                                           resourceProperties->nsAssignLen);\r
+\r
+            /* Cycle through the list of assignments and add them to the NameServer */\r
+            nsAssignmentBasePtr = nsAssignments;\r
+            while (nsAssignments)\r
+            {\r
+                memset((void *)&resourceInfo, 0, sizeof(Rm_ResourceInfo));\r
+\r
+                resourceInfo.base = nsAssignments->resourceBase;\r
+                resourceInfo.length = nsAssignments->resourceLength;\r
+                strcpy(resourceInfo.nsName, nsAssignments->nsName);\r
+                \r
+                /* TODO: RETURN IF ANY OF THE ADDS FAIL??? */\r
+                Rm_nsAddObject(rmInst, &resourceInfo);\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_resourceFreeRange(rangeBasePtr);\r
+    Rm_resourceFreeLinuxAlias(linuxAlias);\r
+\r
+    return(retVal);\r
+}\r
+\r
+int32_t Rm_parseResourceProperty(void *globalResourceDtb, int32_t offset, Rm_ResourceProperties *propertyInfo)\r
+{\r
+       int32_t propertyLen;\r
+       const char *propertyName;\r
+       const void *propertyData;\r
+    Rm_ResourcePropType propertyType;\r
+    int32_t retVal = RM_DTB_UTIL_RESULT_OKAY;\r
+\r
+    /* Get the property data and store it in the corresponding propertyInfo field */\r
+       propertyData = fdt_getprop_by_offset(globalResourceDtb, offset, &propertyName, &propertyLen);\r
+    if (propertyData)\r
+    {\r
+        propertyType = Rm_resourceGetPropertyType(propertyName);\r
+        if (propertyType == Rm_resourcePropType_RESOURCE_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
+            }\r
+        }\r
+        else if (propertyType == Rm_resourcePropType_NSASSIGNMENT)\r
+        {\r
+            if (propertyInfo->nsAssignData || propertyInfo->nsAssignLen)\r
+            {\r
+                /* The nsAssign fields have already been populated.  Return an error.\r
+                 * The resource list has specified a property field more than once\r
+                 * for a resource node */\r
+                retVal = -19; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
+            }\r
+            else\r
+            {\r
+                propertyInfo->nsAssignData = propertyData;\r
+                propertyInfo->nsAssignLen = propertyLen;\r
+            }\r
+        }\r
+        else 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
+            retVal = -20; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
+        }\r
+    }\r
+    else\r
+    {\r
+        retVal = -16; /* TEMP ERROR: Can't conflict with LIBFDT errors */\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
+}\r
+\r
+int32_t Rm_parseResourceNode(Rm_Inst *rmInst, void *globalResourceDtb, int32_t nodeOffset, int32_t depth,\r
+                             void *linuxDtb)\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
+    /* Initialize the resource properties structure */\r
+    memset((void *)&resourceProperties, 0, sizeof(Rm_ResourceProperties));\r
+\r
+    /* Ignore properties of the base node */\r
+    if (strcmp(resourceName, rmDtbStartingNode))\r
+    {\r
+        /* Get the properties for the resource node if any exist */\r
+       offset = fdt_first_property_offset(globalResourceDtb, nodeOffset);\r
+       if (offset >= RM_DTB_UTIL_STARTING_NODE_OFFSET)\r
+       {\r
+            /* Since at least one property exists attempt to parse the property nodes and \r
+             * use them to create and initialize a resource allocator */\r
+               error =  Rm_parseResourceProperty(globalResourceDtb, offset, &resourceProperties);\r
+            if (error < -FDT_ERR_NOTFOUND)\r
+            {\r
+                return (error);\r
+            }\r
+            \r
+            /* Initialize an allocator with the resource properties if no error was returned */\r
+            Rm_createAndInitAllocator(rmInst, resourceName, &resourceProperties, 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
+    {\r
+        error = Rm_parseResourceNode(rmInst, globalResourceDtb, offset, depth, linuxDtb);\r
+        if (error < -FDT_ERR_NOTFOUND)\r
+        {\r
+            return (error);\r
         }\r
     }\r
+    else if (offset != -FDT_ERR_NOTFOUND)\r
+    {\r
+        /* Error was returned by LIBFDT when parsing the nodes */\r
+        return (offset);\r
+    }\r
+\r
+    return (RM_DTB_UTIL_RESULT_OKAY);\r
 }\r
 \r
+int32_t Rm_initializeAllocators(Rm_Inst *rmInst, void *globalResourceDtb, void *linuxDtb)\r
+{\r
+    int32_t nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;\r
+    int32_t startDepth = RM_DTB_UTIL_STARTING_DEPTH;\r
+    int32_t result = RM_DTB_UTIL_RESULT_OKAY;\r
+\r
+    /* Recursively parse the Global Resource List, creating an allocator for\r
+     * each resource as specified in the node */\r
+    result = Rm_parseResourceNode(rmInst, globalResourceDtb, nodeOffset, startDepth, linuxDtb);\r
+\r
+    return(result);\r
+}\r
+     \r
 /**********************************************************************\r
  ********************** Application visible APIs **********************\r
  **********************************************************************/\r
 \r
+/* Server Only */\r
+void Rm_printResourceStatus(Rm_Handle *rmHandle)\r
+{\r
+    Rm_Inst *rmInst = (Rm_Inst *) rmHandle;\r
+    Rm_Allocator *allocator = rmInst->allocators;\r
+    Rm_ResourceTree *treeRoot;\r
+    Rm_ResourceTreeNode *treeNode;\r
+    uint32_t numLinuxResources;\r
+\r
+    while (allocator != NULL)\r
+    {\r
+        numLinuxResources = 0;\r
+\r
+        Rm_osalLog("Resource: %s\n", allocator->resourceName);\r
+\r
+        treeRoot = allocator->allocatorRootEntry;\r
+\r
+        RB_FOREACH(treeNode, _Rm_ResourceTree, treeRoot)\r
+        {               \r
+            Rm_osalLog("          %10d - %10d ", treeNode->base, \r
+                                                 treeNode->base + treeNode->length -1);\r
+            \r
+            if (strcmp(treeNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0)\r
+            {\r
+                Rm_osalLog("NOT ALLOCATED\n");\r
+            }\r
+            else\r
+            {\r
+                Rm_osalLog("allocated to %s\n", treeNode->allocatedTo);\r
+            }\r
+\r
+            if (strcmp(treeNode->allocatedTo, RM_ALLOCATED_TO_LINUX) == 0)\r
+            {\r
+                numLinuxResources += treeNode->length;\r
+            }\r
+        }\r
+        \r
+        Rm_osalLog("Total allocated to Linux: %d\n", numLinuxResources);\r
+        \r
+        allocator = allocator->nextAllocator;\r
+    }\r
+\r
+    Rm_nsPrintObjects(rmInst);\r
+}\r
+\r
 Rm_Handle Rm_init(Rm_InitCfg *initCfg)\r
 {\r
     Rm_Inst *rmInst;\r
+    void *globalResourceDtb = NULL;\r
+    void *linuxResourceDtb = NULL;\r
 \r
     /* Instance creation checks.  Add one to strlen calculation for null character */\r
     if ((strlen(initCfg->instName) + 1) > RM_INSTANCE_NAME_MAX_CHARS)\r
@@ -801,32 +2070,64 @@ Rm_Handle Rm_init(Rm_InitCfg *initCfg)
     }\r
     \r
     /* Get memory for RM instance from local memory */\r
-    rmInst = Rm_osalMalloc (sizeof(Rm_Inst), false);\r
+    rmInst = Rm_osalMalloc (sizeof(Rm_Inst));\r
     /* Populate instance based on input parameters */\r
     strcpy (&rmInst->name[0], initCfg->instName);\r
     rmInst->instType = initCfg->instType;\r
-    rmInst->instState = RM_state_IDLE;\r
     rmInst->registeredWithDelegateOrServer = false;\r
+    rmInst->policyDtb = NULL;\r
 \r
     /* Initialize the transport routing map linked list pointer to NULL.  The linked list\r
      * nodes will be created when the application registers transports */\r
     rmInst->routeMap = NULL;\r
 \r
-    /* Initialize the transaction queue elements.  The linked list pointer is set to NULL\r
-     * and the transaction sequence number is initialized to 0. */\r
-    rmInst->transactionSeqNum = 0;\r
+    /* Initialize the allocators linked list pointer to NULL.  The linked list nodes will\r
+     * be created on the Server instance when the application reads in the resource list.\r
+     * Nodes will also be created on Client Delegates when blocks of resources are requested\r
+     * for allocation to clients. */\r
+    rmInst->allocators = NULL;\r
+\r
+    /* Initialize the NameServer pointer to NULL.  The NameServer should only be located\r
+     * on the RM Server */\r
+    rmInst->nameServer = NULL;\r
+\r
+    /* Initialize the transaction queue elements. */\r
+    rmInst->transactionSeqNum = Rm_transactionInitSequenceNum();\r
     rmInst->transactionQueue= NULL;\r
 \r
     /* RM Server specific actions */\r
     if (rmInst->instType == Rm_instType_SERVER)\r
     {\r
-       /* parse DTB, etc */\r
+        /* Initialize the NameServer */\r
+        Rm_nsInit(rmInst);\r
+        \r
+        /* Open the ResourceList file and provide it to the resource initializer.  The Linux\r
+         * DTB will be parsed simultaneously for resource's consumed by the kernel.  The resources\r
+         * used by the kernel will be marked as used in the resource allocators. */\r
+        if (initCfg->globalResourceList)\r
+        {\r
+            globalResourceDtb = initCfg->globalResourceList;\r
+            fdt_open_into(globalResourceDtb, globalResourceDtb, fdt_totalsize(globalResourceDtb));\r
+\r
+            if (initCfg->linuxDtb)\r
+            {\r
+                linuxResourceDtb = initCfg->linuxDtb;\r
+                fdt_open_into(linuxResourceDtb, linuxResourceDtb, fdt_totalsize(linuxResourceDtb));   \r
+            }\r
+            \r
+            Rm_initializeAllocators(rmInst, globalResourceDtb, linuxResourceDtb);\r
+        }\r
     }\r
 \r
     /* Instance startup policies are only used for Servers and Client Delegates */\r
     if (rmInst->instType != Rm_instType_CLIENT)\r
     {\r
-        rmInst->instPolicy = initCfg->startupPolicy;\r
+        /* Open the instance's policy and store it */\r
+        if (initCfg->startupPolicy)\r
+        {\r
+            rmInst->policyDtb = initCfg->startupPolicy;\r
+            fdt_open_into(rmInst->policyDtb, rmInst->policyDtb, fdt_totalsize(rmInst->policyDtb));  \r
+        }\r
 \r
         /* Store policy via policy APIs ... */\r
     }\r