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-2013, 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 external API includes */
44 #include <ti/drv/rm/rm.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 const char rmDtbStartingNode[] = "\0";
62 /* Construct and return a list of ranges as specified in either the Resource
63 * DTB or a Policy DTB */
64 Rm_ResourceRange *dtbUtilCommonExtractRange(const void *dtbDataPtr, int32_t dtbDataLen)
65 {
66 uint32_t *dtbRangeData = (uint32_t *)dtbDataPtr;
67 Rm_ResourceRange *startRange = NULL;
68 Rm_ResourceRange *newRange = NULL;
69 Rm_ResourceRange *prevRange = NULL;
70 uint32_t i;
72 /* Ranges are stored in the DTB as a list of 32-bit words. The number of 32-bit
73 * words in the DTB ranges field should be even since ranges are specified in a
74 * base, lenth format. The DTB gives properties lengths in bytes so the length
75 * returned from the DTB should be a multiple of the number of bytes in two
76 * uint32_ts. */
77 if (dtbDataLen % (2 * sizeof(uint32_t))) {
78 return (NULL);
79 }
81 for (i = 0; i < (dtbDataLen / sizeof(uint32_t)); i+=2) {
82 newRange = (Rm_ResourceRange *) Rm_osalMalloc(sizeof(Rm_ResourceRange));
83 newRange->base = fdt32_to_cpu(dtbRangeData[i]);
84 newRange->length = fdt32_to_cpu(dtbRangeData[i+1]);
85 newRange->nextRange = NULL;
87 if (prevRange == NULL) {
88 startRange = newRange;
89 }
90 else {
91 prevRange->nextRange = newRange;
92 }
93 prevRange = newRange;
94 }
95 return (startRange);
96 }
98 /* Function to clean up the memory allocated for a linked list of extracted ranges */
99 void dtbUtilCommonFreeRangeList(Rm_ResourceRange *rangeList)
100 {
101 Rm_ResourceRange *nextRange;
103 while (rangeList) {
104 nextRange = rangeList->nextRange;
105 Rm_osalFree((void *)rangeList, sizeof(Rm_ResourceRange));
106 rangeList = nextRange;
107 }
108 }
110 /* Construct and return a list of values as specified in the Policy DTB */
111 Rm_ResourceValue *dtbUtilCommonExtractValueList(const void *dtbDataPtr, int32_t dtbDataLen)
112 {
113 uint32_t *dtbRangeData = (uint32_t *)dtbDataPtr;
114 Rm_ResourceValue *startValue = NULL;
115 Rm_ResourceValue *newValue = NULL;
116 Rm_ResourceValue *prevValue = NULL;
117 uint32_t i;
119 /* Values are stored in the DTB as a list of 32-bit words. The DTB
120 * gives properties lengths in bytes so the length returned from the DTB
121 * should be a multiple of the number of bytes a uint32_t. */
122 if (dtbDataLen % sizeof(uint32_t)) {
123 return (NULL);
124 }
126 for (i = 0; i < (dtbDataLen / sizeof(uint32_t)); i++) {
127 newValue = (Rm_ResourceValue *) Rm_osalMalloc(sizeof(Rm_ResourceValue));
128 newValue->value = fdt32_to_cpu(dtbRangeData[i]);
129 newValue->nextValue = NULL;
131 if (prevValue == NULL) {
132 startValue = newValue;
133 }
134 else {
135 prevValue->nextValue = newValue;
136 }
137 prevValue = newValue;
138 }
139 return (startValue);
140 }
142 /* Function to clean up the memory allocated for a linked list of extracted values */
143 void dtbUtilCommonFreeValueList (Rm_ResourceValue *valueList)
144 {
145 Rm_ResourceValue *nextValue;
147 while (valueList) {
148 nextValue = valueList->nextValue;
149 Rm_osalFree((void *)valueList, sizeof(Rm_ResourceValue));
150 valueList = nextValue;
151 }
152 }
154 /**********************************************************************
155 *******Global Resource List DTB Parsing Defines and Functions*********
156 **********************************************************************/
158 /* Resource List Properties - These are the property values used
159 * by an application integrator to define the properties of resources
160 * listed in the Device Global Resource List */
161 char dtbUtilResRangeProp[] = "resource-range";
162 char dtbUtilResLinuxAliasProp[] = "linux-dtb-alias";
163 char dtbUtilResNsAssignmentProp[] = "ns-assignment";
165 Rm_ResourcePropType rmDtbUtilResGetPropertyType(const char * propertyName)
166 {
167 Rm_ResourcePropType propertyType = Rm_resourcePropType_UNKNOWN;
169 if(strcmp(dtbUtilResRangeProp, propertyName) == 0) {
170 propertyType = Rm_resourcePropType_RESOURCE_RANGE;
171 }
172 else if(strcmp(dtbUtilResLinuxAliasProp, propertyName) == 0) {
173 propertyType = Rm_resourcePropType_RESOURCE_LINUX_ALIAS;
174 }
175 else if(strcmp(dtbUtilResNsAssignmentProp, propertyName) == 0) {
176 propertyType = Rm_resourcePropType_NSASSIGNMENT;
177 }
178 return (propertyType);
179 }
181 Rm_ResourceRange *rmDtbUtilResExtractRange(const void *dtbDataPtr, int32_t dtbDataLen)
182 {
183 return(dtbUtilCommonExtractRange(dtbDataPtr, dtbDataLen));
184 }
186 void rmDtbUtilResFreeRange(Rm_ResourceRange *rangeList)
187 {
188 dtbUtilCommonFreeRangeList(rangeList);
189 }
191 Rm_LinuxAlias *rmDtbUtilResExtractLinuxAlias(const void *dtbDataPtr, int32_t dtbDataLen, int32_t *result)
192 {
193 uint8_t *dtbAliasData = (uint8_t *)dtbDataPtr;
194 uint32_t pathLenBytes;
195 uint32_t extractedValue;
196 uint8_t *extractedValueBytePtr;
197 Rm_LinuxAlias *startAlias = NULL;
198 Rm_LinuxAlias *newAlias = NULL;
199 Rm_LinuxAlias *prevAlias = NULL;
200 uint32_t numOffsets;
201 int32_t i = 0;
202 uint16_t j;
204 /* Linux aliases are stored in the DTB as a list space-separated path node names within
205 * null terminated string. Following the path string
206 * will be two or three values specifying the fields in the linux DTB property
207 * that contain the relevant data. The first value specifies the number of offsets
208 * that follow. If two field offsets are specified the
209 * Linux DTB contains a base + length. If one field offset is specified the
210 * Linux DTB contains a single value for reservation. There is no padding between
211 * the path string and the 32-bit offsets. Therefore the 32-bit offsets may not be on
212 * a 4-byte boundary and must be constructed upon extraction */
213 while(i < dtbDataLen) {
214 newAlias = (Rm_LinuxAlias *) Rm_osalMalloc(sizeof(Rm_LinuxAlias));
216 pathLenBytes = strlen((char *) &dtbAliasData[i]) + 1;
217 newAlias->path = (char *) Rm_osalMalloc(pathLenBytes);
218 strncpy(newAlias->path, ((char *) &dtbAliasData[i]), pathLenBytes);
220 /* Extract 32-bit value specifying number of offsets that follow */
221 i += pathLenBytes;
222 extractedValueBytePtr = (uint8_t *)&extractedValue;
223 for (j = 0; j < sizeof(uint32_t); j++, i++) {
224 extractedValueBytePtr[j] = dtbAliasData[i];
225 }
226 numOffsets = fdt32_to_cpu(extractedValue);
228 if ((numOffsets == 1) || (numOffsets == 2)) {
229 /* Always extract the base value */
230 extractedValueBytePtr = (uint8_t *)&extractedValue;
231 for (j = 0; j < sizeof(uint32_t); j++, i++) {
232 extractedValueBytePtr[j] = dtbAliasData[i];
233 }
234 newAlias->baseOffset = fdt32_to_cpu(extractedValue);
236 if (numOffsets == 2) {
237 for (j = 0; j < sizeof(uint32_t); j++, i++) {
238 extractedValueBytePtr[j] = dtbAliasData[i];
239 }
240 newAlias->lengthOffset = fdt32_to_cpu(extractedValue);
241 }
242 else {
243 newAlias->lengthOffset = RM_DTB_LINUX_ALIAS_OFFSET_NOT_SET;
244 }
246 newAlias->nextLinuxAlias = NULL;
247 if (prevAlias == NULL) {
248 startAlias = newAlias;
249 }
250 else {
251 prevAlias->nextLinuxAlias = newAlias;
252 }
253 prevAlias = newAlias;
254 }
255 else {
256 Rm_osalFree((void *)newAlias->path, pathLenBytes);
257 Rm_osalFree((void *)newAlias, sizeof(Rm_LinuxAlias));
258 while (startAlias) {
259 newAlias = startAlias->nextLinuxAlias;
260 pathLenBytes = strlen(startAlias->path);
261 Rm_osalFree((void *)startAlias->path, pathLenBytes + 1);
262 Rm_osalFree((void *)startAlias, sizeof(Rm_LinuxAlias));
263 startAlias = newAlias;
264 }
265 *result = RM_INIT_ERROR_GRL_INVALID_LINUX_ALIAS_FORMAT;
266 return(NULL);
267 }
268 }
269 return (startAlias);
270 }
272 /* Function to clean up the memory allocated for a linked list of extracted Linux
273 * aliases. */
274 void rmDtbUtilResFreeLinuxAlias(Rm_LinuxAlias *aliasList)
275 {
276 Rm_LinuxAlias *nextAlias;
277 int32_t pathSize;
279 while (aliasList) {
280 nextAlias = aliasList->nextLinuxAlias;
281 pathSize = strlen(aliasList->path);
282 Rm_osalFree((void *)aliasList->path, pathSize + 1);
283 Rm_osalFree((void *)aliasList, sizeof(Rm_LinuxAlias));
284 aliasList = nextAlias;
285 }
286 }
288 /* Construct and return a list of NameServer assignments as specified in the Resource DTB */
289 Rm_NsAssignment *rmDtbUtilResExtractNsAssignment(const void *dtbDataPtr, int32_t dtbDataLen, int32_t *result)
290 {
291 uint8_t *dtbNsAssignmentData = (uint8_t *)dtbDataPtr;
292 uint32_t nameLenBytes;
293 uint32_t extractedValue;
294 uint8_t *extractedValueBytePtr;
295 Rm_NsAssignment *startAssignment = NULL;
296 Rm_NsAssignment *newAssignment = NULL;
297 Rm_NsAssignment *prevAssignment = NULL;
298 int32_t i = 0;
299 uint16_t j;
301 /* NameServer assignments are stored in the DTB as a null-terminated character
302 * string followed by a 32-bit word containing the value to be assigned to the
303 * name in the string. There is no padding between the string and the 32-bit
304 * word. Therefore the 32-bit word may not be on a 4-byte boundary and must
305 * be constructed upon extraction */
306 while(i < dtbDataLen) {
307 newAssignment = (Rm_NsAssignment *) Rm_osalMalloc(sizeof(Rm_NsAssignment));
309 nameLenBytes = strlen((char *) &dtbNsAssignmentData[i]) + 1;
310 if (nameLenBytes > RM_NAME_MAX_CHARS) {
311 Rm_osalFree((void *)newAssignment, sizeof(Rm_NsAssignment));
312 while (startAssignment) {
313 newAssignment = startAssignment->nextNsAssignment;
314 Rm_osalFree((void *)startAssignment, sizeof(Rm_NsAssignment));
315 startAssignment = newAssignment;
316 }
317 *result = RM_INIT_ERROR_NS_ASSIGNMENT_NAME_TOO_LONG;
318 return(NULL);
319 }
320 strncpy(newAssignment->nsName, ((char *) &dtbNsAssignmentData[i]), RM_NAME_MAX_CHARS);
322 /* Extract 32-bit base value and flip endian */
323 i += nameLenBytes;
324 extractedValueBytePtr = (uint8_t *)&extractedValue;
325 for (j = 0; j < sizeof(uint32_t); j++, i++) {
326 extractedValueBytePtr[j] = dtbNsAssignmentData[i];
327 }
328 newAssignment->resourceBase = fdt32_to_cpu(extractedValue);
330 /* Extract 32-bit length value and flip endian */
331 for (j = 0; j < sizeof(uint32_t); j++, i++) {
332 extractedValueBytePtr[j] = dtbNsAssignmentData[i];
333 }
334 newAssignment->resourceLength = fdt32_to_cpu(extractedValue);
336 newAssignment->nextNsAssignment = NULL;
337 if (prevAssignment == NULL) {
338 startAssignment = newAssignment;
339 }
340 else {
341 prevAssignment->nextNsAssignment = newAssignment;
342 }
343 prevAssignment = newAssignment;
344 }
346 return (startAssignment);
347 }
349 /* Function to clean up the memory allocated for a linked list of extracted NameServer
350 * assignments. */
351 void rmDtbUtilResFreeNsAssignmentList (Rm_NsAssignment *nsAssignmentList)
352 {
353 Rm_NsAssignment *nextAssignment;
355 while (nsAssignmentList) {
356 nextAssignment = nsAssignmentList->nextNsAssignment;
357 Rm_osalFree((void *)nsAssignmentList, sizeof(Rm_NsAssignment));
358 nsAssignmentList = nextAssignment;
359 }
360 }
362 /**********************************************************************
363 ***************Policy DTB Parsing Defines and Functions***************
364 **********************************************************************/
366 /* Policy Properties - These are the property values used
367 * by an application integrator to define the properties of resources
368 * listed in a Resource Manager Policy */
369 char dtbUtilPolicyValidInstances[] = "valid-instances";
370 char dtbUtilPolicyAssignments[] = "assignments";
371 char dtbUtilPolicyAllocationSize[] = "allocation-size";
372 char dtbUtilPolicyAllocationAlignment[] = "allocation-alignment";
374 Rm_PolicyPropType rmDtbUtilPolicyGetPropertyType(const char * propertyName)
375 {
376 Rm_PolicyPropType propertyType = Rm_policyPropType_UNKNOWN;
378 if(strcmp(dtbUtilPolicyAssignments, propertyName) == 0) {
379 propertyType = Rm_policyPropType_ASSIGNMENTS;
380 }
381 else if(strcmp(dtbUtilPolicyAllocationSize, propertyName) == 0) {
382 propertyType = Rm_policyPropType_ALLOCATION_SIZE;
383 }
384 else if(strcmp(dtbUtilPolicyAllocationAlignment, propertyName) == 0) {
385 propertyType = Rm_policyPropType_ALLOCATION_ALIGNMENT;
386 }
387 else if(strcmp(dtbUtilPolicyValidInstances, propertyName) == 0) {
388 propertyType = Rm_policyPropType_VALID_INSTANCES;
389 }
390 return (propertyType);
391 }
393 Rm_PolicyAssignment *rmDtbUtilPolicyExtractAssignments(const void *dtbDataPtr, int32_t dtbDataLen)
394 {
395 uint8_t *dtbAssignmentData = (uint8_t *)dtbDataPtr;
396 uint32_t permissionsLenBytes;
397 uint32_t extractedValue;
398 uint8_t *extractedValueBytePtr;
399 Rm_PolicyAssignment *startAssignment = NULL;
400 Rm_PolicyAssignment *newAssignment = NULL;
401 Rm_PolicyAssignment *prevAssignment = NULL;
402 int32_t i = 0;
403 uint16_t j;
405 /* Policy assignments are stored in the DTB as two 32-bit words containing a
406 * resource base and length to be assigned the permissions in the defined in
407 * the string that follows. There is no padding between the 32-bit words and the
408 * string. Therefore the 32-bit word may not be on a 4-byte boundary and must
409 * be constructed upon extraction */
410 while(i < dtbDataLen) {
411 newAssignment = (Rm_PolicyAssignment *) Rm_osalMalloc(sizeof(Rm_PolicyAssignment));
413 /* Extract 32-bit resource base value and flip endianness */
414 extractedValueBytePtr = (uint8_t *)&extractedValue;
415 for (j = 0; j < sizeof(uint32_t); j++, i++) {
416 extractedValueBytePtr[j] = dtbAssignmentData[i];
417 }
418 newAssignment->resourceBase = fdt32_to_cpu(extractedValue);
420 /* Extract 32-bit resource length value and flip endianness */
421 for (j = 0; j < sizeof(uint32_t); j++, i++) {
422 extractedValueBytePtr[j] = dtbAssignmentData[i];
423 }
424 newAssignment->resourceLength = fdt32_to_cpu(extractedValue);
426 permissionsLenBytes = strlen((char *) &dtbAssignmentData[i]) + 1;
427 newAssignment->permissionsList = (char *) Rm_osalMalloc(permissionsLenBytes);
428 strncpy(newAssignment->permissionsList, ((char *) &dtbAssignmentData[i]), permissionsLenBytes);
429 i += permissionsLenBytes;
431 newAssignment->nextAssignment = NULL;
432 if (prevAssignment == NULL) {
433 startAssignment = newAssignment;
434 }
435 else {
436 prevAssignment->nextAssignment = newAssignment;
437 }
438 prevAssignment = newAssignment;
439 }
440 return (startAssignment);
441 }
443 void rmDtbUtilPolicyFreeAssignments(Rm_PolicyAssignment *assignmentList)
444 {
445 Rm_PolicyAssignment *nextAssignment;
446 int32_t permissionsSize;
448 while (assignmentList) {
449 nextAssignment = assignmentList->nextAssignment;
450 permissionsSize = strlen(assignmentList->permissionsList);
451 Rm_osalFree((void *)assignmentList->permissionsList, permissionsSize+1);
452 Rm_osalFree((void *)assignmentList, sizeof(Rm_PolicyAssignment));
453 assignmentList = nextAssignment;
454 }
455 }
457 /* Construct and return a list of allocation sizes as specified in the Policy DTB */
458 Rm_ResourceValue *rmDtbUtilPolicyExtractAllocationSizes(const void *dtbDataPtr, int32_t dtbDataLen)
459 {
460 return(dtbUtilCommonExtractValueList(dtbDataPtr, dtbDataLen));
461 }
463 /* Function to clean up the memory allocated for a linked list of extracted allocation sizes */
464 void rmDtbUtilPolicyFreeAllocationSizes (Rm_ResourceValue *allocationSizeList)
465 {
466 dtbUtilCommonFreeValueList(allocationSizeList);
467 }
469 /* Construct and return a list of allocation alignments as specified in the Policy DTB */
470 Rm_ResourceValue *rmDtbUtilPolicyExtractResourceAlignments(const void *dtbDataPtr, int32_t dtbDataLen)
471 {
472 return(dtbUtilCommonExtractValueList(dtbDataPtr, dtbDataLen));
473 }
475 /* Function to clean up the memory allocated for a linked list of extracted allocation alignments */
476 void rmDtbUtilPolicyFreeResourceAlignments (Rm_ResourceValue *alignmentList)
477 {
478 dtbUtilCommonFreeValueList(alignmentList);
479 }
481 Rm_PolicyValidInst *rmDtbUtilPolicyExtractValidInstances(const void *dtbDataPtr, int32_t dtbDataLen,
482 int32_t *result)
483 {
484 uint8_t *dtbValidInstData = (uint8_t *)dtbDataPtr;
485 uint32_t instLenBytes;
486 Rm_PolicyValidInst *startInst = NULL;
487 Rm_PolicyValidInst *newInst = NULL;
488 Rm_PolicyValidInst *prevInst = NULL;
489 int32_t i = 0;
491 /* Valid RM instances are stored in the DTB as a list of null-terminated character
492 * strings. */
493 while(i < dtbDataLen) {
494 newInst = (Rm_PolicyValidInst *) Rm_osalMalloc(sizeof(Rm_PolicyValidInst));
496 instLenBytes = strlen((char *) &dtbValidInstData[i]) + 1;
497 if (instLenBytes > RM_NAME_MAX_CHARS) {
498 Rm_osalFree((void *)newInst, sizeof(Rm_PolicyValidInst));
499 while (startInst) {
500 newInst = startInst->nextValidInst;
501 Rm_osalFree((void *)startInst, sizeof(Rm_PolicyValidInst));
502 startInst = newInst;
503 }
504 *result = RM_INIT_ERROR_POLICY_VALID_INSTANCE_NAME_TOO_LONG;
505 return(NULL);
506 }
507 strncpy(newInst->instName, ((char *) &dtbValidInstData[i]), instLenBytes);
509 i += instLenBytes;
511 newInst->nextValidInst = NULL;
513 if (prevInst == NULL) {
514 startInst = newInst;
515 }
516 else {
517 prevInst->nextValidInst = newInst;
518 }
519 prevInst = newInst;
520 }
521 return (startInst);
522 }
524 void rmDtbUtilPolicyFreeValidInstances (Rm_PolicyValidInst *validInstList)
525 {
526 Rm_PolicyValidInst *nextInst;
528 while (validInstList) {
529 nextInst = validInstList->nextValidInst;
530 Rm_osalFree((void *)validInstList, sizeof(Rm_PolicyValidInst));
531 validInstList = nextInst;
532 }
533 }
535 /**********************************************************************
536 ****************Linux DTB Parsing Defines and Functions***************
537 **********************************************************************/
539 Rm_LinuxValueRange *rmDtbUtilLinuxExtractValues(const void *dtbDataPtr, int32_t dtbDataLen)
540 {
541 uint32_t *dtbValueData = (uint32_t *)dtbDataPtr;
542 Rm_LinuxValueRange *startValue = NULL;
543 Rm_LinuxValueRange *newValue = NULL;
544 Rm_LinuxValueRange *prevValue = NULL;
545 uint32_t i;
547 /* Values are stored in the Linux DTB as a list of 32-bit words. The number of 32-bit
548 * words in the value field can differ. depending on the number of values specified. */
549 for (i = 0; i < (dtbDataLen / sizeof(uint32_t)); i++) {
550 newValue = (Rm_LinuxValueRange *) Rm_osalMalloc(sizeof(Rm_LinuxValueRange));
551 /* Endianness of extracted value must be flipped */
552 newValue->value = fdt32_to_cpu(dtbValueData[i]);
553 newValue->nextValue = NULL;
555 if (prevValue == NULL) {
556 startValue = newValue;
557 }
558 else {
559 prevValue->nextValue = newValue;
560 }
561 prevValue = newValue;
562 }
563 return (startValue);
564 }
566 void rmDtbUtilLinuxFreeValues(Rm_LinuxValueRange *valueList)
567 {
568 Rm_LinuxValueRange *nextValue;
570 while (valueList) {
571 nextValue = valueList->nextValue;
572 Rm_osalFree((void *)valueList, sizeof(Rm_LinuxValueRange));
573 valueList = nextValue;
574 }
575 }
577 /**
578 @}
579 */