diff --git a/src/rm.c b/src/rm.c
index 8f54b2ef90baf6e45a0182c10062bdd3418fb417..d66ae06494669a74a004f62e7b9aea6a431b61e0 100644 (file)
--- a/src/rm.c
+++ b/src/rm.c
*
* \par
* ============================================================================
- * @n (C) Copyright 2012, Texas Instruments, Inc.
+ * @n (C) Copyright 2012-2013, Texas Instruments, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* \par
*/
-/* RM Types */
-#include <ti/drv/rm/rm_types.h>
+/* Standard includes */
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
-/* RM includes */
+/* RM external includes */
#include <ti/drv/rm/rm.h>
+#include <ti/drv/rm/rmver.h>
#include <ti/drv/rm/rm_services.h>
#include <ti/drv/rm/rm_transport.h>
-#include <ti/drv/rm/rm_policy.h>
-#include <ti/drv/rm/include/rm_pvt.h>
+
+/* RM internal includes */
+#include <ti/drv/rm/include/rm_loc.h>
+#include <ti/drv/rm/include/rm_transportloc.h>
+#include <ti/drv/rm/include/rm_nameserverloc.h>
+#include <ti/drv/rm/include/rm_dtb_utilloc.h>
+#include <ti/drv/rm/include/rm_policyloc.h>
+#include <ti/drv/rm/include/rm_treeloc.h>
+
+/* RM LIBFDT includes */
+#include <ti/drv/rm/util/libfdt/libfdt.h>
+
+/* Tree algorithm includes */
+#include <ti/drv/rm/util/tree.h>
/* RM OSAL layer */
#include <rm_osal.h>
************************** Globals ***********************************
**********************************************************************/
-/* Place QMSS PDSP permissions array */
-#pragma DATA_SECTION (rmQmssPdspFirmwarePerms, ".rm");
-#pragma DATA_ALIGN (rmQmssPdspFirmwarePerms, 128)
-Rm_Perms rmQmssPdspFirmwarePerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_QMSS_FIRMWARE_PDSPS, Rm_Perms)];
-
-
/** @brief Global Variable which describes the RM Version Information */
-const char rmVersionStr[] = RM_VERSION_STR ":" __DATE__ ":" __TIME__;
+const char rmVersionStr[] = RM_VERSION_STR ":" __DATE__ ":" __TIME__;
/**********************************************************************
- ********************** Internal Functions *********************************
+ ************************ Local Functions *****************************
**********************************************************************/
-Rm_TransactionResult rmTransactionForwarder (void *rmHandle, Rm_Transaction *transInfo,
- Rm_TransactionReceipt *transReceipt)
+/* FUNCTION PURPOSE: Initializes a RM inst's transaction sequence number
+ ***********************************************************************
+ * DESCRIPTION: The RM instance transaction sequence number can never
+ * have a value of 0 to avoid conflicts with transactions
+ * that have a remoteOriginatingId of 0 (transaction ID
+ * will be used as the remoteOriginatingId for
+ * transactions that are responses to requests).
+ */
+static uint32_t transactionInitSequenceNum(void)
{
- Rm_Inst *rmInst = (Rm_Inst *) rmHandle;
- Rm_TransRouteMapNode *routeMap = (Rm_TransRouteMapNode *) rmInst->routeMap;
- Rm_ProtocolPkt *rmPkt = NULL;
+ return (1);
+}
- /* Error if no transports have been registered and a service has been requested that
- * must be forwarded to another RM agent */
- if (routeMap == NULL)
- {
- return (-1); /* temp error */
- }
-
- /* Make sure the RM instance has a transport registered with a higher level agent */
- if (!rmInst->registeredWithDelegateOrServer)
- {
- return (-1); /* temp error - can't handle request because client delegate or server not registered */
- }
+/* FUNCTION PURPOSE: Provides a sequence number for new transactions
+ ***********************************************************************
+ * DESCRIPTION: Returns a sequence number for a new transaction
+ * specific to a RM instance. Handles rollover of
+ * sequence number.
+ */
+static uint32_t transactionGetSequenceNum(Rm_Inst *rmInst)
+{
+ rmInst->transactionSeqNum++;
+ if (!rmInst->transactionSeqNum) {
+ rmInst->transactionSeqNum++;
+ }
+ return (rmInst->transactionSeqNum);
+}
- /* Parse the RM instance's routing map to find the higher level agent for forwarding */
- while ((routeMap->remoteInstType != Rm_instType_CLIENT_DELEGATE) ||
- (routeMap->remoteInstType != Rm_instType_SERVER))
- {
- /* Traverse the list until arriving at the upper level agent node */
- routeMap = routeMap->nextNode;
+/* FUNCTION PURPOSE: Creates a resource allocator
+ ***********************************************************************
+ * DESCRIPTION: Returns a newly Created and initialized resource
+ * The allocator is also stored in the RM instance
+ * allocator list.
+ */
+static Rm_Allocator *allocatorAdd(Rm_Inst *rmInst, const char *resourceName)
+{
+ Rm_Allocator *allocators = rmInst->allocators;
+ Rm_Allocator *newAllocator = NULL;
+
+ newAllocator = Rm_osalMalloc(sizeof(Rm_Allocator));
+
+ if (newAllocator) {
+ memset((void *)newAllocator, 0, sizeof(Rm_Allocator));
+ strncpy(newAllocator->resourceName, resourceName, RM_NAME_MAX_CHARS);
+ newAllocator->allocatorRootEntry = NULL;
+ newAllocator->nextAllocator = NULL;
+
+ /* Add allocator to end of list */
+ if (allocators) {
+ while (allocators->nextAllocator) {
+ allocators = allocators->nextAllocator;
+ }
+ allocators->nextAllocator = newAllocator;
+ }
+ else {
+ rmInst->allocators = newAllocator;
+ }
}
+ return (newAllocator);
+}
- /* Create a RM packet using the service information */
- if (rmInst->transport.rmAllocPkt)
- {
- rmPkt = rmInst->transport.rmAllocPkt (routeMap->transHandle, sizeof(Rm_ProtocolPkt));
+/* FUNCTION PURPOSE: Deletes a resource allocator
+ ***********************************************************************
+ * DESCRIPTION: Deletes a resource allocator based on the given
+ * resource name. The resource allocator will be
+ * removed from the RM instance allocator list.
+ */
+static int32_t allocatorDelete(Rm_Inst *rmInst, char *resourceName)
+{
+ Rm_Allocator *allocator = rmInst->allocators;
+ Rm_Allocator *prevAllocator = NULL;
+ int32_t retVal = RM_OK;
+
+ while (allocator) {
+ if (strncmp(allocator->resourceName, resourceName, RM_NAME_MAX_CHARS) == 0) {
+ break;
+ }
+ prevAllocator = allocator;
+ allocator = allocator->nextAllocator;
}
- /* Return error if the packet allocation API is not plugged or if a NULL packet pointer
- * was returned */
- if (!rmPkt)
- {
- return (-1); /* temp error */
+ if (allocator) {
+ if (prevAllocator == NULL) {
+ rmInst->allocators = allocator->nextAllocator;
+ }
+ else {
+ prevAllocator->nextAllocator = allocator->nextAllocator;
+ }
+ Rm_osalFree((void *)allocator, sizeof(Rm_Allocator));
}
+ else {
+ retVal = RM_ERROR_RES_ALLOCATOR_DOES_NOT_EXIST;
+ }
+ return (retVal);
+}
+
+/* FUNCTION PURPOSE: Adds an owner to an allocator resource
+ ***********************************************************************
+ * DESCRIPTION: Adds a RM instance node to a resource node's
+ * list of owners.
+ */
+static void addOwner(Rm_ResourceNode *node, void *serviceInstNode)
+{
+ Rm_Owner *ownerList = node->ownerList;
+ Rm_Owner *newOwner = NULL;
- /* Populate the RM packet using the service information */
+ newOwner = Rm_osalMalloc(sizeof(Rm_Owner));
+ if (newOwner) {
+ newOwner->instNameNode = serviceInstNode;
+ newOwner->nextOwner = NULL;
+ /* Add owner entry to end of list */
+ if (ownerList) {
+ while (ownerList->nextOwner) {
+ ownerList = ownerList->nextOwner;
+ }
+ ownerList->nextOwner = newOwner;
+ }
+ else {
+ node->ownerList = newOwner;
+ }
- /* Inform component that requested the service that the resource is being requested
- * from the higher level RM agent. The component must assume the resource service
- * result will be returned using the specified callback function */
- return (RM_REQUESTING_RESOURCE);
+ node->allocationCount++;
+ newOwner->instNameNode->allocRefCount++;
+ }
}
-Rm_TransactionResult rmTransactionProcessor (rmHandle, Rm_Transaction *newTransaction,
- Rm_TransactionReceipt *newTransactionReceipt)
+/* FUNCTION PURPOSE: Checks a resource node's ownership
+ ***********************************************************************
+ * DESCRIPTION: Returns TRUE if the provided instance node is
+ * in the list of resource node owners. Otherwise,
+ * returns FALSE.
+ */
+static bool isOwnedBy(Rm_ResourceNode *node, void *serviceInstNode)
{
+ Rm_Owner *owner = node->ownerList;
+ while (owner) {
+ if (owner->instNameNode == serviceInstNode) {
+ return(true);
+ }
+ owner = owner->nextOwner;
+ }
+ return(false);
}
-Rm_ServiceResult rmServiceHandler (void *rmHandle, Rm_ServiceReqInfo *requestInfo,
- Rm_ServiceRespInfo *responseInfo)
+/* FUNCTION PURPOSE: Compares two resource node's owners
+ ***********************************************************************
+ * DESCRIPTION: Returns TRUE if the owners of two resource nodes
+ * are equivalent. Otherwise, returns FALSE.
+ */
+static bool compareResourceNodeOwners(Rm_ResourceNode *node1, Rm_ResourceNode *node2)
{
- Rm_Inst *rmInst = (Rm_Inst *) rmHandle;
- Rm_Transaction newTransaction;
- Rm_TransactionReceipt newTransactionReceipt;
- Rm_ServiceResult retVal = RM_service_OKAY;
- void *key;
+ Rm_Owner *node1Owners = node1->ownerList;
+ Rm_Owner *node2Owners = node2->ownerList;
+ bool matchedInst;
+
+ if (node1->allocationCount == node2->allocationCount) {
+ while (node1Owners) {
+ matchedInst = false;
+ while (node2Owners) {
+ if (node1Owners->instNameNode == node2Owners->instNameNode) {
+ matchedInst = true;
+ break;
+ }
+ node2Owners = node2Owners->nextOwner;
+ }
+
+ if (matchedInst) {
+ node2Owners = node2->ownerList;
+ node1Owners = node1Owners->nextOwner;
+ }
+ else {
+ return(false);
+ }
+ }
+ }
+ else {
+ return(false);
+ }
+
+ return(true);
+}
- /* Prevent another component using the same instance from wiping out the current
- * service request */
- key = Rm_osalLocalCsEnter();
+/* FUNCTION PURPOSE: Deletes an owner from an allocator resource
+ ***********************************************************************
+ * DESCRIPTION: Removes a RM instance node from a resource node's
+ * list of owners.
+ */
+static void deleteOwner(Rm_ResourceNode *node, void *serviceInstNode)
+{
+ Rm_Owner *owner = node->ownerList;
+ Rm_Owner *prevOwner = NULL;
- /* Transfer request information into the internal transaction format */
- newTransaction.transType = (Rm_Command) requestInfo->serviceType;
- /* Policy modifications will never originate from components */
- strcpy ((void *) &(newTransaction.u.transInfo.resName)[0], (void *)requestInfo->resName);
- newTransaction.u.transInfo.resBase = requestInfo->resourceAlign;
- newTransaction.u.transInfo.resNum = requestInfo->resourceNum;
- newTransaction.u.transInfo.resAlign = requestInfo->resourceAlign;
- strcpy ((void *) &(newTransaction.u.transInfo.resNsName)[0], (void *)requestInfo->resNsName);
+ while (owner) {
+ if (owner->instNameNode == serviceInstNode) {
+ break;
+ }
+ prevOwner = owner;
+ owner = owner->nextOwner;
+ }
- /* All service requests on Clients are forwarded to the higher level RM agent
- * either a Client Delegate or Server, based on the RM system architecture */
- if (rmInst->instType == Rm_instType_CLIENT)
- {
- retVal = (Rm_ServiceResult) rmTransactionForwarder (rmHandle, &newTransaction, &newTransactionReceipt);
+ if (prevOwner == NULL) {
+ node->ownerList = owner->nextOwner;
+ }
+ else {
+ prevOwner->nextOwner = owner->nextOwner;
+ }
+
+ node->allocationCount--;
+ owner->instNameNode->allocRefCount--;
+ Rm_osalFree((void *)owner, sizeof(Rm_Owner));
+}
+
+/* FUNCTION PURPOSE: Copies the owners of a resource node
+ ***********************************************************************
+ * DESCRIPTION: Creates a list of resource owners for the destination
+ * resource node that is equivalent to the the
+ * source resource node's owners
+ */
+static void copyOwners(Rm_ResourceNode *dstNode, Rm_ResourceNode *srcNode)
+{
+ Rm_Owner *srcOwnerList = srcNode->ownerList;
+ Rm_Owner *dstNewOwner;
+ Rm_Owner *dstPrevOwner;
+
+ dstNode->allocationCount = srcNode->allocationCount;
- /* Copy internal transaction receipt information into the response info fields for the
- * component */
- responseInfo->requestId = newTransactionReceipt.transactionId;
- responseInfo->resBase = newTransactionReceipt.resBase;
- responseInfo->resNum = newTransactionReceipt.resNum;
+ while (srcOwnerList) {
+ dstNewOwner = Rm_osalMalloc(sizeof(Rm_Owner));
+ dstNewOwner->instNameNode = srcOwnerList->instNameNode;
+ dstNewOwner->nextOwner = NULL;
+
+ if (dstNode->ownerList == NULL) {
+ dstNode->ownerList = dstNewOwner;
+ }
+ else {
+ dstPrevOwner->nextOwner = dstNewOwner;
+ }
+ dstPrevOwner = dstNewOwner;
+ srcOwnerList = srcOwnerList->nextOwner;
}
- else
- {
- /* Directly handle the request if on a Client Delegate or Server. On Client Delegates, if
- * the request cannot be serviced it will be forwarded to the higher level RM instance. */
- retVal = (Rm_ServiceResult) rmTransactionProcessor (rmHandle, &newTransaction, &newTransactionReceipt);
+}
- /* Copy internal transaction receipt information into the response info fields for the
- * component */
- responseInfo->requestId = newTransactionReceipt.transactionId;
- responseInfo->resBase = newTransactionReceipt.resBase;
- responseInfo->resNum = newTransactionReceipt.resNum;
+/* FUNCTION PURPOSE: Clears a resource node's owners
+ ***********************************************************************
+ * DESCRIPTION: Deletes all owners from the owners list of a
+ * resource node.
+ */
+static void clearOwners(Rm_ResourceNode *node)
+{
+ Rm_Owner *owner = node->ownerList;
+ Rm_Owner *nextOwner;
+
+ while (owner) {
+ nextOwner = owner->nextOwner;
+ node->allocationCount--;
+ Rm_osalFree((void *)owner, sizeof(Rm_Owner));
+ owner = nextOwner;
}
+}
- Rm_osalLocalCsExit(key);
+/* FUNCTION PURPOSE: Creates a new resource tree
+ ***********************************************************************
+ * DESCRIPTION: Creates a new resource tree using the provided
+ * resource name and value range. The name and value
+ * typically originate from the GRL.
+ */
+static int32_t createResourceTree(Rm_Inst *rmInst, const char *resourceName, Rm_ResourceRange *range)
+{
+ Rm_Allocator *allocator = NULL;
+ Rm_ResourceTree *treeRootEntry = NULL;
+ Rm_ResourceNode *treeNode = NULL;
+ Rm_ResourceNode *collidingNode = NULL;
+
+ allocator = allocatorAdd(rmInst, resourceName);
+ treeRootEntry = Rm_osalMalloc(sizeof(Rm_ResourceTree));
+ RB_INIT(treeRootEntry);
+
+ while (range != NULL) {
+ treeNode = rmResourceNodeNew(range->base, range->length);
+ collidingNode = RB_INSERT(_Rm_AllocatorResourceTree, treeRootEntry, treeNode);
+
+ if (collidingNode) {
+ Rm_ResourceNode *nextNode = NULL;
+
+ /* Node that was inserted collides with existing node. Destroy tree and return error */
+ for (treeNode = RB_MIN(_Rm_AllocatorResourceTree, treeRootEntry); treeNode != NULL; treeNode = nextNode) {
+ nextNode = RB_NEXT(_Rm_AllocatorResourceTree, treeRootEntry, treeNode);
+ RB_REMOVE(_Rm_AllocatorResourceTree, treeRootEntry, nextNode);
+ rmResourceNodeFree(treeNode);
+ }
+ Rm_osalFree((void *)treeRootEntry, sizeof(Rm_ResourceTree));
+ allocatorDelete(rmInst, allocator->resourceName);
+ return (RM_ERROR_GRL_RES_SPECIFIED_MORE_THAN_ONCE);
+ }
+ range = range->nextRange;
+ }
- return (retVal);
+ allocator->allocatorRootEntry = treeRootEntry;
+ return(RM_OK);
}
-/**********************************************************************
- *********************** Application visible APIs ***************************
- **********************************************************************/
-
-Rm_Handle Rm_init(Rm_InitCfg *initCfg)
+/* FUNCTION PURPOSE: Preallocates a resource
+ ***********************************************************************
+ * DESCRIPTION: Called when an allocate request is made but the base
+ * is unspecified. The preallocation algorithm looks at
+ * available resources as well as policy permissions to
+ * determine a resource range that satisfies the request.
+ * If a valid range is found it will be returned for the
+ * treeAllocate algorithm to handle.
+ */
+static int32_t treePreAllocate(Rm_Inst *rmInst, Rm_Allocator *allocator, int32_t resourcePolicy,
+ Rm_AllocatorOpInfo *opInfo)
{
- Rm_Inst *rmInst;
+ Rm_ResourceNode findNode;
+ Rm_ResourceNode *matchingNode = NULL;
+ uint32_t matchingEnd;
+ uint32_t rangeIndex;
+ bool resourceFound = false;
+ Rm_PolicyCheckType policyCheckType;
+ Rm_PolicyCheckCfg policyCheckCfg;
+ bool nodePassesPolicy;
+ int32_t retVal = RM_SERVICE_PROCESSING;
+
+ opInfo->resourceInfo->base = rmPolicyGetResourceBase(rmInst->policy, opInfo->serviceSrcInstNode,
+ resourcePolicy, opInfo->allocType,
+ &retVal);
+ if (retVal != RM_SERVICE_PROCESSING) {
+ return (retVal);
+ }
- /* Instance creation checks. Add one to strlen calculation for null character */
- if ((strlen(initCfg->instName) + 1) > RM_INSTANCE_NAME_MAX_CHARS)
- {
- /* Failure: Instance name is too big */
- return (NULL);
+ if (opInfo->resourceInfo->alignment == RM_RESOURCE_ALIGNMENT_UNSPECIFIED) {
+ /* Get alignment from policy */
+ opInfo->resourceInfo->alignment = rmPolicyGetResourceAlignment(rmInst->policy, resourcePolicy);
}
- /* Get memory for RM instance from local memory */
- rmInst = Rm_osalMalloc (sizeof(Rm_Inst), false);
- /* Populate instance based on input parameters */
- strcpy (&rmInst->name[0], initCfg->instName);
- rmInst->instType = initCfg->instType;
- rmInst->instState = RM_state_IDLE;
- rmInst->registeredWithDelegateOrServer = false;
- rmInst->serviceCallback = NULL;
+ if (opInfo->resourceInfo->alignment == 0) {
+ opInfo->resourceInfo->alignment = 1;
+ }
+
+ memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));
+ findNode.base = opInfo->resourceInfo->base;
+ findNode.length = opInfo->resourceInfo->length;
+
+ /* Configure policy checking structure */
+ memset((void *)&policyCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));
+ if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_INIT_SHIFT)) {
+ policyCheckType = Rm_policyCheck_INIT;
+ }
+ else if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_USE_SHIFT)) {
+ policyCheckType = Rm_policyCheck_USE;
+ }
+ policyCheckCfg.policyDtb = rmInst->policy;
+ policyCheckCfg.resourceOffset = resourcePolicy;
+
+ do {
+ matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
+
+ if (matchingNode) {
+ nodePassesPolicy = false;
+ policyCheckCfg.type = policyCheckType;
+ policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
+ policyCheckCfg.resourceBase = findNode.base;
+ policyCheckCfg.resourceLength = findNode.length;
+ nodePassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
+
+ if (nodePassesPolicy && (matchingNode->allocationCount > 0)) {
+ /* Check exclusive privileges of instance requesting resource. Requesting
+ * instance with exclusive privileges can't reserve resource if already owned*/
+ policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;
+ policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
+ nodePassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
+ }
+
+ if (nodePassesPolicy && (matchingNode->allocationCount == 1)) {
+ /* Check exclusive privileges of instance that currently owns resource */
+ policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;
+ policyCheckCfg.validInstNode = matchingNode->ownerList->instNameNode;
+ nodePassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
+ }
+
+ if (retVal != RM_SERVICE_PROCESSING) {
+ break;
+ }
+
+ if (nodePassesPolicy) {
+ matchingEnd = matchingNode->base + matchingNode->length - 1;
+ /* Initialize indexer to be first resource value that alignment */
+ rangeIndex = findNode.base;
+ if (rangeIndex % opInfo->resourceInfo->alignment) {
+ rangeIndex += (opInfo->resourceInfo->alignment -
+ (rangeIndex % opInfo->resourceInfo->alignment));
+ }
+
+ if ((rangeIndex + opInfo->resourceInfo->length - 1) <= matchingEnd) {
+ /* Block of unallocated resources within matchingNode that satisfies
+ * allocate requirements */
+ opInfo->resourceInfo->base = rangeIndex;
+ resourceFound = true;
+ }
+ }
+
+ if (!resourceFound) {
+ /* Check next resource node for available resources */
+ findNode.base = matchingNode->base + matchingNode->length;
+ }
+ }
+ else {
+ retVal = RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET;
+ }
+ } while ((!resourceFound) &&
+ (retVal != RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET));
- /* Populate the instance transport callouts */
- rmInst->transport.rmAllocPkt = initCfg->rmAllocPktFuncPtr;
- rmInst->transport.rmFreePkt = initCfg->rmFreePktFuncPtr;
- rmInst->transport.rmSend = initCfg->rmSendFuncPtr;
- rmInst->transport.rmReceive = initCfg->rmReceiveFuncPtr;
- rmInst->transport.rmNumPktsReceived = initCfg->rmNumPktsReceivedFuncPtr;
+ return(retVal);
+}
- /* Initialize the transport routing map linked list pointer to NULL. The linked list
- * nodes will be created when the application registers transports */
- rmInst->routeMap = NULL;
+/* FUNCTION PURPOSE: Allocates a resource
+ ***********************************************************************
+ * DESCRIPTION: Will attempt to allocate the resource with specified
+ * base and length from the resource's allocator. The
+ * allocation algorithm will verify the allocation against
+ * the policy permissions for the instance requesting the
+ * allocation. If the policy allows the allocation the
+ * algorithm will allocate the resource then combine any
+ * resource nodes that may have become equivalent (in terms
+ * of ownership) after the allocation.
+ */
+static int32_t treeAllocate(Rm_Inst *rmInst, Rm_Allocator *allocator, int32_t resourcePolicy,
+ Rm_AllocatorOpInfo *opInfo)
+{
+ Rm_ResourceNode findNode;
+ Rm_ResourceNode *matchingNode = NULL;
+ Rm_ResourceNode *leftNode = NULL;
+ Rm_ResourceNode *rightNode = NULL;
+ Rm_PolicyCheckType policyCheckType;
+ Rm_PolicyCheckCfg policyCheckCfg;
+ bool allocPassesPolicy;
+ bool combineLeft = false;
+ bool combineRight = false;
+ uint32_t findEnd;
+ uint32_t matchingEnd;
+ int32_t retVal = RM_SERVICE_PROCESSING;
+
+ memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));
+ findNode.base = opInfo->resourceInfo->base;
+ findNode.length = opInfo->resourceInfo->length;
+ matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
+
+ /* Prepare privilege checks */
+ memset((void *)&policyCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));
+ if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_INIT_SHIFT)) {
+ policyCheckType = Rm_policyCheck_INIT;
+ }
+ else if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_USE_SHIFT)) {
+ policyCheckType = Rm_policyCheck_USE;
+ }
- /* RM Server specific actions */
- if (rmInst->instType == Rm_instType_SERVER)
- {
+ if (matchingNode) {
+ findEnd = findNode.base + findNode.length - 1;
+ matchingEnd = matchingNode->base + matchingNode->length - 1;
+
+ if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {
+ if (opInfo->serviceSrcInstNode == rmPolicyGetLinuxInstNode(rmInst->validInstances)) {
+ /* Bypass policy checks since Linux Kernel has full privileges */
+ allocPassesPolicy = true;
+ }
+ else {
+ policyCheckCfg.policyDtb = rmInst->policy;
+ policyCheckCfg.resourceOffset = resourcePolicy;
+ policyCheckCfg.type = policyCheckType;
+ policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
+ policyCheckCfg.resourceBase = findNode.base;
+ policyCheckCfg.resourceLength = findNode.length;
+ allocPassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
+ if (!allocPassesPolicy) {
+ if (policyCheckType == Rm_policyCheck_INIT) {
+ retVal = RM_SERVICE_DENIED_INIT_PERM_NOT_GIVEN;
+ }
+ else {
+ retVal = RM_SERVICE_DENIED_USE_PERM_NOT_GIVEN;
+ }
+ }
+
+ if (!isOwnedBy(matchingNode, opInfo->serviceSrcInstNode)) {
+ /* Perform exclusive checks if requesting instance does not already an
+ * owner of the resource */
+ if (allocPassesPolicy && (matchingNode->allocationCount > 0)) {
+ /* Check exclusive privileges of instance requesting resource. Requesting
+ * instance with exclusive privileges can't reserve resource if already owned*/
+ policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;
+ policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
+ allocPassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
+ if (!allocPassesPolicy) {
+ retVal = RM_SERVICE_DENIED_EXCLUSIVE_RES_ALLOCD;
+ }
+ }
+ if (allocPassesPolicy && (matchingNode->allocationCount == 1)) {
+ /* Check exclusive privileges of instance that currently owns resource */
+ policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;
+ policyCheckCfg.validInstNode = matchingNode->ownerList->instNameNode;
+ allocPassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
+ if (!allocPassesPolicy) {
+ retVal = RM_SERVICE_DENIED_ALLOCD_TO_EXCLUSIVE_INST;
+ }
+ }
+ }
+ }
+
+ if (allocPassesPolicy) {
+ if (!isOwnedBy(matchingNode, opInfo->serviceSrcInstNode)) {
+ /* Handle any possible node combinations if requesting instance is
+ * not already in resource's owner list. Automatic approval if requesting
+ * instance is already in owner list. */
+ if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd)) {
+ /* findNode range matches matchingNode range
+ *
+ * |<--left node-->||<--matched node-->||<--right node-->| => existing node
+ * |<--alloc request-->| => requested resources
+ */
+ leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
+ rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
+ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
+ addOwner(matchingNode, opInfo->serviceSrcInstNode);
+
+ if (leftNode && compareResourceNodeOwners(leftNode, matchingNode)) {
+ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
+ combineLeft = true;
+ }
+ if (rightNode && compareResourceNodeOwners(rightNode, matchingNode)) {
+ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
+ combineRight = true;
+ }
+
+ if (combineLeft && combineRight) {
+ /* Combine all three nodes into matchingNode */
+ matchingNode->base = leftNode->base;
+ matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;
+
+ clearOwners(leftNode);
+ rmResourceNodeFree(leftNode);
+ clearOwners(rightNode);
+ rmResourceNodeFree(rightNode);
+ }
+ else if (combineLeft) {
+ /* Combine left and matching nodes. Reinsert right. */
+ matchingNode->base = leftNode->base;
+ matchingNode->length += leftNode->length;
+
+ clearOwners(leftNode);
+ rmResourceNodeFree(leftNode);
+ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
+ }
+ else if (combineRight) {
+ /* Combine right and matching nodes. Reinsert left. */
+ matchingNode->length += rightNode->length;
+
+ clearOwners(rightNode);
+ rmResourceNodeFree(rightNode);
+ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
+ }
+ else {
+ /* No combine. */
+ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
+ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
+ }
+
+ /* Always reinsert matchingNode */
+ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
+ }
+ else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {
+ /* findNode range is subset of matchingNode range and neither boundary is
+ * equivalent.
+ *
+ * |<----------matched node---------->|
+ * |<---alloc request--->|
+ */
+ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
+ leftNode = rmResourceNodeNew(matchingNode->base, findNode.base - matchingNode->base);
+ copyOwners(leftNode, matchingNode);
+ rightNode = rmResourceNodeNew(findNode.base + findNode.length, matchingEnd - findEnd);
+ copyOwners(rightNode, matchingNode);
+
+ matchingNode->base = findNode.base;
+ matchingNode->length = findNode.length;
+ addOwner(matchingNode, opInfo->serviceSrcInstNode);
+
+ /* Insert all the nodes */
+ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
+ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
+ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
+ }
+ else {
+ if (findNode.base == matchingNode->base) {
+ /* findNode base and matchingNode base are equivalent. May be combine
+ * possibilities to the left
+ *
+ * |<---left node (alloc'd)--->||<----------matched node---------->|
+ * |<---findNode (alloc req)--->|
+ */
+ leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
+ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
+ /* Add allocating instance to owner list for compare with leftNode */
+ addOwner(matchingNode, opInfo->serviceSrcInstNode);
+
+ if (leftNode && compareResourceNodeOwners(leftNode, matchingNode)) {
+ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
+ /* Combine leftNode and findNode */
+ leftNode->length += findNode.length;
+ }
+ else {
+ leftNode = rmResourceNodeNew(findNode.base, findNode.length);
+ copyOwners(leftNode, matchingNode);
+ }
+
+ /* Account for leftNode in matchingNode */
+ matchingNode->base = findNode.base + findNode.length;
+ matchingNode->length = matchingEnd - findEnd;
+
+ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
+ }
+ else if (findEnd == matchingEnd) {
+ /* findNode end and matchingNode end are equivalent. May be combine
+ * possibilities to the right
+ *
+ * |<----------matched node---------->||<---right node (alloc'd)--->|
+ * |<---findNode (alloc req)--->|
+ */
+ rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
+ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
+ /* Add allocating instance to owner list for compare with rightNode */
+ addOwner(matchingNode, opInfo->serviceSrcInstNode);
+
+ if (rightNode && compareResourceNodeOwners(rightNode, matchingNode)) {
+ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
+ /* Combine rightNode and findNode */
+ rightNode->base = findNode.base;
+ rightNode->length += findNode.length;
+ }
+ else {
+ rightNode = rmResourceNodeNew(findNode.base, findNode.length);
+ copyOwners(rightNode, matchingNode);
+ }
+
+ /* Account for rightNode in matchingNode */
+ matchingNode->length -= findNode.length;
+
+ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
+ }
+ /* Remove allocating instance from leftover matchingNode */
+ deleteOwner(matchingNode, opInfo->serviceSrcInstNode);
+ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
+ }
+ }
+ retVal = RM_SERVICE_APPROVED;
+ }
+ }
+ else {
+ retVal = RM_SERVICE_DENIED_PARTIAL_ALLOCATION;
+ }
+ }
+ else {
+ retVal = RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST;
+ }
+ return(retVal);
+}
+
+/* FUNCTION PURPOSE: Frees a resource
+ ***********************************************************************
+ * DESCRIPTION: Will attempt to free the resource with specified
+ * base and length from the resource's allocator. The
+ * free algorithm will verify the free request parameters
+ * match an allocated range for the resource and that the
+ * range is owned by the instance requesting the free. If
+ * the free is validated the algorithm will free the
+ * resource then combine any resource nodes that may have
+ * become equivalent (in terms of ownership) after the
+ * allocation.
+ */
+static int32_t treeFree(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)
+{
+ Rm_ResourceNode findNode;
+ Rm_ResourceNode *matchingNode = NULL;
+ Rm_ResourceNode *leftNode = NULL;
+ Rm_ResourceNode *rightNode = NULL;
+ bool combineLeft = false;
+ bool combineRight = false;
+ uint32_t findEnd;
+ uint32_t matchingEnd;
+ int32_t retVal;
+
+ memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));
+ findNode.base = opInfo->resourceInfo->base;
+ findNode.length = opInfo->resourceInfo->length;
+ matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
+
+ if (matchingNode) {
+ findEnd = findNode.base + findNode.length - 1;
+ matchingEnd = matchingNode->base + matchingNode->length - 1;
+
+ if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {
+ if (matchingNode->allocationCount) {
+ if (isOwnedBy(matchingNode, opInfo->serviceSrcInstNode)) {
+ if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd))
+ {
+ /* Case 1: Free range equals allocated matched node exactly. Attempt to combine
+ * freed node with nodes to left and right.
+ *
+ * |<--left node-->||<---matched node--->||<--right node-->|
+ * |<---free request--->|
+ */
+ leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
+ rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
+ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
+ deleteOwner(matchingNode, opInfo->serviceSrcInstNode);
+
+ if (leftNode && compareResourceNodeOwners(leftNode, matchingNode)) {
+ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
+ combineLeft = true;
+ }
+ if (rightNode && compareResourceNodeOwners(rightNode, matchingNode)) {
+ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
+ combineRight = true;
+ }
+
+ if (combineLeft && combineRight) {
+ /* Combine all three nodes into matchingNode */
+ matchingNode->base = leftNode->base;
+ matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;
+
+ clearOwners(leftNode);
+ rmResourceNodeFree(leftNode);
+ clearOwners(rightNode);
+ rmResourceNodeFree(rightNode);
+ }
+ else if (combineLeft) {
+ /* Combine left and matching nodes. Reinsert right. */
+ matchingNode->base = leftNode->base;
+ matchingNode->length += leftNode->length;
+
+ clearOwners(leftNode);
+ rmResourceNodeFree(leftNode);
+ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
+ }
+ else if (combineRight) {
+ /* Combine right and matching nodes. Reinsert left. */
+ matchingNode->length += rightNode->length;
+
+ clearOwners(rightNode);
+ rmResourceNodeFree(rightNode);
+ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
+ }
+ else {
+ /* No combine. */
+ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
+ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
+ }
+
+ /* Always reinsert matchingNode */
+ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
+ }
+ else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {
+ /* Case 2: Free range is less than range in matched node. Split
+ * matched node into three nodes.
+ *
+ * |<----------matched node---------->|
+ * |<---free request--->|
+ *
+ * Remove instance from AllocatedTo list then add it back in for side nodes for
+ * proper accounting of allocations in validInstance list
+ */
+ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
+ deleteOwner(matchingNode, opInfo->serviceSrcInstNode);
+
+ leftNode = rmResourceNodeNew(matchingNode->base, findNode.base - matchingNode->base);
+ copyOwners(leftNode, matchingNode);
+ addOwner(leftNode, opInfo->serviceSrcInstNode);
+ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
+
+ rightNode = rmResourceNodeNew(findNode.base + findNode.length, matchingEnd - findEnd);
+ copyOwners(rightNode, matchingNode);
+ addOwner(rightNode, opInfo->serviceSrcInstNode);
+ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
+
+ matchingNode->base = findNode.base;
+ matchingNode->length = findNode.length;
+ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
+ }
+ else {
+ if (findNode.base == matchingNode->base) {
+ /* Case 3: Free range is on left boundary of matched node. Try to
+ * combine free range with left node.
+ *
+ * |<---left node (free)--->||<----------matched node---------->|
+ * |<---findNode (free req)--->|
+ */
+
+ leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
+ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
+ /* Remove freeing instance from owner list for compare with leftNode */
+ deleteOwner(matchingNode, opInfo->serviceSrcInstNode);
+
+ if (leftNode && compareResourceNodeOwners(leftNode, matchingNode)) {
+ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
+ /* Combine leftNode and findNode */
+ leftNode->length += findNode.length;
+ }
+ else {
+ leftNode = rmResourceNodeNew(findNode.base, findNode.length);
+ copyOwners(leftNode, matchingNode);
+ }
+
+ /* Remove leftNode range from matchingNode */
+ matchingNode->base = findNode.base + findNode.length;
+ matchingNode->length = matchingEnd - findEnd;
+ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
+ }
+ else if (findEnd == matchingEnd) {
+ /* Case 4: Free range is on right boundary of matched node. Try to
+ * combine free range with right node.
+ *
+ * |<----------matched node---------->||<---right node (free)--->|
+ * |<---findNode (free req)--->|
+ */
+
+ rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
+ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
+ /* Remove freeing instance from owner list for compare with rightNode */
+ deleteOwner(matchingNode, opInfo->serviceSrcInstNode);
+
+ if (rightNode && compareResourceNodeOwners(rightNode, matchingNode)) {
+ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
+ /* Combine rightNode and findNode */
+ rightNode->base = findNode.base;
+ rightNode->length += findNode.length;
+ }
+ else {
+ rightNode = rmResourceNodeNew(findNode.base, findNode.length);
+ copyOwners(rightNode, matchingNode);
+ }
+
+ /* Remove rightNode range from matchingNode */
+ matchingNode->length -= findNode.length;
+ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
+ }
+
+ /* Add freeing instance back into matchingNode allocations */
+ addOwner(matchingNode, opInfo->serviceSrcInstNode);
+ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
+ }
+
+ retVal = RM_SERVICE_APPROVED;
+ }
+ else {
+ retVal = RM_SERVICE_DENIED_RES_NOT_ALLOCD_TO_INST;
+ }
+ }
+ else {
+ retVal = RM_SERVICE_DENIED_RES_ALREADY_FREE;
+ }
+ }
+ else {
+ retVal = RM_SERVICE_DENIED_PARTIAL_FREE;
+ }
+ }
+ else {
+ retVal = RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST;
}
+ return(retVal);
+}
- /* Instance startup policies are only used for Servers and Client Delegates */
- if (rmInst->instType != Rm_instType_CLIENT)
+/* FUNCTION PURPOSE: Issues a service response to application
+ ***********************************************************************
+ * DESCRIPTION: Provides a service response back to the application
+ * using the service callback function provided to
+ * the RM instance at the time of the service request.
+ */
+static void serviceResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)
+{
+ Rm_ServiceRespInfo serviceResponse;
+
+ /* The responseTransaction will contain the resultant state details of
+ * the requestTransaction's service request */
+ serviceResponse.serviceState = transaction->state;
+ /* Pass back the ID that was provided to the component when it requested
+ * the service */
+ serviceResponse.serviceId = transaction->localId;
+
+ /* Service was approved and service was an allocate request. The resource
+ * data is passed back to the component */
+ if ((serviceResponse.serviceState == RM_SERVICE_APPROVED) &&
+ ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
+ (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||
+ (transaction->type == Rm_service_RESOURCE_GET_BY_NAME)))
{
- rmInst->instPolicy = initCfg->startupPolicy;
+ strncpy(serviceResponse.resourceName, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
+ serviceResponse.resourceBase = transaction->resourceInfo.base;
+ serviceResponse.resourceLength = transaction->resourceInfo.length;
+ }
+
+ /* Issue the callback to the requesting component with the response information */
+ transaction->callback.serviceCallback(&serviceResponse);
+
+ /* Delete the transaction from the transaction queue */
+ rmTransactionQueueDelete(rmInst, transaction->localId);
+ return;
+}
- /* Store policy via policy APIs ... */
+/* FUNCTION PURPOSE: Sends RM response packets
+ ***********************************************************************
+ * DESCRIPTION: Sends RM response packets to RM instance's that sent
+ * RM request packets to the RM instance. The response
+ * is sent via the RM transport API which is plugged
+ * with an application created transport path.
+ */
+static void transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)
+{
+ Rm_Transport *dstTransport = NULL;
+ Rm_PacketHandle pktHandle = NULL;
+
+ dstTransport = rmTransportFindRemoteName((Rm_Transport *) rmInst->transports, transaction->pktSrcInstName);
+
+ switch (transaction->type) {
+ case Rm_service_RESOURCE_ALLOCATE_INIT:
+ case Rm_service_RESOURCE_ALLOCATE_USE:
+ case Rm_service_RESOURCE_FREE:
+ case Rm_service_RESOURCE_GET_BY_NAME:
+ pktHandle = rmTransportCreateResourceResponsePkt(rmInst, dstTransport->appTransportHandle,
+ transaction);
+ break;
+ case Rm_service_RESOURCE_MAP_TO_NAME:
+ case Rm_service_RESOURCE_UNMAP_NAME:
+ pktHandle = rmTransportCreateNsResponsePkt(rmInst, dstTransport->appTransportHandle,
+ transaction);
+ break;
}
- /* Return the RM Handle */
- return ((Rm_Handle) rmInst);
+ if (pktHandle) {
+ if (rmInst->transportCallouts.rmSendPkt) {
+ if (rmInst->transportCallouts.rmSendPkt(dstTransport->appTransportHandle, pktHandle) < RM_OK) {
+ transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;
+ }
+ }
+ else {
+ transaction->state = RM_ERROR_TRANSPORT_SEND_NOT_REGD;
+ }
+ }
+ rmTransactionQueueDelete(rmInst, transaction->localId);
}
-Rm_Result Rm_preMainAllocResource(Rm_PreMainAllocInfo
- *preMainAllocInfo)
+/* FUNCTION PURPOSE: Sends RM request packets
+ ***********************************************************************
+ * DESCRIPTION: Sends RM request packets to RM instance's that are
+ * capable of forwarding or validating service requests.
+ * The request is sent via the RM transport API which is
+ * plugged with an application created transport path.
+ */
+static void transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction)
{
+ Rm_Transport *dstTransport = NULL;
+ Rm_PacketHandle pktHandle = NULL;
+
+ if (rmInst->registeredWithDelegateOrServer) {
+ if (rmInst->instType == Rm_instType_CLIENT) {
+ dstTransport = rmTransportFindRemoteInstType((Rm_Transport *) rmInst->transports, Rm_instType_CLIENT_DELEGATE);
+
+ if (!dstTransport) {
+ dstTransport = rmTransportFindRemoteInstType((Rm_Transport *) rmInst->transports, Rm_instType_SERVER);
+ }
+ }
+ else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
+ dstTransport = rmTransportFindRemoteInstType((Rm_Transport *) rmInst->transports, Rm_instType_SERVER);
+ }
+
+ switch (transaction->type) {
+ case Rm_service_RESOURCE_ALLOCATE_INIT:
+ case Rm_service_RESOURCE_ALLOCATE_USE:
+ case Rm_service_RESOURCE_FREE:
+ case Rm_service_RESOURCE_GET_BY_NAME:
+ pktHandle = rmTransportCreateResourceReqPkt(rmInst, dstTransport->appTransportHandle, transaction);
+ break;
+ case Rm_service_RESOURCE_MAP_TO_NAME:
+ case Rm_service_RESOURCE_UNMAP_NAME:
+ pktHandle = rmTransportCreateNsRequestPkt(rmInst, dstTransport->appTransportHandle, transaction);
+ break;
+ }
+ if (pktHandle) {
+ if (rmInst->transportCallouts.rmSendPkt) {
+ if (rmInst->transportCallouts.rmSendPkt(dstTransport->appTransportHandle, pktHandle) < RM_OK) {
+ transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;
+ }
+ }
+ else {
+ transaction->state = RM_ERROR_TRANSPORT_SEND_NOT_REGD;
+ }
+ }
+
+ transaction->hasBeenForwarded = true;
+ /* Transaction not deleted. Waiting for response from RM CD or Server */
+ }
}
-Rm_ServiceHandle Rm_getServiceHandle(Rm_Handle rmHandle)
+/* FUNCTION PURPOSE: Issues an allocator operation
+ ***********************************************************************
+ * DESCRIPTION: Issues an allocator preallocate, allocate, or free
+ * for an RM resource.
+ */
+static int32_t allocatorOperation(Rm_Inst *rmInst, Rm_AllocatorOpInfo *opInfo)
{
- Rm_Inst *rmInst = (Rm_Inst *) rmHandle;
- Rm_ServicesPort *newServicePort;
+ Rm_Allocator *allocator = NULL;
+ int32_t resourceOffsetInPolicy;
+ int32_t retVal;
+
+ resourceOffsetInPolicy = rmPolicyGetResourceOffset(rmInst->policy, opInfo->resourceInfo->name);
+ allocator = rmAllocatorFind(rmInst->allocators, opInfo->resourceInfo->name);
- /* Create a new service handle for the specified RM instance */
+ if ((resourceOffsetInPolicy > 0) && allocator) {
+ if (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE) {
+ retVal = treePreAllocate(rmInst, allocator, resourceOffsetInPolicy, opInfo);
+ }
+ else if (opInfo->operation == Rm_allocatorOp_ALLOCATE) {
+ retVal = treeAllocate(rmInst, allocator, resourceOffsetInPolicy, opInfo);
+ }
+ else if (opInfo->operation == Rm_allocatorOp_FREE) {
+ retVal = treeFree(allocator, opInfo);
+ }
+ }
+ else {
+ /* Resource could not be found in policy and/or allocator */
+ retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;
+ }
+ return(retVal);
+}
+
+/* FUNCTION PURPOSE: Arbitrates allocation service requests
+ ***********************************************************************
+ * DESCRIPTION: Issues a set of allocator operations in order to
+ * handle a received allocation request. Allocation
+ * requests are always forwarded to the Server on Client
+ * CD instances. If a request is made with a NameServer
+ * name the resource base and length parameters are
+ * retrieved from the NameServer prior to the allocation
+ * attempt.
+ */
+static void allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction, void *validInstNode,
+ uint32_t allocType)
+{
+ Rm_AllocatorOpInfo opInfo;
+ Rm_NameServerObjCfg nameServerObjCfg;
+ int32_t retVal = transaction->state;
+
+ memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
- /* Get memory for a new service port from local memory */
- newServicePort = Rm_osalMalloc (sizeof(Rm_ServicesPort), false);
+ if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
+ /* Forward all allocation requests to Server if transport is up. Otherwise, just queue. */
+ if (rmInst->registeredWithDelegateOrServer) {
+ transactionForwarder(rmInst, transaction);
+ }
+ }
+ else if (rmInst->instType == Rm_instType_SERVER) {
+ opInfo.resourceInfo = &transaction->resourceInfo;
+ opInfo.serviceSrcInstNode = validInstNode;
+ opInfo.allocType = allocType;
+
+ /* Populated NameServer name has precedence over base */
+ if (strlen(transaction->resourceInfo.nameServerName) > 0) {
+ if ((transaction->resourceInfo.base == 0) &&
+ (transaction->resourceInfo.length == 0) &&
+ (transaction->resourceInfo.alignment == 0)) {
+ memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
+ nameServerObjCfg.nameServerTree = rmInst->nameServer;
+ nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
+ if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {
+ strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
+ transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
+ transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
+ }
+ }
+ else {
+ retVal = RM_ERROR_NS_NAME_AND_RES_VAL_CONFLICT;
+ }
+ }
- newServicePort->rmHandle = rmHandle;
- newServicePort->rmService = rmServiceHandler;
+ if (retVal == RM_SERVICE_PROCESSING) {
+ if (transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) {
+ opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE;
+ retVal = allocatorOperation(rmInst, &opInfo);
+ }
+
+ if (retVal == RM_SERVICE_PROCESSING) {
+ opInfo.operation = Rm_allocatorOp_ALLOCATE;
+ retVal = allocatorOperation(rmInst, &opInfo);
+ }
+ }
+
+ transaction->state = retVal;
- return ((Rm_ServiceHandle) newServicePort);
+ if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
+ /* Source of allocation was not the server instance, provide the transaction
+ * to the transaction responder */
+ transactionResponder(rmInst, transaction);
+ }
+ /* Otherwise let the return stack return the transaction to the serviceHandler */
+ }
}
-Rm_TransportHandle Rm_registerTransport (Rm_Handle rmHandle,
- Rm_TransCfg *transCfg)
+/* FUNCTION PURPOSE: Arbitrates free service requests
+ ***********************************************************************
+ * DESCRIPTION: Issues a set of allocator operations in order to
+ * handle a received free request. Free
+ * requests are always forwarded to the Server on Client
+ * CD instances. If a request is made with a NameServer
+ * name the resource base and length parameters are
+ * retrieved from the NameServer prior to the free
+ * attempt.
+ */
+static void freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction, void *validInstNode)
{
- Rm_Inst *rmInst = (Rm_Inst *) rmHandle;
- Rm_TransRouteMapNode *existingRouteMap = (Rm_TransRouteMapNode *) rmInst->routeMap;
- Rm_TransRouteMapNode *newRouteMapNode;
+ Rm_AllocatorOpInfo opInfo;
+ Rm_NameServerObjCfg nameServerObjCfg;
+ int32_t retVal = transaction->state;
- /* RM Servers cannot connect to other Servers */
- if ((rmInst->instType == Rm_instType_SERVER) &&
- (transCfg->rmRemoteInstType == Rm_instType_SERVER))
- {
- return (NULL); /* Error -return null */
+ memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
+
+ if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
+ /* Forward all free requests to Server if transport is up. Otherwise, just queue. */
+ if (rmInst->registeredWithDelegateOrServer) {
+ transactionForwarder(rmInst, transaction);
+ }
}
+ else if (rmInst->instType == Rm_instType_SERVER) {
+ opInfo.resourceInfo = &transaction->resourceInfo;
+ opInfo.serviceSrcInstNode = validInstNode;
+
+ /* Populated NameServer name has precedence over base */
+ if (strlen(transaction->resourceInfo.nameServerName) > 0) {
+ if ((transaction->resourceInfo.base == 0) &&
+ (transaction->resourceInfo.length == 0) &&
+ (transaction->resourceInfo.alignment == 0)) {
+ memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
+ nameServerObjCfg.nameServerTree = rmInst->nameServer;
+ nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
+ if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {
+ strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
+ transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
+ transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
+ }
+ }
+ else {
+ retVal = RM_ERROR_NS_NAME_AND_RES_VAL_CONFLICT;
+ }
+ }
+
+ if(retVal == RM_SERVICE_PROCESSING) {
+ opInfo.operation = Rm_allocatorOp_FREE;
+ retVal = allocatorOperation(rmInst, &opInfo);
+ }
+
+ transaction->state = retVal;
+
+ if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
+ /* Source of allocation was not the server instance, provide the transaction
+ * to the transaction responder */
+ transactionResponder(rmInst, transaction);
+ }
+ /* Otherwise let the return stack return the transaction to the serviceHandler */
+ }
+}
- /* Verify Clients and Client Delegates are not registering with more than one Client Delegate or Server.
- * Assuming a Client Delegate can register with another Client Delegate that can "act" as a server */
- if (((rmInst->instType == Rm_instType_CLIENT) || (rmInst->instType == Rm_instType_CLIENT_DELEGATE)) &&
- ((transCfg->rmRemoteInstType == Rm_instType_CLIENT_DELEGATE) ||
- (transCfg->rmRemoteInstType == Rm_instType_SERVER)) &&
- rmInst->registeredWithDelegateOrServer)
- {
- return (NULL); /* Error -return null */
- }
+/* FUNCTION PURPOSE: Reserves a Linux resource
+ ***********************************************************************
+ * DESCRIPTION: Reserves resources for Linux using the base and length
+ * values retrieved from the Linux DTB via the
+ * "linux-dtb-alias" properties within the GRL.
+ */
+static int32_t reserveLinuxResource(Rm_Inst *rmInst, Rm_LinuxAlias *linuxAlias,
+ Rm_LinuxValueRange *linuxValues, Rm_AllocatorOpInfo *opInfo)
+{
+ int32_t retVal = RM_OK;
+ bool baseFound = false;
+ bool lengthFound = false;
+ uint32_t valueIndex = 0;
+
+ while ((linuxValues) && (!baseFound || !lengthFound)) {
+ if (linuxAlias->baseOffset == valueIndex) {
+ opInfo->resourceInfo->base = linuxValues->value;
+ baseFound = true;
+
+ if (linuxAlias->lengthOffset == RM_DTB_UTIL_LINUX_ALIAS_OFFSET_NOT_SET) {
+ opInfo->resourceInfo->length = 1;
+ lengthFound = true;
+ }
+ }
+ else if (linuxAlias->lengthOffset == valueIndex) {
+ opInfo->resourceInfo->length = linuxValues->value;
+ lengthFound = true;
+ }
- /* Error checks passed - Create a new transport handle for the specified RM instance */
-
- /* Get memory for a new routing map node from local memory */
- newRouteMapNode = Rm_osalMalloc (sizeof(Rm_TransRouteMapNode), false);
+ linuxValues = (Rm_LinuxValueRange *)linuxValues->nextValue;
+ valueIndex++;
+ }
- /* Populate the new node. The address of the node itself is stored since this address is returned
- * to the application as the Rm_TransportHandle */
- newRouteMapNode->transHandle = newRouteMapNode;
- newRouteMapNode->remoteInstType = transCfg->rmRemoteInstType;
- newRouteMapNode->nextNode = NULL; /* New node will always be NULL */
+ if (!baseFound || !lengthFound) {
+ retVal = RM_ERROR_DATA_NOT_FOUND_AT_LINUX_ALIAS;
+ }
+ else {
+ /* Allocate resource to Linux */
+ retVal = allocatorOperation(rmInst, opInfo);
+ }
+ return (retVal);
+}
- /* Check if there are any entries in the routing map */
- if (existingRouteMap)
- {
- /* At least one entry in the routing map. Add the new routing map node to the end of the
- * routing map node list */
- while (existingRouteMap->nextNode != NULL)
- {
- /* Traverse the list until arriving at the last node */
- existingRouteMap = existingRouteMap->nextNode;
+/* FUNCTION PURPOSE: Finds and reserves Linux resources
+ ***********************************************************************
+ * DESCRIPTION: Parses the Linux DTB for resources consumed by the
+ * Linux kernel. If the resource is found via the
+ * "linux-dtb-alias" property defined in the GRL it is
+ * reserved.
+ */
+static int32_t findAndReserveLinuxResource(Rm_Inst *rmInst, const char *resourceName, void *linuxDtb,
+ Rm_LinuxAlias *linuxAlias)
+{
+ Rm_AllocatorOpInfo opInfo;
+ Rm_ResourceInfo resourceInfo;
+ uint32_t pathOffset;
+ uint32_t pathSize;
+ char *spacePtr;
+ int32_t propOffset;
+ int32_t nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;
+ int32_t prevDepth = RM_DTB_UTIL_STARTING_DEPTH;
+ int32_t depth;
+ int32_t propertyLen;
+ const char *propertyName;
+ const void *propertyData;
+ Rm_LinuxValueRange *linuxValueRange;
+ int32_t retVal = RM_OK;
+
+ memset((void *) &opInfo, 0, sizeof(Rm_AllocatorOpInfo));
+ memset((void *) &resourceInfo, 0, sizeof(Rm_ResourceInfo));
+
+ strncpy(resourceInfo.name, resourceName, RM_NAME_MAX_CHARS);
+ opInfo.serviceSrcInstNode = rmPolicyGetLinuxInstNode(rmInst->validInstances);
+ opInfo.operation = Rm_allocatorOp_ALLOCATE;
+ opInfo.resourceInfo = &resourceInfo;
+
+ while(linuxAlias) {
+ /* Reset parsing variables */
+ pathOffset = 0;
+ pathSize = strlen(linuxAlias->path) + 1;
+ nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;
+ prevDepth = RM_DTB_UTIL_STARTING_DEPTH;
+ resourceInfo.base = 0;
+ resourceInfo.length = 0;
+
+ spacePtr = strpbrk(linuxAlias->path, " ");
+ if (spacePtr) {
+ *spacePtr = '\0';
+ }
+
+ while(pathOffset < pathSize) {
+ /* Move through DTB nodes until next alias path node found */
+ if (strcmp(linuxAlias->path + pathOffset, fdt_get_name(linuxDtb, nodeOffset, NULL))) {
+ nodeOffset = fdt_next_node(linuxDtb, nodeOffset, &depth);
+
+ if ((depth < prevDepth) || (nodeOffset == -FDT_ERR_NOTFOUND)) {
+ /* Returning from subnode that matched part of alias path without finding
+ * resource values */
+ retVal = RM_ERROR_DATA_NOT_FOUND_AT_LINUX_ALIAS;
+ break;
+ }
+ }
+ else {
+ /* Found next alias path node. Move to next node name in path string. */
+ pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);
+ spacePtr = strpbrk(linuxAlias->path + pathOffset, " ");
+ if (spacePtr) {
+ *spacePtr = '\0';
+ }
+
+ prevDepth = fdt_node_depth(linuxDtb, nodeOffset);
+ propOffset = fdt_first_property_offset(linuxDtb, nodeOffset);
+ while ((propOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) &&
+ (pathOffset < pathSize)) {
+ propertyData = fdt_getprop_by_offset(linuxDtb, propOffset,
+ &propertyName, &propertyLen);
+
+ if (strcmp(linuxAlias->path + pathOffset, propertyName) == 0) {
+ /* Found resource at end of alias path */
+ pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);
+ linuxValueRange = rmDtbUtilLinuxExtractValues(propertyData, propertyLen);
+ retVal = reserveLinuxResource(rmInst, linuxAlias,
+ linuxValueRange, &opInfo);
+ rmDtbUtilLinuxFreeValues(linuxValueRange);
+ }
+ propOffset = fdt_next_property_offset(linuxDtb, propOffset);
+ }
+
+ if (propOffset < -FDT_ERR_NOTFOUND) {
+ retVal = propOffset;
+ break;
+ }
+ }
}
- /* Add the new node to the end of the list */
- existingRouteMap->nextNode = newRouteMapNode;
- }
- else
- {
- /* A routing map does not currently exist. The new node is the first entry */
- rmInst->routeMap = newRouteMapNode;
+ if (retVal < RM_OK) {
+ break;
+ }
+ linuxAlias = linuxAlias->nextLinuxAlias;
}
+ return (retVal);
+}
- /* Specify RM instance has registered with a higher level agent */
- if ((newRouteMapNode->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||
- (newRouteMapNode->remoteInstType == Rm_instType_SERVER))
- {
- rmInst->registeredWithDelegateOrServer = true;
+/* FUNCTION PURPOSE: Creates and initializes a resource allocator
+ ***********************************************************************
+ * DESCRIPTION: Creates a resource allocator for the provided
+ * resource name and resource properties retrieved
+ * from the GRL. Resources will be reserved for
+ * the Linux kernel if the Linux DTB is provided
+ * and there are "linux-dtb-alias" properties
+ * specified in the GRL.
+ */
+static int32_t createAndInitAllocator(Rm_Inst *rmInst, const char *resourceName,
+ Rm_ResourceProperties *resourceProperties, void *linuxDtb)
+{
+ Rm_ResourceRange *range = NULL;
+ Rm_ResourceRange *rangeBasePtr = NULL;
+ Rm_NsAssignment *nsAssignments = NULL;
+ Rm_NsAssignment *nsAssignmentBasePtr = NULL;
+ Rm_LinuxAlias *linuxAlias = NULL;
+ Rm_NameServerObjCfg nameServerObjCfg;
+ int32_t retVal = RM_OK;
+
+ if (resourceProperties->rangeData && (resourceProperties->rangeLen > 0)) {
+ range = rangeBasePtr = rmDtbUtilResExtractRange(resourceProperties->rangeData,
+ resourceProperties->rangeLen);
+
+ if ((retVal = createResourceTree(rmInst, resourceName, range)) >= RM_OK) {
+ if (resourceProperties->linuxAliasData && resourceProperties->linuxAliasLen) {
+ if (linuxDtb) {
+ linuxAlias = rmDtbUtilResExtractLinuxAlias(resourceProperties->linuxAliasData,
+ resourceProperties->linuxAliasLen, &retVal);
+ if (linuxAlias) {
+ retVal = findAndReserveLinuxResource(rmInst, resourceName, linuxDtb, linuxAlias);
+ }
+ }
+ else {
+ retVal = RM_ERROR_GRL_LINUX_ALIAS_BUT_NO_DTB;
+ }
+ }
+ }
+ }
+
+ if (retVal >= RM_OK) {
+ if (resourceProperties->nsAssignData && resourceProperties->nsAssignLen) {
+ nsAssignments = rmDtbUtilResExtractNsAssignment(resourceProperties->nsAssignData,
+ resourceProperties->nsAssignLen, &retVal);
+ if (nsAssignments) {
+ nsAssignmentBasePtr = nsAssignments;
+ while (nsAssignments) {
+ memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
+ nameServerObjCfg.nameServerTree = rmInst->nameServer;
+ nameServerObjCfg.nodeCfg.objName = nsAssignments->nsName;
+ nameServerObjCfg.nodeCfg.resourceName = (char *)resourceName;
+ nameServerObjCfg.nodeCfg.resourceBase= nsAssignments->resourceBase;
+ nameServerObjCfg.nodeCfg.resourceLength = nsAssignments->resourceLength;
+ rmNameServerAddObject(&nameServerObjCfg);
+ nsAssignments = nsAssignments->nextNsAssignment;
+ }
+ rmDtbUtilResFreeNsAssignmentList(nsAssignmentBasePtr);
+ }
+ }
}
- return ((Rm_TransportHandle) newRouteMapNode);
+ rmDtbUtilResFreeRange(rangeBasePtr);
+ if (linuxAlias) {
+ rmDtbUtilResFreeLinuxAlias(linuxAlias);
+ }
+ return(retVal);
}
-Rm_Result Rm_unregisterTransport (Rm_Handle rmHandle, Rm_TransportHandle transHandle)
+/* FUNCTION PURPOSE: Recursively parses GRL resource properties
+ ***********************************************************************
+ * DESCRIPTION: Recursively parses and stores GRL resource node
+ * properties using the LIBFDT APIs
+ */
+static int32_t parseResourceProperty(void *globalResourceDtb, int32_t offset,
+ Rm_ResourceProperties *propertyInfo)
{
- Rm_Inst *rmInst = (Rm_Inst *) rmHandle;
- Rm_TransRouteMapNode *routeMapNode = (Rm_TransRouteMapNode *) rmInst->routeMap;
- Rm_TransRouteMapNode *prevNode = NULL;
+ int32_t propertyLen;
+ const char *propertyName;
+ const void *propertyData;
+ Rm_ResourcePropType propertyType;
+ int32_t retVal = RM_OK;
+
+ propertyData = fdt_getprop_by_offset(globalResourceDtb, offset, &propertyName, &propertyLen);
+ propertyType = rmDtbUtilResGetPropertyType(propertyName);
+ if (propertyType == Rm_resourcePropType_RESOURCE_RANGE) {
+ propertyInfo->rangeData = propertyData;
+ propertyInfo->rangeLen = propertyLen;
+ }
+ else if (propertyType == Rm_resourcePropType_NSASSIGNMENT) {
+ propertyInfo->nsAssignData = propertyData;
+ propertyInfo->nsAssignLen = propertyLen;
+ }
+ else if (propertyType == Rm_resourcePropType_RESOURCE_LINUX_ALIAS) {
+ propertyInfo->linuxAliasData = propertyData;
+ propertyInfo->linuxAliasLen = propertyLen;
+ }
+ else {
+ retVal = RM_ERROR_GRL_UNKNOWN_RESOURCE_PROPERTY;
+ }
- /* Make sure a routing map exists for the RM instance */
- if (!routeMapNode)
- {
- return (-1); /* TEMP ERROR RETURN */
+ if (retVal == RM_OK) {
+ offset = fdt_next_property_offset(globalResourceDtb, offset);
+ if (offset >= 0) {
+ retVal = parseResourceProperty(globalResourceDtb, offset, propertyInfo);
+ }
+ else if (offset != -FDT_ERR_NOTFOUND) {
+ /* Error returned by LIBFDT */
+ retVal = offset;
+ }
}
+ return (retVal);
+}
- /* Find the transport handle within the specified RM instance's routing map. */
- while (1)
- {
- if (routeMapNode->transHandle == transHandle)
- {
- /* Match: break out of loop and delete the node */
- break;
- }
- else if (routeMapNode->nextNode == NULL)
- {
- return (-1); /* TEMP ERROR: transhandle does not exist for RM instance */
- }
-
- prevNode = routeMapNode;
- routeMapNode = routeMapNode->nextNode;
+/* FUNCTION PURPOSE: Recursively parses GRL resource nodes
+ ***********************************************************************
+ * DESCRIPTION: Recursively parses GRL resource nodes looking for
+ * resource properties to create the resource allocators.
+ * The LIBFDT APIs are used to parse the GRL.
+ */
+static int32_t parseResourceNode(Rm_Inst *rmInst, void *globalResourceDtb, int32_t nodeOffset, int32_t depth,
+ void *linuxDtb)
+{
+ const char *resourceName = fdt_get_name(globalResourceDtb, nodeOffset, NULL);
+ Rm_ResourceProperties resourceProperties;
+ int32_t retVal = RM_OK;
+ int32_t offset;
+
+ memset((void *)&resourceProperties, 0, sizeof(Rm_ResourceProperties));
+ /* Get properties of resource node */
+ offset = fdt_first_property_offset(globalResourceDtb, nodeOffset);
+ if (offset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) {
+ retVal = parseResourceProperty(globalResourceDtb, offset, &resourceProperties);
+ if (retVal < -FDT_ERR_NOTFOUND) {
+ return (retVal);
+ }
+ if (retVal = createAndInitAllocator(rmInst, resourceName, &resourceProperties, linuxDtb) < RM_OK) {
+ return (retVal);
+ }
+ }
+ else if (offset != -FDT_ERR_NOTFOUND) {
+ /* Error returned by LIBFDT */
+ return (offset);
}
- /* Delete the routing map node */
- if ((prevNode == NULL) && routeMapNode->nextNode)
- {
- /* Node to be deleted exists at start of route map. Map second node to be start of
- * node list as long as there are more than one routing map nodes */
- rmInst->routeMap = routeMapNode->nextNode;
+ offset = fdt_next_node(globalResourceDtb, nodeOffset, &depth);
+ if ((offset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && (depth >= RM_DTB_UTIL_STARTING_DEPTH)) {
+ retVal = parseResourceNode(rmInst, globalResourceDtb, offset, depth, linuxDtb);
+ if (retVal < -FDT_ERR_NOTFOUND) {
+ return (retVal);
+ }
}
- else
- {
- /* Node to be deleted is in the middle or at end of the list. Adjust adjacent
- * nodes pointers. This covers the case where the node to be removed is at the
- * end of the list. */
- prevNode->nextNode = routeMapNode->nextNode;
+ else if (offset != -FDT_ERR_NOTFOUND) {
+ /* Error returned by LIBFDT */
+ return (offset);
}
+ return (retVal);
+}
- /* Remove specification in RM instance that it has been connected to an upper level agent
- * if the node to be deleted has a remote instance type of Client Delegate or Server */
- if ((routeMapNode->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||
- (routeMapNode->remoteInstType == Rm_instType_SERVER))
- {
- rmInst->registeredWithDelegateOrServer = false;
+/* FUNCTION PURPOSE: Initializes server allocators
+ ***********************************************************************
+ * DESCRIPTION: Creates and initializes a server instance's
+ * resource allocators using the GRL and, if
+ * provided, Linux DTB.
+ */
+static int32_t initializeAllocators(Rm_Inst *rmInst, void *globalResourceDtb, void *linuxDtb)
+{
+ int32_t nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;
+ int32_t startDepth = RM_DTB_UTIL_STARTING_DEPTH;
+ int32_t result = RM_OK;
+
+ /* Recursively parse the Global Resource List, creating an allocator for
+ * each resource as specified in the node */
+ result = parseResourceNode(rmInst, globalResourceDtb, nodeOffset, startDepth, linuxDtb);
+
+ return(result);
+}
+
+/**********************************************************************
+ ********************** Internal Functions ****************************
+ **********************************************************************/
+
+/* FUNCTION PURPOSE: Adds a transaction
+ ***********************************************************************
+ * DESCRIPTION: Returns a pointer to a newly created transaction.
+ * The transaction is created based on a new service
+ * request received via the service API or the
+ * transport API (service forwarded from another instance)
+ */
+Rm_Transaction *rmTransactionQueueAdd(Rm_Inst *rmInst)
+{
+ Rm_Transaction *transactionQueue = rmInst->transactionQueue;
+ Rm_Transaction *newTransaction = NULL;
+
+ newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction));
+ if (newTransaction) {
+ memset((void *)newTransaction, 0, sizeof(Rm_Transaction));
+
+ newTransaction->localId = transactionGetSequenceNum(rmInst);
+ newTransaction->nextTransaction = NULL;
+ if (transactionQueue) {
+ while (transactionQueue->nextTransaction) {
+ transactionQueue = transactionQueue->nextTransaction;
+ }
+ transactionQueue->nextTransaction = newTransaction;
+ }
+ else {
+ rmInst->transactionQueue = newTransaction;
+ }
}
+ return (newTransaction);
+}
- /* Delete the node, free the memory associated with the node. */
- Rm_osalFree((void *) routeMapNode, sizeof(Rm_TransRouteMapNode), false);
+/* FUNCTION PURPOSE: Finds a transaction
+ ***********************************************************************
+ * DESCRIPTION: Returns a pointer to a transaction resident
+ * in the transaction queue that matches the provided
+ * transaction ID.
+ */
+Rm_Transaction *rmTransactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)
+{
+ Rm_Transaction *transaction = rmInst->transactionQueue;
- return (RM_OK);
+ while (transaction) {
+ if (transaction->localId == transactionId) {
+ break;
+ }
+ transaction = transaction->nextTransaction;
+ }
+
+ return (transaction);
}
+/* FUNCTION PURPOSE: Deletes a transaction
+ ***********************************************************************
+ * DESCRIPTION: Deletes the transaction with the provided transaction
+ * ID from the instance's transaction queue.
+ */
+int32_t rmTransactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)
+{
+ Rm_Transaction *transaction = rmInst->transactionQueue;
+ Rm_Transaction *prevTransaction = NULL;
+ int32_t retVal = RM_OK;
+
+ while (transaction) {
+ if (transaction->localId == transactionId) {
+ break;
+ }
+
+ prevTransaction = transaction;
+ transaction = transaction->nextTransaction;
+ }
+
+ if (transaction) {
+ if (prevTransaction == NULL) {
+ /* Transaction at start of queue. Map second transaction to start of queue
+ * as long as more than one transactions. */
+ rmInst->transactionQueue = transaction->nextTransaction;
+ }
+ else {
+ /* Transaction in middle or end of queue. */
+ prevTransaction->nextTransaction = transaction->nextTransaction;
+ }
+ Rm_osalFree((void *)transaction, sizeof(Rm_Transaction));
+ }
+ else {
+ retVal = RM_ERROR_SERVICE_TRANS_DOES_NOT_EXIST;
+ }
+ return (retVal);
+}
-Rm_TransVerifyResult Rm_verifyTransport (Rm_Handle, uint32_t timeout,
- Rm_TransFailData *failData)
+/* FUNCTION PURPOSE: Finds an allocator
+ ***********************************************************************
+ * DESCRIPTION: Returns a pointer to an allocator that matches the
+ * provided resource name.
+ */
+Rm_Allocator *rmAllocatorFind(Rm_Allocator *allocatorList, char *resourceName)
{
+ while (allocatorList) {
+ if (strncmp(allocatorList->resourceName, resourceName, RM_NAME_MAX_CHARS) == 0) {
+ break;
+ }
+ allocatorList = allocatorList->nextAllocator;
+ }
+ return (allocatorList);
}
+/* FUNCTION PURPOSE: Processes a transaction
+ ***********************************************************************
+ * DESCRIPTION: Processes transactions created from services
+ * received via the service handle or the transport.
+ * Transactions will be routed within the RM system
+ * based on the RM instance type and the type of
+ * the transaction.
+ */
+void rmTransactionProcessor (Rm_Inst *rmInst, Rm_Transaction *transaction)
+{
+ void *validInstNode;
+ Rm_PolicyCheckCfg privCheckCfg;
+ Rm_NameServerObjCfg nameServerObjCfg;
+ uint32_t allocType = 0;
+
+ /* Handle static transactions originating on this instance. Any other static transactions will be
+ * stored in transaction queue until all transports are up. */
+ if (((rmInst->instType == Rm_instType_CLIENT) || (rmInst->instType == Rm_instType_CLIENT_DELEGATE)) &&
+ (!rmInst->registeredWithDelegateOrServer) &&
+ (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS) == 0)) {
+ if (rmInst->staticInfo.staticPolicy) {
+ if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
+ (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE)) {
+ /* Check request against startup policy */
+ memset((void *)&privCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));
+
+ if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
+ privCheckCfg.type = Rm_policyCheck_INIT;
+ }
+ else {
+ privCheckCfg.type = Rm_policyCheck_USE;
+ }
+ privCheckCfg.policyDtb = rmInst->staticInfo.staticPolicy;
+ privCheckCfg.validInstNode = rmPolicyGetValidInstNode(rmInst->staticInfo.staticValidInstTree,
+ rmInst->instName);
+ privCheckCfg.resourceOffset = rmPolicyGetResourceOffset(rmInst->staticInfo.staticPolicy,
+ transaction->resourceInfo.name);
+ privCheckCfg.resourceBase = transaction->resourceInfo.base;
+ privCheckCfg.resourceLength = transaction->resourceInfo.length;
+
+ if (rmPolicyCheckPrivilege(&privCheckCfg, &transaction->state)) {
+ transaction->state = RM_SERVICE_APPROVED_STATIC;
+ }
+ else if (transaction->state == RM_SERVICE_PROCESSING) {
+ /* Privilege check returned false without error */
+ transaction->state = RM_SERVICE_DENIED_BY_STATIC_POLICY;
+ }
+ }
+ else {
+ transaction->state = RM_SERVICE_DENIED_INVALID_STATIC_REQUEST;
+ }
+ }
+ else {
+ transaction->state = RM_ERROR_REQ_FAILED_NO_STATIC_POLICY;
+ }
+ }
+ else {
+ /* Handle auto-forwarded transactions. These transactions include:
+ * - All request transactions received on Clients are forwarded to the Client Delegate
+ * - NameServer requests received on the Client Delegate are forwarded to the Server */
+ if ((rmInst->instType == Rm_instType_CLIENT) ||
+ ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&
+ ((transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) ||
+ (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) ||
+ (transaction->type == Rm_service_RESOURCE_UNMAP_NAME)))) {
+
+ if ((transaction->state != RM_SERVICE_PROCESSING) &&
+ (transaction->state != RM_SERVICE_APPROVED_STATIC)) {
+ if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
+ /* Transaction did not originate on this instance */
+ transactionResponder(rmInst, transaction);
+ }
+ else {
+ /* Transaction originated on this instance */
+ serviceResponder(rmInst, transaction);
+ }
+ }
+ else {
+ /* Forward request if transport is up. Otherwise, just queue. */
+ if (rmInst->registeredWithDelegateOrServer) {
+ transactionForwarder(rmInst, transaction);
+ }
+ }
+ }
+ else {
+ /* Validate service's originating instance name */
+ if (rmInst->instType == Rm_instType_SERVER) {
+ validInstNode = rmPolicyGetValidInstNode(rmInst->validInstances, transaction->serviceSrcInstName);
+ if (validInstNode == NULL) {
+ transaction->state = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;
+
+ /* Send result via responder if transaction did not originate from this instance */
+ if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
+ transactionResponder(rmInst, transaction);
+ }
+ }
+ }
+
+ switch (transaction->type) {
+ case Rm_service_RESOURCE_ALLOCATE_INIT:
+ case Rm_service_RESOURCE_ALLOCATE_USE:
+ case Rm_service_RESOURCE_FREE:
+ if ((transaction->state != RM_SERVICE_PROCESSING) &&
+ (transaction->state != RM_SERVICE_APPROVED_STATIC)) {
+ /* Transaction complete */
+ if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
+ /* Transaction result not destined for this instance */
+ transactionResponder(rmInst, transaction);
+ }
+ else {
+ /* Transaction result destined for this instance */
+ serviceResponder(rmInst, transaction);
+ }
+ }
+ else {
+ /* Complete allocation/free request */
+ if (transaction->type == Rm_service_RESOURCE_FREE) {
+ freeHandler(rmInst, transaction, validInstNode);
+ }
+ else {
+ switch (transaction->type) {
+ case Rm_service_RESOURCE_ALLOCATE_INIT:
+ RM_policy_SET_PERM(allocType, RM_POLICY_PERM_INIT_SHIFT, 1);
+ break;
+ case Rm_service_RESOURCE_ALLOCATE_USE:
+ RM_policy_SET_PERM(allocType, RM_POLICY_PERM_USE_SHIFT, 1);
+ break;
+ }
+ allocationHandler(rmInst, transaction, validInstNode, allocType);
+ }
+ }
+ break;
+ case Rm_service_RESOURCE_MAP_TO_NAME:
+ case Rm_service_RESOURCE_GET_BY_NAME:
+ case Rm_service_RESOURCE_UNMAP_NAME:
+ /* NameServer resides on server */
+ memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
+ if (rmInst->nameServer) {
+ nameServerObjCfg.nameServerTree = rmInst->nameServer;
+ nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
+ if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {
+ nameServerObjCfg.nodeCfg.resourceName = transaction->resourceInfo.name;
+ nameServerObjCfg.nodeCfg.resourceBase= transaction->resourceInfo.base;
+ nameServerObjCfg.nodeCfg.resourceLength = transaction->resourceInfo.length;
+ transaction->state = rmNameServerAddObject(&nameServerObjCfg);
+ }
+ else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {
+ if ((transaction->state = rmNameServerFindObject(&nameServerObjCfg)) ==
+ RM_SERVICE_PROCESSING) {
+ strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
+ transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
+ transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
+ transaction->state = RM_SERVICE_APPROVED;
+ }
+ }
+ else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {
+ transaction->state = rmNameServerDeleteObject(&nameServerObjCfg);
+ }
+ }
+ else {
+ transaction->state = RM_ERROR_NAMESERVER_DOES_NOT_EXIST;
+ }
+
+ /* Send result via responder if transaction did not originate from this instance */
+ if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
+ transactionResponder(rmInst, transaction);
+ }
+ break;
+ }
+ }
+ }
+
+ /* Forward any queued requests that weren't forwarded yet */
+ if (rmInst->registeredWithDelegateOrServer) {
+ transaction = rmInst->transactionQueue;
+ while(transaction) {
+ if (((transaction->state == RM_SERVICE_PROCESSING) ||
+ (transaction->state == RM_SERVICE_APPROVED_STATIC)) &&
+ !transaction->hasBeenForwarded) {
+ transactionForwarder(rmInst, transaction);
+ }
+ transaction = transaction->nextTransaction;
+ }
+ }
+}
+
+/**********************************************************************
+ ********************** Application visible APIs **********************
+ **********************************************************************/
+
+/* FUNCTION PURPOSE: Display status of managed resources
+ ***********************************************************************
+ * DESCRIPTION: Prints the status (allocate/free status, as well as
+ * owners) for all resources managed by the RM
+ * instance network. Also, prints the NameServer name
+ * entries. This function is only available on server
+ * instances.
+ */
+void Rm_printResourceStatus(Rm_Handle rmServerHandle)
+{
+ Rm_Inst *rmInst = (Rm_Inst *)rmServerHandle;
+ Rm_Allocator *allocator = rmInst->allocators;
+ Rm_Owner *owners;
+ Rm_ResourceTree *treeRoot;
+ Rm_ResourceNode *treeNode;
+
+ if (rmInst->instType == Rm_instType_SERVER) {
+ while (allocator != NULL) {
+ Rm_osalLog("Resource: %s\n", allocator->resourceName);
+
+ treeRoot = allocator->allocatorRootEntry;
+
+ RB_FOREACH(treeNode, _Rm_AllocatorResourceTree, treeRoot) {
+ Rm_osalLog(" %10d - %10d ", treeNode->base,
+ treeNode->base + treeNode->length -1);
+
+ if (treeNode->allocationCount == 0) {
+ Rm_osalLog("NOT ALLOCATED\n");
+ }
+ else {
+ owners = treeNode->ownerList;
+ Rm_osalLog("allocated to");
+ while (owners) {
+ Rm_osalLog(" %s", owners->instNameNode->name);
+ owners = owners->nextOwner;
+ }
+ Rm_osalLog("\n");
+ }
+ }
+ allocator = allocator->nextAllocator;
+ }
+ rmNameServerPrintObjects(rmInst->nameServer);
+ }
+}
+
+/* FUNCTION PURPOSE: Display status of a RM instance
+ ***********************************************************************
+ * DESCRIPTION: Prints the current status of various RM instance
+ * properties such as the state of all transactions
+ * in the transaction queue and registered transports
+ */
+void Rm_printInstanceStatus(Rm_Handle rmHandle)
+{
+ Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
+ Rm_Transport *transportList = (Rm_Transport *)rmInst->transports;
+ Rm_Transaction *transactionQ = rmInst->transactionQueue;
+
+ Rm_osalLog("Instance name: %s\n", rmInst->instName);
+ if (rmInst->instType == Rm_instType_SERVER) {
+ Rm_osalLog("Type: Server\n");
+ }
+ else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
+ Rm_osalLog("Type: Client Delegate\n");
+ }
+ else {
+ Rm_osalLog("Type: Client\n");
+ }
+
+ if (transportList) {
+ Rm_osalLog("\nRegistered Transports:\n");
+ while (transportList) {
+ Rm_osalLog(" Remote instName: %s\n", transportList->remoteInstName);
+ if (transportList->remoteInstType == Rm_instType_SERVER) {
+ Rm_osalLog(" Remote instType: Server\n");
+ }
+ else if (transportList->remoteInstType == Rm_instType_CLIENT_DELEGATE) {
+ Rm_osalLog(" Remote instType: Client Delegate\n");
+ }
+ else {
+ Rm_osalLog(" Remote instType: Client\n");
+ }
+ Rm_osalLog(" appTransportHandle: 0x%08x\n", transportList->appTransportHandle);
+ Rm_osalLog("\n");
+ transportList = transportList->nextTransport;
+ }
+ }
+
+ if (transactionQ) {
+ Rm_osalLog("\nQueued Service Transactions:\n");
+ while (transactionQ) {
+ Rm_osalLog(" Service type: %d\n", transactionQ->type);
+ Rm_osalLog(" Service ID: %d\n", transactionQ->localId);
+ Rm_osalLog(" Service srcInstName %s\n", transactionQ->serviceSrcInstName);
+ Rm_osalLog(" Service state: %d\n", transactionQ->state);
+ Rm_osalLog(" Resource name: %s\n", transactionQ->resourceInfo.name);
+ Rm_osalLog(" Resource base: %d\n", transactionQ->resourceInfo.base);
+ Rm_osalLog(" Resource length: %d\n", transactionQ->resourceInfo.length);
+ Rm_osalLog(" Resource alignment: %d\n", transactionQ->resourceInfo.alignment);
+ Rm_osalLog(" Resource NS name: %s\n", transactionQ->resourceInfo.nameServerName);
+ Rm_osalLog("\n");
+ transactionQ = transactionQ->nextTransaction;
+ }
+ }
+}
+
+/* FUNCTION PURPOSE: RM instance creation and initialization
+ ***********************************************************************
+ * DESCRIPTION: Returns a new RM instance created and initialized
+ * using the parameters provided via the initCfg
+ * structure.
+ */
+Rm_Handle Rm_init(const Rm_InitCfg *initCfg, int32_t *result)
+{
+ Rm_Inst *rmInst;
+ void *globalResourceDtb = NULL;
+ void *linuxResourceDtb = NULL;
+ bool addLinux = false;
+
+ *result = RM_OK;
+
+ if ((initCfg->instName == NULL) ||
+ ((strlen(initCfg->instName) + 1) > RM_NAME_MAX_CHARS)) {
+ *result = RM_ERROR_INVALID_INST_NAME;
+ return (NULL);
+ }
+
+ if (initCfg->instType >= Rm_instType_LAST) {
+ *result = RM_ERROR_INVALID_INST_TYPE;
+ }
+
+ /* Create and initialize instance */
+ rmInst = Rm_osalMalloc (sizeof(Rm_Inst));
+ memset ((void *) rmInst, 0, sizeof(Rm_Inst));
+ rmInst->isLocked = false;
+ rmInst->registeredWithDelegateOrServer = false;
+ rmInst->transactionSeqNum = transactionInitSequenceNum();
+
+ rmInst->instType = initCfg->instType;
+ strncpy (rmInst->instName, initCfg->instName, RM_NAME_MAX_CHARS);
+
+ if (rmInst->instType == Rm_instType_SERVER) {
+ if (!initCfg->instCfg.serverCfg.globalResourceList ||
+ !initCfg->instCfg.serverCfg.globalPolicy) {
+ *result = RM_ERROR_INVALID_SERVER_CONFIGURATION;
+ Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
+ return(NULL);
+ }
+
+ rmInst->policy = initCfg->instCfg.serverCfg.globalPolicy;
+ fdt_open_into(rmInst->policy, rmInst->policy, fdt_totalsize(rmInst->policy));
+
+ if (initCfg->instCfg.serverCfg.linuxDtb) {
+ linuxResourceDtb = initCfg->instCfg.serverCfg.linuxDtb;
+ fdt_open_into(linuxResourceDtb, linuxResourceDtb, fdt_totalsize(linuxResourceDtb));
+ addLinux = true;
+ }
+
+ /* Create valid instance list from policy. Must be done prior to parsing
+ * GRL so that Linux resources can be reserved correctly */
+ rmInst->validInstances = rmPolicyCreateValidInstTree(rmInst->policy, addLinux, result);
+ /* Validate policy assignment strings */
+ *result = rmPolicyValidatePolicy(rmInst->policy, rmInst->validInstances);
+
+ rmInst->nameServer = rmNameServerInit();
+
+ globalResourceDtb = initCfg->instCfg.serverCfg.globalResourceList;
+ fdt_open_into(globalResourceDtb, globalResourceDtb, fdt_totalsize(globalResourceDtb));
+
+ if ((*result = initializeAllocators(rmInst, globalResourceDtb, linuxResourceDtb)) == RM_OK) {
+ *result = rmPolicyValidatePolicyResourceNames(rmInst->policy, (void *)rmInst->allocators);
+ }
+ if (*result < RM_OK) {
+ Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
+ return(NULL);
+ }
+ }
+
+ if ((rmInst->instType == Rm_instType_CLIENT) &&
+ (initCfg->instCfg.clientCfg.staticPolicy)) {
+ rmInst->staticInfo.staticPolicy = initCfg->instCfg.clientCfg.staticPolicy;
+ }
+ else if ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&
+ (initCfg->instCfg.cdCfg.staticPolicy)) {
+ rmInst->staticInfo.staticPolicy = initCfg->instCfg.cdCfg.staticPolicy;
+ }
+ if (rmInst->staticInfo.staticPolicy) {
+ fdt_open_into(rmInst->staticInfo.staticPolicy, rmInst->staticInfo.staticPolicy,
+ fdt_totalsize(rmInst->staticInfo.staticPolicy));
+ rmInst->staticInfo.staticValidInstTree = rmPolicyCreateValidInstTree(rmInst->staticInfo.staticPolicy,
+ addLinux, result);
+ if (*result == RM_OK) {
+ /* Validate policy assignment strings */
+ *result = rmPolicyValidatePolicy(rmInst->staticInfo.staticPolicy, rmInst->staticInfo.staticValidInstTree);
+ }
+ if (*result != RM_OK) {
+ if (rmInst->staticInfo.staticValidInstTree) {
+ rmPolicyFreeValidInstTree(rmInst->staticInfo.staticValidInstTree);
+ }
+ Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
+ rmInst = NULL;
+ }
+ }
+ return ((Rm_Handle) rmInst);
+}
+
+/* FUNCTION PURPOSE: Returns RM version information
+ ***********************************************************************
+ */
uint32_t Rm_getVersion (void)
{
return RM_VERSION_ID;
}
-
+/* FUNCTION PURPOSE: Returns RM version string
+ ***********************************************************************
+ */
const char* Rm_getVersionStr (void)
{
return rmVersionStr;
}
-/**
-@}
-*/