0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <stddef.h>
0011 #include <stdio.h>
0012 #include <page.h>
0013 #include <libfdt.h>
0014 #include "ops.h"
0015
0016 #define DEBUG 0
0017 #define BAD_ERROR(err) (((err) < 0) \
0018 && ((err) != -FDT_ERR_NOTFOUND) \
0019 && ((err) != -FDT_ERR_EXISTS))
0020
0021 #define check_err(err) \
0022 ({ \
0023 if (BAD_ERROR(err) || ((err < 0) && DEBUG)) \
0024 printf("%s():%d %s\n\r", __func__, __LINE__, \
0025 fdt_strerror(err)); \
0026 if (BAD_ERROR(err)) \
0027 exit(); \
0028 (err < 0) ? -1 : 0; \
0029 })
0030
0031 #define offset_devp(off) \
0032 ({ \
0033 unsigned long _offset = (off); \
0034 check_err(_offset) ? NULL : (void *)(_offset+1); \
0035 })
0036
0037 #define devp_offset_find(devp) (((unsigned long)(devp))-1)
0038 #define devp_offset(devp) (devp ? ((unsigned long)(devp))-1 : 0)
0039
0040 static void *fdt;
0041 static void *buf;
0042
0043 #define EXPAND_GRANULARITY 1024
0044
0045 static void expand_buf(int minexpand)
0046 {
0047 int size = fdt_totalsize(fdt);
0048 int rc;
0049
0050 size = _ALIGN(size + minexpand, EXPAND_GRANULARITY);
0051 buf = platform_ops.realloc(buf, size);
0052 if (!buf)
0053 fatal("Couldn't find %d bytes to expand device tree\n\r", size);
0054 rc = fdt_open_into(fdt, buf, size);
0055 if (rc != 0)
0056 fatal("Couldn't expand fdt into new buffer: %s\n\r",
0057 fdt_strerror(rc));
0058
0059 fdt = buf;
0060 }
0061
0062 static void *fdt_wrapper_finddevice(const char *path)
0063 {
0064 return offset_devp(fdt_path_offset(fdt, path));
0065 }
0066
0067 static int fdt_wrapper_getprop(const void *devp, const char *name,
0068 void *buf, const int buflen)
0069 {
0070 const void *p;
0071 int len;
0072
0073 p = fdt_getprop(fdt, devp_offset(devp), name, &len);
0074 if (!p)
0075 return check_err(len);
0076 memcpy(buf, p, min(len, buflen));
0077 return len;
0078 }
0079
0080 static int fdt_wrapper_setprop(const void *devp, const char *name,
0081 const void *buf, const int len)
0082 {
0083 int rc;
0084
0085 rc = fdt_setprop(fdt, devp_offset(devp), name, buf, len);
0086 if (rc == -FDT_ERR_NOSPACE) {
0087 expand_buf(len + 16);
0088 rc = fdt_setprop(fdt, devp_offset(devp), name, buf, len);
0089 }
0090
0091 return check_err(rc);
0092 }
0093
0094 static int fdt_wrapper_del_node(const void *devp)
0095 {
0096 return fdt_del_node(fdt, devp_offset(devp));
0097 }
0098
0099 static void *fdt_wrapper_get_parent(const void *devp)
0100 {
0101 return offset_devp(fdt_parent_offset(fdt, devp_offset(devp)));
0102 }
0103
0104 static void *fdt_wrapper_create_node(const void *devp, const char *name)
0105 {
0106 int offset;
0107
0108 offset = fdt_add_subnode(fdt, devp_offset(devp), name);
0109 if (offset == -FDT_ERR_NOSPACE) {
0110 expand_buf(strlen(name) + 16);
0111 offset = fdt_add_subnode(fdt, devp_offset(devp), name);
0112 }
0113
0114 return offset_devp(offset);
0115 }
0116
0117 static void *fdt_wrapper_find_node_by_prop_value(const void *prev,
0118 const char *name,
0119 const char *val,
0120 int len)
0121 {
0122 int offset = fdt_node_offset_by_prop_value(fdt, devp_offset_find(prev),
0123 name, val, len);
0124 return offset_devp(offset);
0125 }
0126
0127 static void *fdt_wrapper_find_node_by_compatible(const void *prev,
0128 const char *val)
0129 {
0130 int offset = fdt_node_offset_by_compatible(fdt, devp_offset_find(prev),
0131 val);
0132 return offset_devp(offset);
0133 }
0134
0135 static char *fdt_wrapper_get_path(const void *devp, char *buf, int len)
0136 {
0137 int rc;
0138
0139 rc = fdt_get_path(fdt, devp_offset(devp), buf, len);
0140 if (check_err(rc))
0141 return NULL;
0142 return buf;
0143 }
0144
0145 static unsigned long fdt_wrapper_finalize(void)
0146 {
0147 int rc;
0148
0149 rc = fdt_pack(fdt);
0150 if (rc != 0)
0151 fatal("Couldn't pack flat tree: %s\n\r",
0152 fdt_strerror(rc));
0153 return (unsigned long)fdt;
0154 }
0155
0156 void fdt_init(void *blob)
0157 {
0158 int err;
0159 int bufsize;
0160
0161 dt_ops.finddevice = fdt_wrapper_finddevice;
0162 dt_ops.getprop = fdt_wrapper_getprop;
0163 dt_ops.setprop = fdt_wrapper_setprop;
0164 dt_ops.get_parent = fdt_wrapper_get_parent;
0165 dt_ops.create_node = fdt_wrapper_create_node;
0166 dt_ops.find_node_by_prop_value = fdt_wrapper_find_node_by_prop_value;
0167 dt_ops.find_node_by_compatible = fdt_wrapper_find_node_by_compatible;
0168 dt_ops.del_node = fdt_wrapper_del_node;
0169 dt_ops.get_path = fdt_wrapper_get_path;
0170 dt_ops.finalize = fdt_wrapper_finalize;
0171
0172
0173 fdt = blob;
0174 bufsize = fdt_totalsize(fdt) + EXPAND_GRANULARITY;
0175 buf = malloc(bufsize);
0176 if(!buf)
0177 fatal("malloc failed. can't relocate the device tree\n\r");
0178
0179 err = fdt_open_into(fdt, buf, bufsize);
0180
0181 if (err != 0)
0182 fatal("fdt_init(): %s\n\r", fdt_strerror(err));
0183
0184 fdt = buf;
0185 }