~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to dtc/util.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2011 The Chromium Authors, All Rights Reserved.
 
3
 * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
 
4
 *
 
5
 * util_is_printable_string contributed by
 
6
 *      Pantelis Antoniou <pantelis.antoniou AT gmail.com>
 
7
 *
 
8
 * This program is free software; you can redistribute it and/or
 
9
 * modify it under the terms of the GNU General Public License as
 
10
 * published by the Free Software Foundation; either version 2 of the
 
11
 * License, or (at your option) any later version.
 
12
 *
 
13
 *  This program is distributed in the hope that it will be useful,
 
14
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
16
 *  General Public License for more details.
 
17
 *
 
18
 *  You should have received a copy of the GNU General Public License
 
19
 *  along with this program; if not, write to the Free Software
 
20
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 
21
 *                                                                   USA
 
22
 */
 
23
 
 
24
#include <ctype.h>
 
25
#include <stdio.h>
 
26
#include <stdlib.h>
 
27
#include <stdarg.h>
 
28
#include <string.h>
 
29
#include <assert.h>
 
30
 
 
31
#include <errno.h>
 
32
#include <fcntl.h>
 
33
#include <unistd.h>
 
34
 
 
35
#include "libfdt.h"
 
36
#include "util.h"
 
37
#include "version_gen.h"
 
38
 
 
39
char *xstrdup(const char *s)
 
40
{
 
41
        int len = strlen(s) + 1;
 
42
        char *d = xmalloc(len);
 
43
 
 
44
        memcpy(d, s, len);
 
45
 
 
46
        return d;
 
47
}
 
48
 
 
49
/* based in part from (3) vsnprintf */
 
50
int xasprintf(char **strp, const char *fmt, ...)
 
51
{
 
52
        int n, size = 128;      /* start with 128 bytes */
 
53
        char *p;
 
54
        va_list ap;
 
55
 
 
56
        /* initial pointer is NULL making the fist realloc to be malloc */
 
57
        p = NULL;
 
58
        while (1) {
 
59
                p = xrealloc(p, size);
 
60
 
 
61
                /* Try to print in the allocated space. */
 
62
                va_start(ap, fmt);
 
63
                n = vsnprintf(p, size, fmt, ap);
 
64
                va_end(ap);
 
65
 
 
66
                /* If that worked, return the string. */
 
67
                if (n > -1 && n < size)
 
68
                        break;
 
69
                /* Else try again with more space. */
 
70
                if (n > -1)     /* glibc 2.1 */
 
71
                        size = n + 1; /* precisely what is needed */
 
72
                else            /* glibc 2.0 */
 
73
                        size *= 2; /* twice the old size */
 
74
        }
 
75
        *strp = p;
 
76
        return strlen(p);
 
77
}
 
78
 
 
79
char *join_path(const char *path, const char *name)
 
80
{
 
81
        int lenp = strlen(path);
 
82
        int lenn = strlen(name);
 
83
        int len;
 
84
        int needslash = 1;
 
85
        char *str;
 
86
 
 
87
        len = lenp + lenn + 2;
 
88
        if ((lenp > 0) && (path[lenp-1] == '/')) {
 
89
                needslash = 0;
 
90
                len--;
 
91
        }
 
92
 
 
93
        str = xmalloc(len);
 
94
        memcpy(str, path, lenp);
 
95
        if (needslash) {
 
96
                str[lenp] = '/';
 
97
                lenp++;
 
98
        }
 
99
        memcpy(str+lenp, name, lenn+1);
 
100
        return str;
 
101
}
 
102
 
 
103
bool util_is_printable_string(const void *data, int len)
 
104
{
 
105
        const char *s = data;
 
106
        const char *ss, *se;
 
107
 
 
108
        /* zero length is not */
 
109
        if (len == 0)
 
110
                return 0;
 
111
 
 
112
        /* must terminate with zero */
 
113
        if (s[len - 1] != '\0')
 
114
                return 0;
 
115
 
 
116
        se = s + len;
 
117
 
 
118
        while (s < se) {
 
119
                ss = s;
 
120
                while (s < se && *s && isprint((unsigned char)*s))
 
121
                        s++;
 
122
 
 
123
                /* not zero, or not done yet */
 
124
                if (*s != '\0' || s == ss)
 
125
                        return 0;
 
126
 
 
127
                s++;
 
128
        }
 
129
 
 
130
        return 1;
 
131
}
 
