]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/rm-lld.git/blobdiff - src/rm_policy.c
Coverity fixes
[keystone-rtos/rm-lld.git] / src / rm_policy.c
index 07525a7a148e2baaa38005b7d071e88400f533e6..63f1dc0e1cd136aa9639a7aafd1aa8fe894a6a8f 100644 (file)
@@ -1,12 +1,12 @@
 /**
- *   @file  rmpolicy.c
+ *   @file  rm_policy.c
  *
  *   @brief   
- *      This is the Resource Manager Policy source.
+ *      Resource Manager Policy source.
  *
  *  \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 <ctype.h>
 
 /* RM external API includes */
-#include <ti/drv/rm/rm_policy.h>
+#include <ti/drv/rm/rm.h>
 
 /* RM internal API includes */
-//#include <ti/drv/rm/include/rm_policyloc.h>
+#include <ti/drv/rm/include/rm_internal.h>
+#include <ti/drv/rm/include/rm_loc.h>
+#include <ti/drv/rm/include/rm_allocatorloc.h>
+#include <ti/drv/rm/include/rm_policyloc.h>
 #include <ti/drv/rm/include/rm_dtb_utilloc.h>
 
 /* RM LIBFDT includes */
-#include <ti/drv/rm/src/libfdt/libfdt.h>
+#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>
 
