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