132
 
 
133
/*
 
134
 * Parse a octal encoded character starting at index i in string s.  The
 
135
 * resulting character will be returned and the index i will be updated to
 
136
 * point at the character directly after the end of the encoding, this may be
 
137
 * the '\0' terminator of the string.
 
138
 */
 
139
static char get_oct_char(const char *s, int *i)
 
140
{
 
141
        char x[4];
 
142
        char *endx;
 
143
        long val;
 
144
 
 
145
        x[3] = '\0';
 
146
        strncpy(x, s + *i, 3);
 
147
 
 
148
        val = strtol(x, &endx, 8);
 
149
 
 
150
        assert(endx > x);
 
151
 
 
152
        (*i) += endx - x;
 
153
        return val;
 
154
}
 
155
 
 
156
/*
 
157
 * Parse a hexadecimal encoded character starting at index i in string s.  The
 
158
 * resulting character will be returned and the index i will be updated to
 
159
 * point at the character directly after the end of the encoding, this may be
 
160
 * the '\0' terminator of the string.
 
161
 */
 
162
static char get_hex_char(const char *s, int *i)
 
163
{
 
164
        char x[3];
 
165
        char *endx;
 
166
        long val;
 
167
 
 
168
        x[2] = '\0';
 
169
        strncpy(x, s + *i, 2);
 
170
 
 
171
        val = strtol(x, &endx, 16);
 
172
        if (!(endx  > x))
 
173
                die("\\x used with no following hex digits\n");
 
174
 
 
175
        (*i) += endx - x;
 
176
        return val;
 
177
}
 
178
 
 
179
char get_escape_char(const char *s, int *i)
 
180
{
 
181
        char    c = s[*i];
 
182
        int     j = *i + 1;
 
183
        char    val;
 
184
 
 
185
        switch (c) {
 
186
        case 'a':
 
187
                val = '\a';
 
188
                break;
 
189
        case 'b':
 
190
                val = '\b';
 
191
                break;
 
192
        case 't':
 
193
                val = '\t';
 
194
                break;
 
195
        case 'n':
 
196
                val = '\n';
 
197
                break;
 
198
        case 'v':
 
199
                val = '\v';
 
200
                break;
 
201
        case 'f':
 
202
                val = '\f';
 
203
                break;
 
204
        case 'r':
 
205
                val = '\r';
 
206
                break;
 
207
        case '0':
 
208
        case '1':
 
209
        case '2':
 
210
        case '3':
 
211
        case '4':
 
212
        case '5':
 
213
        case '6':
 
214
        case '7':
 
215
                j--; /* need to re-read the first digit as
 
216
                      * part of the octal value */
 
217
                val = get_oct_char(s, &j);
 
218
                break;
 
219
        case 'x':
 
220
                val = get_hex_char(s, &j);
 
221
                break;
 
222
        default:
 
223
                val = c;
 
224
        }
 
225
 
 
226
        (*i) = j;
 
227
        return val;
 
228
}
 
229
 
 
230
int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len)
 
231
{
 
232
        int fd = 0;     /* assume stdin */
 
233
        char *buf = NULL;
 
234
        off_t bufsize = 1024, offset = 0;
 
235
        int ret = 0;
 
236
 
 
237
        *buffp = NULL;
 
238
        if (strcmp(filename, "-") != 0) {
 
239
                fd = open(filename, O_RDONLY);
 
240
                if (fd < 0)
 
241
                        return errno;
 
242
        }
 
243
 
 
244
        /* Loop until we have read everything */
 
245
        buf = xmalloc(bufsize);
 
246
        do {
 
247
                /* Expand the buffer to hold the next chunk */
 
248
                if (offset == bufsize) {
 
249
                        bufsize *= 2;
 
250
                        buf = xrealloc(buf, bufsize);
 
251
                }
 
252
 
 
253
                ret = read(fd, &buf[offset], bufsize - offset);
 
254
                if (ret < 0) {
 
255
                        ret = errno;
 
256
                        break;
 
257
                }
 
258
                offset += ret;
 
259
        } while (ret != 0);
 
260
 
 
261
        /* Clean up, including closing stdin; return errno on error */
 
262
        close(fd);
 
263
        if (ret)
 
264
                free(buf);
 
265
        else
 
266
                *buffp = buf;
 
267
        *len = bufsize;
 
268
        return ret;
 
269
}
 