+/**********************************************************************
+ *********************** Policy Globals *******************************
+ **********************************************************************/
+
+/* Character used in Policies to specify all RM instances receive
+ * the defined permissions for a resource node */
+const char Rm_policyAllInstances[] = "*";
+
+/**********************************************************************
+ ******************** Local Policy Functions **************************
+ **********************************************************************/
+
+/* FUNCTION PURPOSE: Returns a pointer to the valid instance tree
+ ***********************************************************************
+ * DESCRIPTION: Returns a pointer to the instance's valid instance
+ *              tree based on the instance type
+ */
+static Rm_PolicyValidInstTree *policyGetValidInstTree(Rm_Handle rmHandle)
+{
+    Rm_Inst                *rmInst = (Rm_Inst *)rmHandle;
+    Rm_PolicyValidInstTree *tree = NULL;
+
+    if ((rmInst->instType == Rm_instType_SERVER) ||
+        (rmInst->instType == Rm_instType_SHARED_SERVER)) {
+        tree = rmInst->u.server.globalValidInstTree;
+    }
+    else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
+        tree = rmInst->u.cd.cdValidInstTree;
+    }
+    else if (rmInst->instType == Rm_instType_CLIENT) {
+        tree = rmInst->u.client.staticValidInstTree;
+    }
+    return(tree);
+}
+
+/* FUNCTION PURPOSE: Validates the instance names in a permissions string
+ ***********************************************************************
+ * DESCRIPTION: Returns RM_OK if all the instance names in a permissions
+ *              string match instance names defined in the valid instance
+ *              list.  RM_ERROR_PERM_STR_INST_NOT_VALID is returned if
+ *              there are any mismatches
+ */
+static int32_t policyCheckInstances(Rm_Handle rmHandle, Rm_PolicyPermission *permissionsList)
+{
+    while (permissionsList) {
+        if (strncmp(permissionsList->instName, Rm_policyAllInstances, RM_NAME_MAX_CHARS) &&
+            (!rmPolicyGetValidInstNode(rmHandle, permissionsList->instName))) {
+            return(RM_ERROR_PERM_STR_INST_NOT_VALID);
+        }
+        permissionsList = permissionsList->nextPermission;
+    }
+    return(RM_OK);
+}
+
+/* FUNCTION PURPOSE: Parses a permissions subgroup
+ ***********************************************************************
+ * DESCRIPTION: Returns a linked list of policy permissions defining
+ *              which RM instance referenced in the permissions subgroup
+ *              get which permissions.  Returns NULL if any syntax
+ *              errors are encountered during the parsing.  The error
+ *              is returned via the result pointer parameter.
+ */
+static Rm_PolicyPermission *policyParseSubPermission(char *permStrStart, char *permStrEnd, 
+                                                     int32_t *result)
+{
+    Rm_PolicyPermission *startPerm = NULL;
+    Rm_PolicyPermission *newPerm = NULL;
+    Rm_PolicyPermission *prevPerm = NULL;
+    Rm_PolicyPermission *nextPerm = NULL;
+    char                *permStrPtr = NULL;
+    char                *subgroupStart = NULL;
+    char                *subgroupEnd = NULL;
+    uint32_t             permStrLen = (uint32_t)(permStrEnd - permStrStart + 1);
+    char                 instNameTemp[RM_NAME_MAX_CHARS];
+    uint32_t             instNameIndex;
+    int                  foundInstName;
+    int                  instNameComplete;
+    int                  assignmentLeft;
+    int                  assignmentRight;
+
+    /* Create a local copy of the sub-permission string */
+    permStrPtr = Rm_osalMalloc(permStrLen);
+    strncpy(permStrPtr, permStrStart, permStrLen);
+    /* Make sure the last character in the copied sub-permission string is null */
+    permStrPtr[permStrLen - 1] = '\0';
+
+    permStrStart = permStrPtr;
+    permStrEnd = permStrPtr + strlen(permStrPtr);
+
+    /* Find the beginning and end of the sub-permission instance group */
+    subgroupStart = strchr(permStrStart, RM_POLICY_PERM_SUBGROUP_START);
+    subgroupEnd = strchr(permStrStart, RM_POLICY_PERM_SUBGROUP_END);
+
+    if ((!subgroupStart) || (!subgroupEnd) || (subgroupStart > subgroupEnd) ||
+        ((subgroupStart != strrchr(permStrStart, RM_POLICY_PERM_SUBGROUP_START)) &&
+         (subgroupEnd != strrchr(permStrStart, RM_POLICY_PERM_SUBGROUP_END)))) {
+        /* Free the memory associated with the temp string and return an error if:
+         * a) Could not find the instance group start
+         * b) Could not find the instance group end
+         * c) Subgroup start and end are out of order
+         * d) There is more than one instance subgroup specified in the string.  There
+         *    should only be one subgroup per sub-permission string */
+        *result = RM_ERROR_PERM_STR_TOO_MANY_INST_GROUPS;
+        goto parseError;
+    }
+
+    /* Create a permission entry for each instance specified in the instance group.
+     * Instances names are separated by one or more spaces. */
+    permStrPtr = subgroupStart + 1;
+    instNameIndex = 0;
+    foundInstName = RM_FALSE;
+    instNameComplete = RM_FALSE;
+    while (permStrPtr <= subgroupEnd) {
+        if ((isspace(*permStrPtr) || (*permStrPtr == RM_POLICY_PERM_SUBGROUP_END))
+            && foundInstName) {
+            /* First space encountered after copying an instance name.  This
+             * terminates the instance name.  All other space characters are
+             * ignored. */
+            instNameTemp[instNameIndex] = '\0';
+            instNameComplete = RM_TRUE; 
+        }
+        else {
+            if (!foundInstName) {
+                /* First non-whitespace character encountered is the start of an
+                 * instance name */
+                foundInstName = RM_TRUE;
+            }
+
+            /* Copy the character into the temporary instance name string */
+            instNameTemp[instNameIndex++] = *permStrPtr;
+        }
+
+        if (instNameComplete) {
+            newPerm = (Rm_PolicyPermission *) Rm_osalMalloc(sizeof(Rm_PolicyPermission));
+            memset((void *)newPerm, 0, sizeof(Rm_PolicyPermission));
+
+            strncpy(newPerm->instName, instNameTemp, RM_NAME_MAX_CHARS);
+            newPerm->nextPermission = NULL;
+
+            if (prevPerm == NULL) {
+                /* Save the first instance so it can be returned */
+                startPerm = newPerm;
+            }
+            else {
+                prevPerm->nextPermission = newPerm;
+            }
+            prevPerm = newPerm;
+
+            instNameComplete = RM_FALSE;
+            instNameIndex = 0;
+            foundInstName = RM_FALSE;
+        }
+        else if (instNameIndex == RM_NAME_MAX_CHARS) {
+            /* Instance name is longer than max length */
+            *result = RM_ERROR_INST_NAME_IN_ASSIGNMENT_TOO_LONG;
+            goto parseError;
+        }
+
+        permStrPtr++;
+    }
+
+    /* Fill in the permissions for each instance name */
+
+    /* Look on left of instance group for permission assignments. */
+    permStrPtr = subgroupStart - 1;
+    assignmentLeft = RM_FALSE;
+    while (permStrPtr >= permStrStart)
+    {
+        if (*permStrPtr == RM_POLICY_PERM_ASSIGNMENT) {
+            if (assignmentLeft) {
+                /* Assignment character has been found more than once.  This is a
+                 * syntax error.  Free the permission list and the temporary string
+                 * and return. */
+                *result = RM_ERROR_PERM_STR_TOO_MANY_ASSIGN_CHARS;
+                goto parseError;
+            }
+            else {
+                assignmentLeft = RM_TRUE;
+            }
+        }
+        else if (!isspace(*permStrPtr)) {
+            if (assignmentLeft) {
+                if ((*permStrPtr == RM_POLICY_PERM_INIT_LOWER) || 
+                    (*permStrPtr == RM_POLICY_PERM_INIT_UPPER)) {
+                    newPerm = startPerm;
+                    while (newPerm) {
+                        RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_INIT_SHIFT, 1);
+                        newPerm = newPerm->nextPermission;
+                    }
+                }
+                else if ((*permStrPtr == RM_POLICY_PERM_USE_LOWER) || 
+                         (*permStrPtr == RM_POLICY_PERM_USE_UPPER)) {
+                    newPerm = startPerm;
+                    while (newPerm) {                                           
+                        RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_USE_SHIFT, 1);
+                        newPerm = newPerm->nextPermission;
+                    }
+                }
+                else if ((*permStrPtr == RM_POLICY_PERM_EXCLUSIVE_LOWER) || 
+                         (*permStrPtr == RM_POLICY_PERM_EXCLUSIVE_UPPER)) {
+                    newPerm = startPerm;
+                    while (newPerm) {                       
+                        RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_EXCLUSIVE_SHIFT, 1);
+                        newPerm = newPerm->nextPermission;
+                    }
+                }
+                else if ((*permStrPtr == RM_POLICY_PERM_SHARED_LINUX_LOWER) || 
+                         (*permStrPtr == RM_POLICY_PERM_SHARED_LINUX_UPPER)) {
+                    newPerm = startPerm;
+                    while (newPerm) {                       
+                        RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_SHARED_LINUX_SHIFT, 1);
+                        newPerm = newPerm->nextPermission;
+                    }
+                }                
+                else {
+                    /* Invalid permission character.  This is a
+                     * syntax error.  Free the permission list and the temporary string
+                     * and return. */
+                    *result = RM_ERROR_PERM_STR_INVALID_CHAR;
+                    goto parseError;
+                }
+            }
+            else {
+                /* Character found without the assignment character being found.  This is a
+                 * syntax error.  Free the permission list and the temporary string
+                 * and return. */
+                *result = RM_ERROR_PERM_CHAR_WITHOUT_ASSIGN_CHAR;
+                goto parseError;
+            }
+        }
+        permStrPtr--;
+    }
+
+    /* Look on right of instance group for permission assignments. */
+    permStrPtr = subgroupEnd + 1;
+    assignmentRight = RM_FALSE;
+    while (permStrPtr < permStrEnd) {
+        if (assignmentLeft && (!isspace(*permStrPtr))) {
+            /* There should be nothing but spaces on right if assignment was already found on left */
+            *result = RM_ERROR_INVALID_PERMS_CHAR_ON_RIGHT;
+            goto parseError;             
+        }
+        
+        if (*permStrPtr == RM_POLICY_PERM_ASSIGNMENT) {
+            if (assignmentRight) {
+                /* Assignment character has been found more than once.  This is a
+                 * syntax error.  Free the permission list and the temporary string
+                 * and return. */
+                *result = RM_ERROR_PERM_STR_TOO_MANY_ASSIGN_CHARS;
+                goto parseError;               
+            }
+            else {
+                assignmentRight = RM_TRUE;
+            }
+        }
+        else if (!isspace(*permStrPtr)) {
+            if (assignmentRight) {
+                if ((*permStrPtr == RM_POLICY_PERM_INIT_LOWER) || 
+                    (*permStrPtr == RM_POLICY_PERM_INIT_UPPER)) {
+                    newPerm = startPerm;
+                    while (newPerm) {
+                        RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_INIT_SHIFT, 1);
+                        newPerm = newPerm->nextPermission;
+                    }
+                }
+                else if ((*permStrPtr == RM_POLICY_PERM_USE_LOWER) || 
+                         (*permStrPtr == RM_POLICY_PERM_USE_UPPER)) {
+                    newPerm = startPerm;
+                    while (newPerm) {                                           
+                        RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_USE_SHIFT, 1);
+                        newPerm = newPerm->nextPermission;
+                    }
+                }
+                else if ((*permStrPtr == RM_POLICY_PERM_EXCLUSIVE_LOWER) || 
+                         (*permStrPtr == RM_POLICY_PERM_EXCLUSIVE_UPPER)) {
+                    newPerm = startPerm;
+                    while (newPerm) {                       
+                        RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_EXCLUSIVE_SHIFT, 1);
+                        newPerm = newPerm->nextPermission;
+                    }
+                }
+                else if ((*permStrPtr == RM_POLICY_PERM_SHARED_LINUX_LOWER) || 
+                         (*permStrPtr == RM_POLICY_PERM_SHARED_LINUX_UPPER)) {
+                    newPerm = startPerm;
+                    while (newPerm) {                       
+                        RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_SHARED_LINUX_SHIFT, 1);
+                        newPerm = newPerm->nextPermission;
+                    }
+                }                  
+                else {
+                    /* Invalid permission character.  This is a
+                     * syntax error.  Free the permission list and the temporary string
+                     * and return. */
+                    *result = RM_ERROR_PERM_STR_INVALID_CHAR;
+                    goto parseError;                   
+                }
+            }
+            else {
+                /* Character found without the assignment character being found.  This is a
+                 * syntax error.  Free the permission list and the temporary string
+                 * and return. */
+                *result = RM_ERROR_PERM_STR_TOO_MANY_ASSIGN_CHARS;
+                goto parseError;
+            }
+        }
+        permStrPtr++;
+    }
+
+    Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
+    *result = RM_OK;
+    return (startPerm);
+
+parseError:
+    while (startPerm) {
+        nextPerm = startPerm->nextPermission;
+        Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
+        startPerm = nextPerm;
+    }    
+    Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
+    return(NULL);     
+}
+
+/* FUNCTION PURPOSE: Frees a linked list of assignment permissions
+ ***********************************************************************
+ * DESCRIPTION: Frees the memory associated with a linked list of
+ *              assignment permissions extracted from a permissions
+ *              assignment subgroup in a policy DTB.
+ */
+static void policyFreeAssignmentPermissions(Rm_PolicyPermission *permissionList)
+{
+    Rm_PolicyPermission *nextPerm;
+    
+    while (permissionList) {
+        nextPerm = permissionList->nextPermission;
+        Rm_osalFree((void *)permissionList, sizeof(Rm_PolicyPermission));
+        permissionList = nextPerm;
+    }
+}
+
+/* FUNCTION PURPOSE: Extracts permissions from a Policy "assignment"
+ ***********************************************************************
+ * DESCRIPTION: Returns a linked list of permissions for a resource node
+ *              containing an "assignment" property in the Policy DTB.
+ *              Each node in the linked list will contain a valid instance
+ *              name along with the permissions assigned to the instance
+ */
+static Rm_PolicyPermission *policyGetAssignmentPermissions(Rm_PolicyAssignment *assignment, 
+                                                           int32_t *result)
+{
+    Rm_PolicyPermission *startPerm = NULL;
+    Rm_PolicyPermission *newPerm = NULL;
+    Rm_PolicyPermission *prevPerm = NULL;
+    char                *permStrStart = assignment->permissionsList;
+    char                *permStrEnd;
+    uint32_t             permStrLen = strlen(assignment->permissionsList) + 1;
+    uint32_t             i = 0;
+
+    *result = RM_OK;
+    
+    while(i < permStrLen) {
+        /* Find the first sub-permission specification and parse it.  A sub-permission
+         * can be terminated by the termination character or the end of the string. */
+        if (!(permStrEnd = strchr(permStrStart, RM_POLICY_PERM_TERMINATOR))) {           
+            /* Sub-permission termination character not found.  The permission string
+             * end is the end of the entire permission string */
+            permStrEnd = permStrStart + strlen(permStrStart);
+        }
+
+        newPerm = policyParseSubPermission(permStrStart, permStrEnd, result);
+
+        if (*result != RM_OK) {
+            /* Delete the permission list that's been created thus far, return
+             * the error and NULL for the permission list */
+            policyFreeAssignmentPermissions(startPerm);
+            return(NULL);
+        }
+
+        if (prevPerm == NULL) {
+            startPerm = newPerm;
+        }
+        else {
+            prevPerm->nextPermission = newPerm;
+        }
+
+        /* Set prevPerm to the last sub-permission returned by the sub-permission parser */
+        prevPerm = newPerm;
+        while(prevPerm->nextPermission != NULL) {
+            prevPerm = prevPerm->nextPermission;
+        }
+        
+        /* Update the number of characters parsed from the permission list and point to 
+         * the start of the next sub-permission */
+        i += ((uint32_t)(permStrEnd - permStrStart + 1));
+        permStrStart = permStrEnd + 1;
+    }
+
+    return(startPerm);
+}
+
+/* FUNCTION PURPOSE: Validates a policy "assignment" string list
+ ***********************************************************************
+ * DESCRIPTION: Returns RM_OK if the specified Policy DTB "assignment"
+ *              property specification parses okay and all the RM
+ *              instances in the assignment match RM instances in the
+ *              valid instances list
+ */
+static int32_t policyValidateAssignmentPermissions(Rm_Handle rmHandle,
+                                                   Rm_PolicyAssignment *assignmentList)
+{
+    Rm_PolicyAssignment *assignment = assignmentList;
+    Rm_PolicyPermission *permissionList;
+    int32_t              result;
+
+    while (assignment) {
+        /* Make sure assignment's permissions parse okay */
+        permissionList = policyGetAssignmentPermissions(assignment, &result);
+        if (result != RM_OK) {
+            return(result);
+        }                        
+        
+        if (result = policyCheckInstances(rmHandle, permissionList) != RM_OK) {
+            policyFreeAssignmentPermissions(permissionList);
+            return(result);
+        }
+
+        policyFreeAssignmentPermissions(permissionList);
+        assignment = assignment->nextAssignment;
+    }
+
+    return (RM_OK);
+}
+
+/**********************************************************************
+ ************************ Internal Policy APIs ************************
+ **********************************************************************/
+
+/* FUNCTION PURPOSE: Returns a pointer to the instance policy
+ ***********************************************************************
+ * DESCRIPTION: Returns a pointer to the instance's policy based on
+ *              the instance type
+ */
+void *rmPolicyGetPolicy(Rm_Handle rmHandle)
+{
+    Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
+    void    *policy = NULL;
+
+    if ((rmInst->instType == Rm_instType_SERVER) ||
+        (rmInst->instType == Rm_instType_SHARED_SERVER)) {
+        policy = rmInst->u.server.globalPolicy;
+    }
+    else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
+        policy = rmInst->u.cd.cdPolicy;
+    }
+    else if (rmInst->instType == Rm_instType_CLIENT) {
+        policy = rmInst->u.client.staticPolicy;
+    }
+    return(policy);
+}
+
+/* FUNCTION PURPOSE: Get a valid instace node from the valid inst tree
+ ***********************************************************************
+ * DESCRIPTION: Returns a valid instance node from the valid instance
+ *              tree that matches the specified instName
+ */
+Rm_PolicyValidInstNode *rmPolicyGetValidInstNode(Rm_Handle rmHandle, char *instName)
+{
+    Rm_Inst                *rmInst = (Rm_Inst *)rmHandle;
+    Rm_PolicyValidInstTree *treeRoot = policyGetValidInstTree(rmHandle);
+    Rm_PolicyValidInstNode  findNode;
+
+    if (rmInst->instType == Rm_instType_SHARED_SERVER) {
+        rmPolicyValidInstTreeInv(treeRoot);
+    }
+
+    memset((void *)&findNode, 0, sizeof(Rm_PolicyValidInstNode));
+    strncpy(findNode.name, instName, RM_NAME_MAX_CHARS);
+    
+    return (RB_FIND(_Rm_PolicyValidInstTree, treeRoot, &findNode));
+}
+
+/* FUNCTION PURPOSE: Gets the Linux Valid instance node
+ ***********************************************************************
+ * DESCRIPTION: Returns a pointer to the valid instance node in the
+ *              valid instance tree that matches the instance name
+ *              reserved for resource assigned to the Linux kernel.
+ */
+Rm_PolicyValidInstNode *rmPolicyGetLinuxInstNode(Rm_Handle rmHandle)
+{
+    char linuxName[] = RM_ALLOCATED_TO_LINUX;
+
+    return (rmPolicyGetValidInstNode(rmHandle, linuxName));
+}
+
+/* FUNCTION PURPOSE: Validates resource permissions against a Policy DTB
+ ***********************************************************************
+ * DESCRIPTION: Returns TRUE if the instance name has the specified
+ *              permissions for the specified resource in the Policy
+ *              DTB.  Otherwise, returns FALSE.
+ */
+int rmPolicyCheckPrivilege(Rm_PolicyCheckCfg *privilegeCfg, int32_t *result)
+{
+    int32_t              propertyOffset;
+    const char          *propertyName;
+    int32_t              propertyLen;
+    const void          *propertyData;
+    Rm_PolicyAssignment *assignment = NULL;
+    Rm_PolicyAssignment *assignmentStart = NULL;
+    Rm_PolicyPermission *permission = NULL;
+    Rm_PolicyPermission *permissionStart = NULL;
+    uint32_t             assignmentEnd;
+    uint32_t             resourceEnd = privilegeCfg->resourceBase + privilegeCfg->resourceLength - 1;
+    int                  foundInstance;
+
+    *result = RM_OK;
+
+    /* Get the resource's assignments */
+    propertyOffset = fdt_first_property_offset(privilegeCfg->policyDtb, privilegeCfg->resourceOffset);
+    if (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
+        while (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
+            propertyData = fdt_getprop_by_offset(privilegeCfg->policyDtb, propertyOffset, &propertyName, &propertyLen);
+            if (rmDtbUtilPolicyGetPropertyType(propertyName) == Rm_policyPropType_ASSIGNMENTS) {
+                assignment = assignmentStart = rmDtbUtilPolicyExtractAssignments(propertyData, propertyLen);
+                break;
+            }
+            propertyOffset = fdt_next_property_offset(privilegeCfg->policyDtb, propertyOffset);
+        }
+    }
+
+    if (assignment) {
+        while (assignment) {
+            assignmentEnd = assignment->resourceBase + assignment->resourceLength - 1;
+            foundInstance = RM_FALSE;
+            if (((privilegeCfg->resourceBase >= assignment->resourceBase) &&
+                 (privilegeCfg->resourceBase <= assignmentEnd)) ||
+                ((privilegeCfg->resourceBase < assignment->resourceBase) &&
+                 (resourceEnd > assignmentEnd)) ||
+                ((resourceEnd >= assignment->resourceBase) &&
+                 (resourceEnd <= assignmentEnd))) {
+                 
+                permission = permissionStart = policyGetAssignmentPermissions(assignment, result);
+                while (permission) {
+                    if ((strncmp(permission->instName, privilegeCfg->validInstNode->name, RM_NAME_MAX_CHARS) == 0) ||
+                        (strncmp(permission->instName, Rm_policyAllInstances, RM_NAME_MAX_CHARS) == 0)) {
+                        foundInstance = RM_TRUE;
+                        
+                        /* Check instance's permissions */
+                        if (privilegeCfg->type == Rm_policyCheck_INIT) {
+                            if (!RM_policy_GET_PERM(permission->permissionBits, RM_POLICY_PERM_INIT_SHIFT)) {
+                                policyFreeAssignmentPermissions(permissionStart);
+                                rmDtbUtilPolicyFreeAssignments(assignmentStart);
+                                return(RM_FALSE);
+                            }
+                        }
+                        else if (privilegeCfg->type == Rm_policyCheck_USE) {
+                            if (!RM_policy_GET_PERM(permission->permissionBits, RM_POLICY_PERM_USE_SHIFT)) {
+                                policyFreeAssignmentPermissions(permissionStart);
+                                rmDtbUtilPolicyFreeAssignments(assignmentStart);
+                                return(RM_FALSE);
+                            }   
+                        }
+                        else if (privilegeCfg->type == Rm_policyCheck_EXCLUSIVE) {
+                            if (!RM_policy_GET_PERM(permission->permissionBits, RM_POLICY_PERM_EXCLUSIVE_SHIFT)) {
+                                policyFreeAssignmentPermissions(permissionStart);
+                                rmDtbUtilPolicyFreeAssignments(assignmentStart);
+                                return(RM_FALSE);
+                            }   
+                        }
+                        else if (privilegeCfg->type == Rm_policyCheck_SHARED_LINUX) {
+                            if (!RM_policy_GET_PERM(permission->permissionBits, RM_POLICY_PERM_SHARED_LINUX_SHIFT)) {
+                                policyFreeAssignmentPermissions(permissionStart);
+                                rmDtbUtilPolicyFreeAssignments(assignmentStart);
+                                return(RM_FALSE);
+                            }   
+                        }                        
+                        break;
+                    }
+                    permission = permission->nextPermission;
+                }
+                
+                policyFreeAssignmentPermissions(permissionStart);
+                if (!foundInstance) {
+                    rmDtbUtilPolicyFreeAssignments(assignmentStart);
+                    return(RM_FALSE);
+                }
+            }
+            assignment = assignment->nextAssignment;
+        }
+        rmDtbUtilPolicyFreeAssignments(assignmentStart);
+    }
+    else {
+        return(RM_FALSE);
+    }
+    
+    return(RM_TRUE);
+}
+
+/* FUNCTION PURPOSE: Returns resource base value according to the Policy
+ ***********************************************************************
+ * DESCRIPTION: Returns a resource base value based on the resource
+ *              ranges assigned to the specified valid instance by the
+ *              Policy DTB.
+ */
+uint32_t rmPolicyGetResourceBase(void *policyDtb, Rm_PolicyValidInstNode *validInstNode, 
+                                 int32_t resourceOffset, Rm_PolicyCheckType policyCheckType, 
+                                 int32_t *result)
+
+{
+    int32_t              propertyOffset;
+    const char          *propertyName;
+    int32_t              propertyLen;
+    const void          *propertyData;
+    Rm_PolicyAssignment *assignment = NULL;
+    Rm_PolicyAssignment *assignmentStart = NULL;
+    Rm_PolicyPermission *permission = NULL;
+    Rm_PolicyPermission *permissionStart = NULL;
+    uint32_t             resourceBase = 0;
+
+    *result = RM_OK;
+
+    propertyOffset = fdt_first_property_offset(policyDtb, resourceOffset);
+    if (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
+        while (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
+            propertyData = fdt_getprop_by_offset(policyDtb, propertyOffset, &propertyName, &propertyLen);
+            if (rmDtbUtilPolicyGetPropertyType(propertyName) == Rm_policyPropType_ASSIGNMENTS) {
+                assignment = assignmentStart = rmDtbUtilPolicyExtractAssignments(propertyData, propertyLen);
+                break;
+            }
+            propertyOffset = fdt_next_property_offset(policyDtb, propertyOffset);
+        }
+    }
+
+    /* Search policy permissions for valid resource base */
+    while (assignment) {
+        permission = permissionStart = policyGetAssignmentPermissions(assignment, result);
+        while (permission) {
+            if ((strncmp(permission->instName, validInstNode->name, RM_NAME_MAX_CHARS) == 0) ||
+                (strncmp(permission->instName, Rm_policyAllInstances, RM_NAME_MAX_CHARS) == 0)) {
+                /* Check instance's permissions */
+                if ((policyCheckType == Rm_policyCheck_INIT) &&
+                    RM_policy_GET_PERM(permission->permissionBits, RM_POLICY_PERM_INIT_SHIFT)) {
+                    resourceBase = assignment->resourceBase;
+                    break;
+                }
+                else if ((policyCheckType == Rm_policyCheck_USE) &&
+                         RM_policy_GET_PERM(permission->permissionBits, RM_POLICY_PERM_USE_SHIFT)) {
+                    resourceBase = assignment->resourceBase;
+                    break;
+                }
+            }
+            permission = permission->nextPermission;
+        }
+        policyFreeAssignmentPermissions(permissionStart);
+
+        if (resourceBase) {
+            break;
+        }
+        else {
+            assignment = assignment->nextAssignment;
+        }
+    }
+
+    if (assignmentStart) {
+        rmDtbUtilPolicyFreeAssignments(assignmentStart);
+    }
+    
+    return(resourceBase);
+}
+
+/* FUNCTION PURPOSE: Returns resource alignment value according to the Policy
+ ***********************************************************************
+ * DESCRIPTION: Returns a resource alignment value based on the resource
+ *              alignment assigned to the specified valid instance by the
+ *              Policy DTB.
+ */
+uint32_t rmPolicyGetResourceAlignment(void *policyDtb, int32_t resourceOffset)
+{
+    int32_t            propertyOffset;
+    const char        *propertyName;
+    int32_t            propertyLen;
+    const void        *propertyData;
+    Rm_ResourceValue  *alignmentList;
+    uint32_t           resourceAlignment = 0;
+
+    propertyOffset = fdt_first_property_offset(policyDtb, resourceOffset);
+    if (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
+        while (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
+            propertyData = fdt_getprop_by_offset(policyDtb, propertyOffset, &propertyName, &propertyLen);
+            if (rmDtbUtilPolicyGetPropertyType(propertyName) == Rm_policyPropType_ALLOCATION_ALIGNMENT) {
+                alignmentList = rmDtbUtilPolicyExtractResourceAlignments(propertyData, propertyLen);
+                resourceAlignment = alignmentList->value;                
+                rmDtbUtilPolicyFreeResourceAlignments(alignmentList);
+            }
+            propertyOffset = fdt_next_property_offset(policyDtb, propertyOffset);
+        }
+    }
+    return(resourceAlignment);
+}
+
+/* FUNCTION PURPOSE: Get a resource's offset into a Policy
+ ***********************************************************************
+ * DESCRIPTION: Returns the location of the specified resource node
+ *              within the specified Policy in the form of an offset
+ *              into the DTB.  The resourceName and the Policy
+ *              node name must match.
+ */
+int32_t rmPolicyGetResourceOffset(void *policyDtb, char *resourceName)
+{
+    int32_t     nodeOffset;
+    int32_t     depth;
+    const char *nodeName;
+
+    depth = RM_DTB_UTIL_STARTING_DEPTH;
+    nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;       
+
+    /* Find node offset for provided resource name */
+    while ((nodeOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && 
+           (depth >= RM_DTB_UTIL_STARTING_DEPTH)) {
+        nodeOffset = fdt_next_node(policyDtb, nodeOffset, &depth);
+        nodeName = fdt_get_name(policyDtb, nodeOffset, NULL);
+
+        if (strncmp(nodeName, resourceName, RM_NAME_MAX_CHARS) == 0)
+        {
+            break;
+        }
+    }
+
+    if (depth < RM_DTB_UTIL_STARTING_DEPTH) {
+        /* Resource name not found */
+        nodeOffset = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;
+    }
+    return(nodeOffset);
+}
+
+/* FUNCTION PURPOSE: Validates a Policy's resource node names
+ ***********************************************************************
+ * DESCRIPTION: Returns RM_OK if all of a Policy's resource node names
+ *              match a node name specified in the "valid-instances"
+ *              list specified at the top of the Policy.  Otherwise,
+ *              returns error
+ */
+int32_t rmPolicyValidatePolicyResourceNames(Rm_Handle rmHandle)
+{
+    void       *policyDtb = rmPolicyGetPolicy(rmHandle);
+    int32_t     nodeOffset;
+    int32_t     depth;
+    const char *nodeName;
+
+    depth = RM_DTB_UTIL_STARTING_DEPTH;
+    nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;       
+
+    /* Parse DTB, verifying each resource's assignment permissions.
+     * Permissions must have correct syntax and contain valid instance names
+     * according validInstList */
+    while ((nodeOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && 
+           (depth >= RM_DTB_UTIL_STARTING_DEPTH)) {
+        nodeOffset = fdt_next_node(policyDtb, nodeOffset, &depth);
+        nodeName = fdt_get_name(policyDtb, nodeOffset, NULL);
+        if (fdt_first_property_offset(policyDtb, nodeOffset) > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
+            if (rmAllocatorFind(rmHandle, nodeName) == NULL) {
+                /* No allocator tied to resource name */
+                return(RM_ERROR_UNKNOWN_RESOURCE_IN_POLICY);
+            }        
+        }
+    }
+    return(RM_OK);
+}
+
+/* FUNCTION PURPOSE: Validates a Policy DTB
+ ***********************************************************************
+ * DESCRIPTION: Returns RM_OK if the input Policy satisfies the
+ *              following conditions:
+ *              a) All "assignment" permission string parse okay
+ *              b) All RM instance names specified in the permission
+ *                 strings match an instance name in the valid instance
+ *                 list
+ *              c) All resource node names match a resource allocator
+ */
+int32_t rmPolicyValidatePolicy(Rm_Handle rmHandle)
+{
+    void                *policyDtb = rmPolicyGetPolicy(rmHandle);
+    int32_t              nodeOffset;
+    int32_t              propertyOffset;
+    int32_t              depth;
+    const char          *propertyName;
+    int32_t              propertyLen;
+    const void          *propertyData;
+    Rm_PolicyPropType    propertyType;
+    Rm_PolicyAssignment *assignmentList;
+    int32_t              result;
+
+    depth = RM_DTB_UTIL_STARTING_DEPTH;
+    nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;       
+
+    /* Parse DTB, verifying each resource's assignment permissions.
+     * Permissions must have correct syntax and contain valid instance names
+     * according validInstList */
+    while ((nodeOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && 
+           (depth >= RM_DTB_UTIL_STARTING_DEPTH)) {
+        nodeOffset = fdt_next_node(policyDtb, nodeOffset, &depth);
+        propertyOffset = fdt_first_property_offset(policyDtb, nodeOffset);                
+        while (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
+            propertyData = fdt_getprop_by_offset(policyDtb, propertyOffset, &propertyName, &propertyLen);
+            propertyType = rmDtbUtilPolicyGetPropertyType(propertyName);
+            if (propertyType == Rm_policyPropType_ASSIGNMENTS) {
+                assignmentList = rmDtbUtilPolicyExtractAssignments(propertyData, propertyLen);
+                
+                if ((result = policyValidateAssignmentPermissions(rmHandle, assignmentList)) != RM_OK) {
+                    rmDtbUtilPolicyFreeAssignments(assignmentList);
+                    return(result);
+                }
+                rmDtbUtilPolicyFreeAssignments(assignmentList);
+            }
+            else if (propertyType == Rm_policyPropType_UNKNOWN) {
+                return(RM_ERROR_UNKNOWN_POLICY_RESOURCE_PROPERTY);
+            }
+            propertyOffset = fdt_next_property_offset(policyDtb, propertyOffset);
+        }
+    }
+    return(RM_OK);
+}
+
+/* FUNCTION PURPOSE: Creates the valid instance tree for a RM instance
+ ***********************************************************************
+ * DESCRIPTION: Creates the valid instance tree for a RM instance 
+ *              that has been provided a global or static policy
+ *              The valid instance tree is created from the
+ *              "valid-instances" property at the top of the Policy.
+ *              The root entry of the valid instance tree is returned.
+ */
+Rm_PolicyValidInstTree *rmPolicyCreateValidInstTree(Rm_Handle rmHandle, int addLinux, int32_t *result)
+{
+    Rm_Inst                *rmInst = (Rm_Inst *)rmHandle;
+    void                   *policyDtb = rmPolicyGetPolicy(rmHandle);
+    int32_t                 validInstOffset;
+    const char             *validInstName = NULL;
+    int32_t                 validInstLen;
+    const void             *validInstData = NULL;
+    Rm_PolicyPropType       propertyType;
+    Rm_PolicyValidInst     *vInstListStart = NULL;
+    Rm_PolicyValidInst     *validInstList = NULL;
+    Rm_PolicyValidInstTree *rootEntry = NULL;
+    Rm_PolicyValidInstNode *newNode = NULL;  
+    char                    linuxName[] = RM_ALLOCATED_TO_LINUX;
+
+    /* Valid instance list must be first and only property in the root node of
+     * the policyDtb */
+    validInstOffset = fdt_first_property_offset(policyDtb, RM_DTB_UTIL_STARTING_NODE_OFFSET);
+    if (validInstOffset < -FDT_ERR_NOTFOUND) {
+        *result = validInstOffset;
+        return (NULL);
+    } 
+    else if (validInstOffset == -FDT_ERR_NOTFOUND) {
+        *result = RM_ERROR_NO_VALID_INST_IN_POLICY;
+        return (NULL);
+    }
+    validInstData = fdt_getprop_by_offset(policyDtb, validInstOffset, &validInstName, &validInstLen);
+    propertyType = rmDtbUtilPolicyGetPropertyType(validInstName);
+    if (propertyType != Rm_policyPropType_VALID_INSTANCES) {
+        *result = RM_ERROR_NO_VALID_INST_IN_POLICY;
+        return (NULL);
+    }
+
+    if (!(validInstList = rmDtbUtilPolicyExtractValidInstances(validInstData, validInstLen, result))) {
+        return (NULL);
+    }
+    
+    /* Create the tree */
+    rootEntry = Rm_osalMalloc(sizeof(Rm_PolicyValidInstTree));
+    RB_INIT(rootEntry);
+
+    vInstListStart = validInstList;
+    while (validInstList) {
+        newNode = rmPolicyValidInstNodeNew(validInstList->instName);
+        RB_INSERT(_Rm_PolicyValidInstTree, rootEntry, newNode);
+        
+        validInstList = validInstList->nextValidInst;
+    }
+    rmDtbUtilPolicyFreeValidInstances(vInstListStart);
+
+    /* Add the Linux kernel node */
+    if (addLinux) {
+        newNode = rmPolicyValidInstNodeNew(linuxName);
+        RB_INSERT(_Rm_PolicyValidInstTree, rootEntry, newNode);    
+    }
+
+    if (rmInst->instType == Rm_instType_SHARED_SERVER) {
+        /* Writeback the valid instance tree */
+        rmPolicyValidInstTreeWb(rootEntry);
+    }
+
+    *result = RM_OK;
+    return (rootEntry);
+}
+
+/* FUNCTION PURPOSE: Deletes a valid instance tree
+ ***********************************************************************
+ * DESCRIPTION: Frees all memory associated with a Policy valid
+ *              instance tree.
+ */
+void rmPolicyFreeValidInstTree(Rm_Handle rmHandle)
+{
+    Rm_Inst                *rmInst = (Rm_Inst *)rmHandle;
+    Rm_PolicyValidInstTree *treeRoot = policyGetValidInstTree(rmHandle);
+    Rm_PolicyValidInstNode *node;
+    Rm_PolicyValidInstNode *nextNode;
+
+    if (treeRoot) {
+        if (rmInst->instType == Rm_instType_SHARED_SERVER) {
+            rmPolicyValidInstTreeInv(treeRoot);
+        }
+
+        for (node = RB_MIN(_Rm_PolicyValidInstTree, treeRoot); node != NULL; node = nextNode) {
+            nextNode = RB_NEXT(_Rm_PolicyValidInstTree, treeRoot, node);
+            RB_REMOVE(_Rm_PolicyValidInstTree, treeRoot, node);
+            rmPolicyValidInstNodeFree(node);
+        }
+
+        /* Don't need to writeback tree node changes since valid instance will be made
+         * NULL in instance */
+         
+        if (RB_MIN(_Rm_PolicyValidInstTree, treeRoot) == NULL) {
+            /* No more valid instance nodes in tree */
+            Rm_osalFree((void *)treeRoot, sizeof(Rm_PolicyValidInstTree));
+        }
+
+        if ((rmInst->instType == Rm_instType_SERVER) ||
+            (rmInst->instType == Rm_instType_SHARED_SERVER)) {
+            rmInst->u.server.globalValidInstTree = NULL;
+        }
+        else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
+            rmInst->u.cd.cdValidInstTree = NULL;
+        }
+        else if (rmInst->instType == Rm_instType_CLIENT) {
+            rmInst->u.client.staticValidInstTree = NULL;
+        }
+    }
+}
+