]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/rm-lld.git/blob - src/rm_policy.c
Coverity fixes
[keystone-rtos/rm-lld.git] / src / rm_policy.c
1 /**
2  *   @file  rm_policy.c
3  *
4  *   @brief   
5  *      Resource Manager Policy source.
6  *
7  *  \par
8  *  ============================================================================
9  *  @n   (C) Copyright 2012-2013, Texas Instruments, Inc.
10  * 
11  *  Redistribution and use in source and binary forms, with or without 
12  *  modification, are permitted provided that the following conditions 
13  *  are met:
14  *
15  *    Redistributions of source code must retain the above copyright 
16  *    notice, this list of conditions and the following disclaimer.
17  *
18  *    Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the 
20  *    documentation and/or other materials provided with the   
21  *    distribution.
22  *
23  *    Neither the name of Texas Instruments Incorporated nor the names of
24  *    its contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
28  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
29  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
31  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
32  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
33  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
36  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
37  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38  *
39  *  \par
40 */
42 /* Standard includes */
43 #include <ctype.h>
45 /* RM external API includes */
46 #include <ti/drv/rm/rm.h>
48 /* RM internal API includes */
49 #include <ti/drv/rm/include/rm_internal.h>
50 #include <ti/drv/rm/include/rm_loc.h>
51 #include <ti/drv/rm/include/rm_allocatorloc.h>
52 #include <ti/drv/rm/include/rm_policyloc.h>
53 #include <ti/drv/rm/include/rm_dtb_utilloc.h>
55 /* RM LIBFDT includes */
56 #include <ti/drv/rm/util/libfdt/libfdt.h>
58 /* Tree algorithm includes */
59 #include <ti/drv/rm/util/tree.h>
61 /* RM OSAL layer */
62 #include <rm_osal.h>
64 /**********************************************************************
65  *********************** Policy Globals *******************************
66  **********************************************************************/
68 /* Character used in Policies to specify all RM instances receive
69  * the defined permissions for a resource node */
70 const char Rm_policyAllInstances[] = "*";
72 /**********************************************************************
73  ******************** Local Policy Functions **************************
74  **********************************************************************/
76 /* FUNCTION PURPOSE: Returns a pointer to the valid instance tree
77  ***********************************************************************
78  * DESCRIPTION: Returns a pointer to the instance's valid instance
79  *              tree based on the instance type
80  */
81 static Rm_PolicyValidInstTree *policyGetValidInstTree(Rm_Handle rmHandle)
82 {
83     Rm_Inst                *rmInst = (Rm_Inst *)rmHandle;
84     Rm_PolicyValidInstTree *tree = NULL;
86     if ((rmInst->instType == Rm_instType_SERVER) ||
87         (rmInst->instType == Rm_instType_SHARED_SERVER)) {
88         tree = rmInst->u.server.globalValidInstTree;
89     }
90     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
91         tree = rmInst->u.cd.cdValidInstTree;
92     }
93     else if (rmInst->instType == Rm_instType_CLIENT) {
94         tree = rmInst->u.client.staticValidInstTree;
95     }
96     return(tree);
97 }
99 /* FUNCTION PURPOSE: Validates the instance names in a permissions string
100  ***********************************************************************
101  * DESCRIPTION: Returns RM_OK if all the instance names in a permissions
102  *              string match instance names defined in the valid instance
103  *              list.  RM_ERROR_PERM_STR_INST_NOT_VALID is returned if
104  *              there are any mismatches
105  */
106 static int32_t policyCheckInstances(Rm_Handle rmHandle, Rm_PolicyPermission *permissionsList)
108     while (permissionsList) {
109         if (strncmp(permissionsList->instName, Rm_policyAllInstances, RM_NAME_MAX_CHARS) &&
110             (!rmPolicyGetValidInstNode(rmHandle, permissionsList->instName))) {
111             return(RM_ERROR_PERM_STR_INST_NOT_VALID);
112         }
113         permissionsList = permissionsList->nextPermission;
114     }
115     return(RM_OK);
118 /* FUNCTION PURPOSE: Parses a permissions subgroup
119  ***********************************************************************
120  * DESCRIPTION: Returns a linked list of policy permissions defining
121  *              which RM instance referenced in the permissions subgroup
122  *              get which permissions.  Returns NULL if any syntax
123  *              errors are encountered during the parsing.  The error
124  *              is returned via the result pointer parameter.
125  */
126 static Rm_PolicyPermission *policyParseSubPermission(char *permStrStart, char *permStrEnd, 
127                                                      int32_t *result)
129     Rm_PolicyPermission *startPerm = NULL;
130     Rm_PolicyPermission *newPerm = NULL;
131     Rm_PolicyPermission *prevPerm = NULL;
132     Rm_PolicyPermission *nextPerm = NULL;
133     char                *permStrPtr = NULL;
134     char                *subgroupStart = NULL;
135     char                *subgroupEnd = NULL;
136     uint32_t             permStrLen = (uint32_t)(permStrEnd - permStrStart + 1);
137     char                 instNameTemp[RM_NAME_MAX_CHARS];
138     uint32_t             instNameIndex;
139     int                  foundInstName;
140     int                  instNameComplete;
141     int                  assignmentLeft;
142     int                  assignmentRight;
144     /* Create a local copy of the sub-permission string */
145     permStrPtr = Rm_osalMalloc(permStrLen);
146     strncpy(permStrPtr, permStrStart, permStrLen);
147     /* Make sure the last character in the copied sub-permission string is null */
148     permStrPtr[permStrLen - 1] = '\0';
150     permStrStart = permStrPtr;
151     permStrEnd = permStrPtr + strlen(permStrPtr);
153     /* Find the beginning and end of the sub-permission instance group */
154     subgroupStart = strchr(permStrStart, RM_POLICY_PERM_SUBGROUP_START);
155     subgroupEnd = strchr(permStrStart, RM_POLICY_PERM_SUBGROUP_END);
157     if ((!subgroupStart) || (!subgroupEnd) || (subgroupStart > subgroupEnd) ||
158         ((subgroupStart != strrchr(permStrStart, RM_POLICY_PERM_SUBGROUP_START)) &&
159          (subgroupEnd != strrchr(permStrStart, RM_POLICY_PERM_SUBGROUP_END)))) {
160         /* Free the memory associated with the temp string and return an error if:
161          * a) Could not find the instance group start
162          * b) Could not find the instance group end
163          * c) Subgroup start and end are out of order
164          * d) There is more than one instance subgroup specified in the string.  There
165          *    should only be one subgroup per sub-permission string */
166         *result = RM_ERROR_PERM_STR_TOO_MANY_INST_GROUPS;
167         goto parseError;
168     }
170     /* Create a permission entry for each instance specified in the instance group.
171      * Instances names are separated by one or more spaces. */
172     permStrPtr = subgroupStart + 1;
173     instNameIndex = 0;
174     foundInstName = RM_FALSE;
175     instNameComplete = RM_FALSE;
176     while (permStrPtr <= subgroupEnd) {
177         if ((isspace(*permStrPtr) || (*permStrPtr == RM_POLICY_PERM_SUBGROUP_END))
178             && foundInstName) {
179             /* First space encountered after copying an instance name.  This
180              * terminates the instance name.  All other space characters are
181              * ignored. */
182             instNameTemp[instNameIndex] = '\0';
183             instNameComplete = RM_TRUE; 
184         }
185         else {
186             if (!foundInstName) {
187                 /* First non-whitespace character encountered is the start of an
188                  * instance name */
189                 foundInstName = RM_TRUE;
190             }
192             /* Copy the character into the temporary instance name string */
193             instNameTemp[instNameIndex++] = *permStrPtr;
194         }
196         if (instNameComplete) {
197             newPerm = (Rm_PolicyPermission *) Rm_osalMalloc(sizeof(Rm_PolicyPermission));
198             memset((void *)newPerm, 0, sizeof(Rm_PolicyPermission));
200             strncpy(newPerm->instName, instNameTemp, RM_NAME_MAX_CHARS);
201             newPerm->nextPermission = NULL;
203             if (prevPerm == NULL) {
204                 /* Save the first instance so it can be returned */
205                 startPerm = newPerm;
206             }
207             else {
208                 prevPerm->nextPermission = newPerm;
209             }
210             prevPerm = newPerm;
212             instNameComplete = RM_FALSE;
213             instNameIndex = 0;
214             foundInstName = RM_FALSE;
215         }
216         else if (instNameIndex == RM_NAME_MAX_CHARS) {
217             /* Instance name is longer than max length */
218             *result = RM_ERROR_INST_NAME_IN_ASSIGNMENT_TOO_LONG;
219             goto parseError;
220         }
222         permStrPtr++;
223     }
225     /* Fill in the permissions for each instance name */
227     /* Look on left of instance group for permission assignments. */
228     permStrPtr = subgroupStart - 1;
229     assignmentLeft = RM_FALSE;
230     while (permStrPtr >= permStrStart)
231     {
232         if (*permStrPtr == RM_POLICY_PERM_ASSIGNMENT) {
233             if (assignmentLeft) {
234                 /* Assignment character has been found more than once.  This is a
235                  * syntax error.  Free the permission list and the temporary string
236                  * and return. */
237                 *result = RM_ERROR_PERM_STR_TOO_MANY_ASSIGN_CHARS;
238                 goto parseError;
239             }
240             else {
241                 assignmentLeft = RM_TRUE;
242             }
243         }
244         else if (!isspace(*permStrPtr)) {
245             if (assignmentLeft) {
246                 if ((*permStrPtr == RM_POLICY_PERM_INIT_LOWER) || 
247                     (*permStrPtr == RM_POLICY_PERM_INIT_UPPER)) {
248                     newPerm = startPerm;
249                     while (newPerm) {
250                         RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_INIT_SHIFT, 1);
251                         newPerm = newPerm->nextPermission;
252                     }
253                 }
254                 else if ((*permStrPtr == RM_POLICY_PERM_USE_LOWER) || 
255                          (*permStrPtr == RM_POLICY_PERM_USE_UPPER)) {
256                     newPerm = startPerm;
257                     while (newPerm) {                                           
258                         RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_USE_SHIFT, 1);
259                         newPerm = newPerm->nextPermission;
260                     }
261                 }
262                 else if ((*permStrPtr == RM_POLICY_PERM_EXCLUSIVE_LOWER) || 
263                          (*permStrPtr == RM_POLICY_PERM_EXCLUSIVE_UPPER)) {
264                     newPerm = startPerm;
265                     while (newPerm) {                       
266                         RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_EXCLUSIVE_SHIFT, 1);
267                         newPerm = newPerm->nextPermission;
268                     }
269                 }
270                 else if ((*permStrPtr == RM_POLICY_PERM_SHARED_LINUX_LOWER) || 
271                          (*permStrPtr == RM_POLICY_PERM_SHARED_LINUX_UPPER)) {
272                     newPerm = startPerm;
273                     while (newPerm) {                       
274                         RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_SHARED_LINUX_SHIFT, 1);
275                         newPerm = newPerm->nextPermission;
276                     }
277                 }                
278                 else {
279                     /* Invalid permission character.  This is a
280                      * syntax error.  Free the permission list and the temporary string
281                      * and return. */
282                     *result = RM_ERROR_PERM_STR_INVALID_CHAR;
283                     goto parseError;
284                 }
285             }
286             else {
287                 /* Character found without the assignment character being found.  This is a
288                  * syntax error.  Free the permission list and the temporary string
289                  * and return. */
290                 *result = RM_ERROR_PERM_CHAR_WITHOUT_ASSIGN_CHAR;
291                 goto parseError;
292             }
293         }
294         permStrPtr--;
295     }
297     /* Look on right of instance group for permission assignments. */
298     permStrPtr = subgroupEnd + 1;
299     assignmentRight = RM_FALSE;
300     while (permStrPtr < permStrEnd) {
301         if (assignmentLeft && (!isspace(*permStrPtr))) {
302             /* There should be nothing but spaces on right if assignment was already found on left */
303             *result = RM_ERROR_INVALID_PERMS_CHAR_ON_RIGHT;
304             goto parseError;             
305         }
306         
307         if (*permStrPtr == RM_POLICY_PERM_ASSIGNMENT) {
308             if (assignmentRight) {
309                 /* Assignment character has been found more than once.  This is a
310                  * syntax error.  Free the permission list and the temporary string
311                  * and return. */
312                 *result = RM_ERROR_PERM_STR_TOO_MANY_ASSIGN_CHARS;
313                 goto parseError;               
314             }
315             else {
316                 assignmentRight = RM_TRUE;
317             }
318         }
319         else if (!isspace(*permStrPtr)) {
320             if (assignmentRight) {
321                 if ((*permStrPtr == RM_POLICY_PERM_INIT_LOWER) || 
322                     (*permStrPtr == RM_POLICY_PERM_INIT_UPPER)) {
323                     newPerm = startPerm;
324                     while (newPerm) {
325                         RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_INIT_SHIFT, 1);
326                         newPerm = newPerm->nextPermission;
327                     }
328                 }
329                 else if ((*permStrPtr == RM_POLICY_PERM_USE_LOWER) || 
330                          (*permStrPtr == RM_POLICY_PERM_USE_UPPER)) {
331                     newPerm = startPerm;
332                     while (newPerm) {                                           
333                         RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_USE_SHIFT, 1);
334                         newPerm = newPerm->nextPermission;
335                     }
336                 }
337                 else if ((*permStrPtr == RM_POLICY_PERM_EXCLUSIVE_LOWER) || 
338                          (*permStrPtr == RM_POLICY_PERM_EXCLUSIVE_UPPER)) {
339                     newPerm = startPerm;
340                     while (newPerm) {                       
341                         RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_EXCLUSIVE_SHIFT, 1);
342                         newPerm = newPerm->nextPermission;
343                     }
344                 }
345                 else if ((*permStrPtr == RM_POLICY_PERM_SHARED_LINUX_LOWER) || 
346                          (*permStrPtr == RM_POLICY_PERM_SHARED_LINUX_UPPER)) {
347                     newPerm = startPerm;
348                     while (newPerm) {                       
349                         RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_SHARED_LINUX_SHIFT, 1);
350                         newPerm = newPerm->nextPermission;
351                     }
352                 }                  
353                 else {
354                     /* Invalid permission character.  This is a
355                      * syntax error.  Free the permission list and the temporary string
356                      * and return. */
357                     *result = RM_ERROR_PERM_STR_INVALID_CHAR;
358                     goto parseError;                   
359                 }
360             }
361             else {
362                 /* Character found without the assignment character being found.  This is a
363                  * syntax error.  Free the permission list and the temporary string
364                  * and return. */
365                 *result = RM_ERROR_PERM_STR_TOO_MANY_ASSIGN_CHARS;
366                 goto parseError;
367             }
368         }
369         permStrPtr++;
370     }
372     Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
373     *result = RM_OK;
374     return (startPerm);
376 parseError:
377     while (startPerm) {
378         nextPerm = startPerm->nextPermission;
379         Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
380         startPerm = nextPerm;
381     }    
382     Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
383     return(NULL);     
386 /* FUNCTION PURPOSE: Frees a linked list of assignment permissions
387  ***********************************************************************
388  * DESCRIPTION: Frees the memory associated with a linked list of
389  *              assignment permissions extracted from a permissions
390  *              assignment subgroup in a policy DTB.
391  */
392 static void policyFreeAssignmentPermissions(Rm_PolicyPermission *permissionList)
394     Rm_PolicyPermission *nextPerm;
395     
396     while (permissionList) {
397         nextPerm = permissionList->nextPermission;
398         Rm_osalFree((void *)permissionList, sizeof(Rm_PolicyPermission));
399         permissionList = nextPerm;
400     }
403 /* FUNCTION PURPOSE: Extracts permissions from a Policy "assignment"
404  ***********************************************************************
405  * DESCRIPTION: Returns a linked list of permissions for a resource node
406  *              containing an "assignment" property in the Policy DTB.
407  *              Each node in the linked list will contain a valid instance
408  *              name along with the permissions assigned to the instance
409  */
410 static Rm_PolicyPermission *policyGetAssignmentPermissions(Rm_PolicyAssignment *assignment, 
411                                                            int32_t *result)
413     Rm_PolicyPermission *startPerm = NULL;
414     Rm_PolicyPermission *newPerm = NULL;
415     Rm_PolicyPermission *prevPerm = NULL;
416     char                *permStrStart = assignment->permissionsList;
417     char                *permStrEnd;
418     uint32_t             permStrLen = strlen(assignment->permissionsList) + 1;
419     uint32_t             i = 0;
421     *result = RM_OK;
422     
423     while(i < permStrLen) {
424         /* Find the first sub-permission specification and parse it.  A sub-permission
425          * can be terminated by the termination character or the end of the string. */
426         if (!(permStrEnd = strchr(permStrStart, RM_POLICY_PERM_TERMINATOR))) {           
427             /* Sub-permission termination character not found.  The permission string
428              * end is the end of the entire permission string */
429             permStrEnd = permStrStart + strlen(permStrStart);
430         }
432         newPerm = policyParseSubPermission(permStrStart, permStrEnd, result);
434         if (*result != RM_OK) {
435             /* Delete the permission list that's been created thus far, return
436              * the error and NULL for the permission list */
437             policyFreeAssignmentPermissions(startPerm);
438             return(NULL);
439         }
441         if (prevPerm == NULL) {
442             startPerm = newPerm;
443         }
444         else {
445             prevPerm->nextPermission = newPerm;
446         }
448         /* Set prevPerm to the last sub-permission returned by the sub-permission parser */
449         prevPerm = newPerm;
450         while(prevPerm->nextPermission != NULL) {
451             prevPerm = prevPerm->nextPermission;
452         }
453         
454         /* Update the number of characters parsed from the permission list and point to 
455          * the start of the next sub-permission */
456         i += ((uint32_t)(permStrEnd - permStrStart + 1));
457         permStrStart = permStrEnd + 1;
458     }
460     return(startPerm);
463 /* FUNCTION PURPOSE: Validates a policy "assignment" string list
464  ***********************************************************************
465  * DESCRIPTION: Returns RM_OK if the specified Policy DTB "assignment"
466  *              property specification parses okay and all the RM
467  *              instances in the assignment match RM instances in the
468  *              valid instances list
469  */
470 static int32_t policyValidateAssignmentPermissions(Rm_Handle rmHandle,
471                                                    Rm_PolicyAssignment *assignmentList)
473     Rm_PolicyAssignment *assignment = assignmentList;
474     Rm_PolicyPermission *permissionList;
475     int32_t              result;
477     while (assignment) {
478         /* Make sure assignment's permissions parse okay */
479         permissionList = policyGetAssignmentPermissions(assignment, &result);
480         if (result != RM_OK) {
481             return(result);
482         }                        
483         
484         if (result = policyCheckInstances(rmHandle, permissionList) != RM_OK) {
485             policyFreeAssignmentPermissions(permissionList);
486             return(result);
487         }
489         policyFreeAssignmentPermissions(permissionList);
490         assignment = assignment->nextAssignment;
491     }
493     return (RM_OK);
496 /**********************************************************************
497  ************************ Internal Policy APIs ************************
498  **********************************************************************/
500 /* FUNCTION PURPOSE: Returns a pointer to the instance policy
501  ***********************************************************************
502  * DESCRIPTION: Returns a pointer to the instance's policy based on
503  *              the instance type
504  */
505 void *rmPolicyGetPolicy(Rm_Handle rmHandle)
507     Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
508     void    *policy = NULL;
510     if ((rmInst->instType == Rm_instType_SERVER) ||
511         (rmInst->instType == Rm_instType_SHARED_SERVER)) {
512         policy = rmInst->u.server.globalPolicy;
513     }
514     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
515         policy = rmInst->u.cd.cdPolicy;
516     }
517     else if (rmInst->instType == Rm_instType_CLIENT) {
518         policy = rmInst->u.client.staticPolicy;
519     }
520     return(policy);
523 /* FUNCTION PURPOSE: Get a valid instace node from the valid inst tree
524  ***********************************************************************
525  * DESCRIPTION: Returns a valid instance node from the valid instance
526  *              tree that matches the specified instName
527  */
528 Rm_PolicyValidInstNode *rmPolicyGetValidInstNode(Rm_Handle rmHandle, char *instName)
530     Rm_Inst                *rmInst = (Rm_Inst *)rmHandle;
531     Rm_PolicyValidInstTree *treeRoot = policyGetValidInstTree(rmHandle);
532     Rm_PolicyValidInstNode  findNode;
534     if (rmInst->instType == Rm_instType_SHARED_SERVER) {
535         rmPolicyValidInstTreeInv(treeRoot);
536     }
538     memset((void *)&findNode, 0, sizeof(Rm_PolicyValidInstNode));
539     strncpy(findNode.name, instName, RM_NAME_MAX_CHARS);
540     
541     return (RB_FIND(_Rm_PolicyValidInstTree, treeRoot, &findNode));
544 /* FUNCTION PURPOSE: Gets the Linux Valid instance node
545  ***********************************************************************
546  * DESCRIPTION: Returns a pointer to the valid instance node in the
547  *              valid instance tree that matches the instance name
548  *              reserved for resource assigned to the Linux kernel.
549  */
550 Rm_PolicyValidInstNode *rmPolicyGetLinuxInstNode(Rm_Handle rmHandle)
552     char linuxName[] = RM_ALLOCATED_TO_LINUX;
554     return (rmPolicyGetValidInstNode(rmHandle, linuxName));
557 /* FUNCTION PURPOSE: Validates resource permissions against a Policy DTB
558  ***********************************************************************
559  * DESCRIPTION: Returns TRUE if the instance name has the specified
560  *              permissions for the specified resource in the Policy
561  *              DTB.  Otherwise, returns FALSE.
562  */
563 int rmPolicyCheckPrivilege(Rm_PolicyCheckCfg *privilegeCfg, int32_t *result)
565     int32_t              propertyOffset;
566     const char          *propertyName;
567     int32_t              propertyLen;
568     const void          *propertyData;
569     Rm_PolicyAssignment *assignment = NULL;
570     Rm_PolicyAssignment *assignmentStart = NULL;
571     Rm_PolicyPermission *permission = NULL;
572     Rm_PolicyPermission *permissionStart = NULL;
573     uint32_t             assignmentEnd;
574     uint32_t             resourceEnd = privilegeCfg->resourceBase + privilegeCfg->resourceLength - 1;
575     int                  foundInstance;
577     *result = RM_OK;
579     /* Get the resource's assignments */
580     propertyOffset = fdt_first_property_offset(privilegeCfg->policyDtb, privilegeCfg->resourceOffset);
581     if (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
582         while (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
583             propertyData = fdt_getprop_by_offset(privilegeCfg->policyDtb, propertyOffset, &propertyName, &propertyLen);
584             if (rmDtbUtilPolicyGetPropertyType(propertyName) == Rm_policyPropType_ASSIGNMENTS) {
585                 assignment = assignmentStart = rmDtbUtilPolicyExtractAssignments(propertyData, propertyLen);
586                 break;
587             }
588             propertyOffset = fdt_next_property_offset(privilegeCfg->policyDtb, propertyOffset);
589         }
590     }
592     if (assignment) {
593         while (assignment) {
594             assignmentEnd = assignment->resourceBase + assignment->resourceLength - 1;
595             foundInstance = RM_FALSE;
596             if (((privilegeCfg->resourceBase >= assignment->resourceBase) &&
597                  (privilegeCfg->resourceBase <= assignmentEnd)) ||
598                 ((privilegeCfg->resourceBase < assignment->resourceBase) &&
599                  (resourceEnd > assignmentEnd)) ||
600                 ((resourceEnd >= assignment->resourceBase) &&
601                  (resourceEnd <= assignmentEnd))) {
602                  
603                 permission = permissionStart = policyGetAssignmentPermissions(assignment, result);
604                 while (permission) {
605                     if ((strncmp(permission->instName, privilegeCfg->validInstNode->name, RM_NAME_MAX_CHARS) == 0) ||
606                         (strncmp(permission->instName, Rm_policyAllInstances, RM_NAME_MAX_CHARS) == 0)) {
607                         foundInstance = RM_TRUE;
608                         
609                         /* Check instance's permissions */
610                         if (privilegeCfg->type == Rm_policyCheck_INIT) {
611                             if (!RM_policy_GET_PERM(permission->permissionBits, RM_POLICY_PERM_INIT_SHIFT)) {
612                                 policyFreeAssignmentPermissions(permissionStart);
613                                 rmDtbUtilPolicyFreeAssignments(assignmentStart);
614                                 return(RM_FALSE);
615                             }
616                         }
617                         else if (privilegeCfg->type == Rm_policyCheck_USE) {
618                             if (!RM_policy_GET_PERM(permission->permissionBits, RM_POLICY_PERM_USE_SHIFT)) {
619                                 policyFreeAssignmentPermissions(permissionStart);
620                                 rmDtbUtilPolicyFreeAssignments(assignmentStart);
621                                 return(RM_FALSE);
622                             }   
623                         }
624                         else if (privilegeCfg->type == Rm_policyCheck_EXCLUSIVE) {
625                             if (!RM_policy_GET_PERM(permission->permissionBits, RM_POLICY_PERM_EXCLUSIVE_SHIFT)) {
626                                 policyFreeAssignmentPermissions(permissionStart);
627                                 rmDtbUtilPolicyFreeAssignments(assignmentStart);
628                                 return(RM_FALSE);
629                             }   
630                         }
631                         else if (privilegeCfg->type == Rm_policyCheck_SHARED_LINUX) {
632                             if (!RM_policy_GET_PERM(permission->permissionBits, RM_POLICY_PERM_SHARED_LINUX_SHIFT)) {
633                                 policyFreeAssignmentPermissions(permissionStart);
634                                 rmDtbUtilPolicyFreeAssignments(assignmentStart);
635                                 return(RM_FALSE);
636                             }   
637                         }                        
638                         break;
639                     }
640                     permission = permission->nextPermission;
641                 }
642                 
643                 policyFreeAssignmentPermissions(permissionStart);
644                 if (!foundInstance) {
645                     rmDtbUtilPolicyFreeAssignments(assignmentStart);
646                     return(RM_FALSE);
647                 }
648             }
649             assignment = assignment->nextAssignment;
650         }
651         rmDtbUtilPolicyFreeAssignments(assignmentStart);
652     }
653     else {
654         return(RM_FALSE);
655     }
656     
657     return(RM_TRUE);
660 /* FUNCTION PURPOSE: Returns resource base value according to the Policy
661  ***********************************************************************
662  * DESCRIPTION: Returns a resource base value based on the resource
663  *              ranges assigned to the specified valid instance by the
664  *              Policy DTB.
665  */
666 uint32_t rmPolicyGetResourceBase(void *policyDtb, Rm_PolicyValidInstNode *validInstNode, 
667                                  int32_t resourceOffset, Rm_PolicyCheckType policyCheckType, 
668                                  int32_t *result)
671     int32_t              propertyOffset;
672     const char          *propertyName;
673     int32_t              propertyLen;
674     const void          *propertyData;
675     Rm_PolicyAssignment *assignment = NULL;
676     Rm_PolicyAssignment *assignmentStart = NULL;
677     Rm_PolicyPermission *permission = NULL;
678     Rm_PolicyPermission *permissionStart = NULL;
679     uint32_t             resourceBase = 0;
681     *result = RM_OK;
683     propertyOffset = fdt_first_property_offset(policyDtb, resourceOffset);
684     if (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
685         while (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
686             propertyData = fdt_getprop_by_offset(policyDtb, propertyOffset, &propertyName, &propertyLen);
687             if (rmDtbUtilPolicyGetPropertyType(propertyName) == Rm_policyPropType_ASSIGNMENTS) {
688                 assignment = assignmentStart = rmDtbUtilPolicyExtractAssignments(propertyData, propertyLen);
689                 break;
690             }
691             propertyOffset = fdt_next_property_offset(policyDtb, propertyOffset);
692         }
693     }
695     /* Search policy permissions for valid resource base */
696     while (assignment) {
697         permission = permissionStart = policyGetAssignmentPermissions(assignment, result);
698         while (permission) {
699             if ((strncmp(permission->instName, validInstNode->name, RM_NAME_MAX_CHARS) == 0) ||
700                 (strncmp(permission->instName, Rm_policyAllInstances, RM_NAME_MAX_CHARS) == 0)) {
701                 /* Check instance's permissions */
702                 if ((policyCheckType == Rm_policyCheck_INIT) &&
703                     RM_policy_GET_PERM(permission->permissionBits, RM_POLICY_PERM_INIT_SHIFT)) {
704                     resourceBase = assignment->resourceBase;
705                     break;
706                 }
707                 else if ((policyCheckType == Rm_policyCheck_USE) &&
708                          RM_policy_GET_PERM(permission->permissionBits, RM_POLICY_PERM_USE_SHIFT)) {
709                     resourceBase = assignment->resourceBase;
710                     break;
711                 }
712             }
713             permission = permission->nextPermission;
714         }
715         policyFreeAssignmentPermissions(permissionStart);
717         if (resourceBase) {
718             break;
719         }
720         else {
721             assignment = assignment->nextAssignment;
722         }
723     }
725     if (assignmentStart) {
726         rmDtbUtilPolicyFreeAssignments(assignmentStart);
727     }
728     
729     return(resourceBase);
732 /* FUNCTION PURPOSE: Returns resource alignment value according to the Policy
733  ***********************************************************************
734  * DESCRIPTION: Returns a resource alignment value based on the resource
735  *              alignment assigned to the specified valid instance by the
736  *              Policy DTB.
737  */
738 uint32_t rmPolicyGetResourceAlignment(void *policyDtb, int32_t resourceOffset)
740     int32_t            propertyOffset;
741     const char        *propertyName;
742     int32_t            propertyLen;
743     const void        *propertyData;
744     Rm_ResourceValue  *alignmentList;
745     uint32_t           resourceAlignment = 0;
747     propertyOffset = fdt_first_property_offset(policyDtb, resourceOffset);
748     if (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
749         while (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
750             propertyData = fdt_getprop_by_offset(policyDtb, propertyOffset, &propertyName, &propertyLen);
751             if (rmDtbUtilPolicyGetPropertyType(propertyName) == Rm_policyPropType_ALLOCATION_ALIGNMENT) {
752                 alignmentList = rmDtbUtilPolicyExtractResourceAlignments(propertyData, propertyLen);
753                 resourceAlignment = alignmentList->value;                
754                 rmDtbUtilPolicyFreeResourceAlignments(alignmentList);
755             }
756             propertyOffset = fdt_next_property_offset(policyDtb, propertyOffset);
757         }
758     }
759     return(resourceAlignment);
762 /* FUNCTION PURPOSE: Get a resource's offset into a Policy
763  ***********************************************************************
764  * DESCRIPTION: Returns the location of the specified resource node
765  *              within the specified Policy in the form of an offset
766  *              into the DTB.  The resourceName and the Policy
767  *              node name must match.
768  */
769 int32_t rmPolicyGetResourceOffset(void *policyDtb, char *resourceName)
771     int32_t     nodeOffset;
772     int32_t     depth;
773     const char *nodeName;
775     depth = RM_DTB_UTIL_STARTING_DEPTH;
776     nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;       
778     /* Find node offset for provided resource name */
779     while ((nodeOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && 
780            (depth >= RM_DTB_UTIL_STARTING_DEPTH)) {
781         nodeOffset = fdt_next_node(policyDtb, nodeOffset, &depth);
782         nodeName = fdt_get_name(policyDtb, nodeOffset, NULL);
784         if (strncmp(nodeName, resourceName, RM_NAME_MAX_CHARS) == 0)
785         {
786             break;
787         }
788     }
790     if (depth < RM_DTB_UTIL_STARTING_DEPTH) {
791         /* Resource name not found */
792         nodeOffset = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;
793     }
794     return(nodeOffset);
797 /* FUNCTION PURPOSE: Validates a Policy's resource node names
798  ***********************************************************************
799  * DESCRIPTION: Returns RM_OK if all of a Policy's resource node names
800  *              match a node name specified in the "valid-instances"
801  *              list specified at the top of the Policy.  Otherwise,
802  *              returns error
803  */
804 int32_t rmPolicyValidatePolicyResourceNames(Rm_Handle rmHandle)
806     void       *policyDtb = rmPolicyGetPolicy(rmHandle);
807     int32_t     nodeOffset;
808     int32_t     depth;
809     const char *nodeName;
811     depth = RM_DTB_UTIL_STARTING_DEPTH;
812     nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;       
814     /* Parse DTB, verifying each resource's assignment permissions.
815      * Permissions must have correct syntax and contain valid instance names
816      * according validInstList */
817     while ((nodeOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && 
818            (depth >= RM_DTB_UTIL_STARTING_DEPTH)) {
819         nodeOffset = fdt_next_node(policyDtb, nodeOffset, &depth);
820         nodeName = fdt_get_name(policyDtb, nodeOffset, NULL);
821         if (fdt_first_property_offset(policyDtb, nodeOffset) > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
822             if (rmAllocatorFind(rmHandle, nodeName) == NULL) {
823                 /* No allocator tied to resource name */
824                 return(RM_ERROR_UNKNOWN_RESOURCE_IN_POLICY);
825             }        
826         }
827     }
828     return(RM_OK);
831 /* FUNCTION PURPOSE: Validates a Policy DTB
832  ***********************************************************************
833  * DESCRIPTION: Returns RM_OK if the input Policy satisfies the
834  *              following conditions:
835  *              a) All "assignment" permission string parse okay
836  *              b) All RM instance names specified in the permission
837  *                 strings match an instance name in the valid instance
838  *                 list
839  *              c) All resource node names match a resource allocator
840  */
841 int32_t rmPolicyValidatePolicy(Rm_Handle rmHandle)
843     void                *policyDtb = rmPolicyGetPolicy(rmHandle);
844     int32_t              nodeOffset;
845     int32_t              propertyOffset;
846     int32_t              depth;
847     const char          *propertyName;
848     int32_t              propertyLen;
849     const void          *propertyData;
850     Rm_PolicyPropType    propertyType;
851     Rm_PolicyAssignment *assignmentList;
852     int32_t              result;
854     depth = RM_DTB_UTIL_STARTING_DEPTH;
855     nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;       
857     /* Parse DTB, verifying each resource's assignment permissions.
858      * Permissions must have correct syntax and contain valid instance names
859      * according validInstList */
860     while ((nodeOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && 
861            (depth >= RM_DTB_UTIL_STARTING_DEPTH)) {
862         nodeOffset = fdt_next_node(policyDtb, nodeOffset, &depth);
863         propertyOffset = fdt_first_property_offset(policyDtb, nodeOffset);                
864         while (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
865             propertyData = fdt_getprop_by_offset(policyDtb, propertyOffset, &propertyName, &propertyLen);
866             propertyType = rmDtbUtilPolicyGetPropertyType(propertyName);
867             if (propertyType == Rm_policyPropType_ASSIGNMENTS) {
868                 assignmentList = rmDtbUtilPolicyExtractAssignments(propertyData, propertyLen);
869                 
870                 if ((result = policyValidateAssignmentPermissions(rmHandle, assignmentList)) != RM_OK) {
871                     rmDtbUtilPolicyFreeAssignments(assignmentList);
872                     return(result);
873                 }
874                 rmDtbUtilPolicyFreeAssignments(assignmentList);
875             }
876             else if (propertyType == Rm_policyPropType_UNKNOWN) {
877                 return(RM_ERROR_UNKNOWN_POLICY_RESOURCE_PROPERTY);
878             }
879             propertyOffset = fdt_next_property_offset(policyDtb, propertyOffset);
880         }
881     }
882     return(RM_OK);
885 /* FUNCTION PURPOSE: Creates the valid instance tree for a RM instance
886  ***********************************************************************
887  * DESCRIPTION: Creates the valid instance tree for a RM instance 
888  *              that has been provided a global or static policy
889  *              The valid instance tree is created from the
890  *              "valid-instances" property at the top of the Policy.
891  *              The root entry of the valid instance tree is returned.
892  */
893 Rm_PolicyValidInstTree *rmPolicyCreateValidInstTree(Rm_Handle rmHandle, int addLinux, int32_t *result)
895     Rm_Inst                *rmInst = (Rm_Inst *)rmHandle;
896     void                   *policyDtb = rmPolicyGetPolicy(rmHandle);
897     int32_t                 validInstOffset;
898     const char             *validInstName = NULL;
899     int32_t                 validInstLen;
900     const void             *validInstData = NULL;
901     Rm_PolicyPropType       propertyType;
902     Rm_PolicyValidInst     *vInstListStart = NULL;
903     Rm_PolicyValidInst     *validInstList = NULL;
904     Rm_PolicyValidInstTree *rootEntry = NULL;
905     Rm_PolicyValidInstNode *newNode = NULL;  
906     char                    linuxName[] = RM_ALLOCATED_TO_LINUX;
908     /* Valid instance list must be first and only property in the root node of
909      * the policyDtb */
910     validInstOffset = fdt_first_property_offset(policyDtb, RM_DTB_UTIL_STARTING_NODE_OFFSET);
911     if (validInstOffset < -FDT_ERR_NOTFOUND) {
912         *result = validInstOffset;
913         return (NULL);
914     } 
915     else if (validInstOffset == -FDT_ERR_NOTFOUND) {
916         *result = RM_ERROR_NO_VALID_INST_IN_POLICY;
917         return (NULL);
918     }
919     validInstData = fdt_getprop_by_offset(policyDtb, validInstOffset, &validInstName, &validInstLen);
920     propertyType = rmDtbUtilPolicyGetPropertyType(validInstName);
921     if (propertyType != Rm_policyPropType_VALID_INSTANCES) {
922         *result = RM_ERROR_NO_VALID_INST_IN_POLICY;
923         return (NULL);
924     }
926     if (!(validInstList = rmDtbUtilPolicyExtractValidInstances(validInstData, validInstLen, result))) {
927         return (NULL);
928     }
929     
930     /* Create the tree */
931     rootEntry = Rm_osalMalloc(sizeof(Rm_PolicyValidInstTree));
932     RB_INIT(rootEntry);
934     vInstListStart = validInstList;
935     while (validInstList) {
936         newNode = rmPolicyValidInstNodeNew(validInstList->instName);
937         RB_INSERT(_Rm_PolicyValidInstTree, rootEntry, newNode);
938         
939         validInstList = validInstList->nextValidInst;
940     }
941     rmDtbUtilPolicyFreeValidInstances(vInstListStart);
943     /* Add the Linux kernel node */
944     if (addLinux) {
945         newNode = rmPolicyValidInstNodeNew(linuxName);
946         RB_INSERT(_Rm_PolicyValidInstTree, rootEntry, newNode);    
947     }
949     if (rmInst->instType == Rm_instType_SHARED_SERVER) {
950         /* Writeback the valid instance tree */
951         rmPolicyValidInstTreeWb(rootEntry);
952     }
954     *result = RM_OK;
955     return (rootEntry);
958 /* FUNCTION PURPOSE: Deletes a valid instance tree
959  ***********************************************************************
960  * DESCRIPTION: Frees all memory associated with a Policy valid
961  *              instance tree.
962  */
963 void rmPolicyFreeValidInstTree(Rm_Handle rmHandle)
965     Rm_Inst                *rmInst = (Rm_Inst *)rmHandle;
966     Rm_PolicyValidInstTree *treeRoot = policyGetValidInstTree(rmHandle);
967     Rm_PolicyValidInstNode *node;
968     Rm_PolicyValidInstNode *nextNode;
970     if (treeRoot) {
971         if (rmInst->instType == Rm_instType_SHARED_SERVER) {
972             rmPolicyValidInstTreeInv(treeRoot);
973         }
975         for (node = RB_MIN(_Rm_PolicyValidInstTree, treeRoot); node != NULL; node = nextNode) {
976             nextNode = RB_NEXT(_Rm_PolicyValidInstTree, treeRoot, node);
977             RB_REMOVE(_Rm_PolicyValidInstTree, treeRoot, node);
978             rmPolicyValidInstNodeFree(node);
979         }
981         /* Don't need to writeback tree node changes since valid instance will be made
982          * NULL in instance */
983          
984         if (RB_MIN(_Rm_PolicyValidInstTree, treeRoot) == NULL) {
985             /* No more valid instance nodes in tree */
986             Rm_osalFree((void *)treeRoot, sizeof(Rm_PolicyValidInstTree));
987         }
989         if ((rmInst->instType == Rm_instType_SERVER) ||
990             (rmInst->instType == Rm_instType_SHARED_SERVER)) {
991             rmInst->u.server.globalValidInstTree = NULL;
992         }
993         else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
994             rmInst->u.cd.cdValidInstTree = NULL;
995         }
996         else if (rmInst->instType == Rm_instType_CLIENT) {
997             rmInst->u.client.staticValidInstTree = NULL;
998         }
999     }