270
 
 
271
int utilfdt_read_err(const char *filename, char **buffp)
 
272
{
 
273
        off_t len;
 
274
        return utilfdt_read_err_len(filename, buffp, &len);
 
275
}
 
276
 
 
277
char *utilfdt_read_len(const char *filename, off_t *len)
 
278
{
 
279
        char *buff;
 
280
        int ret = utilfdt_read_err_len(filename, &buff, len);
 
281
 
 
282
        if (ret) {
 
283
                fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename,
 
284
                        strerror(ret));
 
285
                return NULL;
 
286
        }
 
287
        /* Successful read */
 
288
        return buff;
 
289
}
 
290
 
 
291
char *utilfdt_read(const char *filename)
 
292
{
 
293
        off_t len;
 
294
        return utilfdt_read_len(filename, &len);
 
295
}
 
296
 
 
297
int utilfdt_write_err(const char *filename, const void *blob)
 
298
{
 
299
        int fd = 1;     /* assume stdout */
 
300
        int totalsize;
 
301
        int offset;
 
302
        int ret = 0;
 
303
        const char *ptr = blob;
 
304
 
 
305
        if (strcmp(filename, "-") != 0) {
 
306
                fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
 
307
                if (fd < 0)
 
308
                        return errno;
 
309
        }
 
310
 
 
311
        totalsize = fdt_totalsize(blob);
 
312
        offset = 0;
 
313
 
 
314
        while (offset < totalsize) {
 
315
                ret = write(fd, ptr + offset, totalsize - offset);
 
316
                if (ret < 0) {
 
317
                        ret = -errno;
 
318
                        break;
 
319
                }
 
320
                offset += ret;
 
321
        }
 
322
        /* Close the file/stdin; return errno on error */
 
323
        if (fd != 1)
 
324
                close(fd);
 
325
        return ret < 0 ? -ret : 0;
 
326
}
 
327
 
 
328
 
 
329
int utilfdt_write(const char *filename, const void *blob)
 
330
{
 
331
        int ret = utilfdt_write_err(filename, blob);
 
332
 
 
333
        if (ret) {
 
334
                fprintf(stderr, "Couldn't write blob to '%s': %s\n", filename,
 
335
                        strerror(ret));
 
336
        }
 
337
        return ret ? -1 : 0;
 
338
}
 
339
 
 
340
int utilfdt_decode_type(const char *fmt, int *type, int *size)
 
341
{
 
342
        int qualifier = 0;
 
343
 
 
344
        if (!*fmt)
 
345
                return -1;
 
346
 
 
347
        /* get the conversion qualifier */
 
348
        *size = -1;
 
349
        if (strchr("hlLb", *fmt)) {
 
350
                qualifier = *fmt++;
 
351
                if (qualifier == *fmt) {
 
352
                        switch (*fmt++) {
 
353
/* TODO:                case 'l': qualifier = 'L'; break;*/
 
354
                        case 'h':
 
355
                                qualifier = 'b';
 
356
                                break;
 
357
                        }
 
358
                }
 
359
        }
 
360
 
 
361
        /* we should now have a type */
 
362
        if ((*fmt == '\0') || !strchr("iuxs", *fmt))
 
363
                return -1;
 
364
 
 
365
        /* convert qualifier (bhL) to byte size */
 
366
        if (*fmt != 's')
 
367
                *size = qualifier == 'b' ? 1 :
 
368
                                qualifier == 'h' ? 2 :
 
369
                                qualifier == 'l' ? 4 : -1;
 
370
        *type = *fmt++;
 
371
 
 
372
        /* that should be it! */
 
373
        if (*fmt)
 
374
                return -1;
 
375
        return 0;
 
376
}
 
