1 /**
2 * @file rm_dtb_util.c
3 *
4 * @brief
5 * This is the Resource Manager Resource List and Policy DTB parsing
6 * utility source
7 *
8 * \par
9 * ============================================================================
10 * @n (C) Copyright 2012, Texas Instruments, Inc.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 *
16 * Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 *
19 * Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the
22 * distribution.
23 *
24 * Neither the name of Texas Instruments Incorporated nor the names of
25 * its contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \par
41 */
43 /* RM Types */
44 #include <ti/drv/rm/rm_types.h>
46 /* RM internal API includes */
47 #include <ti/drv/rm/include/rm_dtb_utilloc.h>
49 /* RM OSAL layer */
50 #include <rm_osal.h>
52 /* LIBFDT includes */
53 #include <ti/drv/rm/src/libfdt/libfdt.h>
54 #include <ti/drv/rm/src/libfdt/libfdt_env.h>
56 /**********************************************************************
57 ********************Common DTB Parsing Functions**********************
58 **********************************************************************/
60 char *Rm_commonExtractName(const void *dtbDataPtr, int32_t dtbDataLen)
61 {
62 char *resourceName = NULL;
64 resourceName = (char *) Rm_osalMalloc(dtbDataLen);
66 /* The resource name is stored as a null terminated string in the DTB
67 * so it's just a straightforward string copy operation to a local
68 * buffer to extract it. */
69 strcpy(resourceName, (char *)dtbDataPtr);
71 return(resourceName);
72 }
74 /* Free memory that was allocated to extract a name property string */
75 void Rm_commonFreeName(char *resourceName)
76 {
77 int32_t nameSize;
79 /* Free the character array memory */
80 nameSize = strlen(resourceName);
81 /* Add one for the NULL character */
82 Rm_osalFree((void *)resourceName, nameSize+1);
83 }
85 /* Construct and return a list of ranges as specified in either the Resource
86 * DTB or a Policy DTB */
87 Rm_ResourceRange *Rm_commonExtractRange(const void *dtbDataPtr, int32_t dtbDataLen)
88 {
89 uint32_t *dtbRangeData = (uint32_t *)dtbDataPtr;
90 Rm_ResourceRange *startRange = NULL;
91 Rm_ResourceRange *newRange = NULL;
92 Rm_ResourceRange *prevRange = NULL;
93 uint32_t i;
95 /* Ranges are stored in the DTB as a list of 32-bit words. The number of 32-bit
96 * words in the DTB ranges field should be even since ranges are specified in a
97 * base, lenth format. The DTB gives properties lengths in bytes so the length
98 * returned from the DTB should be a multiple of the number of bytes in two
99 * uint32_ts. */
100 if (dtbDataLen % (2 * sizeof(uint32_t)))
101 {
102 /* Return NULL if there are an odd number of range values */
103 return (NULL);
104 }
106 /* Extract the range data from the DTB */
107 for (i = 0; i < (dtbDataLen / sizeof(uint32_t)); i+=2)
108 {
109 /* Creat a new range entry */
110 newRange = (Rm_ResourceRange *) Rm_osalMalloc(sizeof(Rm_ResourceRange));
111 /* Populate the new range entry. The endianness of the value extracted must
112 * be flipped */
113 newRange->base = fdt32_to_cpu(dtbRangeData[i]);
114 newRange->length = fdt32_to_cpu(dtbRangeData[i+1]);
115 newRange->nextRange = NULL;
117 /* Range linked list pointer accounting */
118 if (prevRange == NULL)
119 {
120 /* Save the first entry so it can be returned */
121 startRange = newRange;
122 }
123 else
124 {
125 prevRange->nextRange = (void *) newRange;
126 }
128 prevRange = newRange;
129 }
131 /* Return a pointer to the start of the range list */
132 return (startRange);
133 }
135 /* Function to clean up the memory allocated for a linked list of extracted ranges */
136 void Rm_commonFreeRangeList(Rm_ResourceRange *rangeList)
137 {
138 Rm_ResourceRange *nextRange;
140 while (rangeList != NULL)
141 {
142 nextRange = rangeList->nextRange;
143 Rm_osalFree((void *)rangeList, sizeof(Rm_ResourceRange));
144 rangeList = nextRange;
145 }
146 }
148 /**********************************************************************
149 ***********Resource List DTB Parsing Defines and Functions************
150 **********************************************************************/
152 /* Resource List Properties - These are the property values used
153 * by an application integrator to define the properties of resources
154 * listed in the Device Resource List */
155 char rmResourceDeviceNameProp[] = "device-name";
156 char rmResourceResourceNameProp[] = "resource-name";
157 char rmResourceResourceRangeProp[] = "resource-range";
158 char rmResourceResourceAllocatorProp[] = "allocator";
159 char rmResourceNsAssignmentProp[] = "ns-assignment";
161 Rm_ResourcePropType Rm_resourceGetPropertyType(const char * propertyName)
162 {
163 Rm_ResourcePropType propertyType = Rm_resourcePropType_UNKNOWN;
165 if(strcmp(rmResourceDeviceNameProp, propertyName) == 0)
166 {
167 propertyType = Rm_resourcePropType_DEVICE_NAME;
168 }
169 else if(strcmp(rmResourceResourceNameProp, propertyName) == 0)
170 {
171 propertyType = Rm_resourcePropType_RESOURCE_NAME;
172 }
173 else if(strcmp(rmResourceResourceRangeProp, propertyName) == 0)
174 {
175 propertyType = Rm_resourcePropType_RESOURCE_RANGE;
176 }
177 else if(strcmp(rmResourceResourceAllocatorProp, propertyName) == 0)
178 {
179 propertyType = Rm_resourcePropType_RESOURCE_ALLOCATOR;
180 }
181 else if(strcmp(rmResourceNsAssignmentProp, propertyName) == 0)
182 {
183 propertyType = Rm_resourcePropType_NSASSIGNMENT;
184 }
186 return (propertyType);
187 }
189 char *Rm_resourceExtractDeviceName(const void *dtbDataPtr, int32_t dtbDataLen)
190 {
191 return(Rm_commonExtractName(dtbDataPtr, dtbDataLen));
192 }
194 void Rm_resourceFreeDeviceName(char *deviceName)
195 {
196 Rm_commonFreeName(deviceName);
197 }
199 char *Rm_resourceExtractResourceName(const void *dtbDataPtr, int32_t dtbDataLen)
200 {
201 return(Rm_commonExtractName(dtbDataPtr, dtbDataLen));
202 }
204 void Rm_resourceFreeResourceName(char *resourceName)
205 {
206 Rm_commonFreeName(resourceName);
207 }
209 Rm_ResourceRange *Rm_resourceExtractResourceRange(const void *dtbDataPtr, int32_t dtbDataLen)
210 {
211 return(Rm_commonExtractRange(dtbDataPtr, dtbDataLen));
212 }
214 void Rm_resourceFreeResourceRange(Rm_ResourceRange *rangeList)
215 {
216 Rm_commonFreeRangeList(rangeList);
217 }
219 /* MODIFY TO RETURN AN ALLOCATOR TYPE INSTEAD OF A STRING??? */
220 char *Rm_resourceExtractResourceAllocator(const void *dtbDataPtr, int32_t dtbDataLen)
221 {
222 return(Rm_commonExtractName(dtbDataPtr, dtbDataLen));
223 }
225 void Rm_resourceFreeResourceAllocator(char *resourceAllocatorType)
226 {
227 Rm_commonFreeName(resourceAllocatorType);
228 }
230 /* Construct and return a list of NameServer assignments as specified in the Resource DTB */
231 Rm_NsAssignment *Rm_resourceExtractNsAssignment(const void *dtbDataPtr, int32_t dtbDataLen)
232 {
233 uint8_t *dtbNsAssignmentData = (uint8_t *)dtbDataPtr;
234 uint32_t nameLenBytes;
235 uint32_t extractedValue;
236 uint8_t *extractedValueBytePtr;
237 Rm_NsAssignment *startAssignment = NULL;
238 Rm_NsAssignment *newAssignment = NULL;
239 Rm_NsAssignment *prevAssignment = NULL;
240 int8_t i = 0;
241 uint16_t j;
243 /* NameServer assignments are stored in the DTB as a null-terminated character
244 * string followed by a 32-bit word containing the value to be assigned to the
245 * name in the string. There is no padding between the string and the 32-bit
246 * word. Therefore the 32-bit word may not be on a 4-byte boundary and must
247 * be constructed upon extraction */
249 /* Extract the NameServer assignment data from the DTB */
250 while(i < dtbDataLen)
251 {
252 /* Creat a new NameServer assignment entry */
253 newAssignment = (Rm_NsAssignment *) Rm_osalMalloc(sizeof(Rm_NsAssignment));
255 /* Populate the new assignment entry. Allocate a buffer for the assignment
256 * name string (adding one for the null character). */
257 nameLenBytes = strlen((char *) &dtbNsAssignmentData[i]) + 1;
258 newAssignment->nsName = (char *) Rm_osalMalloc(nameLenBytes);
259 strcpy(newAssignment->nsName, ((char *) &dtbNsAssignmentData[i]));
261 /* Extract the 32-bit value */
262 i += nameLenBytes;
263 extractedValueBytePtr = (uint8_t *)&extractedValue;
264 for (j = 0; j < sizeof(uint32_t); j++, i++)
265 {
266 extractedValueBytePtr[j] = dtbNsAssignmentData[i];
267 }
268 /* flip the endianness */
269 newAssignment->resourceValue = fdt32_to_cpu(extractedValue);
271 newAssignment->nextNsAssignment = NULL;
273 if (prevAssignment == NULL)
274 {
275 /* Save the first entry so it can be returned */
276 startAssignment = newAssignment;
277 }
278 else
279 {
280 prevAssignment->nextNsAssignment = (void *) newAssignment;
281 }
282 prevAssignment = newAssignment;
283 }
285 /* Return a pointer to the start of the NameServer assignment list */
286 return (startAssignment);
287 }
289 /* Function to clean up the memory allocated for a linked list of extracted NameServer
290 * assignments. */
291 void Rm_resourceFreeNsAssignmentList (Rm_NsAssignment *nsAssignmentList)
292 {
293 Rm_NsAssignment *nextAssignment;
294 int32_t nameSize;
296 while (nsAssignmentList != NULL)
297 {
298 nextAssignment = nsAssignmentList->nextNsAssignment;
299 /* Free the character array memory first */
300 nameSize = strlen(nsAssignmentList->nsName);
301 /* Add one for the NULL character */
302 Rm_osalFree((void *)nsAssignmentList->nsName, nameSize+1);
303 /* Free the list element */
304 Rm_osalFree((void *)nsAssignmentList, sizeof(Rm_NsAssignment));
305 nsAssignmentList = nextAssignment;
306 }
307 }
309 /**********************************************************************
310 ***************Policy DTB Parsing Defines and Functions***************
311 **********************************************************************/
313 /* Policy Properties - These are the property values used
314 * by an application integrator to define the properties of resources
315 * listed in a Resource Manager Policy */
316 char rmPolicyPolicyTypeProp[] = "policy-type";
317 char rmPolicyInstanceNameProp[] = "instance-name";
318 char rmPolicyResourceNameProp[] = "resource-name";
319 char rmPolicyResourceAssignedRangesProp[] = "assigned-ranges";
320 char rmPolicyResourceAllocationSizesProp[] = "allocation-sizes";
321 char rmPolicyResourceAssignedNsNamesProp[] = "assigned-ns-names";
323 Rm_PolicyPropType Rm_policyGetPropertyType(const char * propertyName)
324 {
325 Rm_PolicyPropType propertyType = Rm_policyPropType_UNKNOWN;
327 if(strcmp(rmPolicyPolicyTypeProp, propertyName) == 0)
328 {
329 propertyType = Rm_policyPropType_POLICY_TYPE;
330 }
331 else if(strcmp(rmPolicyInstanceNameProp, propertyName) == 0)
332 {
333 propertyType = Rm_policyPropType_INSTANCE_NAME;
334 }
335 else if(strcmp(rmPolicyResourceNameProp, propertyName) == 0)
336 {
337 propertyType = Rm_policyPropType_RESOURCE_NAME;
338 }
339 else if(strcmp(rmPolicyResourceAssignedRangesProp, propertyName) == 0)
340 {
341 propertyType = Rm_policyPropType_RESOURCE_ASSIGNED_RANGES;
342 }
343 else if(strcmp(rmPolicyResourceAllocationSizesProp, propertyName) == 0)
344 {
345 propertyType = Rm_policyPropType_RESOURCE_ALLOCATION_SIZES;
346 }
347 else if(strcmp(rmPolicyResourceAssignedNsNamesProp, propertyName) == 0)
348 {
349 propertyType = Rm_policyPropType_ASSIGNED_NS_NAMES;
350 }
352 return (propertyType);
353 }
355 /* MODIFY TO RETURN A POLICY TYPE INSTEAD OF A STRING??? */
356 char *Rm_policyExtractPolicyType(const void *dtbDataPtr, int32_t dtbDataLen)
357 {
358 return(Rm_commonExtractName(dtbDataPtr, dtbDataLen));
359 }
361 void Rm_policyFreePolicyType(char *policyType)
362 {
363 Rm_commonFreeName(policyType);
364 }
366 char *Rm_policyExtractInstanceName(const void *dtbDataPtr, int32_t dtbDataLen)
367 {
368 return(Rm_commonExtractName(dtbDataPtr, dtbDataLen));
369 }
371 void Rm_policyFreeInstanceName(char *instanceName)
372 {
373 Rm_commonFreeName(instanceName);
374 }
376 Rm_ResourceRange *Rm_policyExtractResourceAssignedRanges(const void *dtbDataPtr, int32_t dtbDataLen)
377 {
378 return(Rm_commonExtractRange(dtbDataPtr, dtbDataLen));
379 }
381 void Rm_policyFreeResourceAssignedRanges(Rm_ResourceRange *rangeList)
382 {
383 Rm_commonFreeRangeList(rangeList);
384 }
386 /* Construct and return a list of allocation sizes as specified in the Policy DTB */
387 Rm_AllocationSize *Rm_policyExtractAllocationSizes(const void *dtbDataPtr, int32_t dtbDataLen)
388 {
389 uint32_t *dtbRangeData = (uint32_t *)dtbDataPtr;
390 Rm_AllocationSize *startAllocationSize = NULL;
391 Rm_AllocationSize *newAllocationSize = NULL;
392 Rm_AllocationSize *prevAllocationSize = NULL;
393 uint32_t i;
395 /* Allocation sizes are stored in the DTB as a list of 32-bit words. The DTB
396 * gives properties lengths in bytes so the length returned from the DTB
397 * should be a multiple of the number of bytes a uint32_t. */
398 if (dtbDataLen % sizeof(uint32_t))
399 {
400 return (NULL);
401 }
403 /* Extract the allocation size data from the DTB */
404 for (i = 0; i < (dtbDataLen / sizeof(uint32_t)); i++)
405 {
406 /* Creat a new allocation size entry */
407 newAllocationSize = (Rm_AllocationSize *) Rm_osalMalloc(sizeof(Rm_AllocationSize));
408 /* Populate the new allocation size entry. The endianness of the value extracted must
409 * be flipped */
410 newAllocationSize->allocationSize = fdt32_to_cpu(dtbRangeData[i]);
411 newAllocationSize->nextAllocationSize = NULL;
413 /* Allocation size linked list pointer accounting */
414 if (prevAllocationSize == NULL)
415 {
416 /* Save the first entry so it can be returned */
417 startAllocationSize = newAllocationSize;
418 }
419 else
420 {
421 prevAllocationSize->nextAllocationSize = (void *) newAllocationSize;
422 }
424 prevAllocationSize = newAllocationSize;
425 }
427 /* Return a pointer to the start of the allocation size list */
428 return (startAllocationSize);
429 }
431 /* Function to clean up the memory allocated for a linked list of extracted allocation sizes */
432 void Rm_policyFreeAllocationSizesList (Rm_AllocationSize *allocationSizeList)
433 {
434 Rm_AllocationSize *nextAllocationSize;
436 while (allocationSizeList != NULL)
437 {
438 nextAllocationSize = allocationSizeList->nextAllocationSize;
439 Rm_osalFree((void *)allocationSizeList, sizeof(Rm_AllocationSize));
440 allocationSizeList = nextAllocationSize;
441 }
442 }
444 /* Construct and return a list of assigned NameServer names as specified in the Policy DTB */
445 Rm_AssignedNsNames *Rm_policyExtractAssignedNsNames(const void *dtbDataPtr, int32_t dtbDataLen)
446 {
447 uint8_t *dtbAssignedNsNamesData = (uint8_t *)dtbDataPtr;
448 uint32_t nameLenBytes;
449 Rm_AssignedNsNames *startAssignedName = NULL;
450 Rm_AssignedNsNames *newAssignedName = NULL;
451 Rm_AssignedNsNames *prevAssignedName = NULL;
452 int8_t i = 0;
454 /* Assigned NameServer names are stored in the DTB as a block of null-terminated
455 * character strings. There is no padding between the strings. */
457 /* Extract the assigned NameServer name data from the DTB */
458 while(i < dtbDataLen)
459 {
460 /* Creat a new assigned NameServer name entry */
461 newAssignedName = (Rm_AssignedNsNames *) Rm_osalMalloc(sizeof(Rm_AssignedNsNames));
463 /* Populate the new assigned name entry. Allocate a buffer for the assigned
464 * name string (adding one for the null character). */
465 nameLenBytes = strlen((char *) &dtbAssignedNsNamesData[i]) + 1;
466 newAssignedName->assignedName = (char *) Rm_osalMalloc(nameLenBytes);
467 strcpy(newAssignedName->assignedName, ((char *) &dtbAssignedNsNamesData[i]));
469 newAssignedName->nextAssignedName = NULL;
471 if (prevAssignedName == NULL)
472 {
473 /* Save the first entry so it can be returned */
474 startAssignedName = newAssignedName;
475 }
476 else
477 {
478 prevAssignedName->nextAssignedName = (void *) newAssignedName;
479 }
480 prevAssignedName = newAssignedName;
481 }
483 /* Return a pointer to the start of the assigned NameServer names list */
484 return (startAssignedName);
485 }
487 /* Function to clean up the memory allocated for a linked list of extracted
488 * assigned NameServer names. */
489 void Rm_policyFreeAssignmentNsNamesList (Rm_AssignedNsNames *assignedNsNamesList)
490 {
491 Rm_AssignedNsNames *nextAssignedName;
492 int32_t nameSize;
494 while (assignedNsNamesList != NULL)
495 {
496 nextAssignedName = assignedNsNamesList->nextAssignedName;
497 /* Free the character array memory first */
498 nameSize = strlen(assignedNsNamesList->assignedName);
499 /* Add one for the NULL character */
500 Rm_osalFree((void *)assignedNsNamesList->assignedName, nameSize+1);
501 /* Free the list element */
502 Rm_osalFree((void *)assignedNsNamesList, sizeof(Rm_AssignedNsNames));
503 assignedNsNamesList = nextAssignedName;
504 }
505 }
507 /**
508 @}
509 */