8e5c156f8332b01d41425a8f0f04a07b187ecd8b
[keystone-rtos/rm-lld.git] / src / rm_policy.c
1 /**
2  *   @file  rmpolicy.c
3  *
4  *   @brief   
5  *      This is the 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  ************************** Globals ***********************************
66  **********************************************************************/
68 char Rm_policyAllInstances[] = "*";
70 /**********************************************************************
71  ************ Red-Black BBST Tree Valid Instance Functions ************
72  **********************************************************************/
73 Rm_ValidInstNode *Rm_newValidInstNode(char *instName)
74 {
75     Rm_ValidInstNode *newNode = NULL;
77     newNode = Rm_osalMalloc(sizeof(Rm_ValidInstNode));
78     
79     strcpy(newNode->name, instName);
80     newNode->allocRefCount = 0;
81     newNode->deletePending = FALSE;
82     
83     return(newNode);
84 }
86 void Rm_freeValidInstNode(Rm_ValidInstNode *node)
87 {
88     if (node->allocRefCount == 0) {
89         Rm_osalFree((void *)node, sizeof(Rm_ValidInstNode));
90     }
91 }
93 /* Prototype for tree node comparison function
94  * element1 < element2 --> return < 0
95  * element1 = element2 --> return 0
96  * element1 > element2 --> return > 0 */
97 int Rm_ValidInstNodeCompare(Rm_ValidInstNode *element1, Rm_ValidInstNode *element2)
98 {
99     return(strcmp(element1->name, element2->name));
102 /* Generate the red-black tree manipulation functions */
103 RB_GENERATE(_Rm_ValidInstTree, _Rm_ValidInstNode, linkage, Rm_ValidInstNodeCompare);
105 /**********************************************************************
106  ********************** Internal Functions ****************************
107  **********************************************************************/
109 int32_t Rm_policyCheckInstances(Rm_ValidInstTree *root, 
110                                 Rm_PolicyPermission *permissionsList)
112     Rm_PolicyPermission *permission = permissionsList;
113     bool                 instNameMatch = FALSE;
114     
115     while (permission) {
116         if (strcmp(permission->instName, Rm_policyAllInstances) == 0) {
117             instNameMatch = TRUE;
118         }
119         else if (Rm_policyGetValidInstNode(root, permission->instName)) {
120                     instNameMatch = TRUE; 
121         }
123         if (!instNameMatch) {
124             return(RM_INIT_ERROR_POLICY_UNKNOWN_INSTANCE);
125         }
127         permission = permission->nextPermission;
128         instNameMatch = FALSE;
129     }
130     
131     return(RM_INIT_OK);
134 Rm_PolicyPermission *Rm_policyParseSubPermission(char *permStrStart, char *permStrEnd, 
135                                                  int32_t *result)
137     Rm_PolicyPermission *startPerm = NULL;
138     Rm_PolicyPermission *newPerm = NULL;
139     Rm_PolicyPermission *prevPerm = NULL;
140     Rm_PolicyPermission *nextPerm = NULL;
141     char *permStrPtr = NULL;
142     char *subgroupStart = NULL;
143     char *subgroupEnd = NULL;
144     uint32_t permStrLen = (uint32_t)(permStrEnd - permStrStart + 1);
145     char instNameTemp[RM_INSTANCE_NAME_MAX_CHARS];
146     uint32_t instNameIndex;
147     bool foundInstName;
148     bool instNameComplete;
149     bool assignmentLeft;
150     bool assignmentRight;
152     /* Create a local copy of the sub-permission string */
153     permStrPtr = Rm_osalMalloc(permStrLen);
154     strncpy(permStrPtr, permStrStart, permStrLen);
155     /* Make sure the last character in the copied sub-permission string is null */
156     permStrPtr[permStrLen - 1] = '\0';
158     permStrStart = permStrPtr;
159     permStrEnd = permStrPtr + strlen(permStrPtr);
161     /* Find the beginning and end of the sub-permission instance group */
162     subgroupStart = strchr(permStrStart, RM_POLICY_PERM_SUBGROUP_START);
163     subgroupEnd = strchr(permStrStart, RM_POLICY_PERM_SUBGROUP_END);
165     if ((!subgroupStart) || (!subgroupEnd) || (subgroupStart > subgroupEnd) ||
166         ((subgroupStart != strrchr(permStrStart, RM_POLICY_PERM_SUBGROUP_START)) &&
167          (subgroupEnd != strrchr(permStrStart, RM_POLICY_PERM_SUBGROUP_END))))
168     {
169         /* Free the memory associated with the temp string and return an error if:
170          * a) Could not find the instance group start
171          * b) Could not find the instance group end
172          * c) Subgroup start and end are out of order
173          * d) There is more than one instance subgroup specified in the string.  There
174          *    should only be one subgroup per sub-permission string */
175         Rm_osalFree((void *)permStrStart, permStrLen);
176         *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_MORE_THAN_ONE_INSTANCE_GROUP;
177         return(NULL);
178     }
180     /* Create a permission entry for each instance specified in the instance group.
181      * Instances names are separated by one or more spaces. */
182     permStrPtr = subgroupStart + 1;
183     instNameIndex = 0;
184     foundInstName = FALSE;
185     instNameComplete = FALSE;
186     while (permStrPtr <= subgroupEnd) {
187         if ((isspace(*permStrPtr) || (*permStrPtr == RM_POLICY_PERM_SUBGROUP_END))
188             && foundInstName) {
189             /* First space encountered after copying an instance name.  This
190              * terminates the instance name.  All other space characters are
191              * ignored. */
192             instNameTemp[instNameIndex] = '\0';
193             instNameComplete = TRUE; 
194         }
195         else {
196             if (!foundInstName) {
197                 /* First non-whitespace character encountered is the start of an
198                  * instance name */
199                 foundInstName = TRUE;
200             }
202             /* Copy the character into the temporary instance name string */
203             instNameTemp[instNameIndex++] = *permStrPtr;
204         }
206         if (instNameComplete) {
207             newPerm = (Rm_PolicyPermission *) Rm_osalMalloc(sizeof(Rm_PolicyPermission));
208             memset((void *)newPerm, 0, sizeof(Rm_PolicyPermission));
210             strcpy(newPerm->instName, instNameTemp);
211             newPerm->nextPermission = NULL;
213             if (prevPerm == NULL) {
214                 /* Save the first instance so it can be returned */
215                 startPerm = newPerm;
216             }
217             else {
218                 prevPerm->nextPermission = (void *) newPerm;
219             }
220             prevPerm = newPerm;
222             instNameComplete = FALSE;
223             instNameIndex = 0;
224             foundInstName = FALSE;
225         }
227         permStrPtr++;
228     }
230     /* Fill in the permissions for each instance name */
232     /* Look on left of instance group for permission assignments. */
233     permStrPtr = subgroupStart - 1;
234     assignmentLeft = FALSE;
235     while (permStrPtr >= permStrStart)
236     {
237         if (*permStrPtr == RM_POLICY_PERM_ASSIGNMENT) {
238             if (assignmentLeft) {
239                 /* Assignment character has been found more than once.  This is a
240                  * syntax error.  Free the permission list and the temporary string
241                  * and return. */
242                 while (startPerm) {
243                     nextPerm = startPerm->nextPermission;
244                     Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
245                     startPerm = nextPerm;
246                 } 
247                 Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
248                 *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_MORE_THAN_ONE_ASSIGNMENT_CHAR;
249                 return(NULL);
250             }
251             else {
252                 assignmentLeft = TRUE;
253             }
254         }
255         else if (!isspace(*permStrPtr)) {
256             if (assignmentLeft) {
257                 if ((*permStrPtr == RM_POLICY_PERM_INIT_LOWER) || 
258                     (*permStrPtr == RM_POLICY_PERM_INIT_UPPER)) {
259                     newPerm = startPerm;
260                     while (newPerm) {
261                         RM_POLICY_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_INIT_SHIFT, 1);
262                         newPerm = newPerm->nextPermission;
263                     }
264                 }
265                 else if ((*permStrPtr == RM_POLICY_PERM_USE_LOWER) || 
266                          (*permStrPtr == RM_POLICY_PERM_USE_UPPER)) {
267                     newPerm = startPerm;
268                     while (newPerm) {                                           
269                         RM_POLICY_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_USE_SHIFT, 1);
270                         newPerm = newPerm->nextPermission;
271                     }
272                 }
273                 else if ((*permStrPtr == RM_POLICY_PERM_EXCLUSIVE_LOWER) || 
274                          (*permStrPtr == RM_POLICY_PERM_EXCLUSIVE_UPPER)) {
275                     newPerm = startPerm;
276                     while (newPerm) {                       
277                         RM_POLICY_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_EXCLUSIVE_SHIFT, 1);
278                         newPerm = newPerm->nextPermission;
279                     }
280                 }
281                 else if ((*permStrPtr == RM_POLICY_PERM_SHARED_LINUX_LOWER) || 
282                          (*permStrPtr == RM_POLICY_PERM_SHARED_LINUX_UPPER)) {
283                     newPerm = startPerm;
284                     while (newPerm) {                       
285                         RM_POLICY_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_SHARED_LINUX_SHIFT, 1);
286                         newPerm = newPerm->nextPermission;
287                     }
288                 }                
289                 else {
290                     /* Invalid permission character.  This is a
291                      * syntax error.  Free the permission list and the temporary string
292                      * and return. */
293                     while (startPerm) {
294                         nextPerm = startPerm->nextPermission;
295                         Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
296                         startPerm = nextPerm;
297                     }  
298                     Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
299                     *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_INVALID_PERM_CHAR;
300                     return(NULL);
301                 }
302             }
303             else {
304                 /* Character found without the assignment character being found.  This is a
305                  * syntax error.  Free the permission list and the temporary string
306                  * and return. */
307                 while (startPerm) {
308                     nextPerm = startPerm->nextPermission;
309                     Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
310                     startPerm = nextPerm;
311                 }  
312                 Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
313                 *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_PERM_CHAR_WITHOUT_ASSIGN_CHAR;
314                 return(NULL);
315             }
316         }
317         permStrPtr--;
318     }
320     /* Look on right of instance group for permission assignments. */
321     permStrPtr = subgroupEnd + 1;
322     assignmentRight = FALSE;
323     while (permStrPtr < permStrEnd) {
324         if (assignmentLeft && (!isspace(*permStrPtr))) {
325             /* There should be nothing but spaces on right if assignment was already found on left */
326             while (startPerm) {
327                 nextPerm = startPerm->nextPermission;
328                 Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
329                 startPerm = nextPerm;
330             } 
331             Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
332             *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_INVALID_CHAR_ON_RIGHT_WITH_ASSINMENT_ON_LEFT;
333             return(NULL);              
334         }
335         
336         if (*permStrPtr == RM_POLICY_PERM_ASSIGNMENT) {
337             if (assignmentRight) {
338                 /* Assignment character has been found more than once.  This is a
339                  * syntax error.  Free the permission list and the temporary string
340                  * and return. */
341                 while (startPerm) {
342                     nextPerm = startPerm->nextPermission;
343                     Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
344                     startPerm = nextPerm;
345                 } 
346                 Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
347                 *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_MORE_THAN_ONE_ASSIGNMENT_CHAR;
348                 return(NULL);                
349             }
350             else {
351                 assignmentRight = TRUE;
352             }
353         }
354         else if (!isspace(*permStrPtr)) {
355             if (assignmentRight) {
356                 if ((*permStrPtr == RM_POLICY_PERM_INIT_LOWER) || 
357                     (*permStrPtr == RM_POLICY_PERM_INIT_UPPER)) {
358                     newPerm = startPerm;
359                     while (newPerm) {
360                         RM_POLICY_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_INIT_SHIFT, 1);
361                         newPerm = newPerm->nextPermission;
362                     }
363                 }
364                 else if ((*permStrPtr == RM_POLICY_PERM_USE_LOWER) || 
365                          (*permStrPtr == RM_POLICY_PERM_USE_UPPER)) {
366                     newPerm = startPerm;
367                     while (newPerm) {                                           
368                         RM_POLICY_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_USE_SHIFT, 1);
369                         newPerm = newPerm->nextPermission;
370                     }
371                 }
372                 else if ((*permStrPtr == RM_POLICY_PERM_EXCLUSIVE_LOWER) || 
373                          (*permStrPtr == RM_POLICY_PERM_EXCLUSIVE_UPPER)) {
374                     newPerm = startPerm;
375                     while (newPerm) {                       
376                         RM_POLICY_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_EXCLUSIVE_SHIFT, 1);
377                         newPerm = newPerm->nextPermission;
378                     }
379                 }
380                 else if ((*permStrPtr == RM_POLICY_PERM_SHARED_LINUX_LOWER) || 
381                          (*permStrPtr == RM_POLICY_PERM_SHARED_LINUX_UPPER)) {
382                     newPerm = startPerm;
383                     while (newPerm) {                       
384                         RM_POLICY_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_SHARED_LINUX_SHIFT, 1);
385                         newPerm = newPerm->nextPermission;
386                     }
387                 }                  
388                 else {
389                     /* Invalid permission character.  This is a
390                      * syntax error.  Free the permission list and the temporary string
391                      * and return. */
392                     while (startPerm) {
393                         nextPerm = startPerm->nextPermission;
394                         Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
395                         startPerm = nextPerm;
396                     }    
397                     Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
398                     *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_INVALID_PERM_CHAR;
399                     return(NULL);                    
400                 }
401             }
402             else {
403                 /* Character found without the assignment character being found.  This is a
404                  * syntax error.  Free the permission list and the temporary string
405                  * and return. */
406                 while (startPerm) {
407                     nextPerm = startPerm->nextPermission;
408                     Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
409                     startPerm = nextPerm;
410                 }    
411                 Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
412                 *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_MORE_THAN_ONE_ASSIGNMENT_CHAR;
413                 return(NULL);                
414             }
415         }
416         permStrPtr++;
417     }
419     Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
420     return (startPerm);
423 void Rm_policyFreeAssignmentPermissions(Rm_PolicyPermission *permissionList)
425     Rm_PolicyPermission *nextPerm;
426     
427     while (permissionList) {
428         nextPerm = permissionList->nextPermission;
429         Rm_osalFree((void *)permissionList, sizeof(Rm_PolicyPermission));
430         permissionList = nextPerm;
431     }
434 Rm_PolicyPermission *Rm_policyGetAssignmentPermissions(Rm_PolicyAssignment *assignment, 
435                                                        int32_t *result)
437     Rm_PolicyPermission *startPerm = NULL;
438     Rm_PolicyPermission *newPerm = NULL;
439     Rm_PolicyPermission *prevPerm = NULL;
440     char *permStrStart = assignment->permissionsList;
441     char *permStrEnd;
442     uint32_t permStrLen = strlen(assignment->permissionsList) + 1;
443     uint32_t i = 0;
444     
445     while(i < permStrLen) {
446         /* Find the first sub-permission specification and parse it.  A sub-permission
447          * can be terminated by the termination character or the end of the string. */
448         if (!(permStrEnd = strchr(permStrStart, RM_POLICY_PERM_TERMINATOR))) {           
449             /* Sub-permission termination character not found.  The permission string
450              * end is the end of the entire permission string */
451             permStrEnd = permStrStart + strlen(permStrStart);
452         }
454         newPerm = Rm_policyParseSubPermission(permStrStart, permStrEnd, result);
456         if (*result != RM_SERVICE_PROCESSING) {
457             /* Delete the permission list that's been created thus far, return
458              * the error and NULL for the permission list */
459             Rm_policyFreeAssignmentPermissions(startPerm);
460             return(NULL);
461         }
463         if (prevPerm == NULL) {
464             startPerm = newPerm;
465         }
466         else {
467             prevPerm->nextPermission = newPerm;
468         }
470         /* Set prevPerm to the last sub-permission returned by the sub-permission parser */
471         prevPerm = newPerm;
472         while(prevPerm->nextPermission != NULL) {
473             prevPerm = prevPerm->nextPermission;
474         }
475         
476         /* Update the number of characters parsed from the permission list and point to 
477          * the start of the next sub-permission */
478         i += ((uint32_t)(permStrEnd - permStrStart + 1));
479         permStrStart = permStrEnd + 1;
480     }
482     return(startPerm);
485 int32_t Rm_policyValidateAssignmentPermissions(Rm_ValidInstTree *root,
486                                                Rm_PolicyAssignment *assignmentList)
488     Rm_PolicyAssignment *assignment = assignmentList;
489     Rm_PolicyPermission *permissionList;
490     int32_t result;
492     while (assignment) {
493         /* Make sure assignment's permissions parse okay */
494         permissionList = Rm_policyGetAssignmentPermissions(assignment, &result);
495         if (result != RM_INIT_OK) {
496             return(result);
497         }                        
498         
499         if (result = Rm_policyCheckInstances(root, permissionList) != RM_INIT_OK) {
500             Rm_policyFreeAssignmentPermissions(permissionList);
501             return(result);
502         }
504         Rm_policyFreeAssignmentPermissions(permissionList);
505         assignment = assignment->nextAssignment;
506     }
508     return (RM_INIT_OK);
511 void Rm_policyIncrementValidInstAllocationCount(void *validInstNameNode)
513     Rm_ValidInstNode *node = (Rm_ValidInstNode *)validInstNameNode;
515     node->allocRefCount++;
518 void Rm_policyDecrementValidInstAllocationCount(void *validInstNameNode)
520     Rm_ValidInstNode *node = (Rm_ValidInstNode *)validInstNameNode;
522     node->allocRefCount--;
525 void *Rm_policyGetValidInstNode(void *validInstTree, char *instName)
527     Rm_ValidInstTree *root = (Rm_ValidInstTree *)validInstTree;
528     Rm_ValidInstNode  findNode;
530     memset((void *)&findNode, 0, sizeof(Rm_ValidInstNode));
531     strcpy(findNode.name, instName);
532     
533     return (RB_FIND(_Rm_ValidInstTree, root, &findNode));
536 char *Rm_policyGetValidInstNodeName(void *validInstNode)
538     Rm_ValidInstNode *node = validInstNode;
540     return (node->name);
543 bool Rm_policyCheckPrivilege(Rm_PolicyCheckCfg *privilegeCfg, int32_t *result)
545     Rm_ValidInstNode    *instNode = (Rm_ValidInstNode *)privilegeCfg->validInstNode;
546     int32_t              propertyOffset;
547     const char          *propertyName;
548         int32_t              propertyLen;
549         const void          *propertyData;
550     Rm_PolicyAssignment *assignment = NULL;
551     Rm_PolicyAssignment *assignmentStart = NULL;
552     Rm_PolicyPermission *permission = NULL;
553     Rm_PolicyPermission *permissionStart = NULL;
554     uint32_t             assignmentEnd;
555     uint32_t             resourceEnd = privilegeCfg->resourceBase + privilegeCfg->resourceLength - 1;
556     bool                 foundInstance;
558     /* Get the resource's assignments */
559     propertyOffset = fdt_first_property_offset(privilegeCfg->policyDtb, privilegeCfg->resourcePolicy);
560     if (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
561         while (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
562             propertyData = fdt_getprop_by_offset(privilegeCfg->policyDtb, propertyOffset, &propertyName, &propertyLen);
563             if (Rm_policyGetPropertyType(propertyName) == Rm_policyPropType_ASSIGNMENTS) {
564                 assignment = assignmentStart = Rm_policyExtractAssignments(propertyData, propertyLen);
565                 break;
566             }
567             propertyOffset = fdt_next_property_offset(privilegeCfg->policyDtb, propertyOffset);
568         }
569     }
571     if (assignment) {
572         while (assignment) {
573             assignmentEnd = assignment->resourceBase + assignment->resourceLength - 1;
574             foundInstance = FALSE;
575             if (((privilegeCfg->resourceBase >= assignment->resourceBase) &&
576                  (privilegeCfg->resourceBase <= assignmentEnd)) ||
577                 ((privilegeCfg->resourceBase < assignment->resourceBase) &&
578                  (resourceEnd > assignmentEnd)) ||
579                 ((resourceEnd >= assignment->resourceBase) &&
580                  (resourceEnd <= assignmentEnd))) {
581                  
582                 permission = permissionStart = Rm_policyGetAssignmentPermissions(assignment, result);
583                 while (permission) {
584                     if ((strcmp(permission->instName, instNode->name) == 0) ||
585                         (strcmp(permission->instName, Rm_policyAllInstances) == 0)) {
586                         foundInstance = TRUE;
587                         
588                         /* Check instance's permissions */
589                         if (privilegeCfg->type == Rm_policyCheck_INIT) {
590                             if (!RM_POLICY_GET_PERM(permission->permissionBits, RM_POLICY_PERM_INIT_SHIFT)) {
591                                 Rm_policyFreeAssignmentPermissions(permissionStart);
592                                 Rm_policyFreeAssignments(assignmentStart);
593                                 return(FALSE);
594                             }
595                         }
596                         else if (privilegeCfg->type == Rm_policyCheck_USE) {
597                             if (!RM_POLICY_GET_PERM(permission->permissionBits, RM_POLICY_PERM_USE_SHIFT)) {
598                                 Rm_policyFreeAssignmentPermissions(permissionStart);
599                                 Rm_policyFreeAssignments(assignmentStart);
600                                 return(FALSE);
601                             }   
602                         }
603                         else if (privilegeCfg->type == Rm_policyCheck_EXCLUSIVE) {
604                             if (!RM_POLICY_GET_PERM(permission->permissionBits, RM_POLICY_PERM_EXCLUSIVE_SHIFT)) {
605                                 Rm_policyFreeAssignmentPermissions(permissionStart);
606                                 Rm_policyFreeAssignments(assignmentStart);
607                                 return(FALSE);
608                             }   
609                         }
610                         break;
611                     }
612                     permission = permission->nextPermission;
613                 }
614                 
615                 Rm_policyFreeAssignmentPermissions(permissionStart);
616                 if (!foundInstance) {
617                     Rm_policyFreeAssignments(assignmentStart);
618                     return(FALSE);
619                 }
620             }
621             assignment = assignment->nextAssignment;
622         }
623         Rm_policyFreeAssignments(assignmentStart);
624     }
625     else {
626         return(FALSE);
627     }
628     
629     return(TRUE);
632 uint32_t Rm_policyGetResourceBase(void *policyDtb, void *validInstNode, 
633                                   int32_t resourcePolicy, uint32_t allocType, 
634                                   int32_t *result)
637     Rm_ValidInstNode    *instNode = (Rm_ValidInstNode *)validInstNode;
638     int32_t              propertyOffset;
639     const char          *propertyName;
640         int32_t              propertyLen;
641         const void          *propertyData;
642     Rm_PolicyAssignment *assignment = NULL;
643     Rm_PolicyAssignment *assignmentStart = NULL;
644     Rm_PolicyPermission *permission = NULL;
645     Rm_PolicyPermission *permissionStart = NULL;
646     uint32_t             resourceBase = 0;
648     propertyOffset = fdt_first_property_offset(policyDtb, resourcePolicy);
649     if (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
650         while (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
651             propertyData = fdt_getprop_by_offset(policyDtb, propertyOffset, &propertyName, &propertyLen);
652             if (Rm_policyGetPropertyType(propertyName) == Rm_policyPropType_ASSIGNMENTS) {
653                 assignment = assignmentStart = Rm_policyExtractAssignments(propertyData, propertyLen);
654                 break;
655             }
656             propertyOffset = fdt_next_property_offset(policyDtb, propertyOffset);
657         }
658     }
660     /* Search policy permissions for a valid resource base */
661     if (assignment) {
662         while (assignment) {
663             permission = permissionStart = Rm_policyGetAssignmentPermissions(assignment, result);
664             while (permission) {
665                 if ((strcmp(permission->instName, instNode->name) == 0) ||
666                     (strcmp(permission->instName, Rm_policyAllInstances) == 0)) {
667                     /* Check instance's permissions */
668                     if (RM_POLICY_GET_PERM(allocType, RM_POLICY_PERM_INIT_SHIFT)) {
669                         if (RM_POLICY_GET_PERM(permission->permissionBits, RM_POLICY_PERM_INIT_SHIFT)) {
670                             resourceBase = assignment->resourceBase;
671                             break;
672                         }
673                     }
674                     else if (RM_POLICY_GET_PERM(allocType, RM_POLICY_PERM_USE_SHIFT)) {
675                         if (RM_POLICY_GET_PERM(permission->permissionBits, RM_POLICY_PERM_USE_SHIFT)) {
676                             resourceBase = assignment->resourceBase;
677                             break;
678                         }   
679                     }
680                 }
681                 permission = permission->nextPermission;
682             }
683             Rm_policyFreeAssignmentPermissions(permissionStart);
685             if (resourceBase) {
686                 break;
687             }
688             else {
689                 assignment = assignment->nextAssignment;
690             }
691         }
692         Rm_policyFreeAssignments(assignmentStart);
693     }
694     else {
695         *result = RM_SERVICE_DENIED_NO_RANGE_ASSIGNMENTS_FOR_POLICY;
696     }
697     
698     return(resourceBase);
701 uint32_t Rm_policyGetResourceAlignment(void *policyDtb, int32_t resourcePolicy)
703     int32_t            propertyOffset;
704     const char        *propertyName;
705         int32_t            propertyLen;
706         const void        *propertyData;
707     Rm_ResourceValue  *alignmentList;
708     uint32_t           resourceAlignment = 0;
710     propertyOffset = fdt_first_property_offset(policyDtb, resourcePolicy);
711     if (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
712         while (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
713             propertyData = fdt_getprop_by_offset(policyDtb, propertyOffset, &propertyName, &propertyLen);
714             if (Rm_policyGetPropertyType(propertyName) == Rm_policyPropType_ALLOCATION_ALIGNMENTS) {
715                 alignmentList = Rm_policyExtractResourceAlignments(propertyData, propertyLen);
716                 resourceAlignment = alignmentList->value;                
717                 Rm_policyFreeResourceAlignments(alignmentList);
718             }
719             propertyOffset = fdt_next_property_offset(policyDtb, propertyOffset);
720         }
721     }
722     return(resourceAlignment);
725 int32_t Rm_policyGetResourcePolicy(void *policyDtb, char *resourceName)
727     int32_t     nodeOffset;
728     int32_t     depth;
729     const char *nodeName;
731     depth = RM_DTB_UTIL_STARTING_DEPTH;
732     nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;       
734     /* Find node offset for provided resource name */
735     while ((nodeOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && 
736            (depth >= RM_DTB_UTIL_STARTING_DEPTH)) {
737         nodeOffset = fdt_next_node(policyDtb, nodeOffset, &depth);
738         nodeName = fdt_get_name(policyDtb, nodeOffset, NULL);
740         if (strcmp(nodeName, resourceName) == 0)
741         {
742             break;
743         }
744     }
745     return(nodeOffset);
748 void *Rm_policyGetLinuxInstNode(void * validInstTree)
750     char linuxName[] = RM_ALLOCATED_TO_LINUX;
752     return (Rm_policyGetValidInstNode(validInstTree, linuxName));
755 int32_t Rm_policyValidatePolicyResourceNames(Rm_Inst *rmInst, void *policyDtb)
757     int32_t              nodeOffset;
758     int32_t              depth;
759     const char          *nodeName;
761     depth = RM_DTB_UTIL_STARTING_DEPTH;
762     nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;       
764     /* Parse DTB, verifying each resource's assignment permissions.
765      * Permissions must have correct syntax and contain valid instance names
766      * according validInstList */
767     while ((nodeOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && 
768            (depth >= RM_DTB_UTIL_STARTING_DEPTH)) {
769         nodeOffset = fdt_next_node(policyDtb, nodeOffset, &depth);
770         nodeName = fdt_get_name(policyDtb, nodeOffset, NULL);
771         if (fdt_first_property_offset(policyDtb, nodeOffset) > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
772             if (Rm_allocatorFind(rmInst, (char *)nodeName) == NULL) {
773                 /* No allocator tied to resource name */
774                 return(RM_INIT_ERROR_POLICY_UNKNOWN_RESOURCE);
775             }        
776         }
777     }
778     return(RM_INIT_OK);
781 /* TODO: ADD ABILITY TO RETURN THE SYNTAX ERROR LOCATION */
782 int32_t Rm_policyValidatePolicy(Rm_Inst *rmInst, void *policyDtb)
784     int32_t              nodeOffset;
785     int32_t              propertyOffset;
786     int32_t              depth;
787     const char          *propertyName;
788         int32_t              propertyLen;
789         const void          *propertyData;
790     Rm_PolicyAssignment *assignmentList;
791     int32_t              result;
793     depth = RM_DTB_UTIL_STARTING_DEPTH;
794     nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;       
796     /* Parse DTB, verifying each resource's assignment permissions.
797      * Permissions must have correct syntax and contain valid instance names
798      * according validInstList */
799     while ((nodeOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && 
800            (depth >= RM_DTB_UTIL_STARTING_DEPTH)) {
801         nodeOffset = fdt_next_node(policyDtb, nodeOffset, &depth);
802         propertyOffset = fdt_first_property_offset(policyDtb, nodeOffset);                
803         while (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
804             propertyData = fdt_getprop_by_offset(policyDtb, propertyOffset, &propertyName, &propertyLen);
805             if (Rm_policyGetPropertyType(propertyName) == Rm_policyPropType_ASSIGNMENTS) {
806                 assignmentList = Rm_policyExtractAssignments(propertyData, propertyLen);
807                 
808                 if ((result = Rm_policyValidateAssignmentPermissions((Rm_ValidInstTree *) rmInst->validInstances, 
809                                                                      assignmentList)) != RM_INIT_OK) {
810                     Rm_policyFreeAssignments(assignmentList);
811                     return(result);
812                 }
813                 Rm_policyFreeAssignments(assignmentList);
814             }
815             propertyOffset = fdt_next_property_offset(policyDtb, propertyOffset);
816         }
817     }
818     return(RM_INIT_OK);
821 void *Rm_policyCreateValidInstTree(void *policyDtb, int32_t *result)
823     int32_t             validInstOffset;
824     const char         *validInstName;
825         int32_t             validInstLen;
826         const void         *validInstData;
827     Rm_PolicyPropType   propertyType;
828     Rm_PolicyValidInst *validInstList;
829     Rm_ValidInstTree   *rootEntry = NULL;
830     Rm_ValidInstNode   *newNode;  
831     char                linuxName[] = RM_ALLOCATED_TO_LINUX;
833     /* Valid instance list must be first and only property in the root node of
834      * the policyDtb */
835     validInstOffset = fdt_first_property_offset(policyDtb, RM_DTB_UTIL_STARTING_NODE_OFFSET);
836     if (validInstOffset < -FDT_ERR_NOTFOUND) {
837         *result = validInstOffset;
838         return (NULL);
839     } 
840     else if (validInstOffset == -FDT_ERR_NOTFOUND) {
841         *result = RM_INIT_ERROR_POLICY_NO_VALID_INSTANCES_DEFINED;
842         return (NULL);
843     }
844     validInstData = fdt_getprop_by_offset(policyDtb, validInstOffset, &validInstName, &validInstLen);
845     propertyType = Rm_policyGetPropertyType(validInstName);
846     if (propertyType != Rm_policyPropType_VALID_INSTANCES) {
847         *result = RM_INIT_ERROR_POLICY_NO_VALID_INSTANCES_DEFINED;
848         return (NULL);
849     }
850     validInstList = Rm_policyExtractValidInstances(validInstData, validInstLen);
852     /* Create the tree */
853     rootEntry = Rm_osalMalloc(sizeof(Rm_ValidInstTree));
854     RB_INIT(rootEntry);
856     while (validInstList) {
857         newNode = Rm_newValidInstNode(validInstList->instName);
858         RB_INSERT(_Rm_ValidInstTree, rootEntry, newNode);
859         
860         validInstList = validInstList->nextValidInst;
861     }
863     /* Add the Linux kernel node */
864     newNode = Rm_newValidInstNode(linuxName);
865     RB_INSERT(_Rm_ValidInstTree, rootEntry, newNode);    
867     *result = RM_INIT_OK;
868     return ((void *)rootEntry);