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));
79 strcpy(newNode->name, instName);
80 newNode->allocRefCount = 0;
81 newNode->deletePending = FALSE;
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));
100 }
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)
111 {
112 Rm_PolicyPermission *permission = permissionsList;
113 bool instNameMatch = FALSE;
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 }
131 return(RM_INIT_OK);
132 }
134 Rm_PolicyPermission *Rm_policyParseSubPermission(char *permStrStart, char *permStrEnd,
135 int32_t *result)
136 {
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 }
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);
421 }
423 void Rm_policyFreeAssignmentPermissions(Rm_PolicyPermission *permissionList)
424 {
425 Rm_PolicyPermission *nextPerm;
427 while (permissionList) {
428 nextPerm = permissionList->nextPermission;
429 Rm_osalFree((void *)permissionList, sizeof(Rm_PolicyPermission));
430 permissionList = nextPerm;
431 }
432 }
434 Rm_PolicyPermission *Rm_policyGetAssignmentPermissions(Rm_PolicyAssignment *assignment,
435 int32_t *result)
436 {
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;
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 }
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);
483 }
485 int32_t Rm_policyValidateAssignmentPermissions(Rm_ValidInstTree *root,
486 Rm_PolicyAssignment *assignmentList)
487 {
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 }
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);
509 }
511 void Rm_policyIncrementValidInstAllocationCount(void *validInstNameNode)
512 {
513 Rm_ValidInstNode *node = (Rm_ValidInstNode *)validInstNameNode;
515 node->allocRefCount++;
516 }
518 void Rm_policyDecrementValidInstAllocationCount(void *validInstNameNode)
519 {
520 Rm_ValidInstNode *node = (Rm_ValidInstNode *)validInstNameNode;
522 node->allocRefCount--;
523 }
525 void *Rm_policyGetValidInstNode(void *validInstTree, char *instName)
526 {
527 Rm_ValidInstTree *root = (Rm_ValidInstTree *)validInstTree;
528 Rm_ValidInstNode findNode;
530 memset((void *)&findNode, 0, sizeof(Rm_ValidInstNode));
531 strcpy(findNode.name, instName);
533 return (RB_FIND(_Rm_ValidInstTree, root, &findNode));
534 }
536 char *Rm_policyGetValidInstNodeName(void *validInstNode)
537 {
538 Rm_ValidInstNode *node = validInstNode;
540 return (node->name);
541 }
543 bool Rm_policyCheckPrivilege(Rm_PolicyCheckCfg *privilegeCfg, int32_t *result)
544 {
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))) {
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;
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 }
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 }
629 return(TRUE);
630 }
632 uint32_t Rm_policyGetResourceBase(void *policyDtb, void *validInstNode,
633 int32_t resourcePolicy, uint32_t allocType,
634 int32_t *result)
636 {
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 }
698 return(resourceBase);
699 }
701 uint32_t Rm_policyGetResourceAlignment(void *policyDtb, int32_t resourcePolicy)
702 {
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);
723 }
725 int32_t Rm_policyGetResourcePolicy(void *policyDtb, char *resourceName)
726 {
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);
746 }
748 void *Rm_policyGetLinuxInstNode(void * validInstTree)
749 {
750 char linuxName[] = RM_ALLOCATED_TO_LINUX;
752 return (Rm_policyGetValidInstNode(validInstTree, linuxName));
753 }
755 int32_t Rm_policyValidatePolicyResourceNames(Rm_Inst *rmInst, void *policyDtb)
756 {
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);
779 }
781 /* TODO: ADD ABILITY TO RETURN THE SYNTAX ERROR LOCATION */
782 int32_t Rm_policyValidatePolicy(Rm_Inst *rmInst, void *policyDtb)
783 {
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);
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);
819 }
821 void *Rm_policyCreateValidInstTree(void *policyDtb, int32_t *result)
822 {
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);
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);
869 }