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