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