summaryrefslogtreecommitdiff
path: root/scripts/dtc/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/dtc/util.c')
-rw-r--r--scripts/dtc/util.c242
1 files changed, 203 insertions, 39 deletions
diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c
index 2422c34e11df..412592320265 100644
--- a/scripts/dtc/util.c
+++ b/scripts/dtc/util.c
@@ -1,24 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright 2011 The Chromium Authors, All Rights Reserved.
* Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
*
* util_is_printable_string contributed by
* Pantelis Antoniou <pantelis.antoniou AT gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
*/
#include <ctype.h>
@@ -27,6 +13,7 @@
#include <stdarg.h>
#include <string.h>
#include <assert.h>
+#include <inttypes.h>
#include <errno.h>
#include <fcntl.h>
@@ -34,15 +21,91 @@
#include "libfdt.h"
#include "util.h"
+#include "version_gen.h"
+
+void fprint_path_escaped(FILE *fp, const char *path)
+{
+ const char *p = path;
+
+ while (*p) {
+ if (*p == ' ') {
+ fputc('\\', fp);
+ fputc(' ', fp);
+ } else {
+ fputc(*p, fp);
+ }
+
+ p++;
+ }
+}
char *xstrdup(const char *s)
{
int len = strlen(s) + 1;
- char *dup = xmalloc(len);
+ char *d = xmalloc(len);
- memcpy(dup, s, len);
+ memcpy(d, s, len);
- return dup;
+ return d;
+}
+
+char *xstrndup(const char *s, size_t n)
+{
+ size_t len = strnlen(s, n) + 1;
+ char *d = xmalloc(len);
+
+ memcpy(d, s, len - 1);
+ d[len - 1] = '\0';
+
+ return d;
+}
+
+int xavsprintf_append(char **strp, const char *fmt, va_list ap)
+{
+ int n, size = 0; /* start with 128 bytes */
+ char *p;
+ va_list ap_copy;
+
+ p = *strp;
+ if (p)
+ size = strlen(p);
+
+ va_copy(ap_copy, ap);
+ n = vsnprintf(NULL, 0, fmt, ap_copy) + 1;
+ va_end(ap_copy);
+
+ p = xrealloc(p, size + n);
+
+ n = vsnprintf(p + size, n, fmt, ap);
+
+ *strp = p;
+ return strlen(p);
+}
+
+int xasprintf_append(char **strp, const char *fmt, ...)
+{
+ int n;
+ va_list ap;
+
+ va_start(ap, fmt);
+ n = xavsprintf_append(strp, fmt, ap);
+ va_end(ap);
+
+ return n;
+}
+
+int xasprintf(char **strp, const char *fmt, ...)
+{
+ int n;
+ va_list ap;
+
+ *strp = NULL;
+
+ va_start(ap, fmt);
+ n = xavsprintf_append(strp, fmt, ap);
+ va_end(ap);
+
+ return n;
}
char *join_path(const char *path, const char *name)
@@ -69,10 +132,10 @@ char *join_path(const char *path, const char *name)
return str;
}
-int util_is_printable_string(const void *data, int len)
+bool util_is_printable_string(const void *data, int len)
{
const char *s = data;
- const char *ss;
+ const char *ss, *se;
/* zero length is not */
if (len == 0)
@@ -82,13 +145,19 @@ int util_is_printable_string(const void *data, int len)
if (s[len - 1] != '\0')
return 0;
- ss = s;
- while (*s && isprint(*s))
- s++;
+ se = s + len;
- /* not zero, or not done yet */
- if (*s != '\0' || (s + 1 - ss) < len)
- return 0;
+ while (s < se) {
+ ss = s;
+ while (s < se && *s && isprint((unsigned char)*s))
+ s++;
+
+ /* not zero, or not done yet */
+ if (*s != '\0' || s == ss)
+ return 0;
+
+ s++;
+ }
return 1;
}
@@ -145,7 +214,6 @@ char get_escape_char(const char *s, int *i)
int j = *i + 1;
char val;
- assert(c);
switch (c) {
case 'a':
val = '\a';
@@ -191,11 +259,11 @@ char get_escape_char(const char *s, int *i)
return val;
}
-int utilfdt_read_err(const char *filename, char **buffp)
+int utilfdt_read_err(const char *filename, char **buffp, size_t *len)
{
int fd = 0; /* assume stdin */
char *buf = NULL;
- off_t bufsize = 1024, offset = 0;
+ size_t bufsize = 1024, offset = 0;
int ret = 0;
*buffp = NULL;
@@ -206,16 +274,12 @@ int utilfdt_read_err(const char *filename, char **buffp)
}
/* Loop until we have read everything */
- buf = malloc(bufsize);
+ buf = xmalloc(bufsize);
do {
/* Expand the buffer to hold the next chunk */
if (offset == bufsize) {
bufsize *= 2;
- buf = realloc(buf, bufsize);
- if (!buf) {
- ret = ENOMEM;
- break;
- }
+ buf = xrealloc(buf, bufsize);
}
ret = read(fd, &buf[offset], bufsize - offset);
@@ -232,13 +296,15 @@ int utilfdt_read_err(const char *filename, char **buffp)
free(buf);
else
*buffp = buf;
+ if (len)
+ *len = bufsize;
return ret;
}
-char *utilfdt_read(const char *filename)
+char *utilfdt_read(const char *filename, size_t *len)
{
char *buff;
- int ret = utilfdt_read_err(filename, &buff);
+ int ret = utilfdt_read_err(filename, &buff, len);
if (ret) {
fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename,
@@ -314,11 +380,11 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size)
}
/* we should now have a type */
- if ((*fmt == '\0') || !strchr("iuxs", *fmt))
+ if ((*fmt == '\0') || !strchr("iuxsr", *fmt))
return -1;
/* convert qualifier (bhL) to byte size */
- if (*fmt != 's')
+ if (*fmt != 's' && *fmt != 'r')
*size = qualifier == 'b' ? 1 :
qualifier == 'h' ? 2 :
qualifier == 'l' ? 4 : -1;
@@ -329,3 +395,101 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size)
return -1;
return 0;
}
+
+void utilfdt_print_data(const char *data, int len)
+{
+ int i;
+ const char *s;
+
+ /* no data, don't print */
+ if (len == 0)
+ return;
+
+ if (util_is_printable_string(data, len)) {
+ printf(" = ");
+
+ s = data;
+ do {
+ printf("\"%s\"", s);
+ s += strlen(s) + 1;
+ if (s < data + len)
+ printf(", ");
+ } while (s < data + len);
+
+ } else if ((len % 4) == 0) {
+ const fdt32_t *cell = (const fdt32_t *)data;
+
+ printf(" = <");
+ for (i = 0, len /= 4; i < len; i++)
+ printf("0x%08" PRIx32 "%s", fdt32_to_cpu(cell[i]),
+ i < (len - 1) ? " " : "");
+ printf(">");
+ } else {
+ const unsigned char *p = (const unsigned char *)data;
+ printf(" = [");
+ for (i = 0; i < len; i++)
+ printf("%02x%s", *p++, i < len - 1 ? " " : "");
+ printf("]");
+ }
+}
+
+void NORETURN util_version(void)
+{
+ printf("Version: %s\n", DTC_VERSION);
+ exit(0);
+}
+
+void NORETURN util_usage(const char *errmsg, const char *synopsis,
+ const char *short_opts,
+ struct option const long_opts[],
+ const char * const opts_help[])
+{
+ FILE *fp = errmsg ? stderr : stdout;
+ const char a_arg[] = "<arg>";
+ size_t a_arg_len = strlen(a_arg) + 1;
+ size_t i;
+ int optlen;
+
+ fprintf(fp,
+ "Usage: %s\n"
+ "\n"
+ "Options: -[%s]\n", synopsis, short_opts);
+
+ /* prescan the --long opt length to auto-align */
+ optlen = 0;
+ for (i = 0; long_opts[i].name; ++i) {
+ /* +1 is for space between --opt and help text */
+ int l = strlen(long_opts[i].name) + 1;
+ if (long_opts[i].has_arg == a_argument)
+ l += a_arg_len;
+ if (optlen < l)
+ optlen = l;
+ }
+
+ for (i = 0; long_opts[i].name; ++i) {
+ /* helps when adding new applets or options */
+ assert(opts_help[i] != NULL);
+
+ /* first output the short flag if it has one */
+ if (long_opts[i].val > '~')
+ fprintf(fp, " ");
+ else
+ fprintf(fp, " -%c, ", long_opts[i].val);
+
+ /* then the long flag */
+ if (long_opts[i].has_arg == no_argument)
+ fprintf(fp, "--%-*s", optlen, long_opts[i].name);
+ else
+ fprintf(fp, "--%s %s%*s", long_opts[i].name, a_arg,
+ (int)(optlen - strlen(long_opts[i].name) - a_arg_len), "");
+
+ /* finally the help text */
+ fprintf(fp, "%s\n", opts_help[i]);
+ }
+
+ if (errmsg) {
+ fprintf(fp, "\nError: %s\n", errmsg);
+ exit(EXIT_FAILURE);
+ } else
+ exit(EXIT_SUCCESS);
+}