diff options
author | Simon Glass <sjg@chromium.org> | 2011-09-22 10:11:02 -0700 |
---|---|---|
committer | Jon Loeliger <jdl@jdl.com> | 2011-09-22 13:49:33 -0500 |
commit | 36204fdf742cabc074617648a5b2cf62409dc40b (patch) | |
tree | 5ae8e7f6daf783865231df90c7c23a1a7747e9a9 /util.c | |
parent | 9ebd9b4a56e54656431111e5ea7cd74e651910bf (diff) | |
download | dtc-36204fdf742cabc074617648a5b2cf62409dc40b.zip dtc-36204fdf742cabc074617648a5b2cf62409dc40b.tar.gz dtc-36204fdf742cabc074617648a5b2cf62409dc40b.tar.bz2 |
Add fdt read/write utility functions
This adds higher-level libfdt operations for reading/writing an fdt
blob from/to a file, as well as a function to decode a data type string
as will be used by fdtget, fdtput.
This also adds a few tests for the simple type argument supported by
utilfdt_decode_type.
Signed-off-by: Simon Glass <sjg@chromium.org>
Acked-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'util.c')
-rw-r--r-- | util.c | 142 |
1 files changed, 142 insertions, 0 deletions
@@ -1,4 +1,5 @@ /* + * Copyright 2011 The Chromium Authors, All Rights Reserved. * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. * * util_is_printable_string contributed by @@ -27,6 +28,11 @@ #include <string.h> #include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> + +#include "libfdt.h" #include "util.h" char *xstrdup(const char *s) @@ -184,3 +190,139 @@ char get_escape_char(const char *s, int *i) (*i) = j; return val; } + +int utilfdt_read_err(const char *filename, char **buffp) +{ + int fd = 0; /* assume stdin */ + char *buf = NULL; + off_t bufsize = 1024, offset = 0; + int ret = 0; + + *buffp = NULL; + if (strcmp(filename, "-") != 0) { + fd = open(filename, O_RDONLY); + if (fd < 0) + return errno; + } + + /* Loop until we have read everything */ + buf = malloc(bufsize); + do { + /* Expand the buffer to hold the next chunk */ + if (offset == bufsize) { + bufsize *= 2; + buf = realloc(buf, bufsize); + if (!buf) { + ret = ENOMEM; + break; + } + } + + ret = read(fd, &buf[offset], bufsize - offset); + if (ret < 0) { + ret = errno; + break; + } + offset += ret; + } while (ret != 0); + + /* Clean up, including closing stdin; return errno on error */ + close(fd); + if (ret) + free(buf); + else + *buffp = buf; + return ret; +} + +char *utilfdt_read(const char *filename) +{ + char *buff; + int ret = utilfdt_read_err(filename, &buff); + + if (ret) { + fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename, + strerror(ret)); + return NULL; + } + /* Successful read */ + return buff; +} + +int utilfdt_write_err(const char *filename, const void *blob) +{ + int fd = 1; /* assume stdout */ + int totalsize; + int offset; + int ret = 0; + const char *ptr = blob; + + if (strcmp(filename, "-") != 0) { + fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (fd < 0) + return errno; + } + + totalsize = fdt_totalsize(blob); + offset = 0; + + while (offset < totalsize) { + ret = write(fd, ptr + offset, totalsize - offset); + if (ret < 0) { + ret = -errno; + break; + } + offset += ret; + } + /* Close the file/stdin; return errno on error */ + if (fd != 1) + close(fd); + return ret < 0 ? -ret : 0; +} + + +int utilfdt_write(const char *filename, const void *blob) +{ + int ret = utilfdt_write_err(filename, blob); + + if (ret) { + fprintf(stderr, "Couldn't write blob to '%s': %s\n", filename, + strerror(ret)); + } + return ret ? -1 : 0; +} + +int utilfdt_decode_type(const char *fmt, int *type, int *size) +{ + int qualifier = 0; + + /* get the conversion qualifier */ + *size = -1; + if (strchr("hlLb", *fmt)) { + qualifier = *fmt++; + if (qualifier == *fmt) { + switch (*fmt++) { +/* TODO: case 'l': qualifier = 'L'; break;*/ + case 'h': + qualifier = 'b'; + break; + } + } + } + + /* we should now have a type */ + if (!strchr("iuxs", *fmt)) + return -1; + + /* convert qualifier (bhL) to byte size */ + if (*fmt != 's') + *size = qualifier == 'b' ? 1 : + qualifier == 'h' ? 2 : + qualifier == 'l' ? 4 : -1; + *type = *fmt++; + + /* that should be it! */ + if (*fmt) + return -1; + return 0; +} |