1 /**
2 * @file rm_policy.c
3 *
4 * @brief
5 * Resource Manager Policy source.
6 *
7 * \par
8 * ============================================================================
9 * @n (C) Copyright 2012-2013, Texas Instruments, Inc.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 *
15 * Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 *
18 * Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the
21 * distribution.
22 *
23 * Neither the name of Texas Instruments Incorporated nor the names of
24 * its contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 *
39 * \par
40 */
42 /* Standard includes */
43 #include <ctype.h>
45 /* RM external API includes */
46 #include <ti/drv/rm/rm.h>
48 /* RM internal API includes */
49 #include <ti/drv/rm/include/rm_loc.h>
50 #include <ti/drv/rm/include/rm_policyloc.h>
51 #include <ti/drv/rm/include/rm_dtb_utilloc.h>
53 /* RM LIBFDT includes */
54 #include <ti/drv/rm/util/libfdt/libfdt.h>
56 /* Tree algorithm includes */
57 #include <ti/drv/rm/util/tree.h>
59 /* RM OSAL layer */
60 #include <rm_osal.h>
62 /**********************************************************************
63 *********************** Policy Globals *******************************
64 **********************************************************************/
66 const char Rm_policyAllInstances[] = "*";
68 /**********************************************************************
69 ******************** Local Policy Functions **************************
70 **********************************************************************/
72 int32_t policyCheckInstances(Rm_PolicyValidInstTree *validInstTree,
73 Rm_PolicyPermission *permissionsList)
74 {
75 while (permissionsList) {
76 if (strcmp(permissionsList->instName, Rm_policyAllInstances) &&
77 (!rmPolicyGetValidInstNode(validInstTree, permissionsList->instName))) {
78 return(RM_INIT_ERROR_POLICY_UNKNOWN_INSTANCE);
79 }
80 permissionsList = permissionsList->nextPermission;
81 }
82 return(RM_INIT_OK);
83 }
85 Rm_PolicyPermission *policyParseSubPermission(char *permStrStart, char *permStrEnd,
86 int32_t *result)
87 {
88 Rm_PolicyPermission *startPerm = NULL;
89 Rm_PolicyPermission *newPerm = NULL;
90 Rm_PolicyPermission *prevPerm = NULL;
91 Rm_PolicyPermission *nextPerm = NULL;
92 char *permStrPtr = NULL;
93 char *subgroupStart = NULL;
94 char *subgroupEnd = NULL;
95 uint32_t permStrLen = (uint32_t)(permStrEnd - permStrStart + 1);
96 char instNameTemp[RM_NAME_MAX_CHARS];
97 uint32_t instNameIndex;
98 bool foundInstName;
99 bool instNameComplete;
100 bool assignmentLeft;
101 bool assignmentRight;
103 /* Create a local copy of the sub-permission string */
104 permStrPtr = Rm_osalMalloc(permStrLen);
105 strncpy(permStrPtr, permStrStart, permStrLen);
106 /* Make sure the last character in the copied sub-permission string is null */
107 permStrPtr[permStrLen - 1] = '\0';
109 permStrStart = permStrPtr;
110 permStrEnd = permStrPtr + strlen(permStrPtr);
112 /* Find the beginning and end of the sub-permission instance group */
113 subgroupStart = strchr(permStrStart, RM_POLICY_PERM_SUBGROUP_START);
114 subgroupEnd = strchr(permStrStart, RM_POLICY_PERM_SUBGROUP_END);
116 if ((!subgroupStart) || (!subgroupEnd) || (subgroupStart > subgroupEnd) ||
117 ((subgroupStart != strrchr(permStrStart, RM_POLICY_PERM_SUBGROUP_START)) &&
118 (subgroupEnd != strrchr(permStrStart, RM_POLICY_PERM_SUBGROUP_END)))) {
119 /* Free the memory associated with the temp string and return an error if:
120 * a) Could not find the instance group start
121 * b) Could not find the instance group end
122 * c) Subgroup start and end are out of order
123 * d) There is more than one instance subgroup specified in the string. There
124 * should only be one subgroup per sub-permission string */
125 Rm_osalFree((void *)permStrStart, permStrLen);
126 *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_MORE_THAN_ONE_INSTANCE_GROUP;
127 return(NULL);
128 }
130 /* Create a permission entry for each instance specified in the instance group.
131 * Instances names are separated by one or more spaces. */
132 permStrPtr = subgroupStart + 1;
133 instNameIndex = 0;
134 foundInstName = FALSE;
135 instNameComplete = FALSE;
136 while (permStrPtr <= subgroupEnd) {
137 if ((isspace(*permStrPtr) || (*permStrPtr == RM_POLICY_PERM_SUBGROUP_END))
138 && foundInstName) {
139 /* First space encountered after copying an instance name. This
140 * terminates the instance name. All other space characters are
141 * ignored. */
142 instNameTemp[instNameIndex] = '\0';
143 instNameComplete = TRUE;
144 }
145 else {
146 if (!foundInstName) {
147 /* First non-whitespace character encountered is the start of an
148 * instance name */
149 foundInstName = TRUE;
150 }
152 /* Copy the character into the temporary instance name string */
153 instNameTemp[instNameIndex++] = *permStrPtr;
154 }
156 if (instNameComplete) {
157 newPerm = (Rm_PolicyPermission *) Rm_osalMalloc(sizeof(Rm_PolicyPermission));
158 memset((void *)newPerm, 0, sizeof(Rm_PolicyPermission));
160 strncpy(newPerm->instName, instNameTemp, RM_NAME_MAX_CHARS);
161 newPerm->nextPermission = NULL;
163 if (prevPerm == NULL) {
164 /* Save the first instance so it can be returned */
165 startPerm = newPerm;
166 }
167 else {
168 prevPerm->nextPermission = (void *) newPerm;
169 }
170 prevPerm = newPerm;
172 instNameComplete = FALSE;
173 instNameIndex = 0;
174 foundInstName = FALSE;
175 }
176 else if (instNameIndex == RM_NAME_MAX_CHARS) {
177 /* Instance name is longer than max length */
178 while (startPerm) {
179 nextPerm = startPerm->nextPermission;
180 Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
181 startPerm = nextPerm;
182 }
183 Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
184 *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_INSTANCE_NAME_IN_ASSIGNMENT_TOO_LONG;
185 return(NULL);
186 }
188 permStrPtr++;
189 }
191 /* Fill in the permissions for each instance name */
193 /* Look on left of instance group for permission assignments. */
194 permStrPtr = subgroupStart - 1;
195 assignmentLeft = FALSE;
196 while (permStrPtr >= permStrStart)
197 {
198 if (*permStrPtr == RM_POLICY_PERM_ASSIGNMENT) {
199 if (assignmentLeft) {
200 /* Assignment character has been found more than once. This is a
201 * syntax error. Free the permission list and the temporary string
202 * and return. */
203 while (startPerm) {
204 nextPerm = startPerm->nextPermission;
205 Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
206 startPerm = nextPerm;
207 }
208 Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
209 *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_MORE_THAN_ONE_ASSIGNMENT_CHAR;
210 return(NULL);
211 }
212 else {
213 assignmentLeft = TRUE;
214 }
215 }
216 else if (!isspace(*permStrPtr)) {
217 if (assignmentLeft) {
218 if ((*permStrPtr == RM_POLICY_PERM_INIT_LOWER) ||
219 (*permStrPtr == RM_POLICY_PERM_INIT_UPPER)) {
220 newPerm = startPerm;
221 while (newPerm) {
222 RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_INIT_SHIFT, 1);
223 newPerm = newPerm->nextPermission;
224 }
225 }
226 else if ((*permStrPtr == RM_POLICY_PERM_USE_LOWER) ||
227 (*permStrPtr == RM_POLICY_PERM_USE_UPPER)) {
228 newPerm = startPerm;
229 while (newPerm) {
230 RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_USE_SHIFT, 1);
231 newPerm = newPerm->nextPermission;
232 }
233 }
234 else if ((*permStrPtr == RM_POLICY_PERM_EXCLUSIVE_LOWER) ||
235 (*permStrPtr == RM_POLICY_PERM_EXCLUSIVE_UPPER)) {
236 newPerm = startPerm;
237 while (newPerm) {
238 RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_EXCLUSIVE_SHIFT, 1);
239 newPerm = newPerm->nextPermission;
240 }
241 }
242 else if ((*permStrPtr == RM_POLICY_PERM_SHARED_LINUX_LOWER) ||
243 (*permStrPtr == RM_POLICY_PERM_SHARED_LINUX_UPPER)) {
244 newPerm = startPerm;
245 while (newPerm) {
246 RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_SHARED_LINUX_SHIFT, 1);
247 newPerm = newPerm->nextPermission;
248 }
249 }
250 else {
251 /* Invalid permission character. This is a
252 * syntax error. Free the permission list and the temporary string
253 * and return. */
254 while (startPerm) {
255 nextPerm = startPerm->nextPermission;
256 Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
257 startPerm = nextPerm;
258 }
259 Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
260 *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_INVALID_PERM_CHAR;
261 return(NULL);
262 }
263 }
264 else {
265 /* Character found without the assignment character being found. This is a
266 * syntax error. Free the permission list and the temporary string
267 * and return. */
268 while (startPerm) {
269 nextPerm = startPerm->nextPermission;
270 Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
271 startPerm = nextPerm;
272 }
273 Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
274 *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_PERM_CHAR_WITHOUT_ASSIGN_CHAR;
275 return(NULL);
276 }
277 }
278 permStrPtr--;
279 }
281 /* Look on right of instance group for permission assignments. */
282 permStrPtr = subgroupEnd + 1;
283 assignmentRight = FALSE;
284 while (permStrPtr < permStrEnd) {
285 if (assignmentLeft && (!isspace(*permStrPtr))) {
286 /* There should be nothing but spaces on right if assignment was already found on left */
287 while (startPerm) {
288 nextPerm = startPerm->nextPermission;
289 Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
290 startPerm = nextPerm;
291 }
292 Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
293 *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_INVALID_CHAR_ON_RIGHT_WITH_ASSINMENT_ON_LEFT;
294 return(NULL);
295 }
297 if (*permStrPtr == RM_POLICY_PERM_ASSIGNMENT) {
298 if (assignmentRight) {
299 /* Assignment character has been found more than once. This is a
300 * syntax error. Free the permission list and the temporary string
301 * and return. */
302 while (startPerm) {
303 nextPerm = startPerm->nextPermission;
304 Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
305 startPerm = nextPerm;
306 }
307 Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
308 *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_MORE_THAN_ONE_ASSIGNMENT_CHAR;
309 return(NULL);
310 }
311 else {
312 assignmentRight = TRUE;
313 }
314 }
315 else if (!isspace(*permStrPtr)) {
316 if (assignmentRight) {
317 if ((*permStrPtr == RM_POLICY_PERM_INIT_LOWER) ||
318 (*permStrPtr == RM_POLICY_PERM_INIT_UPPER)) {
319 newPerm = startPerm;
320 while (newPerm) {
321 RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_INIT_SHIFT, 1);
322 newPerm = newPerm->nextPermission;
323 }
324 }
325 else if ((*permStrPtr == RM_POLICY_PERM_USE_LOWER) ||
326 (*permStrPtr == RM_POLICY_PERM_USE_UPPER)) {
327 newPerm = startPerm;
328 while (newPerm) {
329 RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_USE_SHIFT, 1);
330 newPerm = newPerm->nextPermission;
331 }
332 }
333 else if ((*permStrPtr == RM_POLICY_PERM_EXCLUSIVE_LOWER) ||
334 (*permStrPtr == RM_POLICY_PERM_EXCLUSIVE_UPPER)) {
335 newPerm = startPerm;
336 while (newPerm) {
337 RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_EXCLUSIVE_SHIFT, 1);
338 newPerm = newPerm->nextPermission;
339 }
340 }
341 else if ((*permStrPtr == RM_POLICY_PERM_SHARED_LINUX_LOWER) ||
342 (*permStrPtr == RM_POLICY_PERM_SHARED_LINUX_UPPER)) {
343 newPerm = startPerm;
344 while (newPerm) {
345 RM_policy_SET_PERM(newPerm->permissionBits, RM_POLICY_PERM_SHARED_LINUX_SHIFT, 1);
346 newPerm = newPerm->nextPermission;
347 }
348 }
349 else {
350 /* Invalid permission character. This is a
351 * syntax error. Free the permission list and the temporary string
352 * and return. */
353 while (startPerm) {
354 nextPerm = startPerm->nextPermission;
355 Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
356 startPerm = nextPerm;
357 }
358 Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
359 *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_INVALID_PERM_CHAR;
360 return(NULL);
361 }
362 }
363 else {
364 /* Character found without the assignment character being found. This is a
365 * syntax error. Free the permission list and the temporary string
366 * and return. */
367 while (startPerm) {
368 nextPerm = startPerm->nextPermission;
369 Rm_osalFree((void *)startPerm, sizeof(Rm_PolicyPermission));
370 startPerm = nextPerm;
371 }
372 Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
373 *result = RM_INIT_ERROR_POLICY_SYNTAX_ERROR_MORE_THAN_ONE_ASSIGNMENT_CHAR;
374 return(NULL);
375 }
376 }
377 permStrPtr++;
378 }
380 Rm_osalFree((void *)permStrStart, sizeof(permStrLen));
381 return (startPerm);
382 }
384 void policyFreeAssignmentPermissions(Rm_PolicyPermission *permissionList)
385 {
386 Rm_PolicyPermission *nextPerm;
388 while (permissionList) {
389 nextPerm = permissionList->nextPermission;
390 Rm_osalFree((void *)permissionList, sizeof(Rm_PolicyPermission));
391 permissionList = nextPerm;
392 }
393 }
395 Rm_PolicyPermission *policyGetAssignmentPermissions(Rm_PolicyAssignment *assignment,
396 int32_t *result)
397 {
398 Rm_PolicyPermission *startPerm = NULL;
399 Rm_PolicyPermission *newPerm = NULL;
400 Rm_PolicyPermission *prevPerm = NULL;
401 char *permStrStart = assignment->permissionsList;
402 char *permStrEnd;
403 uint32_t permStrLen = strlen(assignment->permissionsList) + 1;
404 uint32_t i = 0;
406 while(i < permStrLen) {
407 /* Find the first sub-permission specification and parse it. A sub-permission
408 * can be terminated by the termination character or the end of the string. */
409 if (!(permStrEnd = strchr(permStrStart, RM_POLICY_PERM_TERMINATOR))) {
410 /* Sub-permission termination character not found. The permission string
411 * end is the end of the entire permission string */
412 permStrEnd = permStrStart + strlen(permStrStart);
413 }
415 newPerm = policyParseSubPermission(permStrStart, permStrEnd, result);
417 if (*result != RM_SERVICE_PROCESSING) {
418 /* Delete the permission list that's been created thus far, return
419 * the error and NULL for the permission list */
420 policyFreeAssignmentPermissions(startPerm);
421 return(NULL);
422 }
424 if (prevPerm == NULL) {
425 startPerm = newPerm;
426 }
427 else {
428 prevPerm->nextPermission = newPerm;
429 }
431 /* Set prevPerm to the last sub-permission returned by the sub-permission parser */
432 prevPerm = newPerm;
433 while(prevPerm->nextPermission != NULL) {
434 prevPerm = prevPerm->nextPermission;
435 }
437 /* Update the number of characters parsed from the permission list and point to
438 * the start of the next sub-permission */
439 i += ((uint32_t)(permStrEnd - permStrStart + 1));
440 permStrStart = permStrEnd + 1;
441 }
443 return(startPerm);
444 }
446 int32_t policyValidateAssignmentPermissions(Rm_PolicyValidInstTree *root,
447 Rm_PolicyAssignment *assignmentList)
448 {
449 Rm_PolicyAssignment *assignment = assignmentList;
450 Rm_PolicyPermission *permissionList;
451 int32_t result;
453 while (assignment) {
454 /* Make sure assignment's permissions parse okay */
455 permissionList = policyGetAssignmentPermissions(assignment, &result);
456 if (result != RM_INIT_OK) {
457 return(result);
458 }
460 if (result = policyCheckInstances(root, permissionList) != RM_INIT_OK) {
461 policyFreeAssignmentPermissions(permissionList);
462 return(result);
463 }
465 policyFreeAssignmentPermissions(permissionList);
466 assignment = assignment->nextAssignment;
467 }
469 return (RM_INIT_OK);
470 }
472 /**********************************************************************
473 ************************ Internal Policy APIs ************************
474 **********************************************************************/
476 Rm_PolicyValidInstNode *rmPolicyGetValidInstNode(Rm_PolicyValidInstTree *validInstTree, char *instName)
477 {
478 Rm_PolicyValidInstNode findNode;
480 memset((void *)&findNode, 0, sizeof(Rm_PolicyValidInstNode));
481 strncpy(findNode.name, instName, RM_NAME_MAX_CHARS);
483 return (RB_FIND(_Rm_PolicyValidInstTree, validInstTree, &findNode));
484 }
486 Rm_PolicyValidInstNode *rmPolicyGetLinuxInstNode(Rm_PolicyValidInstTree *validInstTree)
487 {
488 char linuxName[] = RM_ALLOCATED_TO_LINUX;
490 return (rmPolicyGetValidInstNode(validInstTree, linuxName));
491 }
493 bool rmPolicyCheckPrivilege(Rm_PolicyCheckCfg *privilegeCfg, int32_t *result)
494 {
495 int32_t propertyOffset;
496 const char *propertyName;
497 int32_t propertyLen;
498 const void *propertyData;
499 Rm_PolicyAssignment *assignment = NULL;
500 Rm_PolicyAssignment *assignmentStart = NULL;
501 Rm_PolicyPermission *permission = NULL;
502 Rm_PolicyPermission *permissionStart = NULL;
503 uint32_t assignmentEnd;
504 uint32_t resourceEnd = privilegeCfg->resourceBase + privilegeCfg->resourceLength - 1;
505 bool foundInstance;
507 /* Get the resource's assignments */
508 propertyOffset = fdt_first_property_offset(privilegeCfg->policyDtb, privilegeCfg->resourceOffset);
509 if (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
510 while (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
511 propertyData = fdt_getprop_by_offset(privilegeCfg->policyDtb, propertyOffset, &propertyName, &propertyLen);
512 if (rmDtbUtilPolicyGetPropertyType(propertyName) == Rm_policyPropType_ASSIGNMENTS) {
513 assignment = assignmentStart = rmDtbUtilPolicyExtractAssignments(propertyData, propertyLen);
514 break;
515 }
516 propertyOffset = fdt_next_property_offset(privilegeCfg->policyDtb, propertyOffset);
517 }
518 }
520 if (assignment) {
521 while (assignment) {
522 assignmentEnd = assignment->resourceBase + assignment->resourceLength - 1;
523 foundInstance = FALSE;
524 if (((privilegeCfg->resourceBase >= assignment->resourceBase) &&
525 (privilegeCfg->resourceBase <= assignmentEnd)) ||
526 ((privilegeCfg->resourceBase < assignment->resourceBase) &&
527 (resourceEnd > assignmentEnd)) ||
528 ((resourceEnd >= assignment->resourceBase) &&
529 (resourceEnd <= assignmentEnd))) {
531 permission = permissionStart = policyGetAssignmentPermissions(assignment, result);
532 while (permission) {
533 if ((strcmp(permission->instName, privilegeCfg->validInstNode->name) == 0) ||
534 (strcmp(permission->instName, Rm_policyAllInstances) == 0)) {
535 foundInstance = TRUE;
537 /* Check instance's permissions */
538 if (privilegeCfg->type == Rm_policyCheck_INIT) {
539 if (!RM_policy_GET_PERM(permission->permissionBits, RM_POLICY_PERM_INIT_SHIFT)) {
540 policyFreeAssignmentPermissions(permissionStart);
541 rmDtbUtilPolicyFreeAssignments(assignmentStart);
542 return(FALSE);
543 }
544 }
545 else if (privilegeCfg->type == Rm_policyCheck_USE) {
546 if (!RM_policy_GET_PERM(permission->permissionBits, RM_POLICY_PERM_USE_SHIFT)) {
547 policyFreeAssignmentPermissions(permissionStart);
548 rmDtbUtilPolicyFreeAssignments(assignmentStart);
549 return(FALSE);
550 }
551 }
552 else if (privilegeCfg->type == Rm_policyCheck_EXCLUSIVE) {
553 if (!RM_policy_GET_PERM(permission->permissionBits, RM_POLICY_PERM_EXCLUSIVE_SHIFT)) {
554 policyFreeAssignmentPermissions(permissionStart);
555 rmDtbUtilPolicyFreeAssignments(assignmentStart);
556 return(FALSE);
557 }
558 }
559 break;
560 }
561 permission = permission->nextPermission;
562 }
564 policyFreeAssignmentPermissions(permissionStart);
565 if (!foundInstance) {
566 rmDtbUtilPolicyFreeAssignments(assignmentStart);
567 return(FALSE);
568 }
569 }
570 assignment = assignment->nextAssignment;
571 }
572 rmDtbUtilPolicyFreeAssignments(assignmentStart);
573 }
574 else {
575 return(FALSE);
576 }
578 return(TRUE);
579 }
581 uint32_t rmPolicyGetResourceBase(void *policyDtb, Rm_PolicyValidInstNode *validInstNode,
582 int32_t resourceOffset, uint32_t allocType,
583 int32_t *result)
585 {
586 int32_t propertyOffset;
587 const char *propertyName;
588 int32_t propertyLen;
589 const void *propertyData;
590 Rm_PolicyAssignment *assignment = NULL;
591 Rm_PolicyAssignment *assignmentStart = NULL;
592 Rm_PolicyPermission *permission = NULL;
593 Rm_PolicyPermission *permissionStart = NULL;
594 uint32_t resourceBase = 0;
596 propertyOffset = fdt_first_property_offset(policyDtb, resourceOffset);
597 if (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
598 while (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
599 propertyData = fdt_getprop_by_offset(policyDtb, propertyOffset, &propertyName, &propertyLen);
600 if (rmDtbUtilPolicyGetPropertyType(propertyName) == Rm_policyPropType_ASSIGNMENTS) {
601 assignment = assignmentStart = rmDtbUtilPolicyExtractAssignments(propertyData, propertyLen);
602 break;
603 }
604 propertyOffset = fdt_next_property_offset(policyDtb, propertyOffset);
605 }
606 }
608 /* Search policy permissions for a valid resource base */
609 if (assignment) {
610 while (assignment) {
611 permission = permissionStart = policyGetAssignmentPermissions(assignment, result);
612 while (permission) {
613 if ((strcmp(permission->instName, validInstNode->name) == 0) ||
614 (strcmp(permission->instName, Rm_policyAllInstances) == 0)) {
615 /* Check instance's permissions */
616 if (RM_policy_GET_PERM(allocType, RM_POLICY_PERM_INIT_SHIFT) &&
617 RM_policy_GET_PERM(permission->permissionBits, RM_POLICY_PERM_INIT_SHIFT)) {
618 resourceBase = assignment->resourceBase;
619 break;
620 }
621 else if (RM_policy_GET_PERM(allocType, RM_POLICY_PERM_USE_SHIFT) &&
622 RM_policy_GET_PERM(permission->permissionBits, RM_POLICY_PERM_USE_SHIFT)) {
623 resourceBase = assignment->resourceBase;
624 break;
625 }
626 }
627 permission = permission->nextPermission;
628 }
629 policyFreeAssignmentPermissions(permissionStart);
631 if (resourceBase) {
632 break;
633 }
634 else {
635 assignment = assignment->nextAssignment;
636 }
637 }
638 rmDtbUtilPolicyFreeAssignments(assignmentStart);
639 }
640 else {
641 *result = RM_SERVICE_DENIED_NO_RANGE_ASSIGNMENTS_FOR_POLICY;
642 }
644 return(resourceBase);
645 }
647 uint32_t rmPolicyGetResourceAlignment(void *policyDtb, int32_t resourceOffset)
648 {
649 int32_t propertyOffset;
650 const char *propertyName;
651 int32_t propertyLen;
652 const void *propertyData;
653 Rm_ResourceValue *alignmentList;
654 uint32_t resourceAlignment = 0;
656 propertyOffset = fdt_first_property_offset(policyDtb, resourceOffset);
657 if (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
658 while (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
659 propertyData = fdt_getprop_by_offset(policyDtb, propertyOffset, &propertyName, &propertyLen);
660 if (rmDtbUtilPolicyGetPropertyType(propertyName) == Rm_policyPropType_ALLOCATION_ALIGNMENT) {
661 alignmentList = rmDtbUtilPolicyExtractResourceAlignments(propertyData, propertyLen);
662 resourceAlignment = alignmentList->value;
663 rmDtbUtilPolicyFreeResourceAlignments(alignmentList);
664 }
665 propertyOffset = fdt_next_property_offset(policyDtb, propertyOffset);
666 }
667 }
668 return(resourceAlignment);
669 }
671 int32_t rmPolicyGetResourceOffset(void *policyDtb, char *resourceName)
672 {
673 int32_t nodeOffset;
674 int32_t depth;
675 const char *nodeName;
677 depth = RM_DTB_UTIL_STARTING_DEPTH;
678 nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;
680 /* Find node offset for provided resource name */
681 while ((nodeOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) &&
682 (depth >= RM_DTB_UTIL_STARTING_DEPTH)) {
683 nodeOffset = fdt_next_node(policyDtb, nodeOffset, &depth);
684 nodeName = fdt_get_name(policyDtb, nodeOffset, NULL);
686 if (strcmp(nodeName, resourceName) == 0)
687 {
688 break;
689 }
690 }
691 return(nodeOffset);
692 }
694 int32_t rmPolicyValidatePolicyResourceNames(void *policyDtb, void *allocatorList)
695 {
696 Rm_Allocator *allocator = (Rm_Allocator *)allocatorList;
697 int32_t nodeOffset;
698 int32_t depth;
699 const char *nodeName;
701 depth = RM_DTB_UTIL_STARTING_DEPTH;
702 nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;
704 /* Parse DTB, verifying each resource's assignment permissions.
705 * Permissions must have correct syntax and contain valid instance names
706 * according validInstList */
707 while ((nodeOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) &&
708 (depth >= RM_DTB_UTIL_STARTING_DEPTH)) {
709 nodeOffset = fdt_next_node(policyDtb, nodeOffset, &depth);
710 nodeName = fdt_get_name(policyDtb, nodeOffset, NULL);
711 if (fdt_first_property_offset(policyDtb, nodeOffset) > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
712 if (rmAllocatorFind(allocator, (char *)nodeName) == NULL) {
713 /* No allocator tied to resource name */
714 return(RM_INIT_ERROR_POLICY_UNKNOWN_RESOURCE);
715 }
716 }
717 }
718 return(RM_INIT_OK);
719 }
721 /* TODO: ADD ABILITY TO RETURN THE SYNTAX ERROR LOCATION */
722 int32_t rmPolicyValidatePolicy(void *policyDtb, Rm_PolicyValidInstTree *validInstTree)
723 {
724 int32_t nodeOffset;
725 int32_t propertyOffset;
726 int32_t depth;
727 const char *propertyName;
728 int32_t propertyLen;
729 const void *propertyData;
730 Rm_PolicyPropType propertyType;
731 Rm_PolicyAssignment *assignmentList;
732 int32_t result;
734 depth = RM_DTB_UTIL_STARTING_DEPTH;
735 nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;
737 /* Parse DTB, verifying each resource's assignment permissions.
738 * Permissions must have correct syntax and contain valid instance names
739 * according validInstList */
740 while ((nodeOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) &&
741 (depth >= RM_DTB_UTIL_STARTING_DEPTH)) {
742 nodeOffset = fdt_next_node(policyDtb, nodeOffset, &depth);
743 propertyOffset = fdt_first_property_offset(policyDtb, nodeOffset);
744 while (propertyOffset > RM_DTB_UTIL_STARTING_NODE_OFFSET) {
745 propertyData = fdt_getprop_by_offset(policyDtb, propertyOffset, &propertyName, &propertyLen);
746 propertyType = rmDtbUtilPolicyGetPropertyType(propertyName);
747 if (propertyType == Rm_policyPropType_ASSIGNMENTS) {
748 assignmentList = rmDtbUtilPolicyExtractAssignments(propertyData, propertyLen);
750 if ((result = policyValidateAssignmentPermissions(validInstTree, assignmentList)) != RM_INIT_OK) {
751 rmDtbUtilPolicyFreeAssignments(assignmentList);
752 return(result);
753 }
754 rmDtbUtilPolicyFreeAssignments(assignmentList);
755 }
756 else if (propertyType == Rm_policyPropType_UNKNOWN) {
757 return(RM_INIT_ERROR_POLICY_UNKNOWN_RESOURCE_PROPERTY);
758 }
759 propertyOffset = fdt_next_property_offset(policyDtb, propertyOffset);
760 }
761 }
762 return(RM_INIT_OK);
763 }
765 Rm_PolicyValidInstTree *rmPolicyCreateValidInstTree(void *policyDtb, int32_t *result)
766 {
767 int32_t validInstOffset;
768 const char *validInstName = NULL;
769 int32_t validInstLen;
770 const void *validInstData = NULL;
771 Rm_PolicyPropType propertyType;
772 Rm_PolicyValidInst *validInstList = NULL;
773 Rm_PolicyValidInstTree *rootEntry = NULL;
774 Rm_PolicyValidInstNode *newNode = NULL;
775 char linuxName[] = RM_ALLOCATED_TO_LINUX;
777 /* Valid instance list must be first and only property in the root node of
778 * the policyDtb */
779 validInstOffset = fdt_first_property_offset(policyDtb, RM_DTB_UTIL_STARTING_NODE_OFFSET);
780 if (validInstOffset < -FDT_ERR_NOTFOUND) {
781 *result = validInstOffset;
782 return (NULL);
783 }
784 else if (validInstOffset == -FDT_ERR_NOTFOUND) {
785 *result = RM_INIT_ERROR_POLICY_NO_VALID_INSTANCES_DEFINED;
786 return (NULL);
787 }
788 validInstData = fdt_getprop_by_offset(policyDtb, validInstOffset, &validInstName, &validInstLen);
789 propertyType = rmDtbUtilPolicyGetPropertyType(validInstName);
790 if (propertyType != Rm_policyPropType_VALID_INSTANCES) {
791 *result = RM_INIT_ERROR_POLICY_NO_VALID_INSTANCES_DEFINED;
792 return (NULL);
793 }
795 if (!(validInstList = rmDtbUtilPolicyExtractValidInstances(validInstData, validInstLen, result))) {
796 return (NULL);
797 }
799 /* Create the tree */
800 rootEntry = Rm_osalMalloc(sizeof(Rm_PolicyValidInstTree));
801 RB_INIT(rootEntry);
803 while (validInstList) {
804 newNode = policyValidInstNodeNew(validInstList->instName);
805 RB_INSERT(_Rm_PolicyValidInstTree, rootEntry, newNode);
807 validInstList = validInstList->nextValidInst;
808 }
810 /* Add the Linux kernel node */
811 newNode = policyValidInstNodeNew(linuxName);
812 RB_INSERT(_Rm_PolicyValidInstTree, rootEntry, newNode);
814 *result = RM_INIT_OK;
815 return (rootEntry);
816 }
818 void rmPolicyFreeValidInstTree(Rm_PolicyValidInstTree *validInstTree)
819 {
820 Rm_PolicyValidInstNode *node;
822 RB_FOREACH(node, _Rm_PolicyValidInstTree, validInstTree) {
823 RB_REMOVE(_Rm_PolicyValidInstTree, validInstTree, node);
824 policyValidInstNodeFree(node);
825 }
826 Rm_osalFree((void *)validInstTree, sizeof(Rm_PolicyValidInstTree));
827 }