377
 
 
378
void utilfdt_print_data(const char *data, int len)
 
379
{
 
380
        int i;
 
381
        const char *s;
 
382
 
 
383
        /* no data, don't print */
 
384
        if (len == 0)
 
385
                return;
 
386
 
 
387
        if (util_is_printable_string(data, len)) {
 
388
                printf(" = ");
 
389
 
 
390
                s = data;
 
391
                do {
 
392
                        printf("\"%s\"", s);
 
393
                        s += strlen(s) + 1;
 
394
                        if (s < data + len)
 
395
                                printf(", ");
 
396
                } while (s < data + len);
 
397
 
 
398
        } else if ((len % 4) == 0) {
 
399
                const fdt32_t *cell = (const fdt32_t *)data;
 
400
 
 
401
                printf(" = <");
 
402
                for (i = 0, len /= 4; i < len; i++)
 
403
                        printf("0x%08x%s", fdt32_to_cpu(cell[i]),
 
404
                               i < (len - 1) ? " " : "");
 
405
                printf(">");
 
406
        } else {
 
407
                const unsigned char *p = (const unsigned char *)data;
 
408
                printf(" = [");
 
409
                for (i = 0; i < len; i++)
 
410
                        printf("%02x%s", *p++, i < len - 1 ? " " : "");
 
411
                printf("]");
 
412
        }
 
413
}
 
414
 
 
415
void NORETURN util_version(void)
 
416
{
 
417
        printf("Version: %s\n", DTC_VERSION);
 
418
        exit(0);
 
419
}
 
420
 
 
421
void NORETURN util_usage(const char *errmsg, const char *synopsis,
 
422
                         const char *short_opts,
 
423
                         struct option const long_opts[],
 
424
                         const char * const opts_help[])
 
425
{
 
426
        FILE *fp = errmsg ? stderr : stdout;
 
427
        const char a_arg[] = "<arg>";
 
428
        size_t a_arg_len = strlen(a_arg) + 1;
 
429
        size_t i;
 
430
        int optlen;
 
431
 
 
432
        fprintf(fp,
 
433
                "Usage: %s\n"
 
434
                "\n"
 
435
                "Options: -[%s]\n", synopsis, short_opts);
 
436
 
 
437
        /* prescan the --long opt length to auto-align */
 
438
        optlen = 0;
 
439
        for (i = 0; long_opts[i].name; ++i) {
 
440
                /* +1 is for space between --opt and help text */
 
441
                int l = strlen(long_opts[i].name) + 1;
 
442
                if (long_opts[i].has_arg == a_argument)
 
443
                        l += a_arg_len;
 
444
                if (optlen < l)
 
445
                        optlen = l;
 
446
        }
 
447
 
 
448
        for (i = 0; long_opts[i].name; ++i) {
 
449
                /* helps when adding new applets or options */
 
450
                assert(opts_help[i] != NULL);
 
451
 
 
452
                /* first output the short flag if it has one */
 
453
                if (long_opts[i].val > '~')
 
454
                        fprintf(fp, "      ");
 
455
                else
 
456
                        fprintf(fp, "  -%c, ", long_opts[i].val);
 
457
 
 
458
                /* then the long flag */
 
459
                if (long_opts[i].has_arg == no_argument)
 
460
                        fprintf(fp, "--%-*s", optlen, long_opts[i].name);
 
461
                else
 
462
                        fprintf(fp, "--%s %s%*s", long_opts[i].name, a_arg,
 
463
                                (int)(optlen - strlen(long_opts[i].name) - a_arg_len), "");
 
464
 
 
465
                /* finally the help text */
 
466
                fprintf(fp, "%s\n", opts_help[i]);
 
467
        }
 
468
 
 
469
        if (errmsg) {
 
470
                fprintf(fp, "\nError: %s\n", errmsg);
 
471
                exit(EXIT_FAILURE);
 
472
        } else
 
473
                exit(EXIT_SUCCESS);
 
474
}