mirror of
https://github.com/dgibson/dtc.git
synced 2026-10-09 23:53:08 -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)
|
||||
{
|
||||
const char *name;
|
||||
const void *p;
|
||||
int prop;
|
||||
|
||||
prop = fdt_first_property_offset(blob, node);
|
||||
do {
|
||||
/* Stop silently when there are no more properties */
|
||||
if (prop < 0)
|
||||
return prop == -FDT_ERR_NOTFOUND ? 0 : prop;
|
||||
fdt_getprop_by_offset(blob, prop, &name, NULL);
|
||||
if (name)
|
||||
fdt_for_each_property_offset(prop, blob, node) {
|
||||
p = fdt_getprop_by_offset(blob, prop, &name, NULL);
|
||||
if (p && 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
|
||||
|
|
@ -163,47 +162,21 @@ static int list_properties(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;
|
||||
int depth = 1; /* the assumed depth of this node */
|
||||
int subnode;
|
||||
|
||||
while (level >= 0) {
|
||||
tag = fdt_next_tag(blob, node, &nextoffset);
|
||||
switch (tag) {
|
||||
case FDT_BEGIN_NODE:
|
||||
pathp = fdt_get_name(blob, node, NULL);
|
||||
if (level <= depth) {
|
||||
if (pathp == NULL)
|
||||
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;
|
||||
fdt_for_each_subnode(subnode, blob, node) {
|
||||
pathp = fdt_get_name(blob, subnode, NULL);
|
||||
if (pathp == NULL)
|
||||
pathp = "/* NULL pointer error */";
|
||||
if (*pathp == '\0')
|
||||
pathp = "/"; /* root is nameless */
|
||||
puts(pathp);
|
||||
}
|
||||
|
||||
if (subnode < 0 && (subnode != -FDT_ERR_NOTFOUND))
|
||||
return subnode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,8 +27,10 @@ endif
|
|||
|
||||
link_args += version_script
|
||||
libfdt = library(
|
||||
'fdt', sources,
|
||||
'fdt',
|
||||
sources: sources,
|
||||
version: meson.project_version(),
|
||||
soversion: '1',
|
||||
link_args: link_args,
|
||||
link_depends: 'version.lds',
|
||||
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')
|
||||
|
||||
version_gen_h = vcs_tag(
|
||||
command: ['git', 'describe', '--dirty=+'],
|
||||
command: ['git', '--git-dir=.git', 'describe', '--dirty=+'],
|
||||
input: 'version_gen.h.in',
|
||||
output: 'version_gen.h',
|
||||
)
|
||||
|
|
|
|||
|
|
@ -302,6 +302,38 @@ class FdtRo(object):
|
|||
check_err(val[0], quiet)
|
||||
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=()):
|
||||
"""Get the offset of a named subnode
|
||||
|
||||
|
|
@ -604,6 +636,42 @@ class Fdt(FdtRo):
|
|||
del self._fdt[self.totalsize():]
|
||||
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=()):
|
||||
"""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
|
||||
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):
|
||||
"""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
|
||||
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:
|
||||
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
|
||||
"""
|
||||
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 False
|
||||
|
||||
|
|
@ -1136,7 +1208,7 @@ typedef uint32_t fdt32_t;
|
|||
PyObject *buff;
|
||||
|
||||
if ($1) {
|
||||
resultobj = PyString_FromString(
|
||||
resultobj = PyUnicode_FromString(
|
||||
fdt_string(fdt1, fdt32_to_cpu($1->nameoff)));
|
||||
buff = PyByteArray_FromStringAndSize(
|
||||
(const char *)($1 + 1), fdt32_to_cpu($1->len));
|
||||
|
|
@ -1169,13 +1241,13 @@ typedef uint32_t fdt32_t;
|
|||
}
|
||||
$1 = PyBytes_AsString($input);
|
||||
%#else
|
||||
$1 = PyString_AsString($input); /* char *str */
|
||||
$1 = PyBytes_AsString($input); /* char *str */
|
||||
%#endif
|
||||
}
|
||||
|
||||
/* typemaps used for fdt_next_node() */
|
||||
%typemap(in, numinputs=1) int *depth (int depth) {
|
||||
depth = (int) PyInt_AsLong($input);
|
||||
depth = (int) PyLong_AsLong($input);
|
||||
$1 = &depth;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -411,6 +411,35 @@ class PyLibfdtBasicTests(unittest.TestCase):
|
|||
self.fdt.get_mem_rsv(0))
|
||||
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):
|
||||
"""Test that we can create an empty tree"""
|
||||
self.assertEqual(-libfdt.NOSPACE,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue