linux/scripts/dtc/data.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
   3 *
   4 *
   5 * This program is free software; you can redistribute it and/or
   6 * modify it under the terms of the GNU General Public License as
   7 * published by the Free Software Foundation; either version 2 of the
   8 * License, or (at your option) any later version.
   9 *
  10 *  This program is distributed in the hope that it will be useful,
  11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13 *  General Public License for more details.
  14 *
  15 *  You should have received a copy of the GNU General Public License
  16 *  along with this program; if not, write to the Free Software
  17 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
  18 *                                                                   USA
  19 */
  20
  21#include "dtc.h"
  22
  23void data_free(struct data d)
  24{
  25        struct marker *m, *nm;
  26
  27        m = d.markers;
  28        while (m) {
  29                nm = m->next;
  30                free(m->ref);
  31                free(m);
  32                m = nm;
  33        }
  34
  35        if (d.val)
  36                free(d.val);
  37}
  38
  39struct data data_grow_for(struct data d, int xlen)
  40{
  41        struct data nd;
  42        int newsize;
  43
  44        if (xlen == 0)
  45                return d;
  46
  47        nd = d;
  48
  49        newsize = xlen;
  50
  51        while ((d.len + xlen) > newsize)
  52                newsize *= 2;
  53
  54        nd.val = xrealloc(d.val, newsize);
  55
  56        return nd;
  57}
  58
  59struct data data_copy_mem(const char *mem, int len)
  60{
  61        struct data d;
  62
  63        d = data_grow_for(empty_data, len);
  64
  65        d.len = len;
  66        memcpy(d.val, mem, len);
  67
  68        return d;
  69}
  70
  71static char get_oct_char(const char *s, int *i)
  72{
  73        char x[4];
  74        char *endx;
  75        long val;
  76
  77        x[3] = '\0';
  78        strncpy(x, s + *i, 3);
  79
  80        val = strtol(x, &endx, 8);
  81
  82        assert(endx > x);
  83
  84        (*i) += endx - x;
  85        return val;
  86}
  87
  88static char get_hex_char(const char *s, int *i)
  89{
  90        char x[3];
  91        char *endx;
  92        long val;
  93
  94        x[2] = '\0';
  95        strncpy(x, s + *i, 2);
  96
  97        val = strtol(x, &endx, 16);
  98        if (!(endx  > x))
  99                die("\\x used with no following hex digits\n");
 100
 101        (*i) += endx - x;
 102        return val;
 103}
 104
 105struct data data_copy_escape_string(const char *s, int len)
 106{
 107        int i = 0;
 108        struct data d;
 109        char *q;
 110
 111        d = data_grow_for(empty_data, strlen(s)+1);
 112
 113        q = d.val;
 114        while (i < len) {
 115                char c = s[i++];
 116
 117                if (c != '\\') {
 118                        q[d.len++] = c;
 119                        continue;
 120                }
 121
 122                c = s[i++];
 123                assert(c);
 124                switch (c) {
 125                case 'a':
 126                        q[d.len++] = '\a';
 127                        break;
 128                case 'b':
 129                        q[d.len++] = '\b';
 130                        break;
 131                case 't':
 132                        q[d.len++] = '\t';
 133                        break;
 134                case 'n':
 135                        q[d.len++] = '\n';
 136                        break;
 137                case 'v':
 138                        q[d.len++] = '\v';
 139                        break;
 140                case 'f':
 141                        q[d.len++] = '\f';
 142                        break;
 143                case 'r':
 144                        q[d.len++] = '\r';
 145                        break;
 146                case '0':
 147                case '1':
 148                case '2':
 149                case '3':
 150                case '4':
 151                case '5':
 152                case '6':
 153                case '7':
 154                        i--; /* need to re-read the first digit as
 155                              * part of the octal value */
 156                        q[d.len++] = get_oct_char(s, &i);
 157                        break;
 158                case 'x':
 159                        q[d.len++] = get_hex_char(s, &i);
 160                        break;
 161                default:
 162                        q[d.len++] = c;
 163                }
 164        }
 165
 166        q[d.len++] = '\0';
 167        return d;
 168}
 169
 170struct data data_copy_file(FILE *f, size_t maxlen)
 171{
 172        struct data d = empty_data;
 173
 174        while (!feof(f) && (d.len < maxlen)) {
 175                size_t chunksize, ret;
 176
 177                if (maxlen == -1)
 178                        chunksize = 4096;
 179                else
 180                        chunksize = maxlen - d.len;
 181
 182                d = data_grow_for(d, chunksize);
 183                ret = fread(d.val + d.len, 1, chunksize, f);
 184
 185                if (ferror(f))
 186                        die("Error reading file into data: %s", strerror(errno));
 187
 188                if (d.len + ret < d.len)
 189                        die("Overflow reading file into data\n");
 190
 191                d.len += ret;
 192        }
 193
 194        return d;
 195}
 196
 197struct data data_append_data(struct data d, const void *p, int len)
 198{
 199        d = data_grow_for(d, len);
 200        memcpy(d.val + d.len, p, len);
 201        d.len += len;
 202        return d;
 203}
 204
 205struct data data_insert_at_marker(struct data d, struct marker *m,
 206                                  const void *p, int len)
 207{
 208        d = data_grow_for(d, len);
 209        memmove(d.val + m->offset + len, d.val + m->offset, d.len - m->offset);
 210        memcpy(d.val + m->offset, p, len);
 211        d.len += len;
 212
 213        /* Adjust all markers after the one we're inserting at */
 214        m = m->next;
 215        for_each_marker(m)
 216                m->offset += len;
 217        return d;
 218}
 219
 220static struct data data_append_markers(struct data d, struct marker *m)
 221{
 222        struct marker **mp = &d.markers;
 223
 224        /* Find the end of the markerlist */
 225        while (*mp)
 226                mp = &((*mp)->next);
 227        *mp = m;
 228        return d;
 229}
 230
 231struct data data_merge(struct data d1, struct data d2)
 232{
 233        struct data d;
 234        struct marker *m2 = d2.markers;
 235
 236        d = data_append_markers(data_append_data(d1, d2.val, d2.len), m2);
 237
 238        /* Adjust for the length of d1 */
 239        for_each_marker(m2)
 240                m2->offset += d1.len;
 241
 242        d2.markers = NULL; /* So data_free() doesn't clobber them */
 243        data_free(d2);
 244
 245        return d;
 246}
 247
 248struct data data_append_cell(struct data d, cell_t word)
 249{
 250        cell_t beword = cpu_to_fdt32(word);
 251
 252        return data_append_data(d, &beword, sizeof(beword));
 253}
 254
 255struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
 256{
 257        struct fdt_reserve_entry bere;
 258
 259        bere.address = cpu_to_fdt64(re->address);
 260        bere.size = cpu_to_fdt64(re->size);
 261
 262        return data_append_data(d, &bere, sizeof(bere));
 263}
 264
 265struct data data_append_addr(struct data d, uint64_t addr)
 266{
 267        uint64_t beaddr = cpu_to_fdt64(addr);
 268
 269        return data_append_data(d, &beaddr, sizeof(beaddr));
 270}
 271
 272struct data data_append_byte(struct data d, uint8_t byte)
 273{
 274        return data_append_data(d, &byte, 1);
 275}
 276
 277struct data data_append_zeroes(struct data d, int len)
 278{
 279        d = data_grow_for(d, len);
 280
 281        memset(d.val + d.len, 0, len);
 282        d.len += len;
 283        return d;
 284}
 285
 286struct data data_append_align(struct data d, int align)
 287{
 288        int newlen = ALIGN(d.len, align);
 289        return data_append_zeroes(d, newlen - d.len);
 290}
 291
 292struct data data_add_marker(struct data d, enum markertype type, char *ref)
 293{
 294        struct marker *m;
 295
 296        m = xmalloc(sizeof(*m));
 297        m->offset = d.len;
 298        m->type = type;
 299        m->ref = ref;
 300        m->next = NULL;
 301
 302        return data_append_markers(d, m);
 303}
 304
 305int data_is_one_string(struct data d)
 306{
 307        int i;
 308        int len = d.len;
 309
 310        if (len == 0)
 311                return 0;
 312
 313        for (i = 0; i < len-1; i++)
 314                if (d.val[i] == '\0')
 315                        return 0;
 316
 317        if (d.val[len-1] != '\0')
 318                return 0;
 319
 320        return 1;
 321}
 322