Merge git://git.denx.de/u-boot-fdt
This commit is contained in:
commit
dd31be21bf
17
Makefile
17
Makefile
@ -1116,7 +1116,7 @@ cmd_ldr = $(LD) $(LDFLAGS_$(@F)) \
|
|||||||
|
|
||||||
u-boot.rom: u-boot-x86-16bit.bin u-boot.bin \
|
u-boot.rom: u-boot-x86-16bit.bin u-boot.bin \
|
||||||
$(if $(CONFIG_SPL_X86_16BIT_INIT),spl/u-boot-spl.bin) \
|
$(if $(CONFIG_SPL_X86_16BIT_INIT),spl/u-boot-spl.bin) \
|
||||||
$(if $(CONFIG_HAVE_REFCODE),refcode.bin) FORCE
|
$(if $(CONFIG_HAVE_REFCODE),refcode.bin) checkbinman FORCE
|
||||||
$(call if_changed,binman)
|
$(call if_changed,binman)
|
||||||
|
|
||||||
OBJCOPYFLAGS_u-boot-x86-16bit.bin := -O binary -j .start16 -j .resetvec
|
OBJCOPYFLAGS_u-boot-x86-16bit.bin := -O binary -j .start16 -j .resetvec
|
||||||
@ -1125,7 +1125,8 @@ u-boot-x86-16bit.bin: u-boot FORCE
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(CONFIG_ARCH_SUNXI),)
|
ifneq ($(CONFIG_ARCH_SUNXI),)
|
||||||
u-boot-sunxi-with-spl.bin: spl/sunxi-spl.bin u-boot.img u-boot.dtb FORCE
|
u-boot-sunxi-with-spl.bin: spl/sunxi-spl.bin u-boot.img u-boot.dtb \
|
||||||
|
checkbinman FORCE
|
||||||
$(call if_changed,binman)
|
$(call if_changed,binman)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -1354,6 +1355,18 @@ $(version_h): include/config/uboot.release FORCE
|
|||||||
$(timestamp_h): $(srctree)/Makefile FORCE
|
$(timestamp_h): $(srctree)/Makefile FORCE
|
||||||
$(call filechk,timestamp.h)
|
$(call filechk,timestamp.h)
|
||||||
|
|
||||||
|
checkbinman: tools
|
||||||
|
@if ! ( echo 'import libfdt' | ( PYTHONPATH=tools python )); then \
|
||||||
|
echo >&2; \
|
||||||
|
echo >&2 '*** binman needs the Python libfdt library.'; \
|
||||||
|
echo >&2 '*** Either install it on your system, or try:'; \
|
||||||
|
echo >&2 '***'; \
|
||||||
|
echo >&2 '*** sudo apt-get install swig libpython-dev'; \
|
||||||
|
echo >&2 '***'; \
|
||||||
|
echo >&2 '*** to have U-Boot build its own version.'; \
|
||||||
|
false; \
|
||||||
|
fi
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
quiet_cmd_cpp_lds = LDS $@
|
quiet_cmd_cpp_lds = LDS $@
|
||||||
cmd_cpp_lds = $(CPP) -Wp,-MD,$(depfile) $(cpp_flags) $(LDPPFLAGS) \
|
cmd_cpp_lds = $(CPP) -Wp,-MD,$(depfile) $(cpp_flags) $(LDPPFLAGS) \
|
||||||
|
@ -150,7 +150,8 @@ int pci_bar_show(struct udevice *dev)
|
|||||||
if ((!is_64 && size_low) || (is_64 && size)) {
|
if ((!is_64 && size_low) || (is_64 && size)) {
|
||||||
size = ~size + 1;
|
size = ~size + 1;
|
||||||
printf(" %d %#016llx %#016llx %d %s %s\n",
|
printf(" %d %#016llx %#016llx %d %s %s\n",
|
||||||
bar_id, base, size, is_64 ? 64 : 32,
|
bar_id, (unsigned long long)base,
|
||||||
|
(unsigned long long)size, is_64 ? 64 : 32,
|
||||||
is_io ? "I/O" : "MEM",
|
is_io ? "I/O" : "MEM",
|
||||||
prefetchable ? "Prefetchable" : "");
|
prefetchable ? "Prefetchable" : "");
|
||||||
}
|
}
|
||||||
|
112
include/fdt.h
112
include/fdt.h
@ -1,111 +1 @@
|
|||||||
#ifndef _FDT_H
|
#include <../lib/libfdt/fdt.h>
|
||||||
#define _FDT_H
|
|
||||||
/*
|
|
||||||
* libfdt - Flat Device Tree manipulation
|
|
||||||
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
|
||||||
* Copyright 2012 Kim Phillips, Freescale Semiconductor.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
|
||||||
|
|
||||||
struct fdt_header {
|
|
||||||
fdt32_t magic; /* magic word FDT_MAGIC */
|
|
||||||
fdt32_t totalsize; /* total size of DT block */
|
|
||||||
fdt32_t off_dt_struct; /* offset to structure */
|
|
||||||
fdt32_t off_dt_strings; /* offset to strings */
|
|
||||||
fdt32_t off_mem_rsvmap; /* offset to memory reserve map */
|
|
||||||
fdt32_t version; /* format version */
|
|
||||||
fdt32_t last_comp_version; /* last compatible version */
|
|
||||||
|
|
||||||
/* version 2 fields below */
|
|
||||||
fdt32_t boot_cpuid_phys; /* Which physical CPU id we're
|
|
||||||
booting on */
|
|
||||||
/* version 3 fields below */
|
|
||||||
fdt32_t size_dt_strings; /* size of the strings block */
|
|
||||||
|
|
||||||
/* version 17 fields below */
|
|
||||||
fdt32_t size_dt_struct; /* size of the structure block */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct fdt_reserve_entry {
|
|
||||||
fdt64_t address;
|
|
||||||
fdt64_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct fdt_node_header {
|
|
||||||
fdt32_t tag;
|
|
||||||
char name[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct fdt_property {
|
|
||||||
fdt32_t tag;
|
|
||||||
fdt32_t len;
|
|
||||||
fdt32_t nameoff;
|
|
||||||
char data[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* !__ASSEMBLY */
|
|
||||||
|
|
||||||
#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */
|
|
||||||
#define FDT_TAGSIZE sizeof(fdt32_t)
|
|
||||||
|
|
||||||
#define FDT_BEGIN_NODE 0x1 /* Start node: full name */
|
|
||||||
#define FDT_END_NODE 0x2 /* End node */
|
|
||||||
#define FDT_PROP 0x3 /* Property: name off,
|
|
||||||
size, content */
|
|
||||||
#define FDT_NOP 0x4 /* nop */
|
|
||||||
#define FDT_END 0x9
|
|
||||||
|
|
||||||
#define FDT_V1_SIZE (7*sizeof(fdt32_t))
|
|
||||||
#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(fdt32_t))
|
|
||||||
#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(fdt32_t))
|
|
||||||
#define FDT_V16_SIZE FDT_V3_SIZE
|
|
||||||
#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(fdt32_t))
|
|
||||||
|
|
||||||
#endif /* _FDT_H */
|
|
||||||
|
2138
include/libfdt.h
2138
include/libfdt.h
File diff suppressed because it is too large
Load Diff
@ -1169,7 +1169,8 @@ int fdtdec_setup_memory_size(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
gd->ram_size = (phys_size_t)(res.end - res.start + 1);
|
gd->ram_size = (phys_size_t)(res.end - res.start + 1);
|
||||||
debug("%s: Initial DRAM size %llx\n", __func__, (u64)gd->ram_size);
|
debug("%s: Initial DRAM size %llx\n", __func__,
|
||||||
|
(unsigned long long)gd->ram_size);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
67
lib/libfdt/fdt.h
Normal file
67
lib/libfdt/fdt.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#ifndef _FDT_H
|
||||||
|
#define _FDT_H
|
||||||
|
/*
|
||||||
|
* libfdt - Flat Device Tree manipulation
|
||||||
|
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
||||||
|
* Copyright 2012 Kim Phillips, Freescale Semiconductor.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
struct fdt_header {
|
||||||
|
fdt32_t magic; /* magic word FDT_MAGIC */
|
||||||
|
fdt32_t totalsize; /* total size of DT block */
|
||||||
|
fdt32_t off_dt_struct; /* offset to structure */
|
||||||
|
fdt32_t off_dt_strings; /* offset to strings */
|
||||||
|
fdt32_t off_mem_rsvmap; /* offset to memory reserve map */
|
||||||
|
fdt32_t version; /* format version */
|
||||||
|
fdt32_t last_comp_version; /* last compatible version */
|
||||||
|
|
||||||
|
/* version 2 fields below */
|
||||||
|
fdt32_t boot_cpuid_phys; /* Which physical CPU id we're
|
||||||
|
booting on */
|
||||||
|
/* version 3 fields below */
|
||||||
|
fdt32_t size_dt_strings; /* size of the strings block */
|
||||||
|
|
||||||
|
/* version 17 fields below */
|
||||||
|
fdt32_t size_dt_struct; /* size of the structure block */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fdt_reserve_entry {
|
||||||
|
fdt64_t address;
|
||||||
|
fdt64_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fdt_node_header {
|
||||||
|
fdt32_t tag;
|
||||||
|
char name[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fdt_property {
|
||||||
|
fdt32_t tag;
|
||||||
|
fdt32_t len;
|
||||||
|
fdt32_t nameoff;
|
||||||
|
char data[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* !__ASSEMBLY */
|
||||||
|
|
||||||
|
#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */
|
||||||
|
#define FDT_TAGSIZE sizeof(fdt32_t)
|
||||||
|
|
||||||
|
#define FDT_BEGIN_NODE 0x1 /* Start node: full name */
|
||||||
|
#define FDT_END_NODE 0x2 /* End node */
|
||||||
|
#define FDT_PROP 0x3 /* Property: name off,
|
||||||
|
size, content */
|
||||||
|
#define FDT_NOP 0x4 /* nop */
|
||||||
|
#define FDT_END 0x9
|
||||||
|
|
||||||
|
#define FDT_V1_SIZE (7*sizeof(fdt32_t))
|
||||||
|
#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(fdt32_t))
|
||||||
|
#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(fdt32_t))
|
||||||
|
#define FDT_V16_SIZE FDT_V3_SIZE
|
||||||
|
#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(fdt32_t))
|
||||||
|
|
||||||
|
#endif /* _FDT_H */
|
2144
lib/libfdt/libfdt.h
Normal file
2144
lib/libfdt/libfdt.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,113 +0,0 @@
|
|||||||
/* File: libfdt.i */
|
|
||||||
%module libfdt
|
|
||||||
|
|
||||||
%{
|
|
||||||
#define SWIG_FILE_WITH_INIT
|
|
||||||
#include "libfdt.h"
|
|
||||||
%}
|
|
||||||
|
|
||||||
%pythoncode %{
|
|
||||||
def Raise(errnum):
|
|
||||||
raise ValueError('Error %s' % fdt_strerror(errnum))
|
|
||||||
|
|
||||||
def Name(fdt, offset):
|
|
||||||
name, len = fdt_get_name(fdt, offset)
|
|
||||||
return name
|
|
||||||
|
|
||||||
def String(fdt, offset):
|
|
||||||
offset = fdt32_to_cpu(offset)
|
|
||||||
name = fdt_string(fdt, offset)
|
|
||||||
return name
|
|
||||||
|
|
||||||
def swap32(x):
|
|
||||||
return (((x << 24) & 0xFF000000) |
|
|
||||||
((x << 8) & 0x00FF0000) |
|
|
||||||
((x >> 8) & 0x0000FF00) |
|
|
||||||
((x >> 24) & 0x000000FF))
|
|
||||||
|
|
||||||
def fdt32_to_cpu(x):
|
|
||||||
return swap32(x)
|
|
||||||
|
|
||||||
def Data(prop):
|
|
||||||
set_prop(prop)
|
|
||||||
return get_prop_data()
|
|
||||||
%}
|
|
||||||
|
|
||||||
%include "typemaps.i"
|
|
||||||
%include "cstring.i"
|
|
||||||
|
|
||||||
%typemap(in) void* = char*;
|
|
||||||
|
|
||||||
typedef int fdt32_t;
|
|
||||||
|
|
||||||
struct fdt_property {
|
|
||||||
fdt32_t tag;
|
|
||||||
fdt32_t len;
|
|
||||||
fdt32_t nameoff;
|
|
||||||
char data[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is a work-around since I'm not sure of a better way to copy out the
|
|
||||||
* contents of a string. This is used in dtoc/GetProps(). The intent is to
|
|
||||||
* pass in a pointer to a property and access the data field at the end of
|
|
||||||
* it. Ideally the Data() function above would be able to do this directly,
|
|
||||||
* but I'm not sure how to do that.
|
|
||||||
*/
|
|
||||||
#pragma SWIG nowarn=454
|
|
||||||
%inline %{
|
|
||||||
static struct fdt_property *cur_prop;
|
|
||||||
|
|
||||||
void set_prop(struct fdt_property *prop) {
|
|
||||||
cur_prop = prop;
|
|
||||||
}
|
|
||||||
%}
|
|
||||||
|
|
||||||
%cstring_output_allocate_size(char **s, int *sz, free(*$1));
|
|
||||||
%inline %{
|
|
||||||
void get_prop_data(char **s, int *sz) {
|
|
||||||
*sz = fdt32_to_cpu(cur_prop->len);
|
|
||||||
*s = (char *)malloc(*sz);
|
|
||||||
if (!*s)
|
|
||||||
*sz = 0;
|
|
||||||
else
|
|
||||||
memcpy(*s, cur_prop + 1, *sz);
|
|
||||||
}
|
|
||||||
%}
|
|
||||||
|
|
||||||
%typemap(in) (const void *) {
|
|
||||||
if (!PyByteArray_Check($input)) {
|
|
||||||
SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname" "', argument "
|
|
||||||
"$argnum"" of type '" "$type""'");
|
|
||||||
}
|
|
||||||
$1 = (void *) PyByteArray_AsString($input);
|
|
||||||
}
|
|
||||||
|
|
||||||
const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);
|
|
||||||
int fdt_path_offset(const void *fdt, const char *path);
|
|
||||||
int fdt_first_property_offset(const void *fdt, int nodeoffset);
|
|
||||||
int fdt_next_property_offset(const void *fdt, int offset);
|
|
||||||
const char *fdt_strerror(int errval);
|
|
||||||
const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
|
|
||||||
int offset,
|
|
||||||
int *OUTPUT);
|
|
||||||
const char *fdt_get_name(const void *fdt, int nodeoffset, int *OUTPUT);
|
|
||||||
const char *fdt_string(const void *fdt, int stroffset);
|
|
||||||
int fdt_first_subnode(const void *fdt, int offset);
|
|
||||||
int fdt_next_subnode(const void *fdt, int offset);
|
|
||||||
|
|
||||||
%typemap(in) (void *) {
|
|
||||||
if (!PyByteArray_Check($input)) {
|
|
||||||
SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname" "', argument "
|
|
||||||
"$argnum"" of type '" "$type""'");
|
|
||||||
}
|
|
||||||
$1 = PyByteArray_AsString($input);
|
|
||||||
}
|
|
||||||
|
|
||||||
int fdt_delprop(void *fdt, int nodeoffset, const char *name);
|
|
||||||
|
|
||||||
const char *fdt_strerror(int errval);
|
|
||||||
int fdt_pack(void *fdt);
|
|
||||||
|
|
||||||
int fdt_totalsize(const void *fdt);
|
|
||||||
int fdt_off_dt_struct(const void *fdt);
|
|
389
lib/libfdt/pylibfdt/libfdt.i
Normal file
389
lib/libfdt/pylibfdt/libfdt.i
Normal file
@ -0,0 +1,389 @@
|
|||||||
|
/*
|
||||||
|
* pylibfdt - Flat Device Tree manipulation in Python
|
||||||
|
* Copyright (C) 2017 Google, Inc.
|
||||||
|
* Written by Simon Glass <sjg@chromium.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
%module libfdt
|
||||||
|
|
||||||
|
%{
|
||||||
|
#define SWIG_FILE_WITH_INIT
|
||||||
|
#include "libfdt.h"
|
||||||
|
%}
|
||||||
|
|
||||||
|
%pythoncode %{
|
||||||
|
|
||||||
|
import struct
|
||||||
|
|
||||||
|
# Error codes, corresponding to FDT_ERR_... in libfdt.h
|
||||||
|
(NOTFOUND,
|
||||||
|
EXISTS,
|
||||||
|
NOSPACE,
|
||||||
|
BADOFFSET,
|
||||||
|
BADPATH,
|
||||||
|
BADPHANDLE,
|
||||||
|
BADSTATE,
|
||||||
|
TRUNCATED,
|
||||||
|
BADMAGIC,
|
||||||
|
BADVERSION,
|
||||||
|
BADSTRUCTURE,
|
||||||
|
BADLAYOUT,
|
||||||
|
INTERNAL,
|
||||||
|
BADNCELLS,
|
||||||
|
BADVALUE,
|
||||||
|
BADOVERLAY,
|
||||||
|
NOPHANDLES) = QUIET_ALL = range(1, 18)
|
||||||
|
# QUIET_ALL can be passed as the 'quiet' parameter to avoid exceptions
|
||||||
|
# altogether. All # functions passed this value will return an error instead
|
||||||
|
# of raising an exception.
|
||||||
|
|
||||||
|
# Pass this as the 'quiet' parameter to return -ENOTFOUND on NOTFOUND errors,
|
||||||
|
# instead of raising an exception.
|
||||||
|
QUIET_NOTFOUND = (NOTFOUND,)
|
||||||
|
|
||||||
|
|
||||||
|
class FdtException(Exception):
|
||||||
|
"""An exception caused by an error such as one of the codes above"""
|
||||||
|
def __init__(self, err):
|
||||||
|
self.err = err
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return 'pylibfdt error %d: %s' % (self.err, fdt_strerror(self.err))
|
||||||
|
|
||||||
|
def strerror(fdt_err):
|
||||||
|
"""Get the string for an error number
|
||||||
|
|
||||||
|
Args:
|
||||||
|
fdt_err: Error number (-ve)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
String containing the associated error
|
||||||
|
"""
|
||||||
|
return fdt_strerror(fdt_err)
|
||||||
|
|
||||||
|
def check_err(val, quiet=()):
|
||||||
|
"""Raise an error if the return value is -ve
|
||||||
|
|
||||||
|
This is used to check for errors returned by libfdt C functions.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
val: Return value from a libfdt function
|
||||||
|
quiet: Errors to ignore (empty to raise on all errors)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
val if val >= 0
|
||||||
|
|
||||||
|
Raises
|
||||||
|
FdtException if val < 0
|
||||||
|
"""
|
||||||
|
if val < 0:
|
||||||
|
if -val not in quiet:
|
||||||
|
raise FdtException(val)
|
||||||
|
return val
|
||||||
|
|
||||||
|
def check_err_null(val, quiet=()):
|
||||||
|
"""Raise an error if the return value is NULL
|
||||||
|
|
||||||
|
This is used to check for a NULL return value from certain libfdt C
|
||||||
|
functions
|
||||||
|
|
||||||
|
Args:
|
||||||
|
val: Return value from a libfdt function
|
||||||
|
quiet: Errors to ignore (empty to raise on all errors)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
val if val is a list, None if not
|
||||||
|
|
||||||
|
Raises
|
||||||
|
FdtException if val indicates an error was reported and the error
|
||||||
|
is not in @quiet.
|
||||||
|
"""
|
||||||
|
# Normally a list is returned which contains the data and its length.
|
||||||
|
# If we get just an integer error code, it means the function failed.
|
||||||
|
if not isinstance(val, list):
|
||||||
|
if -val not in quiet:
|
||||||
|
raise FdtException(val)
|
||||||
|
return val
|
||||||
|
|
||||||
|
class Fdt:
|
||||||
|
"""Device tree class, supporting all operations
|
||||||
|
|
||||||
|
The Fdt object is created is created from a device tree binary file,
|
||||||
|
e.g. with something like:
|
||||||
|
|
||||||
|
fdt = Fdt(open("filename.dtb").read())
|
||||||
|
|
||||||
|
Operations can then be performed using the methods in this class. Each
|
||||||
|
method xxx(args...) corresponds to a libfdt function fdt_xxx(fdt, args...).
|
||||||
|
|
||||||
|
All methods raise an FdtException if an error occurs. To avoid this
|
||||||
|
behaviour a 'quiet' parameter is provided for some functions. This
|
||||||
|
defaults to empty, but you can pass a list of errors that you expect.
|
||||||
|
If one of these errors occurs, the function will return an error number
|
||||||
|
(e.g. -NOTFOUND).
|
||||||
|
"""
|
||||||
|
def __init__(self, data):
|
||||||
|
self._fdt = bytearray(data)
|
||||||
|
check_err(fdt_check_header(self._fdt));
|
||||||
|
|
||||||
|
def path_offset(self, path, quiet=()):
|
||||||
|
"""Get the offset for a given path
|
||||||
|
|
||||||
|
Args:
|
||||||
|
path: Path to the required node, e.g. '/node@3/subnode@1'
|
||||||
|
quiet: Errors to ignore (empty to raise on all errors)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Node offset
|
||||||
|
|
||||||
|
Raises
|
||||||
|
FdtException if the path is not valid or not found
|
||||||
|
"""
|
||||||
|
return check_err(fdt_path_offset(self._fdt, path), quiet)
|
||||||
|
|
||||||
|
def first_property_offset(self, nodeoffset, quiet=()):
|
||||||
|
"""Get the offset of the first property in a node offset
|
||||||
|
|
||||||
|
Args:
|
||||||
|
nodeoffset: Offset to the node to check
|
||||||
|
quiet: Errors to ignore (empty to raise on all errors)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Offset of the first property
|
||||||
|
|
||||||
|
Raises
|
||||||
|
FdtException if the associated node has no properties, or some
|
||||||
|
other error occurred
|
||||||
|
"""
|
||||||
|
return check_err(fdt_first_property_offset(self._fdt, nodeoffset),
|
||||||
|
quiet)
|
||||||
|
|
||||||
|
def next_property_offset(self, prop_offset, quiet=()):
|
||||||
|
"""Get the next property in a node
|
||||||
|
|
||||||
|
Args:
|
||||||
|
prop_offset: Offset of the previous property
|
||||||
|
quiet: Errors to ignore (empty to raise on all errors)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Offset of the next property
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
FdtException if the associated node has no more properties, or
|
||||||
|
some other error occurred
|
||||||
|
"""
|
||||||
|
return check_err(fdt_next_property_offset(self._fdt, prop_offset),
|
||||||
|
quiet)
|
||||||
|
|
||||||
|
def get_name(self, nodeoffset):
|
||||||
|
"""Get the name of a node
|
||||||
|
|
||||||
|
Args:
|
||||||
|
nodeoffset: Offset of node to check
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Node name
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
FdtException on error (e.g. nodeoffset is invalid)
|
||||||
|
"""
|
||||||
|
return check_err_null(fdt_get_name(self._fdt, nodeoffset))[0]
|
||||||
|
|
||||||
|
def get_property_by_offset(self, prop_offset, quiet=()):
|
||||||
|
"""Obtains a property that can be examined
|
||||||
|
|
||||||
|
Args:
|
||||||
|
prop_offset: Offset of property (e.g. from first_property_offset())
|
||||||
|
quiet: Errors to ignore (empty to raise on all errors)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Property object, or None if not found
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
FdtException on error (e.g. invalid prop_offset or device
|
||||||
|
tree format)
|
||||||
|
"""
|
||||||
|
pdata = check_err_null(
|
||||||
|
fdt_get_property_by_offset(self._fdt, prop_offset), quiet)
|
||||||
|
if isinstance(pdata, (int)):
|
||||||
|
return pdata
|
||||||
|
return Property(pdata[0], pdata[1])
|
||||||
|
|
||||||
|
def first_subnode(self, nodeoffset, quiet=()):
|
||||||
|
"""Find the first subnode of a parent node
|
||||||
|
|
||||||
|
Args:
|
||||||
|
nodeoffset: Node offset of parent node
|
||||||
|
quiet: Errors to ignore (empty to raise on all errors)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The offset of the first subnode, if any
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
FdtException if no subnode found or other error occurs
|
||||||
|
"""
|
||||||
|
return check_err(fdt_first_subnode(self._fdt, nodeoffset), quiet)
|
||||||
|
|
||||||
|
def next_subnode(self, nodeoffset, quiet=()):
|
||||||
|
"""Find the next subnode
|
||||||
|
|
||||||
|
Args:
|
||||||
|
nodeoffset: Node offset of previous subnode
|
||||||
|
quiet: Errors to ignore (empty to raise on all errors)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The offset of the next subnode, if any
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
FdtException if no more subnode found or other error occurs
|
||||||
|
"""
|
||||||
|
return check_err(fdt_next_subnode(self._fdt, nodeoffset), quiet)
|
||||||
|
|
||||||
|
def totalsize(self):
|
||||||
|
"""Return the total size of the device tree
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Total tree size in bytes
|
||||||
|
"""
|
||||||
|
return check_err(fdt_totalsize(self._fdt))
|
||||||
|
|
||||||
|
def off_dt_struct(self):
|
||||||
|
"""Return the start of the device tree struct area
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Start offset of struct area
|
||||||
|
"""
|
||||||
|
return check_err(fdt_off_dt_struct(self._fdt))
|
||||||
|
|
||||||
|
def pack(self, quiet=()):
|
||||||
|
"""Pack the device tree to remove unused space
|
||||||
|
|
||||||
|
This adjusts the tree in place.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
quiet: Errors to ignore (empty to raise on all errors)
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
FdtException if any error occurs
|
||||||
|
"""
|
||||||
|
return check_err(fdt_pack(self._fdt), quiet)
|
||||||
|
|
||||||
|
def delprop(self, nodeoffset, prop_name):
|
||||||
|
"""Delete a property from a node
|
||||||
|
|
||||||
|
Args:
|
||||||
|
nodeoffset: Node offset containing property to delete
|
||||||
|
prop_name: Name of property to delete
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
FdtError if the property does not exist, or another error occurs
|
||||||
|
"""
|
||||||
|
return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name))
|
||||||
|
|
||||||
|
def getprop(self, nodeoffset, prop_name, quiet=()):
|
||||||
|
"""Get a property from a node
|
||||||
|
|
||||||
|
Args:
|
||||||
|
nodeoffset: Node offset containing property to get
|
||||||
|
prop_name: Name of property to get
|
||||||
|
quiet: Errors to ignore (empty to raise on all errors)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Value of property as a bytearray, or -ve error number
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
FdtError if any error occurs (e.g. the property is not found)
|
||||||
|
"""
|
||||||
|
pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name),
|
||||||
|
quiet)
|
||||||
|
if isinstance(pdata, (int)):
|
||||||
|
return pdata
|
||||||
|
return bytearray(pdata[0])
|
||||||
|
|
||||||
|
|
||||||
|
class Property:
|
||||||
|
"""Holds a device tree property name and value.
|
||||||
|
|
||||||
|
This holds a copy of a property taken from the device tree. It does not
|
||||||
|
reference the device tree, so if anything changes in the device tree,
|
||||||
|
a Property object will remain valid.
|
||||||
|
|
||||||
|
Properties:
|
||||||
|
name: Property name
|
||||||
|
value: Proper value as a bytearray
|
||||||
|
"""
|
||||||
|
def __init__(self, name, value):
|
||||||
|
self.name = name
|
||||||
|
self.value = value
|
||||||
|
%}
|
||||||
|
|
||||||
|
%rename(fdt_property) fdt_property_func;
|
||||||
|
|
||||||
|
typedef int fdt32_t;
|
||||||
|
|
||||||
|
%include "libfdt/fdt.h"
|
||||||
|
|
||||||
|
%include "typemaps.i"
|
||||||
|
|
||||||
|
/* Most functions don't change the device tree, so use a const void * */
|
||||||
|
%typemap(in) (const void *)(const void *fdt) {
|
||||||
|
if (!PyByteArray_Check($input)) {
|
||||||
|
SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname"
|
||||||
|
"', argument " "$argnum"" of type '" "$type""'");
|
||||||
|
}
|
||||||
|
$1 = (void *)PyByteArray_AsString($input);
|
||||||
|
fdt = $1;
|
||||||
|
fdt = fdt; /* avoid unused variable warning */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Some functions do change the device tree, so use void * */
|
||||||
|
%typemap(in) (void *)(const void *fdt) {
|
||||||
|
if (!PyByteArray_Check($input)) {
|
||||||
|
SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname"
|
||||||
|
"', argument " "$argnum"" of type '" "$type""'");
|
||||||
|
}
|
||||||
|
$1 = PyByteArray_AsString($input);
|
||||||
|
fdt = $1;
|
||||||
|
fdt = fdt; /* avoid unused variable warning */
|
||||||
|
}
|
||||||
|
|
||||||
|
%typemap(out) (struct fdt_property *) {
|
||||||
|
PyObject *buff;
|
||||||
|
|
||||||
|
if ($1) {
|
||||||
|
resultobj = PyString_FromString(
|
||||||
|
fdt_string(fdt1, fdt32_to_cpu($1->nameoff)));
|
||||||
|
buff = PyByteArray_FromStringAndSize(
|
||||||
|
(const char *)($1 + 1), fdt32_to_cpu($1->len));
|
||||||
|
resultobj = SWIG_Python_AppendOutput(resultobj, buff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
%apply int *OUTPUT { int *lenp };
|
||||||
|
|
||||||
|
/* typemap used for fdt_getprop() */
|
||||||
|
%typemap(out) (const void *) {
|
||||||
|
if (!$1)
|
||||||
|
$result = Py_None;
|
||||||
|
else
|
||||||
|
$result = Py_BuildValue("s#", $1, *arg4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We have both struct fdt_property and a function fdt_property() */
|
||||||
|
%warnfilter(302) fdt_property;
|
||||||
|
|
||||||
|
/* These are macros in the header so have to be redefined here */
|
||||||
|
int fdt_magic(const void *fdt);
|
||||||
|
int fdt_totalsize(const void *fdt);
|
||||||
|
int fdt_off_dt_struct(const void *fdt);
|
||||||
|
int fdt_off_dt_strings(const void *fdt);
|
||||||
|
int fdt_off_mem_rsvmap(const void *fdt);
|
||||||
|
int fdt_version(const void *fdt);
|
||||||
|
int fdt_last_comp_version(const void *fdt);
|
||||||
|
int fdt_boot_cpuid_phys(const void *fdt);
|
||||||
|
int fdt_size_dt_strings(const void *fdt);
|
||||||
|
int fdt_size_dt_struct(const void *fdt);
|
||||||
|
|
||||||
|
%include <../libfdt/libfdt.h>
|
123
lib/libfdt/pylibfdt/setup.py
Executable file
123
lib/libfdt/pylibfdt/setup.py
Executable file
@ -0,0 +1,123 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
setup.py file for SWIG libfdt
|
||||||
|
Copyright (C) 2017 Google, Inc.
|
||||||
|
Written by Simon Glass <sjg@chromium.org>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause
|
||||||
|
|
||||||
|
Files to be built into the extension are provided in SOURCES
|
||||||
|
C flags to use are provided in CPPFLAGS
|
||||||
|
Object file directory is provided in OBJDIR
|
||||||
|
Version is provided in VERSION
|
||||||
|
|
||||||
|
If these variables are not given they are parsed from the Makefiles. This
|
||||||
|
allows this script to be run stand-alone, e.g.:
|
||||||
|
|
||||||
|
./pylibfdt/setup.py install [--prefix=...]
|
||||||
|
"""
|
||||||
|
|
||||||
|
from distutils.core import setup, Extension
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# Decodes a Makefile assignment line into key and value (and plus for +=)
|
||||||
|
RE_KEY_VALUE = re.compile('(?P<key>\w+) *(?P<plus>[+])?= *(?P<value>.*)$')
|
||||||
|
|
||||||
|
|
||||||
|
def ParseMakefile(fname):
|
||||||
|
"""Parse a Makefile to obtain its variables.
|
||||||
|
|
||||||
|
This collects variable assigments of the form:
|
||||||
|
|
||||||
|
VAR = value
|
||||||
|
VAR += more
|
||||||
|
|
||||||
|
It does not pick out := assignments, as these are not needed here. It does
|
||||||
|
handle line continuation.
|
||||||
|
|
||||||
|
Returns a dict:
|
||||||
|
key: Variable name (e.g. 'VAR')
|
||||||
|
value: Variable value (e.g. 'value more')
|
||||||
|
"""
|
||||||
|
makevars = {}
|
||||||
|
with open(fname) as fd:
|
||||||
|
prev_text = '' # Continuation text from previous line(s)
|
||||||
|
for line in fd.read().splitlines():
|
||||||
|
if line and line[-1] == '\\': # Deal with line continuation
|
||||||
|
prev_text += line[:-1]
|
||||||
|
continue
|
||||||
|
elif prev_text:
|
||||||
|
line = prev_text + line
|
||||||
|
prev_text = '' # Continuation is now used up
|
||||||
|
m = RE_KEY_VALUE.match(line)
|
||||||
|
if m:
|
||||||
|
value = m.group('value') or ''
|
||||||
|
key = m.group('key')
|
||||||
|
|
||||||
|
# Appending to a variable inserts a space beforehand
|
||||||
|
if 'plus' in m.groupdict() and key in makevars:
|
||||||
|
makevars[key] += ' ' + value
|
||||||
|
else:
|
||||||
|
makevars[key] = value
|
||||||
|
return makevars
|
||||||
|
|
||||||
|
def GetEnvFromMakefiles():
|
||||||
|
"""Scan the Makefiles to obtain the settings we need.
|
||||||
|
|
||||||
|
This assumes that this script is being run from the top-level directory,
|
||||||
|
not the pylibfdt directory.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Tuple with:
|
||||||
|
List of swig options
|
||||||
|
Version string
|
||||||
|
List of files to build
|
||||||
|
List of extra C preprocessor flags needed
|
||||||
|
Object directory to use (always '')
|
||||||
|
"""
|
||||||
|
basedir = os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0])))
|
||||||
|
swig_opts = ['-I%s' % basedir]
|
||||||
|
makevars = ParseMakefile(os.path.join(basedir, 'Makefile'))
|
||||||
|
version = '%s.%s.%s' % (makevars['VERSION'], makevars['PATCHLEVEL'],
|
||||||
|
makevars['SUBLEVEL'])
|
||||||
|
makevars = ParseMakefile(os.path.join(basedir, 'libfdt', 'Makefile.libfdt'))
|
||||||
|
files = makevars['LIBFDT_SRCS'].split()
|
||||||
|
files = [os.path.join(basedir, 'libfdt', fname) for fname in files]
|
||||||
|
files.append('pylibfdt/libfdt.i')
|
||||||
|
cflags = ['-I%s' % basedir, '-I%s/libfdt' % basedir]
|
||||||
|
objdir = ''
|
||||||
|
return swig_opts, version, files, cflags, objdir
|
||||||
|
|
||||||
|
|
||||||
|
progname = sys.argv[0]
|
||||||
|
files = os.environ.get('SOURCES', '').split()
|
||||||
|
cflags = os.environ.get('CPPFLAGS', '').split()
|
||||||
|
objdir = os.environ.get('OBJDIR')
|
||||||
|
version = os.environ.get('VERSION')
|
||||||
|
swig_opts = os.environ.get('SWIG_OPTS', '').split()
|
||||||
|
|
||||||
|
# If we were called directly rather than through our Makefile (which is often
|
||||||
|
# the case with Python module installation), read the settings from the
|
||||||
|
# Makefile.
|
||||||
|
if not all((swig_opts, version, files, cflags, objdir)):
|
||||||
|
swig_opts, version, files, cflags, objdir = GetEnvFromMakefiles()
|
||||||
|
|
||||||
|
libfdt_module = Extension(
|
||||||
|
'_libfdt',
|
||||||
|
sources = files,
|
||||||
|
extra_compile_args = cflags,
|
||||||
|
swig_opts = swig_opts,
|
||||||
|
)
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name='libfdt',
|
||||||
|
version= version,
|
||||||
|
author='Simon Glass <sjg@chromium.org>',
|
||||||
|
description='Python binding for libfdt',
|
||||||
|
ext_modules=[libfdt_module],
|
||||||
|
package_dir={'': objdir},
|
||||||
|
py_modules=['pylibfdt/libfdt'],
|
||||||
|
)
|
@ -1,38 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
"""
|
|
||||||
setup.py file for SWIG libfdt
|
|
||||||
"""
|
|
||||||
|
|
||||||
from distutils.core import setup, Extension
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
# Don't cross-compile - always use the host compiler.
|
|
||||||
del os.environ['CROSS_COMPILE']
|
|
||||||
del os.environ['CC']
|
|
||||||
|
|
||||||
progname = sys.argv[0]
|
|
||||||
cflags = sys.argv[1]
|
|
||||||
files = sys.argv[2:]
|
|
||||||
|
|
||||||
if cflags:
|
|
||||||
cflags = [flag for flag in cflags.split(' ') if flag]
|
|
||||||
else:
|
|
||||||
cflags = None
|
|
||||||
|
|
||||||
libfdt_module = Extension(
|
|
||||||
'_libfdt',
|
|
||||||
sources = files,
|
|
||||||
extra_compile_args = cflags
|
|
||||||
)
|
|
||||||
|
|
||||||
sys.argv = [progname, '--quiet', 'build_ext', '--inplace', '--force']
|
|
||||||
|
|
||||||
setup (name = 'libfdt',
|
|
||||||
version = '0.1',
|
|
||||||
author = "SWIG Docs",
|
|
||||||
description = """Simple swig libfdt from docs""",
|
|
||||||
ext_modules = [libfdt_module],
|
|
||||||
py_modules = ["libfdt"],
|
|
||||||
)
|
|
@ -257,14 +257,12 @@ PHONY += dts_dir
|
|||||||
dts_dir:
|
dts_dir:
|
||||||
$(shell [ -d $(obj)/dts ] || mkdir -p $(obj)/dts)
|
$(shell [ -d $(obj)/dts ] || mkdir -p $(obj)/dts)
|
||||||
|
|
||||||
include/generated/dt-structs.h: $(obj)/$(SPL_BIN).dtb dts_dir dtoc
|
include/generated/dt-structs.h: $(obj)/$(SPL_BIN).dtb dts_dir checkdtoc
|
||||||
$(call if_changed,dtoch)
|
$(call if_changed,dtoch)
|
||||||
|
|
||||||
$(obj)/dts/dt-platdata.c: $(obj)/$(SPL_BIN).dtb dts_dir dtoc
|
$(obj)/dts/dt-platdata.c: $(obj)/$(SPL_BIN).dtb dts_dir checkdtoc
|
||||||
$(call if_changed,dtocc)
|
$(call if_changed,dtocc)
|
||||||
|
|
||||||
dtoc: #$(objtree)/tools/_libfdt.so
|
|
||||||
|
|
||||||
ifdef CONFIG_SAMSUNG
|
ifdef CONFIG_SAMSUNG
|
||||||
ifdef CONFIG_VAR_SIZE_SPL
|
ifdef CONFIG_VAR_SIZE_SPL
|
||||||
VAR_SIZE_PARAM = --vs
|
VAR_SIZE_PARAM = --vs
|
||||||
@ -357,6 +355,17 @@ ifneq ($(cmd_files),)
|
|||||||
include $(cmd_files)
|
include $(cmd_files)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
checkdtoc: tools
|
||||||
|
@if ! ( echo 'import libfdt' | ( PYTHONPATH=tools python )); then \
|
||||||
|
echo '*** dtoc needs the Python libfdt library. Either '; \
|
||||||
|
echo '*** install it on your system, or try:'; \
|
||||||
|
echo '***'; \
|
||||||
|
echo '*** sudo apt-get install swig libpython-dev'; \
|
||||||
|
echo '***'; \
|
||||||
|
echo '*** to have U-Boot build its own version.'; \
|
||||||
|
false; \
|
||||||
|
fi
|
||||||
|
|
||||||
PHONY += FORCE
|
PHONY += FORCE
|
||||||
FORCE:
|
FORCE:
|
||||||
|
|
||||||
|
@ -60,9 +60,21 @@ hostprogs-$(CONFIG_FIT_SIGNATURE) += fit_info fit_check_sign
|
|||||||
|
|
||||||
FIT_SIG_OBJS-$(CONFIG_FIT_SIGNATURE) := common/image-sig.o
|
FIT_SIG_OBJS-$(CONFIG_FIT_SIGNATURE) := common/image-sig.o
|
||||||
# Flattened device tree objects
|
# Flattened device tree objects
|
||||||
LIBFDT_OBJS := $(addprefix lib/libfdt/, \
|
LIBFDT_CSRCS := fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c \
|
||||||
fdt.o fdt_ro.o fdt_rw.o fdt_strerror.o fdt_wip.o \
|
fdt_empty_tree.c fdt_addresses.c fdt_overlay.c \
|
||||||
fdt_region.o fdt_sw.o)
|
fdt_region.c
|
||||||
|
|
||||||
|
# Unfortunately setup.py below cannot handle srctree being ".." which it often
|
||||||
|
# is. It fails with an error like:
|
||||||
|
# Fatal error: can't create build/temp.linux-x86_64-2.7/../lib/libfdt/fdt.o:
|
||||||
|
# No such file or directory
|
||||||
|
# To fix this, use an absolute path.
|
||||||
|
libfdt_tree := $(shell readlink -f $(srctree)/lib/libfdt)
|
||||||
|
|
||||||
|
LIBFDT_SRCS := $(addprefix $(libfdt_tree)/, $(LIBFDT_CSRCS))
|
||||||
|
LIBFDT_SWIG := $(addprefix $(libfdt_tree)/, pylibfdt/libfdt.i)
|
||||||
|
LIBFDT_OBJS := $(addprefix lib/libfdt/, $(patsubst %.c, %.o, $(LIBFDT_CSRCS)))
|
||||||
|
|
||||||
RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := $(addprefix lib/rsa/, \
|
RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := $(addprefix lib/rsa/, \
|
||||||
rsa-sign.o rsa-verify.o rsa-checksum.o \
|
rsa-sign.o rsa-verify.o rsa-checksum.o \
|
||||||
rsa-mod-exp.o)
|
rsa-mod-exp.o)
|
||||||
@ -112,22 +124,22 @@ mkimage-objs := $(dumpimage-mkimage-objs) mkimage.o
|
|||||||
fit_info-objs := $(dumpimage-mkimage-objs) fit_info.o
|
fit_info-objs := $(dumpimage-mkimage-objs) fit_info.o
|
||||||
fit_check_sign-objs := $(dumpimage-mkimage-objs) fit_check_sign.o
|
fit_check_sign-objs := $(dumpimage-mkimage-objs) fit_check_sign.o
|
||||||
|
|
||||||
# Build a libfdt Python module if swig is available
|
# Unfortunately setup.py (or actually the Python distutil implementation)
|
||||||
# Use 'sudo apt-get install swig libpython-dev' to enable this
|
# puts files into the same directory as the .i file. We cannot touch the source
|
||||||
hostprogs-y += \
|
# directory, so we copy the .i file into the tools/ build subdirectory before
|
||||||
$(if $(shell which swig 2> /dev/null),_libfdt.so)
|
# calling setup. This directory is safe to write to. This ensures that we get
|
||||||
_libfdt.so-sharedobjs += $(LIBFDT_OBJS)
|
# all three files in $(obj)/tools: _libfdt.so, libfdt.py and libfdt_wrap.c
|
||||||
libfdt:
|
# The latter is a temporary file which we could actually remove.
|
||||||
|
tools/_libfdt.so: $(LIBFDT_SRCS) $(LIBFDT_SWIG)
|
||||||
tools/_libfdt.so: $(patsubst %.o,%.c,$(LIBFDT_OBJS)) tools/libfdt_wrap.c
|
cp $(LIBFDT_SWIG) tools/.
|
||||||
LDFLAGS="$(HOSTLDFLAGS)" CFLAGS= ${PYTHON} $(srctree)/lib/libfdt/setup.py \
|
unset CC; \
|
||||||
"$(_hostc_flags)" $^
|
unset CROSS_COMPILE; \
|
||||||
mv _libfdt.so $@
|
LDFLAGS="$(HOSTLDFLAGS)" CFLAGS= VERSION="u-boot-$(UBOOTVERSION)" \
|
||||||
|
CPPFLAGS="$(_hostc_flags)" OBJDIR=tools \
|
||||||
tools/libfdt_wrap.c: $(srctree)/lib/libfdt/libfdt.swig
|
SOURCES="$(LIBFDT_SRCS) tools/libfdt.i" \
|
||||||
swig -python -o $@ $<
|
SWIG_OPTS="-I$(srctree)/lib/libfdt -I$(srctree)/lib" \
|
||||||
|
$(libfdt_tree)/pylibfdt/setup.py --quiet build_ext \
|
||||||
# TODO(sjg@chromium.org): Is this correct on Mac OS?
|
--build-lib tools
|
||||||
|
|
||||||
ifneq ($(CONFIG_MX23)$(CONFIG_MX28),)
|
ifneq ($(CONFIG_MX23)$(CONFIG_MX28),)
|
||||||
# Add CONFIG_MXS into host CFLAGS, so we can check whether or not register
|
# Add CONFIG_MXS into host CFLAGS, so we can check whether or not register
|
||||||
@ -216,6 +228,10 @@ clean-dirs := lib common
|
|||||||
|
|
||||||
always := $(hostprogs-y)
|
always := $(hostprogs-y)
|
||||||
|
|
||||||
|
# Build a libfdt Python module if swig is available
|
||||||
|
# Use 'sudo apt-get install swig libpython-dev' to enable this
|
||||||
|
always += $(if $(shell which swig 2> /dev/null),_libfdt.so)
|
||||||
|
|
||||||
# Generated LCD/video logo
|
# Generated LCD/video logo
|
||||||
LOGO_H = $(objtree)/include/bmp_logo.h
|
LOGO_H = $(objtree)/include/bmp_logo.h
|
||||||
LOGO_DATA_H = $(objtree)/include/bmp_logo_data.h
|
LOGO_DATA_H = $(objtree)/include/bmp_logo_data.h
|
||||||
|
@ -21,6 +21,9 @@ sys.path.append(os.path.join(our_path, '../patman'))
|
|||||||
sys.path.append(os.path.join(our_path, '../dtoc'))
|
sys.path.append(os.path.join(our_path, '../dtoc'))
|
||||||
sys.path.append(os.path.join(our_path, '../'))
|
sys.path.append(os.path.join(our_path, '../'))
|
||||||
|
|
||||||
|
# Bring in the libfdt module
|
||||||
|
sys.path.append('tools')
|
||||||
|
|
||||||
# Also allow entry-type modules to be brought in from the etype directory.
|
# Also allow entry-type modules to be brought in from the etype directory.
|
||||||
sys.path.append(os.path.join(our_path, 'etype'))
|
sys.path.append(os.path.join(our_path, 'etype'))
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import sys
|
|||||||
import tools
|
import tools
|
||||||
|
|
||||||
import command
|
import command
|
||||||
import fdt_select
|
import fdt
|
||||||
import fdt_util
|
import fdt_util
|
||||||
from image import Image
|
from image import Image
|
||||||
import tout
|
import tout
|
||||||
@ -40,15 +40,15 @@ def _ReadImageDesc(binman_node):
|
|||||||
images['image'] = Image('image', binman_node)
|
images['image'] = Image('image', binman_node)
|
||||||
return images
|
return images
|
||||||
|
|
||||||
def _FindBinmanNode(fdt):
|
def _FindBinmanNode(dtb):
|
||||||
"""Find the 'binman' node in the device tree
|
"""Find the 'binman' node in the device tree
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
fdt: Fdt object to scan
|
dtb: Fdt object to scan
|
||||||
Returns:
|
Returns:
|
||||||
Node object of /binman node, or None if not found
|
Node object of /binman node, or None if not found
|
||||||
"""
|
"""
|
||||||
for node in fdt.GetRoot().subnodes:
|
for node in dtb.GetRoot().subnodes:
|
||||||
if node.name == 'binman':
|
if node.name == 'binman':
|
||||||
return node
|
return node
|
||||||
return None
|
return None
|
||||||
@ -92,8 +92,8 @@ def Binman(options, args):
|
|||||||
try:
|
try:
|
||||||
tools.SetInputDirs(options.indir)
|
tools.SetInputDirs(options.indir)
|
||||||
tools.PrepareOutputDir(options.outdir, options.preserve)
|
tools.PrepareOutputDir(options.outdir, options.preserve)
|
||||||
fdt = fdt_select.FdtScan(dtb_fname)
|
dtb = fdt.FdtScan(dtb_fname)
|
||||||
node = _FindBinmanNode(fdt)
|
node = _FindBinmanNode(dtb)
|
||||||
if not node:
|
if not node:
|
||||||
raise ValueError("Device tree '%s' does not have a 'binman' "
|
raise ValueError("Device tree '%s' does not have a 'binman' "
|
||||||
"node" % dtb_fname)
|
"node" % dtb_fname)
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
# Entry-type module for U-Boot device tree with the microcode removed
|
# Entry-type module for U-Boot device tree with the microcode removed
|
||||||
#
|
#
|
||||||
|
|
||||||
import fdt_select
|
import fdt
|
||||||
from entry import Entry
|
from entry import Entry
|
||||||
from blob import Entry_blob
|
from blob import Entry_blob
|
||||||
import tools
|
import tools
|
||||||
@ -44,9 +44,8 @@ class Entry_u_boot_dtb_with_ucode(Entry_blob):
|
|||||||
fd.write(self.data)
|
fd.write(self.data)
|
||||||
|
|
||||||
# Remove the microcode
|
# Remove the microcode
|
||||||
fdt = fdt_select.FdtScan(fname)
|
dtb = fdt.FdtScan(fname)
|
||||||
fdt.Scan()
|
ucode = dtb.GetNode('/microcode')
|
||||||
ucode = fdt.GetNode('/microcode')
|
|
||||||
if not ucode:
|
if not ucode:
|
||||||
raise self.Raise("No /microcode node found in '%s'" % fname)
|
raise self.Raise("No /microcode node found in '%s'" % fname)
|
||||||
|
|
||||||
@ -57,20 +56,15 @@ class Entry_u_boot_dtb_with_ucode(Entry_blob):
|
|||||||
data_prop = node.props.get('data')
|
data_prop = node.props.get('data')
|
||||||
if data_prop:
|
if data_prop:
|
||||||
self.ucode_data += ''.join(data_prop.bytes)
|
self.ucode_data += ''.join(data_prop.bytes)
|
||||||
if not self.collate:
|
|
||||||
poffset = data_prop.GetOffset()
|
|
||||||
if poffset is None:
|
|
||||||
# We cannot obtain a property offset. Collate instead.
|
|
||||||
self.collate = True
|
|
||||||
else:
|
|
||||||
# Find the offset in the device tree of the ucode data
|
|
||||||
self.ucode_offset = poffset + 12
|
|
||||||
self.ucode_size = len(data_prop.bytes)
|
|
||||||
if self.collate:
|
if self.collate:
|
||||||
prop = node.DeleteProp('data')
|
prop = node.DeleteProp('data')
|
||||||
|
else:
|
||||||
|
# Find the offset in the device tree of the ucode data
|
||||||
|
self.ucode_offset = data_prop.GetOffset() + 12
|
||||||
|
self.ucode_size = len(data_prop.bytes)
|
||||||
if self.collate:
|
if self.collate:
|
||||||
fdt.Pack()
|
dtb.Pack()
|
||||||
fdt.Flush()
|
dtb.Flush()
|
||||||
|
|
||||||
# Make this file the contents of this entry
|
# Make this file the contents of this entry
|
||||||
self._pathname = fname
|
self._pathname = fname
|
||||||
|
@ -11,7 +11,8 @@ import sys
|
|||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from fdt_select import FdtScan
|
import fdt
|
||||||
|
from fdt import FdtScan
|
||||||
import fdt_util
|
import fdt_util
|
||||||
import tools
|
import tools
|
||||||
|
|
||||||
@ -28,21 +29,56 @@ class TestFdt(unittest.TestCase):
|
|||||||
def GetCompiled(self, fname):
|
def GetCompiled(self, fname):
|
||||||
return fdt_util.EnsureCompiled(self.TestFile(fname))
|
return fdt_util.EnsureCompiled(self.TestFile(fname))
|
||||||
|
|
||||||
def _DeleteProp(self, fdt):
|
def _DeleteProp(self, dt):
|
||||||
node = fdt.GetNode('/microcode/update@0')
|
node = dt.GetNode('/microcode/update@0')
|
||||||
node.DeleteProp('data')
|
node.DeleteProp('data')
|
||||||
|
|
||||||
def testFdtNormal(self):
|
def testFdtNormal(self):
|
||||||
fname = self.GetCompiled('34_x86_ucode.dts')
|
fname = self.GetCompiled('34_x86_ucode.dts')
|
||||||
fdt = FdtScan(fname)
|
dt = FdtScan(fname)
|
||||||
self._DeleteProp(fdt)
|
self._DeleteProp(dt)
|
||||||
|
|
||||||
def testFdtFallback(self):
|
def testFdtNormalProp(self):
|
||||||
fname = self.GetCompiled('34_x86_ucode.dts')
|
fname = self.GetCompiled('45_prop_test.dts')
|
||||||
fdt = FdtScan(fname, True)
|
dt = FdtScan(fname)
|
||||||
fdt.GetProp('/microcode/update@0', 'data')
|
node = dt.GetNode('/binman/intel-me')
|
||||||
self.assertEqual('fred',
|
self.assertEquals('intel-me', node.name)
|
||||||
fdt.GetProp('/microcode/update@0', 'none', default='fred'))
|
val = fdt_util.GetString(node, 'filename')
|
||||||
self.assertEqual('12345678 12345679',
|
self.assertEquals(str, type(val))
|
||||||
fdt.GetProp('/microcode/update@0', 'data', typespec='x'))
|
self.assertEquals('me.bin', val)
|
||||||
self._DeleteProp(fdt)
|
|
||||||
|
prop = node.props['intval']
|
||||||
|
self.assertEquals(fdt.TYPE_INT, prop.type)
|
||||||
|
self.assertEquals(3, fdt_util.GetInt(node, 'intval'))
|
||||||
|
|
||||||
|
prop = node.props['intarray']
|
||||||
|
self.assertEquals(fdt.TYPE_INT, prop.type)
|
||||||
|
self.assertEquals(list, type(prop.value))
|
||||||
|
self.assertEquals(2, len(prop.value))
|
||||||
|
self.assertEquals([5, 6],
|
||||||
|
[fdt_util.fdt32_to_cpu(val) for val in prop.value])
|
||||||
|
|
||||||
|
prop = node.props['byteval']
|
||||||
|
self.assertEquals(fdt.TYPE_BYTE, prop.type)
|
||||||
|
self.assertEquals(chr(8), prop.value)
|
||||||
|
|
||||||
|
prop = node.props['bytearray']
|
||||||
|
self.assertEquals(fdt.TYPE_BYTE, prop.type)
|
||||||
|
self.assertEquals(list, type(prop.value))
|
||||||
|
self.assertEquals(str, type(prop.value[0]))
|
||||||
|
self.assertEquals(3, len(prop.value))
|
||||||
|
self.assertEquals([chr(1), '#', '4'], prop.value)
|
||||||
|
|
||||||
|
prop = node.props['longbytearray']
|
||||||
|
self.assertEquals(fdt.TYPE_INT, prop.type)
|
||||||
|
self.assertEquals(0x090a0b0c, fdt_util.GetInt(node, 'longbytearray'))
|
||||||
|
|
||||||
|
prop = node.props['stringval']
|
||||||
|
self.assertEquals(fdt.TYPE_STRING, prop.type)
|
||||||
|
self.assertEquals('message2', fdt_util.GetString(node, 'stringval'))
|
||||||
|
|
||||||
|
prop = node.props['stringarray']
|
||||||
|
self.assertEquals(fdt.TYPE_STRING, prop.type)
|
||||||
|
self.assertEquals(list, type(prop.value))
|
||||||
|
self.assertEquals(3, len(prop.value))
|
||||||
|
self.assertEquals(['another', 'multi-word', 'message'], prop.value)
|
||||||
|
@ -21,7 +21,7 @@ import cmdline
|
|||||||
import command
|
import command
|
||||||
import control
|
import control
|
||||||
import entry
|
import entry
|
||||||
import fdt_select
|
import fdt
|
||||||
import fdt_util
|
import fdt_util
|
||||||
import tools
|
import tools
|
||||||
import tout
|
import tout
|
||||||
@ -658,8 +658,8 @@ class TestFunctional(unittest.TestCase):
|
|||||||
fname = tools.GetOutputFilename('test.dtb')
|
fname = tools.GetOutputFilename('test.dtb')
|
||||||
with open(fname, 'wb') as fd:
|
with open(fname, 'wb') as fd:
|
||||||
fd.write(second)
|
fd.write(second)
|
||||||
fdt = fdt_select.FdtScan(fname)
|
dtb = fdt.FdtScan(fname)
|
||||||
ucode = fdt.GetNode('/microcode')
|
ucode = dtb.GetNode('/microcode')
|
||||||
self.assertTrue(ucode)
|
self.assertTrue(ucode)
|
||||||
for node in ucode.subnodes:
|
for node in ucode.subnodes:
|
||||||
self.assertFalse(node.props.get('data'))
|
self.assertFalse(node.props.get('data'))
|
||||||
@ -683,7 +683,7 @@ class TestFunctional(unittest.TestCase):
|
|||||||
self.assertEqual('nodtb with microcode' + pos_and_size +
|
self.assertEqual('nodtb with microcode' + pos_and_size +
|
||||||
' somewhere in here', first)
|
' somewhere in here', first)
|
||||||
|
|
||||||
def _RunPackUbootSingleMicrocode(self, collate):
|
def _RunPackUbootSingleMicrocode(self):
|
||||||
"""Test that x86 microcode can be handled correctly
|
"""Test that x86 microcode can be handled correctly
|
||||||
|
|
||||||
We expect to see the following in the image, in order:
|
We expect to see the following in the image, in order:
|
||||||
@ -695,8 +695,6 @@ class TestFunctional(unittest.TestCase):
|
|||||||
# We need the libfdt library to run this test since only that allows
|
# We need the libfdt library to run this test since only that allows
|
||||||
# finding the offset of a property. This is required by
|
# finding the offset of a property. This is required by
|
||||||
# Entry_u_boot_dtb_with_ucode.ObtainContents().
|
# Entry_u_boot_dtb_with_ucode.ObtainContents().
|
||||||
if not fdt_select.have_libfdt:
|
|
||||||
return
|
|
||||||
data = self._DoReadFile('35_x86_single_ucode.dts', True)
|
data = self._DoReadFile('35_x86_single_ucode.dts', True)
|
||||||
|
|
||||||
second = data[len(U_BOOT_NODTB_DATA):]
|
second = data[len(U_BOOT_NODTB_DATA):]
|
||||||
@ -705,34 +703,22 @@ class TestFunctional(unittest.TestCase):
|
|||||||
third = second[fdt_len:]
|
third = second[fdt_len:]
|
||||||
second = second[:fdt_len]
|
second = second[:fdt_len]
|
||||||
|
|
||||||
if not collate:
|
ucode_data = struct.pack('>2L', 0x12345678, 0x12345679)
|
||||||
ucode_data = struct.pack('>2L', 0x12345678, 0x12345679)
|
self.assertIn(ucode_data, second)
|
||||||
self.assertIn(ucode_data, second)
|
ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
|
||||||
ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
|
|
||||||
|
|
||||||
# Check that the microcode pointer was inserted. It should match the
|
# Check that the microcode pointer was inserted. It should match the
|
||||||
# expected position and size
|
# expected position and size
|
||||||
pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
|
pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
|
||||||
len(ucode_data))
|
len(ucode_data))
|
||||||
first = data[:len(U_BOOT_NODTB_DATA)]
|
first = data[:len(U_BOOT_NODTB_DATA)]
|
||||||
self.assertEqual('nodtb with microcode' + pos_and_size +
|
self.assertEqual('nodtb with microcode' + pos_and_size +
|
||||||
' somewhere in here', first)
|
' somewhere in here', first)
|
||||||
|
|
||||||
def testPackUbootSingleMicrocode(self):
|
def testPackUbootSingleMicrocode(self):
|
||||||
"""Test that x86 microcode can be handled correctly with fdt_normal.
|
"""Test that x86 microcode can be handled correctly with fdt_normal.
|
||||||
"""
|
"""
|
||||||
self._RunPackUbootSingleMicrocode(False)
|
self._RunPackUbootSingleMicrocode()
|
||||||
|
|
||||||
def testPackUbootSingleMicrocodeFallback(self):
|
|
||||||
"""Test that x86 microcode can be handled correctly with fdt_fallback.
|
|
||||||
|
|
||||||
This only supports collating the microcode.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
old_val = fdt_select.UseFallback(True)
|
|
||||||
self._RunPackUbootSingleMicrocode(True)
|
|
||||||
finally:
|
|
||||||
fdt_select.UseFallback(old_val)
|
|
||||||
|
|
||||||
def testUBootImg(self):
|
def testUBootImg(self):
|
||||||
"""Test that u-boot.img can be put in a file"""
|
"""Test that u-boot.img can be put in a file"""
|
||||||
@ -763,14 +749,12 @@ class TestFunctional(unittest.TestCase):
|
|||||||
def testMicrocodeWithoutPtrInElf(self):
|
def testMicrocodeWithoutPtrInElf(self):
|
||||||
"""Test that a U-Boot binary without the microcode symbol is detected"""
|
"""Test that a U-Boot binary without the microcode symbol is detected"""
|
||||||
# ELF file without a '_dt_ucode_base_size' symbol
|
# ELF file without a '_dt_ucode_base_size' symbol
|
||||||
if not fdt_select.have_libfdt:
|
|
||||||
return
|
|
||||||
try:
|
try:
|
||||||
with open(self.TestFile('u_boot_no_ucode_ptr')) as fd:
|
with open(self.TestFile('u_boot_no_ucode_ptr')) as fd:
|
||||||
TestFunctional._MakeInputFile('u-boot', fd.read())
|
TestFunctional._MakeInputFile('u-boot', fd.read())
|
||||||
|
|
||||||
with self.assertRaises(ValueError) as e:
|
with self.assertRaises(ValueError) as e:
|
||||||
self._RunPackUbootSingleMicrocode(False)
|
self._RunPackUbootSingleMicrocode()
|
||||||
self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot locate "
|
self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot locate "
|
||||||
"_dt_ucode_base_size symbol in u-boot", str(e.exception))
|
"_dt_ucode_base_size symbol in u-boot", str(e.exception))
|
||||||
|
|
||||||
|
23
tools/binman/test/45_prop_test.dts
Normal file
23
tools/binman/test/45_prop_test.dts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
|
||||||
|
binman {
|
||||||
|
sort-by-pos;
|
||||||
|
end-at-4gb;
|
||||||
|
size = <16>;
|
||||||
|
intel-me {
|
||||||
|
filename = "me.bin";
|
||||||
|
pos-unset;
|
||||||
|
intval = <3>;
|
||||||
|
intarray = <5 6>;
|
||||||
|
byteval = [08];
|
||||||
|
bytearray = [01 23 34];
|
||||||
|
longbytearray = [09 0a 0b 0c];
|
||||||
|
stringval = "message2";
|
||||||
|
stringarray = "another", "multi-word", "message";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
@ -17,7 +17,6 @@ our_path = os.path.dirname(os.path.realpath(__file__))
|
|||||||
sys.path.append(os.path.join(our_path, '../patman'))
|
sys.path.append(os.path.join(our_path, '../patman'))
|
||||||
|
|
||||||
import fdt
|
import fdt
|
||||||
import fdt_select
|
|
||||||
import fdt_util
|
import fdt_util
|
||||||
|
|
||||||
# When we see these properties we ignore them - i.e. do not create a structure member
|
# When we see these properties we ignore them - i.e. do not create a structure member
|
||||||
@ -170,7 +169,7 @@ class DtbPlatdata:
|
|||||||
Once this is done, self.fdt.GetRoot() can be called to obtain the
|
Once this is done, self.fdt.GetRoot() can be called to obtain the
|
||||||
device tree root node, and progress from there.
|
device tree root node, and progress from there.
|
||||||
"""
|
"""
|
||||||
self.fdt = fdt_select.FdtScan(self._dtb_fname)
|
self.fdt = fdt.FdtScan(self._dtb_fname)
|
||||||
|
|
||||||
def ScanNode(self, root):
|
def ScanNode(self, root):
|
||||||
for node in root.subnodes:
|
for node in root.subnodes:
|
||||||
|
@ -10,12 +10,15 @@ import struct
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
import fdt_util
|
import fdt_util
|
||||||
|
import libfdt
|
||||||
|
|
||||||
# This deals with a device tree, presenting it as an assortment of Node and
|
# This deals with a device tree, presenting it as an assortment of Node and
|
||||||
# Prop objects, representing nodes and properties, respectively. This file
|
# Prop objects, representing nodes and properties, respectively. This file
|
||||||
# contains the base classes and defines the high-level API. Most of the
|
# contains the base classes and defines the high-level API. You can use
|
||||||
# implementation is in the FdtFallback and FdtNormal subclasses. See
|
# FdtScan() as a convenience function to create and scan an Fdt.
|
||||||
# fdt_select.py for how to create an Fdt object.
|
|
||||||
|
# This implementation uses a libfdt Python library to access the device tree,
|
||||||
|
# so it is fairly efficient.
|
||||||
|
|
||||||
# A list of types we support
|
# A list of types we support
|
||||||
(TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL) = range(4)
|
(TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL) = range(4)
|
||||||
@ -25,7 +28,7 @@ def CheckErr(errnum, msg):
|
|||||||
raise ValueError('Error %d: %s: %s' %
|
raise ValueError('Error %d: %s: %s' %
|
||||||
(errnum, libfdt.fdt_strerror(errnum), msg))
|
(errnum, libfdt.fdt_strerror(errnum), msg))
|
||||||
|
|
||||||
class PropBase:
|
class Prop:
|
||||||
"""A device tree property
|
"""A device tree property
|
||||||
|
|
||||||
Properties:
|
Properties:
|
||||||
@ -34,11 +37,17 @@ class PropBase:
|
|||||||
bytes
|
bytes
|
||||||
type: Value type
|
type: Value type
|
||||||
"""
|
"""
|
||||||
def __init__(self, node, offset, name):
|
def __init__(self, node, offset, name, bytes):
|
||||||
self._node = node
|
self._node = node
|
||||||
self._offset = offset
|
self._offset = offset
|
||||||
self.name = name
|
self.name = name
|
||||||
self.value = None
|
self.value = None
|
||||||
|
self.bytes = str(bytes)
|
||||||
|
if not bytes:
|
||||||
|
self.type = TYPE_BOOL
|
||||||
|
self.value = True
|
||||||
|
return
|
||||||
|
self.type, self.value = self.BytesToValue(bytes)
|
||||||
|
|
||||||
def GetPhandle(self):
|
def GetPhandle(self):
|
||||||
"""Get a (single) phandle value from a property
|
"""Get a (single) phandle value from a property
|
||||||
@ -96,6 +105,7 @@ class PropBase:
|
|||||||
TYPE_INT: a byte-swapped integer stored as a 4-byte string
|
TYPE_INT: a byte-swapped integer stored as a 4-byte string
|
||||||
TYPE_BYTE: a byte stored as a single-byte string
|
TYPE_BYTE: a byte stored as a single-byte string
|
||||||
"""
|
"""
|
||||||
|
bytes = str(bytes)
|
||||||
size = len(bytes)
|
size = len(bytes)
|
||||||
strings = bytes.split('\0')
|
strings = bytes.split('\0')
|
||||||
is_string = True
|
is_string = True
|
||||||
@ -147,15 +157,12 @@ class PropBase:
|
|||||||
def GetOffset(self):
|
def GetOffset(self):
|
||||||
"""Get the offset of a property
|
"""Get the offset of a property
|
||||||
|
|
||||||
This can be implemented by subclasses.
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The offset of the property (struct fdt_property) within the
|
The offset of the property (struct fdt_property) within the file
|
||||||
file, or None if not known.
|
|
||||||
"""
|
"""
|
||||||
return None
|
return self._node._fdt.GetStructOffset(self._offset)
|
||||||
|
|
||||||
class NodeBase:
|
class Node:
|
||||||
"""A device tree node
|
"""A device tree node
|
||||||
|
|
||||||
Properties:
|
Properties:
|
||||||
@ -188,25 +195,65 @@ class NodeBase:
|
|||||||
return subnode
|
return subnode
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def Scan(self):
|
def Offset(self):
|
||||||
"""Scan the subnodes of a node
|
"""Returns the offset of a node, after checking the cache
|
||||||
|
|
||||||
This should be implemented by subclasses
|
This should be used instead of self._offset directly, to ensure that
|
||||||
|
the cache does not contain invalid offsets.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
self._fdt.CheckCache()
|
||||||
|
return self._offset
|
||||||
|
|
||||||
|
def Scan(self):
|
||||||
|
"""Scan a node's properties and subnodes
|
||||||
|
|
||||||
|
This fills in the props and subnodes properties, recursively
|
||||||
|
searching into subnodes so that the entire tree is built.
|
||||||
|
"""
|
||||||
|
self.props = self._fdt.GetProps(self)
|
||||||
|
|
||||||
|
offset = libfdt.fdt_first_subnode(self._fdt.GetFdt(), self.Offset())
|
||||||
|
while offset >= 0:
|
||||||
|
sep = '' if self.path[-1] == '/' else '/'
|
||||||
|
name = self._fdt._fdt_obj.get_name(offset)
|
||||||
|
path = self.path + sep + name
|
||||||
|
node = Node(self._fdt, offset, name, path)
|
||||||
|
self.subnodes.append(node)
|
||||||
|
|
||||||
|
node.Scan()
|
||||||
|
offset = libfdt.fdt_next_subnode(self._fdt.GetFdt(), offset)
|
||||||
|
|
||||||
|
def Refresh(self, my_offset):
|
||||||
|
"""Fix up the _offset for each node, recursively
|
||||||
|
|
||||||
|
Note: This does not take account of property offsets - these will not
|
||||||
|
be updated.
|
||||||
|
"""
|
||||||
|
if self._offset != my_offset:
|
||||||
|
#print '%s: %d -> %d\n' % (self.path, self._offset, my_offset)
|
||||||
|
self._offset = my_offset
|
||||||
|
offset = libfdt.fdt_first_subnode(self._fdt.GetFdt(), self._offset)
|
||||||
|
for subnode in self.subnodes:
|
||||||
|
subnode.Refresh(offset)
|
||||||
|
offset = libfdt.fdt_next_subnode(self._fdt.GetFdt(), offset)
|
||||||
|
|
||||||
def DeleteProp(self, prop_name):
|
def DeleteProp(self, prop_name):
|
||||||
"""Delete a property of a node
|
"""Delete a property of a node
|
||||||
|
|
||||||
This should be implemented by subclasses
|
The property is deleted and the offset cache is invalidated.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
prop_name: Name of the property to delete
|
prop_name: Name of the property to delete
|
||||||
|
Raises:
|
||||||
|
ValueError if the property does not exist
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
CheckErr(libfdt.fdt_delprop(self._fdt.GetFdt(), self.Offset(), prop_name),
|
||||||
|
"Node '%s': delete property: '%s'" % (self.path, prop_name))
|
||||||
|
del self.props[prop_name]
|
||||||
|
self._fdt.Invalidate()
|
||||||
|
|
||||||
class Fdt:
|
class Fdt:
|
||||||
"""Provides simple access to a flat device tree blob.
|
"""Provides simple access to a flat device tree blob using libfdts.
|
||||||
|
|
||||||
Properties:
|
Properties:
|
||||||
fname: Filename of fdt
|
fname: Filename of fdt
|
||||||
@ -214,6 +261,13 @@ class Fdt:
|
|||||||
"""
|
"""
|
||||||
def __init__(self, fname):
|
def __init__(self, fname):
|
||||||
self._fname = fname
|
self._fname = fname
|
||||||
|
self._cached_offsets = False
|
||||||
|
if self._fname:
|
||||||
|
self._fname = fdt_util.EnsureCompiled(self._fname)
|
||||||
|
|
||||||
|
with open(self._fname) as fd:
|
||||||
|
self._fdt = bytearray(fd.read())
|
||||||
|
self._fdt_obj = libfdt.Fdt(self._fdt)
|
||||||
|
|
||||||
def Scan(self, root='/'):
|
def Scan(self, root='/'):
|
||||||
"""Scan a device tree, building up a tree of Node objects
|
"""Scan a device tree, building up a tree of Node objects
|
||||||
@ -255,15 +309,100 @@ class Fdt:
|
|||||||
"""Flush device tree changes back to the file
|
"""Flush device tree changes back to the file
|
||||||
|
|
||||||
If the device tree has changed in memory, write it back to the file.
|
If the device tree has changed in memory, write it back to the file.
|
||||||
Subclasses can implement this if needed.
|
|
||||||
"""
|
"""
|
||||||
pass
|
with open(self._fname, 'wb') as fd:
|
||||||
|
fd.write(self._fdt)
|
||||||
|
|
||||||
def Pack(self):
|
def Pack(self):
|
||||||
"""Pack the device tree down to its minimum size
|
"""Pack the device tree down to its minimum size
|
||||||
|
|
||||||
When nodes and properties shrink or are deleted, wasted space can
|
When nodes and properties shrink or are deleted, wasted space can
|
||||||
build up in the device tree binary. Subclasses can implement this
|
build up in the device tree binary.
|
||||||
to remove that spare space.
|
|
||||||
"""
|
"""
|
||||||
pass
|
CheckErr(libfdt.fdt_pack(self._fdt), 'pack')
|
||||||
|
fdt_len = libfdt.fdt_totalsize(self._fdt)
|
||||||
|
del self._fdt[fdt_len:]
|
||||||
|
|
||||||
|
def GetFdt(self):
|
||||||
|
"""Get the contents of the FDT
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The FDT contents as a string of bytes
|
||||||
|
"""
|
||||||
|
return self._fdt
|
||||||
|
|
||||||
|
def CheckErr(errnum, msg):
|
||||||
|
if errnum:
|
||||||
|
raise ValueError('Error %d: %s: %s' %
|
||||||
|
(errnum, libfdt.fdt_strerror(errnum), msg))
|
||||||
|
|
||||||
|
|
||||||
|
def GetProps(self, node):
|
||||||
|
"""Get all properties from a node.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
node: Full path to node name to look in.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A dictionary containing all the properties, indexed by node name.
|
||||||
|
The entries are Prop objects.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: if the node does not exist.
|
||||||
|
"""
|
||||||
|
props_dict = {}
|
||||||
|
poffset = libfdt.fdt_first_property_offset(self._fdt, node._offset)
|
||||||
|
while poffset >= 0:
|
||||||
|
p = self._fdt_obj.get_property_by_offset(poffset)
|
||||||
|
prop = Prop(node, poffset, p.name, p.value)
|
||||||
|
props_dict[prop.name] = prop
|
||||||
|
|
||||||
|
poffset = libfdt.fdt_next_property_offset(self._fdt, poffset)
|
||||||
|
return props_dict
|
||||||
|
|
||||||
|
def Invalidate(self):
|
||||||
|
"""Mark our offset cache as invalid"""
|
||||||
|
self._cached_offsets = False
|
||||||
|
|
||||||
|
def CheckCache(self):
|
||||||
|
"""Refresh the offset cache if needed"""
|
||||||
|
if self._cached_offsets:
|
||||||
|
return
|
||||||
|
self.Refresh()
|
||||||
|
self._cached_offsets = True
|
||||||
|
|
||||||
|
def Refresh(self):
|
||||||
|
"""Refresh the offset cache"""
|
||||||
|
self._root.Refresh(0)
|
||||||
|
|
||||||
|
def GetStructOffset(self, offset):
|
||||||
|
"""Get the file offset of a given struct offset
|
||||||
|
|
||||||
|
Args:
|
||||||
|
offset: Offset within the 'struct' region of the device tree
|
||||||
|
Returns:
|
||||||
|
Position of @offset within the device tree binary
|
||||||
|
"""
|
||||||
|
return libfdt.fdt_off_dt_struct(self._fdt) + offset
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def Node(self, fdt, offset, name, path):
|
||||||
|
"""Create a new node
|
||||||
|
|
||||||
|
This is used by Fdt.Scan() to create a new node using the correct
|
||||||
|
class.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
fdt: Fdt object
|
||||||
|
offset: Offset of node
|
||||||
|
name: Node name
|
||||||
|
path: Full path to node
|
||||||
|
"""
|
||||||
|
node = Node(fdt, offset, name, path)
|
||||||
|
return node
|
||||||
|
|
||||||
|
def FdtScan(fname):
|
||||||
|
"""Returns a new Fdt object from the implementation we are using"""
|
||||||
|
dtb = Fdt(fname)
|
||||||
|
dtb.Scan()
|
||||||
|
return dtb
|
||||||
|
@ -1,181 +0,0 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
#
|
|
||||||
# Copyright (C) 2016 Google, Inc
|
|
||||||
# Written by Simon Glass <sjg@chromium.org>
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: GPL-2.0+
|
|
||||||
#
|
|
||||||
|
|
||||||
import command
|
|
||||||
import fdt
|
|
||||||
from fdt import Fdt, NodeBase, PropBase
|
|
||||||
import fdt_util
|
|
||||||
import sys
|
|
||||||
|
|
||||||
# This deals with a device tree, presenting it as a list of Node and Prop
|
|
||||||
# objects, representing nodes and properties, respectively.
|
|
||||||
#
|
|
||||||
# This implementation uses the fdtget tool to access the device tree, so it
|
|
||||||
# is not very efficient for larger trees. The tool is called once for each
|
|
||||||
# node and property in the tree.
|
|
||||||
|
|
||||||
class Prop(PropBase):
|
|
||||||
"""A device tree property
|
|
||||||
|
|
||||||
Properties:
|
|
||||||
name: Property name (as per the device tree)
|
|
||||||
value: Property value as a string of bytes, or a list of strings of
|
|
||||||
bytes
|
|
||||||
type: Value type
|
|
||||||
"""
|
|
||||||
def __init__(self, node, name, byte_list_str):
|
|
||||||
PropBase.__init__(self, node, 0, name)
|
|
||||||
if not byte_list_str.strip():
|
|
||||||
self.type = fdt.TYPE_BOOL
|
|
||||||
return
|
|
||||||
self.bytes = [chr(int(byte, 16))
|
|
||||||
for byte in byte_list_str.strip().split(' ')]
|
|
||||||
self.type, self.value = self.BytesToValue(''.join(self.bytes))
|
|
||||||
|
|
||||||
|
|
||||||
class Node(NodeBase):
|
|
||||||
"""A device tree node
|
|
||||||
|
|
||||||
Properties:
|
|
||||||
name: Device tree node tname
|
|
||||||
path: Full path to node, along with the node name itself
|
|
||||||
_fdt: Device tree object
|
|
||||||
subnodes: A list of subnodes for this node, each a Node object
|
|
||||||
props: A dict of properties for this node, each a Prop object.
|
|
||||||
Keyed by property name
|
|
||||||
"""
|
|
||||||
def __init__(self, fdt, offset, name, path):
|
|
||||||
NodeBase.__init__(self, fdt, offset, name, path)
|
|
||||||
|
|
||||||
def Scan(self):
|
|
||||||
"""Scan a node's properties and subnodes
|
|
||||||
|
|
||||||
This fills in the props and subnodes properties, recursively
|
|
||||||
searching into subnodes so that the entire tree is built.
|
|
||||||
"""
|
|
||||||
for name, byte_list_str in self._fdt.GetProps(self.path).items():
|
|
||||||
prop = Prop(self, name, byte_list_str)
|
|
||||||
self.props[name] = prop
|
|
||||||
|
|
||||||
for name in self._fdt.GetSubNodes(self.path):
|
|
||||||
sep = '' if self.path[-1] == '/' else '/'
|
|
||||||
path = self.path + sep + name
|
|
||||||
node = Node(self._fdt, 0, name, path)
|
|
||||||
self.subnodes.append(node)
|
|
||||||
|
|
||||||
node.Scan()
|
|
||||||
|
|
||||||
def DeleteProp(self, prop_name):
|
|
||||||
"""Delete a property of a node
|
|
||||||
|
|
||||||
The property is deleted using fdtput.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
prop_name: Name of the property to delete
|
|
||||||
Raises:
|
|
||||||
CommandError if the property does not exist
|
|
||||||
"""
|
|
||||||
args = [self._fdt._fname, '-d', self.path, prop_name]
|
|
||||||
command.Output('fdtput', *args)
|
|
||||||
del self.props[prop_name]
|
|
||||||
|
|
||||||
class FdtFallback(Fdt):
|
|
||||||
"""Provides simple access to a flat device tree blob using fdtget/fdtput
|
|
||||||
|
|
||||||
Properties:
|
|
||||||
See superclass
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, fname):
|
|
||||||
Fdt.__init__(self, fname)
|
|
||||||
if self._fname:
|
|
||||||
self._fname = fdt_util.EnsureCompiled(self._fname)
|
|
||||||
|
|
||||||
def GetSubNodes(self, node):
|
|
||||||
"""Returns a list of sub-nodes of a given node
|
|
||||||
|
|
||||||
Args:
|
|
||||||
node: Node name to return children from
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
List of children in the node (each a string node name)
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
CmdError: if the node does not exist.
|
|
||||||
"""
|
|
||||||
out = command.Output('fdtget', self._fname, '-l', node)
|
|
||||||
return out.strip().splitlines()
|
|
||||||
|
|
||||||
def GetProps(self, node):
|
|
||||||
"""Get all properties from a node
|
|
||||||
|
|
||||||
Args:
|
|
||||||
node: full path to node name to look in
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
A dictionary containing all the properties, indexed by node name.
|
|
||||||
The entries are simply strings - no decoding of lists or numbers
|
|
||||||
is done.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
CmdError: if the node does not exist.
|
|
||||||
"""
|
|
||||||
out = command.Output('fdtget', self._fname, node, '-p')
|
|
||||||
props = out.strip().splitlines()
|
|
||||||
props_dict = {}
|
|
||||||
for prop in props:
|
|
||||||
name = prop
|
|
||||||
props_dict[prop] = self.GetProp(node, name)
|
|
||||||
return props_dict
|
|
||||||
|
|
||||||
def GetProp(self, node, prop, default=None, typespec=None):
|
|
||||||
"""Get a property from a device tree.
|
|
||||||
|
|
||||||
This looks up the given node and property, and returns the value as a
|
|
||||||
string,
|
|
||||||
|
|
||||||
If the node or property does not exist, this will return the default
|
|
||||||
value.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
node: Full path to node to look up.
|
|
||||||
prop: Property name to look up.
|
|
||||||
default: Default value to return if nothing is present in the fdt,
|
|
||||||
or None to raise in this case. This will be converted to a
|
|
||||||
string.
|
|
||||||
typespec: Type character to use (None for default, 's' for string)
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
string containing the property value.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
CmdError: if the property does not exist and no default is provided.
|
|
||||||
"""
|
|
||||||
args = [self._fname, node, prop, '-t', 'bx']
|
|
||||||
if default is not None:
|
|
||||||
args += ['-d', str(default)]
|
|
||||||
if typespec is not None:
|
|
||||||
args += ['-t', typespec]
|
|
||||||
out = command.Output('fdtget', *args)
|
|
||||||
return out.strip()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def Node(self, fdt, offset, name, path):
|
|
||||||
"""Create a new node
|
|
||||||
|
|
||||||
This is used by Fdt.Scan() to create a new node using the correct
|
|
||||||
class.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
fdt: Fdt object
|
|
||||||
offset: Offset of node
|
|
||||||
name: Node name
|
|
||||||
path: Full path to node
|
|
||||||
"""
|
|
||||||
node = Node(fdt, offset, name, path)
|
|
||||||
return node
|
|
@ -1,225 +0,0 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
#
|
|
||||||
# Copyright (C) 2016 Google, Inc
|
|
||||||
# Written by Simon Glass <sjg@chromium.org>
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: GPL-2.0+
|
|
||||||
#
|
|
||||||
|
|
||||||
import struct
|
|
||||||
import sys
|
|
||||||
|
|
||||||
import fdt
|
|
||||||
from fdt import Fdt, NodeBase, PropBase
|
|
||||||
import fdt_util
|
|
||||||
import libfdt
|
|
||||||
|
|
||||||
# This deals with a device tree, presenting it as a list of Node and Prop
|
|
||||||
# objects, representing nodes and properties, respectively.
|
|
||||||
#
|
|
||||||
# This implementation uses a libfdt Python library to access the device tree,
|
|
||||||
# so it is fairly efficient.
|
|
||||||
|
|
||||||
def CheckErr(errnum, msg):
|
|
||||||
if errnum:
|
|
||||||
raise ValueError('Error %d: %s: %s' %
|
|
||||||
(errnum, libfdt.fdt_strerror(errnum), msg))
|
|
||||||
|
|
||||||
class Prop(PropBase):
|
|
||||||
"""A device tree property
|
|
||||||
|
|
||||||
Properties:
|
|
||||||
name: Property name (as per the device tree)
|
|
||||||
value: Property value as a string of bytes, or a list of strings of
|
|
||||||
bytes
|
|
||||||
type: Value type
|
|
||||||
"""
|
|
||||||
def __init__(self, node, offset, name, bytes):
|
|
||||||
PropBase.__init__(self, node, offset, name)
|
|
||||||
self.bytes = bytes
|
|
||||||
if not bytes:
|
|
||||||
self.type = fdt.TYPE_BOOL
|
|
||||||
self.value = True
|
|
||||||
return
|
|
||||||
self.type, self.value = self.BytesToValue(bytes)
|
|
||||||
|
|
||||||
def GetOffset(self):
|
|
||||||
"""Get the offset of a property
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The offset of the property (struct fdt_property) within the file
|
|
||||||
"""
|
|
||||||
return self._node._fdt.GetStructOffset(self._offset)
|
|
||||||
|
|
||||||
class Node(NodeBase):
|
|
||||||
"""A device tree node
|
|
||||||
|
|
||||||
Properties:
|
|
||||||
offset: Integer offset in the device tree
|
|
||||||
name: Device tree node tname
|
|
||||||
path: Full path to node, along with the node name itself
|
|
||||||
_fdt: Device tree object
|
|
||||||
subnodes: A list of subnodes for this node, each a Node object
|
|
||||||
props: A dict of properties for this node, each a Prop object.
|
|
||||||
Keyed by property name
|
|
||||||
"""
|
|
||||||
def __init__(self, fdt, offset, name, path):
|
|
||||||
NodeBase.__init__(self, fdt, offset, name, path)
|
|
||||||
|
|
||||||
def Offset(self):
|
|
||||||
"""Returns the offset of a node, after checking the cache
|
|
||||||
|
|
||||||
This should be used instead of self._offset directly, to ensure that
|
|
||||||
the cache does not contain invalid offsets.
|
|
||||||
"""
|
|
||||||
self._fdt.CheckCache()
|
|
||||||
return self._offset
|
|
||||||
|
|
||||||
def Scan(self):
|
|
||||||
"""Scan a node's properties and subnodes
|
|
||||||
|
|
||||||
This fills in the props and subnodes properties, recursively
|
|
||||||
searching into subnodes so that the entire tree is built.
|
|
||||||
"""
|
|
||||||
self.props = self._fdt.GetProps(self)
|
|
||||||
|
|
||||||
offset = libfdt.fdt_first_subnode(self._fdt.GetFdt(), self.Offset())
|
|
||||||
while offset >= 0:
|
|
||||||
sep = '' if self.path[-1] == '/' else '/'
|
|
||||||
name = libfdt.Name(self._fdt.GetFdt(), offset)
|
|
||||||
path = self.path + sep + name
|
|
||||||
node = Node(self._fdt, offset, name, path)
|
|
||||||
self.subnodes.append(node)
|
|
||||||
|
|
||||||
node.Scan()
|
|
||||||
offset = libfdt.fdt_next_subnode(self._fdt.GetFdt(), offset)
|
|
||||||
|
|
||||||
def Refresh(self, my_offset):
|
|
||||||
"""Fix up the _offset for each node, recursively
|
|
||||||
|
|
||||||
Note: This does not take account of property offsets - these will not
|
|
||||||
be updated.
|
|
||||||
"""
|
|
||||||
if self._offset != my_offset:
|
|
||||||
#print '%s: %d -> %d\n' % (self.path, self._offset, my_offset)
|
|
||||||
self._offset = my_offset
|
|
||||||
offset = libfdt.fdt_first_subnode(self._fdt.GetFdt(), self._offset)
|
|
||||||
for subnode in self.subnodes:
|
|
||||||
subnode.Refresh(offset)
|
|
||||||
offset = libfdt.fdt_next_subnode(self._fdt.GetFdt(), offset)
|
|
||||||
|
|
||||||
def DeleteProp(self, prop_name):
|
|
||||||
"""Delete a property of a node
|
|
||||||
|
|
||||||
The property is deleted and the offset cache is invalidated.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
prop_name: Name of the property to delete
|
|
||||||
Raises:
|
|
||||||
ValueError if the property does not exist
|
|
||||||
"""
|
|
||||||
CheckErr(libfdt.fdt_delprop(self._fdt.GetFdt(), self.Offset(), prop_name),
|
|
||||||
"Node '%s': delete property: '%s'" % (self.path, prop_name))
|
|
||||||
del self.props[prop_name]
|
|
||||||
self._fdt.Invalidate()
|
|
||||||
|
|
||||||
class FdtNormal(Fdt):
|
|
||||||
"""Provides simple access to a flat device tree blob using libfdt.
|
|
||||||
|
|
||||||
Properties:
|
|
||||||
_fdt: Device tree contents (bytearray)
|
|
||||||
_cached_offsets: True if all the nodes have a valid _offset property,
|
|
||||||
False if something has changed to invalidate the offsets
|
|
||||||
"""
|
|
||||||
def __init__(self, fname):
|
|
||||||
Fdt.__init__(self, fname)
|
|
||||||
self._cached_offsets = False
|
|
||||||
if self._fname:
|
|
||||||
self._fname = fdt_util.EnsureCompiled(self._fname)
|
|
||||||
|
|
||||||
with open(self._fname) as fd:
|
|
||||||
self._fdt = bytearray(fd.read())
|
|
||||||
|
|
||||||
def GetFdt(self):
|
|
||||||
"""Get the contents of the FDT
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The FDT contents as a string of bytes
|
|
||||||
"""
|
|
||||||
return self._fdt
|
|
||||||
|
|
||||||
def Flush(self):
|
|
||||||
"""Flush device tree changes back to the file"""
|
|
||||||
with open(self._fname, 'wb') as fd:
|
|
||||||
fd.write(self._fdt)
|
|
||||||
|
|
||||||
def Pack(self):
|
|
||||||
"""Pack the device tree down to its minimum size"""
|
|
||||||
CheckErr(libfdt.fdt_pack(self._fdt), 'pack')
|
|
||||||
fdt_len = libfdt.fdt_totalsize(self._fdt)
|
|
||||||
del self._fdt[fdt_len:]
|
|
||||||
|
|
||||||
def GetProps(self, node):
|
|
||||||
"""Get all properties from a node.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
node: Full path to node name to look in.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
A dictionary containing all the properties, indexed by node name.
|
|
||||||
The entries are Prop objects.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
ValueError: if the node does not exist.
|
|
||||||
"""
|
|
||||||
props_dict = {}
|
|
||||||
poffset = libfdt.fdt_first_property_offset(self._fdt, node._offset)
|
|
||||||
while poffset >= 0:
|
|
||||||
dprop, plen = libfdt.fdt_get_property_by_offset(self._fdt, poffset)
|
|
||||||
prop = Prop(node, poffset, libfdt.String(self._fdt, dprop.nameoff),
|
|
||||||
libfdt.Data(dprop))
|
|
||||||
props_dict[prop.name] = prop
|
|
||||||
|
|
||||||
poffset = libfdt.fdt_next_property_offset(self._fdt, poffset)
|
|
||||||
return props_dict
|
|
||||||
|
|
||||||
def Invalidate(self):
|
|
||||||
"""Mark our offset cache as invalid"""
|
|
||||||
self._cached_offsets = False
|
|
||||||
|
|
||||||
def CheckCache(self):
|
|
||||||
"""Refresh the offset cache if needed"""
|
|
||||||
if self._cached_offsets:
|
|
||||||
return
|
|
||||||
self.Refresh()
|
|
||||||
self._cached_offsets = True
|
|
||||||
|
|
||||||
def Refresh(self):
|
|
||||||
"""Refresh the offset cache"""
|
|
||||||
self._root.Refresh(0)
|
|
||||||
|
|
||||||
def GetStructOffset(self, offset):
|
|
||||||
"""Get the file offset of a given struct offset
|
|
||||||
|
|
||||||
Args:
|
|
||||||
offset: Offset within the 'struct' region of the device tree
|
|
||||||
Returns:
|
|
||||||
Position of @offset within the device tree binary
|
|
||||||
"""
|
|
||||||
return libfdt.fdt_off_dt_struct(self._fdt) + offset
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def Node(self, fdt, offset, name, path):
|
|
||||||
"""Create a new node
|
|
||||||
|
|
||||||
This is used by Fdt.Scan() to create a new node using the correct
|
|
||||||
class.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
fdt: Fdt object
|
|
||||||
offset: Offset of node
|
|
||||||
name: Node name
|
|
||||||
path: Full path to node
|
|
||||||
"""
|
|
||||||
node = Node(fdt, offset, name, path)
|
|
||||||
return node
|
|
@ -1,36 +0,0 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
#
|
|
||||||
# Copyright (C) 2016 Google, Inc
|
|
||||||
# Written by Simon Glass <sjg@chromium.org>
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: GPL-2.0+
|
|
||||||
#
|
|
||||||
|
|
||||||
import fdt_fallback
|
|
||||||
|
|
||||||
# Bring in either the normal fdt library (which relies on libfdt) or the
|
|
||||||
# fallback one (which uses fdtget and is slower). Both provide the same
|
|
||||||
# interface for this file to use.
|
|
||||||
try:
|
|
||||||
import fdt_normal
|
|
||||||
have_libfdt = True
|
|
||||||
except ImportError:
|
|
||||||
have_libfdt = False
|
|
||||||
|
|
||||||
force_fallback = False
|
|
||||||
|
|
||||||
def FdtScan(fname, _force_fallback=False):
|
|
||||||
"""Returns a new Fdt object from the implementation we are using"""
|
|
||||||
if have_libfdt and not force_fallback and not _force_fallback:
|
|
||||||
dtb = fdt_normal.FdtNormal(fname)
|
|
||||||
else:
|
|
||||||
dtb = fdt_fallback.FdtFallback(fname)
|
|
||||||
dtb.Scan()
|
|
||||||
return dtb
|
|
||||||
|
|
||||||
def UseFallback(fallback):
|
|
||||||
global force_fallback
|
|
||||||
|
|
||||||
old_val = force_fallback
|
|
||||||
force_fallback = fallback
|
|
||||||
return old_val
|
|
Loading…
Reference in New Issue
Block a user