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 14 /* 15 * Read cells from a given property of the given node. At most 2 cells of the 16 * property are read, and pointer is updated. Returns 0 on success, and -1 upon 17 * error 18 */ 19 int fdtw_read_cells(const void *dtb, int node, const char *prop, 20 unsigned int cells, void *value) 21 { 22 const uint32_t *value_ptr; 23 uint32_t hi = 0, lo; 24 int value_len; 25 26 assert(dtb != NULL); 27 assert(prop != NULL); 28 assert(value != NULL); 29 assert(node >= 0); 30 31 /* We expect either 1 or 2 cell property */ 32 assert(cells <= 2U); 33 34 /* Access property and obtain its length (in bytes) */ 35 value_ptr = fdt_getprop_namelen(dtb, node, prop, (int)strlen(prop), 36 &value_len); 37 if (value_ptr == NULL) { 38 WARN("Couldn't find property %s in dtb\n", prop); 39 return -1; 40 } 41 42 43 /* Verify that property length accords with cell length */ 44 if (NCELLS((unsigned int)value_len) != cells) { 45 WARN("Property length mismatch\n"); 46 return -1; 47 } 48 49 if (cells == 2U) { 50 hi = fdt32_to_cpu(*value_ptr); 51 value_ptr++; 52 } 53 54 lo = fdt32_to_cpu(*value_ptr); 55 56 if (cells == 2U) 57 *((uint64_t *) value) = ((uint64_t) hi << 32) | lo; 58 else 59 *((uint32_t *) value) = lo; 60 61 return 0; 62 } 63 64 /* 65 * Write cells in place to a given property of the given node. At most 2 cells 66 * of the property are written. Returns 0 on success, and -1 upon error. 67 */ 68 int fdtw_write_inplace_cells(void *dtb, int node, const char *prop, 69 unsigned int cells, void *value) 70 { 71 int err, len; 72 73 assert(dtb != NULL); 74 assert(prop != NULL); 75 assert(value != NULL); 76 assert(node >= 0); 77 78 /* We expect either 1 or 2 cell property */ 79 assert(cells <= 2U); 80 81 if (cells == 2U) 82 *(uint64_t *)value = cpu_to_fdt64(*(uint64_t *)value); 83 else 84 *(uint32_t *)value = cpu_to_fdt32(*(uint32_t *)value); 85 86 len = (int)cells * 4; 87 88 /* Set property value in place */ 89 err = fdt_setprop_inplace(dtb, node, prop, value, len); 90 if (err != 0) { 91 WARN("Modify property %s failed with error %d\n", prop, err); 92 return -1; 93 } 94 95 return 0; 96 } 97