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
  71struct data data_copy_escape_string(const char *s, int len)
  72{
  73        int i = 0;
  74        struct data d;
  75        char *q;
  76
  77        d = data_grow_for(empty_data, strlen(s)+1);
  78
  79        q = d.val;
  80        while (i < len) {
  81                char c = s[i++];
  82
  83                if (c == '\\')
  84                        c = get_escape_char(s, &i);
  85
  86                q[d.len++] = c;
  87        }
  88
  89        q[d.len++] = '\0';
  90        return d;
  91}
  92
  93struct data data_copy_file(FILE *f, size_t maxlen)
  94{
  95        struct data d = empty_data;
  96
  97        while (!feof(f) && (d.len < maxlen)) {
  98                size_t chunksize, ret;
  99
 100                if (maxlen == -1)
 101                        chunksize = 4096;
 102                else
 103                        chunksize = maxlen - d.len;
 104
 105                d = data_grow_for(d, chunksize);
 106                ret = fread(d.val + d.len, 1, chunksize, f);
 107
 108                if (ferror(f))
 109                        die("Error reading file into data: %s", strerror(errno));
 110
 111                if (d.len + ret < d.len)
 112                        die("Overflow reading file into data\n");
 113
 114                d.len += ret;
 115        }
 116
 117        return d;
 118}
 119
 120struct data data_append_data(struct data d, const void *p, int len)
 121{
 122        d = data_grow_for(d, len);
 123        memcpy(d.val + d.len, p, len);
 124        d.len += len;
 125        return d;
 126}
 127
 128struct data data_insert_at_marker(struct data d, struct marker *m,
 129                                  const void *p, int len)
 130{
 131        d = data_grow_for(d, len);
 132        memmove(d.val + m->offset + len, d.val + m->offset, d.len - m->offset);
 133        memcpy(d.val + m->offset, p, len);
 134        d.len += len;
 135
 136        /* Adjust all markers after the one we're inserting at */
 137        m = m->next;
 138        for_each_marker(m)
 139                m->offset += len;
 140        return d;
 141}
 142
 143static struct data data_append_markers(struct data d, struct marker *m)
 144{
 145        struct marker **mp = &d.markers;
 146
 147        /* Find the end of the markerlist */
 148        while (*mp)
 149                mp = &((*mp)->next);
 150        *mp = m;
 151        return d;
 152}
 153
 154struct data data_merge(struct data d1, struct data d2)
 155{
 156        struct data d;
 157        struct marker *m2 = d2.markers;
 158
 159        d = data_append_markers(data_append_data(d1, d2.val, d2.len), m2);
 160
 161        /* Adjust for the length of d1 */
 162        for_each_marker(m2)
 163                m2->offset += d1.len;
 164
 165        d2.markers = NULL; /* So data_free() doesn't clobber them */
 166        data_free(d2);
 167
 168        return d;
 169}
 170
 171struct data data_append_integer(struct data d, uint64_t value, int bits)
 172{
 173        uint8_t value_8;
 174        uint16_t value_16;
 175        uint32_t value_32;
 176        uint64_t value_64;
 177
 178        switch (bits) {
 179        case 8:
 180                value_8 = value;
 181                return data_append_data(d, &value_8, 1);
 182
 183        case 16:
 184                value_16 = cpu_to_fdt16(value);
 185                return data_append_data(d, &value_16, 2);
 186
 187        case 32:
 188                value_32 = cpu_to_fdt32(value);
 189                return data_append_data(d, &value_32, 4);
 190
 191        case 64:
 192                value_64 = cpu_to_fdt64(value);
 193                return data_append_data(d, &value_64, 8);
 194
 195        default:
 196                die("Invalid literal size (%d)\n", bits);
 197        }
 198}
 199
 200struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
 201{
 202        struct fdt_reserve_entry bere;
 203
 204        bere.address = cpu_to_fdt64(re->address);
 205        bere.size = cpu_to_fdt64(re->size);
 206
 207        return data_append_data(d, &bere, sizeof(bere));
 208}
 209
 210struct data data_append_cell(struct data d, cell_t word)
 211{
 212        return data_append_integer(d, word, sizeof(word) * 8);
 213}
 214
 215struct data data_append_addr(struct data d, uint64_t addr)
 216{
 217        return data_append_integer(d, addr, sizeof(addr) * 8);
 218}
 219
 220struct data data_append_byte(struct data d, uint8_t byte)
 221{
 222        return data_append_data(d, &byte, 1);
 223}
 224
 225struct data data_append_zeroes(struct data d, int len)
 226{
 227        d = data_grow_for(d, len);
 228
 229        memset(d.val + d.len, 0, len);
 230        d.len += len;
 231        return d;
 232}
 233
 234struct data data_append_align(struct data d, int align)
 235{
 236        int newlen = ALIGN(d.len, align);
 237        return data_append_zeroes(d, newlen - d.len);
 238}
 239
 240struct data data_add_marker(struct data d, enum markertype type, char *ref)
 241{
 242        struct marker *m;
 243
 244        m = xmalloc(sizeof(*m));
 245        m->offset = d.len;
 246        m->type = type;
 247        m->ref = ref;
 248        m->next = NULL;
 249
 250        return data_append_markers(d, m);
 251}
 252
 253int data_is_one_string(struct data d)
 254{
 255        int i;
 256        int len = d.len;
 257
 258        if (len == 0)
 259                return 0;
 260
 261        for (i = 0; i < len-1; i++)
 262                if (d.val[i] == '\0')
 263                        return 0;
 264
 265        if (d.val[len-1] != '\0')
 266                return 0;
 267
 268        return 1;
 269}
 270