mirror of
https://github.com/dgibson/dtc.git
synced 2026-10-10 08:03:00 -04:00
Compare commits
7 commits
66e1201c37
...
f3451d1253
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f3451d1253 | ||
|
|
7a1e017926 | ||
|
|
8c37c14c95 | ||
|
|
89c99ce78a | ||
|
|
3750493c8b | ||
|
|
0748c384fd | ||
|
|
5008d1d6a3 |
5 changed files with 132 additions and 56 deletions
71
fdtget.c
71
fdtget.c
|
|
@ -138,21 +138,20 @@ static int show_data(struct display_info *disp, const char *data, int len)
|
||||||
static int list_properties(const void *blob, int node)
|
static int list_properties(const void *blob, int node)
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
|
const void *p;
|
||||||
int prop;
|
int prop;
|
||||||
|
|
||||||
prop = fdt_first_property_offset(blob, node);
|
fdt_for_each_property_offset(prop, blob, node) {
|
||||||
do {
|
p = fdt_getprop_by_offset(blob, prop, &name, NULL);
|
||||||
/* Stop silently when there are no more properties */
|
if (p && name)
|
||||||
if (prop < 0)
|
|
||||||
return prop == -FDT_ERR_NOTFOUND ? 0 : prop;
|
|
||||||
fdt_getprop_by_offset(blob, prop, &name, NULL);
|
|
||||||
if (name)
|
|
||||||
puts(name);
|
puts(name);
|
||||||
prop = fdt_next_property_offset(blob, prop);
|
}
|
||||||
} while (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MAX_LEVEL 32 /* how deeply nested we will go */
|
if ((prop < 0) && (prop != -FDT_ERR_NOTFOUND))
|
||||||
|
return prop;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List all subnodes in a node, one per line
|
* List all subnodes in a node, one per line
|
||||||
|
|
@ -163,47 +162,21 @@ static int list_properties(const void *blob, int node)
|
||||||
*/
|
*/
|
||||||
static int list_subnodes(const void *blob, int node)
|
static int list_subnodes(const void *blob, int node)
|
||||||
{
|
{
|
||||||
int nextoffset; /* next node offset from libfdt */
|
|
||||||
uint32_t tag; /* current tag */
|
|
||||||
int level = 0; /* keep track of nesting level */
|
|
||||||
const char *pathp;
|
const char *pathp;
|
||||||
int depth = 1; /* the assumed depth of this node */
|
int subnode;
|
||||||
|
|
||||||
while (level >= 0) {
|
fdt_for_each_subnode(subnode, blob, node) {
|
||||||
tag = fdt_next_tag(blob, node, &nextoffset);
|
pathp = fdt_get_name(blob, subnode, NULL);
|
||||||
switch (tag) {
|
if (pathp == NULL)
|
||||||
case FDT_BEGIN_NODE:
|
pathp = "/* NULL pointer error */";
|
||||||
pathp = fdt_get_name(blob, node, NULL);
|
if (*pathp == '\0')
|
||||||
if (level <= depth) {
|
pathp = "/"; /* root is nameless */
|
||||||
if (pathp == NULL)
|
puts(pathp);
|
||||||
pathp = "/* NULL pointer error */";
|
|
||||||
if (*pathp == '\0')
|
|
||||||
pathp = "/"; /* root is nameless */
|
|
||||||
if (level == 1)
|
|
||||||
puts(pathp);
|
|
||||||
}
|
|
||||||
level++;
|
|
||||||
if (level >= MAX_LEVEL) {
|
|
||||||
printf("Nested too deep, aborting.\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case FDT_END_NODE:
|
|
||||||
level--;
|
|
||||||
if (level == 0)
|
|
||||||
level = -1; /* exit the loop */
|
|
||||||
break;
|
|
||||||
case FDT_END:
|
|
||||||
return 1;
|
|
||||||
case FDT_PROP:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (level <= depth)
|
|
||||||
printf("Unknown tag 0x%08X\n", tag);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
node = nextoffset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (subnode < 0 && (subnode != -FDT_ERR_NOTFOUND))
|
||||||
|
return subnode;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,10 @@ endif
|
||||||
|
|
||||||
link_args += version_script
|
link_args += version_script
|
||||||
libfdt = library(
|
libfdt = library(
|
||||||
'fdt', sources,
|
'fdt',
|
||||||
|
sources: sources,
|
||||||
version: meson.project_version(),
|
version: meson.project_version(),
|
||||||
|
soversion: '1',
|
||||||
link_args: link_args,
|
link_args: link_args,
|
||||||
link_depends: 'version.lds',
|
link_depends: 'version.lds',
|
||||||
install: get_option('default_library') != 'static' or not wheel_only,
|
install: get_option('default_library') != 'static' or not wheel_only,
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ pylibfdt_enabled = not meson.is_cross_build() and py.found() and swig.found() ?
|
||||||
wheel_only = get_option('wheel-only')
|
wheel_only = get_option('wheel-only')
|
||||||
|
|
||||||
version_gen_h = vcs_tag(
|
version_gen_h = vcs_tag(
|
||||||
command: ['git', 'describe', '--dirty=+'],
|
command: ['git', '--git-dir=.git', 'describe', '--dirty=+'],
|
||||||
input: 'version_gen.h.in',
|
input: 'version_gen.h.in',
|
||||||
output: 'version_gen.h',
|
output: 'version_gen.h',
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,38 @@ class FdtRo(object):
|
||||||
check_err(val[0], quiet)
|
check_err(val[0], quiet)
|
||||||
return val[1:]
|
return val[1:]
|
||||||
|
|
||||||
|
def address_cells(self, nodeoffset, quiet=()):
|
||||||
|
"""Return the number of address cells used by a node's children
|
||||||
|
|
||||||
|
Args:
|
||||||
|
nodeoffset: Offset of the node to check
|
||||||
|
quiet: Errors to ignore (empty to raise on all errors)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Number of address cells used by the children of @nodeoffset
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
FdtException if the node has an invalid #address-cells property,
|
||||||
|
or another error occurs
|
||||||
|
"""
|
||||||
|
return check_err(fdt_address_cells(self._fdt, nodeoffset), quiet)
|
||||||
|
|
||||||
|
def size_cells(self, nodeoffset, quiet=()):
|
||||||
|
"""Return the number of size cells used by a node's children
|
||||||
|
|
||||||
|
Args:
|
||||||
|
nodeoffset: Offset of the node to check
|
||||||
|
quiet: Errors to ignore (empty to raise on all errors)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Number of size cells used by the children of @nodeoffset
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
FdtException if the node has an invalid #size-cells property, or
|
||||||
|
another error occurs
|
||||||
|
"""
|
||||||
|
return check_err(fdt_size_cells(self._fdt, nodeoffset), quiet)
|
||||||
|
|
||||||
def subnode_offset(self, parentoffset, name, quiet=()):
|
def subnode_offset(self, parentoffset, name, quiet=()):
|
||||||
"""Get the offset of a named subnode
|
"""Get the offset of a named subnode
|
||||||
|
|
||||||
|
|
@ -604,6 +636,42 @@ class Fdt(FdtRo):
|
||||||
del self._fdt[self.totalsize():]
|
del self._fdt[self.totalsize():]
|
||||||
return err
|
return err
|
||||||
|
|
||||||
|
def add_mem_rsv(self, addr, size, quiet=()):
|
||||||
|
"""Add a memory reserve-map record
|
||||||
|
|
||||||
|
This asks the client program not to use the given region of memory,
|
||||||
|
e.g. because something was loaded there.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
addr: Start address of the region to reserve
|
||||||
|
size: Size of the region to reserve, in bytes
|
||||||
|
quiet: Errors to ignore (empty to raise on all errors)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Error code, or 0 if OK
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
FdtException if there is no space for another record, or another
|
||||||
|
error occurs
|
||||||
|
"""
|
||||||
|
return check_err(fdt_add_mem_rsv(self._fdt, addr, size), quiet)
|
||||||
|
|
||||||
|
def del_mem_rsv(self, index, quiet=()):
|
||||||
|
"""Remove the indexed memory reserve-map record
|
||||||
|
|
||||||
|
Args:
|
||||||
|
index: Record to remove (0=first)
|
||||||
|
quiet: Errors to ignore (empty to raise on all errors)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Error code, or 0 if OK
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
FdtException if there is no record at @index, or another error
|
||||||
|
occurs
|
||||||
|
"""
|
||||||
|
return check_err(fdt_del_mem_rsv(self._fdt, index), quiet)
|
||||||
|
|
||||||
def set_name(self, nodeoffset, name, quiet=()):
|
def set_name(self, nodeoffset, name, quiet=()):
|
||||||
"""Set the name of a node
|
"""Set the name of a node
|
||||||
|
|
||||||
|
|
@ -857,7 +925,7 @@ class FdtSw(FdtRo):
|
||||||
device tree. This will be increased automatically as needed as new items
|
device tree. This will be increased automatically as needed as new items
|
||||||
are added to the tree.
|
are added to the tree.
|
||||||
"""
|
"""
|
||||||
INC_SIZE = 1024 # Expand size by this much when out of space
|
INC_SIZE = 1024 # Expand size by at least this much when out of space
|
||||||
|
|
||||||
def __init__(self, size_hint=None):
|
def __init__(self, size_hint=None):
|
||||||
"""Create a new FdtSw object
|
"""Create a new FdtSw object
|
||||||
|
|
@ -901,6 +969,10 @@ class FdtSw(FdtRo):
|
||||||
-NOSPACE then the FDT will be expanded to have more space, and True will
|
-NOSPACE then the FDT will be expanded to have more space, and True will
|
||||||
be returned, indicating that the operation needs to be tried again.
|
be returned, indicating that the operation needs to be tried again.
|
||||||
|
|
||||||
|
Each expansion copies the whole tree into a new buffer, so the size is
|
||||||
|
at least doubled rather than grown by a fixed amount, to keep the total
|
||||||
|
amount of copying proportional to the size of the tree.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
val: Return value from the operation that was attempted
|
val: Return value from the operation that was attempted
|
||||||
|
|
||||||
|
|
@ -908,7 +980,7 @@ class FdtSw(FdtRo):
|
||||||
True if the operation must be retried, else False
|
True if the operation must be retried, else False
|
||||||
"""
|
"""
|
||||||
if check_err(val, QUIET_NOSPACE) < 0:
|
if check_err(val, QUIET_NOSPACE) < 0:
|
||||||
self.resize(len(self._fdt) + self.INC_SIZE)
|
self.resize(len(self._fdt) + max(len(self._fdt), self.INC_SIZE))
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
@ -1136,7 +1208,7 @@ typedef uint32_t fdt32_t;
|
||||||
PyObject *buff;
|
PyObject *buff;
|
||||||
|
|
||||||
if ($1) {
|
if ($1) {
|
||||||
resultobj = PyString_FromString(
|
resultobj = PyUnicode_FromString(
|
||||||
fdt_string(fdt1, fdt32_to_cpu($1->nameoff)));
|
fdt_string(fdt1, fdt32_to_cpu($1->nameoff)));
|
||||||
buff = PyByteArray_FromStringAndSize(
|
buff = PyByteArray_FromStringAndSize(
|
||||||
(const char *)($1 + 1), fdt32_to_cpu($1->len));
|
(const char *)($1 + 1), fdt32_to_cpu($1->len));
|
||||||
|
|
@ -1169,13 +1241,13 @@ typedef uint32_t fdt32_t;
|
||||||
}
|
}
|
||||||
$1 = PyBytes_AsString($input);
|
$1 = PyBytes_AsString($input);
|
||||||
%#else
|
%#else
|
||||||
$1 = PyString_AsString($input); /* char *str */
|
$1 = PyBytes_AsString($input); /* char *str */
|
||||||
%#endif
|
%#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* typemaps used for fdt_next_node() */
|
/* typemaps used for fdt_next_node() */
|
||||||
%typemap(in, numinputs=1) int *depth (int depth) {
|
%typemap(in, numinputs=1) int *depth (int depth) {
|
||||||
depth = (int) PyInt_AsLong($input);
|
depth = (int) PyLong_AsLong($input);
|
||||||
$1 = &depth;
|
$1 = &depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -411,6 +411,35 @@ class PyLibfdtBasicTests(unittest.TestCase):
|
||||||
self.fdt.get_mem_rsv(0))
|
self.fdt.get_mem_rsv(0))
|
||||||
self.assertEqual([123456789, 0o10000], self.fdt.get_mem_rsv(1))
|
self.assertEqual([123456789, 0o10000], self.fdt.get_mem_rsv(1))
|
||||||
|
|
||||||
|
def testAddDelReserveMap(self):
|
||||||
|
"""Test that we can add to and remove from the memory reserve map"""
|
||||||
|
fdt = _ReadFdt('test_tree1.dtb')
|
||||||
|
fdt.resize(fdt.totalsize() + 64)
|
||||||
|
|
||||||
|
self.assertEqual(0, fdt.add_mem_rsv(0x40000000, 0x2000))
|
||||||
|
self.assertEqual(3, fdt.num_mem_rsv())
|
||||||
|
self.assertEqual([0x40000000, 0x2000], fdt.get_mem_rsv(2))
|
||||||
|
|
||||||
|
self.assertEqual(0, fdt.del_mem_rsv(2))
|
||||||
|
self.assertEqual(2, fdt.num_mem_rsv())
|
||||||
|
self.assertEqual(-libfdt.NOTFOUND,
|
||||||
|
fdt.del_mem_rsv(2, QUIET_NOTFOUND))
|
||||||
|
|
||||||
|
def testCells(self):
|
||||||
|
"""Test that we can read #address-cells and #size-cells"""
|
||||||
|
self.assertEqual(1, self.fdt.address_cells(0))
|
||||||
|
self.assertEqual(0, self.fdt.size_cells(0))
|
||||||
|
|
||||||
|
# A node without the properties inherits neither, so the libfdt
|
||||||
|
# defaults of 2 and 1 apply
|
||||||
|
node = self.fdt.path_offset('/subnode@1')
|
||||||
|
self.assertEqual(2, self.fdt.address_cells(node))
|
||||||
|
self.assertEqual(1, self.fdt.size_cells(node))
|
||||||
|
|
||||||
|
node = self.fdt.path_offset('/subnode@2')
|
||||||
|
self.assertEqual(1, self.fdt.address_cells(node))
|
||||||
|
self.assertEqual(0, self.fdt.size_cells(node))
|
||||||
|
|
||||||
def testEmpty(self):
|
def testEmpty(self):
|
||||||
"""Test that we can create an empty tree"""
|
"""Test that we can create an empty tree"""
|
||||||
self.assertEqual(-libfdt.NOSPACE,
|
self.assertEqual(-libfdt.NOSPACE,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue