API naming convention cleanup, switch to strncpy, renamed resourceNode allocatedTo...
[keystone-rtos/rm-lld.git] / src / rm_dtb_util.c
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 external API includes */
47 #include <ti/drv/rm/rm.h>
48 #include <ti/drv/rm/rm_services.h>
50 /* RM internal API includes */
51 #include <ti/drv/rm/include/rm_dtb_utilloc.h>
53 /* RM OSAL layer */
54 #include <rm_osal.h>
56 /* LIBFDT includes */
57 #include <ti/drv/rm/src/libfdt/libfdt.h>
58 #include <ti/drv/rm/src/libfdt/libfdt_env.h>
60 /**********************************************************************
61  ********************Common DTB Parsing Functions**********************
62  **********************************************************************/
64 char rmDtbStartingNode[] = "\0";
66 /* Construct and return a list of ranges as specified in either the Resource
67  * DTB or a Policy DTB */
68 Rm_ResourceRange *dtbUtilCommonExtractRange(const void *dtbDataPtr, int32_t dtbDataLen)
69 {
70     uint32_t         *dtbRangeData = (uint32_t *)dtbDataPtr;
71     Rm_ResourceRange *startRange = NULL;
72     Rm_ResourceRange *newRange = NULL;
73     Rm_ResourceRange *prevRange = NULL;
74     uint32_t i;
75     
76     /* Ranges are stored in the DTB as a list of 32-bit words.  The number of 32-bit
77      * words in the DTB ranges field should be even since ranges are specified in a 
78      * base, lenth format. The DTB gives properties lengths in bytes so the length
79      * returned from the DTB should be a multiple of the number of bytes in two
80      * uint32_ts. */
81     if (dtbDataLen % (2 * sizeof(uint32_t))) {
82         return (NULL);
83     }
85     for (i = 0; i < (dtbDataLen / sizeof(uint32_t)); i+=2) {
86         newRange = (Rm_ResourceRange *) Rm_osalMalloc(sizeof(Rm_ResourceRange));
87         newRange->base = fdt32_to_cpu(dtbRangeData[i]);
88         newRange->length = fdt32_to_cpu(dtbRangeData[i+1]);
89         newRange->nextRange = NULL;
90         
91         if (prevRange == NULL) {
92             startRange = newRange;
93         }
94         else {
95             prevRange->nextRange = newRange;
96         }
97         prevRange = newRange;
98     }
99     return (startRange);
102 /* Function to clean up the memory allocated for a linked list of extracted ranges */
103 void dtbUtilCommonFreeRangeList(Rm_ResourceRange *rangeList)
105     Rm_ResourceRange *nextRange;
106     
107     while (rangeList) {
108         nextRange = rangeList->nextRange;
109         Rm_osalFree((void *)rangeList, sizeof(Rm_ResourceRange));
110         rangeList = nextRange;
111     }
114 /* Construct and return a list of values as specified in the Policy DTB */
115 Rm_ResourceValue *dtbUtilCommonExtractValueList(const void *dtbDataPtr, int32_t dtbDataLen)
117     uint32_t         *dtbRangeData = (uint32_t *)dtbDataPtr;
118     Rm_ResourceValue *startValue = NULL;
119     Rm_ResourceValue *newValue = NULL;
120     Rm_ResourceValue *prevValue = NULL;
121     uint32_t          i;
122     
123     /* Values are stored in the DTB as a list of 32-bit words. The DTB 
124      * gives properties lengths in bytes so the length returned from the DTB 
125      * should be a multiple of the number of bytes a uint32_t. */
126     if (dtbDataLen % sizeof(uint32_t)) {
127         return (NULL);
128     }
129     
130     for (i = 0; i < (dtbDataLen / sizeof(uint32_t)); i++) {
131         newValue = (Rm_ResourceValue *) Rm_osalMalloc(sizeof(Rm_ResourceValue));
132         newValue->value = fdt32_to_cpu(dtbRangeData[i]);
133         newValue->nextValue = NULL;
134         
135         if (prevValue == NULL) {
136             startValue = newValue;
137         }
138         else {
139             prevValue->nextValue = newValue;
140         }
141         prevValue = newValue;
142     }
143     return (startValue);
146 /* Function to clean up the memory allocated for a linked list of extracted values */
147 void dtbUtilCommonFreeValueList (Rm_ResourceValue *valueList)
149     Rm_ResourceValue *nextValue;
150     
151     while (valueList) {
152         nextValue = valueList->nextValue;
153         Rm_osalFree((void *)valueList, sizeof(Rm_ResourceValue));
154         valueList = nextValue;
155     }
158 /**********************************************************************
159  *******Global Resource List DTB Parsing Defines and Functions*********
160  **********************************************************************/
162 /* Resource List Properties - These are the property values used
163  * by an application integrator to define the properties of resources
164  * listed in the Device Global Resource List */
165 char dtbUtilResRangeProp[]        = "resource-range";
166 char dtbUtilResLinuxAliasProp[]   = "linux-dtb-alias";
167 char dtbUtilResNsAssignmentProp[] = "ns-assignment";
169 Rm_ResourcePropType rmDtbUtilResGetPropertyType(const char * propertyName)
171     Rm_ResourcePropType propertyType = Rm_resourcePropType_UNKNOWN;
173     if(strcmp(dtbUtilResRangeProp, propertyName) == 0) {
174         propertyType = Rm_resourcePropType_RESOURCE_RANGE;
175     }
176     else if(strcmp(dtbUtilResLinuxAliasProp, propertyName) == 0) {
177         propertyType = Rm_resourcePropType_RESOURCE_LINUX_ALIAS;
178     }    
179     else if(strcmp(dtbUtilResNsAssignmentProp, propertyName) == 0) {
180         propertyType = Rm_resourcePropType_NSASSIGNMENT;
181     }
182     return (propertyType);
185 Rm_ResourceRange *rmDtbUtilResExtractRange(const void *dtbDataPtr, int32_t dtbDataLen)
187     return(dtbUtilCommonExtractRange(dtbDataPtr, dtbDataLen));
190 void rmDtbUtilResFreeRange(Rm_ResourceRange *rangeList)
192     dtbUtilCommonFreeRangeList(rangeList);
195 Rm_LinuxAlias *rmDtbUtilResExtractLinuxAlias(const void *dtbDataPtr, int32_t dtbDataLen, int32_t *result)
197     uint8_t       *dtbAliasData = (uint8_t *)dtbDataPtr;
198     uint32_t       pathLenBytes;
199     uint32_t       extractedValue;
200     uint8_t       *extractedValueBytePtr;        
201     Rm_LinuxAlias *startAlias = NULL;
202     Rm_LinuxAlias *newAlias = NULL;
203     Rm_LinuxAlias *prevAlias = NULL;
204     uint32_t       numOffsets;
205     int32_t        i = 0;
206     uint16_t       j;
207     
208     /* Linux aliases are stored in the DTB as a list space-separated path node names within
209      * null terminated string.  Following the path string 
210      * will be two or three values specifying the fields in the linux DTB property
211      * that contain the relevant data.  The first value specifies the number of offsets
212      * that follow.  If two field offsets are specified the 
213      * Linux DTB contains a base + length. If   one field offset is specified the 
214      * Linux DTB contains a single value for reservation.  There is no padding between
215      * the path string and the 32-bit offsets.  Therefore the 32-bit offsets may not be on
216      * a 4-byte boundary and must be constructed upon extraction */
217     while(i < dtbDataLen) {
218         newAlias = (Rm_LinuxAlias *) Rm_osalMalloc(sizeof(Rm_LinuxAlias));
219         
220         pathLenBytes = strlen((char *) &dtbAliasData[i]) + 1;
221         newAlias->path = (char *) Rm_osalMalloc(pathLenBytes);
222         strncpy(newAlias->path, ((char *) &dtbAliasData[i]), pathLenBytes);
223         
224         /* Extract 32-bit value specifying number of offsets that follow */
225         i += pathLenBytes;
226         extractedValueBytePtr = (uint8_t *)&extractedValue;
227         for (j = 0; j < sizeof(uint32_t); j++, i++) {
228             extractedValueBytePtr[j] = dtbAliasData[i];
229         }
230         numOffsets = fdt32_to_cpu(extractedValue);
232         if ((numOffsets == 1) || (numOffsets == 2)) {
233             /* Always extract the base value */
234             extractedValueBytePtr = (uint8_t *)&extractedValue;
235             for (j = 0; j < sizeof(uint32_t); j++, i++) {
236                 extractedValueBytePtr[j] = dtbAliasData[i];
237             }            
238             newAlias->baseOffset = fdt32_to_cpu(extractedValue);
240             if (numOffsets == 2) {
241                 for (j = 0; j < sizeof(uint32_t); j++, i++) {
242                     extractedValueBytePtr[j] = dtbAliasData[i];
243                 }
244                 newAlias->lengthOffset = fdt32_to_cpu(extractedValue);
245             }
246             else {
247                 newAlias->lengthOffset = RM_DTB_LINUX_ALIAS_OFFSET_NOT_SET;
248             }            
249             
250             newAlias->nextLinuxAlias = NULL;
251             if (prevAlias == NULL) {
252                 startAlias = newAlias;
253             }
254             else {
255                 prevAlias->nextLinuxAlias = newAlias;
256             }
257             prevAlias = newAlias;
258         }
259         else {
260             Rm_osalFree((void *)newAlias->path, pathLenBytes);
261             Rm_osalFree((void *)newAlias, sizeof(Rm_LinuxAlias));
262             while (startAlias) {
263                 newAlias = startAlias->nextLinuxAlias;
264                 pathLenBytes = strlen(startAlias->path);        
265                 Rm_osalFree((void *)startAlias->path, pathLenBytes + 1);
266                 Rm_osalFree((void *)startAlias, sizeof(Rm_LinuxAlias));
267                 startAlias = newAlias;
268             }   
269             *result = RM_INIT_ERROR_GRL_INVALID_LINUX_ALIAS_FORMAT;
270             return(NULL);
271         }
272     }
273     return (startAlias);
276 /* Function to clean up the memory allocated for a linked list of extracted Linux
277  * aliases. */
278 void rmDtbUtilResFreeLinuxAlias(Rm_LinuxAlias *aliasList)
280     Rm_LinuxAlias *nextAlias;
281     int32_t        pathSize;
282        
283     while (aliasList) {
284         nextAlias = aliasList->nextLinuxAlias;
285         pathSize = strlen(aliasList->path);        
286         Rm_osalFree((void *)aliasList->path, pathSize + 1);
287         Rm_osalFree((void *)aliasList, sizeof(Rm_LinuxAlias));
288         aliasList = nextAlias;
289     }
292 /* Construct and return a list of NameServer assignments as specified in the Resource DTB */
293 Rm_NsAssignment *rmDtbUtilResExtractNsAssignment(const void *dtbDataPtr, int32_t dtbDataLen, int32_t *result)
295     uint8_t         *dtbNsAssignmentData = (uint8_t *)dtbDataPtr;
296     uint32_t         nameLenBytes;
297     uint32_t         extractedValue;
298     uint8_t         *extractedValueBytePtr;        
299     Rm_NsAssignment *startAssignment = NULL;
300     Rm_NsAssignment *newAssignment = NULL;
301     Rm_NsAssignment *prevAssignment = NULL;
302     int32_t          i = 0;
303     uint16_t         j;
304     
305     /* NameServer assignments are stored in the DTB as a null-terminated character
306      * string followed by a 32-bit word containing the value to be assigned to the
307      * name in the string.  There is no padding between the string and the 32-bit 
308      * word.  Therefore the 32-bit word may not be on a 4-byte boundary and must
309      * be constructed upon extraction */
310     while(i < dtbDataLen) {
311         newAssignment = (Rm_NsAssignment *) Rm_osalMalloc(sizeof(Rm_NsAssignment));
312         
313         nameLenBytes = strlen((char *) &dtbNsAssignmentData[i]) + 1;
314         if (nameLenBytes > RM_RESOURCE_NAME_MAX_CHARS) {
315             Rm_osalFree((void *)newAssignment, sizeof(Rm_NsAssignment));
316             while (startAssignment) {
317                 newAssignment = startAssignment->nextNsAssignment;
318                 Rm_osalFree((void *)startAssignment, sizeof(Rm_NsAssignment));
319                 startAssignment = newAssignment;
320             }
321             *result = RM_INIT_ERROR_NS_ASSIGNMENT_NAME_TOO_LONG;
322             return(NULL);
323         }        
324         strncpy(newAssignment->nsName, ((char *) &dtbNsAssignmentData[i]), RM_RESOURCE_NAME_MAX_CHARS);
325         
326         /* Extract 32-bit base value and flip endian */
327         i += nameLenBytes;
328         extractedValueBytePtr = (uint8_t *)&extractedValue;
329         for (j = 0; j < sizeof(uint32_t); j++, i++) {
330             extractedValueBytePtr[j] = dtbNsAssignmentData[i];
331         }
332         newAssignment->resourceBase = fdt32_to_cpu(extractedValue);
334         /* Extract 32-bit length value and flip endian */
335         for (j = 0; j < sizeof(uint32_t); j++, i++) {
336             extractedValueBytePtr[j] = dtbNsAssignmentData[i];
337         }
338         newAssignment->resourceLength = fdt32_to_cpu(extractedValue);
339         
340         newAssignment->nextNsAssignment = NULL;
341         if (prevAssignment == NULL) {
342             startAssignment = newAssignment;
343         }
344         else {
345             prevAssignment->nextNsAssignment = newAssignment;
346         }
347         prevAssignment = newAssignment;
348     }
349     
350     return (startAssignment);
353 /* Function to clean up the memory allocated for a linked list of extracted NameServer
354  * assignments. */
355 void rmDtbUtilResFreeNsAssignmentList (Rm_NsAssignment *nsAssignmentList)
357     Rm_NsAssignment *nextAssignment;
358     
359     while (nsAssignmentList) {
360         nextAssignment = nsAssignmentList->nextNsAssignment;
361         Rm_osalFree((void *)nsAssignmentList, sizeof(Rm_NsAssignment));
362         nsAssignmentList = nextAssignment;
363     }
366 /**********************************************************************
367  ***************Policy DTB Parsing Defines and Functions***************
368  **********************************************************************/
370 /* Policy Properties - These are the property values used
371  * by an application integrator to define the properties of resources
372  * listed in a Resource Manager Policy */
373 char dtbUtilPolicyValidInstances[]      = "valid-instances";
374 char dtbUtilPolicyAssignments[]         = "assignments";
375 char dtbUtilPolicyAllocationSize[]      = "allocation-size";
376 char dtbUtilPolicyAllocationAlignment[] = "allocation-alignment";
378 Rm_PolicyPropType rmDtbUtilPolicyGetPropertyType(const char * propertyName)
380     Rm_PolicyPropType propertyType = Rm_policyPropType_UNKNOWN;
382     if(strcmp(dtbUtilPolicyAssignments, propertyName) == 0) {
383         propertyType = Rm_policyPropType_ASSIGNMENTS;
384     }
385     else if(strcmp(dtbUtilPolicyAllocationSize, propertyName) == 0) {
386         propertyType = Rm_policyPropType_ALLOCATION_SIZE;
387     }
388     else if(strcmp(dtbUtilPolicyAllocationAlignment, propertyName) == 0) {
389         propertyType = Rm_policyPropType_ALLOCATION_ALIGNMENT;
390     }    
391     else if(strcmp(dtbUtilPolicyValidInstances, propertyName) == 0) {
392         propertyType = Rm_policyPropType_VALID_INSTANCES;
393     }       
394     return (propertyType);
397 Rm_PolicyAssignment *rmDtbUtilPolicyExtractAssignments(const void *dtbDataPtr, int32_t dtbDataLen)
399     uint8_t             *dtbAssignmentData = (uint8_t *)dtbDataPtr;
400     uint32_t             permissionsLenBytes;
401     uint32_t             extractedValue;
402     uint8_t             *extractedValueBytePtr;        
403     Rm_PolicyAssignment *startAssignment = NULL;
404     Rm_PolicyAssignment *newAssignment = NULL;
405     Rm_PolicyAssignment *prevAssignment = NULL;
406     int32_t              i = 0;
407     uint16_t             j;
408     
409     /* Policy assignments are stored in the DTB as two 32-bit words containing a 
410      * resource base and length to be assigned the permissions in the defined in
411      * the string that follows.  There is no padding between the 32-bit words and the 
412      * string.  Therefore the 32-bit word may not be on a 4-byte boundary and must
413      * be constructed upon extraction */
414     while(i < dtbDataLen) {
415         newAssignment = (Rm_PolicyAssignment *) Rm_osalMalloc(sizeof(Rm_PolicyAssignment));
417         /* Extract 32-bit resource base value and flip endianness */
418         extractedValueBytePtr = (uint8_t *)&extractedValue;
419         for (j = 0; j < sizeof(uint32_t); j++, i++) {
420             extractedValueBytePtr[j] = dtbAssignmentData[i];
421         }
422         newAssignment->resourceBase = fdt32_to_cpu(extractedValue);
424         /* Extract 32-bit resource length value and flip endianness */
425         for (j = 0; j < sizeof(uint32_t); j++, i++) {
426             extractedValueBytePtr[j] = dtbAssignmentData[i];
427         }
428         newAssignment->resourceLength = fdt32_to_cpu(extractedValue);
430         permissionsLenBytes = strlen((char *) &dtbAssignmentData[i]) + 1;
431         newAssignment->permissionsList = (char *) Rm_osalMalloc(permissionsLenBytes);
432         strncpy(newAssignment->permissionsList, ((char *) &dtbAssignmentData[i]), permissionsLenBytes);
433         i += permissionsLenBytes;
435         newAssignment->nextAssignment = NULL;
436         if (prevAssignment == NULL) {
437             startAssignment = newAssignment;
438         }
439         else {
440             prevAssignment->nextAssignment = newAssignment;
441         }
442         prevAssignment = newAssignment;
443     }
444     return (startAssignment);
447 void rmDtbUtilPolicyFreeAssignments(Rm_PolicyAssignment *assignmentList)
449     Rm_PolicyAssignment *nextAssignment;
450     int32_t              permissionsSize;
451     
452     while (assignmentList) {
453         nextAssignment = assignmentList->nextAssignment;
454         permissionsSize = strlen(assignmentList->permissionsList);
455         Rm_osalFree((void *)assignmentList->permissionsList, permissionsSize+1);
456         Rm_osalFree((void *)assignmentList, sizeof(Rm_PolicyAssignment));
457         assignmentList = nextAssignment;
458     }
461 /* Construct and return a list of allocation sizes as specified in the Policy DTB */
462 Rm_ResourceValue *rmDtbUtilPolicyExtractAllocationSizes(const void *dtbDataPtr, int32_t dtbDataLen)
464     return(dtbUtilCommonExtractValueList(dtbDataPtr, dtbDataLen));
467 /* Function to clean up the memory allocated for a linked list of extracted allocation sizes */
468 void rmDtbUtilPolicyFreeAllocationSizes (Rm_ResourceValue *allocationSizeList)
470     dtbUtilCommonFreeValueList(allocationSizeList);
473 /* Construct and return a list of allocation alignments as specified in the Policy DTB */
474 Rm_ResourceValue *rmDtbUtilPolicyExtractResourceAlignments(const void *dtbDataPtr, int32_t dtbDataLen)
476     return(dtbUtilCommonExtractValueList(dtbDataPtr, dtbDataLen));
479 /* Function to clean up the memory allocated for a linked list of extracted allocation alignments */
480 void rmDtbUtilPolicyFreeResourceAlignments (Rm_ResourceValue *alignmentList)
482     dtbUtilCommonFreeValueList(alignmentList);
485 Rm_PolicyValidInst *rmDtbUtilPolicyExtractValidInstances(const void *dtbDataPtr, int32_t dtbDataLen,
486                                                          int32_t *result)
488     uint8_t            *dtbValidInstData = (uint8_t *)dtbDataPtr;
489     uint32_t            instLenBytes;       
490     Rm_PolicyValidInst *startInst = NULL;
491     Rm_PolicyValidInst *newInst = NULL;
492     Rm_PolicyValidInst *prevInst = NULL;
493     int32_t             i = 0;
494     
495     /* Valid RM instances are stored in the DTB as a list of null-terminated character
496      * strings. */
497     while(i < dtbDataLen) {
498         newInst = (Rm_PolicyValidInst *) Rm_osalMalloc(sizeof(Rm_PolicyValidInst));
500         instLenBytes = strlen((char *) &dtbValidInstData[i]) + 1;
501         if (instLenBytes > RM_INSTANCE_NAME_MAX_CHARS) {
502             Rm_osalFree((void *)newInst, sizeof(Rm_PolicyValidInst));
503             while (startInst) {
504                 newInst = startInst->nextValidInst;
505                 Rm_osalFree((void *)startInst, sizeof(Rm_PolicyValidInst));
506                 startInst = newInst;
507             }
508             *result = RM_INIT_ERROR_POLICY_VALID_INSTANCE_NAME_TOO_LONG;
509             return(NULL);
510         }
511         strncpy(newInst->instName, ((char *) &dtbValidInstData[i]), instLenBytes);
512         
513         i += instLenBytes;
515         newInst->nextValidInst = NULL;
517         if (prevInst == NULL) {
518             startInst = newInst;
519         }
520         else {
521             prevInst->nextValidInst = newInst;
522         }
523         prevInst = newInst;
524     }
525     return (startInst);
528 void rmDtbUtilPolicyFreeValidInstances (Rm_PolicyValidInst *validInstList)
530     Rm_PolicyValidInst *nextInst;
531     
532     while (validInstList) {
533         nextInst = validInstList->nextValidInst;
534         Rm_osalFree((void *)validInstList, sizeof(Rm_PolicyValidInst));
535         validInstList = nextInst;
536     }
539 /**********************************************************************
540  ****************Linux DTB Parsing Defines and Functions***************
541  **********************************************************************/
543 Rm_LinuxValueRange *rmDtbUtilLinuxExtractValues(const void *dtbDataPtr, int32_t dtbDataLen)
545     uint32_t           *dtbValueData = (uint32_t *)dtbDataPtr;
546     Rm_LinuxValueRange *startValue = NULL;
547     Rm_LinuxValueRange *newValue = NULL;
548     Rm_LinuxValueRange *prevValue = NULL;
549     uint32_t            i;
550     
551     /* Values are stored in the Linux DTB as a list of 32-bit words.  The number of 32-bit
552      * words in the value field can differ.  depending on the number of values specified. */
553     for (i = 0; i < (dtbDataLen / sizeof(uint32_t)); i++) {
554         newValue = (Rm_LinuxValueRange *) Rm_osalMalloc(sizeof(Rm_LinuxValueRange));
555         /* Endianness of extracted value must be flipped */
556         newValue->value = fdt32_to_cpu(dtbValueData[i]);
557         newValue->nextValue = NULL;
558         
559         if (prevValue == NULL) {
560             startValue = newValue;
561         }
562         else {
563             prevValue->nextValue = newValue;
564         }
565         prevValue = newValue;
566     }
567     return (startValue);
570 void rmDtbUtilLinuxFreeValues(Rm_LinuxValueRange *valueList)
572     Rm_LinuxValueRange *nextValue;
573     
574     while (valueList) {
575         nextValue = valueList->nextValue;
576         Rm_osalFree((void *)valueList, sizeof(Rm_LinuxValueRange));
577         valueList = nextValue;
578     }
581 /**
582 @}
583 */