Skip to content

Commit

Permalink
EmbeddedPkg/FdtLib: Update FdtLib to v1.4.5
Browse files Browse the repository at this point in the history
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 <[email protected]>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Pankaj Bansal <[email protected]>
Reviewed-by: Ard Biesheuvel <[email protected]>
  • Loading branch information
pankajbansalnxp authored and Ard Biesheuvel committed Jan 5, 2018
1 parent 0bc94c7 commit a099239
Show file tree
Hide file tree
Showing 14 changed files with 760 additions and 87 deletions.
416 changes: 385 additions & 31 deletions EmbeddedPkg/Include/libfdt.h

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions EmbeddedPkg/Include/libfdt_env.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,8 @@ static inline char *strchr(const char *s, int c) {
return AsciiStrStr (s, pattern);
}

static inline size_t strnlen (const char* str, size_t strsz ) {
return AsciiStrnLenS (str, strsz);
}

#endif /* _LIBFDT_ENV_H */
1 change: 1 addition & 0 deletions EmbeddedPkg/Library/FdtLib/FdtLib.inf
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
fdt_sw.c
fdt_wip.c
fdt.c
fdt_addresses.c

[Packages]
MdePkg/MdePkg.dec
Expand Down
3 changes: 2 additions & 1 deletion EmbeddedPkg/Library/FdtLib/Makefile.libfdt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
13 changes: 7 additions & 6 deletions EmbeddedPkg/Library/FdtLib/fdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
96 changes: 96 additions & 0 deletions EmbeddedPkg/Library/FdtLib/fdt_addresses.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2014 David Gibson <[email protected]>
*
* 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;
}
1 change: 0 additions & 1 deletion EmbeddedPkg/Library/FdtLib/fdt_empty_tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,3 @@ int fdt_create_empty_tree(void *buf, int bufsize)

return fdt_open_into(buf, buf, bufsize);
}

163 changes: 146 additions & 17 deletions EmbeddedPkg/Library/FdtLib/fdt_ro.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -154,17 +180,17 @@ 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;

FDT_CHECK_HEADER(fdt);

/* see if we have an alias */
if (*path != '/') {
const char *q = strchr(path, '/');
const char *q = memchr(path, '/', end - p);

if (!q)
q = end;
Expand All @@ -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;

Expand All @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)
{
Expand All @@ -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,
Expand Down
Loading

0 comments on commit a099239

Please sign in to comment.