9432c3dea0c90f053064b0b9661b7ad2c06df2b0
[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_loc.h>
50 #include <ti/drv/rm/include/rm_policyloc.h>
51 #include <ti/drv/rm/include/rm_dtb_utilloc.h>
53 /* RM LIBFDT includes */
54 #include <ti/drv/rm/util/libfdt/libfdt.h>
56 /* Tree algorithm includes */
57 #include <ti/drv/rm/util/tree.h>
59 /* RM OSAL layer */
60 #include <rm_osal.h>
62 /**********************************************************************
63  *********************** Policy Globals *******************************
64  **********************************************************************/
66 const char Rm_policyAllInstances[] = "*";
68 /**********************************************************************
69  ******************** Local Policy Functions **************************
70  **********************************************************************/
72 static int32_t policyCheckInstances(Rm_PolicyValidInstTree *validInstTree, 
73                                     Rm_PolicyPermission *permissionsList)
74 {
75     while (permissionsList) {
76         if (strcmp(permissionsList->instName, Rm_policyAllInstances) &&
77             (!rmPolicyGetValidInstNode(validInstTree, permissionsList->instName))) {
78             return(RM_INIT_ERROR_POLICY_UNKNOWN_INSTANCE);
79         }
80         permissionsList = permissionsList->nextPermission;
81     }
82     return(RM_INIT_OK);
83 }
85 static Rm_PolicyPermission *policyParseSubPermission(char *permStrStart, char *permStrEnd, 
86                                                      int32_t *result)
87 {
88     Rm_PolicyPermission *startPerm = NULL;
89     Rm_PolicyPermission *newPerm = NULL;
90     Rm_PolicyPermission *prevPerm = NULL;
91     Rm_PolicyPermission *nextPerm = NULL;
92     char                *permStrPtr = NULL;
93     char                *subgroupStart = NULL;
94     char                *subgroupEnd = NULL;
95     uint32_t             permStrLen = (uint32_t)(permStrEnd - permStrStart + 1);
96     char                 instNameTemp[RM_NAME_MAX_CHARS];
97     uint32_t             instNameIndex;
98     bool                 foundInstName;
99     bool                 instNameComplete;
100     bool                 assignmentLeft;
101     bool                 assignmentRight;
103     /* Create a local copy of the sub-permission string */
104     permStrPtr = Rm_osalMalloc(permStrLen);
105     strncpy(permStrPtr, permStrStart, permStrLen);
106     /* Make sure the last character in the copied sub-permission string is null */
107     permStrPtr[permStrLen - 1] = '\0';
109     permStrStart = permStrPtr;
110     permStrEnd = permStrPtr + strlen(permStrPtr);
112     /* Find the beginning and end of the sub-permission instance group */
113     subgroupStart = strchr(permStrStart, RM_POLICY_PERM_SUBGROUP_START);
114     subgroupEnd = strchr(permStrStart, RM_POLICY_PERM_SUBGROUP_END);
116     if ((!subgroupStart) || (!subgroupEnd) || (subgroupStart > subgroupEnd) ||
117         ((subgroupStart != strrchr(permStrStart, RM_POLICY_PERM_SUBGROUP_START)) &&
118          (subgroupEnd != strrchr(permStrStart, RM_POLICY_PERM_SUBGROUP_END)))) {
119         /* Free the memory associated with the temp string and return an error if:
120          * a) Could not find the instance group start
121          * b) Could not find the instance group end
122          * c) Subgroup start and end are out of order
123          * d) There is more than one instance subgroup specified in the string.  There
124          *    should only be one subgroup per sub-permission string */
125         Rm_osalFree((void *)permStrStart, permStrLen);
126         *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_MORE_THAN_ONE_INSTANCE_GROUP;
127         return(NULL);
128     }
130     /* Create a permission entry for each instance specified in the instance group.
131      * Instances names are separated by one or more spaces. */
132     permStrPtr = subgroupStart + 1;
133     instNameIndex = 0;
134     foundInstName = FALSE;
135     instNameComplete = FALSE;
136     while (permStrPtr <= subgroupEnd) {
137         if ((isspace(*permStrPtr) || (*permStrPtr == RM_POLICY_PERM_SUBGROUP_END))
138             && foundInstName) {
139             /* First space encountered after copying an instance name.  This
140              * terminates the instance name.  All other space characters are
141              * ignored. */
142             instNameTemp[instNameIndex] = '\0';
143             instNameComplete = TRUE; 
144         }
145         else {
146             if (!foundInstName) {
147                 /* First non-whitespace character encountered is the start of an
148                  * instance name */
149                 foundInstName = TRUE;
150             }
152             /* Copy the character into the temporary instance name string */
153             instNameTemp[instNameIndex++] = *permStrPtr;
154         }
156         if (instNameComplete) {
157             newPerm = (Rm_PolicyPermission *) Rm_osalMalloc(sizeof(Rm_PolicyPermission));
158             memset((void *)newPerm, 0, sizeof(Rm_PolicyPermission));
160             strncpy(newPerm->instName, instNameTemp, RM_NAME_MAX_CHARS);
161             newPerm->nextPermission = NULL;
163             if (prevPerm == NULL) {
164                 /* Save the first instance so it can be returned */
165                 startPerm = newPerm;
166             }
167             else {
168                 prevPerm->nextPermission = (void *) newPerm;
169             }
170             prevPerm = newPerm;
172             instNameComplete = FALSE;
173             instNameIndex = 0;
174             foundInstName = FALSE;
175         }
176         else if (instNameIndex == RM_NAME_MAX_CHARS) {
177             /* Instance name is longer than max length */
178             while (startPerm) {
179                 nextPerm = startPerm->nextPermission;
180                 Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
181                 startPerm = nextPerm;
182             } 
183             Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
184             *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_INSTANCE_NAME_IN_ASSIGNMENT_TOO_LONG;
185             return(NULL);
186         }
188         permStrPtr++;
189     }
191     /* Fill in the permissions for each instance name */
193     /* Look on left of instance group for permission assignments. */
194     permStrPtr = subgroupStart - 1;
195     assignmentLeft = FALSE;
196     while (permStrPtr >= permStrStart)
197     {
198         if (*permStrPtr == RM_POLICY_PERM_ASSIGNMENT) {
199             if (assignmentLeft) {
200                 /* Assignment character has been found more than once.  This is a
201                  * syntax error.  Free the permission list and the temporary string
202                  * and return. */
203                 while (startPerm) {
204                     nextPerm = startPerm->nextPermission;
205                     Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
206                     startPerm = nextPerm;
207                 } 
208                 Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
209                 *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_MORE_THAN_ONE_ASSIGNMENT_CHAR;
210                 return(NULL);
211             }
212             else {
213                 assignmentLeft = TRUE;
214             }
215         }
216         else if (!isspace(*permStrPtr)) {
217             if (assignmentLeft) {
218                 if ((*permStrPtr == RM_POLICY_PERM_INIT_LOWER) || 
219                     (*permStrPtr == RM_POLICY_PERM_INIT_UPPER)) {
220                     newPerm = startPerm;
221                     while (newPerm) {
222                         RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_INIT_SHIFT, 1);
223                         newPerm = newPerm->nextPermission;
224                     }
225                 }
226                 else if ((*permStrPtr == RM_POLICY_PERM_USE_LOWER) || 
227                          (*permStrPtr == RM_POLICY_PERM_USE_UPPER)) {
228                     newPerm = startPerm;
229                     while (newPerm) {                                           
230                         RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_USE_SHIFT, 1);
231                         newPerm = newPerm->nextPermission;
232                     }
233                 }
234                 else if ((*permStrPtr == RM_POLICY_PERM_EXCLUSIVE_LOWER) || 
235                          (*permStrPtr == RM_POLICY_PERM_EXCLUSIVE_UPPER)) {
236                     newPerm = startPerm;
237                     while (newPerm) {                       
238                         RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_EXCLUSIVE_SHIFT, 1);
239                         newPerm = newPerm->nextPermission;
240                     }
241                 }
242                 else if ((*permStrPtr == RM_POLICY_PERM_SHARED_LINUX_LOWER) || 
243                          (*permStrPtr == RM_POLICY_PERM_SHARED_LINUX_UPPER)) {
244                     newPerm = startPerm;
245                     while (newPerm) {                       
246                         RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_SHARED_LINUX_SHIFT, 1);
247                         newPerm = newPerm->nextPermission;
248                     }
249                 }                
250                 else {
251                     /* Invalid permission character.  This is a
252                      * syntax error.  Free the permission list and the temporary string
253                      * and return. */
254                     while (startPerm) {
255                         nextPerm = startPerm->nextPermission;
256                         Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
257                         startPerm = nextPerm;
258                     }  
259                     Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
260                     *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_INVALID_PERM_CHAR;
261                     return(NULL);
262                 }
263             }
264             else {
265                 /* Character found without the assignment character being found.  This is a
266                  * syntax error.  Free the permission list and the temporary string
267                  * and return. */
268                 while (startPerm) {
269                     nextPerm = startPerm->nextPermission;
270                     Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
271                     startPerm = nextPerm;
272                 }  
273                 Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
274                 *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_PERM_CHAR_WITHOUT_ASSIGN_CHAR;
275                 return(NULL);
276             }
277         }
278         permStrPtr--;
279     }
281     /* Look on right of instance group for permission assignments. */
282     permStrPtr = subgroupEnd + 1;
283     assignmentRight = FALSE;
284     while (permStrPtr < permStrEnd) {
285         if (assignmentLeft && (!isspace(*permStrPtr))) {
286             /* There should be nothing but spaces on right if assignment was already found on left */
287             while (startPerm) {
288                 nextPerm = startPerm->nextPermission;
289                 Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
290                 startPerm = nextPerm;
291             } 
292             Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
293             *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_INVALID_CHAR_ON_RIGHT_WITH_ASSINMENT_ON_LEFT;
294             return(NULL);              
295         }
296         
297         if (*permStrPtr == RM_POLICY_PERM_ASSIGNMENT) {
298             if (assignmentRight) {
299                 /* Assignment character has been found more than once.  This is a
300                  * syntax error.  Free the permission list and the temporary string
301                  * and return. */
302                 while (startPerm) {
303                     nextPerm = startPerm->nextPermission;
304                     Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
305                     startPerm = nextPerm;
306                 } 
307                 Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
308                 *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_MORE_THAN_ONE_ASSIGNMENT_CHAR;
309                 return(NULL);                
310             }
311             else {
312                 assignmentRight = TRUE;
313             }
314         }
315         else if (!isspace(*permStrPtr)) {
316             if (assignmentRight) {
317                 if ((*permStrPtr == RM_POLICY_PERM_INIT_LOWER) || 
318                     (*permStrPtr == RM_POLICY_PERM_INIT_UPPER)) {
319                     newPerm = startPerm;
320                     while (newPerm) {
321                         RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_INIT_SHIFT, 1);
322                         newPerm = newPerm->nextPermission;
323                     }
324                 }
325                 else if ((*permStrPtr == RM_POLICY_PERM_USE_LOWER) || 
326                          (*permStrPtr == RM_POLICY_PERM_USE_UPPER)) {
327                     newPerm = startPerm;
328                     while (newPerm) {                                           
329                         RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_USE_SHIFT, 1);
330                         newPerm = newPerm->nextPermission;
331                     }
332                 }
333                 else if ((*permStrPtr == RM_POLICY_PERM_EXCLUSIVE_LOWER) || 
334                          (*permStrPtr == RM_POLICY_PERM_EXCLUSIVE_UPPER)) {
335                     newPerm = startPerm;
336                     while (newPerm) {                       
337                         RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_EXCLUSIVE_SHIFT, 1);
338                         newPerm = newPerm->nextPermission;
339                     }
340                 }
341                 else if ((*permStrPtr == RM_POLICY_PERM_SHARED_LINUX_LOWER) || 
342                          (*permStrPtr == RM_POLICY_PERM_SHARED_LINUX_UPPER)) {
343                     newPerm = startPerm;
344                     while (newPerm) {                       
345                         RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_SHARED_LINUX_SHIFT, 1);
346                         newPerm = newPerm->nextPermission;
347                     }
348                 }                  
349                 else {
350                     /* Invalid permission character.  This is a
351                      * syntax error.  Free the permission list and the temporary string
352                      * and return. */
353                     while (startPerm) {
354                         nextPerm = startPerm->nextPermission;
355                         Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
356                         startPerm = nextPerm;
357                     }    
358                     Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
359                     *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_INVALID_PERM_CHAR;
360                     return(NULL);                    
361                 }
362             }
363             else {
364                 /* Character found without the assignment character being found.  This is a
365                  * syntax error.  Free the permission list and the temporary string
366                  * and return. */
367                 while (startPerm) {
368                     nextPerm = startPerm->nextPermission;
369                     Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
370                     startPerm = nextPerm;
371                 }    
372                 Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
373                 *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_MORE_THAN_ONE_ASSIGNMENT_CHAR;
374                 return(NULL);                
375             }
376         }
377         permStrPtr++;
378     }
380     Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
381     return (startPerm);
384 static void policyFreeAssignmentPermissions(Rm_PolicyPermission *permissionList)
386     Rm_PolicyPermission *nextPerm;
387     
388     while (permissionList) {
389         nextPerm = permissionList->nextPermission;
390         Rm_osalFree((void *)permissionList, sizeof(Rm_PolicyPermission));
391         permissionList = nextPerm;
392     }
395 static Rm_PolicyPermission *policyGetAssignmentPermissions(Rm_PolicyAssignment *assignment, 
396                                                            int32_t *result)
398     Rm_PolicyPermission *startPerm = NULL;
399     Rm_PolicyPermission *newPerm = NULL;
400     Rm_PolicyPermission *prevPerm = NULL;
401     char                *permStrStart = assignment->permissionsList;
402     char                *permStrEnd;
403     uint32_t             permStrLen = strlen(assignment->permissionsList) + 1;
404     uint32_t             i = 0;
405     
406     while(i < permStrLen) {
407         /* Find the first sub-permission specification and parse it.  A sub-permission
408          * can be terminated by the termination character or the end of the string. */
409         if (!(permStrEnd = strchr(permStrStart, RM_POLICY_PERM_TERMINATOR))) {           
410             /* Sub-permission termination character not found.  The permission string
411              * end is the end of the entire permission string */
412             permStrEnd = permStrStart + strlen(permStrStart);
413         }
415         newPerm = policyParseSubPermission(permStrStart, permStrEnd, result);
417         if (*result != RM_SERVICE_PROCESSING) {
418             /* Delete the permission list that's been created thus far, return
419              * the error and NULL for the permission list */
420             policyFreeAssignmentPermissions(startPerm);
421             return(NULL);
422         }
424         if (prevPerm == NULL) {
425             startPerm = newPerm;
426         }
427         else {
428             prevPerm->nextPermission = newPerm;
429         }
431         /* Set prevPerm to the last sub-permission returned by the sub-permission parser */
432         prevPerm = newPerm;
433         while(prevPerm->nextPermission != NULL) {
434             prevPerm = prevPerm->nextPermission;
435         }
436         
437         /* Update the number of characters parsed from the permission list and point to 
438          * the start of the next sub-permission */
439         i += ((uint32_t)(permStrEnd - permStrStart + 1));
440         permStrStart = permStrEnd + 1;
441     }
443     return(startPerm);
446 static int32_t policyValidateAssignmentPermissions(Rm_PolicyValidInstTree *root,
447                                                    Rm_PolicyAssignment *assignmentList)
449     Rm_PolicyAssignment *assignment = assignmentList;
450     Rm_PolicyPermission *permissionList;
451     int32_t              result;
453     while (assignment) {
454         /* Make sure assignment's permissions parse okay */
455         permissionList = policyGetAssignmentPermissions(assignment, &result);
456         if (result != RM_INIT_OK) {
457             return(result);
458         }                        
459         
460         if (result = policyCheckInstances(root, permissionList) != RM_INIT_OK) {
461             policyFreeAssignmentPermissions(permissionList);
462             return(result);
463         }
465         policyFreeAssignmentPermissions(permissionList);
466         assignment = assignment->nextAssignment;
467     }
469     return (RM_INIT_OK);
472 /**********************************************************************
473  ************************ Internal Policy APIs ************************
474  **********************************************************************/
476 Rm_PolicyValidInstNode *rmPolicyGetValidInstNode(Rm_PolicyValidInstTree *validInstTree, char *instName)
478     Rm_PolicyValidInstNode  findNode;
480     memset((void *)&findNode, 0, sizeof(Rm_PolicyValidInstNode));
481     strncpy(findNode.name, instName, RM_NAME_MAX_CHARS);
482     
483     return (RB_FIND(_Rm_PolicyValidInstTree, validInstTree, &findNode));
486 Rm_PolicyValidInstNode *rmPolicyGetLinuxInstNode(Rm_PolicyValidInstTree *validInstTree)
488     char linuxName[] = RM_ALLOCATED_TO_LINUX;
490     return (rmPolicyGetValidInstNode(validInstTree, linuxName));
493 bool rmPolicyCheckPrivilege(Rm_PolicyCheckCfg *privilegeCfg, int32_t *result)
495     int32_t              propertyOffset;
496     const char          *propertyName;
497         int32_t              propertyLen;
498         const void          *propertyData;
499     Rm_PolicyAssignment *assignment = NULL;
500     Rm_PolicyAssignment *assignmentStart = NULL;
501     Rm_PolicyPermission *permission = NULL;
502     Rm_PolicyPermission *permissionStart = NULL;
503     uint32_t             assignmentEnd;
504     uint32_t             resourceEnd = privilegeCfg->resourceBase + privilegeCfg->resourceLength - 1;
505     bool                 foundInstance;
507     /* Get the resource's assignments */
508     propertyOffset = fdt_first_property_offset(privilegeCfg->policyDtb, privilegeCfg->resourceOffset);
509     if (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
510         while (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
511             propertyData = fdt_getprop_by_offset(privilegeCfg->policyDtb, propertyOffset, &propertyName, &propertyLen);
512             if (rmDtbUtilPolicyGetPropertyType(propertyName) == Rm_policyPropType_ASSIGNMENTS) {
513                 assignment = assignmentStart = rmDtbUtilPolicyExtractAssignments(propertyData, propertyLen);
514                 break;
515             }
516             propertyOffset = fdt_next_property_offset(privilegeCfg->policyDtb, propertyOffset);
517         }
518     }
520     if (assignment) {
521         while (assignment) {
522             assignmentEnd = assignment->resourceBase + assignment->resourceLength - 1;
523             foundInstance = FALSE;
524             if (((privilegeCfg->resourceBase >= assignment->resourceBase) &&
525                  (privilegeCfg->resourceBase <= assignmentEnd)) ||
526                 ((privilegeCfg->resourceBase < assignment->resourceBase) &&
527                  (resourceEnd > assignmentEnd)) ||
528                 ((resourceEnd >= assignment->resourceBase) &&
529                  (resourceEnd <= assignmentEnd))) {
530                  
531                 permission = permissionStart = policyGetAssignmentPermissions(assignment, result);
532                 while (permission) {
533                     if ((strcmp(permission->instName, privilegeCfg->validInstNode->name) == 0) ||
534                         (strcmp(permission->instName, Rm_policyAllInstances) == 0)) {
535                         foundInstance = TRUE;
536                         
537                         /* Check instance's permissions */
538                         if (privilegeCfg->type == Rm_policyCheck_INIT) {
539                             if (!RM_policy_GET_PERM(permission->permissionBits, RM_POLICY_PERM_INIT_SHIFT)) {
540                                 policyFreeAssignmentPermissions(permissionStart);
541                                 rmDtbUtilPolicyFreeAssignments(assignmentStart);
542                                 return(FALSE);
543                             }
544                         }
545                         else if (privilegeCfg->type == Rm_policyCheck_USE) {
546                             if (!RM_policy_GET_PERM(permission->permissionBits, RM_POLICY_PERM_USE_SHIFT)) {
547                                 policyFreeAssignmentPermissions(permissionStart);
548                                 rmDtbUtilPolicyFreeAssignments(assignmentStart);
549                                 return(FALSE);
550                             }   
551                         }
552                         else if (privilegeCfg->type == Rm_policyCheck_EXCLUSIVE) {
553                             if (!RM_policy_GET_PERM(permission->permissionBits, RM_POLICY_PERM_EXCLUSIVE_SHIFT)) {
554                                 policyFreeAssignmentPermissions(permissionStart);
555                                 rmDtbUtilPolicyFreeAssignments(assignmentStart);
556                                 return(FALSE);
557                             }   
558                         }
559                         break;
560                     }
561                     permission = permission->nextPermission;
562                 }
563                 
564                 policyFreeAssignmentPermissions(permissionStart);
565                 if (!foundInstance) {
566                     rmDtbUtilPolicyFreeAssignments(assignmentStart);
567                     return(FALSE);
568                 }
569             }
570             assignment = assignment->nextAssignment;
571         }
572         rmDtbUtilPolicyFreeAssignments(assignmentStart);
573     }
574     else {
575         return(FALSE);
576     }
577     
578     return(TRUE);
581 uint32_t rmPolicyGetResourceBase(void *policyDtb, Rm_PolicyValidInstNode *validInstNode, 
582                                  int32_t resourceOffset, uint32_t allocType, 
583                                  int32_t *result)
586     int32_t              propertyOffset;
587     const char          *propertyName;
588         int32_t              propertyLen;
589         const void          *propertyData;
590     Rm_PolicyAssignment *assignment = NULL;
591     Rm_PolicyAssignment *assignmentStart = NULL;
592     Rm_PolicyPermission *permission = NULL;
593     Rm_PolicyPermission *permissionStart = NULL;
594     uint32_t             resourceBase = 0;
596     propertyOffset = fdt_first_property_offset(policyDtb, resourceOffset);
597     if (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
598         while (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
599             propertyData = fdt_getprop_by_offset(policyDtb, propertyOffset, &propertyName, &propertyLen);
600             if (rmDtbUtilPolicyGetPropertyType(propertyName) == Rm_policyPropType_ASSIGNMENTS) {
601                 assignment = assignmentStart = rmDtbUtilPolicyExtractAssignments(propertyData, propertyLen);
602                 break;
603             }
604             propertyOffset = fdt_next_property_offset(policyDtb, propertyOffset);
605         }
606     }
608     /* Search policy permissions for a valid resource base */
609     if (assignment) {
610         while (assignment) {
611             permission = permissionStart = policyGetAssignmentPermissions(assignment, result);
612             while (permission) {
613                 if ((strcmp(permission->instName, validInstNode->name) == 0) ||
614                     (strcmp(permission->instName, Rm_policyAllInstances) == 0)) {
615                     /* Check instance's permissions */
616                     if (RM_policy_GET_PERM(allocType, RM_POLICY_PERM_INIT_SHIFT) &&
617                         RM_policy_GET_PERM(permission->permissionBits, RM_POLICY_PERM_INIT_SHIFT)) {
618                         resourceBase = assignment->resourceBase;
619                         break;
620                     }
621                     else if (RM_policy_GET_PERM(allocType, RM_POLICY_PERM_USE_SHIFT) &&
622                              RM_policy_GET_PERM(permission->permissionBits, RM_POLICY_PERM_USE_SHIFT)) {
623                         resourceBase = assignment->resourceBase;
624                         break;
625                     }
626                 }
627                 permission = permission->nextPermission;
628             }
629             policyFreeAssignmentPermissions(permissionStart);
631             if (resourceBase) {
632                 break;
633             }
634             else {
635                 assignment = assignment->nextAssignment;
636             }
637         }
638         rmDtbUtilPolicyFreeAssignments(assignmentStart);
639     }
640     else {
641         *result = RM_SERVICE_DENIED_NO_RANGE_ASSIGNMENTS_FOR_POLICY;
642     }
643     
644     return(resourceBase);
647 uint32_t rmPolicyGetResourceAlignment(void *policyDtb, int32_t resourceOffset)
649     int32_t            propertyOffset;
650     const char        *propertyName;
651         int32_t            propertyLen;
652         const void        *propertyData;
653     Rm_ResourceValue  *alignmentList;
654     uint32_t           resourceAlignment = 0;
656     propertyOffset = fdt_first_property_offset(policyDtb, resourceOffset);
657     if (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
658         while (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
659             propertyData = fdt_getprop_by_offset(policyDtb, propertyOffset, &propertyName, &propertyLen);
660             if (rmDtbUtilPolicyGetPropertyType(propertyName) == Rm_policyPropType_ALLOCATION_ALIGNMENT) {
661                 alignmentList = rmDtbUtilPolicyExtractResourceAlignments(propertyData, propertyLen);
662                 resourceAlignment = alignmentList->value;                
663                 rmDtbUtilPolicyFreeResourceAlignments(alignmentList);
664             }
665             propertyOffset = fdt_next_property_offset(policyDtb, propertyOffset);
666         }
667     }
668     return(resourceAlignment);
671 int32_t rmPolicyGetResourceOffset(void *policyDtb, char *resourceName)
673     int32_t     nodeOffset;
674     int32_t     depth;
675     const char *nodeName;
677     depth = RM_DTB_UTIL_STARTING_DEPTH;
678     nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;       
680     /* Find node offset for provided resource name */
681     while ((nodeOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && 
682            (depth >= RM_DTB_UTIL_STARTING_DEPTH)) {
683         nodeOffset = fdt_next_node(policyDtb, nodeOffset, &depth);
684         nodeName = fdt_get_name(policyDtb, nodeOffset, NULL);
686         if (strcmp(nodeName, resourceName) == 0)
687         {
688             break;
689         }
690     }
691     return(nodeOffset);
694 int32_t rmPolicyValidatePolicyResourceNames(void *policyDtb, void *allocatorList)
696     Rm_Allocator *allocator = (Rm_Allocator *)allocatorList;
697     int32_t       nodeOffset;
698     int32_t       depth;
699     const char   *nodeName;
701     depth = RM_DTB_UTIL_STARTING_DEPTH;
702     nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;       
704     /* Parse DTB, verifying each resource's assignment permissions.
705      * Permissions must have correct syntax and contain valid instance names
706      * according validInstList */
707     while ((nodeOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && 
708            (depth >= RM_DTB_UTIL_STARTING_DEPTH)) {
709         nodeOffset = fdt_next_node(policyDtb, nodeOffset, &depth);
710         nodeName = fdt_get_name(policyDtb, nodeOffset, NULL);
711         if (fdt_first_property_offset(policyDtb, nodeOffset) > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
712             if (rmAllocatorFind(allocator, (char *)nodeName) == NULL) {
713                 /* No allocator tied to resource name */
714                 return(RM_INIT_ERROR_POLICY_UNKNOWN_RESOURCE);
715             }        
716         }
717     }
718     return(RM_INIT_OK);
721 /* TODO: ADD ABILITY TO RETURN THE SYNTAX ERROR LOCATION */
722 int32_t rmPolicyValidatePolicy(void *policyDtb, Rm_PolicyValidInstTree *validInstTree)
724     int32_t              nodeOffset;
725     int32_t              propertyOffset;
726     int32_t              depth;
727     const char          *propertyName;
728         int32_t              propertyLen;
729         const void          *propertyData;
730     Rm_PolicyPropType    propertyType;
731     Rm_PolicyAssignment *assignmentList;
732     int32_t              result;
734     depth = RM_DTB_UTIL_STARTING_DEPTH;
735     nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;       
737     /* Parse DTB, verifying each resource's assignment permissions.
738      * Permissions must have correct syntax and contain valid instance names
739      * according validInstList */
740     while ((nodeOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && 
741            (depth >= RM_DTB_UTIL_STARTING_DEPTH)) {
742         nodeOffset = fdt_next_node(policyDtb, nodeOffset, &depth);
743         propertyOffset = fdt_first_property_offset(policyDtb, nodeOffset);                
744         while (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
745             propertyData = fdt_getprop_by_offset(policyDtb, propertyOffset, &propertyName, &propertyLen);
746             propertyType = rmDtbUtilPolicyGetPropertyType(propertyName);
747             if (propertyType == Rm_policyPropType_ASSIGNMENTS) {
748                 assignmentList = rmDtbUtilPolicyExtractAssignments(propertyData, propertyLen);
749                 
750                 if ((result = policyValidateAssignmentPermissions(validInstTree, assignmentList)) != RM_INIT_OK) {
751                     rmDtbUtilPolicyFreeAssignments(assignmentList);
752                     return(result);
753                 }
754                 rmDtbUtilPolicyFreeAssignments(assignmentList);
755             }
756             else if (propertyType == Rm_policyPropType_UNKNOWN) {
757                 return(RM_INIT_ERROR_POLICY_UNKNOWN_RESOURCE_PROPERTY);
758             }
759             propertyOffset = fdt_next_property_offset(policyDtb, propertyOffset);
760         }
761     }
762     return(RM_INIT_OK);
765 Rm_PolicyValidInstTree *rmPolicyCreateValidInstTree(void *policyDtb, int32_t *result)
767     int32_t                 validInstOffset;
768     const char             *validInstName = NULL;
769         int32_t                 validInstLen;
770         const void             *validInstData = NULL;
771     Rm_PolicyPropType       propertyType;
772     Rm_PolicyValidInst     *validInstList = NULL;
773     Rm_PolicyValidInstTree *rootEntry = NULL;
774     Rm_PolicyValidInstNode *newNode = NULL;  
775     char                    linuxName[] = RM_ALLOCATED_TO_LINUX;
777     /* Valid instance list must be first and only property in the root node of
778      * the policyDtb */
779     validInstOffset = fdt_first_property_offset(policyDtb, RM_DTB_UTIL_STARTING_NODE_OFFSET);
780     if (validInstOffset < -FDT_ERR_NOTFOUND) {
781         *result = validInstOffset;
782         return (NULL);
783     } 
784     else if (validInstOffset == -FDT_ERR_NOTFOUND) {
785         *result = RM_INIT_ERROR_POLICY_NO_VALID_INSTANCES_DEFINED;
786         return (NULL);
787     }
788     validInstData = fdt_getprop_by_offset(policyDtb, validInstOffset, &validInstName, &validInstLen);
789     propertyType = rmDtbUtilPolicyGetPropertyType(validInstName);
790     if (propertyType != Rm_policyPropType_VALID_INSTANCES) {
791         *result = RM_INIT_ERROR_POLICY_NO_VALID_INSTANCES_DEFINED;
792         return (NULL);
793     }
795     if (!(validInstList = rmDtbUtilPolicyExtractValidInstances(validInstData, validInstLen, result))) {
796         return (NULL);
797     }
798     
799     /* Create the tree */
800     rootEntry = Rm_osalMalloc(sizeof(Rm_PolicyValidInstTree));
801     RB_INIT(rootEntry);
803     while (validInstList) {
804         newNode = rmPolicyValidInstNodeNew(validInstList->instName);
805         RB_INSERT(_Rm_PolicyValidInstTree, rootEntry, newNode);
806         
807         validInstList = validInstList->nextValidInst;
808     }
810     /* Add the Linux kernel node */
811     newNode = rmPolicyValidInstNodeNew(linuxName);
812     RB_INSERT(_Rm_PolicyValidInstTree, rootEntry, newNode);    
814     *result = RM_INIT_OK;
815     return (rootEntry);
818 void rmPolicyFreeValidInstTree(Rm_PolicyValidInstTree *validInstTree)
820     Rm_PolicyValidInstNode *node;
821     
822     RB_FOREACH(node, _Rm_PolicyValidInstTree, validInstTree) {               
823         RB_REMOVE(_Rm_PolicyValidInstTree, validInstTree, node);
824         rmPolicyValidInstNodeFree(node);
825     }        
826     Rm_osalFree((void *)validInstTree, sizeof(Rm_PolicyValidInstTree));