1 /* 2 * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 /* Helper functions to offer easier navigation of Device Tree Blob */ 8 9 #include <assert.h> 10 #include <debug.h> 11 #include <fdt_wrappers.h> 12 #include <libfdt.h> 13 #include <string.h> 14 15 /* 16 * Read cells from a given property of the given node. At most 2 cells of the 17 * property are read, and pointer is updated. Returns 0 on success, and -1 upon 18 * error 19 */ 20 int fdtw_read_cells(const void *dtb, int node, const char *prop, 21 unsigned int cells, void *value) 22 { 23 const uint32_t *value_ptr; 24 uint32_t hi = 0, lo; 25 int value_len; 26 27 assert(dtb != NULL); 28 assert(prop != NULL); 29 assert(value != NULL); 30 assert(node >= 0); 31 32 /* We expect either 1 or 2 cell property */ 33 assert(cells <= 2U); 34 35 /* Access property and obtain its length (in bytes) */ 36 value_ptr = fdt_getprop_namelen(dtb, node, prop, (int)strlen(prop), 37 &value_len); 38 if (value_ptr == NULL) { 39 WARN("Couldn't find property %s in dtb\n", prop); 40 return -1; 41 } 42 43 44 /* Verify that property length accords with cell length */ 45 if (NCELLS((unsigned int)value_len) != cells) { 46 WARN("Property length mismatch\n"); 47 return -1; 48 } 49 50 if (cells == 2U) { 51 hi = fdt32_to_cpu(*value_ptr); 52 value_ptr++; 53 } 54 55 lo = fdt32_to_cpu(*value_ptr); 56 57 if (cells == 2U) 58 *((uint64_t *) value) = ((uint64_t) hi << 32) | lo; 59 else 60 *((uint32_t *) value) = lo; 61 62 return 0; 63 } 64 65 /* 66 * Read string from a given property of the given node. Up to 'size - 1' 67 * characters are read, and a NUL terminator is added. Returns 0 on success, 68 * and -1 upon error. 69 */ 70 int fdtw_read_string(const void *dtb, int node, const char *prop, 71 char *str, size_t size) 72 { 73 const char *ptr; 74 size_t len; 75 76 assert(dtb != NULL); 77 assert(node >= 0); 78 assert(prop != NULL); 79 assert(str != NULL); 80 assert(size > 0U); 81 82 ptr = fdt_getprop_namelen(dtb, node, prop, (int)strlen(prop), NULL); 83 if (ptr == NULL) { 84 WARN("Couldn't find property %s in dtb\n", prop); 85 return -1; 86 } 87 88 len = strlcpy(str, ptr, size); 89 if (len >= size) { 90 WARN("String of property %s in dtb has been truncated\n", prop); 91 return -1; 92 } 93 94 return 0; 95 } 96 97 /* 98 * Write cells in place to a given property of the given node. At most 2 cells 99 * of the property are written. Returns 0 on success, and -1 upon error. 100 */ 101 int fdtw_write_inplace_cells(void *dtb, int node, const char *prop, 102 unsigned int cells, void *value) 103 { 104 int err, len; 105 106 assert(dtb != NULL); 107 assert(prop != NULL); 108 assert(value != NULL); 109 assert(node >= 0); 110 111 /* We expect either 1 or 2 cell property */ 112 assert(cells <= 2U); 113 114 if (cells == 2U) 115 *(uint64_t *)value = cpu_to_fdt64(*(uint64_t *)value); 116 else 117 *(uint32_t *)value = cpu_to_fdt32(*(uint32_t *)value); 118 119 len = (int)cells * 4; 120 121 /* Set property value in place */ 122 err = fdt_setprop_inplace(dtb, node, prop, value, len); 123 if (err != 0) { 124 WARN("Modify property %s failed with error %d\n", prop, err); 125 return -1; 126 } 127 128 return 0; 129 } 130