EmbeddedPkg/FdtLib: Update FdtLib to v1.4.5
Update the FdtLib so that new APIs provided by FdtLib like fdt_address_cells, fdt_size_cells etc. can be used. Reference code: https://git.kernel.org/pub/scm/utils/dtc/dtc.git/tree/libfdt?h=v1.4.5 Cc: Leif Lindholm <leif.lindholm@linaro.org> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Pankaj Bansal <pankaj.bansal@nxp.com> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
This commit is contained in:
committed by
Ard Biesheuvel
parent
0bc94c748b
commit
a099239015
@@ -32,6 +32,7 @@
|
||||
fdt_sw.c
|
||||
fdt_wip.c
|
||||
fdt.c
|
||||
fdt_addresses.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
|
@@ -6,5 +6,6 @@
|
||||
LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1
|
||||
LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h
|
||||
LIBFDT_VERSION = version.lds
|
||||
LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c
|
||||
LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c \
|
||||
fdt_addresses.c
|
||||
LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
|
||||
|
@@ -76,18 +76,19 @@ int fdt_check_header(const void *fdt)
|
||||
|
||||
const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
|
||||
{
|
||||
const char *p;
|
||||
unsigned absoffset = offset + fdt_off_dt_struct(fdt);
|
||||
|
||||
if ((absoffset < offset)
|
||||
|| ((absoffset + len) < absoffset)
|
||||
|| (absoffset + len) > fdt_totalsize(fdt))
|
||||
return NULL;
|
||||
|
||||
if (fdt_version(fdt) >= 0x11)
|
||||
if (((offset + len) < offset)
|
||||
|| ((offset + len) > fdt_size_dt_struct(fdt)))
|
||||
return NULL;
|
||||
|
||||
p = _fdt_offset_ptr(fdt, offset);
|
||||
|
||||
if (p + len < p)
|
||||
return NULL;
|
||||
return p;
|
||||
return _fdt_offset_ptr(fdt, offset);
|
||||
}
|
||||
|
||||
uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
|
||||
|
96
EmbeddedPkg/Library/FdtLib/fdt_addresses.c
Normal file
96
EmbeddedPkg/Library/FdtLib/fdt_addresses.c
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* libfdt - Flat Device Tree manipulation
|
||||
* Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au>
|
||||
*
|
||||
* libfdt is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
*
|
||||
* a) This library 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 library 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 library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*
|
||||
* Alternatively,
|
||||
*
|
||||
* b) Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "libfdt_env.h"
|
||||
|
||||
#include <fdt.h>
|
||||
#include <libfdt.h>
|
||||
|
||||
#include "libfdt_internal.h"
|
||||
|
||||
int fdt_address_cells(const void *fdt, int nodeoffset)
|
||||
{
|
||||
const fdt32_t *ac;
|
||||
int val;
|
||||
int len;
|
||||
|
||||
ac = fdt_getprop(fdt, nodeoffset, "#address-cells", &len);
|
||||
if (!ac)
|
||||
return 2;
|
||||
|
||||
if (len != sizeof(*ac))
|
||||
return -FDT_ERR_BADNCELLS;
|
||||
|
||||
val = fdt32_to_cpu(*ac);
|
||||
if ((val <= 0) || (val > FDT_MAX_NCELLS))
|
||||
return -FDT_ERR_BADNCELLS;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
int fdt_size_cells(const void *fdt, int nodeoffset)
|
||||
{
|
||||
const fdt32_t *sc;
|
||||
int val;
|
||||
int len;
|
||||
|
||||
sc = fdt_getprop(fdt, nodeoffset, "#size-cells", &len);
|
||||
if (!sc)
|
||||
return 2;
|
||||
|
||||
if (len != sizeof(*sc))
|
||||
return -FDT_ERR_BADNCELLS;
|
||||
|
||||
val = fdt32_to_cpu(*sc);
|
||||
if ((val < 0) || (val > FDT_MAX_NCELLS))
|
||||
return -FDT_ERR_BADNCELLS;
|
||||
|
||||
return val;
|
||||
}
|
@@ -81,4 +81,3 @@ int fdt_create_empty_tree(void *buf, int bufsize)
|
||||
|
||||
return fdt_open_into(buf, buf, bufsize);
|
||||
}
|
||||
|
||||
|
@@ -60,7 +60,7 @@ static int _fdt_nodename_eq(const void *fdt, int offset,
|
||||
{
|
||||
const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
|
||||
|
||||
if (! p)
|
||||
if (!p)
|
||||
/* short match */
|
||||
return 0;
|
||||
|
||||
@@ -88,6 +88,32 @@ static int _fdt_string_eq(const void *fdt, int stroffset,
|
||||
return (strlen(p) == len) && (memcmp(p, s, len) == 0);
|
||||
}
|
||||
|
||||
uint32_t fdt_get_max_phandle(const void *fdt)
|
||||
{
|
||||
uint32_t max_phandle = 0;
|
||||
int offset;
|
||||
|
||||
for (offset = fdt_next_node(fdt, -1, NULL);;
|
||||
offset = fdt_next_node(fdt, offset, NULL)) {
|
||||
uint32_t phandle;
|
||||
|
||||
if (offset == -FDT_ERR_NOTFOUND)
|
||||
return max_phandle;
|
||||
|
||||
if (offset < 0)
|
||||
return (uint32_t)-1;
|
||||
|
||||
phandle = fdt_get_phandle(fdt, offset);
|
||||
if (phandle == (uint32_t)-1)
|
||||
continue;
|
||||
|
||||
if (phandle > max_phandle)
|
||||
max_phandle = phandle;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
|
||||
{
|
||||
FDT_CHECK_HEADER(fdt);
|
||||
@@ -154,9 +180,9 @@ int fdt_subnode_offset(const void *fdt, int parentoffset,
|
||||
return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name));
|
||||
}
|
||||
|
||||
int fdt_path_offset(const void *fdt, const char *path)
|
||||
int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
|
||||
{
|
||||
const char *end = path + strlen(path);
|
||||
const char *end = path + namelen;
|
||||
const char *p = path;
|
||||
int offset = 0;
|
||||
|
||||
@@ -164,7 +190,7 @@ int fdt_path_offset(const void *fdt, const char *path)
|
||||
|
||||
/* see if we have an alias */
|
||||
if (*path != '/') {
|
||||
const char *q = strchr(path, '/');
|
||||
const char *q = memchr(path, '/', end - p);
|
||||
|
||||
if (!q)
|
||||
q = end;
|
||||
@@ -177,14 +203,15 @@ int fdt_path_offset(const void *fdt, const char *path)
|
||||
p = q;
|
||||
}
|
||||
|
||||
while (*p) {
|
||||
while (p < end) {
|
||||
const char *q;
|
||||
|
||||
while (*p == '/')
|
||||
while (*p == '/') {
|
||||
p++;
|
||||
if (! *p)
|
||||
return offset;
|
||||
q = strchr(p, '/');
|
||||
if (p == end)
|
||||
return offset;
|
||||
}
|
||||
q = memchr(p, '/', end - p);
|
||||
if (! q)
|
||||
q = end;
|
||||
|
||||
@@ -198,6 +225,11 @@ int fdt_path_offset(const void *fdt, const char *path)
|
||||
return offset;
|
||||
}
|
||||
|
||||
int fdt_path_offset(const void *fdt, const char *path)
|
||||
{
|
||||
return fdt_path_offset_namelen(fdt, path, strlen(path));
|
||||
}
|
||||
|
||||
const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
|
||||
{
|
||||
const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset);
|
||||
@@ -267,8 +299,7 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt,
|
||||
(offset = fdt_next_property_offset(fdt, offset))) {
|
||||
const struct fdt_property *prop;
|
||||
|
||||
prop = fdt_get_property_by_offset(fdt, offset, lenp);
|
||||
if (!prop) {
|
||||
if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) {
|
||||
offset = -FDT_ERR_INTERNAL;
|
||||
break;
|
||||
}
|
||||
@@ -296,7 +327,7 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
|
||||
const struct fdt_property *prop;
|
||||
|
||||
prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
|
||||
if (! prop)
|
||||
if (!prop)
|
||||
return NULL;
|
||||
|
||||
return prop->data;
|
||||
@@ -495,7 +526,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
|
||||
{
|
||||
int offset;
|
||||
|
||||
if ((phandle == 0) || (phandle == (uint32_t)-1))
|
||||
if ((phandle == 0) || (phandle == -1))
|
||||
return -FDT_ERR_BADPHANDLE;
|
||||
|
||||
FDT_CHECK_HEADER(fdt);
|
||||
@@ -533,6 +564,106 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property)
|
||||
{
|
||||
const char *list, *end;
|
||||
int length, count = 0;
|
||||
|
||||
list = fdt_getprop(fdt, nodeoffset, property, &length);
|
||||
if (!list)
|
||||
return length;
|
||||
|
||||
end = list + length;
|
||||
|
||||
while (list < end) {
|
||||
length = strnlen(list, end - list) + 1;
|
||||
|
||||
/* Abort if the last string isn't properly NUL-terminated. */
|
||||
if (list + length > end)
|
||||
return -FDT_ERR_BADVALUE;
|
||||
|
||||
list += length;
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
|
||||
const char *string)
|
||||
{
|
||||
int length, len, idx = 0;
|
||||
const char *list, *end;
|
||||
|
||||
list = fdt_getprop(fdt, nodeoffset, property, &length);
|
||||
if (!list)
|
||||
return length;
|
||||
|
||||
len = strlen(string) + 1;
|
||||
end = list + length;
|
||||
|
||||
while (list < end) {
|
||||
length = strnlen(list, end - list) + 1;
|
||||
|
||||
/* Abort if the last string isn't properly NUL-terminated. */
|
||||
if (list + length > end)
|
||||
return -FDT_ERR_BADVALUE;
|
||||
|
||||
if (length == len && memcmp(list, string, length) == 0)
|
||||
return idx;
|
||||
|
||||
list += length;
|
||||
idx++;
|
||||
}
|
||||
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
}
|
||||
|
||||
const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
|
||||
const char *property, int idx,
|
||||
int *lenp)
|
||||
{
|
||||
const char *list, *end;
|
||||
int length;
|
||||
|
||||
list = fdt_getprop(fdt, nodeoffset, property, &length);
|
||||
if (!list) {
|
||||
if (lenp)
|
||||
*lenp = length;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
end = list + length;
|
||||
|
||||
while (list < end) {
|
||||
length = strnlen(list, end - list) + 1;
|
||||
|
||||
/* Abort if the last string isn't properly NUL-terminated. */
|
||||
if (list + length > end) {
|
||||
if (lenp)
|
||||
*lenp = -FDT_ERR_BADVALUE;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (idx == 0) {
|
||||
if (lenp)
|
||||
*lenp = length - 1;
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
list += length;
|
||||
idx--;
|
||||
}
|
||||
|
||||
if (lenp)
|
||||
*lenp = -FDT_ERR_NOTFOUND;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int fdt_node_check_compatible(const void *fdt, int nodeoffset,
|
||||
const char *compatible)
|
||||
{
|
||||
@@ -542,10 +673,8 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
|
||||
prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
|
||||
if (!prop)
|
||||
return len;
|
||||
if (fdt_stringlist_contains(prop, len, compatible))
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
|
||||
return !fdt_stringlist_contains(prop, len, compatible);
|
||||
}
|
||||
|
||||
int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
|
||||
|
@@ -84,9 +84,9 @@ static int _fdt_rw_check_header(void *fdt)
|
||||
|
||||
#define FDT_RW_CHECK_HEADER(fdt) \
|
||||
{ \
|
||||
int err; \
|
||||
if ((err = _fdt_rw_check_header(fdt)) != 0) \
|
||||
return err; \
|
||||
int __err; \
|
||||
if ((__err = _fdt_rw_check_header(fdt)) != 0) \
|
||||
return __err; \
|
||||
}
|
||||
|
||||
static inline int _fdt_data_size(void *fdt)
|
||||
@@ -101,6 +101,8 @@ static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)
|
||||
|
||||
if (((p + oldlen) < p) || ((p + oldlen) > end))
|
||||
return -FDT_ERR_BADOFFSET;
|
||||
if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt))
|
||||
return -FDT_ERR_BADOFFSET;
|
||||
if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
|
||||
return -FDT_ERR_NOSPACE;
|
||||
memmove(p + newlen, p + oldlen, end - p - oldlen);
|
||||
@@ -126,8 +128,7 @@ static int _fdt_splice_struct(void *fdt, void *p,
|
||||
int delta = newlen - oldlen;
|
||||
int err;
|
||||
|
||||
err = _fdt_splice(fdt, p, oldlen, newlen);
|
||||
if (err)
|
||||
if ((err = _fdt_splice(fdt, p, oldlen, newlen)))
|
||||
return err;
|
||||
|
||||
fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
|
||||
@@ -141,8 +142,7 @@ static int _fdt_splice_string(void *fdt, int newlen)
|
||||
+ fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
|
||||
int err;
|
||||
|
||||
err = _fdt_splice(fdt, p, 0, newlen);
|
||||
if (err)
|
||||
if ((err = _fdt_splice(fdt, p, 0, newlen)))
|
||||
return err;
|
||||
|
||||
fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);
|
||||
@@ -191,17 +191,13 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
|
||||
int fdt_del_mem_rsv(void *fdt, int n)
|
||||
{
|
||||
struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n);
|
||||
int err;
|
||||
|
||||
FDT_RW_CHECK_HEADER(fdt);
|
||||
|
||||
if (n >= fdt_num_mem_rsv(fdt))
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
|
||||
err = _fdt_splice_mem_rsv(fdt, re, 1, 0);
|
||||
if (err)
|
||||
return err;
|
||||
return 0;
|
||||
return _fdt_splice_mem_rsv(fdt, re, 1, 0);
|
||||
}
|
||||
|
||||
static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
|
||||
@@ -211,12 +207,11 @@ static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
|
||||
int err;
|
||||
|
||||
*prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
|
||||
if (! (*prop))
|
||||
if (!*prop)
|
||||
return oldlen;
|
||||
|
||||
err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
|
||||
FDT_TAGALIGN(len));
|
||||
if (err)
|
||||
if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
|
||||
FDT_TAGALIGN(len))))
|
||||
return err;
|
||||
|
||||
(*prop)->len = cpu_to_fdt32(len);
|
||||
@@ -274,8 +269,8 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fdt_setprop(void *fdt, int nodeoffset, const char *name,
|
||||
const void *val, int len)
|
||||
int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
|
||||
int len, void **prop_data)
|
||||
{
|
||||
struct fdt_property *prop;
|
||||
int err;
|
||||
@@ -288,7 +283,22 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
memcpy(prop->data, val, len);
|
||||
*prop_data = prop->data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fdt_setprop(void *fdt, int nodeoffset, const char *name,
|
||||
const void *val, int len)
|
||||
{
|
||||
void *prop_data;
|
||||
int err;
|
||||
|
||||
err = fdt_setprop_placeholder(fdt, nodeoffset, name, len, &prop_data);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (len)
|
||||
memcpy(prop_data, val, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -327,7 +337,7 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name)
|
||||
FDT_RW_CHECK_HEADER(fdt);
|
||||
|
||||
prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
|
||||
if (! prop)
|
||||
if (!prop)
|
||||
return len;
|
||||
|
||||
proplen = sizeof(*prop) + FDT_TAGALIGN(len);
|
||||
|
@@ -69,6 +69,7 @@ static struct fdt_errtabent fdt_errtable[] = {
|
||||
|
||||
FDT_ERRTABENT(FDT_ERR_BADOFFSET),
|
||||
FDT_ERRTABENT(FDT_ERR_BADPATH),
|
||||
FDT_ERRTABENT(FDT_ERR_BADPHANDLE),
|
||||
FDT_ERRTABENT(FDT_ERR_BADSTATE),
|
||||
|
||||
FDT_ERRTABENT(FDT_ERR_TRUNCATED),
|
||||
@@ -76,6 +77,11 @@ static struct fdt_errtabent fdt_errtable[] = {
|
||||
FDT_ERRTABENT(FDT_ERR_BADVERSION),
|
||||
FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE),
|
||||
FDT_ERRTABENT(FDT_ERR_BADLAYOUT),
|
||||
FDT_ERRTABENT(FDT_ERR_INTERNAL),
|
||||
FDT_ERRTABENT(FDT_ERR_BADNCELLS),
|
||||
FDT_ERRTABENT(FDT_ERR_BADVALUE),
|
||||
FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
|
||||
FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
|
||||
};
|
||||
#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
|
||||
|
||||
|
@@ -107,6 +107,38 @@ int fdt_create(void *buf, int bufsize)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fdt_resize(void *fdt, void *buf, int bufsize)
|
||||
{
|
||||
size_t headsize, tailsize;
|
||||
char *oldtail, *newtail;
|
||||
|
||||
FDT_SW_CHECK_HEADER(fdt);
|
||||
|
||||
headsize = fdt_off_dt_struct(fdt);
|
||||
tailsize = fdt_size_dt_strings(fdt);
|
||||
|
||||
if ((headsize + tailsize) > bufsize)
|
||||
return -FDT_ERR_NOSPACE;
|
||||
|
||||
oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize;
|
||||
newtail = (char *)buf + bufsize - tailsize;
|
||||
|
||||
/* Two cases to avoid clobbering data if the old and new
|
||||
* buffers partially overlap */
|
||||
if (buf <= fdt) {
|
||||
memmove(buf, fdt, headsize);
|
||||
memmove(newtail, oldtail, tailsize);
|
||||
} else {
|
||||
memmove(newtail, oldtail, tailsize);
|
||||
memmove(buf, fdt, headsize);
|
||||
}
|
||||
|
||||
fdt_set_off_dt_strings(buf, bufsize);
|
||||
fdt_set_totalsize(buf, bufsize);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
|
||||
{
|
||||
struct fdt_reserve_entry *re;
|
||||
@@ -188,7 +220,7 @@ static int _fdt_find_add_string(void *fdt, const char *s)
|
||||
return offset;
|
||||
}
|
||||
|
||||
int fdt_property(void *fdt, const char *name, const void *val, int len)
|
||||
int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp)
|
||||
{
|
||||
struct fdt_property *prop;
|
||||
int nameoff;
|
||||
@@ -206,7 +238,19 @@ int fdt_property(void *fdt, const char *name, const void *val, int len)
|
||||
prop->tag = cpu_to_fdt32(FDT_PROP);
|
||||
prop->nameoff = cpu_to_fdt32(nameoff);
|
||||
prop->len = cpu_to_fdt32(len);
|
||||
memcpy(prop->data, val, len);
|
||||
*valp = prop->data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fdt_property(void *fdt, const char *name, const void *val, int len)
|
||||
{
|
||||
void *ptr;
|
||||
int ret;
|
||||
|
||||
ret = fdt_property_placeholder(fdt, name, len, &ptr);
|
||||
if (ret)
|
||||
return ret;
|
||||
memcpy(ptr, val, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -55,21 +55,42 @@
|
||||
|
||||
#include "libfdt_internal.h"
|
||||
|
||||
int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
|
||||
const void *val, int len)
|
||||
int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
|
||||
const char *name, int namelen,
|
||||
uint32_t idx, const void *val,
|
||||
int len)
|
||||
{
|
||||
void *propval;
|
||||
int proplen;
|
||||
|
||||
propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen);
|
||||
if (! propval)
|
||||
propval = fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen,
|
||||
&proplen);
|
||||
if (!propval)
|
||||
return proplen;
|
||||
|
||||
if (proplen < (len + idx))
|
||||
return -FDT_ERR_NOSPACE;
|
||||
|
||||
memcpy((char *)propval + idx, val, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
|
||||
const void *val, int len)
|
||||
{
|
||||
const void *propval;
|
||||
int proplen;
|
||||
|
||||
propval = fdt_getprop(fdt, nodeoffset, name, &proplen);
|
||||
if (!propval)
|
||||
return proplen;
|
||||
|
||||
if (proplen != len)
|
||||
return -FDT_ERR_NOSPACE;
|
||||
|
||||
memcpy(propval, val, len);
|
||||
return 0;
|
||||
return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name,
|
||||
strlen(name), 0,
|
||||
val, len);
|
||||
}
|
||||
|
||||
static void _fdt_nop_region(void *start, int len)
|
||||
@@ -86,7 +107,7 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
|
||||
int len;
|
||||
|
||||
prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
|
||||
if (! prop)
|
||||
if (!prop)
|
||||
return len;
|
||||
|
||||
_fdt_nop_region(prop, len + sizeof(*prop));
|
||||
|
@@ -57,9 +57,9 @@
|
||||
|
||||
#define FDT_CHECK_HEADER(fdt) \
|
||||
{ \
|
||||
int err; \
|
||||
if ((err = fdt_check_header(fdt)) != 0) \
|
||||
return err; \
|
||||
int __err; \
|
||||
if ((__err = fdt_check_header(fdt)) != 0) \
|
||||
return __err; \
|
||||
}
|
||||
|
||||
int _fdt_check_node_offset(const void *fdt, int offset);
|
||||
|
@@ -8,6 +8,7 @@ LIBFDT_1.2 {
|
||||
fdt_get_mem_rsv;
|
||||
fdt_subnode_offset_namelen;
|
||||
fdt_subnode_offset;
|
||||
fdt_path_offset_namelen;
|
||||
fdt_path_offset;
|
||||
fdt_get_name;
|
||||
fdt_get_property_namelen;
|
||||
@@ -54,6 +55,12 @@ LIBFDT_1.2 {
|
||||
fdt_get_property_by_offset;
|
||||
fdt_getprop_by_offset;
|
||||
fdt_next_property_offset;
|
||||
fdt_first_subnode;
|
||||
fdt_next_subnode;
|
||||
fdt_address_cells;
|
||||
fdt_size_cells;
|
||||
fdt_stringlist_contains;
|
||||
fdt_resize;
|
||||
|
||||
local:
|
||||
*;
|
||||
|
Reference in New Issue
Block a user