libfdt-wrapper.c (4520B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * This file does the necessary interface mapping between the bootwrapper 4 * device tree operations and the interface provided by shared source 5 * files flatdevicetree.[ch]. 6 * 7 * Copyright 2007 David Gibson, IBM Corporation. 8 */ 9 10#include <stddef.h> 11#include <stdio.h> 12#include <page.h> 13#include <libfdt.h> 14#include "ops.h" 15 16#define DEBUG 0 17#define BAD_ERROR(err) (((err) < 0) \ 18 && ((err) != -FDT_ERR_NOTFOUND) \ 19 && ((err) != -FDT_ERR_EXISTS)) 20 21#define check_err(err) \ 22 ({ \ 23 if (BAD_ERROR(err) || ((err < 0) && DEBUG)) \ 24 printf("%s():%d %s\n\r", __func__, __LINE__, \ 25 fdt_strerror(err)); \ 26 if (BAD_ERROR(err)) \ 27 exit(); \ 28 (err < 0) ? -1 : 0; \ 29 }) 30 31#define offset_devp(off) \ 32 ({ \ 33 unsigned long _offset = (off); \ 34 check_err(_offset) ? NULL : (void *)(_offset+1); \ 35 }) 36 37#define devp_offset_find(devp) (((unsigned long)(devp))-1) 38#define devp_offset(devp) (devp ? ((unsigned long)(devp))-1 : 0) 39 40static void *fdt; 41static void *buf; /* = NULL */ 42 43#define EXPAND_GRANULARITY 1024 44 45static void expand_buf(int minexpand) 46{ 47 int size = fdt_totalsize(fdt); 48 int rc; 49 50 size = _ALIGN(size + minexpand, EXPAND_GRANULARITY); 51 buf = platform_ops.realloc(buf, size); 52 if (!buf) 53 fatal("Couldn't find %d bytes to expand device tree\n\r", size); 54 rc = fdt_open_into(fdt, buf, size); 55 if (rc != 0) 56 fatal("Couldn't expand fdt into new buffer: %s\n\r", 57 fdt_strerror(rc)); 58 59 fdt = buf; 60} 61 62static void *fdt_wrapper_finddevice(const char *path) 63{ 64 return offset_devp(fdt_path_offset(fdt, path)); 65} 66 67static int fdt_wrapper_getprop(const void *devp, const char *name, 68 void *buf, const int buflen) 69{ 70 const void *p; 71 int len; 72 73 p = fdt_getprop(fdt, devp_offset(devp), name, &len); 74 if (!p) 75 return check_err(len); 76 memcpy(buf, p, min(len, buflen)); 77 return len; 78} 79 80static int fdt_wrapper_setprop(const void *devp, const char *name, 81 const void *buf, const int len) 82{ 83 int rc; 84 85 rc = fdt_setprop(fdt, devp_offset(devp), name, buf, len); 86 if (rc == -FDT_ERR_NOSPACE) { 87 expand_buf(len + 16); 88 rc = fdt_setprop(fdt, devp_offset(devp), name, buf, len); 89 } 90 91 return check_err(rc); 92} 93 94static int fdt_wrapper_del_node(const void *devp) 95{ 96 return fdt_del_node(fdt, devp_offset(devp)); 97} 98 99static void *fdt_wrapper_get_parent(const void *devp) 100{ 101 return offset_devp(fdt_parent_offset(fdt, devp_offset(devp))); 102} 103 104static void *fdt_wrapper_create_node(const void *devp, const char *name) 105{ 106 int offset; 107 108 offset = fdt_add_subnode(fdt, devp_offset(devp), name); 109 if (offset == -FDT_ERR_NOSPACE) { 110 expand_buf(strlen(name) + 16); 111 offset = fdt_add_subnode(fdt, devp_offset(devp), name); 112 } 113 114 return offset_devp(offset); 115} 116 117static void *fdt_wrapper_find_node_by_prop_value(const void *prev, 118 const char *name, 119 const char *val, 120 int len) 121{ 122 int offset = fdt_node_offset_by_prop_value(fdt, devp_offset_find(prev), 123 name, val, len); 124 return offset_devp(offset); 125} 126 127static void *fdt_wrapper_find_node_by_compatible(const void *prev, 128 const char *val) 129{ 130 int offset = fdt_node_offset_by_compatible(fdt, devp_offset_find(prev), 131 val); 132 return offset_devp(offset); 133} 134 135static char *fdt_wrapper_get_path(const void *devp, char *buf, int len) 136{ 137 int rc; 138 139 rc = fdt_get_path(fdt, devp_offset(devp), buf, len); 140 if (check_err(rc)) 141 return NULL; 142 return buf; 143} 144 145static unsigned long fdt_wrapper_finalize(void) 146{ 147 int rc; 148 149 rc = fdt_pack(fdt); 150 if (rc != 0) 151 fatal("Couldn't pack flat tree: %s\n\r", 152 fdt_strerror(rc)); 153 return (unsigned long)fdt; 154} 155 156void fdt_init(void *blob) 157{ 158 int err; 159 int bufsize; 160 161 dt_ops.finddevice = fdt_wrapper_finddevice; 162 dt_ops.getprop = fdt_wrapper_getprop; 163 dt_ops.setprop = fdt_wrapper_setprop; 164 dt_ops.get_parent = fdt_wrapper_get_parent; 165 dt_ops.create_node = fdt_wrapper_create_node; 166 dt_ops.find_node_by_prop_value = fdt_wrapper_find_node_by_prop_value; 167 dt_ops.find_node_by_compatible = fdt_wrapper_find_node_by_compatible; 168 dt_ops.del_node = fdt_wrapper_del_node; 169 dt_ops.get_path = fdt_wrapper_get_path; 170 dt_ops.finalize = fdt_wrapper_finalize; 171 172 /* Make sure the dt blob is the right version and so forth */ 173 fdt = blob; 174 bufsize = fdt_totalsize(fdt) + EXPAND_GRANULARITY; 175 buf = malloc(bufsize); 176 if(!buf) 177 fatal("malloc failed. can't relocate the device tree\n\r"); 178 179 err = fdt_open_into(fdt, buf, bufsize); 180 181 if (err != 0) 182 fatal("fdt_init(): %s\n\r", fdt_strerror(err)); 183 184 fdt = buf; 185}