Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * This file does the necessary interface mapping between the bootwrapper
0004  * device tree operations and the interface provided by shared source
0005  * files flatdevicetree.[ch].
0006  *
0007  * Copyright 2007 David Gibson, IBM Corporation.
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; /* = NULL */
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     /* Make sure the dt blob is the right version and so forth */
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 }