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