Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
0004  */
0005 
0006 #include "dtc.h"
0007 
0008 void data_free(struct data d)
0009 {
0010     struct marker *m, *nm;
0011 
0012     m = d.markers;
0013     while (m) {
0014         nm = m->next;
0015         free(m->ref);
0016         free(m);
0017         m = nm;
0018     }
0019 
0020     if (d.val)
0021         free(d.val);
0022 }
0023 
0024 struct data data_grow_for(struct data d, unsigned int xlen)
0025 {
0026     struct data nd;
0027     unsigned int newsize;
0028 
0029     if (xlen == 0)
0030         return d;
0031 
0032     nd = d;
0033 
0034     newsize = xlen;
0035 
0036     while ((d.len + xlen) > newsize)
0037         newsize *= 2;
0038 
0039     nd.val = xrealloc(d.val, newsize);
0040 
0041     return nd;
0042 }
0043 
0044 struct data data_copy_mem(const char *mem, int len)
0045 {
0046     struct data d;
0047 
0048     d = data_grow_for(empty_data, len);
0049 
0050     d.len = len;
0051     memcpy(d.val, mem, len);
0052 
0053     return d;
0054 }
0055 
0056 struct data data_copy_escape_string(const char *s, int len)
0057 {
0058     int i = 0;
0059     struct data d;
0060     char *q;
0061 
0062     d = data_add_marker(empty_data, TYPE_STRING, NULL);
0063     d = data_grow_for(d, len + 1);
0064 
0065     q = d.val;
0066     while (i < len) {
0067         char c = s[i++];
0068 
0069         if (c == '\\')
0070             c = get_escape_char(s, &i);
0071 
0072         q[d.len++] = c;
0073     }
0074 
0075     q[d.len++] = '\0';
0076     return d;
0077 }
0078 
0079 struct data data_copy_file(FILE *f, size_t maxlen)
0080 {
0081     struct data d = empty_data;
0082 
0083     d = data_add_marker(d, TYPE_NONE, NULL);
0084     while (!feof(f) && (d.len < maxlen)) {
0085         size_t chunksize, ret;
0086 
0087         if (maxlen == (size_t)-1)
0088             chunksize = 4096;
0089         else
0090             chunksize = maxlen - d.len;
0091 
0092         d = data_grow_for(d, chunksize);
0093         ret = fread(d.val + d.len, 1, chunksize, f);
0094 
0095         if (ferror(f))
0096             die("Error reading file into data: %s", strerror(errno));
0097 
0098         if (d.len + ret < d.len)
0099             die("Overflow reading file into data\n");
0100 
0101         d.len += ret;
0102     }
0103 
0104     return d;
0105 }
0106 
0107 struct data data_append_data(struct data d, const void *p, int len)
0108 {
0109     d = data_grow_for(d, len);
0110     memcpy(d.val + d.len, p, len);
0111     d.len += len;
0112     return d;
0113 }
0114 
0115 struct data data_insert_at_marker(struct data d, struct marker *m,
0116                   const void *p, int len)
0117 {
0118     d = data_grow_for(d, len);
0119     memmove(d.val + m->offset + len, d.val + m->offset, d.len - m->offset);
0120     memcpy(d.val + m->offset, p, len);
0121     d.len += len;
0122 
0123     /* Adjust all markers after the one we're inserting at */
0124     m = m->next;
0125     for_each_marker(m)
0126         m->offset += len;
0127     return d;
0128 }
0129 
0130 static struct data data_append_markers(struct data d, struct marker *m)
0131 {
0132     struct marker **mp = &d.markers;
0133 
0134     /* Find the end of the markerlist */
0135     while (*mp)
0136         mp = &((*mp)->next);
0137     *mp = m;
0138     return d;
0139 }
0140 
0141 struct data data_merge(struct data d1, struct data d2)
0142 {
0143     struct data d;
0144     struct marker *m2 = d2.markers;
0145 
0146     d = data_append_markers(data_append_data(d1, d2.val, d2.len), m2);
0147 
0148     /* Adjust for the length of d1 */
0149     for_each_marker(m2)
0150         m2->offset += d1.len;
0151 
0152     d2.markers = NULL; /* So data_free() doesn't clobber them */
0153     data_free(d2);
0154 
0155     return d;
0156 }
0157 
0158 struct data data_append_integer(struct data d, uint64_t value, int bits)
0159 {
0160     uint8_t value_8;
0161     fdt16_t value_16;
0162     fdt32_t value_32;
0163     fdt64_t value_64;
0164 
0165     switch (bits) {
0166     case 8:
0167         value_8 = value;
0168         return data_append_data(d, &value_8, 1);
0169 
0170     case 16:
0171         value_16 = cpu_to_fdt16(value);
0172         return data_append_data(d, &value_16, 2);
0173 
0174     case 32:
0175         value_32 = cpu_to_fdt32(value);
0176         return data_append_data(d, &value_32, 4);
0177 
0178     case 64:
0179         value_64 = cpu_to_fdt64(value);
0180         return data_append_data(d, &value_64, 8);
0181 
0182     default:
0183         die("Invalid literal size (%d)\n", bits);
0184     }
0185 }
0186 
0187 struct data data_append_re(struct data d, uint64_t address, uint64_t size)
0188 {
0189     struct fdt_reserve_entry re;
0190 
0191     re.address = cpu_to_fdt64(address);
0192     re.size = cpu_to_fdt64(size);
0193 
0194     return data_append_data(d, &re, sizeof(re));
0195 }
0196 
0197 struct data data_append_cell(struct data d, cell_t word)
0198 {
0199     return data_append_integer(d, word, sizeof(word) * 8);
0200 }
0201 
0202 struct data data_append_addr(struct data d, uint64_t addr)
0203 {
0204     return data_append_integer(d, addr, sizeof(addr) * 8);
0205 }
0206 
0207 struct data data_append_byte(struct data d, uint8_t byte)
0208 {
0209     return data_append_data(d, &byte, 1);
0210 }
0211 
0212 struct data data_append_zeroes(struct data d, int len)
0213 {
0214     d = data_grow_for(d, len);
0215 
0216     memset(d.val + d.len, 0, len);
0217     d.len += len;
0218     return d;
0219 }
0220 
0221 struct data data_append_align(struct data d, int align)
0222 {
0223     int newlen = ALIGN(d.len, align);
0224     return data_append_zeroes(d, newlen - d.len);
0225 }
0226 
0227 struct data data_add_marker(struct data d, enum markertype type, char *ref)
0228 {
0229     struct marker *m;
0230 
0231     m = xmalloc(sizeof(*m));
0232     m->offset = d.len;
0233     m->type = type;
0234     m->ref = ref;
0235     m->next = NULL;
0236 
0237     return data_append_markers(d, m);
0238 }
0239 
0240 bool data_is_one_string(struct data d)
0241 {
0242     int i;
0243     int len = d.len;
0244 
0245     if (len == 0)
0246         return false;
0247 
0248     for (i = 0; i < len-1; i++)
0249         if (d.val[i] == '\0')
0250             return false;
0251 
0252     if (d.val[len-1] != '\0')
0253         return false;
0254 
0255     return true;
0256 }