26f2529de315bb409477ea87f8c96028ea1ead90
[keystone-rtos/rm-lld.git] / src / rm_policy.c
1 /**
2  *   @file  rmpolicy.c
3  *
4  *   @brief   
5  *      Resource Manager Policy source.
6  *
7  *  \par
8  *  ============================================================================
9  *  @n   (C) Copyright 2012, 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 /* RM Types */
43 #include <ti/drv/rm/rm_types.h>
45 /* RM external API includes */
46 #include <ti/drv/rm/rm.h>
47 #include <ti/drv/rm/rm_policy.h>
48 #include <ti/drv/rm/rm_services.h>
50 /* RM internal API includes */
51 #include <ti/drv/rm/include/rm_loc.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/src/libfdt/libfdt.h>
58 /* AVL BBST includes */
59 #include <ti/drv/rm/include/tree.h>
61 /* RM OSAL layer */
62 #include <rm_osal.h>
64 /**********************************************************************
65  *********************** Policy Globals *******************************
66  **********************************************************************/
68 char Rm_policyAllInstances[] = "*";
70 /**********************************************************************
71  *************** Policy Valid Instance Tree Functions *****************
72  **********************************************************************/
73 Rm_PolicyValidInstNode *Rm_policyNewValidInstNode(char *instName)
74 {
75     Rm_PolicyValidInstNode *newNode = NULL;
77     newNode = Rm_osalMalloc(sizeof(Rm_PolicyValidInstNode));
78     
79     strcpy(newNode->name, instName);
80     newNode->allocRefCount = 0;
81     newNode->deletePending = FALSE;
82     
83     return(newNode);
84 }
86 void Rm_policyFreeValidInstNode(Rm_PolicyValidInstNode *node)
87 {
88     if (node->allocRefCount == 0) {
89         Rm_osalFree((void *)node, sizeof(Rm_PolicyValidInstNode));
90     }
91 }
93 int Rm_policyValidInstNodeCompare(Rm_PolicyValidInstNode *node1, Rm_PolicyValidInstNode *node2)
94 {
95     return(strcmp(node1->name, node2->name));
96 }
98 /* Generate the valid instance tree manipulation functions */
99 RB_GENERATE(_Rm_PolicyValidInstTree, _Rm_PolicyValidInstNode, linkage, Rm_policyValidInstNodeCompare);
101 /**********************************************************************
102  ******************** Local Policy Functions **************************
103  **********************************************************************/
105 int32_t Rm_policyCheckInstances(Rm_PolicyValidInstTree *validInstTree, 
106                                 Rm_PolicyPermission *permissionsList)
108     while (permissionsList) {
109         if (strcmp(permissionsList->instName, Rm_policyAllInstances) &&
110             (!Rm_policyGetValidInstNode(validInstTree, permissionsList->instName))) {
111             return(RM_INIT_ERROR_POLICY_UNKNOWN_INSTANCE);
112         }
113         permissionsList = permissionsList->nextPermission;
114     }
115     return(RM_INIT_OK);
118 Rm_PolicyPermission *Rm_policyParseSubPermission(char *permStrStart, char *permStrEnd, 
119                                                  int32_t *result)
121     Rm_PolicyPermission *startPerm = NULL;
122     Rm_PolicyPermission *newPerm = NULL;
123     Rm_PolicyPermission *prevPerm = NULL;
124     Rm_PolicyPermission *nextPerm = NULL;
125     char *permStrPtr = NULL;
126     char *subgroupStart = NULL;
127     char *subgroupEnd = NULL;
128     uint32_t permStrLen = (uint32_t)(permStrEnd - permStrStart + 1);
129     char instNameTemp[RM_INSTANCE_NAME_MAX_CHARS];
130     uint32_t instNameIndex;
131     bool foundInstName;
132     bool instNameComplete;
133     bool assignmentLeft;
134     bool assignmentRight;
136     /* Create a local copy of the sub-permission string */
137     permStrPtr = Rm_osalMalloc(permStrLen);
138     strncpy(permStrPtr, permStrStart, permStrLen);
139     /* Make sure the last character in the copied sub-permission string is null */
140     permStrPtr[permStrLen - 1] = '\0';
142     permStrStart = permStrPtr;
143     permStrEnd = permStrPtr + strlen(permStrPtr);
145     /* Find the beginning and end of the sub-permission instance group */
146     subgroupStart = strchr(permStrStart, RM_POLICY_PERM_SUBGROUP_START);
147     subgroupEnd = strchr(permStrStart, RM_POLICY_PERM_SUBGROUP_END);
149     if ((!subgroupStart) || (!subgroupEnd) || (subgroupStart > subgroupEnd) ||
150         ((subgroupStart != strrchr(permStrStart, RM_POLICY_PERM_SUBGROUP_START)) &&
151          (subgroupEnd != strrchr(permStrStart, RM_POLICY_PERM_SUBGROUP_END))))
152     {
153         /* Free the memory associated with the temp string and return an error if:
154          * a) Could not find the instance group start
155          * b) Could not find the instance group end
156          * c) Subgroup start and end are out of order
157          * d) There is more than one instance subgroup specified in the string.  There
158          *    should only be one subgroup per sub-permission string */
159         Rm_osalFree((void *)permStrStart, permStrLen);
160         *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_MORE_THAN_ONE_INSTANCE_GROUP;
161         return(NULL);
162     }
164     /* Create a permission entry for each instance specified in the instance group.
165      * Instances names are separated by one or more spaces. */
166     permStrPtr = subgroupStart + 1;
167     instNameIndex = 0;
168     foundInstName = FALSE;
169     instNameComplete = FALSE;
170     while (permStrPtr <= subgroupEnd) {
171         if ((isspace(*permStrPtr) || (*permStrPtr == RM_POLICY_PERM_SUBGROUP_END))
172             && foundInstName) {
173             /* First space encountered after copying an instance name.  This
174              * terminates the instance name.  All other space characters are
175              * ignored. */
176             instNameTemp[instNameIndex] = '\0';
177             instNameComplete = TRUE; 
178         }
179         else {
180             if (!foundInstName) {
181                 /* First non-whitespace character encountered is the start of an
182                  * instance name */
183                 foundInstName = TRUE;
184             }
186             /* Copy the character into the temporary instance name string */
187             instNameTemp[instNameIndex++] = *permStrPtr;
188         }
190         if (instNameComplete) {
191             newPerm = (Rm_PolicyPermission *) Rm_osalMalloc(sizeof(Rm_PolicyPermission));
192             memset((void *)newPerm, 0, sizeof(Rm_PolicyPermission));
194             strcpy(newPerm->instName, instNameTemp);
195             newPerm->nextPermission = NULL;
197             if (prevPerm == NULL) {
198                 /* Save the first instance so it can be returned */
199                 startPerm = newPerm;
200             }
201             else {
202                 prevPerm->nextPermission = (void *) newPerm;
203             }
204             prevPerm = newPerm;
206             instNameComplete = FALSE;
207             instNameIndex = 0;
208             foundInstName = FALSE;
209         }
211         permStrPtr++;
212     }
214     /* Fill in the permissions for each instance name */
216     /* Look on left of instance group for permission assignments. */
217     permStrPtr = subgroupStart - 1;
218     assignmentLeft = FALSE;
219     while (permStrPtr >= permStrStart)
220     {
221         if (*permStrPtr == RM_POLICY_PERM_ASSIGNMENT) {
222             if (assignmentLeft) {
223                 /* Assignment character has been found more than once.  This is a
224                  * syntax error.  Free the permission list and the temporary string
225                  * and return. */
226                 while (startPerm) {
227                     nextPerm = startPerm->nextPermission;
228                     Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
229                     startPerm = nextPerm;
230                 } 
231                 Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
232                 *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_MORE_THAN_ONE_ASSIGNMENT_CHAR;
233                 return(NULL);
234             }
235             else {
236                 assignmentLeft = TRUE;
237             }
238         }
239         else if (!isspace(*permStrPtr)) {
240             if (assignmentLeft) {
241                 if ((*permStrPtr == RM_POLICY_PERM_INIT_LOWER) || 
242                     (*permStrPtr == RM_POLICY_PERM_INIT_UPPER)) {
243                     newPerm = startPerm;
244                     while (newPerm) {
245                         RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_INIT_SHIFT, 1);
246                         newPerm = newPerm->nextPermission;
247                     }
248                 }
249                 else if ((*permStrPtr == RM_POLICY_PERM_USE_LOWER) || 
250                          (*permStrPtr == RM_POLICY_PERM_USE_UPPER)) {
251                     newPerm = startPerm;
252                     while (newPerm) {                                           
253                         RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_USE_SHIFT, 1);
254                         newPerm = newPerm->nextPermission;
255                     }
256                 }
257                 else if ((*permStrPtr == RM_POLICY_PERM_EXCLUSIVE_LOWER) || 
258                          (*permStrPtr == RM_POLICY_PERM_EXCLUSIVE_UPPER)) {
259                     newPerm = startPerm;
260                     while (newPerm) {                       
261                         RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_EXCLUSIVE_SHIFT, 1);
262                         newPerm = newPerm->nextPermission;
263                     }
264                 }
265                 else if ((*permStrPtr == RM_POLICY_PERM_SHARED_LINUX_LOWER) || 
266                          (*permStrPtr == RM_POLICY_PERM_SHARED_LINUX_UPPER)) {
267                     newPerm = startPerm;
268                     while (newPerm) {                       
269                         RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_SHARED_LINUX_SHIFT, 1);
270                         newPerm = newPerm->nextPermission;
271                     }
272                 }                
273                 else {
274                     /* Invalid permission character.  This is a
275                      * syntax error.  Free the permission list and the temporary string
276                      * and return. */
277                     while (startPerm) {
278                         nextPerm = startPerm->nextPermission;
279                         Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
280                         startPerm = nextPerm;
281                     }  
282                     Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
283                     *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_INVALID_PERM_CHAR;
284                     return(NULL);
285                 }
286             }
287             else {
288                 /* Character found without the assignment character being found.  This is a
289                  * syntax error.  Free the permission list and the temporary string
290                  * and return. */
291                 while (startPerm) {
292                     nextPerm = startPerm->nextPermission;
293                     Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
294                     startPerm = nextPerm;
295                 }  
296                 Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
297                 *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_PERM_CHAR_WITHOUT_ASSIGN_CHAR;
298                 return(NULL);
299             }
300         }
301         permStrPtr--;
302     }
304     /* Look on right of instance group for permission assignments. */
305     permStrPtr = subgroupEnd + 1;
306     assignmentRight = FALSE;
307     while (permStrPtr < permStrEnd) {
308         if (assignmentLeft && (!isspace(*permStrPtr))) {
309             /* There should be nothing but spaces on right if assignment was already found on left */
310             while (startPerm) {
311                 nextPerm = startPerm->nextPermission;
312                 Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
313                 startPerm = nextPerm;
314             } 
315             Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
316             *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_INVALID_CHAR_ON_RIGHT_WITH_ASSINMENT_ON_LEFT;
317             return(NULL);              
318         }
319         
320         if (*permStrPtr == RM_POLICY_PERM_ASSIGNMENT) {
321             if (assignmentRight) {
322                 /* Assignment character has been found more than once.  This is a
323                  * syntax error.  Free the permission list and the temporary string
324                  * and return. */
325                 while (startPerm) {
326                     nextPerm = startPerm->nextPermission;
327                     Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
328                     startPerm = nextPerm;
329                 } 
330                 Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
331                 *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_MORE_THAN_ONE_ASSIGNMENT_CHAR;
332                 return(NULL);                
333             }
334             else {
335                 assignmentRight = TRUE;
336             }
337         }
338         else if (!isspace(*permStrPtr)) {
339             if (assignmentRight) {
340                 if ((*permStrPtr == RM_POLICY_PERM_INIT_LOWER) || 
341                     (*permStrPtr == RM_POLICY_PERM_INIT_UPPER)) {
342                     newPerm = startPerm;
343                     while (newPerm) {
344                         RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_INIT_SHIFT, 1);
345                         newPerm = newPerm->nextPermission;
346                     }
347                 }
348                 else if ((*permStrPtr == RM_POLICY_PERM_USE_LOWER) || 
349                          (*permStrPtr == RM_POLICY_PERM_USE_UPPER)) {
350                     newPerm = startPerm;
351                     while (newPerm) {                                           
352                         RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_USE_SHIFT, 1);
353                         newPerm = newPerm->nextPermission;
354                     }
355                 }
356                 else if ((*permStrPtr == RM_POLICY_PERM_EXCLUSIVE_LOWER) || 
357                          (*permStrPtr == RM_POLICY_PERM_EXCLUSIVE_UPPER)) {
358                     newPerm = startPerm;
359                     while (newPerm) {                       
360                         RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_EXCLUSIVE_SHIFT, 1);
361                         newPerm = newPerm->nextPermission;
362                     }
363                 }
364                 else if ((*permStrPtr == RM_POLICY_PERM_SHARED_LINUX_LOWER) || 
365                          (*permStrPtr == RM_POLICY_PERM_SHARED_LINUX_UPPER)) {
366                     newPerm = startPerm;
367                     while (newPerm) {                       
368                         RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_SHARED_LINUX_SHIFT, 1);
369                         newPerm = newPerm->nextPermission;
370                     }
371                 }                  
372                 else {
373                     /* Invalid permission character.  This is a
374                      * syntax error.  Free the permission list and the temporary string
375                      * and return. */
376                     while (startPerm) {
377                         nextPerm = startPerm->nextPermission;
378                         Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
379                         startPerm = nextPerm;
380                     }    
381                     Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
382                     *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_INVALID_PERM_CHAR;
383                     return(NULL);                    
384                 }
385             }
386             else {
387                 /* Character found without the assignment character being found.  This is a
388                  * syntax error.  Free the permission list and the temporary string
389                  * and return. */
390                 while (startPerm) {
391                     nextPerm = startPerm->nextPermission;
392                     Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
393                     startPerm = nextPerm;
394                 }    
395                 Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
396                 *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_MORE_THAN_ONE_ASSIGNMENT_CHAR;
397                 return(NULL);                
398             }
399         }
400         permStrPtr++;
401     }
403     Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
404     return (startPerm);
407 void Rm_policyFreeAssignmentPermissions(Rm_PolicyPermission *permissionList)
409     Rm_PolicyPermission *nextPerm;
410     
411     while (permissionList) {
412         nextPerm = permissionList->nextPermission;
413         Rm_osalFree((void *)permissionList, sizeof(Rm_PolicyPermission));
414         permissionList = nextPerm;
415     }
418 Rm_PolicyPermission *Rm_policyGetAssignmentPermissions(Rm_PolicyAssignment *assignment, 
419                                                        int32_t *result)
421     Rm_PolicyPermission *startPerm = NULL;
422     Rm_PolicyPermission *newPerm = NULL;
423     Rm_PolicyPermission *prevPerm = NULL;
424     char *permStrStart = assignment->permissionsList;
425     char *permStrEnd;
426     uint32_t permStrLen = strlen(assignment->permissionsList) + 1;
427     uint32_t i = 0;
428     
429     while(i < permStrLen) {
430         /* Find the first sub-permission specification and parse it.  A sub-permission
431          * can be terminated by the termination character or the end of the string. */
432         if (!(permStrEnd = strchr(permStrStart, RM_POLICY_PERM_TERMINATOR))) {           
433             /* Sub-permission termination character not found.  The permission string
434              * end is the end of the entire permission string */
435             permStrEnd = permStrStart + strlen(permStrStart);
436         }
438         newPerm = Rm_policyParseSubPermission(permStrStart, permStrEnd, result);
440         if (*result != RM_SERVICE_PROCESSING) {
441             /* Delete the permission list that's been created thus far, return
442              * the error and NULL for the permission list */
443             Rm_policyFreeAssignmentPermissions(startPerm);
444             return(NULL);
445         }
447         if (prevPerm == NULL) {
448             startPerm = newPerm;
449         }
450         else {
451             prevPerm->nextPermission = newPerm;
452         }
454         /* Set prevPerm to the last sub-permission returned by the sub-permission parser */
455         prevPerm = newPerm;
456         while(prevPerm->nextPermission != NULL) {
457             prevPerm = prevPerm->nextPermission;
458         }
459         
460         /* Update the number of characters parsed from the permission list and point to 
461          * the start of the next sub-permission */
462         i += ((uint32_t)(permStrEnd - permStrStart + 1));
463         permStrStart = permStrEnd + 1;
464     }
466     return(startPerm);
469 int32_t Rm_policyValidateAssignmentPermissions(Rm_PolicyValidInstTree *root,
470                                                Rm_PolicyAssignment *assignmentList)
472     Rm_PolicyAssignment *assignment = assignmentList;
473     Rm_PolicyPermission *permissionList;
474     int32_t result;
476     while (assignment) {
477         /* Make sure assignment's permissions parse okay */
478         permissionList = Rm_policyGetAssignmentPermissions(assignment, &result);
479         if (result != RM_INIT_OK) {
480             return(result);
481         }                        
482         
483         if (result = Rm_policyCheckInstances(root, permissionList) != RM_INIT_OK) {
484             Rm_policyFreeAssignmentPermissions(permissionList);
485             return(result);
486         }
488         Rm_policyFreeAssignmentPermissions(permissionList);
489         assignment = assignment->nextAssignment;
490     }
492     return (RM_INIT_OK);
495 /**********************************************************************
496  ************************ Internal Policy APIs ************************
497  **********************************************************************/
499 Rm_PolicyValidInstNode *Rm_policyGetValidInstNode(Rm_PolicyValidInstTree *validInstTree, char *instName)
501     Rm_PolicyValidInstNode  findNode;
503     memset((void *)&findNode, 0, sizeof(Rm_PolicyValidInstNode));
504     strcpy(findNode.name, instName);
505     
506     return (RB_FIND(_Rm_PolicyValidInstTree, validInstTree, &findNode));
509 Rm_PolicyValidInstNode *Rm_policyGetLinuxInstNode(Rm_PolicyValidInstTree *validInstTree)
511     char linuxName[] = RM_ALLOCATED_TO_LINUX;
513     return (Rm_policyGetValidInstNode(validInstTree, linuxName));
516 bool Rm_policyCheckPrivilege(Rm_PolicyCheckCfg *privilegeCfg, int32_t *result)
518     int32_t              propertyOffset;
519     const char          *propertyName;
520         int32_t              propertyLen;
521         const void          *propertyData;
522     Rm_PolicyAssignment *assignment = NULL;
523     Rm_PolicyAssignment *assignmentStart = NULL;
524     Rm_PolicyPermission *permission = NULL;
525     Rm_PolicyPermission *permissionStart = NULL;
526     uint32_t             assignmentEnd;
527     uint32_t             resourceEnd = privilegeCfg->resourceBase + privilegeCfg->resourceLength - 1;
528     bool                 foundInstance;
530     /* Get the resource's assignments */
531     propertyOffset = fdt_first_property_offset(privilegeCfg->policyDtb, privilegeCfg->resourceOffset);
532     if (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
533         while (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
534             propertyData = fdt_getprop_by_offset(privilegeCfg->policyDtb, propertyOffset, &propertyName, &propertyLen);
535             if (Rm_policyGetPropertyType(propertyName) == Rm_policyPropType_ASSIGNMENTS) {
536                 assignment = assignmentStart = Rm_policyExtractAssignments(propertyData, propertyLen);
537                 break;
538             }
539             propertyOffset = fdt_next_property_offset(privilegeCfg->policyDtb, propertyOffset);
540         }
541     }
543     if (assignment) {
544         while (assignment) {
545             assignmentEnd = assignment->resourceBase + assignment->resourceLength - 1;
546             foundInstance = FALSE;
547             if (((privilegeCfg->resourceBase >= assignment->resourceBase) &&
548                  (privilegeCfg->resourceBase <= assignmentEnd)) ||
549                 ((privilegeCfg->resourceBase < assignment->resourceBase) &&
550                  (resourceEnd > assignmentEnd)) ||
551                 ((resourceEnd >= assignment->resourceBase) &&
552                  (resourceEnd <= assignmentEnd))) {
553                  
554                 permission = permissionStart = Rm_policyGetAssignmentPermissions(assignment, result);
555                 while (permission) {
556                     if ((strcmp(permission->instName, privilegeCfg->validInstNode->name) == 0) ||
557                         (strcmp(permission->instName, Rm_policyAllInstances) == 0)) {
558                         foundInstance = TRUE;
559                         
560                         /* Check instance's permissions */
561                         if (privilegeCfg->type == Rm_policyCheck_INIT) {
562                             if (!RM_policy_GET_PERM(permission->permissionBits, RM_POLICY_PERM_INIT_SHIFT)) {
563                                 Rm_policyFreeAssignmentPermissions(permissionStart);
564                                 Rm_policyFreeAssignments(assignmentStart);
565                                 return(FALSE);
566                             }
567                         }
568                         else if (privilegeCfg->type == Rm_policyCheck_USE) {
569                             if (!RM_policy_GET_PERM(permission->permissionBits, RM_POLICY_PERM_USE_SHIFT)) {
570                                 Rm_policyFreeAssignmentPermissions(permissionStart);
571                                 Rm_policyFreeAssignments(assignmentStart);
572                                 return(FALSE);
573                             }   
574                         }
575                         else if (privilegeCfg->type == Rm_policyCheck_EXCLUSIVE) {
576                             if (!RM_policy_GET_PERM(permission->permissionBits, RM_POLICY_PERM_EXCLUSIVE_SHIFT)) {
577                                 Rm_policyFreeAssignmentPermissions(permissionStart);
578                                 Rm_policyFreeAssignments(assignmentStart);
579                                 return(FALSE);
580                             }   
581                         }
582                         break;
583                     }
584                     permission = permission->nextPermission;
585                 }
586                 
587                 Rm_policyFreeAssignmentPermissions(permissionStart);
588                 if (!foundInstance) {
589                     Rm_policyFreeAssignments(assignmentStart);
590                     return(FALSE);
591                 }
592             }
593             assignment = assignment->nextAssignment;
594         }
595         Rm_policyFreeAssignments(assignmentStart);
596     }
597     else {
598         return(FALSE);
599     }
600     
601     return(TRUE);
604 uint32_t Rm_policyGetResourceBase(void *policyDtb, Rm_PolicyValidInstNode *validInstNode, 
605                                   int32_t resourceOffset, uint32_t allocType, 
606                                   int32_t *result)
609     int32_t              propertyOffset;
610     const char          *propertyName;
611         int32_t              propertyLen;
612         const void          *propertyData;
613     Rm_PolicyAssignment *assignment = NULL;
614     Rm_PolicyAssignment *assignmentStart = NULL;
615     Rm_PolicyPermission *permission = NULL;
616     Rm_PolicyPermission *permissionStart = NULL;
617     uint32_t             resourceBase = 0;
619     propertyOffset = fdt_first_property_offset(policyDtb, resourceOffset);
620     if (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
621         while (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
622             propertyData = fdt_getprop_by_offset(policyDtb, propertyOffset, &propertyName, &propertyLen);
623             if (Rm_policyGetPropertyType(propertyName) == Rm_policyPropType_ASSIGNMENTS) {
624                 assignment = assignmentStart = Rm_policyExtractAssignments(propertyData, propertyLen);
625                 break;
626             }
627             propertyOffset = fdt_next_property_offset(policyDtb, propertyOffset);
628         }
629     }
631     /* Search policy permissions for a valid resource base */
632     if (assignment) {
633         while (assignment) {
634             permission = permissionStart = Rm_policyGetAssignmentPermissions(assignment, result);
635             while (permission) {
636                 if ((strcmp(permission->instName, validInstNode->name) == 0) ||
637                     (strcmp(permission->instName, Rm_policyAllInstances) == 0)) {
638                     /* Check instance's permissions */
639                     if (RM_policy_GET_PERM(allocType, RM_POLICY_PERM_INIT_SHIFT) &&
640                         RM_policy_GET_PERM(permission->permissionBits, RM_POLICY_PERM_INIT_SHIFT)) {
641                         resourceBase = assignment->resourceBase;
642                         break;
643                     }
644                     else if (RM_policy_GET_PERM(allocType, RM_POLICY_PERM_USE_SHIFT) &&
645                              RM_policy_GET_PERM(permission->permissionBits, RM_POLICY_PERM_USE_SHIFT)) {
646                         resourceBase = assignment->resourceBase;
647                         break;
648                     }
649                 }
650                 permission = permission->nextPermission;
651             }
652             Rm_policyFreeAssignmentPermissions(permissionStart);
654             if (resourceBase) {
655                 break;
656             }
657             else {
658                 assignment = assignment->nextAssignment;
659             }
660         }
661         Rm_policyFreeAssignments(assignmentStart);
662     }
663     else {
664         *result = RM_SERVICE_DENIED_NO_RANGE_ASSIGNMENTS_FOR_POLICY;
665     }
666     
667     return(resourceBase);
670 uint32_t Rm_policyGetResourceAlignment(void *policyDtb, int32_t resourceOffset)
672     int32_t            propertyOffset;
673     const char        *propertyName;
674         int32_t            propertyLen;
675         const void        *propertyData;
676     Rm_ResourceValue  *alignmentList;
677     uint32_t           resourceAlignment = 0;
679     propertyOffset = fdt_first_property_offset(policyDtb, resourceOffset);
680     if (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
681         while (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
682             propertyData = fdt_getprop_by_offset(policyDtb, propertyOffset, &propertyName, &propertyLen);
683             if (Rm_policyGetPropertyType(propertyName) == Rm_policyPropType_ALLOCATION_ALIGNMENTS) {
684                 alignmentList = Rm_policyExtractResourceAlignments(propertyData, propertyLen);
685                 resourceAlignment = alignmentList->value;                
686                 Rm_policyFreeResourceAlignments(alignmentList);
687             }
688             propertyOffset = fdt_next_property_offset(policyDtb, propertyOffset);
689         }
690     }
691     return(resourceAlignment);
694 int32_t Rm_policyGetResourceOffset(void *policyDtb, char *resourceName)
696     int32_t     nodeOffset;
697     int32_t     depth;
698     const char *nodeName;
700     depth = RM_DTB_UTIL_STARTING_DEPTH;
701     nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;       
703     /* Find node offset for provided resource name */
704     while ((nodeOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && 
705            (depth >= RM_DTB_UTIL_STARTING_DEPTH)) {
706         nodeOffset = fdt_next_node(policyDtb, nodeOffset, &depth);
707         nodeName = fdt_get_name(policyDtb, nodeOffset, NULL);
709         if (strcmp(nodeName, resourceName) == 0)
710         {
711             break;
712         }
713     }
714     return(nodeOffset);
717 int32_t Rm_policyValidatePolicyResourceNames(void *policyDtb, void *allocatorList)
719     Rm_Allocator *allocator = (Rm_Allocator *)allocatorList;
720     int32_t              nodeOffset;
721     int32_t              depth;
722     const char          *nodeName;
724     depth = RM_DTB_UTIL_STARTING_DEPTH;
725     nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;       
727     /* Parse DTB, verifying each resource's assignment permissions.
728      * Permissions must have correct syntax and contain valid instance names
729      * according validInstList */
730     while ((nodeOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && 
731            (depth >= RM_DTB_UTIL_STARTING_DEPTH)) {
732         nodeOffset = fdt_next_node(policyDtb, nodeOffset, &depth);
733         nodeName = fdt_get_name(policyDtb, nodeOffset, NULL);
734         if (fdt_first_property_offset(policyDtb, nodeOffset) > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
735             if (Rm_allocatorFind(allocator, (char *)nodeName) == NULL) {
736                 /* No allocator tied to resource name */
737                 return(RM_INIT_ERROR_POLICY_UNKNOWN_RESOURCE);
738             }        
739         }
740     }
741     return(RM_INIT_OK);
744 /* TODO: ADD ABILITY TO RETURN THE SYNTAX ERROR LOCATION */
745 int32_t Rm_policyValidatePolicy(void *policyDtb, Rm_PolicyValidInstTree *validInstTree)
747     int32_t              nodeOffset;
748     int32_t              propertyOffset;
749     int32_t              depth;
750     const char          *propertyName;
751         int32_t              propertyLen;
752         const void          *propertyData;
753     Rm_PolicyPropType    propertyType;
754     Rm_PolicyAssignment *assignmentList;
755     int32_t              result;
757     depth = RM_DTB_UTIL_STARTING_DEPTH;
758     nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;       
760     /* Parse DTB, verifying each resource's assignment permissions.
761      * Permissions must have correct syntax and contain valid instance names
762      * according validInstList */
763     while ((nodeOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && 
764            (depth >= RM_DTB_UTIL_STARTING_DEPTH)) {
765         nodeOffset = fdt_next_node(policyDtb, nodeOffset, &depth);
766         propertyOffset = fdt_first_property_offset(policyDtb, nodeOffset);                
767         while (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
768             propertyData = fdt_getprop_by_offset(policyDtb, propertyOffset, &propertyName, &propertyLen);
769             propertyType = Rm_policyGetPropertyType(propertyName);
770             if (propertyType == Rm_policyPropType_ASSIGNMENTS) {
771                 assignmentList = Rm_policyExtractAssignments(propertyData, propertyLen);
772                 
773                 if ((result = Rm_policyValidateAssignmentPermissions(validInstTree, assignmentList)) != RM_INIT_OK) {
774                     Rm_policyFreeAssignments(assignmentList);
775                     return(result);
776                 }
777                 Rm_policyFreeAssignments(assignmentList);
778             }
779             else if (propertyType == Rm_policyPropType_UNKNOWN) {
780                 return(RM_INIT_ERROR_POLICY_UNKNOWN_RESOURCE_PROPERTY);
781             }
782             propertyOffset = fdt_next_property_offset(policyDtb, propertyOffset);
783         }
784     }
785     return(RM_INIT_OK);
788 Rm_PolicyValidInstTree *Rm_policyCreateValidInstTree(void *policyDtb, int32_t *result)
790     int32_t             validInstOffset;
791     const char         *validInstName;
792         int32_t             validInstLen;
793         const void         *validInstData;
794     Rm_PolicyPropType   propertyType;
795     Rm_PolicyValidInst *validInstList;
796     Rm_PolicyValidInstTree   *rootEntry = NULL;
797     Rm_PolicyValidInstNode   *newNode;  
798     char                linuxName[] = RM_ALLOCATED_TO_LINUX;
800     /* Valid instance list must be first and only property in the root node of
801      * the policyDtb */
802     validInstOffset = fdt_first_property_offset(policyDtb, RM_DTB_UTIL_STARTING_NODE_OFFSET);
803     if (validInstOffset < -FDT_ERR_NOTFOUND) {
804         *result = validInstOffset;
805         return (NULL);
806     } 
807     else if (validInstOffset == -FDT_ERR_NOTFOUND) {
808         *result = RM_INIT_ERROR_POLICY_NO_VALID_INSTANCES_DEFINED;
809         return (NULL);
810     }
811     validInstData = fdt_getprop_by_offset(policyDtb, validInstOffset, &validInstName, &validInstLen);
812     propertyType = Rm_policyGetPropertyType(validInstName);
813     if (propertyType != Rm_policyPropType_VALID_INSTANCES) {
814         *result = RM_INIT_ERROR_POLICY_NO_VALID_INSTANCES_DEFINED;
815         return (NULL);
816     }
817     validInstList = Rm_policyExtractValidInstances(validInstData, validInstLen);
819     /* Create the tree */
820     rootEntry = Rm_osalMalloc(sizeof(Rm_PolicyValidInstTree));
821     RB_INIT(rootEntry);
823     while (validInstList) {
824         newNode = Rm_policyNewValidInstNode(validInstList->instName);
825         RB_INSERT(_Rm_PolicyValidInstTree, rootEntry, newNode);
826         
827         validInstList = validInstList->nextValidInst;
828     }
830     /* Add the Linux kernel node */
831     newNode = Rm_policyNewValidInstNode(linuxName);
832     RB_INSERT(_Rm_PolicyValidInstTree, rootEntry, newNode);    
834     *result = RM_INIT_OK;
835     return (rootEntry);
838 void Rm_policyFreeValidInstTree(Rm_PolicyValidInstTree *validInstTree)
840     Rm_PolicyValidInstNode *node;
841     
842     RB_FOREACH(node, _Rm_PolicyValidInstTree, validInstTree) {               
843         RB_REMOVE(_Rm_PolicyValidInstTree, validInstTree, node);
844         Rm_policyFreeValidInstNode(node);
845     }        
846     Rm_osalFree((void *)validInstTree, sizeof(Rm_PolicyValidInstTree));