Adding policy checking feature on RM Server
[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 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 rmDtbStartingNode[] = "\0";
61  
62 char *Rm_commonExtractName(const void *dtbDataPtr, int32_t dtbDataLen)
63 {
64     char *resourceName = NULL;
65     
66     resourceName = (char *) Rm_osalMalloc(dtbDataLen);
68     /* The resource name is stored as a null terminated string in the DTB
69      * so it's just a straightforward string copy operation to a local
70      * buffer to extract it. */
71     strcpy(resourceName, (char *)dtbDataPtr);
73     return(resourceName);
74 }
76 /* Free memory that was allocated to extract a name property string */
77 void Rm_commonFreeName(char *resourceName)
78 {
79     int32_t nameSize;
80     
81     /* Free the character array memory */
82     nameSize = strlen(resourceName);
83     /* Add one for the NULL character */
84     Rm_osalFree((void *)resourceName, nameSize+1);
85 }
87 /* Construct and return a list of ranges as specified in either the Resource
88  * DTB or a Policy DTB */
89 Rm_ResourceRange *Rm_commonExtractRange(const void *dtbDataPtr, int32_t dtbDataLen)
90 {
91     uint32_t *dtbRangeData = (uint32_t *)dtbDataPtr;
92     Rm_ResourceRange *startRange = NULL;
93     Rm_ResourceRange *newRange = NULL;
94     Rm_ResourceRange *prevRange = NULL;
95     uint32_t i;
96     
97     /* Ranges are stored in the DTB as a list of 32-bit words.  The number of 32-bit
98      * words in the DTB ranges field should be even since ranges are specified in a 
99      * base, lenth format. The DTB gives properties lengths in bytes so the length
100      * returned from the DTB should be a multiple of the number of bytes in two
101      * uint32_ts. */
102     if (dtbDataLen % (2 * sizeof(uint32_t)))
103     {
104         /* Return NULL if there are an odd number of range values */
105         return (NULL);
106     }
108     /* Extract the range data from the DTB */
109     for (i = 0; i < (dtbDataLen / sizeof(uint32_t)); i+=2)
110     {
111         /* Creat a new range entry */
112         newRange = (Rm_ResourceRange *) Rm_osalMalloc(sizeof(Rm_ResourceRange));
113         /* Populate the new range entry.  The endianness of the value extracted must
114          * be flipped */
115         newRange->base = fdt32_to_cpu(dtbRangeData[i]);
116         newRange->length = fdt32_to_cpu(dtbRangeData[i+1]);
117         newRange->nextRange = NULL;
118         
119         /* Range linked list pointer accounting */
120         if (prevRange == NULL)
121         {
122             /* Save the first entry so it can be returned */
123             startRange = newRange;
124         }
125         else
126         {
127             prevRange->nextRange = (void *) newRange;
128         }
130         prevRange = newRange;
131     }
133     /* Return a pointer to the start of the range list */
134     return (startRange);
137 /* Function to clean up the memory allocated for a linked list of extracted ranges */
138 void Rm_commonFreeRangeList(Rm_ResourceRange *rangeList)
140     Rm_ResourceRange *nextRange;
141     
142     while (rangeList != NULL)
143     {
144         nextRange = rangeList->nextRange;
145         Rm_osalFree((void *)rangeList, sizeof(Rm_ResourceRange));
146         rangeList = nextRange;
147     }
150 /* Construct and return a list of values as specified in the Policy DTB */
151 Rm_ResourceValue *Rm_commonExtractValueList(const void *dtbDataPtr, int32_t dtbDataLen)
153     uint32_t *dtbRangeData = (uint32_t *)dtbDataPtr;
154     Rm_ResourceValue *startValue = NULL;
155     Rm_ResourceValue *newValue = NULL;
156     Rm_ResourceValue *prevValue = NULL;
157     uint32_t i;
158     
159     /* Values are stored in the DTB as a list of 32-bit words. The DTB 
160      * gives properties lengths in bytes so the length returned from the DTB 
161      * should be a multiple of the number of bytes a uint32_t. */
162     if (dtbDataLen % sizeof(uint32_t))
163     {
164         return (NULL);
165     }
167     /* Extract the value data from the DTB */
168     for (i = 0; i < (dtbDataLen / sizeof(uint32_t)); i++)
169     {
170         /* Creat a new allocation size entry */
171         newValue = (Rm_ResourceValue *) Rm_osalMalloc(sizeof(Rm_ResourceValue));
172         /* Populate the new allocation size entry.  The endianness of the value extracted must
173          * be flipped */
174         newValue->value = fdt32_to_cpu(dtbRangeData[i]);
175         newValue->nextValue = NULL;
176         
177         /* Resource value linked list pointer accounting */
178         if (prevValue == NULL)
179         {
180             /* Save the first entry so it can be returned */
181             startValue = newValue;
182         }
183         else
184         {
185             prevValue->nextValue = (void *) newValue;
186         }
188         prevValue = newValue;
189     }
191     /* Return a pointer to the start of the resource value list */
192     return (startValue);
195 /* Function to clean up the memory allocated for a linked list of extracted values */
196 void Rm_commonFreeValueList (Rm_ResourceValue *valueList)
198     Rm_ResourceValue *nextValue;
199     
200     while (valueList != NULL)
201     {
202         nextValue = valueList->nextValue;
203         Rm_osalFree((void *)valueList, sizeof(Rm_ResourceValue));
204         valueList = nextValue;
205     }
209 /**********************************************************************
210  ***********Resource List DTB Parsing Defines and Functions************
211  **********************************************************************/
213 /* Resource List Properties - These are the property values used
214  * by an application integrator to define the properties of resources
215  * listed in the Device Resource List */
216 char rmResourceDeviceNameProp[] = "device-name";
217 char rmResourceRangeProp[] = "resource-range";
218 char rmResourceLinuxAliasProp[] = "linux-dtb-alias";
219 char rmResourceNsAssignmentProp[] = "ns-assignment";
221 Rm_ResourcePropType Rm_resourceGetPropertyType(const char * propertyName)
223     Rm_ResourcePropType propertyType = Rm_resourcePropType_UNKNOWN;
225     if(strcmp(rmResourceDeviceNameProp, propertyName) == 0)
226     {
227         propertyType = Rm_resourcePropType_DEVICE_NAME;
228     }    
229     else if(strcmp(rmResourceRangeProp, propertyName) == 0)
230     {
231         propertyType = Rm_resourcePropType_RESOURCE_RANGE;
232     }
233     else if(strcmp(rmResourceLinuxAliasProp, propertyName) == 0)
234     {
235         propertyType = Rm_resourcePropType_RESOURCE_LINUX_ALIAS;
236     }    
237     else if(strcmp(rmResourceNsAssignmentProp, propertyName) == 0)
238     {
239         propertyType = Rm_resourcePropType_NSASSIGNMENT;
240     }
242     return (propertyType);
245 char *Rm_resourceExtractDeviceName(const void *dtbDataPtr, int32_t dtbDataLen)
247     return(Rm_commonExtractName(dtbDataPtr, dtbDataLen));
250 void Rm_resourceFreeDeviceName(char *deviceName)
252     Rm_commonFreeName(deviceName);
255 Rm_ResourceRange *Rm_resourceExtractRange(const void *dtbDataPtr, int32_t dtbDataLen)
257     return(Rm_commonExtractRange(dtbDataPtr, dtbDataLen));
260 void Rm_resourceFreeRange(Rm_ResourceRange *rangeList)
262     Rm_commonFreeRangeList(rangeList);
265 Rm_LinuxAlias *Rm_resourceExtractLinuxAlias(const void *dtbDataPtr, int32_t dtbDataLen)
267     uint8_t *dtbAliasData = (uint8_t *)dtbDataPtr;
268     uint32_t pathLenBytes;
269     uint32_t extractedValue;
270     uint8_t *extractedValueBytePtr;        
271     Rm_LinuxAlias *startAlias = NULL;
272     Rm_LinuxAlias *newAlias = NULL;
273     Rm_LinuxAlias *prevAlias = NULL;
274     uint32_t numOffsets;
275     int32_t i = 0;
276     uint16_t j;
277     
278     /* Linux aliases are stored in the DTB as a list space-separated path node names within
279      * null terminated string.  Following the path string 
280      * will be two or three values specifying the fields in the linux DTB property
281      * that contain the relevant data.  The first value specifies the number of offsets
282      * that follow.  If two field offsets are specified the 
283      * Linux DTB contains a base + length. If   one field offset is specified the 
284      * Linux DTB contains a single value for reservation.  There is no padding between
285      * the path string and the 32-bit offsets.  Therefore the 32-bit offsets may not be on
286      * a 4-byte boundary and must be constructed upon extraction */
288     /* Extract the alias data from the DTB */
289     while(i < dtbDataLen)
290     {
291         /* Creat a new alias entry */
292         newAlias = (Rm_LinuxAlias *) Rm_osalMalloc(sizeof(Rm_LinuxAlias));
293         
294         /* Populate the new alias entry.  Allocate a buffer for the path
295          * string (adding one for the null character). */
296         pathLenBytes = strlen((char *) &dtbAliasData[i]) + 1;
297         newAlias->path = (char *) Rm_osalMalloc(pathLenBytes);
298         strcpy(newAlias->path, ((char *) &dtbAliasData[i]));
299         
300         /* Extract the 32-bit value specifying the number of offsets that follow */
301         i += pathLenBytes;
302         extractedValueBytePtr = (uint8_t *)&extractedValue;
303         for (j = 0; j < sizeof(uint32_t); j++, i++)
304         {
305             extractedValueBytePtr[j] = dtbAliasData[i];
306         }
307         /* flip the endianness */
308         numOffsets = fdt32_to_cpu(extractedValue);
310         /* numOffsets should always be either 1 or 2 */
311         if ((numOffsets == 1) || (numOffsets == 2))
312         {
313             /* Always extract the base value */
314             extractedValueBytePtr = (uint8_t *)&extractedValue;
315             for (j = 0; j < sizeof(uint32_t); j++, i++)
316             {
317                 extractedValueBytePtr[j] = dtbAliasData[i];
318             }            
319             newAlias->baseOffset = fdt32_to_cpu(extractedValue);
321             if (numOffsets == 2)
322             {
323                 /* Extract the 32-bit length value if two offsets were specified */
324                 for (j = 0; j < sizeof(uint32_t); j++, i++)
325                 {
326                     extractedValueBytePtr[j] = dtbAliasData[i];
327                 }
328                 /* flip the endianness */
329                 newAlias->lengthOffset = fdt32_to_cpu(extractedValue);
330             }
331             else
332             {
333                 newAlias->lengthOffset = RM_DTB_LINUX_ALIAS_OFFSET_NOT_SET;
334             }            
335             
336             newAlias->nextLinuxAlias = NULL;
337             
338             if (prevAlias == NULL)
339             {
340                 /* Save the first entry so it can be returned */
341                 startAlias = newAlias;
342             }
343             else
344             {
345                 prevAlias->nextLinuxAlias = (void *) newAlias;
346             }
347             prevAlias = newAlias;
348         }
349         else
350         {
351             /* Return NULL */
352             startAlias = NULL;
353             break;
354         }
355     }
357     /* Return a pointer to the start of the NameServer assignment list */
358     return (startAlias);
361 /* Function to clean up the memory allocated for a linked list of extracted Linux
362  * aliases. */
363 void Rm_resourceFreeLinuxAlias(Rm_LinuxAlias *aliasList)
365     Rm_LinuxAlias *nextAlias;
366     int32_t pathSize;
367        
368     while (aliasList != NULL)
369     {
370         nextAlias = aliasList->nextLinuxAlias;
371         /* Free the path string memory first */
372         pathSize = strlen(aliasList->path);        
373         Rm_osalFree((void *)aliasList->path, pathSize + 1);
374         /* Free the list element */
375         Rm_osalFree((void *)aliasList, sizeof(Rm_LinuxAlias));
376         aliasList = nextAlias;
377     }
380 /* Construct and return a list of NameServer assignments as specified in the Resource DTB */
381 Rm_NsAssignment *Rm_resourceExtractNsAssignment(const void *dtbDataPtr, int32_t dtbDataLen)
383     uint8_t *dtbNsAssignmentData = (uint8_t *)dtbDataPtr;
384     uint32_t nameLenBytes;
385     uint32_t extractedValue;
386     uint8_t *extractedValueBytePtr;        
387     Rm_NsAssignment *startAssignment = NULL;
388     Rm_NsAssignment *newAssignment = NULL;
389     Rm_NsAssignment *prevAssignment = NULL;
390     int8_t i = 0;
391     uint16_t j;
392     
393     /* NameServer assignments are stored in the DTB as a null-terminated character
394      * string followed by a 32-bit word containing the value to be assigned to the
395      * name in the string.  There is no padding between the string and the 32-bit 
396      * word.  Therefore the 32-bit word may not be on a 4-byte boundary and must
397      * be constructed upon extraction */
399     /* Extract the NameServer assignment data from the DTB */
400     while(i < dtbDataLen)
401     {
402         /* Creat a new NameServer assignment entry */
403         newAssignment = (Rm_NsAssignment *) Rm_osalMalloc(sizeof(Rm_NsAssignment));
404         
405         /* Populate the new assignment entry.  Allocate a buffer for the assignment
406          * name string (adding one for the null character). */
407         nameLenBytes = strlen((char *) &dtbNsAssignmentData[i]) + 1;
408         newAssignment->nsName = (char *) Rm_osalMalloc(nameLenBytes);
409         strcpy(newAssignment->nsName, ((char *) &dtbNsAssignmentData[i]));
410         
411         /* Extract the 32-bit base value */
412         i += nameLenBytes;
413         extractedValueBytePtr = (uint8_t *)&extractedValue;
414         for (j = 0; j < sizeof(uint32_t); j++, i++)
415         {
416             extractedValueBytePtr[j] = dtbNsAssignmentData[i];
417         }
418         /* flip the endianness */
419         newAssignment->resourceBase = fdt32_to_cpu(extractedValue);
421         /* Extract the 32-bit length value */
422         for (j = 0; j < sizeof(uint32_t); j++, i++)
423         {
424             extractedValueBytePtr[j] = dtbNsAssignmentData[i];
425         }
426         /* flip the endianness */
427         newAssignment->resourceLength = fdt32_to_cpu(extractedValue);
429         newAssignment->nextNsAssignment = NULL;
431         if (prevAssignment == NULL)
432         {
433             /* Save the first entry so it can be returned */
434             startAssignment = newAssignment;
435         }
436         else
437         {
438             prevAssignment->nextNsAssignment = (void *) newAssignment;
439         }
440         prevAssignment = newAssignment;
441     }
443     /* Return a pointer to the start of the NameServer assignment list */
444     return (startAssignment);
447 /* Function to clean up the memory allocated for a linked list of extracted NameServer
448  * assignments. */
449 void Rm_resourceFreeNsAssignmentList (Rm_NsAssignment *nsAssignmentList)
451     Rm_NsAssignment *nextAssignment;
452     int32_t nameSize;
453     
454     while (nsAssignmentList != NULL)
455     {
456         nextAssignment = nsAssignmentList->nextNsAssignment;
457         /* Free the character array memory first */
458         nameSize = strlen(nsAssignmentList->nsName);
459         /* Add one for the NULL character */
460         Rm_osalFree((void *)nsAssignmentList->nsName, nameSize+1);
461         /* Free the list element */
462         Rm_osalFree((void *)nsAssignmentList, sizeof(Rm_NsAssignment));
463         nsAssignmentList = nextAssignment;
464     }
467 /**********************************************************************
468  ***************Policy DTB Parsing Defines and Functions***************
469  **********************************************************************/
471 /* Policy Properties - These are the property values used
472  * by an application integrator to define the properties of resources
473  * listed in a Resource Manager Policy */
474 char rmPolicyAssignedRanges[] = "assigned-ranges";
475 char rmPolicyAllocationSizes[] = "allocation-sizes";
476 char rmPolicyAssignedNames[] = "assigned-names";
477 char rmPolicyAllocationAlignments[] = "allocation-alignments";
479 Rm_PolicyPropType Rm_policyGetPropertyType(const char * propertyName)
481     Rm_PolicyPropType propertyType = Rm_policyPropType_UNKNOWN;
483     if(strcmp(rmPolicyAssignedRanges, propertyName) == 0)
484     {
485         propertyType = Rm_policyPropType_ASSIGNED_RANGES;
486     }
487     else if(strcmp(rmPolicyAllocationSizes, propertyName) == 0)
488     {
489         propertyType = Rm_policyPropType_ALLOCATION_SIZES;
490     }
491     else if(strcmp(rmPolicyAssignedNames, propertyName) == 0)
492     {
493         propertyType = Rm_policyPropType_ASSIGNED_NAMES;
494     }
495     else if(strcmp(rmPolicyAllocationAlignments, propertyName) == 0)
496     {
497         propertyType = Rm_policyPropType_ALLOCATION_ALIGNMENTS;
498     }    
500     return (propertyType);
503 Rm_ResourceRange *Rm_policyExtractAssignedRanges(const void *dtbDataPtr, int32_t dtbDataLen)
505     return(Rm_commonExtractRange(dtbDataPtr, dtbDataLen));
508 void Rm_policyFreeAssignedRanges(Rm_ResourceRange *rangeList)
510     Rm_commonFreeRangeList(rangeList);
513 /* Construct and return a list of allocation sizes as specified in the Policy DTB */
514 Rm_ResourceValue *Rm_policyExtractAllocationSizes(const void *dtbDataPtr, int32_t dtbDataLen)
516     return(Rm_commonExtractValueList(dtbDataPtr, dtbDataLen));
519 /* Function to clean up the memory allocated for a linked list of extracted allocation sizes */
520 void Rm_policyFreeAllocationSizes (Rm_ResourceValue *allocationSizeList)
522     Rm_commonFreeValueList(allocationSizeList);
525 /* Construct and return a list of assigned NameServer names as specified in the Policy DTB */
526 Rm_AssignedNsNames *Rm_policyExtractAssignedNames(const void *dtbDataPtr, int32_t dtbDataLen)
528     uint8_t *dtbAssignedNsNamesData = (uint8_t *)dtbDataPtr;
529     uint32_t nameLenBytes;        
530     Rm_AssignedNsNames *startAssignedName = NULL;
531     Rm_AssignedNsNames *newAssignedName = NULL;
532     Rm_AssignedNsNames *prevAssignedName = NULL;
533     int8_t i = 0;
534     
535     /* Assigned NameServer names are stored in the DTB as a block of null-terminated 
536      * character strings.  There is no padding between the strings. */
538     /* Extract the assigned NameServer name data from the DTB */
539     while(i < dtbDataLen)
540     {
541         /* Creat a new assigned NameServer name entry */
542         newAssignedName = (Rm_AssignedNsNames *) Rm_osalMalloc(sizeof(Rm_AssignedNsNames));
543         
544         /* Populate the new assigned name entry.  Allocate a buffer for the assigned
545          * name string (adding one for the null character). */
546         nameLenBytes = strlen((char *) &dtbAssignedNsNamesData[i]) + 1;
547         newAssignedName->assignedName = (char *) Rm_osalMalloc(nameLenBytes);
548         strcpy(newAssignedName->assignedName, ((char *) &dtbAssignedNsNamesData[i]));
550         newAssignedName->nextAssignedName = NULL;
552         if (prevAssignedName == NULL)
553         {
554             /* Save the first entry so it can be returned */
555             startAssignedName = newAssignedName;
556         }
557         else
558         {
559             prevAssignedName->nextAssignedName = (void *) newAssignedName;
560         }
561         prevAssignedName = newAssignedName;
562     }
564     /* Return a pointer to the start of the assigned NameServer names list */
565     return (startAssignedName);
568 /* Function to clean up the memory allocated for a linked list of extracted 
569  * assigned NameServer names. */
570 void Rm_policyFreeAssignmentNames (Rm_AssignedNsNames *assignedNsNamesList)
572     Rm_AssignedNsNames *nextAssignedName;
573     int32_t nameSize;
574     
575     while (assignedNsNamesList != NULL)
576     {
577         nextAssignedName = assignedNsNamesList->nextAssignedName;
578         /* Free the character array memory first */
579         nameSize = strlen(assignedNsNamesList->assignedName);
580         /* Add one for the NULL character */
581         Rm_osalFree((void *)assignedNsNamesList->assignedName, nameSize+1);
582         /* Free the list element */
583         Rm_osalFree((void *)assignedNsNamesList, sizeof(Rm_AssignedNsNames));
584         assignedNsNamesList = nextAssignedName;
585     }
588 /* Construct and return a list of allocation alignments as specified in the Policy DTB */
589 Rm_ResourceValue *Rm_policyExtractResourceAlignments(const void *dtbDataPtr, int32_t dtbDataLen)
591     return(Rm_commonExtractValueList(dtbDataPtr, dtbDataLen));
594 /* Function to clean up the memory allocated for a linked list of extracted allocation alignments */
595 void Rm_policyFreeResourceAlignments (Rm_ResourceValue *alignmentList)
597     Rm_commonFreeValueList(alignmentList);
600 /**********************************************************************
601  ****************Linux DTB Parsing Defines and Functions***************
602  **********************************************************************/
604 Rm_LinuxValueRange *Rm_linuxExtractValues(const void *dtbDataPtr, int32_t dtbDataLen)
606     uint32_t *dtbValueData = (uint32_t *)dtbDataPtr;
607     Rm_LinuxValueRange *startValue = NULL;
608     Rm_LinuxValueRange *newValue = NULL;
609     Rm_LinuxValueRange *prevValue = NULL;
610     uint32_t i;
611     
612     /* Values are stored in the Linux DTB as a list of 32-bit words.  The number of 32-bit
613      * words in the value field can differ.  depending on the number of values specified. */
615     /* Extract the value data from the Linux DTB */
616     for (i = 0; i < (dtbDataLen / sizeof(uint32_t)); i++)
617     {
618         /* Creat a new value entry */
619         newValue = (Rm_LinuxValueRange *) Rm_osalMalloc(sizeof(Rm_LinuxValueRange));
620         /* Populate the new value entry.  The endianness of the value extracted must
621          * be flipped */
622         newValue->value = fdt32_to_cpu(dtbValueData[i]);
623         newValue->nextValue = NULL;
624         
625         /* Value linked list pointer accounting */
626         if (prevValue == NULL)
627         {
628             /* Save the first entry so it can be returned */
629             startValue = newValue;
630         }
631         else
632         {
633             prevValue->nextValue = (void *) newValue;
634         }
636         prevValue = newValue;
637     }
639     /* Return a pointer to the start of the value list */
640     return (startValue);
643 void Rm_linuxFreeValues(Rm_LinuxValueRange *valueList)
645     Rm_LinuxValueRange *nextValue;
646     
647     while (valueList != NULL)
648     {
649         nextValue = valueList->nextValue;
650         Rm_osalFree((void *)valueList, sizeof(Rm_LinuxValueRange));
651         valueList = nextValue;
652     }
655 /**
656 @}
657 */