// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation.
*/ #include"libfdt_env.h"
#include <fdt.h> #include <libfdt.h>
#include"libfdt_internal.h"
/* * Minimal sanity check for a read-only tree. fdt_ro_probe_() checks * that the given buffer contains what appears to be a flattened * device tree with sane information in its header.
*/
int32_t fdt_ro_probe_(constvoid *fdt)
{
uint32_t totalsize = fdt_totalsize(fdt);
if (can_assume(VALID_DTB)) return totalsize;
/* The device tree must be at an 8-byte aligned address */ if ((uintptr_t)fdt & 7) return -FDT_ERR_ALIGNMENT;
if (fdt_magic(fdt) == FDT_MAGIC) { /* Complete tree */ if (!can_assume(LATEST)) { if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) return -FDT_ERR_BADVERSION; if (fdt_last_comp_version(fdt) >
FDT_LAST_SUPPORTED_VERSION) return -FDT_ERR_BADVERSION;
}
} elseif (fdt_magic(fdt) == FDT_SW_MAGIC) { /* Unfinished sequential-write blob */ if (!can_assume(VALID_INPUT) && fdt_size_dt_struct(fdt) == 0) return -FDT_ERR_BADSTATE;
} else { return -FDT_ERR_BADMAGIC;
}
if (totalsize < INT32_MAX) return totalsize; else return -FDT_ERR_TRUNCATED;
}
if (!can_assume(VALID_INPUT)) if ((absoffset < uoffset)
|| ((absoffset + len) < absoffset)
|| (absoffset + len) > fdt_totalsize(fdt)) return NULL;
if (can_assume(LATEST) || fdt_version(fdt) >= 0x11) if (((uoffset + len) < uoffset)
|| ((offset + len) > fdt_size_dt_struct(fdt))) return NULL;
return fdt_offset_ptr_(fdt, offset);
}
uint32_t fdt_next_tag(constvoid *fdt, int startoffset, int *nextoffset)
{ const fdt32_t *tagp, *lenp;
uint32_t tag, len, sum; int offset = startoffset; constchar *p;
*nextoffset = -FDT_ERR_TRUNCATED;
tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); if (!can_assume(VALID_DTB) && !tagp) return FDT_END; /* premature end */
tag = fdt32_to_cpu(*tagp);
offset += FDT_TAGSIZE;
*nextoffset = -FDT_ERR_BADSTRUCTURE; switch (tag) { case FDT_BEGIN_NODE: /* skip name */ do {
p = fdt_offset_ptr(fdt, offset++, 1);
} while (p && (*p != '\0')); if (!can_assume(VALID_DTB) && !p) return FDT_END; /* premature end */ break;
case FDT_PROP:
lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); if (!can_assume(VALID_DTB) && !lenp) return FDT_END; /* premature end */
len = fdt32_to_cpu(*lenp);
sum = len + offset; if (!can_assume(VALID_DTB) &&
(INT_MAX <= sum || sum < (uint32_t) offset)) return FDT_END; /* premature end */
/* skip-name offset, length and value */
offset += sizeof(struct fdt_property) - FDT_TAGSIZE + len;
int fdt_next_subnode(constvoid *fdt, int offset)
{ int depth = 1;
/* * With respect to the parent, the depth of the next subnode will be * the same as the last.
*/ do {
offset = fdt_next_node(fdt, offset, &depth); if (offset < 0 || depth < 1) return -FDT_ERR_NOTFOUND;
} while (depth > 1);
return offset;
}
constchar *fdt_find_string_(constchar *strtab, int tabsize, constchar *s)
{ int len = strlen(s) + 1; constchar *last = strtab + tabsize - len; constchar *p;
for (p = strtab; p <= last; p++) if (memcmp(p, s, len) == 0) return p; return NULL;
}
int fdt_move(constvoid *fdt, void *buf, int bufsize)
{ if (!can_assume(VALID_INPUT) && bufsize < 0) return -FDT_ERR_NOSPACE;
FDT_RO_PROBE(fdt);
if (fdt_totalsize(fdt) > (unsignedint)bufsize) return -FDT_ERR_NOSPACE;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.