178e3f1ec293804f336e9cdcae8a0417f54741be
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_policy.h>
47 #include <ti/drv/rm/rm_services.h>
49 /* RM internal API includes */
50 #include <ti/drv/rm/include/rm_loc.h>
51 #include <ti/drv/rm/include/rm_policyloc.h>
52 #include <ti/drv/rm/include/rm_dtb_utilloc.h>
54 /* RM LIBFDT includes */
55 #include <ti/drv/rm/src/libfdt/libfdt.h>
57 /* RM OSAL layer */
58 #include <rm_osal.h>
60 /**********************************************************************
61 ************** Red-Black BBST Tree NameServer Functions **************
62 **********************************************************************/
64 Rm_PolicyInstNode *Rm_newPolicyInstNode(const char *instName, int32_t nodeOffset)
65 {
66 Rm_PolicyInstNode *newNode = NULL;
68 newNode = Rm_osalMalloc(sizeof(Rm_PolicyInstNode));
70 /* Populate the node */
71 strcpy(newNode->instName, instName);
72 newNode->nodeOffset = nodeOffset;
74 return(newNode);
75 }
77 void Rm_freePolicyInstNode(Rm_PolicyInstNode *node)
78 {
79 /* Free the memory associated with the tree node. */
80 Rm_osalFree((void *)node, sizeof(Rm_PolicyInstNode));
81 }
83 /* Prototype for tree node comparison function
84 * element1 < element2 --> return < 0
85 * element1 = element2 --> return 0
86 * element1 > element2 --> return > 0 */
87 int Rm_PolicyInstNodeCompare(Rm_PolicyInstNode *element1, Rm_PolicyInstNode *element2)
88 {
89 return(strcmp(element1->instName, element2->instName));
90 }
92 /* Generate the red-black tree manipulation functions */
93 RB_GENERATE(_Rm_PolicyInstLookupTree, _Rm_PolicyInstNode, linkage, Rm_PolicyInstNodeCompare);
95 /**********************************************************************
96 ********************** Internal Functions ****************************
97 **********************************************************************/
99 /* Function parses the policy DTB and saves the offset into the DTB for each
100 * RM instance name. When services need to be checked against the policy the
101 * RM instance offset into the policy DTB can be retrieved from the lookup
102 * tree rather than reparsing the entire policy DTB */
103 void Rm_policyCreateInstanceLookup(Rm_PolicyData *policyDataPtr)
104 {
105 Rm_PolicyInstLookupTree *rootEntry = NULL;
106 Rm_PolicyInstNode *policyNode = NULL;
107 Rm_PolicyInstNode *collidingNode = NULL;
108 int32_t nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;
109 int32_t depth = RM_DTB_UTIL_STARTING_DEPTH;
110 const char *instName;
112 /* Create the policy instance lookup root entry and initialize it */
113 rootEntry = Rm_osalMalloc(sizeof(Rm_PolicyInstLookupTree));
114 RB_INIT(rootEntry);
116 policyDataPtr->instLookupTreeRoot = (void *)rootEntry;
118 /* Parse the entire policy DTB and store the node offsets that correspond to the root
119 * node for each RM instance. */
120 do
121 {
122 if (depth == RM_POLICY_DTB_INSTANCE_DEPTH)
123 {
124 instName = fdt_get_name(policyDataPtr->policyDtb, nodeOffset, NULL);
126 /* Store the RM instance name and it's node offset into the policy DTB */
127 policyNode = Rm_newPolicyInstNode(instName, nodeOffset);
129 /* Try to insert the new policy lookup node */
130 collidingNode = RB_INSERT(_Rm_PolicyInstLookupTree,
131 policyDataPtr->instLookupTreeRoot, policyNode);
132 if (collidingNode)
133 {
134 Rm_freePolicyInstNode(policyNode);
135 }
136 }
138 /* Get the next node */
139 nodeOffset = fdt_next_node(policyDataPtr->policyDtb, nodeOffset, &depth);
140 } while ((nodeOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && (depth >= RM_DTB_UTIL_STARTING_DEPTH));
142 /* TODO: ADD ERROR RETURN CODES */
143 }
145 int32_t Rm_policyCheck(Rm_PolicyHandle policyDtb, Rm_PolicyCheckInfo *checkInfo,
146 Rm_PolicyNodeProperties *nodeProperties)
147 {
149 }
151 int32_t Rm_policyCheckResource(Rm_Inst *rmInst, Rm_PolicyCheckInfo *checkInfo)
152 {
153 Rm_PolicyData *policyDataPtr = (Rm_PolicyData *) rmInst->policyData;
154 Rm_PolicyInstNode findNode;
155 Rm_PolicyInstNode *matchingNode = NULL;
156 int32_t nodeOffset;
157 int32_t depth = RM_DTB_UTIL_STARTING_DEPTH;
158 const char *nodeName;
159 Rm_PolicyNodeProperties nodeProps;
160 int32_t propertyLen;
161 const void *propertyData;
162 Rm_PolicyPropType propertyType;
163 int32_t retVal = RM_SERVICE_PROCESSING;
165 /* Initialize the node properties to NULL */
166 memset((void *) &nodeProps, 0, sizeof(Rm_PolicyNodeProperties));
168 /* Get the RM instance's node offset from the lookup tree */
169 strcpy(findNode.instName, checkInfo->serviceSrcInstName);
170 matchingNode = RB_FIND(_Rm_PolicyInstLookupTree, policyDataPtr->instLookupTreeRoot, &findNode);
172 if (matchingNode)
173 {
174 nodeOffset = matchingNode->nodeOffset;
175 nodeName = matchingNode->instName;
177 /* Search for the resource node that matches the resource in the service request.
178 * Exit the search loop if the resource node is found or if all subnodes have been parsed
179 * without finding the resource (signalled by the depth being equivalent to the starting
180 * depth. */
181 while (strcmp(nodeName, checkInfo->resourceInfo->name))
182 {
183 /* Parse the nodes for the resource node. All nodes should be subnodes of the
184 * found RM instance node. Therefore, the depth should be greater than the
185 * starting depth */
186 nodeOffset = fdt_next_node(policyDataPtr->policyDtb, nodeOffset, &depth);
188 if ((depth <= RM_DTB_UTIL_STARTING_DEPTH) || (nodeOffset <= -FDT_ERR_NOTFOUND))
189 {
190 retVal = RM_SERVICE_DENIED_RESOURCE_NOT_DEFINED_IN_POLICY;
191 break;
192 }
194 nodeName = fdt_get_name(policyDataPtr->policyDtb, nodeOffset, NULL);
195 }
197 if (retVal == RM_SERVICE_PROCESSING)
198 {
199 /* Get the resource node's properties */
201 /* Get the properties for the resource node if any exist */
202 nodeOffset = fdt_first_property_offset(policyDataPtr->policyDtb, nodeOffset);
204 while ((nodeOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && (retVal == RM_SERVICE_PROCESSING))
205 {
206 /* Get the property data and store it in the corresponding nodeProps field */
207 propertyData = fdt_getprop_by_offset(policyDataPtr->policyDtb, nodeOffset,
208 &nodeName, &propertyLen);
210 propertyType = Rm_policyGetPropertyType(nodeName);
211 if (propertyType == Rm_policyPropType_ASSIGNED_RANGES)
212 {
213 if (nodeProps.rangeData || nodeProps.rangeLen)
214 {
215 /* The range fields have already been populated. Return an error.
216 * The policy has specified a property field more than once
217 * for a resource node */
218 retVal = RM_SERVICE_DENIED_ASSIGNED_RANGE_SPECIFICATION_ERROR;
219 }
220 else
221 {
222 nodeProps.rangeData = propertyData;
223 nodeProps.rangeLen = propertyLen;
224 }
225 }
226 else if (propertyType == Rm_policyPropType_ALLOCATION_SIZES)
227 {
228 if (nodeProps.allocationSizeData || nodeProps.allocationSizeLen)
229 {
230 /* The allocationSize fields have already been populated. Return an error.
231 * The policy has specified a property field more than once
232 * for a resource node */
233 retVal = RM_SERVICE_DENIED_ALLOCATION_SIZE_SPECIFICATION_ERROR;
234 }
235 else
236 {
237 nodeProps.allocationSizeData = propertyData;
238 nodeProps.allocationSizeLen = propertyLen;
239 }
240 }
241 else if (propertyType == Rm_policyPropType_ASSIGNED_NAMES)
242 {
243 if (nodeProps.assignedNamesData || nodeProps.assignedNamesLen)
244 {
245 /* The assignedNames fields have already been populated. Return an error.
246 * The policy has specified a property field more than once
247 * for a resource node */
248 retVal = RM_SERVICE_DENIED_ASSIGNED_NAME_SPECIFICATION_ERROR;
249 }
250 else
251 {
252 nodeProps.assignedNamesData = propertyData;
253 nodeProps.assignedNamesLen = propertyLen;
254 }
255 }
256 else if (propertyType == Rm_policyPropType_ALLOCATION_ALIGNMENTS)
257 {
258 if (nodeProps.alignmentData || nodeProps.alignmentLen)
259 {
260 /* The alignment fields have already been populated. Return an error.
261 * The policy has specified a property field more than once
262 * for a resource node */
263 retVal = RM_SERVICE_DENIED_ALLOCATION_ALIGNMENT_SPECIFICATION_ERROR;
264 }
265 else
266 {
267 nodeProps.alignmentData = propertyData;
268 nodeProps.alignmentLen = propertyLen;
269 }
270 }
271 else
272 {
273 retVal = RM_SERVICE_DENIED_UNKNOWN_POLICY_PROPERTY;
274 }
276 nodeOffset = fdt_next_property_offset(policyDataPtr->policyDtb, nodeOffset);
277 }
278 }
280 if (retVal == RM_SERVICE_PROCESSING)
281 {
282 /* Check the resource(s) in the service request against what is assigned to
283 * the instance */
284 retVal = Rm_policyCheck(policyDataPtr->policyDtb, checkInfo, &nodeProps);
285 }
286 }
287 else
288 {
289 /* RM instance not defined in policy. Service denied */
290 retVal = RM_SERVICE_DENIED_RM_INST_NOT_DEFINED_IN_POLICY;
291 }
293 return(retVal);
294 }
296 void Rm_policyInit(Rm_Inst *rmInst, void *policyDtb)
297 {
298 Rm_PolicyData *policyDataPtr;
300 /* Allocate memory for the policy data structure */
301 policyDataPtr = Rm_osalMalloc(sizeof(Rm_PolicyData));
303 /* Open the policy DTB and create the instance node offset lookup table */
304 fdt_open_into(policyDtb, policyDtb, fdt_totalsize(policyDtb));
305 policyDataPtr->policyDtb = policyDtb;
306 Rm_policyCreateInstanceLookup(policyDataPtr);
308 /* Store the policy in the RM instance */
309 rmInst->policyData = (void *) policyDataPtr;
310 }