uboot/lib/libfdt/fdt_wip.c
<<
>>
Prefs
   1/*
   2 * libfdt - Flat Device Tree manipulation
   3 * Copyright (C) 2006 David Gibson, IBM Corporation.
   4 * SPDX-License-Identifier:     GPL-2.0+ BSD-2-Clause
   5 */
   6#include <libfdt_env.h>
   7
   8#ifndef USE_HOSTCC
   9#include <fdt.h>
  10#include <libfdt.h>
  11#else
  12#include "fdt_host.h"
  13#endif
  14
  15#include "libfdt_internal.h"
  16
  17int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
  18                                        const char *name, int namelen,
  19                                        uint32_t idx, const void *val,
  20                                        int len)
  21{
  22        void *propval;
  23        int proplen;
  24
  25        propval = fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen,
  26                                        &proplen);
  27        if (!propval)
  28                return proplen;
  29
  30        if (proplen < (len + idx))
  31                return -FDT_ERR_NOSPACE;
  32
  33        memcpy((char *)propval + idx, val, len);
  34        return 0;
  35}
  36
  37int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
  38                        const void *val, int len)
  39{
  40        const void *propval;
  41        int proplen;
  42
  43        propval = fdt_getprop(fdt, nodeoffset, name, &proplen);
  44        if (!propval)
  45                return proplen;
  46
  47        if (proplen != len)
  48                return -FDT_ERR_NOSPACE;
  49
  50        return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name,
  51                                                   strlen(name), 0,
  52                                                   val, len);
  53}
  54
  55static void _fdt_nop_region(void *start, int len)
  56{
  57        fdt32_t *p;
  58
  59        for (p = start; (char *)p < ((char *)start + len); p++)
  60                *p = cpu_to_fdt32(FDT_NOP);
  61}
  62
  63int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
  64{
  65        struct fdt_property *prop;
  66        int len;
  67
  68        prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
  69        if (!prop)
  70                return len;
  71
  72        _fdt_nop_region(prop, len + sizeof(*prop));
  73
  74        return 0;
  75}
  76
  77int _fdt_node_end_offset(void *fdt, int offset)
  78{
  79        int depth = 0;
  80
  81        while ((offset >= 0) && (depth >= 0))
  82                offset = fdt_next_node(fdt, offset, &depth);
  83
  84        return offset;
  85}
  86
  87int fdt_nop_node(void *fdt, int nodeoffset)
  88{
  89        int endoffset;
  90
  91        endoffset = _fdt_node_end_offset(fdt, nodeoffset);
  92        if (endoffset < 0)
  93                return endoffset;
  94
  95        _fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0),
  96                        endoffset - nodeoffset);
  97        return 0;
  98}
  99
 100#define FDT_MAX_DEPTH   32
 101
 102static int str_in_list(const char *str, char * const list[], int count)
 103{
 104        int i;
 105
 106        for (i = 0; i < count; i++)
 107                if (!strcmp(list[i], str))
 108                        return 1;
 109
 110        return 0;
 111}
 112
 113int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
 114                     char * const exc_prop[], int exc_prop_count,
 115                     struct fdt_region region[], int max_regions,
 116                     char *path, int path_len, int add_string_tab)
 117{
 118        int stack[FDT_MAX_DEPTH] = { 0 };
 119        char *end;
 120        int nextoffset = 0;
 121        uint32_t tag;
 122        int count = 0;
 123        int start = -1;
 124        int depth = -1;
 125        int want = 0;
 126        int base = fdt_off_dt_struct(fdt);
 127
 128        end = path;
 129        *end = '\0';
 130        do {
 131                const struct fdt_property *prop;
 132                const char *name;
 133                const char *str;
 134                int include = 0;
 135                int stop_at = 0;
 136                int offset;
 137                int len;
 138
 139                offset = nextoffset;
 140                tag = fdt_next_tag(fdt, offset, &nextoffset);
 141                stop_at = nextoffset;
 142
 143                switch (tag) {
 144                case FDT_PROP:
 145                        include = want >= 2;
 146                        stop_at = offset;
 147                        prop = fdt_get_property_by_offset(fdt, offset, NULL);
 148                        str = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
 149                        if (str_in_list(str, exc_prop, exc_prop_count))
 150                                include = 0;
 151                        break;
 152
 153                case FDT_NOP:
 154                        include = want >= 2;
 155                        stop_at = offset;
 156                        break;
 157
 158                case FDT_BEGIN_NODE:
 159                        depth++;
 160                        if (depth == FDT_MAX_DEPTH)
 161                                return -FDT_ERR_BADSTRUCTURE;
 162                        name = fdt_get_name(fdt, offset, &len);
 163                        if (end - path + 2 + len >= path_len)
 164                                return -FDT_ERR_NOSPACE;
 165                        if (end != path + 1)
 166                                *end++ = '/';
 167                        strcpy(end, name);
 168                        end += len;
 169                        stack[depth] = want;
 170                        if (want == 1)
 171                                stop_at = offset;
 172                        if (str_in_list(path, inc, inc_count))
 173                                want = 2;
 174                        else if (want)
 175                                want--;
 176                        else
 177                                stop_at = offset;
 178                        include = want;
 179                        break;
 180
 181                case FDT_END_NODE:
 182                        include = want;
 183                        want = stack[depth--];
 184                        while (end > path && *--end != '/')
 185                                ;
 186                        *end = '\0';
 187                        break;
 188
 189                case FDT_END:
 190                        include = 1;
 191                        break;
 192                }
 193
 194                if (include && start == -1) {
 195                        /* Should we merge with previous? */
 196                        if (count && count <= max_regions &&
 197                            offset == region[count - 1].offset +
 198                                        region[count - 1].size - base)
 199                                start = region[--count].offset - base;
 200                        else
 201                                start = offset;
 202                }
 203
 204                if (!include && start != -1) {
 205                        if (count < max_regions) {
 206                                region[count].offset = base + start;
 207                                region[count].size = stop_at - start;
 208                        }
 209                        count++;
 210                        start = -1;
 211                }
 212        } while (tag != FDT_END);
 213
 214        if (nextoffset != fdt_size_dt_struct(fdt))
 215                return -FDT_ERR_BADLAYOUT;
 216
 217        /* Add a region for the END tag and the string table */
 218        if (count < max_regions) {
 219                region[count].offset = base + start;
 220                region[count].size = nextoffset - start;
 221                if (add_string_tab)
 222                        region[count].size += fdt_size_dt_strings(fdt);
 223        }
 224        count++;
 225
 226        return count;
 227}
 228