DeviceTree updates for 4.17:
- Sync dtc to upstream version v1.4.6-9-gaadd0b65c987. This adds a bunch more warnings (hidden behind W=1). - Build dtc lexer and parser files instead of using shipped versions. - Rework overlay apply API to take an FDT as input and apply overlays in a single step. - Add a phandle lookup cache. This improves boot time by hundreds of msec on systems with large DT. - Add trivial mcp4017/18/19 potentiometers bindings. - Remove VLA stack usage in DT code. -----BEGIN PGP SIGNATURE----- iQItBAABCAAXBQJaxiUdEBxyb2JoQGtlcm5lbC5vcmcACgkQ+vtdtY28YcM0+w/+ L7nkug1Hz2476eRrsn5bm6oOO0vCrhQcDTJ/AlvU1YO8XBVgGEetLDs8drmvD0/O FQDcpumX6G0eFoHTnTNWD7keM+0nY5jZBIAqKQNa9a0HKkjYc4HO5Ot9E02XG8W8 759vvCcGeJpysoCls9u8OplzqiDyNVQJd1a0fLivtafdKypuE/Ywh15wrzckPO+F bxqWQd+uwm98ZVz8/o3vfYtAOJmA06A+hsyVLXYu7iKQcXYVxi+ZNbRV44MQ50NI 1w5m8GgtWe4A2lpXjmeXk1VmLPO3eEgQKnBoH7gcJmCHaVg/SVfMgBscuGSQZRQa rQvaYRUNGJ0Mtji8EZpZb5Vip4ZCDtZCQBB3snN24CvGXI6WuIIg/8ncXt0AfLqn pxFmC32ZcwvJR2NCpPVfTgILm6foT9IzJWKl6SQLVtqqVp9nPFua7T3l8AQak7FB 2MMaaqh7L0l0za0ZgArZZo/IWUHRb0MwZdXAkqBZlQ6f3IBqGQeKCnkclAeH8qYr OorCOmC2OlKXLPHoz8XHeBzPRdnv1dQ//gEkKXBJ2igLU03hRWv9dxnGju/45sun Ifo79uBAUc9s3F4Kjd/zs2iLztuPrYCSICHtJh9LPeOxoV1ZUNt+6Cm23yQ014Uo /GsFW+lzh7c9wB1eETjPHd1WuYXiSrmE4zvbdykyLCk= =ZWpa -----END PGP SIGNATURE----- Merge tag 'devicetree-for-4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux Pull DeviceTree updates from Rob Herring: - Sync dtc to upstream version v1.4.6-9-gaadd0b65c987. This adds a bunch more warnings (hidden behind W=1). - Build dtc lexer and parser files instead of using shipped versions. - Rework overlay apply API to take an FDT as input and apply overlays in a single step. - Add a phandle lookup cache. This improves boot time by hundreds of msec on systems with large DT. - Add trivial mcp4017/18/19 potentiometers bindings. - Remove VLA stack usage in DT code. * tag 'devicetree-for-4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux: (26 commits) of: unittest: fix an error code in of_unittest_apply_overlay() of: unittest: move misplaced function declaration of: unittest: Remove VLA stack usage of: overlay: Fix forgotten reference to of_overlay_apply() of: Documentation: Fix forgotten reference to of_overlay_apply() of: unittest: local return value variable related cleanups of: unittest: remove unneeded local return value variables dt-bindings: trivial: add various mcp4017/18/19 potentiometers of: unittest: fix an error test in of_unittest_overlay_8() of: cache phandle nodes to reduce cost of of_find_node_by_phandle() dt-bindings: rockchip-dw-mshc: use consistent clock names MAINTAINERS: Add linux/of_*.h headers to appropriate subsystems scripts: turn off some new dtc warnings by default scripts/dtc: Update to upstream version v1.4.6-9-gaadd0b65c987 scripts/dtc: generate lexer and parser during build instead of shipping powerpc: boot: add strrchr function of: overlay: do not include path in full_name of added nodes of: unittest: clean up changeset test arm64/efi: Make strrchr() available to the EFI namespace ARM: boot: add strrchr function ...
This commit is contained in:
commit
9c2dd8405c
45 changed files with 1213 additions and 5169 deletions
|
@ -21,7 +21,7 @@ Required Properties:
|
||||||
- "rockchip,rk3399-dw-mshc", "rockchip,rk3288-dw-mshc": for Rockchip RK3399
|
- "rockchip,rk3399-dw-mshc", "rockchip,rk3288-dw-mshc": for Rockchip RK3399
|
||||||
|
|
||||||
Optional Properties:
|
Optional Properties:
|
||||||
* clocks: from common clock binding: if ciu_drive and ciu_sample are
|
* clocks: from common clock binding: if ciu-drive and ciu-sample are
|
||||||
specified in clock-names, should contain handles to these clocks.
|
specified in clock-names, should contain handles to these clocks.
|
||||||
|
|
||||||
* clock-names: Apart from the clock-names described in synopsys-dw-mshc.txt
|
* clock-names: Apart from the clock-names described in synopsys-dw-mshc.txt
|
||||||
|
@ -29,7 +29,7 @@ Optional Properties:
|
||||||
to control the clock phases, "ciu-sample" is required for tuning high-
|
to control the clock phases, "ciu-sample" is required for tuning high-
|
||||||
speed modes.
|
speed modes.
|
||||||
|
|
||||||
* rockchip,default-sample-phase: The default phase to set ciu_sample at
|
* rockchip,default-sample-phase: The default phase to set ciu-sample at
|
||||||
probing, low speeds or in case where all phases work at tuning time.
|
probing, low speeds or in case where all phases work at tuning time.
|
||||||
If not specified 0 deg will be used.
|
If not specified 0 deg will be used.
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,18 @@ maxim,max6621 PECI-to-I2C translator for PECI-to-SMBus/I2C protocol conversion
|
||||||
maxim,max6625 9-Bit/12-Bit Temperature Sensors with I²C-Compatible Serial Interface
|
maxim,max6625 9-Bit/12-Bit Temperature Sensors with I²C-Compatible Serial Interface
|
||||||
mcube,mc3230 mCube 3-axis 8-bit digital accelerometer
|
mcube,mc3230 mCube 3-axis 8-bit digital accelerometer
|
||||||
memsic,mxc6225 MEMSIC 2-axis 8-bit digital accelerometer
|
memsic,mxc6225 MEMSIC 2-axis 8-bit digital accelerometer
|
||||||
|
microchip,mcp4017-502 Microchip 7-bit Single I2C Digital POT (5k)
|
||||||
|
microchip,mcp4017-103 Microchip 7-bit Single I2C Digital POT (10k)
|
||||||
|
microchip,mcp4017-503 Microchip 7-bit Single I2C Digital POT (50k)
|
||||||
|
microchip,mcp4017-104 Microchip 7-bit Single I2C Digital POT (100k)
|
||||||
|
microchip,mcp4018-502 Microchip 7-bit Single I2C Digital POT (5k)
|
||||||
|
microchip,mcp4018-103 Microchip 7-bit Single I2C Digital POT (10k)
|
||||||
|
microchip,mcp4018-503 Microchip 7-bit Single I2C Digital POT (50k)
|
||||||
|
microchip,mcp4018-104 Microchip 7-bit Single I2C Digital POT (100k)
|
||||||
|
microchip,mcp4019-502 Microchip 7-bit Single I2C Digital POT (5k)
|
||||||
|
microchip,mcp4019-103 Microchip 7-bit Single I2C Digital POT (10k)
|
||||||
|
microchip,mcp4019-503 Microchip 7-bit Single I2C Digital POT (50k)
|
||||||
|
microchip,mcp4019-104 Microchip 7-bit Single I2C Digital POT (100k)
|
||||||
microchip,mcp4531-502 Microchip 7-bit Single I2C Digital Potentiometer (5k)
|
microchip,mcp4531-502 Microchip 7-bit Single I2C Digital Potentiometer (5k)
|
||||||
microchip,mcp4531-103 Microchip 7-bit Single I2C Digital Potentiometer (10k)
|
microchip,mcp4531-103 Microchip 7-bit Single I2C Digital Potentiometer (10k)
|
||||||
microchip,mcp4531-503 Microchip 7-bit Single I2C Digital Potentiometer (50k)
|
microchip,mcp4531-503 Microchip 7-bit Single I2C Digital Potentiometer (50k)
|
||||||
|
|
|
@ -91,8 +91,8 @@ The API is quite easy to use.
|
||||||
return value is an error or a cookie identifying this overlay.
|
return value is an error or a cookie identifying this overlay.
|
||||||
|
|
||||||
2. Call of_overlay_remove() to remove and cleanup the overlay changeset
|
2. Call of_overlay_remove() to remove and cleanup the overlay changeset
|
||||||
previously created via the call to of_overlay_apply(). Removal of an overlay
|
previously created via the call to of_overlay_fdt_apply(). Removal of an
|
||||||
changeset that is stacked by another will not be permitted.
|
overlay changeset that is stacked by another will not be permitted.
|
||||||
|
|
||||||
Finally, if you need to remove all overlays in one-go, just call
|
Finally, if you need to remove all overlays in one-go, just call
|
||||||
of_overlay_remove_all() which will remove every single one in the correct
|
of_overlay_remove_all() which will remove every single one in the correct
|
||||||
|
|
|
@ -4287,6 +4287,7 @@ Q: https://patchwork.kernel.org/project/linux-dmaengine/list/
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: drivers/dma/
|
F: drivers/dma/
|
||||||
F: include/linux/dmaengine.h
|
F: include/linux/dmaengine.h
|
||||||
|
F: include/linux/of_dma.h
|
||||||
F: Documentation/devicetree/bindings/dma/
|
F: Documentation/devicetree/bindings/dma/
|
||||||
F: Documentation/driver-api/dmaengine/
|
F: Documentation/driver-api/dmaengine/
|
||||||
T: git git://git.infradead.org/users/vkoul/slave-dma.git
|
T: git git://git.infradead.org/users/vkoul/slave-dma.git
|
||||||
|
@ -5986,6 +5987,7 @@ F: Documentation/ABI/obsolete/sysfs-gpio
|
||||||
F: drivers/gpio/
|
F: drivers/gpio/
|
||||||
F: include/linux/gpio/
|
F: include/linux/gpio/
|
||||||
F: include/linux/gpio.h
|
F: include/linux/gpio.h
|
||||||
|
F: include/linux/of_gpio.h
|
||||||
F: include/asm-generic/gpio.h
|
F: include/asm-generic/gpio.h
|
||||||
F: include/uapi/linux/gpio.h
|
F: include/uapi/linux/gpio.h
|
||||||
F: tools/gpio/
|
F: tools/gpio/
|
||||||
|
@ -7295,6 +7297,7 @@ S: Maintained
|
||||||
F: Documentation/devicetree/bindings/iommu/
|
F: Documentation/devicetree/bindings/iommu/
|
||||||
F: drivers/iommu/
|
F: drivers/iommu/
|
||||||
F: include/linux/iommu.h
|
F: include/linux/iommu.h
|
||||||
|
F: include/linux/of_iommu.h
|
||||||
F: include/linux/iova.h
|
F: include/linux/iova.h
|
||||||
|
|
||||||
IP MASQUERADING
|
IP MASQUERADING
|
||||||
|
@ -10785,6 +10788,7 @@ F: drivers/acpi/pci*
|
||||||
F: drivers/pci/
|
F: drivers/pci/
|
||||||
F: include/asm-generic/pci*
|
F: include/asm-generic/pci*
|
||||||
F: include/linux/pci*
|
F: include/linux/pci*
|
||||||
|
F: include/linux/of_pci.h
|
||||||
F: include/uapi/linux/pci*
|
F: include/uapi/linux/pci*
|
||||||
F: lib/pci*
|
F: lib/pci*
|
||||||
F: arch/x86/pci/
|
F: arch/x86/pci/
|
||||||
|
|
|
@ -121,6 +121,16 @@ char *strchr(const char *s, int c)
|
||||||
return (char *)s;
|
return (char *)s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *strrchr(const char *s, int c)
|
||||||
|
{
|
||||||
|
const char *last = NULL;
|
||||||
|
do {
|
||||||
|
if (*s == (char)c)
|
||||||
|
last = s;
|
||||||
|
} while (*s++);
|
||||||
|
return (char *)last;
|
||||||
|
}
|
||||||
|
|
||||||
#undef memset
|
#undef memset
|
||||||
|
|
||||||
void *memset(void *s, int c, size_t count)
|
void *memset(void *s, int c, size_t count)
|
||||||
|
|
|
@ -103,6 +103,7 @@ __efistub_strlen = KALLSYMS_HIDE(__pi_strlen);
|
||||||
__efistub_strnlen = KALLSYMS_HIDE(__pi_strnlen);
|
__efistub_strnlen = KALLSYMS_HIDE(__pi_strnlen);
|
||||||
__efistub_strcmp = KALLSYMS_HIDE(__pi_strcmp);
|
__efistub_strcmp = KALLSYMS_HIDE(__pi_strcmp);
|
||||||
__efistub_strncmp = KALLSYMS_HIDE(__pi_strncmp);
|
__efistub_strncmp = KALLSYMS_HIDE(__pi_strncmp);
|
||||||
|
__efistub_strrchr = KALLSYMS_HIDE(__pi_strrchr);
|
||||||
__efistub___flush_dcache_area = KALLSYMS_HIDE(__pi___flush_dcache_area);
|
__efistub___flush_dcache_area = KALLSYMS_HIDE(__pi___flush_dcache_area);
|
||||||
|
|
||||||
#ifdef CONFIG_KASAN
|
#ifdef CONFIG_KASAN
|
||||||
|
|
|
@ -40,4 +40,4 @@ ENTRY(strrchr)
|
||||||
b 1b
|
b 1b
|
||||||
2: mov x0, x3
|
2: mov x0, x3
|
||||||
ret
|
ret
|
||||||
ENDPROC(strrchr)
|
ENDPIPROC(strrchr)
|
||||||
|
|
|
@ -21,6 +21,16 @@ size_t strnlen(const char * s, size_t count)
|
||||||
return sc - s;
|
return sc - s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *strrchr(const char *s, int c)
|
||||||
|
{
|
||||||
|
const char *last = NULL;
|
||||||
|
do {
|
||||||
|
if (*s == (char)c)
|
||||||
|
last = s;
|
||||||
|
} while (*s++);
|
||||||
|
return (char *)last;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __powerpc64__
|
#ifdef __powerpc64__
|
||||||
|
|
||||||
# define do_div(n, base) ({ \
|
# define do_div(n, base) ({ \
|
||||||
|
|
|
@ -7,6 +7,7 @@ extern char *strcpy(char *dest, const char *src);
|
||||||
extern char *strncpy(char *dest, const char *src, size_t n);
|
extern char *strncpy(char *dest, const char *src, size_t n);
|
||||||
extern char *strcat(char *dest, const char *src);
|
extern char *strcat(char *dest, const char *src);
|
||||||
extern char *strchr(const char *s, int c);
|
extern char *strchr(const char *s, int c);
|
||||||
|
extern char *strrchr(const char *s, int c);
|
||||||
extern int strcmp(const char *s1, const char *s2);
|
extern int strcmp(const char *s1, const char *s2);
|
||||||
extern int strncmp(const char *s1, const char *s2, size_t n);
|
extern int strncmp(const char *s1, const char *s2, size_t n);
|
||||||
extern size_t strlen(const char *s);
|
extern size_t strlen(const char *s);
|
||||||
|
|
|
@ -111,8 +111,8 @@ struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
|
||||||
struct gpio_desc *desc;
|
struct gpio_desc *desc;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", index,
|
ret = of_parse_phandle_with_args_map(np, propname, "gpio", index,
|
||||||
&gpiospec);
|
&gpiospec);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_debug("%s: can't parse '%s' property of node '%pOF[%d]'\n",
|
pr_debug("%s: can't parse '%s' property of node '%pOF[%d]'\n",
|
||||||
__func__, propname, np, index);
|
__func__, propname, np, index);
|
||||||
|
|
|
@ -91,10 +91,72 @@ int __weak of_node_to_nid(struct device_node *np)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static struct device_node **phandle_cache;
|
||||||
|
static u32 phandle_cache_mask;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Assumptions behind phandle_cache implementation:
|
||||||
|
* - phandle property values are in a contiguous range of 1..n
|
||||||
|
*
|
||||||
|
* If the assumptions do not hold, then
|
||||||
|
* - the phandle lookup overhead reduction provided by the cache
|
||||||
|
* will likely be less
|
||||||
|
*/
|
||||||
|
static void of_populate_phandle_cache(void)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
u32 cache_entries;
|
||||||
|
struct device_node *np;
|
||||||
|
u32 phandles = 0;
|
||||||
|
|
||||||
|
raw_spin_lock_irqsave(&devtree_lock, flags);
|
||||||
|
|
||||||
|
kfree(phandle_cache);
|
||||||
|
phandle_cache = NULL;
|
||||||
|
|
||||||
|
for_each_of_allnodes(np)
|
||||||
|
if (np->phandle && np->phandle != OF_PHANDLE_ILLEGAL)
|
||||||
|
phandles++;
|
||||||
|
|
||||||
|
cache_entries = roundup_pow_of_two(phandles);
|
||||||
|
phandle_cache_mask = cache_entries - 1;
|
||||||
|
|
||||||
|
phandle_cache = kcalloc(cache_entries, sizeof(*phandle_cache),
|
||||||
|
GFP_ATOMIC);
|
||||||
|
if (!phandle_cache)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
for_each_of_allnodes(np)
|
||||||
|
if (np->phandle && np->phandle != OF_PHANDLE_ILLEGAL)
|
||||||
|
phandle_cache[np->phandle & phandle_cache_mask] = np;
|
||||||
|
|
||||||
|
out:
|
||||||
|
raw_spin_unlock_irqrestore(&devtree_lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_MODULES
|
||||||
|
static int __init of_free_phandle_cache(void)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
raw_spin_lock_irqsave(&devtree_lock, flags);
|
||||||
|
|
||||||
|
kfree(phandle_cache);
|
||||||
|
phandle_cache = NULL;
|
||||||
|
|
||||||
|
raw_spin_unlock_irqrestore(&devtree_lock, flags);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
late_initcall_sync(of_free_phandle_cache);
|
||||||
|
#endif
|
||||||
|
|
||||||
void __init of_core_init(void)
|
void __init of_core_init(void)
|
||||||
{
|
{
|
||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
|
|
||||||
|
of_populate_phandle_cache();
|
||||||
|
|
||||||
/* Create the kset, and register existing nodes */
|
/* Create the kset, and register existing nodes */
|
||||||
mutex_lock(&of_mutex);
|
mutex_lock(&of_mutex);
|
||||||
of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj);
|
of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj);
|
||||||
|
@ -1021,16 +1083,32 @@ EXPORT_SYMBOL_GPL(of_modalias_node);
|
||||||
*/
|
*/
|
||||||
struct device_node *of_find_node_by_phandle(phandle handle)
|
struct device_node *of_find_node_by_phandle(phandle handle)
|
||||||
{
|
{
|
||||||
struct device_node *np;
|
struct device_node *np = NULL;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
phandle masked_handle;
|
||||||
|
|
||||||
if (!handle)
|
if (!handle)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
raw_spin_lock_irqsave(&devtree_lock, flags);
|
raw_spin_lock_irqsave(&devtree_lock, flags);
|
||||||
for_each_of_allnodes(np)
|
|
||||||
if (np->phandle == handle)
|
masked_handle = handle & phandle_cache_mask;
|
||||||
break;
|
|
||||||
|
if (phandle_cache) {
|
||||||
|
if (phandle_cache[masked_handle] &&
|
||||||
|
handle == phandle_cache[masked_handle]->phandle)
|
||||||
|
np = phandle_cache[masked_handle];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!np) {
|
||||||
|
for_each_of_allnodes(np)
|
||||||
|
if (np->phandle == handle) {
|
||||||
|
if (phandle_cache)
|
||||||
|
phandle_cache[masked_handle] = np;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
of_node_get(np);
|
of_node_get(np);
|
||||||
raw_spin_unlock_irqrestore(&devtree_lock, flags);
|
raw_spin_unlock_irqrestore(&devtree_lock, flags);
|
||||||
return np;
|
return np;
|
||||||
|
@ -1283,6 +1361,190 @@ int of_parse_phandle_with_args(const struct device_node *np, const char *list_na
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(of_parse_phandle_with_args);
|
EXPORT_SYMBOL(of_parse_phandle_with_args);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* of_parse_phandle_with_args_map() - Find a node pointed by phandle in a list and remap it
|
||||||
|
* @np: pointer to a device tree node containing a list
|
||||||
|
* @list_name: property name that contains a list
|
||||||
|
* @stem_name: stem of property names that specify phandles' arguments count
|
||||||
|
* @index: index of a phandle to parse out
|
||||||
|
* @out_args: optional pointer to output arguments structure (will be filled)
|
||||||
|
*
|
||||||
|
* This function is useful to parse lists of phandles and their arguments.
|
||||||
|
* Returns 0 on success and fills out_args, on error returns appropriate errno
|
||||||
|
* value. The difference between this function and of_parse_phandle_with_args()
|
||||||
|
* is that this API remaps a phandle if the node the phandle points to has
|
||||||
|
* a <@stem_name>-map property.
|
||||||
|
*
|
||||||
|
* Caller is responsible to call of_node_put() on the returned out_args->np
|
||||||
|
* pointer.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* phandle1: node1 {
|
||||||
|
* #list-cells = <2>;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* phandle2: node2 {
|
||||||
|
* #list-cells = <1>;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* phandle3: node3 {
|
||||||
|
* #list-cells = <1>;
|
||||||
|
* list-map = <0 &phandle2 3>,
|
||||||
|
* <1 &phandle2 2>,
|
||||||
|
* <2 &phandle1 5 1>;
|
||||||
|
* list-map-mask = <0x3>;
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* node4 {
|
||||||
|
* list = <&phandle1 1 2 &phandle3 0>;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* To get a device_node of the `node2' node you may call this:
|
||||||
|
* of_parse_phandle_with_args(node4, "list", "list", 1, &args);
|
||||||
|
*/
|
||||||
|
int of_parse_phandle_with_args_map(const struct device_node *np,
|
||||||
|
const char *list_name,
|
||||||
|
const char *stem_name,
|
||||||
|
int index, struct of_phandle_args *out_args)
|
||||||
|
{
|
||||||
|
char *cells_name, *map_name = NULL, *mask_name = NULL;
|
||||||
|
char *pass_name = NULL;
|
||||||
|
struct device_node *cur, *new = NULL;
|
||||||
|
const __be32 *map, *mask, *pass;
|
||||||
|
static const __be32 dummy_mask[] = { [0 ... MAX_PHANDLE_ARGS] = ~0 };
|
||||||
|
static const __be32 dummy_pass[] = { [0 ... MAX_PHANDLE_ARGS] = 0 };
|
||||||
|
__be32 initial_match_array[MAX_PHANDLE_ARGS];
|
||||||
|
const __be32 *match_array = initial_match_array;
|
||||||
|
int i, ret, map_len, match;
|
||||||
|
u32 list_size, new_size;
|
||||||
|
|
||||||
|
if (index < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
cells_name = kasprintf(GFP_KERNEL, "#%s-cells", stem_name);
|
||||||
|
if (!cells_name)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
ret = -ENOMEM;
|
||||||
|
map_name = kasprintf(GFP_KERNEL, "%s-map", stem_name);
|
||||||
|
if (!map_name)
|
||||||
|
goto free;
|
||||||
|
|
||||||
|
mask_name = kasprintf(GFP_KERNEL, "%s-map-mask", stem_name);
|
||||||
|
if (!mask_name)
|
||||||
|
goto free;
|
||||||
|
|
||||||
|
pass_name = kasprintf(GFP_KERNEL, "%s-map-pass-thru", stem_name);
|
||||||
|
if (!pass_name)
|
||||||
|
goto free;
|
||||||
|
|
||||||
|
ret = __of_parse_phandle_with_args(np, list_name, cells_name, 0, index,
|
||||||
|
out_args);
|
||||||
|
if (ret)
|
||||||
|
goto free;
|
||||||
|
|
||||||
|
/* Get the #<list>-cells property */
|
||||||
|
cur = out_args->np;
|
||||||
|
ret = of_property_read_u32(cur, cells_name, &list_size);
|
||||||
|
if (ret < 0)
|
||||||
|
goto put;
|
||||||
|
|
||||||
|
/* Precalculate the match array - this simplifies match loop */
|
||||||
|
for (i = 0; i < list_size; i++)
|
||||||
|
initial_match_array[i] = cpu_to_be32(out_args->args[i]);
|
||||||
|
|
||||||
|
ret = -EINVAL;
|
||||||
|
while (cur) {
|
||||||
|
/* Get the <list>-map property */
|
||||||
|
map = of_get_property(cur, map_name, &map_len);
|
||||||
|
if (!map) {
|
||||||
|
ret = 0;
|
||||||
|
goto free;
|
||||||
|
}
|
||||||
|
map_len /= sizeof(u32);
|
||||||
|
|
||||||
|
/* Get the <list>-map-mask property (optional) */
|
||||||
|
mask = of_get_property(cur, mask_name, NULL);
|
||||||
|
if (!mask)
|
||||||
|
mask = dummy_mask;
|
||||||
|
/* Iterate through <list>-map property */
|
||||||
|
match = 0;
|
||||||
|
while (map_len > (list_size + 1) && !match) {
|
||||||
|
/* Compare specifiers */
|
||||||
|
match = 1;
|
||||||
|
for (i = 0; i < list_size; i++, map_len--)
|
||||||
|
match &= !((match_array[i] ^ *map++) & mask[i]);
|
||||||
|
|
||||||
|
of_node_put(new);
|
||||||
|
new = of_find_node_by_phandle(be32_to_cpup(map));
|
||||||
|
map++;
|
||||||
|
map_len--;
|
||||||
|
|
||||||
|
/* Check if not found */
|
||||||
|
if (!new)
|
||||||
|
goto put;
|
||||||
|
|
||||||
|
if (!of_device_is_available(new))
|
||||||
|
match = 0;
|
||||||
|
|
||||||
|
ret = of_property_read_u32(new, cells_name, &new_size);
|
||||||
|
if (ret)
|
||||||
|
goto put;
|
||||||
|
|
||||||
|
/* Check for malformed properties */
|
||||||
|
if (WARN_ON(new_size > MAX_PHANDLE_ARGS))
|
||||||
|
goto put;
|
||||||
|
if (map_len < new_size)
|
||||||
|
goto put;
|
||||||
|
|
||||||
|
/* Move forward by new node's #<list>-cells amount */
|
||||||
|
map += new_size;
|
||||||
|
map_len -= new_size;
|
||||||
|
}
|
||||||
|
if (!match)
|
||||||
|
goto put;
|
||||||
|
|
||||||
|
/* Get the <list>-map-pass-thru property (optional) */
|
||||||
|
pass = of_get_property(cur, pass_name, NULL);
|
||||||
|
if (!pass)
|
||||||
|
pass = dummy_pass;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Successfully parsed a <list>-map translation; copy new
|
||||||
|
* specifier into the out_args structure, keeping the
|
||||||
|
* bits specified in <list>-map-pass-thru.
|
||||||
|
*/
|
||||||
|
match_array = map - new_size;
|
||||||
|
for (i = 0; i < new_size; i++) {
|
||||||
|
__be32 val = *(map - new_size + i);
|
||||||
|
|
||||||
|
if (i < list_size) {
|
||||||
|
val &= ~pass[i];
|
||||||
|
val |= cpu_to_be32(out_args->args[i]) & pass[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
out_args->args[i] = be32_to_cpu(val);
|
||||||
|
}
|
||||||
|
out_args->args_count = list_size = new_size;
|
||||||
|
/* Iterate again with new provider */
|
||||||
|
out_args->np = new;
|
||||||
|
of_node_put(cur);
|
||||||
|
cur = new;
|
||||||
|
}
|
||||||
|
put:
|
||||||
|
of_node_put(cur);
|
||||||
|
of_node_put(new);
|
||||||
|
free:
|
||||||
|
kfree(mask_name);
|
||||||
|
kfree(map_name);
|
||||||
|
kfree(cells_name);
|
||||||
|
kfree(pass_name);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(of_parse_phandle_with_args_map);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* of_parse_phandle_with_fixed_args() - Find a node pointed by phandle in a list
|
* of_parse_phandle_with_fixed_args() - Find a node pointed by phandle in a list
|
||||||
* @np: pointer to a device tree node containing a list
|
* @np: pointer to a device tree node containing a list
|
||||||
|
|
|
@ -383,25 +383,24 @@ struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __of_node_dup() - Duplicate or create an empty device node dynamically.
|
* __of_node_dup() - Duplicate or create an empty device node dynamically.
|
||||||
* @fmt: Format string (plus vargs) for new full name of the device node
|
* @np: if not NULL, contains properties to be duplicated in new node
|
||||||
|
* @full_name: string value to be duplicated into new node's full_name field
|
||||||
*
|
*
|
||||||
* Create an device tree node, either by duplicating an empty node or by allocating
|
* Create a device tree node, optionally duplicating the properties of
|
||||||
* an empty one suitable for further modification. The node data are
|
* another node. The node data are dynamically allocated and all the node
|
||||||
* dynamically allocated and all the node flags have the OF_DYNAMIC &
|
* flags have the OF_DYNAMIC & OF_DETACHED bits set.
|
||||||
* OF_DETACHED bits set. Returns the newly allocated node or NULL on out of
|
*
|
||||||
* memory error.
|
* Returns the newly allocated node or NULL on out of memory error.
|
||||||
*/
|
*/
|
||||||
struct device_node *__of_node_dup(const struct device_node *np, const char *fmt, ...)
|
struct device_node *__of_node_dup(const struct device_node *np,
|
||||||
|
const char *full_name)
|
||||||
{
|
{
|
||||||
va_list vargs;
|
|
||||||
struct device_node *node;
|
struct device_node *node;
|
||||||
|
|
||||||
node = kzalloc(sizeof(*node), GFP_KERNEL);
|
node = kzalloc(sizeof(*node), GFP_KERNEL);
|
||||||
if (!node)
|
if (!node)
|
||||||
return NULL;
|
return NULL;
|
||||||
va_start(vargs, fmt);
|
node->full_name = kstrdup(full_name, GFP_KERNEL);
|
||||||
node->full_name = kvasprintf(GFP_KERNEL, fmt, vargs);
|
|
||||||
va_end(vargs);
|
|
||||||
if (!node->full_name) {
|
if (!node->full_name) {
|
||||||
kfree(node);
|
kfree(node);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -104,7 +104,8 @@ extern void *__unflatten_device_tree(const void *blob,
|
||||||
* own the devtree lock or work on detached trees only.
|
* own the devtree lock or work on detached trees only.
|
||||||
*/
|
*/
|
||||||
struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags);
|
struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags);
|
||||||
__printf(2, 3) struct device_node *__of_node_dup(const struct device_node *np, const char *fmt, ...);
|
struct device_node *__of_node_dup(const struct device_node *np,
|
||||||
|
const char *full_name);
|
||||||
|
|
||||||
struct device_node *__of_find_node_by_path(struct device_node *parent,
|
struct device_node *__of_find_node_by_path(struct device_node *parent,
|
||||||
const char *path);
|
const char *path);
|
||||||
|
@ -131,6 +132,9 @@ extern void __of_detach_node_sysfs(struct device_node *np);
|
||||||
extern void __of_sysfs_remove_bin_file(struct device_node *np,
|
extern void __of_sysfs_remove_bin_file(struct device_node *np,
|
||||||
struct property *prop);
|
struct property *prop);
|
||||||
|
|
||||||
|
/* illegal phandle value (set when unresolved) */
|
||||||
|
#define OF_PHANDLE_ILLEGAL 0xdeadbeef
|
||||||
|
|
||||||
/* iterators for transactions, used for overlays */
|
/* iterators for transactions, used for overlays */
|
||||||
/* forward iterator */
|
/* forward iterator */
|
||||||
#define for_each_transaction_entry(_oft, _te) \
|
#define for_each_transaction_entry(_oft, _te) \
|
||||||
|
|
|
@ -312,7 +312,20 @@ static int add_changeset_property(struct overlay_changeset *ovcs,
|
||||||
* If @node has child nodes, add the children recursively via
|
* If @node has child nodes, add the children recursively via
|
||||||
* build_changeset_next_level().
|
* build_changeset_next_level().
|
||||||
*
|
*
|
||||||
* NOTE: Multiple mods of created nodes not supported.
|
* NOTE_1: A live devicetree created from a flattened device tree (FDT) will
|
||||||
|
* not contain the full path in node->full_name. Thus an overlay
|
||||||
|
* created from an FDT also will not contain the full path in
|
||||||
|
* node->full_name. However, a live devicetree created from Open
|
||||||
|
* Firmware may have the full path in node->full_name.
|
||||||
|
*
|
||||||
|
* add_changeset_node() follows the FDT convention and does not include
|
||||||
|
* the full path in node->full_name. Even though it expects the overlay
|
||||||
|
* to not contain the full path, it uses kbasename() to remove the
|
||||||
|
* full path should it exist. It also uses kbasename() in comparisons
|
||||||
|
* to nodes in the live devicetree so that it can apply an overlay to
|
||||||
|
* a live devicetree created from Open Firmware.
|
||||||
|
*
|
||||||
|
* NOTE_2: Multiple mods of created nodes not supported.
|
||||||
* If more than one fragment contains a node that does not already exist
|
* If more than one fragment contains a node that does not already exist
|
||||||
* in the live tree, then for each fragment of_changeset_attach_node()
|
* in the live tree, then for each fragment of_changeset_attach_node()
|
||||||
* will add a changeset entry to add the node. When the changeset is
|
* will add a changeset entry to add the node. When the changeset is
|
||||||
|
@ -339,8 +352,7 @@ static int add_changeset_node(struct overlay_changeset *ovcs,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!tchild) {
|
if (!tchild) {
|
||||||
tchild = __of_node_dup(node, "%pOF/%s",
|
tchild = __of_node_dup(node, node_kbasename);
|
||||||
target_node, node_kbasename);
|
|
||||||
if (!tchild)
|
if (!tchild)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -958,7 +970,7 @@ static int overlay_removal_is_ok(struct overlay_changeset *remove_ovcs)
|
||||||
* @ovcs_id: Pointer to overlay changeset id
|
* @ovcs_id: Pointer to overlay changeset id
|
||||||
*
|
*
|
||||||
* Removes an overlay if it is permissible. @ovcs_id was previously returned
|
* Removes an overlay if it is permissible. @ovcs_id was previously returned
|
||||||
* by of_overlay_apply().
|
* by of_overlay_fdt_apply().
|
||||||
*
|
*
|
||||||
* If an error occurred while attempting to revert the overlay changeset,
|
* If an error occurred while attempting to revert the overlay changeset,
|
||||||
* then an attempt is made to re-apply any changeset entry that was
|
* then an attempt is made to re-apply any changeset entry that was
|
||||||
|
|
|
@ -19,9 +19,6 @@
|
||||||
|
|
||||||
#include "of_private.h"
|
#include "of_private.h"
|
||||||
|
|
||||||
/* illegal phandle value (set when unresolved) */
|
|
||||||
#define OF_PHANDLE_ILLEGAL 0xdeadbeef
|
|
||||||
|
|
||||||
static phandle live_tree_max_phandle(void)
|
static phandle live_tree_max_phandle(void)
|
||||||
{
|
{
|
||||||
struct device_node *node;
|
struct device_node *node;
|
||||||
|
|
|
@ -26,6 +26,18 @@
|
||||||
#phandle-cells = <3>;
|
#phandle-cells = <3>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
provider4: provider4 {
|
||||||
|
#phandle-cells = <2>;
|
||||||
|
phandle-map = <0 1 &provider1 3>,
|
||||||
|
<4 0 &provider0>,
|
||||||
|
<16 5 &provider3 3 5 0>,
|
||||||
|
<200 8 &provider2 23 6>,
|
||||||
|
<19 0 &provider2 15 0>,
|
||||||
|
<2 3 &provider3 2 5 3>;
|
||||||
|
phandle-map-mask = <0xff 0xf>;
|
||||||
|
phandle-map-pass-thru = <0x0 0xf0>;
|
||||||
|
};
|
||||||
|
|
||||||
consumer-a {
|
consumer-a {
|
||||||
phandle-list = <&provider1 1>,
|
phandle-list = <&provider1 1>,
|
||||||
<&provider2 2 0>,
|
<&provider2 2 0>,
|
||||||
|
@ -44,6 +56,19 @@
|
||||||
unterminated-string = [40 41 42 43];
|
unterminated-string = [40 41 42 43];
|
||||||
unterminated-string-list = "first", "second", [40 41 42 43];
|
unterminated-string-list = "first", "second", [40 41 42 43];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
consumer-b {
|
||||||
|
phandle-list = <&provider1 1>,
|
||||||
|
<&provider4 2 3>,
|
||||||
|
<0>,
|
||||||
|
<&provider4 4 0x100>,
|
||||||
|
<&provider4 0 0x61>,
|
||||||
|
<&provider0>,
|
||||||
|
<&provider4 19 0x20>;
|
||||||
|
phandle-list-bad-phandle = <12345678 0 0>;
|
||||||
|
phandle-list-bad-args = <&provider2 1 0>,
|
||||||
|
<&provider4 0>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -45,8 +45,6 @@ static struct unittest_results {
|
||||||
failed; \
|
failed; \
|
||||||
})
|
})
|
||||||
|
|
||||||
static int __init overlay_data_apply(const char *overlay_name, int *overlay_id);
|
|
||||||
|
|
||||||
static void __init of_unittest_find_node_by_name(void)
|
static void __init of_unittest_find_node_by_name(void)
|
||||||
{
|
{
|
||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
|
@ -254,12 +252,18 @@ static void __init of_unittest_check_tree_linkage(void)
|
||||||
static void __init of_unittest_printf_one(struct device_node *np, const char *fmt,
|
static void __init of_unittest_printf_one(struct device_node *np, const char *fmt,
|
||||||
const char *expected)
|
const char *expected)
|
||||||
{
|
{
|
||||||
unsigned char buf[strlen(expected)+10];
|
unsigned char *buf;
|
||||||
|
int buf_size;
|
||||||
int size, i;
|
int size, i;
|
||||||
|
|
||||||
|
buf_size = strlen(expected) + 10;
|
||||||
|
buf = kmalloc(buf_size, GFP_KERNEL);
|
||||||
|
if (!buf)
|
||||||
|
return;
|
||||||
|
|
||||||
/* Baseline; check conversion with a large size limit */
|
/* Baseline; check conversion with a large size limit */
|
||||||
memset(buf, 0xff, sizeof(buf));
|
memset(buf, 0xff, buf_size);
|
||||||
size = snprintf(buf, sizeof(buf) - 2, fmt, np);
|
size = snprintf(buf, buf_size - 2, fmt, np);
|
||||||
|
|
||||||
/* use strcmp() instead of strncmp() here to be absolutely sure strings match */
|
/* use strcmp() instead of strncmp() here to be absolutely sure strings match */
|
||||||
unittest((strcmp(buf, expected) == 0) && (buf[size+1] == 0xff),
|
unittest((strcmp(buf, expected) == 0) && (buf[size+1] == 0xff),
|
||||||
|
@ -270,12 +274,13 @@ static void __init of_unittest_printf_one(struct device_node *np, const char *fm
|
||||||
size++;
|
size++;
|
||||||
for (i = 0; i < 2; i++, size--) {
|
for (i = 0; i < 2; i++, size--) {
|
||||||
/* Clear the buffer, and make sure it works correctly still */
|
/* Clear the buffer, and make sure it works correctly still */
|
||||||
memset(buf, 0xff, sizeof(buf));
|
memset(buf, 0xff, buf_size);
|
||||||
snprintf(buf, size+1, fmt, np);
|
snprintf(buf, size+1, fmt, np);
|
||||||
unittest(strncmp(buf, expected, size) == 0 && (buf[size+1] == 0xff),
|
unittest(strncmp(buf, expected, size) == 0 && (buf[size+1] == 0xff),
|
||||||
"snprintf failed; size=%i fmt='%s' expected='%s' rslt='%s'\n",
|
"snprintf failed; size=%i fmt='%s' expected='%s' rslt='%s'\n",
|
||||||
size, fmt, expected, buf);
|
size, fmt, expected, buf);
|
||||||
}
|
}
|
||||||
|
kfree(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __init of_unittest_printf(void)
|
static void __init of_unittest_printf(void)
|
||||||
|
@ -455,6 +460,125 @@ static void __init of_unittest_parse_phandle_with_args(void)
|
||||||
unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);
|
unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __init of_unittest_parse_phandle_with_args_map(void)
|
||||||
|
{
|
||||||
|
struct device_node *np, *p0, *p1, *p2, *p3;
|
||||||
|
struct of_phandle_args args;
|
||||||
|
int i, rc;
|
||||||
|
|
||||||
|
np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-b");
|
||||||
|
if (!np) {
|
||||||
|
pr_err("missing testcase data\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
p0 = of_find_node_by_path("/testcase-data/phandle-tests/provider0");
|
||||||
|
if (!p0) {
|
||||||
|
pr_err("missing testcase data\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
p1 = of_find_node_by_path("/testcase-data/phandle-tests/provider1");
|
||||||
|
if (!p1) {
|
||||||
|
pr_err("missing testcase data\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
p2 = of_find_node_by_path("/testcase-data/phandle-tests/provider2");
|
||||||
|
if (!p2) {
|
||||||
|
pr_err("missing testcase data\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
p3 = of_find_node_by_path("/testcase-data/phandle-tests/provider3");
|
||||||
|
if (!p3) {
|
||||||
|
pr_err("missing testcase data\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = of_count_phandle_with_args(np, "phandle-list", "#phandle-cells");
|
||||||
|
unittest(rc == 7, "of_count_phandle_with_args() returned %i, expected 7\n", rc);
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
bool passed = true;
|
||||||
|
|
||||||
|
rc = of_parse_phandle_with_args_map(np, "phandle-list",
|
||||||
|
"phandle", i, &args);
|
||||||
|
|
||||||
|
/* Test the values from tests-phandle.dtsi */
|
||||||
|
switch (i) {
|
||||||
|
case 0:
|
||||||
|
passed &= !rc;
|
||||||
|
passed &= (args.np == p1);
|
||||||
|
passed &= (args.args_count == 1);
|
||||||
|
passed &= (args.args[0] == 1);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
passed &= !rc;
|
||||||
|
passed &= (args.np == p3);
|
||||||
|
passed &= (args.args_count == 3);
|
||||||
|
passed &= (args.args[0] == 2);
|
||||||
|
passed &= (args.args[1] == 5);
|
||||||
|
passed &= (args.args[2] == 3);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
passed &= (rc == -ENOENT);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
passed &= !rc;
|
||||||
|
passed &= (args.np == p0);
|
||||||
|
passed &= (args.args_count == 0);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
passed &= !rc;
|
||||||
|
passed &= (args.np == p1);
|
||||||
|
passed &= (args.args_count == 1);
|
||||||
|
passed &= (args.args[0] == 3);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
passed &= !rc;
|
||||||
|
passed &= (args.np == p0);
|
||||||
|
passed &= (args.args_count == 0);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
passed &= !rc;
|
||||||
|
passed &= (args.np == p2);
|
||||||
|
passed &= (args.args_count == 2);
|
||||||
|
passed &= (args.args[0] == 15);
|
||||||
|
passed &= (args.args[1] == 0x20);
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
passed &= (rc == -ENOENT);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
passed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest(passed, "index %i - data error on node %s rc=%i\n",
|
||||||
|
i, args.np->full_name, rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for missing list property */
|
||||||
|
rc = of_parse_phandle_with_args_map(np, "phandle-list-missing",
|
||||||
|
"phandle", 0, &args);
|
||||||
|
unittest(rc == -ENOENT, "expected:%i got:%i\n", -ENOENT, rc);
|
||||||
|
|
||||||
|
/* Check for missing cells,map,mask property */
|
||||||
|
rc = of_parse_phandle_with_args_map(np, "phandle-list",
|
||||||
|
"phandle-missing", 0, &args);
|
||||||
|
unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);
|
||||||
|
|
||||||
|
/* Check for bad phandle in list */
|
||||||
|
rc = of_parse_phandle_with_args_map(np, "phandle-list-bad-phandle",
|
||||||
|
"phandle", 0, &args);
|
||||||
|
unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);
|
||||||
|
|
||||||
|
/* Check for incorrectly formed argument list */
|
||||||
|
rc = of_parse_phandle_with_args_map(np, "phandle-list-bad-args",
|
||||||
|
"phandle", 1, &args);
|
||||||
|
unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);
|
||||||
|
}
|
||||||
|
|
||||||
static void __init of_unittest_property_string(void)
|
static void __init of_unittest_property_string(void)
|
||||||
{
|
{
|
||||||
const char *strings[4];
|
const char *strings[4];
|
||||||
|
@ -564,42 +688,72 @@ static void __init of_unittest_property_copy(void)
|
||||||
static void __init of_unittest_changeset(void)
|
static void __init of_unittest_changeset(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_OF_DYNAMIC
|
#ifdef CONFIG_OF_DYNAMIC
|
||||||
struct property *ppadd, padd = { .name = "prop-add", .length = 0, .value = "" };
|
struct property *ppadd, padd = { .name = "prop-add", .length = 1, .value = "" };
|
||||||
|
struct property *ppname_n1, pname_n1 = { .name = "name", .length = 3, .value = "n1" };
|
||||||
|
struct property *ppname_n2, pname_n2 = { .name = "name", .length = 3, .value = "n2" };
|
||||||
|
struct property *ppname_n21, pname_n21 = { .name = "name", .length = 3, .value = "n21" };
|
||||||
struct property *ppupdate, pupdate = { .name = "prop-update", .length = 5, .value = "abcd" };
|
struct property *ppupdate, pupdate = { .name = "prop-update", .length = 5, .value = "abcd" };
|
||||||
struct property *ppremove;
|
struct property *ppremove;
|
||||||
struct device_node *n1, *n2, *n21, *nremove, *parent, *np;
|
struct device_node *n1, *n2, *n21, *nchangeset, *nremove, *parent, *np;
|
||||||
struct of_changeset chgset;
|
struct of_changeset chgset;
|
||||||
|
|
||||||
n1 = __of_node_dup(NULL, "/testcase-data/changeset/n1");
|
n1 = __of_node_dup(NULL, "n1");
|
||||||
unittest(n1, "testcase setup failure\n");
|
unittest(n1, "testcase setup failure\n");
|
||||||
n2 = __of_node_dup(NULL, "/testcase-data/changeset/n2");
|
|
||||||
|
n2 = __of_node_dup(NULL, "n2");
|
||||||
unittest(n2, "testcase setup failure\n");
|
unittest(n2, "testcase setup failure\n");
|
||||||
n21 = __of_node_dup(NULL, "%s/%s", "/testcase-data/changeset/n2", "n21");
|
|
||||||
|
n21 = __of_node_dup(NULL, "n21");
|
||||||
unittest(n21, "testcase setup failure %p\n", n21);
|
unittest(n21, "testcase setup failure %p\n", n21);
|
||||||
nremove = of_find_node_by_path("/testcase-data/changeset/node-remove");
|
|
||||||
|
nchangeset = of_find_node_by_path("/testcase-data/changeset");
|
||||||
|
nremove = of_get_child_by_name(nchangeset, "node-remove");
|
||||||
unittest(nremove, "testcase setup failure\n");
|
unittest(nremove, "testcase setup failure\n");
|
||||||
|
|
||||||
ppadd = __of_prop_dup(&padd, GFP_KERNEL);
|
ppadd = __of_prop_dup(&padd, GFP_KERNEL);
|
||||||
unittest(ppadd, "testcase setup failure\n");
|
unittest(ppadd, "testcase setup failure\n");
|
||||||
|
|
||||||
|
ppname_n1 = __of_prop_dup(&pname_n1, GFP_KERNEL);
|
||||||
|
unittest(ppname_n1, "testcase setup failure\n");
|
||||||
|
|
||||||
|
ppname_n2 = __of_prop_dup(&pname_n2, GFP_KERNEL);
|
||||||
|
unittest(ppname_n2, "testcase setup failure\n");
|
||||||
|
|
||||||
|
ppname_n21 = __of_prop_dup(&pname_n21, GFP_KERNEL);
|
||||||
|
unittest(ppname_n21, "testcase setup failure\n");
|
||||||
|
|
||||||
ppupdate = __of_prop_dup(&pupdate, GFP_KERNEL);
|
ppupdate = __of_prop_dup(&pupdate, GFP_KERNEL);
|
||||||
unittest(ppupdate, "testcase setup failure\n");
|
unittest(ppupdate, "testcase setup failure\n");
|
||||||
parent = nremove->parent;
|
|
||||||
|
parent = nchangeset;
|
||||||
n1->parent = parent;
|
n1->parent = parent;
|
||||||
n2->parent = parent;
|
n2->parent = parent;
|
||||||
n21->parent = n2;
|
n21->parent = n2;
|
||||||
n2->child = n21;
|
|
||||||
ppremove = of_find_property(parent, "prop-remove", NULL);
|
ppremove = of_find_property(parent, "prop-remove", NULL);
|
||||||
unittest(ppremove, "failed to find removal prop");
|
unittest(ppremove, "failed to find removal prop");
|
||||||
|
|
||||||
of_changeset_init(&chgset);
|
of_changeset_init(&chgset);
|
||||||
|
|
||||||
unittest(!of_changeset_attach_node(&chgset, n1), "fail attach n1\n");
|
unittest(!of_changeset_attach_node(&chgset, n1), "fail attach n1\n");
|
||||||
|
unittest(!of_changeset_add_property(&chgset, n1, ppname_n1), "fail add prop name\n");
|
||||||
|
|
||||||
unittest(!of_changeset_attach_node(&chgset, n2), "fail attach n2\n");
|
unittest(!of_changeset_attach_node(&chgset, n2), "fail attach n2\n");
|
||||||
|
unittest(!of_changeset_add_property(&chgset, n2, ppname_n2), "fail add prop name\n");
|
||||||
|
|
||||||
unittest(!of_changeset_detach_node(&chgset, nremove), "fail remove node\n");
|
unittest(!of_changeset_detach_node(&chgset, nremove), "fail remove node\n");
|
||||||
|
unittest(!of_changeset_add_property(&chgset, n21, ppname_n21), "fail add prop name\n");
|
||||||
|
|
||||||
unittest(!of_changeset_attach_node(&chgset, n21), "fail attach n21\n");
|
unittest(!of_changeset_attach_node(&chgset, n21), "fail attach n21\n");
|
||||||
unittest(!of_changeset_add_property(&chgset, parent, ppadd), "fail add prop\n");
|
|
||||||
|
unittest(!of_changeset_add_property(&chgset, parent, ppadd), "fail add prop prop-add\n");
|
||||||
unittest(!of_changeset_update_property(&chgset, parent, ppupdate), "fail update prop\n");
|
unittest(!of_changeset_update_property(&chgset, parent, ppupdate), "fail update prop\n");
|
||||||
unittest(!of_changeset_remove_property(&chgset, parent, ppremove), "fail remove prop\n");
|
unittest(!of_changeset_remove_property(&chgset, parent, ppremove), "fail remove prop\n");
|
||||||
|
|
||||||
unittest(!of_changeset_apply(&chgset), "apply failed\n");
|
unittest(!of_changeset_apply(&chgset), "apply failed\n");
|
||||||
|
|
||||||
|
of_node_put(nchangeset);
|
||||||
|
|
||||||
/* Make sure node names are constructed correctly */
|
/* Make sure node names are constructed correctly */
|
||||||
unittest((np = of_find_node_by_path("/testcase-data/changeset/n2/n21")),
|
unittest((np = of_find_node_by_path("/testcase-data/changeset/n2/n21")),
|
||||||
"'%pOF' not added\n", n21);
|
"'%pOF' not added\n", n21);
|
||||||
|
@ -1036,6 +1190,7 @@ static int __init unittest_data_add(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_OF_OVERLAY
|
#ifdef CONFIG_OF_OVERLAY
|
||||||
|
static int __init overlay_data_apply(const char *overlay_name, int *overlay_id);
|
||||||
|
|
||||||
static int unittest_probe(struct platform_device *pdev)
|
static int unittest_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
|
@ -1267,26 +1422,18 @@ static void of_unittest_destroy_tracked_overlays(void)
|
||||||
static int __init of_unittest_apply_overlay(int overlay_nr, int unittest_nr,
|
static int __init of_unittest_apply_overlay(int overlay_nr, int unittest_nr,
|
||||||
int *overlay_id)
|
int *overlay_id)
|
||||||
{
|
{
|
||||||
struct device_node *np = NULL;
|
|
||||||
const char *overlay_name;
|
const char *overlay_name;
|
||||||
int ret;
|
|
||||||
|
|
||||||
overlay_name = overlay_name_from_nr(overlay_nr);
|
overlay_name = overlay_name_from_nr(overlay_nr);
|
||||||
|
|
||||||
ret = overlay_data_apply(overlay_name, overlay_id);
|
if (!overlay_data_apply(overlay_name, overlay_id)) {
|
||||||
if (!ret) {
|
|
||||||
unittest(0, "could not apply overlay \"%s\"\n",
|
unittest(0, "could not apply overlay \"%s\"\n",
|
||||||
overlay_name);
|
overlay_name);
|
||||||
goto out;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
of_unittest_track_overlay(*overlay_id);
|
of_unittest_track_overlay(*overlay_id);
|
||||||
|
|
||||||
ret = 0;
|
return 0;
|
||||||
|
|
||||||
out:
|
|
||||||
of_node_put(np);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* apply an overlay while checking before and after states */
|
/* apply an overlay while checking before and after states */
|
||||||
|
@ -1380,11 +1527,8 @@ static int __init of_unittest_apply_revert_overlay_check(int overlay_nr,
|
||||||
/* test activation of device */
|
/* test activation of device */
|
||||||
static void __init of_unittest_overlay_0(void)
|
static void __init of_unittest_overlay_0(void)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* device should enable */
|
/* device should enable */
|
||||||
ret = of_unittest_apply_overlay_check(0, 0, 0, 1, PDEV_OVERLAY);
|
if (of_unittest_apply_overlay_check(0, 0, 0, 1, PDEV_OVERLAY))
|
||||||
if (ret != 0)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
unittest(1, "overlay test %d passed\n", 0);
|
unittest(1, "overlay test %d passed\n", 0);
|
||||||
|
@ -1393,11 +1537,8 @@ static void __init of_unittest_overlay_0(void)
|
||||||
/* test deactivation of device */
|
/* test deactivation of device */
|
||||||
static void __init of_unittest_overlay_1(void)
|
static void __init of_unittest_overlay_1(void)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* device should disable */
|
/* device should disable */
|
||||||
ret = of_unittest_apply_overlay_check(1, 1, 1, 0, PDEV_OVERLAY);
|
if (of_unittest_apply_overlay_check(1, 1, 1, 0, PDEV_OVERLAY))
|
||||||
if (ret != 0)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
unittest(1, "overlay test %d passed\n", 1);
|
unittest(1, "overlay test %d passed\n", 1);
|
||||||
|
@ -1406,11 +1547,8 @@ static void __init of_unittest_overlay_1(void)
|
||||||
/* test activation of device */
|
/* test activation of device */
|
||||||
static void __init of_unittest_overlay_2(void)
|
static void __init of_unittest_overlay_2(void)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* device should enable */
|
/* device should enable */
|
||||||
ret = of_unittest_apply_overlay_check(2, 2, 0, 1, PDEV_OVERLAY);
|
if (of_unittest_apply_overlay_check(2, 2, 0, 1, PDEV_OVERLAY))
|
||||||
if (ret != 0)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
unittest(1, "overlay test %d passed\n", 2);
|
unittest(1, "overlay test %d passed\n", 2);
|
||||||
|
@ -1419,11 +1557,8 @@ static void __init of_unittest_overlay_2(void)
|
||||||
/* test deactivation of device */
|
/* test deactivation of device */
|
||||||
static void __init of_unittest_overlay_3(void)
|
static void __init of_unittest_overlay_3(void)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* device should disable */
|
/* device should disable */
|
||||||
ret = of_unittest_apply_overlay_check(3, 3, 1, 0, PDEV_OVERLAY);
|
if (of_unittest_apply_overlay_check(3, 3, 1, 0, PDEV_OVERLAY))
|
||||||
if (ret != 0)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
unittest(1, "overlay test %d passed\n", 3);
|
unittest(1, "overlay test %d passed\n", 3);
|
||||||
|
@ -1432,11 +1567,8 @@ static void __init of_unittest_overlay_3(void)
|
||||||
/* test activation of a full device node */
|
/* test activation of a full device node */
|
||||||
static void __init of_unittest_overlay_4(void)
|
static void __init of_unittest_overlay_4(void)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* device should disable */
|
/* device should disable */
|
||||||
ret = of_unittest_apply_overlay_check(4, 4, 0, 1, PDEV_OVERLAY);
|
if (of_unittest_apply_overlay_check(4, 4, 0, 1, PDEV_OVERLAY))
|
||||||
if (ret != 0)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
unittest(1, "overlay test %d passed\n", 4);
|
unittest(1, "overlay test %d passed\n", 4);
|
||||||
|
@ -1445,11 +1577,8 @@ static void __init of_unittest_overlay_4(void)
|
||||||
/* test overlay apply/revert sequence */
|
/* test overlay apply/revert sequence */
|
||||||
static void __init of_unittest_overlay_5(void)
|
static void __init of_unittest_overlay_5(void)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* device should disable */
|
/* device should disable */
|
||||||
ret = of_unittest_apply_revert_overlay_check(5, 5, 0, 1, PDEV_OVERLAY);
|
if (of_unittest_apply_revert_overlay_check(5, 5, 0, 1, PDEV_OVERLAY))
|
||||||
if (ret != 0)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
unittest(1, "overlay test %d passed\n", 5);
|
unittest(1, "overlay test %d passed\n", 5);
|
||||||
|
@ -1458,7 +1587,7 @@ static void __init of_unittest_overlay_5(void)
|
||||||
/* test overlay application in sequence */
|
/* test overlay application in sequence */
|
||||||
static void __init of_unittest_overlay_6(void)
|
static void __init of_unittest_overlay_6(void)
|
||||||
{
|
{
|
||||||
int ret, i, ov_id[2], ovcs_id;
|
int i, ov_id[2], ovcs_id;
|
||||||
int overlay_nr = 6, unittest_nr = 6;
|
int overlay_nr = 6, unittest_nr = 6;
|
||||||
int before = 0, after = 1;
|
int before = 0, after = 1;
|
||||||
const char *overlay_name;
|
const char *overlay_name;
|
||||||
|
@ -1481,8 +1610,7 @@ static void __init of_unittest_overlay_6(void)
|
||||||
|
|
||||||
overlay_name = overlay_name_from_nr(overlay_nr + i);
|
overlay_name = overlay_name_from_nr(overlay_nr + i);
|
||||||
|
|
||||||
ret = overlay_data_apply(overlay_name, &ovcs_id);
|
if (!overlay_data_apply(overlay_name, &ovcs_id)) {
|
||||||
if (!ret) {
|
|
||||||
unittest(0, "could not apply overlay \"%s\"\n",
|
unittest(0, "could not apply overlay \"%s\"\n",
|
||||||
overlay_name);
|
overlay_name);
|
||||||
return;
|
return;
|
||||||
|
@ -1506,8 +1634,7 @@ static void __init of_unittest_overlay_6(void)
|
||||||
|
|
||||||
for (i = 1; i >= 0; i--) {
|
for (i = 1; i >= 0; i--) {
|
||||||
ovcs_id = ov_id[i];
|
ovcs_id = ov_id[i];
|
||||||
ret = of_overlay_remove(&ovcs_id);
|
if (of_overlay_remove(&ovcs_id)) {
|
||||||
if (ret != 0) {
|
|
||||||
unittest(0, "%s failed destroy @\"%s\"\n",
|
unittest(0, "%s failed destroy @\"%s\"\n",
|
||||||
overlay_name_from_nr(overlay_nr + i),
|
overlay_name_from_nr(overlay_nr + i),
|
||||||
unittest_path(unittest_nr + i,
|
unittest_path(unittest_nr + i,
|
||||||
|
@ -1536,7 +1663,7 @@ static void __init of_unittest_overlay_6(void)
|
||||||
/* test overlay application in sequence */
|
/* test overlay application in sequence */
|
||||||
static void __init of_unittest_overlay_8(void)
|
static void __init of_unittest_overlay_8(void)
|
||||||
{
|
{
|
||||||
int ret, i, ov_id[2], ovcs_id;
|
int i, ov_id[2], ovcs_id;
|
||||||
int overlay_nr = 8, unittest_nr = 8;
|
int overlay_nr = 8, unittest_nr = 8;
|
||||||
const char *overlay_name;
|
const char *overlay_name;
|
||||||
|
|
||||||
|
@ -1547,8 +1674,7 @@ static void __init of_unittest_overlay_8(void)
|
||||||
|
|
||||||
overlay_name = overlay_name_from_nr(overlay_nr + i);
|
overlay_name = overlay_name_from_nr(overlay_nr + i);
|
||||||
|
|
||||||
ret = overlay_data_apply(overlay_name, &ovcs_id);
|
if (!overlay_data_apply(overlay_name, &ovcs_id)) {
|
||||||
if (ret < 0) {
|
|
||||||
unittest(0, "could not apply overlay \"%s\"\n",
|
unittest(0, "could not apply overlay \"%s\"\n",
|
||||||
overlay_name);
|
overlay_name);
|
||||||
return;
|
return;
|
||||||
|
@ -1559,8 +1685,7 @@ static void __init of_unittest_overlay_8(void)
|
||||||
|
|
||||||
/* now try to remove first overlay (it should fail) */
|
/* now try to remove first overlay (it should fail) */
|
||||||
ovcs_id = ov_id[0];
|
ovcs_id = ov_id[0];
|
||||||
ret = of_overlay_remove(&ovcs_id);
|
if (!of_overlay_remove(&ovcs_id)) {
|
||||||
if (ret == 0) {
|
|
||||||
unittest(0, "%s was destroyed @\"%s\"\n",
|
unittest(0, "%s was destroyed @\"%s\"\n",
|
||||||
overlay_name_from_nr(overlay_nr + 0),
|
overlay_name_from_nr(overlay_nr + 0),
|
||||||
unittest_path(unittest_nr,
|
unittest_path(unittest_nr,
|
||||||
|
@ -1571,8 +1696,7 @@ static void __init of_unittest_overlay_8(void)
|
||||||
/* removing them in order should work */
|
/* removing them in order should work */
|
||||||
for (i = 1; i >= 0; i--) {
|
for (i = 1; i >= 0; i--) {
|
||||||
ovcs_id = ov_id[i];
|
ovcs_id = ov_id[i];
|
||||||
ret = of_overlay_remove(&ovcs_id);
|
if (of_overlay_remove(&ovcs_id)) {
|
||||||
if (ret != 0) {
|
|
||||||
unittest(0, "%s not destroyed @\"%s\"\n",
|
unittest(0, "%s not destroyed @\"%s\"\n",
|
||||||
overlay_name_from_nr(overlay_nr + i),
|
overlay_name_from_nr(overlay_nr + i),
|
||||||
unittest_path(unittest_nr,
|
unittest_path(unittest_nr,
|
||||||
|
@ -1604,8 +1728,8 @@ static void __init of_unittest_overlay_10(void)
|
||||||
|
|
||||||
ret = of_path_device_type_exists(child_path, PDEV_OVERLAY);
|
ret = of_path_device_type_exists(child_path, PDEV_OVERLAY);
|
||||||
kfree(child_path);
|
kfree(child_path);
|
||||||
if (unittest(ret, "overlay test %d failed; no child device\n", 10))
|
|
||||||
return;
|
unittest(ret, "overlay test %d failed; no child device\n", 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* test insertion of a bus with parent devices (and revert) */
|
/* test insertion of a bus with parent devices (and revert) */
|
||||||
|
@ -1616,9 +1740,7 @@ static void __init of_unittest_overlay_11(void)
|
||||||
/* device should disable */
|
/* device should disable */
|
||||||
ret = of_unittest_apply_revert_overlay_check(11, 11, 0, 1,
|
ret = of_unittest_apply_revert_overlay_check(11, 11, 0, 1,
|
||||||
PDEV_OVERLAY);
|
PDEV_OVERLAY);
|
||||||
if (unittest(ret == 0,
|
unittest(ret == 0, "overlay test %d failed; overlay apply\n", 11);
|
||||||
"overlay test %d failed; overlay application\n", 11))
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if IS_BUILTIN(CONFIG_I2C) && IS_ENABLED(CONFIG_OF_OVERLAY)
|
#if IS_BUILTIN(CONFIG_I2C) && IS_ENABLED(CONFIG_OF_OVERLAY)
|
||||||
|
@ -1769,7 +1891,7 @@ static int unittest_i2c_mux_select_chan(struct i2c_mux_core *muxc, u32 chan)
|
||||||
static int unittest_i2c_mux_probe(struct i2c_client *client,
|
static int unittest_i2c_mux_probe(struct i2c_client *client,
|
||||||
const struct i2c_device_id *id)
|
const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
int ret, i, nchans;
|
int i, nchans;
|
||||||
struct device *dev = &client->dev;
|
struct device *dev = &client->dev;
|
||||||
struct i2c_adapter *adap = to_i2c_adapter(dev->parent);
|
struct i2c_adapter *adap = to_i2c_adapter(dev->parent);
|
||||||
struct device_node *np = client->dev.of_node, *child;
|
struct device_node *np = client->dev.of_node, *child;
|
||||||
|
@ -1785,8 +1907,7 @@ static int unittest_i2c_mux_probe(struct i2c_client *client,
|
||||||
|
|
||||||
max_reg = (u32)-1;
|
max_reg = (u32)-1;
|
||||||
for_each_child_of_node(np, child) {
|
for_each_child_of_node(np, child) {
|
||||||
ret = of_property_read_u32(child, "reg", ®);
|
if (of_property_read_u32(child, "reg", ®))
|
||||||
if (ret)
|
|
||||||
continue;
|
continue;
|
||||||
if (max_reg == (u32)-1 || reg > max_reg)
|
if (max_reg == (u32)-1 || reg > max_reg)
|
||||||
max_reg = reg;
|
max_reg = reg;
|
||||||
|
@ -1802,8 +1923,7 @@ static int unittest_i2c_mux_probe(struct i2c_client *client,
|
||||||
if (!muxc)
|
if (!muxc)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
for (i = 0; i < nchans; i++) {
|
for (i = 0; i < nchans; i++) {
|
||||||
ret = i2c_mux_add_adapter(muxc, 0, i, 0);
|
if (i2c_mux_add_adapter(muxc, 0, i, 0)) {
|
||||||
if (ret) {
|
|
||||||
dev_err(dev, "Failed to register mux #%d\n", i);
|
dev_err(dev, "Failed to register mux #%d\n", i);
|
||||||
i2c_mux_del_adapters(muxc);
|
i2c_mux_del_adapters(muxc);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -1877,11 +1997,8 @@ static void of_unittest_overlay_i2c_cleanup(void)
|
||||||
|
|
||||||
static void __init of_unittest_overlay_i2c_12(void)
|
static void __init of_unittest_overlay_i2c_12(void)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* device should enable */
|
/* device should enable */
|
||||||
ret = of_unittest_apply_overlay_check(12, 12, 0, 1, I2C_OVERLAY);
|
if (of_unittest_apply_overlay_check(12, 12, 0, 1, I2C_OVERLAY))
|
||||||
if (ret != 0)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
unittest(1, "overlay test %d passed\n", 12);
|
unittest(1, "overlay test %d passed\n", 12);
|
||||||
|
@ -1890,11 +2007,8 @@ static void __init of_unittest_overlay_i2c_12(void)
|
||||||
/* test deactivation of device */
|
/* test deactivation of device */
|
||||||
static void __init of_unittest_overlay_i2c_13(void)
|
static void __init of_unittest_overlay_i2c_13(void)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* device should disable */
|
/* device should disable */
|
||||||
ret = of_unittest_apply_overlay_check(13, 13, 1, 0, I2C_OVERLAY);
|
if (of_unittest_apply_overlay_check(13, 13, 1, 0, I2C_OVERLAY))
|
||||||
if (ret != 0)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
unittest(1, "overlay test %d passed\n", 13);
|
unittest(1, "overlay test %d passed\n", 13);
|
||||||
|
@ -1907,11 +2021,8 @@ static void of_unittest_overlay_i2c_14(void)
|
||||||
|
|
||||||
static void __init of_unittest_overlay_i2c_15(void)
|
static void __init of_unittest_overlay_i2c_15(void)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* device should enable */
|
/* device should enable */
|
||||||
ret = of_unittest_apply_overlay_check(15, 15, 0, 1, I2C_OVERLAY);
|
if (of_unittest_apply_overlay_check(15, 15, 0, 1, I2C_OVERLAY))
|
||||||
if (ret != 0)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
unittest(1, "overlay test %d passed\n", 15);
|
unittest(1, "overlay test %d passed\n", 15);
|
||||||
|
@ -1927,10 +2038,8 @@ static inline void of_unittest_overlay_i2c_15(void) { }
|
||||||
static void __init of_unittest_overlay(void)
|
static void __init of_unittest_overlay(void)
|
||||||
{
|
{
|
||||||
struct device_node *bus_np = NULL;
|
struct device_node *bus_np = NULL;
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = platform_driver_register(&unittest_driver);
|
if (platform_driver_register(&unittest_driver)) {
|
||||||
if (ret != 0) {
|
|
||||||
unittest(0, "could not register unittest driver\n");
|
unittest(0, "could not register unittest driver\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -1941,8 +2050,7 @@ static void __init of_unittest_overlay(void)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = of_platform_default_populate(bus_np, NULL, NULL);
|
if (of_platform_default_populate(bus_np, NULL, NULL)) {
|
||||||
if (ret != 0) {
|
|
||||||
unittest(0, "could not populate bus @ \"%s\"\n", bus_path);
|
unittest(0, "could not populate bus @ \"%s\"\n", bus_path);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -2156,10 +2264,8 @@ static int __init overlay_data_apply(const char *overlay_name, int *overlay_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
size = info->dtb_end - info->dtb_begin;
|
size = info->dtb_end - info->dtb_begin;
|
||||||
if (!size) {
|
if (!size)
|
||||||
pr_err("no overlay data for %s\n", overlay_name);
|
pr_err("no overlay data for %s\n", overlay_name);
|
||||||
ret = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = of_overlay_fdt_apply(info->dtb_begin, size, &info->overlay_id);
|
ret = of_overlay_fdt_apply(info->dtb_begin, size, &info->overlay_id);
|
||||||
if (overlay_id)
|
if (overlay_id)
|
||||||
|
@ -2193,7 +2299,6 @@ static __init void of_unittest_overlay_high_level(void)
|
||||||
struct device_node *overlay_base_symbols;
|
struct device_node *overlay_base_symbols;
|
||||||
struct device_node **pprev;
|
struct device_node **pprev;
|
||||||
struct property *prop;
|
struct property *prop;
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (!overlay_base_root) {
|
if (!overlay_base_root) {
|
||||||
unittest(0, "overlay_base_root not initialized\n");
|
unittest(0, "overlay_base_root not initialized\n");
|
||||||
|
@ -2284,19 +2389,15 @@ static __init void of_unittest_overlay_high_level(void)
|
||||||
prop->name);
|
prop->name);
|
||||||
goto err_unlock;
|
goto err_unlock;
|
||||||
}
|
}
|
||||||
ret = __of_add_property(of_symbols, new_prop);
|
if (__of_add_property(of_symbols, new_prop)) {
|
||||||
if (ret) {
|
/* "name" auto-generated by unflatten */
|
||||||
if (!strcmp(new_prop->name, "name")) {
|
if (!strcmp(new_prop->name, "name"))
|
||||||
/* auto-generated by unflatten */
|
|
||||||
ret = 0;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
unittest(0, "duplicate property '%s' in overlay_base node __symbols__",
|
unittest(0, "duplicate property '%s' in overlay_base node __symbols__",
|
||||||
prop->name);
|
prop->name);
|
||||||
goto err_unlock;
|
goto err_unlock;
|
||||||
}
|
}
|
||||||
ret = __of_add_property_sysfs(of_symbols, new_prop);
|
if (__of_add_property_sysfs(of_symbols, new_prop)) {
|
||||||
if (ret) {
|
|
||||||
unittest(0, "unable to add property '%s' in overlay_base node __symbols__ to sysfs",
|
unittest(0, "unable to add property '%s' in overlay_base node __symbols__ to sysfs",
|
||||||
prop->name);
|
prop->name);
|
||||||
goto err_unlock;
|
goto err_unlock;
|
||||||
|
@ -2355,6 +2456,7 @@ static int __init of_unittest(void)
|
||||||
of_unittest_find_node_by_name();
|
of_unittest_find_node_by_name();
|
||||||
of_unittest_dynamic();
|
of_unittest_dynamic();
|
||||||
of_unittest_parse_phandle_with_args();
|
of_unittest_parse_phandle_with_args();
|
||||||
|
of_unittest_parse_phandle_with_args_map();
|
||||||
of_unittest_printf();
|
of_unittest_printf();
|
||||||
of_unittest_property_string();
|
of_unittest_property_string();
|
||||||
of_unittest_property_copy();
|
of_unittest_property_copy();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* SPDX-License-Identifier: GPL-2.0 */
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#ifndef _LIBFDT_ENV_H
|
#ifndef LIBFDT_ENV_H
|
||||||
#define _LIBFDT_ENV_H
|
#define LIBFDT_ENV_H
|
||||||
|
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
|
|
||||||
|
@ -15,4 +15,4 @@ typedef __be64 fdt64_t;
|
||||||
#define fdt64_to_cpu(x) be64_to_cpu(x)
|
#define fdt64_to_cpu(x) be64_to_cpu(x)
|
||||||
#define cpu_to_fdt64(x) cpu_to_be64(x)
|
#define cpu_to_fdt64(x) cpu_to_be64(x)
|
||||||
|
|
||||||
#endif /* _LIBFDT_ENV_H */
|
#endif /* LIBFDT_ENV_H */
|
||||||
|
|
|
@ -363,6 +363,9 @@ extern struct device_node *of_parse_phandle(const struct device_node *np,
|
||||||
extern int of_parse_phandle_with_args(const struct device_node *np,
|
extern int of_parse_phandle_with_args(const struct device_node *np,
|
||||||
const char *list_name, const char *cells_name, int index,
|
const char *list_name, const char *cells_name, int index,
|
||||||
struct of_phandle_args *out_args);
|
struct of_phandle_args *out_args);
|
||||||
|
extern int of_parse_phandle_with_args_map(const struct device_node *np,
|
||||||
|
const char *list_name, const char *stem_name, int index,
|
||||||
|
struct of_phandle_args *out_args);
|
||||||
extern int of_parse_phandle_with_fixed_args(const struct device_node *np,
|
extern int of_parse_phandle_with_fixed_args(const struct device_node *np,
|
||||||
const char *list_name, int cells_count, int index,
|
const char *list_name, int cells_count, int index,
|
||||||
struct of_phandle_args *out_args);
|
struct of_phandle_args *out_args);
|
||||||
|
@ -815,6 +818,15 @@ static inline int of_parse_phandle_with_args(const struct device_node *np,
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int of_parse_phandle_with_args_map(const struct device_node *np,
|
||||||
|
const char *list_name,
|
||||||
|
const char *stem_name,
|
||||||
|
int index,
|
||||||
|
struct of_phandle_args *out_args)
|
||||||
|
{
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int of_parse_phandle_with_fixed_args(const struct device_node *np,
|
static inline int of_parse_phandle_with_fixed_args(const struct device_node *np,
|
||||||
const char *list_name, int cells_count, int index,
|
const char *list_name, int cells_count, int index,
|
||||||
struct of_phandle_args *out_args)
|
struct of_phandle_args *out_args)
|
||||||
|
|
|
@ -210,7 +210,7 @@ $(filter %.tab.c,$(targets)): $(obj)/%.tab.c: $(src)/%.y FORCE
|
||||||
$(call if_changed,bison)
|
$(call if_changed,bison)
|
||||||
|
|
||||||
quiet_cmd_bison_h = YACC $@
|
quiet_cmd_bison_h = YACC $@
|
||||||
cmd_bison_h = bison -o/dev/null --defines=$@ -t -l -p $(YACC_PREFIX) $<
|
cmd_bison_h = bison -o/dev/null --defines=$@ -t -l $<
|
||||||
|
|
||||||
ifdef REGENERATE_PARSERS
|
ifdef REGENERATE_PARSERS
|
||||||
.PRECIOUS: $(src)/%.tab.h_shipped
|
.PRECIOUS: $(src)/%.tab.h_shipped
|
||||||
|
@ -269,10 +269,9 @@ DTC ?= $(objtree)/scripts/dtc/dtc
|
||||||
# Disable noisy checks by default
|
# Disable noisy checks by default
|
||||||
ifeq ($(findstring 1,$(KBUILD_ENABLE_EXTRA_GCC_CHECKS)),)
|
ifeq ($(findstring 1,$(KBUILD_ENABLE_EXTRA_GCC_CHECKS)),)
|
||||||
DTC_FLAGS += -Wno-unit_address_vs_reg \
|
DTC_FLAGS += -Wno-unit_address_vs_reg \
|
||||||
-Wno-simple_bus_reg \
|
|
||||||
-Wno-unit_address_format \
|
-Wno-unit_address_format \
|
||||||
-Wno-pci_bridge \
|
-Wno-avoid_unnecessary_addr_size \
|
||||||
-Wno-pci_device_bus_num \
|
-Wno-alias_paths \
|
||||||
-Wno-pci_device_reg
|
-Wno-pci_device_reg
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -309,7 +308,7 @@ cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \
|
||||||
-d $(depfile).dtc.tmp $(dtc-tmp) ; \
|
-d $(depfile).dtc.tmp $(dtc-tmp) ; \
|
||||||
cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile)
|
cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile)
|
||||||
|
|
||||||
$(obj)/%.dtb: $(src)/%.dts FORCE
|
$(obj)/%.dtb: $(src)/%.dts $(DTC) FORCE
|
||||||
$(call if_changed_dep,dtc)
|
$(call if_changed_dep,dtc)
|
||||||
|
|
||||||
dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp)
|
dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp)
|
||||||
|
|
|
@ -28,5 +28,7 @@ HOSTCFLAGS_dtc-parser.tab.o := $(HOSTCFLAGS_DTC)
|
||||||
# dependencies on generated files need to be listed explicitly
|
# dependencies on generated files need to be listed explicitly
|
||||||
$(obj)/dtc-lexer.lex.o: $(obj)/dtc-parser.tab.h
|
$(obj)/dtc-lexer.lex.o: $(obj)/dtc-parser.tab.h
|
||||||
|
|
||||||
# generated files need to be cleaned explicitly
|
# generated files need to include *.cmd and be cleaned explicitly
|
||||||
clean-files := dtc-lexer.lex.c dtc-parser.tab.c dtc-parser.tab.h
|
generated-files := dtc-lexer.lex.c dtc-parser.tab.c dtc-parser.tab.h
|
||||||
|
targets := $(generated-files)
|
||||||
|
clean-files := $(generated-files)
|
||||||
|
|
|
@ -53,26 +53,28 @@ struct check {
|
||||||
struct check **prereq;
|
struct check **prereq;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CHECK_ENTRY(_nm, _fn, _d, _w, _e, ...) \
|
#define CHECK_ENTRY(nm_, fn_, d_, w_, e_, ...) \
|
||||||
static struct check *_nm##_prereqs[] = { __VA_ARGS__ }; \
|
static struct check *nm_##_prereqs[] = { __VA_ARGS__ }; \
|
||||||
static struct check _nm = { \
|
static struct check nm_ = { \
|
||||||
.name = #_nm, \
|
.name = #nm_, \
|
||||||
.fn = (_fn), \
|
.fn = (fn_), \
|
||||||
.data = (_d), \
|
.data = (d_), \
|
||||||
.warn = (_w), \
|
.warn = (w_), \
|
||||||
.error = (_e), \
|
.error = (e_), \
|
||||||
.status = UNCHECKED, \
|
.status = UNCHECKED, \
|
||||||
.num_prereqs = ARRAY_SIZE(_nm##_prereqs), \
|
.num_prereqs = ARRAY_SIZE(nm_##_prereqs), \
|
||||||
.prereq = _nm##_prereqs, \
|
.prereq = nm_##_prereqs, \
|
||||||
};
|
};
|
||||||
#define WARNING(_nm, _fn, _d, ...) \
|
#define WARNING(nm_, fn_, d_, ...) \
|
||||||
CHECK_ENTRY(_nm, _fn, _d, true, false, __VA_ARGS__)
|
CHECK_ENTRY(nm_, fn_, d_, true, false, __VA_ARGS__)
|
||||||
#define ERROR(_nm, _fn, _d, ...) \
|
#define ERROR(nm_, fn_, d_, ...) \
|
||||||
CHECK_ENTRY(_nm, _fn, _d, false, true, __VA_ARGS__)
|
CHECK_ENTRY(nm_, fn_, d_, false, true, __VA_ARGS__)
|
||||||
#define CHECK(_nm, _fn, _d, ...) \
|
#define CHECK(nm_, fn_, d_, ...) \
|
||||||
CHECK_ENTRY(_nm, _fn, _d, false, false, __VA_ARGS__)
|
CHECK_ENTRY(nm_, fn_, d_, false, false, __VA_ARGS__)
|
||||||
|
|
||||||
static inline void PRINTF(3, 4) check_msg(struct check *c, struct dt_info *dti,
|
static inline void PRINTF(5, 6) check_msg(struct check *c, struct dt_info *dti,
|
||||||
|
struct node *node,
|
||||||
|
struct property *prop,
|
||||||
const char *fmt, ...)
|
const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
@ -83,19 +85,33 @@ static inline void PRINTF(3, 4) check_msg(struct check *c, struct dt_info *dti,
|
||||||
fprintf(stderr, "%s: %s (%s): ",
|
fprintf(stderr, "%s: %s (%s): ",
|
||||||
strcmp(dti->outname, "-") ? dti->outname : "<stdout>",
|
strcmp(dti->outname, "-") ? dti->outname : "<stdout>",
|
||||||
(c->error) ? "ERROR" : "Warning", c->name);
|
(c->error) ? "ERROR" : "Warning", c->name);
|
||||||
|
if (node) {
|
||||||
|
fprintf(stderr, "%s", node->fullpath);
|
||||||
|
if (prop)
|
||||||
|
fprintf(stderr, ":%s", prop->name);
|
||||||
|
fputs(": ", stderr);
|
||||||
|
}
|
||||||
vfprintf(stderr, fmt, ap);
|
vfprintf(stderr, fmt, ap);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FAIL(c, dti, ...) \
|
#define FAIL(c, dti, node, ...) \
|
||||||
do { \
|
do { \
|
||||||
TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
|
TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
|
||||||
(c)->status = FAILED; \
|
(c)->status = FAILED; \
|
||||||
check_msg((c), dti, __VA_ARGS__); \
|
check_msg((c), dti, node, NULL, __VA_ARGS__); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define FAIL_PROP(c, dti, node, prop, ...) \
|
||||||
|
do { \
|
||||||
|
TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
|
||||||
|
(c)->status = FAILED; \
|
||||||
|
check_msg((c), dti, node, prop, __VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
static void check_nodes_props(struct check *c, struct dt_info *dti, struct node *node)
|
static void check_nodes_props(struct check *c, struct dt_info *dti, struct node *node)
|
||||||
{
|
{
|
||||||
struct node *child;
|
struct node *child;
|
||||||
|
@ -126,7 +142,7 @@ static bool run_check(struct check *c, struct dt_info *dti)
|
||||||
error = error || run_check(prq, dti);
|
error = error || run_check(prq, dti);
|
||||||
if (prq->status != PASSED) {
|
if (prq->status != PASSED) {
|
||||||
c->status = PREREQ;
|
c->status = PREREQ;
|
||||||
check_msg(c, dti, "Failed prerequisite '%s'",
|
check_msg(c, dti, NULL, NULL, "Failed prerequisite '%s'",
|
||||||
c->prereq[i]->name);
|
c->prereq[i]->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,7 +172,7 @@ static bool run_check(struct check *c, struct dt_info *dti)
|
||||||
static inline void check_always_fail(struct check *c, struct dt_info *dti,
|
static inline void check_always_fail(struct check *c, struct dt_info *dti,
|
||||||
struct node *node)
|
struct node *node)
|
||||||
{
|
{
|
||||||
FAIL(c, dti, "always_fail check");
|
FAIL(c, dti, node, "always_fail check");
|
||||||
}
|
}
|
||||||
CHECK(always_fail, check_always_fail, NULL);
|
CHECK(always_fail, check_always_fail, NULL);
|
||||||
|
|
||||||
|
@ -171,14 +187,42 @@ static void check_is_string(struct check *c, struct dt_info *dti,
|
||||||
return; /* Not present, assumed ok */
|
return; /* Not present, assumed ok */
|
||||||
|
|
||||||
if (!data_is_one_string(prop->val))
|
if (!data_is_one_string(prop->val))
|
||||||
FAIL(c, dti, "\"%s\" property in %s is not a string",
|
FAIL_PROP(c, dti, node, prop, "property is not a string");
|
||||||
propname, node->fullpath);
|
|
||||||
}
|
}
|
||||||
#define WARNING_IF_NOT_STRING(nm, propname) \
|
#define WARNING_IF_NOT_STRING(nm, propname) \
|
||||||
WARNING(nm, check_is_string, (propname))
|
WARNING(nm, check_is_string, (propname))
|
||||||
#define ERROR_IF_NOT_STRING(nm, propname) \
|
#define ERROR_IF_NOT_STRING(nm, propname) \
|
||||||
ERROR(nm, check_is_string, (propname))
|
ERROR(nm, check_is_string, (propname))
|
||||||
|
|
||||||
|
static void check_is_string_list(struct check *c, struct dt_info *dti,
|
||||||
|
struct node *node)
|
||||||
|
{
|
||||||
|
int rem, l;
|
||||||
|
struct property *prop;
|
||||||
|
char *propname = c->data;
|
||||||
|
char *str;
|
||||||
|
|
||||||
|
prop = get_property(node, propname);
|
||||||
|
if (!prop)
|
||||||
|
return; /* Not present, assumed ok */
|
||||||
|
|
||||||
|
str = prop->val.val;
|
||||||
|
rem = prop->val.len;
|
||||||
|
while (rem > 0) {
|
||||||
|
l = strnlen(str, rem);
|
||||||
|
if (l == rem) {
|
||||||
|
FAIL_PROP(c, dti, node, prop, "property is not a string list");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rem -= l + 1;
|
||||||
|
str += l + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#define WARNING_IF_NOT_STRING_LIST(nm, propname) \
|
||||||
|
WARNING(nm, check_is_string_list, (propname))
|
||||||
|
#define ERROR_IF_NOT_STRING_LIST(nm, propname) \
|
||||||
|
ERROR(nm, check_is_string_list, (propname))
|
||||||
|
|
||||||
static void check_is_cell(struct check *c, struct dt_info *dti,
|
static void check_is_cell(struct check *c, struct dt_info *dti,
|
||||||
struct node *node)
|
struct node *node)
|
||||||
{
|
{
|
||||||
|
@ -190,8 +234,7 @@ static void check_is_cell(struct check *c, struct dt_info *dti,
|
||||||
return; /* Not present, assumed ok */
|
return; /* Not present, assumed ok */
|
||||||
|
|
||||||
if (prop->val.len != sizeof(cell_t))
|
if (prop->val.len != sizeof(cell_t))
|
||||||
FAIL(c, dti, "\"%s\" property in %s is not a single cell",
|
FAIL_PROP(c, dti, node, prop, "property is not a single cell");
|
||||||
propname, node->fullpath);
|
|
||||||
}
|
}
|
||||||
#define WARNING_IF_NOT_CELL(nm, propname) \
|
#define WARNING_IF_NOT_CELL(nm, propname) \
|
||||||
WARNING(nm, check_is_cell, (propname))
|
WARNING(nm, check_is_cell, (propname))
|
||||||
|
@ -212,8 +255,7 @@ static void check_duplicate_node_names(struct check *c, struct dt_info *dti,
|
||||||
child2;
|
child2;
|
||||||
child2 = child2->next_sibling)
|
child2 = child2->next_sibling)
|
||||||
if (streq(child->name, child2->name))
|
if (streq(child->name, child2->name))
|
||||||
FAIL(c, dti, "Duplicate node name %s",
|
FAIL(c, dti, node, "Duplicate node name");
|
||||||
child->fullpath);
|
|
||||||
}
|
}
|
||||||
ERROR(duplicate_node_names, check_duplicate_node_names, NULL);
|
ERROR(duplicate_node_names, check_duplicate_node_names, NULL);
|
||||||
|
|
||||||
|
@ -227,8 +269,7 @@ static void check_duplicate_property_names(struct check *c, struct dt_info *dti,
|
||||||
if (prop2->deleted)
|
if (prop2->deleted)
|
||||||
continue;
|
continue;
|
||||||
if (streq(prop->name, prop2->name))
|
if (streq(prop->name, prop2->name))
|
||||||
FAIL(c, dti, "Duplicate property name %s in %s",
|
FAIL_PROP(c, dti, node, prop, "Duplicate property name");
|
||||||
prop->name, node->fullpath);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -246,8 +287,8 @@ static void check_node_name_chars(struct check *c, struct dt_info *dti,
|
||||||
int n = strspn(node->name, c->data);
|
int n = strspn(node->name, c->data);
|
||||||
|
|
||||||
if (n < strlen(node->name))
|
if (n < strlen(node->name))
|
||||||
FAIL(c, dti, "Bad character '%c' in node %s",
|
FAIL(c, dti, node, "Bad character '%c' in node name",
|
||||||
node->name[n], node->fullpath);
|
node->name[n]);
|
||||||
}
|
}
|
||||||
ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@");
|
ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@");
|
||||||
|
|
||||||
|
@ -257,8 +298,8 @@ static void check_node_name_chars_strict(struct check *c, struct dt_info *dti,
|
||||||
int n = strspn(node->name, c->data);
|
int n = strspn(node->name, c->data);
|
||||||
|
|
||||||
if (n < node->basenamelen)
|
if (n < node->basenamelen)
|
||||||
FAIL(c, dti, "Character '%c' not recommended in node %s",
|
FAIL(c, dti, node, "Character '%c' not recommended in node name",
|
||||||
node->name[n], node->fullpath);
|
node->name[n]);
|
||||||
}
|
}
|
||||||
CHECK(node_name_chars_strict, check_node_name_chars_strict, PROPNODECHARSSTRICT);
|
CHECK(node_name_chars_strict, check_node_name_chars_strict, PROPNODECHARSSTRICT);
|
||||||
|
|
||||||
|
@ -266,8 +307,7 @@ static void check_node_name_format(struct check *c, struct dt_info *dti,
|
||||||
struct node *node)
|
struct node *node)
|
||||||
{
|
{
|
||||||
if (strchr(get_unitname(node), '@'))
|
if (strchr(get_unitname(node), '@'))
|
||||||
FAIL(c, dti, "Node %s has multiple '@' characters in name",
|
FAIL(c, dti, node, "multiple '@' characters in node name");
|
||||||
node->fullpath);
|
|
||||||
}
|
}
|
||||||
ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars);
|
ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars);
|
||||||
|
|
||||||
|
@ -285,12 +325,10 @@ static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
|
||||||
|
|
||||||
if (prop) {
|
if (prop) {
|
||||||
if (!unitname[0])
|
if (!unitname[0])
|
||||||
FAIL(c, dti, "Node %s has a reg or ranges property, but no unit name",
|
FAIL(c, dti, node, "node has a reg or ranges property, but no unit name");
|
||||||
node->fullpath);
|
|
||||||
} else {
|
} else {
|
||||||
if (unitname[0])
|
if (unitname[0])
|
||||||
FAIL(c, dti, "Node %s has a unit name, but no reg property",
|
FAIL(c, dti, node, "node has a unit name, but no reg property");
|
||||||
node->fullpath);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL);
|
WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL);
|
||||||
|
@ -304,8 +342,8 @@ static void check_property_name_chars(struct check *c, struct dt_info *dti,
|
||||||
int n = strspn(prop->name, c->data);
|
int n = strspn(prop->name, c->data);
|
||||||
|
|
||||||
if (n < strlen(prop->name))
|
if (n < strlen(prop->name))
|
||||||
FAIL(c, dti, "Bad character '%c' in property name \"%s\", node %s",
|
FAIL_PROP(c, dti, node, prop, "Bad character '%c' in property name",
|
||||||
prop->name[n], prop->name, node->fullpath);
|
prop->name[n]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS);
|
ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS);
|
||||||
|
@ -336,8 +374,8 @@ static void check_property_name_chars_strict(struct check *c,
|
||||||
n = strspn(name, c->data);
|
n = strspn(name, c->data);
|
||||||
}
|
}
|
||||||
if (n < strlen(name))
|
if (n < strlen(name))
|
||||||
FAIL(c, dti, "Character '%c' not recommended in property name \"%s\", node %s",
|
FAIL_PROP(c, dti, node, prop, "Character '%c' not recommended in property name",
|
||||||
name[n], prop->name, node->fullpath);
|
name[n]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CHECK(property_name_chars_strict, check_property_name_chars_strict, PROPNODECHARSSTRICT);
|
CHECK(property_name_chars_strict, check_property_name_chars_strict, PROPNODECHARSSTRICT);
|
||||||
|
@ -370,7 +408,7 @@ static void check_duplicate_label(struct check *c, struct dt_info *dti,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((othernode != node) || (otherprop != prop) || (othermark != mark))
|
if ((othernode != node) || (otherprop != prop) || (othermark != mark))
|
||||||
FAIL(c, dti, "Duplicate label '%s' on " DESCLABEL_FMT
|
FAIL(c, dti, node, "Duplicate label '%s' on " DESCLABEL_FMT
|
||||||
" and " DESCLABEL_FMT,
|
" and " DESCLABEL_FMT,
|
||||||
label, DESCLABEL_ARGS(node, prop, mark),
|
label, DESCLABEL_ARGS(node, prop, mark),
|
||||||
DESCLABEL_ARGS(othernode, otherprop, othermark));
|
DESCLABEL_ARGS(othernode, otherprop, othermark));
|
||||||
|
@ -410,8 +448,8 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (prop->val.len != sizeof(cell_t)) {
|
if (prop->val.len != sizeof(cell_t)) {
|
||||||
FAIL(c, dti, "%s has bad length (%d) %s property",
|
FAIL_PROP(c, dti, node, prop, "bad length (%d) %s property",
|
||||||
node->fullpath, prop->val.len, prop->name);
|
prop->val.len, prop->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,8 +460,8 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
|
||||||
/* "Set this node's phandle equal to some
|
/* "Set this node's phandle equal to some
|
||||||
* other node's phandle". That's nonsensical
|
* other node's phandle". That's nonsensical
|
||||||
* by construction. */ {
|
* by construction. */ {
|
||||||
FAIL(c, dti, "%s in %s is a reference to another node",
|
FAIL(c, dti, node, "%s is a reference to another node",
|
||||||
prop->name, node->fullpath);
|
prop->name);
|
||||||
}
|
}
|
||||||
/* But setting this node's phandle equal to its own
|
/* But setting this node's phandle equal to its own
|
||||||
* phandle is allowed - that means allocate a unique
|
* phandle is allowed - that means allocate a unique
|
||||||
|
@ -436,8 +474,8 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
|
||||||
phandle = propval_cell(prop);
|
phandle = propval_cell(prop);
|
||||||
|
|
||||||
if ((phandle == 0) || (phandle == -1)) {
|
if ((phandle == 0) || (phandle == -1)) {
|
||||||
FAIL(c, dti, "%s has bad value (0x%x) in %s property",
|
FAIL_PROP(c, dti, node, prop, "bad value (0x%x) in %s property",
|
||||||
node->fullpath, phandle, prop->name);
|
phandle, prop->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,16 +501,16 @@ static void check_explicit_phandles(struct check *c, struct dt_info *dti,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (linux_phandle && phandle && (phandle != linux_phandle))
|
if (linux_phandle && phandle && (phandle != linux_phandle))
|
||||||
FAIL(c, dti, "%s has mismatching 'phandle' and 'linux,phandle'"
|
FAIL(c, dti, node, "mismatching 'phandle' and 'linux,phandle'"
|
||||||
" properties", node->fullpath);
|
" properties");
|
||||||
|
|
||||||
if (linux_phandle && !phandle)
|
if (linux_phandle && !phandle)
|
||||||
phandle = linux_phandle;
|
phandle = linux_phandle;
|
||||||
|
|
||||||
other = get_node_by_phandle(root, phandle);
|
other = get_node_by_phandle(root, phandle);
|
||||||
if (other && (other != node)) {
|
if (other && (other != node)) {
|
||||||
FAIL(c, dti, "%s has duplicated phandle 0x%x (seen before at %s)",
|
FAIL(c, dti, node, "duplicated phandle 0x%x (seen before at %s)",
|
||||||
node->fullpath, phandle, other->fullpath);
|
phandle, other->fullpath);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -496,8 +534,8 @@ static void check_name_properties(struct check *c, struct dt_info *dti,
|
||||||
|
|
||||||
if ((prop->val.len != node->basenamelen+1)
|
if ((prop->val.len != node->basenamelen+1)
|
||||||
|| (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
|
|| (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
|
||||||
FAIL(c, dti, "\"name\" property in %s is incorrect (\"%s\" instead"
|
FAIL(c, dti, node, "\"name\" property is incorrect (\"%s\" instead"
|
||||||
" of base node name)", node->fullpath, prop->val.val);
|
" of base node name)", prop->val.val);
|
||||||
} else {
|
} else {
|
||||||
/* The name property is correct, and therefore redundant.
|
/* The name property is correct, and therefore redundant.
|
||||||
* Delete it */
|
* Delete it */
|
||||||
|
@ -531,7 +569,7 @@ static void fixup_phandle_references(struct check *c, struct dt_info *dti,
|
||||||
refnode = get_node_by_ref(dt, m->ref);
|
refnode = get_node_by_ref(dt, m->ref);
|
||||||
if (! refnode) {
|
if (! refnode) {
|
||||||
if (!(dti->dtsflags & DTSF_PLUGIN))
|
if (!(dti->dtsflags & DTSF_PLUGIN))
|
||||||
FAIL(c, dti, "Reference to non-existent node or "
|
FAIL(c, dti, node, "Reference to non-existent node or "
|
||||||
"label \"%s\"\n", m->ref);
|
"label \"%s\"\n", m->ref);
|
||||||
else /* mark the entry as unresolved */
|
else /* mark the entry as unresolved */
|
||||||
*((fdt32_t *)(prop->val.val + m->offset)) =
|
*((fdt32_t *)(prop->val.val + m->offset)) =
|
||||||
|
@ -563,7 +601,7 @@ static void fixup_path_references(struct check *c, struct dt_info *dti,
|
||||||
|
|
||||||
refnode = get_node_by_ref(dt, m->ref);
|
refnode = get_node_by_ref(dt, m->ref);
|
||||||
if (!refnode) {
|
if (!refnode) {
|
||||||
FAIL(c, dti, "Reference to non-existent node or label \"%s\"\n",
|
FAIL(c, dti, node, "Reference to non-existent node or label \"%s\"\n",
|
||||||
m->ref);
|
m->ref);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -586,6 +624,45 @@ WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells");
|
||||||
WARNING_IF_NOT_STRING(device_type_is_string, "device_type");
|
WARNING_IF_NOT_STRING(device_type_is_string, "device_type");
|
||||||
WARNING_IF_NOT_STRING(model_is_string, "model");
|
WARNING_IF_NOT_STRING(model_is_string, "model");
|
||||||
WARNING_IF_NOT_STRING(status_is_string, "status");
|
WARNING_IF_NOT_STRING(status_is_string, "status");
|
||||||
|
WARNING_IF_NOT_STRING(label_is_string, "label");
|
||||||
|
|
||||||
|
WARNING_IF_NOT_STRING_LIST(compatible_is_string_list, "compatible");
|
||||||
|
|
||||||
|
static void check_names_is_string_list(struct check *c, struct dt_info *dti,
|
||||||
|
struct node *node)
|
||||||
|
{
|
||||||
|
struct property *prop;
|
||||||
|
|
||||||
|
for_each_property(node, prop) {
|
||||||
|
const char *s = strrchr(prop->name, '-');
|
||||||
|
if (!s || !streq(s, "-names"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
c->data = prop->name;
|
||||||
|
check_is_string_list(c, dti, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WARNING(names_is_string_list, check_names_is_string_list, NULL);
|
||||||
|
|
||||||
|
static void check_alias_paths(struct check *c, struct dt_info *dti,
|
||||||
|
struct node *node)
|
||||||
|
{
|
||||||
|
struct property *prop;
|
||||||
|
|
||||||
|
if (!streq(node->name, "aliases"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
for_each_property(node, prop) {
|
||||||
|
if (!prop->val.val || !get_node_by_path(dti->dt, prop->val.val)) {
|
||||||
|
FAIL_PROP(c, dti, node, prop, "aliases property is not a valid node (%s)",
|
||||||
|
prop->val.val);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (strspn(prop->name, LOWERCASE DIGITS "-") != strlen(prop->name))
|
||||||
|
FAIL(c, dti, node, "aliases property name must include only lowercase and '-'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WARNING(alias_paths, check_alias_paths, NULL);
|
||||||
|
|
||||||
static void fixup_addr_size_cells(struct check *c, struct dt_info *dti,
|
static void fixup_addr_size_cells(struct check *c, struct dt_info *dti,
|
||||||
struct node *node)
|
struct node *node)
|
||||||
|
@ -622,21 +699,21 @@ static void check_reg_format(struct check *c, struct dt_info *dti,
|
||||||
return; /* No "reg", that's fine */
|
return; /* No "reg", that's fine */
|
||||||
|
|
||||||
if (!node->parent) {
|
if (!node->parent) {
|
||||||
FAIL(c, dti, "Root node has a \"reg\" property");
|
FAIL(c, dti, node, "Root node has a \"reg\" property");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prop->val.len == 0)
|
if (prop->val.len == 0)
|
||||||
FAIL(c, dti, "\"reg\" property in %s is empty", node->fullpath);
|
FAIL_PROP(c, dti, node, prop, "property is empty");
|
||||||
|
|
||||||
addr_cells = node_addr_cells(node->parent);
|
addr_cells = node_addr_cells(node->parent);
|
||||||
size_cells = node_size_cells(node->parent);
|
size_cells = node_size_cells(node->parent);
|
||||||
entrylen = (addr_cells + size_cells) * sizeof(cell_t);
|
entrylen = (addr_cells + size_cells) * sizeof(cell_t);
|
||||||
|
|
||||||
if (!entrylen || (prop->val.len % entrylen) != 0)
|
if (!entrylen || (prop->val.len % entrylen) != 0)
|
||||||
FAIL(c, dti, "\"reg\" property in %s has invalid length (%d bytes) "
|
FAIL_PROP(c, dti, node, prop, "property has invalid length (%d bytes) "
|
||||||
"(#address-cells == %d, #size-cells == %d)",
|
"(#address-cells == %d, #size-cells == %d)",
|
||||||
node->fullpath, prop->val.len, addr_cells, size_cells);
|
prop->val.len, addr_cells, size_cells);
|
||||||
}
|
}
|
||||||
WARNING(reg_format, check_reg_format, NULL, &addr_size_cells);
|
WARNING(reg_format, check_reg_format, NULL, &addr_size_cells);
|
||||||
|
|
||||||
|
@ -651,7 +728,7 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!node->parent) {
|
if (!node->parent) {
|
||||||
FAIL(c, dti, "Root node has a \"ranges\" property");
|
FAIL_PROP(c, dti, node, prop, "Root node has a \"ranges\" property");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -663,20 +740,20 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,
|
||||||
|
|
||||||
if (prop->val.len == 0) {
|
if (prop->val.len == 0) {
|
||||||
if (p_addr_cells != c_addr_cells)
|
if (p_addr_cells != c_addr_cells)
|
||||||
FAIL(c, dti, "%s has empty \"ranges\" property but its "
|
FAIL_PROP(c, dti, node, prop, "empty \"ranges\" property but its "
|
||||||
"#address-cells (%d) differs from %s (%d)",
|
"#address-cells (%d) differs from %s (%d)",
|
||||||
node->fullpath, c_addr_cells, node->parent->fullpath,
|
c_addr_cells, node->parent->fullpath,
|
||||||
p_addr_cells);
|
p_addr_cells);
|
||||||
if (p_size_cells != c_size_cells)
|
if (p_size_cells != c_size_cells)
|
||||||
FAIL(c, dti, "%s has empty \"ranges\" property but its "
|
FAIL_PROP(c, dti, node, prop, "empty \"ranges\" property but its "
|
||||||
"#size-cells (%d) differs from %s (%d)",
|
"#size-cells (%d) differs from %s (%d)",
|
||||||
node->fullpath, c_size_cells, node->parent->fullpath,
|
c_size_cells, node->parent->fullpath,
|
||||||
p_size_cells);
|
p_size_cells);
|
||||||
} else if ((prop->val.len % entrylen) != 0) {
|
} else if ((prop->val.len % entrylen) != 0) {
|
||||||
FAIL(c, dti, "\"ranges\" property in %s has invalid length (%d bytes) "
|
FAIL_PROP(c, dti, node, prop, "\"ranges\" property has invalid length (%d bytes) "
|
||||||
"(parent #address-cells == %d, child #address-cells == %d, "
|
"(parent #address-cells == %d, child #address-cells == %d, "
|
||||||
"#size-cells == %d)", node->fullpath, prop->val.len,
|
"#size-cells == %d)", prop->val.len,
|
||||||
p_addr_cells, c_addr_cells, c_size_cells);
|
p_addr_cells, c_addr_cells, c_size_cells);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells);
|
WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells);
|
||||||
|
@ -696,41 +773,33 @@ static void check_pci_bridge(struct check *c, struct dt_info *dti, struct node *
|
||||||
|
|
||||||
node->bus = &pci_bus;
|
node->bus = &pci_bus;
|
||||||
|
|
||||||
if (!strneq(node->name, "pci", node->basenamelen) &&
|
if (!strprefixeq(node->name, node->basenamelen, "pci") &&
|
||||||
!strneq(node->name, "pcie", node->basenamelen))
|
!strprefixeq(node->name, node->basenamelen, "pcie"))
|
||||||
FAIL(c, dti, "Node %s node name is not \"pci\" or \"pcie\"",
|
FAIL(c, dti, node, "node name is not \"pci\" or \"pcie\"");
|
||||||
node->fullpath);
|
|
||||||
|
|
||||||
prop = get_property(node, "ranges");
|
prop = get_property(node, "ranges");
|
||||||
if (!prop)
|
if (!prop)
|
||||||
FAIL(c, dti, "Node %s missing ranges for PCI bridge (or not a bridge)",
|
FAIL(c, dti, node, "missing ranges for PCI bridge (or not a bridge)");
|
||||||
node->fullpath);
|
|
||||||
|
|
||||||
if (node_addr_cells(node) != 3)
|
if (node_addr_cells(node) != 3)
|
||||||
FAIL(c, dti, "Node %s incorrect #address-cells for PCI bridge",
|
FAIL(c, dti, node, "incorrect #address-cells for PCI bridge");
|
||||||
node->fullpath);
|
|
||||||
if (node_size_cells(node) != 2)
|
if (node_size_cells(node) != 2)
|
||||||
FAIL(c, dti, "Node %s incorrect #size-cells for PCI bridge",
|
FAIL(c, dti, node, "incorrect #size-cells for PCI bridge");
|
||||||
node->fullpath);
|
|
||||||
|
|
||||||
prop = get_property(node, "bus-range");
|
prop = get_property(node, "bus-range");
|
||||||
if (!prop) {
|
if (!prop) {
|
||||||
FAIL(c, dti, "Node %s missing bus-range for PCI bridge",
|
FAIL(c, dti, node, "missing bus-range for PCI bridge");
|
||||||
node->fullpath);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (prop->val.len != (sizeof(cell_t) * 2)) {
|
if (prop->val.len != (sizeof(cell_t) * 2)) {
|
||||||
FAIL(c, dti, "Node %s bus-range must be 2 cells",
|
FAIL_PROP(c, dti, node, prop, "value must be 2 cells");
|
||||||
node->fullpath);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cells = (cell_t *)prop->val.val;
|
cells = (cell_t *)prop->val.val;
|
||||||
if (fdt32_to_cpu(cells[0]) > fdt32_to_cpu(cells[1]))
|
if (fdt32_to_cpu(cells[0]) > fdt32_to_cpu(cells[1]))
|
||||||
FAIL(c, dti, "Node %s bus-range 1st cell must be less than or equal to 2nd cell",
|
FAIL_PROP(c, dti, node, prop, "1st cell must be less than or equal to 2nd cell");
|
||||||
node->fullpath);
|
|
||||||
if (fdt32_to_cpu(cells[1]) > 0xff)
|
if (fdt32_to_cpu(cells[1]) > 0xff)
|
||||||
FAIL(c, dti, "Node %s bus-range maximum bus number must be less than 256",
|
FAIL_PROP(c, dti, node, prop, "maximum bus number must be less than 256");
|
||||||
node->fullpath);
|
|
||||||
}
|
}
|
||||||
WARNING(pci_bridge, check_pci_bridge, NULL,
|
WARNING(pci_bridge, check_pci_bridge, NULL,
|
||||||
&device_type_is_string, &addr_size_cells);
|
&device_type_is_string, &addr_size_cells);
|
||||||
|
@ -760,8 +829,8 @@ static void check_pci_device_bus_num(struct check *c, struct dt_info *dti, struc
|
||||||
max_bus = fdt32_to_cpu(cells[0]);
|
max_bus = fdt32_to_cpu(cells[0]);
|
||||||
}
|
}
|
||||||
if ((bus_num < min_bus) || (bus_num > max_bus))
|
if ((bus_num < min_bus) || (bus_num > max_bus))
|
||||||
FAIL(c, dti, "Node %s PCI bus number %d out of range, expected (%d - %d)",
|
FAIL_PROP(c, dti, node, prop, "PCI bus number %d out of range, expected (%d - %d)",
|
||||||
node->fullpath, bus_num, min_bus, max_bus);
|
bus_num, min_bus, max_bus);
|
||||||
}
|
}
|
||||||
WARNING(pci_device_bus_num, check_pci_device_bus_num, NULL, ®_format, &pci_bridge);
|
WARNING(pci_device_bus_num, check_pci_device_bus_num, NULL, ®_format, &pci_bridge);
|
||||||
|
|
||||||
|
@ -778,25 +847,22 @@ static void check_pci_device_reg(struct check *c, struct dt_info *dti, struct no
|
||||||
|
|
||||||
prop = get_property(node, "reg");
|
prop = get_property(node, "reg");
|
||||||
if (!prop) {
|
if (!prop) {
|
||||||
FAIL(c, dti, "Node %s missing PCI reg property", node->fullpath);
|
FAIL(c, dti, node, "missing PCI reg property");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cells = (cell_t *)prop->val.val;
|
cells = (cell_t *)prop->val.val;
|
||||||
if (cells[1] || cells[2])
|
if (cells[1] || cells[2])
|
||||||
FAIL(c, dti, "Node %s PCI reg config space address cells 2 and 3 must be 0",
|
FAIL_PROP(c, dti, node, prop, "PCI reg config space address cells 2 and 3 must be 0");
|
||||||
node->fullpath);
|
|
||||||
|
|
||||||
reg = fdt32_to_cpu(cells[0]);
|
reg = fdt32_to_cpu(cells[0]);
|
||||||
dev = (reg & 0xf800) >> 11;
|
dev = (reg & 0xf800) >> 11;
|
||||||
func = (reg & 0x700) >> 8;
|
func = (reg & 0x700) >> 8;
|
||||||
|
|
||||||
if (reg & 0xff000000)
|
if (reg & 0xff000000)
|
||||||
FAIL(c, dti, "Node %s PCI reg address is not configuration space",
|
FAIL_PROP(c, dti, node, prop, "PCI reg address is not configuration space");
|
||||||
node->fullpath);
|
|
||||||
if (reg & 0x000000ff)
|
if (reg & 0x000000ff)
|
||||||
FAIL(c, dti, "Node %s PCI reg config space address register number must be 0",
|
FAIL_PROP(c, dti, node, prop, "PCI reg config space address register number must be 0");
|
||||||
node->fullpath);
|
|
||||||
|
|
||||||
if (func == 0) {
|
if (func == 0) {
|
||||||
snprintf(unit_addr, sizeof(unit_addr), "%x", dev);
|
snprintf(unit_addr, sizeof(unit_addr), "%x", dev);
|
||||||
|
@ -808,8 +874,8 @@ static void check_pci_device_reg(struct check *c, struct dt_info *dti, struct no
|
||||||
if (streq(unitname, unit_addr))
|
if (streq(unitname, unit_addr))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
FAIL(c, dti, "Node %s PCI unit address format error, expected \"%s\"",
|
FAIL(c, dti, node, "PCI unit address format error, expected \"%s\"",
|
||||||
node->fullpath, unit_addr);
|
unit_addr);
|
||||||
}
|
}
|
||||||
WARNING(pci_device_reg, check_pci_device_reg, NULL, ®_format, &pci_bridge);
|
WARNING(pci_device_reg, check_pci_device_reg, NULL, ®_format, &pci_bridge);
|
||||||
|
|
||||||
|
@ -828,7 +894,7 @@ static bool node_is_compatible(struct node *node, const char *compat)
|
||||||
|
|
||||||
for (str = prop->val.val, end = str + prop->val.len; str < end;
|
for (str = prop->val.val, end = str + prop->val.len; str < end;
|
||||||
str += strnlen(str, end - str) + 1) {
|
str += strnlen(str, end - str) + 1) {
|
||||||
if (strneq(str, compat, end - str))
|
if (strprefixeq(str, end - str, compat))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -865,7 +931,7 @@ static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct no
|
||||||
|
|
||||||
if (!cells) {
|
if (!cells) {
|
||||||
if (node->parent->parent && !(node->bus == &simple_bus))
|
if (node->parent->parent && !(node->bus == &simple_bus))
|
||||||
FAIL(c, dti, "Node %s missing or empty reg/ranges property", node->fullpath);
|
FAIL(c, dti, node, "missing or empty reg/ranges property");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -875,8 +941,8 @@ static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct no
|
||||||
|
|
||||||
snprintf(unit_addr, sizeof(unit_addr), "%"PRIx64, reg);
|
snprintf(unit_addr, sizeof(unit_addr), "%"PRIx64, reg);
|
||||||
if (!streq(unitname, unit_addr))
|
if (!streq(unitname, unit_addr))
|
||||||
FAIL(c, dti, "Node %s simple-bus unit address format error, expected \"%s\"",
|
FAIL(c, dti, node, "simple-bus unit address format error, expected \"%s\"",
|
||||||
node->fullpath, unit_addr);
|
unit_addr);
|
||||||
}
|
}
|
||||||
WARNING(simple_bus_reg, check_simple_bus_reg, NULL, ®_format, &simple_bus_bridge);
|
WARNING(simple_bus_reg, check_simple_bus_reg, NULL, ®_format, &simple_bus_bridge);
|
||||||
|
|
||||||
|
@ -892,14 +958,12 @@ static void check_unit_address_format(struct check *c, struct dt_info *dti,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!strncmp(unitname, "0x", 2)) {
|
if (!strncmp(unitname, "0x", 2)) {
|
||||||
FAIL(c, dti, "Node %s unit name should not have leading \"0x\"",
|
FAIL(c, dti, node, "unit name should not have leading \"0x\"");
|
||||||
node->fullpath);
|
|
||||||
/* skip over 0x for next test */
|
/* skip over 0x for next test */
|
||||||
unitname += 2;
|
unitname += 2;
|
||||||
}
|
}
|
||||||
if (unitname[0] == '0' && isxdigit(unitname[1]))
|
if (unitname[0] == '0' && isxdigit(unitname[1]))
|
||||||
FAIL(c, dti, "Node %s unit name should not have leading 0s",
|
FAIL(c, dti, node, "unit name should not have leading 0s");
|
||||||
node->fullpath);
|
|
||||||
}
|
}
|
||||||
WARNING(unit_address_format, check_unit_address_format, NULL,
|
WARNING(unit_address_format, check_unit_address_format, NULL,
|
||||||
&node_name_format, &pci_bridge, &simple_bus_bridge);
|
&node_name_format, &pci_bridge, &simple_bus_bridge);
|
||||||
|
@ -922,16 +986,38 @@ static void check_avoid_default_addr_size(struct check *c, struct dt_info *dti,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (node->parent->addr_cells == -1)
|
if (node->parent->addr_cells == -1)
|
||||||
FAIL(c, dti, "Relying on default #address-cells value for %s",
|
FAIL(c, dti, node, "Relying on default #address-cells value");
|
||||||
node->fullpath);
|
|
||||||
|
|
||||||
if (node->parent->size_cells == -1)
|
if (node->parent->size_cells == -1)
|
||||||
FAIL(c, dti, "Relying on default #size-cells value for %s",
|
FAIL(c, dti, node, "Relying on default #size-cells value");
|
||||||
node->fullpath);
|
|
||||||
}
|
}
|
||||||
WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL,
|
WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL,
|
||||||
&addr_size_cells);
|
&addr_size_cells);
|
||||||
|
|
||||||
|
static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info *dti,
|
||||||
|
struct node *node)
|
||||||
|
{
|
||||||
|
struct property *prop;
|
||||||
|
struct node *child;
|
||||||
|
bool has_reg = false;
|
||||||
|
|
||||||
|
if (!node->parent || node->addr_cells < 0 || node->size_cells < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (get_property(node, "ranges") || !node->children)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for_each_child(node, child) {
|
||||||
|
prop = get_property(child, "reg");
|
||||||
|
if (prop)
|
||||||
|
has_reg = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!has_reg)
|
||||||
|
FAIL(c, dti, node, "unnecessary #address-cells/#size-cells without \"ranges\" or child \"reg\" property");
|
||||||
|
}
|
||||||
|
WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size);
|
||||||
|
|
||||||
static void check_obsolete_chosen_interrupt_controller(struct check *c,
|
static void check_obsolete_chosen_interrupt_controller(struct check *c,
|
||||||
struct dt_info *dti,
|
struct dt_info *dti,
|
||||||
struct node *node)
|
struct node *node)
|
||||||
|
@ -950,12 +1036,61 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c,
|
||||||
|
|
||||||
prop = get_property(chosen, "interrupt-controller");
|
prop = get_property(chosen, "interrupt-controller");
|
||||||
if (prop)
|
if (prop)
|
||||||
FAIL(c, dti, "/chosen has obsolete \"interrupt-controller\" "
|
FAIL_PROP(c, dti, node, prop,
|
||||||
"property");
|
"/chosen has obsolete \"interrupt-controller\" property");
|
||||||
}
|
}
|
||||||
WARNING(obsolete_chosen_interrupt_controller,
|
WARNING(obsolete_chosen_interrupt_controller,
|
||||||
check_obsolete_chosen_interrupt_controller, NULL);
|
check_obsolete_chosen_interrupt_controller, NULL);
|
||||||
|
|
||||||
|
static void check_chosen_node_is_root(struct check *c, struct dt_info *dti,
|
||||||
|
struct node *node)
|
||||||
|
{
|
||||||
|
if (!streq(node->name, "chosen"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (node->parent != dti->dt)
|
||||||
|
FAIL(c, dti, node, "chosen node must be at root node");
|
||||||
|
}
|
||||||
|
WARNING(chosen_node_is_root, check_chosen_node_is_root, NULL);
|
||||||
|
|
||||||
|
static void check_chosen_node_bootargs(struct check *c, struct dt_info *dti,
|
||||||
|
struct node *node)
|
||||||
|
{
|
||||||
|
struct property *prop;
|
||||||
|
|
||||||
|
if (!streq(node->name, "chosen"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
prop = get_property(node, "bootargs");
|
||||||
|
if (!prop)
|
||||||
|
return;
|
||||||
|
|
||||||
|
c->data = prop->name;
|
||||||
|
check_is_string(c, dti, node);
|
||||||
|
}
|
||||||
|
WARNING(chosen_node_bootargs, check_chosen_node_bootargs, NULL);
|
||||||
|
|
||||||
|
static void check_chosen_node_stdout_path(struct check *c, struct dt_info *dti,
|
||||||
|
struct node *node)
|
||||||
|
{
|
||||||
|
struct property *prop;
|
||||||
|
|
||||||
|
if (!streq(node->name, "chosen"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
prop = get_property(node, "stdout-path");
|
||||||
|
if (!prop) {
|
||||||
|
prop = get_property(node, "linux,stdout-path");
|
||||||
|
if (!prop)
|
||||||
|
return;
|
||||||
|
FAIL_PROP(c, dti, node, prop, "Use 'stdout-path' instead");
|
||||||
|
}
|
||||||
|
|
||||||
|
c->data = prop->name;
|
||||||
|
check_is_string(c, dti, node);
|
||||||
|
}
|
||||||
|
WARNING(chosen_node_stdout_path, check_chosen_node_stdout_path, NULL);
|
||||||
|
|
||||||
struct provider {
|
struct provider {
|
||||||
const char *prop_name;
|
const char *prop_name;
|
||||||
const char *cell_name;
|
const char *cell_name;
|
||||||
|
@ -972,8 +1107,9 @@ static void check_property_phandle_args(struct check *c,
|
||||||
int cell, cellsize = 0;
|
int cell, cellsize = 0;
|
||||||
|
|
||||||
if (prop->val.len % sizeof(cell_t)) {
|
if (prop->val.len % sizeof(cell_t)) {
|
||||||
FAIL(c, dti, "property '%s' size (%d) is invalid, expected multiple of %zu in node %s",
|
FAIL_PROP(c, dti, node, prop,
|
||||||
prop->name, prop->val.len, sizeof(cell_t), node->fullpath);
|
"property size (%d) is invalid, expected multiple of %zu",
|
||||||
|
prop->val.len, sizeof(cell_t));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1004,14 +1140,16 @@ static void check_property_phandle_args(struct check *c,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!m)
|
if (!m)
|
||||||
FAIL(c, dti, "Property '%s', cell %d is not a phandle reference in %s",
|
FAIL_PROP(c, dti, node, prop,
|
||||||
prop->name, cell, node->fullpath);
|
"cell %d is not a phandle reference",
|
||||||
|
cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
provider_node = get_node_by_phandle(root, phandle);
|
provider_node = get_node_by_phandle(root, phandle);
|
||||||
if (!provider_node) {
|
if (!provider_node) {
|
||||||
FAIL(c, dti, "Could not get phandle node for %s:%s(cell %d)",
|
FAIL_PROP(c, dti, node, prop,
|
||||||
node->fullpath, prop->name, cell);
|
"Could not get phandle node for (cell %d)",
|
||||||
|
cell);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1021,16 +1159,17 @@ static void check_property_phandle_args(struct check *c,
|
||||||
} else if (provider->optional) {
|
} else if (provider->optional) {
|
||||||
cellsize = 0;
|
cellsize = 0;
|
||||||
} else {
|
} else {
|
||||||
FAIL(c, dti, "Missing property '%s' in node %s or bad phandle (referred from %s:%s[%d])",
|
FAIL(c, dti, node, "Missing property '%s' in node %s or bad phandle (referred from %s[%d])",
|
||||||
provider->cell_name,
|
provider->cell_name,
|
||||||
provider_node->fullpath,
|
provider_node->fullpath,
|
||||||
node->fullpath, prop->name, cell);
|
prop->name, cell);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prop->val.len < ((cell + cellsize + 1) * sizeof(cell_t))) {
|
if (prop->val.len < ((cell + cellsize + 1) * sizeof(cell_t))) {
|
||||||
FAIL(c, dti, "%s property size (%d) too small for cell size %d in %s",
|
FAIL_PROP(c, dti, node, prop,
|
||||||
prop->name, prop->val.len, cellsize, node->fullpath);
|
"property size (%d) too small for cell size %d",
|
||||||
|
prop->val.len, cellsize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1066,7 +1205,7 @@ WARNING_PROPERTY_PHANDLE_CELLS(phys, "phys", "#phy-cells");
|
||||||
WARNING_PROPERTY_PHANDLE_CELLS(power_domains, "power-domains", "#power-domain-cells");
|
WARNING_PROPERTY_PHANDLE_CELLS(power_domains, "power-domains", "#power-domain-cells");
|
||||||
WARNING_PROPERTY_PHANDLE_CELLS(pwms, "pwms", "#pwm-cells");
|
WARNING_PROPERTY_PHANDLE_CELLS(pwms, "pwms", "#pwm-cells");
|
||||||
WARNING_PROPERTY_PHANDLE_CELLS(resets, "resets", "#reset-cells");
|
WARNING_PROPERTY_PHANDLE_CELLS(resets, "resets", "#reset-cells");
|
||||||
WARNING_PROPERTY_PHANDLE_CELLS(sound_dais, "sound-dais", "#sound-dai-cells");
|
WARNING_PROPERTY_PHANDLE_CELLS(sound_dai, "sound-dai", "#sound-dai-cells");
|
||||||
WARNING_PROPERTY_PHANDLE_CELLS(thermal_sensors, "thermal-sensors", "#thermal-sensor-cells");
|
WARNING_PROPERTY_PHANDLE_CELLS(thermal_sensors, "thermal-sensors", "#thermal-sensor-cells");
|
||||||
|
|
||||||
static bool prop_is_gpio(struct property *prop)
|
static bool prop_is_gpio(struct property *prop)
|
||||||
|
@ -1132,8 +1271,8 @@ static void check_deprecated_gpio_property(struct check *c,
|
||||||
if (!streq(str, "gpio"))
|
if (!streq(str, "gpio"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
FAIL(c, dti, "'[*-]gpio' is deprecated, use '[*-]gpios' instead for %s:%s",
|
FAIL_PROP(c, dti, node, prop,
|
||||||
node->fullpath, prop->name);
|
"'[*-]gpio' is deprecated, use '[*-]gpios' instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1167,9 +1306,8 @@ static void check_interrupts_property(struct check *c,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (irq_prop->val.len % sizeof(cell_t))
|
if (irq_prop->val.len % sizeof(cell_t))
|
||||||
FAIL(c, dti, "property '%s' size (%d) is invalid, expected multiple of %zu in node %s",
|
FAIL_PROP(c, dti, node, irq_prop, "size (%d) is invalid, expected multiple of %zu",
|
||||||
irq_prop->name, irq_prop->val.len, sizeof(cell_t),
|
irq_prop->val.len, sizeof(cell_t));
|
||||||
node->fullpath);
|
|
||||||
|
|
||||||
while (parent && !prop) {
|
while (parent && !prop) {
|
||||||
if (parent != node && node_is_interrupt_provider(parent)) {
|
if (parent != node && node_is_interrupt_provider(parent)) {
|
||||||
|
@ -1187,14 +1325,12 @@ static void check_interrupts_property(struct check *c,
|
||||||
|
|
||||||
irq_node = get_node_by_phandle(root, phandle);
|
irq_node = get_node_by_phandle(root, phandle);
|
||||||
if (!irq_node) {
|
if (!irq_node) {
|
||||||
FAIL(c, dti, "Bad interrupt-parent phandle for %s",
|
FAIL_PROP(c, dti, parent, prop, "Bad phandle");
|
||||||
node->fullpath);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!node_is_interrupt_provider(irq_node))
|
if (!node_is_interrupt_provider(irq_node))
|
||||||
FAIL(c, dti,
|
FAIL(c, dti, irq_node,
|
||||||
"Missing interrupt-controller or interrupt-map property in %s",
|
"Missing interrupt-controller or interrupt-map property");
|
||||||
irq_node->fullpath);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1203,23 +1339,21 @@ static void check_interrupts_property(struct check *c,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!irq_node) {
|
if (!irq_node) {
|
||||||
FAIL(c, dti, "Missing interrupt-parent for %s", node->fullpath);
|
FAIL(c, dti, node, "Missing interrupt-parent");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
prop = get_property(irq_node, "#interrupt-cells");
|
prop = get_property(irq_node, "#interrupt-cells");
|
||||||
if (!prop) {
|
if (!prop) {
|
||||||
FAIL(c, dti, "Missing #interrupt-cells in interrupt-parent %s",
|
FAIL(c, dti, irq_node, "Missing #interrupt-cells in interrupt-parent");
|
||||||
irq_node->fullpath);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
irq_cells = propval_cell(prop);
|
irq_cells = propval_cell(prop);
|
||||||
if (irq_prop->val.len % (irq_cells * sizeof(cell_t))) {
|
if (irq_prop->val.len % (irq_cells * sizeof(cell_t))) {
|
||||||
FAIL(c, dti,
|
FAIL_PROP(c, dti, node, prop,
|
||||||
"interrupts size is (%d), expected multiple of %d in %s",
|
"size is (%d), expected multiple of %d",
|
||||||
irq_prop->val.len, (int)(irq_cells * sizeof(cell_t)),
|
irq_prop->val.len, (int)(irq_cells * sizeof(cell_t)));
|
||||||
node->fullpath);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WARNING(interrupts_property, check_interrupts_property, &phandle_references);
|
WARNING(interrupts_property, check_interrupts_property, &phandle_references);
|
||||||
|
@ -1236,6 +1370,9 @@ static struct check *check_table[] = {
|
||||||
|
|
||||||
&address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
|
&address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
|
||||||
&device_type_is_string, &model_is_string, &status_is_string,
|
&device_type_is_string, &model_is_string, &status_is_string,
|
||||||
|
&label_is_string,
|
||||||
|
|
||||||
|
&compatible_is_string_list, &names_is_string_list,
|
||||||
|
|
||||||
&property_name_chars_strict,
|
&property_name_chars_strict,
|
||||||
&node_name_chars_strict,
|
&node_name_chars_strict,
|
||||||
|
@ -1253,7 +1390,9 @@ static struct check *check_table[] = {
|
||||||
&simple_bus_reg,
|
&simple_bus_reg,
|
||||||
|
|
||||||
&avoid_default_addr_size,
|
&avoid_default_addr_size,
|
||||||
|
&avoid_unnecessary_addr_size,
|
||||||
&obsolete_chosen_interrupt_controller,
|
&obsolete_chosen_interrupt_controller,
|
||||||
|
&chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path,
|
||||||
|
|
||||||
&clocks_property,
|
&clocks_property,
|
||||||
&cooling_device_property,
|
&cooling_device_property,
|
||||||
|
@ -1269,13 +1408,15 @@ static struct check *check_table[] = {
|
||||||
&power_domains_property,
|
&power_domains_property,
|
||||||
&pwms_property,
|
&pwms_property,
|
||||||
&resets_property,
|
&resets_property,
|
||||||
&sound_dais_property,
|
&sound_dai_property,
|
||||||
&thermal_sensors_property,
|
&thermal_sensors_property,
|
||||||
|
|
||||||
&deprecated_gpio_property,
|
&deprecated_gpio_property,
|
||||||
&gpios_property,
|
&gpios_property,
|
||||||
&interrupts_property,
|
&interrupts_property,
|
||||||
|
|
||||||
|
&alias_paths,
|
||||||
|
|
||||||
&always_fail,
|
&always_fail,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,125 +0,0 @@
|
||||||
/* A Bison parser, made by GNU Bison 3.0.4. */
|
|
||||||
|
|
||||||
/* Bison interface for Yacc-like parsers in C
|
|
||||||
|
|
||||||
Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This program 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 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program 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 program. If not, see <http://www.gnu.org/licenses/>. */
|
|
||||||
|
|
||||||
/* As a special exception, you may create a larger work that contains
|
|
||||||
part or all of the Bison parser skeleton and distribute that work
|
|
||||||
under terms of your choice, so long as that work isn't itself a
|
|
||||||
parser generator using the skeleton or a modified version thereof
|
|
||||||
as a parser skeleton. Alternatively, if you modify or redistribute
|
|
||||||
the parser skeleton itself, you may (at your option) remove this
|
|
||||||
special exception, which will cause the skeleton and the resulting
|
|
||||||
Bison output files to be licensed under the GNU General Public
|
|
||||||
License without this special exception.
|
|
||||||
|
|
||||||
This special exception was added by the Free Software Foundation in
|
|
||||||
version 2.2 of Bison. */
|
|
||||||
|
|
||||||
#ifndef YY_YY_DTC_PARSER_TAB_H_INCLUDED
|
|
||||||
# define YY_YY_DTC_PARSER_TAB_H_INCLUDED
|
|
||||||
/* Debug traces. */
|
|
||||||
#ifndef YYDEBUG
|
|
||||||
# define YYDEBUG 0
|
|
||||||
#endif
|
|
||||||
#if YYDEBUG
|
|
||||||
extern int yydebug;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Token type. */
|
|
||||||
#ifndef YYTOKENTYPE
|
|
||||||
# define YYTOKENTYPE
|
|
||||||
enum yytokentype
|
|
||||||
{
|
|
||||||
DT_V1 = 258,
|
|
||||||
DT_PLUGIN = 259,
|
|
||||||
DT_MEMRESERVE = 260,
|
|
||||||
DT_LSHIFT = 261,
|
|
||||||
DT_RSHIFT = 262,
|
|
||||||
DT_LE = 263,
|
|
||||||
DT_GE = 264,
|
|
||||||
DT_EQ = 265,
|
|
||||||
DT_NE = 266,
|
|
||||||
DT_AND = 267,
|
|
||||||
DT_OR = 268,
|
|
||||||
DT_BITS = 269,
|
|
||||||
DT_DEL_PROP = 270,
|
|
||||||
DT_DEL_NODE = 271,
|
|
||||||
DT_PROPNODENAME = 272,
|
|
||||||
DT_LITERAL = 273,
|
|
||||||
DT_CHAR_LITERAL = 274,
|
|
||||||
DT_BYTE = 275,
|
|
||||||
DT_STRING = 276,
|
|
||||||
DT_LABEL = 277,
|
|
||||||
DT_REF = 278,
|
|
||||||
DT_INCBIN = 279
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Value type. */
|
|
||||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
|
||||||
|
|
||||||
union YYSTYPE
|
|
||||||
{
|
|
||||||
#line 39 "dtc-parser.y" /* yacc.c:1909 */
|
|
||||||
|
|
||||||
char *propnodename;
|
|
||||||
char *labelref;
|
|
||||||
uint8_t byte;
|
|
||||||
struct data data;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
struct data data;
|
|
||||||
int bits;
|
|
||||||
} array;
|
|
||||||
|
|
||||||
struct property *prop;
|
|
||||||
struct property *proplist;
|
|
||||||
struct node *node;
|
|
||||||
struct node *nodelist;
|
|
||||||
struct reserve_info *re;
|
|
||||||
uint64_t integer;
|
|
||||||
unsigned int flags;
|
|
||||||
|
|
||||||
#line 99 "dtc-parser.tab.h" /* yacc.c:1909 */
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef union YYSTYPE YYSTYPE;
|
|
||||||
# define YYSTYPE_IS_TRIVIAL 1
|
|
||||||
# define YYSTYPE_IS_DECLARED 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Location type. */
|
|
||||||
#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
|
|
||||||
typedef struct YYLTYPE YYLTYPE;
|
|
||||||
struct YYLTYPE
|
|
||||||
{
|
|
||||||
int first_line;
|
|
||||||
int first_column;
|
|
||||||
int last_line;
|
|
||||||
int last_column;
|
|
||||||
};
|
|
||||||
# define YYLTYPE_IS_DECLARED 1
|
|
||||||
# define YYLTYPE_IS_TRIVIAL 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
extern YYSTYPE yylval;
|
|
||||||
extern YYLTYPE yylloc;
|
|
||||||
int yyparse (void);
|
|
||||||
|
|
||||||
#endif /* !YY_YY_DTC_PARSER_TAB_H_INCLUDED */
|
|
|
@ -166,7 +166,17 @@ devicetree:
|
||||||
{
|
{
|
||||||
$$ = merge_nodes($1, $3);
|
$$ = merge_nodes($1, $3);
|
||||||
}
|
}
|
||||||
|
| DT_REF nodedef
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* We rely on the rule being always:
|
||||||
|
* versioninfo plugindecl memreserves devicetree
|
||||||
|
* so $-1 is what we want (plugindecl)
|
||||||
|
*/
|
||||||
|
if (!($<flags>-1 & DTSF_PLUGIN))
|
||||||
|
ERROR(&@2, "Label or path %s not found", $1);
|
||||||
|
$$ = add_orphan_node(name_node(build_node(NULL, NULL), ""), $2, $1);
|
||||||
|
}
|
||||||
| devicetree DT_LABEL DT_REF nodedef
|
| devicetree DT_LABEL DT_REF nodedef
|
||||||
{
|
{
|
||||||
struct node *target = get_node_by_ref($1, $3);
|
struct node *target = get_node_by_ref($1, $3);
|
||||||
|
@ -209,11 +219,6 @@ devicetree:
|
||||||
|
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
}
|
}
|
||||||
| /* empty */
|
|
||||||
{
|
|
||||||
/* build empty node */
|
|
||||||
$$ = name_node(build_node(NULL, NULL), "");
|
|
||||||
}
|
|
||||||
;
|
;
|
||||||
|
|
||||||
nodedef:
|
nodedef:
|
||||||
|
|
|
@ -59,8 +59,6 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Usage related data. */
|
/* Usage related data. */
|
||||||
#define FDT_VERSION(version) _FDT_VERSION(version)
|
|
||||||
#define _FDT_VERSION(version) #version
|
|
||||||
static const char usage_synopsis[] = "dtc [options] <input file>";
|
static const char usage_synopsis[] = "dtc [options] <input file>";
|
||||||
static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@Ahv";
|
static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@Ahv";
|
||||||
static struct option const usage_long_opts[] = {
|
static struct option const usage_long_opts[] = {
|
||||||
|
@ -98,7 +96,7 @@ static const char * const usage_opts_help[] = {
|
||||||
"\t\tdts - device tree source text\n"
|
"\t\tdts - device tree source text\n"
|
||||||
"\t\tdtb - device tree blob\n"
|
"\t\tdtb - device tree blob\n"
|
||||||
"\t\tasm - assembler source",
|
"\t\tasm - assembler source",
|
||||||
"\n\tBlob version to produce, defaults to "FDT_VERSION(DEFAULT_FDT_VERSION)" (for dtb and asm output)",
|
"\n\tBlob version to produce, defaults to "stringify(DEFAULT_FDT_VERSION)" (for dtb and asm output)",
|
||||||
"\n\tOutput dependency file",
|
"\n\tOutput dependency file",
|
||||||
"\n\tMake space for <number> reserve map entries (for dtb and asm output)",
|
"\n\tMake space for <number> reserve map entries (for dtb and asm output)",
|
||||||
"\n\tMake the blob at least <bytes> long (extra space)",
|
"\n\tMake the blob at least <bytes> long (extra space)",
|
||||||
|
@ -319,13 +317,14 @@ int main(int argc, char *argv[])
|
||||||
dti->boot_cpuid_phys = cmdline_boot_cpuid;
|
dti->boot_cpuid_phys = cmdline_boot_cpuid;
|
||||||
|
|
||||||
fill_fullpaths(dti->dt, "");
|
fill_fullpaths(dti->dt, "");
|
||||||
process_checks(force, dti);
|
|
||||||
|
|
||||||
/* on a plugin, generate by default */
|
/* on a plugin, generate by default */
|
||||||
if (dti->dtsflags & DTSF_PLUGIN) {
|
if (dti->dtsflags & DTSF_PLUGIN) {
|
||||||
generate_fixups = 1;
|
generate_fixups = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
process_checks(force, dti);
|
||||||
|
|
||||||
if (auto_label_aliases)
|
if (auto_label_aliases)
|
||||||
generate_label_tree(dti, "aliases", false);
|
generate_label_tree(dti, "aliases", false);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef _DTC_H
|
#ifndef DTC_H
|
||||||
#define _DTC_H
|
#define DTC_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
|
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
|
||||||
|
@ -67,7 +67,8 @@ typedef uint32_t cell_t;
|
||||||
|
|
||||||
|
|
||||||
#define streq(a, b) (strcmp((a), (b)) == 0)
|
#define streq(a, b) (strcmp((a), (b)) == 0)
|
||||||
#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
|
#define strstarts(s, prefix) (strncmp((s), (prefix), strlen(prefix)) == 0)
|
||||||
|
#define strprefixeq(a, n, b) (strlen(b) == (n) && (memcmp(a, b, n) == 0))
|
||||||
|
|
||||||
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
|
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
|
||||||
|
|
||||||
|
@ -203,7 +204,7 @@ struct node *build_node_delete(void);
|
||||||
struct node *name_node(struct node *node, char *name);
|
struct node *name_node(struct node *node, char *name);
|
||||||
struct node *chain_node(struct node *first, struct node *list);
|
struct node *chain_node(struct node *first, struct node *list);
|
||||||
struct node *merge_nodes(struct node *old_node, struct node *new_node);
|
struct node *merge_nodes(struct node *old_node, struct node *new_node);
|
||||||
void add_orphan_node(struct node *old_node, struct node *new_node, char *ref);
|
struct node *add_orphan_node(struct node *old_node, struct node *new_node, char *ref);
|
||||||
|
|
||||||
void add_property(struct node *node, struct property *prop);
|
void add_property(struct node *node, struct property *prop);
|
||||||
void delete_property_by_name(struct node *node, char *name);
|
void delete_property_by_name(struct node *node, char *name);
|
||||||
|
@ -289,4 +290,4 @@ struct dt_info *dt_from_source(const char *f);
|
||||||
|
|
||||||
struct dt_info *dt_from_fs(const char *dirname);
|
struct dt_info *dt_from_fs(const char *dirname);
|
||||||
|
|
||||||
#endif /* _DTC_H */
|
#endif /* DTC_H */
|
||||||
|
|
|
@ -731,7 +731,7 @@ static char *nodename_from_path(const char *ppath, const char *cpath)
|
||||||
|
|
||||||
plen = strlen(ppath);
|
plen = strlen(ppath);
|
||||||
|
|
||||||
if (!strneq(ppath, cpath, plen))
|
if (!strstarts(cpath, ppath))
|
||||||
die("Path \"%s\" is not valid as a child of \"%s\"\n",
|
die("Path \"%s\" is not valid as a child of \"%s\"\n",
|
||||||
cpath, ppath);
|
cpath, ppath);
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,7 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
|
||||||
|| ((offset + len) > fdt_size_dt_struct(fdt)))
|
|| ((offset + len) > fdt_size_dt_struct(fdt)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return _fdt_offset_ptr(fdt, offset);
|
return fdt_offset_ptr_(fdt, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
|
uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
|
||||||
|
@ -123,6 +123,9 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
|
||||||
/* skip-name offset, length and value */
|
/* skip-name offset, length and value */
|
||||||
offset += sizeof(struct fdt_property) - FDT_TAGSIZE
|
offset += sizeof(struct fdt_property) - FDT_TAGSIZE
|
||||||
+ fdt32_to_cpu(*lenp);
|
+ fdt32_to_cpu(*lenp);
|
||||||
|
if (fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
|
||||||
|
((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
|
||||||
|
offset += 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FDT_END:
|
case FDT_END:
|
||||||
|
@ -141,7 +144,7 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _fdt_check_node_offset(const void *fdt, int offset)
|
int fdt_check_node_offset_(const void *fdt, int offset)
|
||||||
{
|
{
|
||||||
if ((offset < 0) || (offset % FDT_TAGSIZE)
|
if ((offset < 0) || (offset % FDT_TAGSIZE)
|
||||||
|| (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
|
|| (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
|
||||||
|
@ -150,7 +153,7 @@ int _fdt_check_node_offset(const void *fdt, int offset)
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _fdt_check_prop_offset(const void *fdt, int offset)
|
int fdt_check_prop_offset_(const void *fdt, int offset)
|
||||||
{
|
{
|
||||||
if ((offset < 0) || (offset % FDT_TAGSIZE)
|
if ((offset < 0) || (offset % FDT_TAGSIZE)
|
||||||
|| (fdt_next_tag(fdt, offset, &offset) != FDT_PROP))
|
|| (fdt_next_tag(fdt, offset, &offset) != FDT_PROP))
|
||||||
|
@ -165,7 +168,7 @@ int fdt_next_node(const void *fdt, int offset, int *depth)
|
||||||
uint32_t tag;
|
uint32_t tag;
|
||||||
|
|
||||||
if (offset >= 0)
|
if (offset >= 0)
|
||||||
if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0)
|
if ((nextoffset = fdt_check_node_offset_(fdt, offset)) < 0)
|
||||||
return nextoffset;
|
return nextoffset;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@ -227,7 +230,7 @@ int fdt_next_subnode(const void *fdt, int offset)
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
|
const char *fdt_find_string_(const char *strtab, int tabsize, const char *s)
|
||||||
{
|
{
|
||||||
int len = strlen(s) + 1;
|
int len = strlen(s) + 1;
|
||||||
const char *last = strtab + tabsize - len;
|
const char *last = strtab + tabsize - len;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef _FDT_H
|
#ifndef FDT_H
|
||||||
#define _FDT_H
|
#define FDT_H
|
||||||
/*
|
/*
|
||||||
* libfdt - Flat Device Tree manipulation
|
* libfdt - Flat Device Tree manipulation
|
||||||
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
||||||
|
@ -108,4 +108,4 @@ struct fdt_property {
|
||||||
#define FDT_V16_SIZE FDT_V3_SIZE
|
#define FDT_V16_SIZE FDT_V3_SIZE
|
||||||
#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(fdt32_t))
|
#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(fdt32_t))
|
||||||
|
|
||||||
#endif /* _FDT_H */
|
#endif /* FDT_H */
|
||||||
|
|
|
@ -1,3 +1,54 @@
|
||||||
|
/*
|
||||||
|
* libfdt - Flat Device Tree manipulation
|
||||||
|
* Copyright (C) 2016 Free Electrons
|
||||||
|
* Copyright (C) 2016 NextThing Co.
|
||||||
|
*
|
||||||
|
* libfdt is dual licensed: you can use it either under the terms of
|
||||||
|
* the GPL, or the BSD license, at your option.
|
||||||
|
*
|
||||||
|
* a) This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public
|
||||||
|
* License along with this library; if not, write to the Free
|
||||||
|
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* Alternatively,
|
||||||
|
*
|
||||||
|
* b) Redistribution and use in source and binary forms, with or
|
||||||
|
* without modification, are permitted provided that the following
|
||||||
|
* conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above
|
||||||
|
* copyright notice, this list of conditions and the following
|
||||||
|
* disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following
|
||||||
|
* disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||||
|
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||||
|
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||||
|
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||||
|
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
#include "libfdt_env.h"
|
#include "libfdt_env.h"
|
||||||
|
|
||||||
#include <fdt.h>
|
#include <fdt.h>
|
||||||
|
|
|
@ -55,12 +55,13 @@
|
||||||
|
|
||||||
#include "libfdt_internal.h"
|
#include "libfdt_internal.h"
|
||||||
|
|
||||||
static int _fdt_nodename_eq(const void *fdt, int offset,
|
static int fdt_nodename_eq_(const void *fdt, int offset,
|
||||||
const char *s, int len)
|
const char *s, int len)
|
||||||
{
|
{
|
||||||
const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
|
int olen;
|
||||||
|
const char *p = fdt_get_name(fdt, offset, &olen);
|
||||||
|
|
||||||
if (!p)
|
if (!p || olen < len)
|
||||||
/* short match */
|
/* short match */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -80,7 +81,7 @@ const char *fdt_string(const void *fdt, int stroffset)
|
||||||
return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
|
return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _fdt_string_eq(const void *fdt, int stroffset,
|
static int fdt_string_eq_(const void *fdt, int stroffset,
|
||||||
const char *s, int len)
|
const char *s, int len)
|
||||||
{
|
{
|
||||||
const char *p = fdt_string(fdt, stroffset);
|
const char *p = fdt_string(fdt, stroffset);
|
||||||
|
@ -117,8 +118,8 @@ uint32_t fdt_get_max_phandle(const void *fdt)
|
||||||
int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
|
int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
|
||||||
{
|
{
|
||||||
FDT_CHECK_HEADER(fdt);
|
FDT_CHECK_HEADER(fdt);
|
||||||
*address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address);
|
*address = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->address);
|
||||||
*size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size);
|
*size = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->size);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,12 +127,12 @@ int fdt_num_mem_rsv(const void *fdt)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0)
|
while (fdt64_to_cpu(fdt_mem_rsv_(fdt, i)->size) != 0)
|
||||||
i++;
|
i++;
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _nextprop(const void *fdt, int offset)
|
static int nextprop_(const void *fdt, int offset)
|
||||||
{
|
{
|
||||||
uint32_t tag;
|
uint32_t tag;
|
||||||
int nextoffset;
|
int nextoffset;
|
||||||
|
@ -166,7 +167,7 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset,
|
||||||
(offset >= 0) && (depth >= 0);
|
(offset >= 0) && (depth >= 0);
|
||||||
offset = fdt_next_node(fdt, offset, &depth))
|
offset = fdt_next_node(fdt, offset, &depth))
|
||||||
if ((depth == 1)
|
if ((depth == 1)
|
||||||
&& _fdt_nodename_eq(fdt, offset, name, namelen))
|
&& fdt_nodename_eq_(fdt, offset, name, namelen))
|
||||||
return offset;
|
return offset;
|
||||||
|
|
||||||
if (depth < 0)
|
if (depth < 0)
|
||||||
|
@ -232,17 +233,35 @@ int fdt_path_offset(const void *fdt, const char *path)
|
||||||
|
|
||||||
const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
|
const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
|
||||||
{
|
{
|
||||||
const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset);
|
const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset);
|
||||||
|
const char *nameptr;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (((err = fdt_check_header(fdt)) != 0)
|
if (((err = fdt_check_header(fdt)) != 0)
|
||||||
|| ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
|
|| ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (len)
|
nameptr = nh->name;
|
||||||
*len = strlen(nh->name);
|
|
||||||
|
|
||||||
return nh->name;
|
if (fdt_version(fdt) < 0x10) {
|
||||||
|
/*
|
||||||
|
* For old FDT versions, match the naming conventions of V16:
|
||||||
|
* give only the leaf name (after all /). The actual tree
|
||||||
|
* contents are loosely checked.
|
||||||
|
*/
|
||||||
|
const char *leaf;
|
||||||
|
leaf = strrchr(nameptr, '/');
|
||||||
|
if (leaf == NULL) {
|
||||||
|
err = -FDT_ERR_BADSTRUCTURE;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
nameptr = leaf+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len)
|
||||||
|
*len = strlen(nameptr);
|
||||||
|
|
||||||
|
return nameptr;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
if (len)
|
if (len)
|
||||||
|
@ -254,34 +273,34 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset)
|
||||||
{
|
{
|
||||||
int offset;
|
int offset;
|
||||||
|
|
||||||
if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
|
if ((offset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
|
||||||
return offset;
|
return offset;
|
||||||
|
|
||||||
return _nextprop(fdt, offset);
|
return nextprop_(fdt, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fdt_next_property_offset(const void *fdt, int offset)
|
int fdt_next_property_offset(const void *fdt, int offset)
|
||||||
{
|
{
|
||||||
if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0)
|
if ((offset = fdt_check_prop_offset_(fdt, offset)) < 0)
|
||||||
return offset;
|
return offset;
|
||||||
|
|
||||||
return _nextprop(fdt, offset);
|
return nextprop_(fdt, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
|
static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
|
||||||
int offset,
|
int offset,
|
||||||
int *lenp)
|
int *lenp)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
const struct fdt_property *prop;
|
const struct fdt_property *prop;
|
||||||
|
|
||||||
if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) {
|
if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) {
|
||||||
if (lenp)
|
if (lenp)
|
||||||
*lenp = err;
|
*lenp = err;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
prop = _fdt_offset_ptr(fdt, offset);
|
prop = fdt_offset_ptr_(fdt, offset);
|
||||||
|
|
||||||
if (lenp)
|
if (lenp)
|
||||||
*lenp = fdt32_to_cpu(prop->len);
|
*lenp = fdt32_to_cpu(prop->len);
|
||||||
|
@ -289,23 +308,44 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
|
||||||
return prop;
|
return prop;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct fdt_property *fdt_get_property_namelen(const void *fdt,
|
const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
|
||||||
int offset,
|
int offset,
|
||||||
const char *name,
|
int *lenp)
|
||||||
int namelen, int *lenp)
|
{
|
||||||
|
/* Prior to version 16, properties may need realignment
|
||||||
|
* and this API does not work. fdt_getprop_*() will, however. */
|
||||||
|
|
||||||
|
if (fdt_version(fdt) < 0x10) {
|
||||||
|
if (lenp)
|
||||||
|
*lenp = -FDT_ERR_BADVERSION;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fdt_get_property_by_offset_(fdt, offset, lenp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
|
||||||
|
int offset,
|
||||||
|
const char *name,
|
||||||
|
int namelen,
|
||||||
|
int *lenp,
|
||||||
|
int *poffset)
|
||||||
{
|
{
|
||||||
for (offset = fdt_first_property_offset(fdt, offset);
|
for (offset = fdt_first_property_offset(fdt, offset);
|
||||||
(offset >= 0);
|
(offset >= 0);
|
||||||
(offset = fdt_next_property_offset(fdt, offset))) {
|
(offset = fdt_next_property_offset(fdt, offset))) {
|
||||||
const struct fdt_property *prop;
|
const struct fdt_property *prop;
|
||||||
|
|
||||||
if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) {
|
if (!(prop = fdt_get_property_by_offset_(fdt, offset, lenp))) {
|
||||||
offset = -FDT_ERR_INTERNAL;
|
offset = -FDT_ERR_INTERNAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff),
|
if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff),
|
||||||
name, namelen))
|
name, namelen)) {
|
||||||
|
if (poffset)
|
||||||
|
*poffset = offset;
|
||||||
return prop;
|
return prop;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lenp)
|
if (lenp)
|
||||||
|
@ -313,6 +353,25 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const struct fdt_property *fdt_get_property_namelen(const void *fdt,
|
||||||
|
int offset,
|
||||||
|
const char *name,
|
||||||
|
int namelen, int *lenp)
|
||||||
|
{
|
||||||
|
/* Prior to version 16, properties may need realignment
|
||||||
|
* and this API does not work. fdt_getprop_*() will, however. */
|
||||||
|
if (fdt_version(fdt) < 0x10) {
|
||||||
|
if (lenp)
|
||||||
|
*lenp = -FDT_ERR_BADVERSION;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fdt_get_property_namelen_(fdt, offset, name, namelen, lenp,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const struct fdt_property *fdt_get_property(const void *fdt,
|
const struct fdt_property *fdt_get_property(const void *fdt,
|
||||||
int nodeoffset,
|
int nodeoffset,
|
||||||
const char *name, int *lenp)
|
const char *name, int *lenp)
|
||||||
|
@ -324,12 +383,18 @@ const struct fdt_property *fdt_get_property(const void *fdt,
|
||||||
const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
|
const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
|
||||||
const char *name, int namelen, int *lenp)
|
const char *name, int namelen, int *lenp)
|
||||||
{
|
{
|
||||||
|
int poffset;
|
||||||
const struct fdt_property *prop;
|
const struct fdt_property *prop;
|
||||||
|
|
||||||
prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
|
prop = fdt_get_property_namelen_(fdt, nodeoffset, name, namelen, lenp,
|
||||||
|
&poffset);
|
||||||
if (!prop)
|
if (!prop)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
/* Handle realignment */
|
||||||
|
if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 &&
|
||||||
|
fdt32_to_cpu(prop->len) >= 8)
|
||||||
|
return prop->data + 4;
|
||||||
return prop->data;
|
return prop->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,11 +403,16 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
|
||||||
{
|
{
|
||||||
const struct fdt_property *prop;
|
const struct fdt_property *prop;
|
||||||
|
|
||||||
prop = fdt_get_property_by_offset(fdt, offset, lenp);
|
prop = fdt_get_property_by_offset_(fdt, offset, lenp);
|
||||||
if (!prop)
|
if (!prop)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (namep)
|
if (namep)
|
||||||
*namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
|
*namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
|
||||||
|
|
||||||
|
/* Handle realignment */
|
||||||
|
if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 &&
|
||||||
|
fdt32_to_cpu(prop->len) >= 8)
|
||||||
|
return prop->data + 4;
|
||||||
return prop->data;
|
return prop->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,8 +55,8 @@
|
||||||
|
|
||||||
#include "libfdt_internal.h"
|
#include "libfdt_internal.h"
|
||||||
|
|
||||||
static int _fdt_blocks_misordered(const void *fdt,
|
static int fdt_blocks_misordered_(const void *fdt,
|
||||||
int mem_rsv_size, int struct_size)
|
int mem_rsv_size, int struct_size)
|
||||||
{
|
{
|
||||||
return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8))
|
return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8))
|
||||||
|| (fdt_off_dt_struct(fdt) <
|
|| (fdt_off_dt_struct(fdt) <
|
||||||
|
@ -67,13 +67,13 @@ static int _fdt_blocks_misordered(const void *fdt,
|
||||||
(fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
|
(fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _fdt_rw_check_header(void *fdt)
|
static int fdt_rw_check_header_(void *fdt)
|
||||||
{
|
{
|
||||||
FDT_CHECK_HEADER(fdt);
|
FDT_CHECK_HEADER(fdt);
|
||||||
|
|
||||||
if (fdt_version(fdt) < 17)
|
if (fdt_version(fdt) < 17)
|
||||||
return -FDT_ERR_BADVERSION;
|
return -FDT_ERR_BADVERSION;
|
||||||
if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry),
|
if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry),
|
||||||
fdt_size_dt_struct(fdt)))
|
fdt_size_dt_struct(fdt)))
|
||||||
return -FDT_ERR_BADLAYOUT;
|
return -FDT_ERR_BADLAYOUT;
|
||||||
if (fdt_version(fdt) > 17)
|
if (fdt_version(fdt) > 17)
|
||||||
|
@ -84,20 +84,20 @@ static int _fdt_rw_check_header(void *fdt)
|
||||||
|
|
||||||
#define FDT_RW_CHECK_HEADER(fdt) \
|
#define FDT_RW_CHECK_HEADER(fdt) \
|
||||||
{ \
|
{ \
|
||||||
int __err; \
|
int err_; \
|
||||||
if ((__err = _fdt_rw_check_header(fdt)) != 0) \
|
if ((err_ = fdt_rw_check_header_(fdt)) != 0) \
|
||||||
return __err; \
|
return err_; \
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int _fdt_data_size(void *fdt)
|
static inline int fdt_data_size_(void *fdt)
|
||||||
{
|
{
|
||||||
return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
|
return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)
|
static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen)
|
||||||
{
|
{
|
||||||
char *p = splicepoint;
|
char *p = splicepoint;
|
||||||
char *end = (char *)fdt + _fdt_data_size(fdt);
|
char *end = (char *)fdt + fdt_data_size_(fdt);
|
||||||
|
|
||||||
if (((p + oldlen) < p) || ((p + oldlen) > end))
|
if (((p + oldlen) < p) || ((p + oldlen) > end))
|
||||||
return -FDT_ERR_BADOFFSET;
|
return -FDT_ERR_BADOFFSET;
|
||||||
|
@ -109,12 +109,12 @@ static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
|
static int fdt_splice_mem_rsv_(void *fdt, struct fdt_reserve_entry *p,
|
||||||
int oldn, int newn)
|
int oldn, int newn)
|
||||||
{
|
{
|
||||||
int delta = (newn - oldn) * sizeof(*p);
|
int delta = (newn - oldn) * sizeof(*p);
|
||||||
int err;
|
int err;
|
||||||
err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
|
err = fdt_splice_(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta);
|
fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta);
|
||||||
|
@ -122,13 +122,13 @@ static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _fdt_splice_struct(void *fdt, void *p,
|
static int fdt_splice_struct_(void *fdt, void *p,
|
||||||
int oldlen, int newlen)
|
int oldlen, int newlen)
|
||||||
{
|
{
|
||||||
int delta = newlen - oldlen;
|
int delta = newlen - oldlen;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if ((err = _fdt_splice(fdt, p, oldlen, newlen)))
|
if ((err = fdt_splice_(fdt, p, oldlen, newlen)))
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
|
fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
|
||||||
|
@ -136,20 +136,20 @@ static int _fdt_splice_struct(void *fdt, void *p,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _fdt_splice_string(void *fdt, int newlen)
|
static int fdt_splice_string_(void *fdt, int newlen)
|
||||||
{
|
{
|
||||||
void *p = (char *)fdt
|
void *p = (char *)fdt
|
||||||
+ fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
|
+ fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if ((err = _fdt_splice(fdt, p, 0, newlen)))
|
if ((err = fdt_splice_(fdt, p, 0, newlen)))
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);
|
fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _fdt_find_add_string(void *fdt, const char *s)
|
static int fdt_find_add_string_(void *fdt, const char *s)
|
||||||
{
|
{
|
||||||
char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
|
char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
|
||||||
const char *p;
|
const char *p;
|
||||||
|
@ -157,13 +157,13 @@ static int _fdt_find_add_string(void *fdt, const char *s)
|
||||||
int len = strlen(s) + 1;
|
int len = strlen(s) + 1;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s);
|
p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s);
|
||||||
if (p)
|
if (p)
|
||||||
/* found it */
|
/* found it */
|
||||||
return (p - strtab);
|
return (p - strtab);
|
||||||
|
|
||||||
new = strtab + fdt_size_dt_strings(fdt);
|
new = strtab + fdt_size_dt_strings(fdt);
|
||||||
err = _fdt_splice_string(fdt, len);
|
err = fdt_splice_string_(fdt, len);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -178,8 +178,8 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
|
||||||
|
|
||||||
FDT_RW_CHECK_HEADER(fdt);
|
FDT_RW_CHECK_HEADER(fdt);
|
||||||
|
|
||||||
re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt));
|
re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt));
|
||||||
err = _fdt_splice_mem_rsv(fdt, re, 0, 1);
|
err = fdt_splice_mem_rsv_(fdt, re, 0, 1);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -190,17 +190,17 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
|
||||||
|
|
||||||
int fdt_del_mem_rsv(void *fdt, int n)
|
int fdt_del_mem_rsv(void *fdt, int n)
|
||||||
{
|
{
|
||||||
struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n);
|
struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n);
|
||||||
|
|
||||||
FDT_RW_CHECK_HEADER(fdt);
|
FDT_RW_CHECK_HEADER(fdt);
|
||||||
|
|
||||||
if (n >= fdt_num_mem_rsv(fdt))
|
if (n >= fdt_num_mem_rsv(fdt))
|
||||||
return -FDT_ERR_NOTFOUND;
|
return -FDT_ERR_NOTFOUND;
|
||||||
|
|
||||||
return _fdt_splice_mem_rsv(fdt, re, 1, 0);
|
return fdt_splice_mem_rsv_(fdt, re, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
|
static int fdt_resize_property_(void *fdt, int nodeoffset, const char *name,
|
||||||
int len, struct fdt_property **prop)
|
int len, struct fdt_property **prop)
|
||||||
{
|
{
|
||||||
int oldlen;
|
int oldlen;
|
||||||
|
@ -210,7 +210,7 @@ static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
|
||||||
if (!*prop)
|
if (!*prop)
|
||||||
return oldlen;
|
return oldlen;
|
||||||
|
|
||||||
if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
|
if ((err = fdt_splice_struct_(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
|
||||||
FDT_TAGALIGN(len))))
|
FDT_TAGALIGN(len))))
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -218,7 +218,7 @@ static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _fdt_add_property(void *fdt, int nodeoffset, const char *name,
|
static int fdt_add_property_(void *fdt, int nodeoffset, const char *name,
|
||||||
int len, struct fdt_property **prop)
|
int len, struct fdt_property **prop)
|
||||||
{
|
{
|
||||||
int proplen;
|
int proplen;
|
||||||
|
@ -226,17 +226,17 @@ static int _fdt_add_property(void *fdt, int nodeoffset, const char *name,
|
||||||
int namestroff;
|
int namestroff;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
|
if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
|
||||||
return nextoffset;
|
return nextoffset;
|
||||||
|
|
||||||
namestroff = _fdt_find_add_string(fdt, name);
|
namestroff = fdt_find_add_string_(fdt, name);
|
||||||
if (namestroff < 0)
|
if (namestroff < 0)
|
||||||
return namestroff;
|
return namestroff;
|
||||||
|
|
||||||
*prop = _fdt_offset_ptr_w(fdt, nextoffset);
|
*prop = fdt_offset_ptr_w_(fdt, nextoffset);
|
||||||
proplen = sizeof(**prop) + FDT_TAGALIGN(len);
|
proplen = sizeof(**prop) + FDT_TAGALIGN(len);
|
||||||
|
|
||||||
err = _fdt_splice_struct(fdt, *prop, 0, proplen);
|
err = fdt_splice_struct_(fdt, *prop, 0, proplen);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -260,7 +260,7 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name)
|
||||||
|
|
||||||
newlen = strlen(name);
|
newlen = strlen(name);
|
||||||
|
|
||||||
err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1),
|
err = fdt_splice_struct_(fdt, namep, FDT_TAGALIGN(oldlen+1),
|
||||||
FDT_TAGALIGN(newlen+1));
|
FDT_TAGALIGN(newlen+1));
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
@ -277,9 +277,9 @@ int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
|
||||||
|
|
||||||
FDT_RW_CHECK_HEADER(fdt);
|
FDT_RW_CHECK_HEADER(fdt);
|
||||||
|
|
||||||
err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop);
|
err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop);
|
||||||
if (err == -FDT_ERR_NOTFOUND)
|
if (err == -FDT_ERR_NOTFOUND)
|
||||||
err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
|
err = fdt_add_property_(fdt, nodeoffset, name, len, &prop);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -313,7 +313,7 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
|
||||||
prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
|
prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
|
||||||
if (prop) {
|
if (prop) {
|
||||||
newlen = len + oldlen;
|
newlen = len + oldlen;
|
||||||
err = _fdt_splice_struct(fdt, prop->data,
|
err = fdt_splice_struct_(fdt, prop->data,
|
||||||
FDT_TAGALIGN(oldlen),
|
FDT_TAGALIGN(oldlen),
|
||||||
FDT_TAGALIGN(newlen));
|
FDT_TAGALIGN(newlen));
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -321,7 +321,7 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
|
||||||
prop->len = cpu_to_fdt32(newlen);
|
prop->len = cpu_to_fdt32(newlen);
|
||||||
memcpy(prop->data + oldlen, val, len);
|
memcpy(prop->data + oldlen, val, len);
|
||||||
} else {
|
} else {
|
||||||
err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
|
err = fdt_add_property_(fdt, nodeoffset, name, len, &prop);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
memcpy(prop->data, val, len);
|
memcpy(prop->data, val, len);
|
||||||
|
@ -341,7 +341,7 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name)
|
||||||
return len;
|
return len;
|
||||||
|
|
||||||
proplen = sizeof(*prop) + FDT_TAGALIGN(len);
|
proplen = sizeof(*prop) + FDT_TAGALIGN(len);
|
||||||
return _fdt_splice_struct(fdt, prop, proplen, 0);
|
return fdt_splice_struct_(fdt, prop, proplen, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fdt_add_subnode_namelen(void *fdt, int parentoffset,
|
int fdt_add_subnode_namelen(void *fdt, int parentoffset,
|
||||||
|
@ -369,10 +369,10 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
|
||||||
tag = fdt_next_tag(fdt, offset, &nextoffset);
|
tag = fdt_next_tag(fdt, offset, &nextoffset);
|
||||||
} while ((tag == FDT_PROP) || (tag == FDT_NOP));
|
} while ((tag == FDT_PROP) || (tag == FDT_NOP));
|
||||||
|
|
||||||
nh = _fdt_offset_ptr_w(fdt, offset);
|
nh = fdt_offset_ptr_w_(fdt, offset);
|
||||||
nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE;
|
nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE;
|
||||||
|
|
||||||
err = _fdt_splice_struct(fdt, nh, 0, nodelen);
|
err = fdt_splice_struct_(fdt, nh, 0, nodelen);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -396,15 +396,15 @@ int fdt_del_node(void *fdt, int nodeoffset)
|
||||||
|
|
||||||
FDT_RW_CHECK_HEADER(fdt);
|
FDT_RW_CHECK_HEADER(fdt);
|
||||||
|
|
||||||
endoffset = _fdt_node_end_offset(fdt, nodeoffset);
|
endoffset = fdt_node_end_offset_(fdt, nodeoffset);
|
||||||
if (endoffset < 0)
|
if (endoffset < 0)
|
||||||
return endoffset;
|
return endoffset;
|
||||||
|
|
||||||
return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset),
|
return fdt_splice_struct_(fdt, fdt_offset_ptr_w_(fdt, nodeoffset),
|
||||||
endoffset - nodeoffset, 0);
|
endoffset - nodeoffset, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _fdt_packblocks(const char *old, char *new,
|
static void fdt_packblocks_(const char *old, char *new,
|
||||||
int mem_rsv_size, int struct_size)
|
int mem_rsv_size, int struct_size)
|
||||||
{
|
{
|
||||||
int mem_rsv_off, struct_off, strings_off;
|
int mem_rsv_off, struct_off, strings_off;
|
||||||
|
@ -450,7 +450,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
|
||||||
return struct_size;
|
return struct_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
|
if (!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
|
||||||
/* no further work necessary */
|
/* no further work necessary */
|
||||||
err = fdt_move(fdt, buf, bufsize);
|
err = fdt_move(fdt, buf, bufsize);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -478,7 +478,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
|
||||||
return -FDT_ERR_NOSPACE;
|
return -FDT_ERR_NOSPACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
_fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size);
|
fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size);
|
||||||
memmove(buf, tmp, newsize);
|
memmove(buf, tmp, newsize);
|
||||||
|
|
||||||
fdt_set_magic(buf, FDT_MAGIC);
|
fdt_set_magic(buf, FDT_MAGIC);
|
||||||
|
@ -498,8 +498,8 @@ int fdt_pack(void *fdt)
|
||||||
|
|
||||||
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
|
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
|
||||||
* sizeof(struct fdt_reserve_entry);
|
* sizeof(struct fdt_reserve_entry);
|
||||||
_fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
|
fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
|
||||||
fdt_set_totalsize(fdt, _fdt_data_size(fdt));
|
fdt_set_totalsize(fdt, fdt_data_size_(fdt));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
|
|
||||||
#include "libfdt_internal.h"
|
#include "libfdt_internal.h"
|
||||||
|
|
||||||
static int _fdt_sw_check_header(void *fdt)
|
static int fdt_sw_check_header_(void *fdt)
|
||||||
{
|
{
|
||||||
if (fdt_magic(fdt) != FDT_SW_MAGIC)
|
if (fdt_magic(fdt) != FDT_SW_MAGIC)
|
||||||
return -FDT_ERR_BADMAGIC;
|
return -FDT_ERR_BADMAGIC;
|
||||||
|
@ -66,11 +66,11 @@ static int _fdt_sw_check_header(void *fdt)
|
||||||
#define FDT_SW_CHECK_HEADER(fdt) \
|
#define FDT_SW_CHECK_HEADER(fdt) \
|
||||||
{ \
|
{ \
|
||||||
int err; \
|
int err; \
|
||||||
if ((err = _fdt_sw_check_header(fdt)) != 0) \
|
if ((err = fdt_sw_check_header_(fdt)) != 0) \
|
||||||
return err; \
|
return err; \
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *_fdt_grab_space(void *fdt, size_t len)
|
static void *fdt_grab_space_(void *fdt, size_t len)
|
||||||
{
|
{
|
||||||
int offset = fdt_size_dt_struct(fdt);
|
int offset = fdt_size_dt_struct(fdt);
|
||||||
int spaceleft;
|
int spaceleft;
|
||||||
|
@ -82,7 +82,7 @@ static void *_fdt_grab_space(void *fdt, size_t len)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
fdt_set_size_dt_struct(fdt, offset + len);
|
fdt_set_size_dt_struct(fdt, offset + len);
|
||||||
return _fdt_offset_ptr_w(fdt, offset);
|
return fdt_offset_ptr_w_(fdt, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fdt_create(void *buf, int bufsize)
|
int fdt_create(void *buf, int bufsize)
|
||||||
|
@ -174,7 +174,7 @@ int fdt_begin_node(void *fdt, const char *name)
|
||||||
|
|
||||||
FDT_SW_CHECK_HEADER(fdt);
|
FDT_SW_CHECK_HEADER(fdt);
|
||||||
|
|
||||||
nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
|
nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
|
||||||
if (! nh)
|
if (! nh)
|
||||||
return -FDT_ERR_NOSPACE;
|
return -FDT_ERR_NOSPACE;
|
||||||
|
|
||||||
|
@ -189,7 +189,7 @@ int fdt_end_node(void *fdt)
|
||||||
|
|
||||||
FDT_SW_CHECK_HEADER(fdt);
|
FDT_SW_CHECK_HEADER(fdt);
|
||||||
|
|
||||||
en = _fdt_grab_space(fdt, FDT_TAGSIZE);
|
en = fdt_grab_space_(fdt, FDT_TAGSIZE);
|
||||||
if (! en)
|
if (! en)
|
||||||
return -FDT_ERR_NOSPACE;
|
return -FDT_ERR_NOSPACE;
|
||||||
|
|
||||||
|
@ -197,7 +197,7 @@ int fdt_end_node(void *fdt)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _fdt_find_add_string(void *fdt, const char *s)
|
static int fdt_find_add_string_(void *fdt, const char *s)
|
||||||
{
|
{
|
||||||
char *strtab = (char *)fdt + fdt_totalsize(fdt);
|
char *strtab = (char *)fdt + fdt_totalsize(fdt);
|
||||||
const char *p;
|
const char *p;
|
||||||
|
@ -205,7 +205,7 @@ static int _fdt_find_add_string(void *fdt, const char *s)
|
||||||
int len = strlen(s) + 1;
|
int len = strlen(s) + 1;
|
||||||
int struct_top, offset;
|
int struct_top, offset;
|
||||||
|
|
||||||
p = _fdt_find_string(strtab - strtabsize, strtabsize, s);
|
p = fdt_find_string_(strtab - strtabsize, strtabsize, s);
|
||||||
if (p)
|
if (p)
|
||||||
return p - strtab;
|
return p - strtab;
|
||||||
|
|
||||||
|
@ -227,11 +227,11 @@ int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp)
|
||||||
|
|
||||||
FDT_SW_CHECK_HEADER(fdt);
|
FDT_SW_CHECK_HEADER(fdt);
|
||||||
|
|
||||||
nameoff = _fdt_find_add_string(fdt, name);
|
nameoff = fdt_find_add_string_(fdt, name);
|
||||||
if (nameoff == 0)
|
if (nameoff == 0)
|
||||||
return -FDT_ERR_NOSPACE;
|
return -FDT_ERR_NOSPACE;
|
||||||
|
|
||||||
prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
|
prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
|
||||||
if (! prop)
|
if (! prop)
|
||||||
return -FDT_ERR_NOSPACE;
|
return -FDT_ERR_NOSPACE;
|
||||||
|
|
||||||
|
@ -265,7 +265,7 @@ int fdt_finish(void *fdt)
|
||||||
FDT_SW_CHECK_HEADER(fdt);
|
FDT_SW_CHECK_HEADER(fdt);
|
||||||
|
|
||||||
/* Add terminator */
|
/* Add terminator */
|
||||||
end = _fdt_grab_space(fdt, sizeof(*end));
|
end = fdt_grab_space_(fdt, sizeof(*end));
|
||||||
if (! end)
|
if (! end)
|
||||||
return -FDT_ERR_NOSPACE;
|
return -FDT_ERR_NOSPACE;
|
||||||
*end = cpu_to_fdt32(FDT_END);
|
*end = cpu_to_fdt32(FDT_END);
|
||||||
|
@ -281,7 +281,7 @@ int fdt_finish(void *fdt)
|
||||||
while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
|
while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
|
||||||
if (tag == FDT_PROP) {
|
if (tag == FDT_PROP) {
|
||||||
struct fdt_property *prop =
|
struct fdt_property *prop =
|
||||||
_fdt_offset_ptr_w(fdt, offset);
|
fdt_offset_ptr_w_(fdt, offset);
|
||||||
int nameoff;
|
int nameoff;
|
||||||
|
|
||||||
nameoff = fdt32_to_cpu(prop->nameoff);
|
nameoff = fdt32_to_cpu(prop->nameoff);
|
||||||
|
|
|
@ -93,7 +93,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
|
||||||
val, len);
|
val, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _fdt_nop_region(void *start, int len)
|
static void fdt_nop_region_(void *start, int len)
|
||||||
{
|
{
|
||||||
fdt32_t *p;
|
fdt32_t *p;
|
||||||
|
|
||||||
|
@ -110,12 +110,12 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
|
||||||
if (!prop)
|
if (!prop)
|
||||||
return len;
|
return len;
|
||||||
|
|
||||||
_fdt_nop_region(prop, len + sizeof(*prop));
|
fdt_nop_region_(prop, len + sizeof(*prop));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _fdt_node_end_offset(void *fdt, int offset)
|
int fdt_node_end_offset_(void *fdt, int offset)
|
||||||
{
|
{
|
||||||
int depth = 0;
|
int depth = 0;
|
||||||
|
|
||||||
|
@ -129,11 +129,11 @@ int fdt_nop_node(void *fdt, int nodeoffset)
|
||||||
{
|
{
|
||||||
int endoffset;
|
int endoffset;
|
||||||
|
|
||||||
endoffset = _fdt_node_end_offset(fdt, nodeoffset);
|
endoffset = fdt_node_end_offset_(fdt, nodeoffset);
|
||||||
if (endoffset < 0)
|
if (endoffset < 0)
|
||||||
return endoffset;
|
return endoffset;
|
||||||
|
|
||||||
_fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0),
|
fdt_nop_region_(fdt_offset_ptr_w(fdt, nodeoffset, 0),
|
||||||
endoffset - nodeoffset);
|
endoffset - nodeoffset);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef _LIBFDT_H
|
#ifndef LIBFDT_H
|
||||||
#define _LIBFDT_H
|
#define LIBFDT_H
|
||||||
/*
|
/*
|
||||||
* libfdt - Flat Device Tree manipulation
|
* libfdt - Flat Device Tree manipulation
|
||||||
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
||||||
|
@ -54,7 +54,7 @@
|
||||||
#include "libfdt_env.h"
|
#include "libfdt_env.h"
|
||||||
#include "fdt.h"
|
#include "fdt.h"
|
||||||
|
|
||||||
#define FDT_FIRST_SUPPORTED_VERSION 0x10
|
#define FDT_FIRST_SUPPORTED_VERSION 0x02
|
||||||
#define FDT_LAST_SUPPORTED_VERSION 0x11
|
#define FDT_LAST_SUPPORTED_VERSION 0x11
|
||||||
|
|
||||||
/* Error codes: informative error codes */
|
/* Error codes: informative error codes */
|
||||||
|
@ -225,23 +225,23 @@ int fdt_next_subnode(const void *fdt, int offset);
|
||||||
#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings))
|
#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings))
|
||||||
#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct))
|
#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct))
|
||||||
|
|
||||||
#define __fdt_set_hdr(name) \
|
#define fdt_set_hdr_(name) \
|
||||||
static inline void fdt_set_##name(void *fdt, uint32_t val) \
|
static inline void fdt_set_##name(void *fdt, uint32_t val) \
|
||||||
{ \
|
{ \
|
||||||
struct fdt_header *fdth = (struct fdt_header *)fdt; \
|
struct fdt_header *fdth = (struct fdt_header *)fdt; \
|
||||||
fdth->name = cpu_to_fdt32(val); \
|
fdth->name = cpu_to_fdt32(val); \
|
||||||
}
|
}
|
||||||
__fdt_set_hdr(magic);
|
fdt_set_hdr_(magic);
|
||||||
__fdt_set_hdr(totalsize);
|
fdt_set_hdr_(totalsize);
|
||||||
__fdt_set_hdr(off_dt_struct);
|
fdt_set_hdr_(off_dt_struct);
|
||||||
__fdt_set_hdr(off_dt_strings);
|
fdt_set_hdr_(off_dt_strings);
|
||||||
__fdt_set_hdr(off_mem_rsvmap);
|
fdt_set_hdr_(off_mem_rsvmap);
|
||||||
__fdt_set_hdr(version);
|
fdt_set_hdr_(version);
|
||||||
__fdt_set_hdr(last_comp_version);
|
fdt_set_hdr_(last_comp_version);
|
||||||
__fdt_set_hdr(boot_cpuid_phys);
|
fdt_set_hdr_(boot_cpuid_phys);
|
||||||
__fdt_set_hdr(size_dt_strings);
|
fdt_set_hdr_(size_dt_strings);
|
||||||
__fdt_set_hdr(size_dt_struct);
|
fdt_set_hdr_(size_dt_struct);
|
||||||
#undef __fdt_set_hdr
|
#undef fdt_set_hdr_
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fdt_check_header - sanity check a device tree or possible device tree
|
* fdt_check_header - sanity check a device tree or possible device tree
|
||||||
|
@ -527,6 +527,9 @@ int fdt_next_property_offset(const void *fdt, int offset);
|
||||||
* offset. If lenp is non-NULL, the length of the property value is
|
* offset. If lenp is non-NULL, the length of the property value is
|
||||||
* also returned, in the integer pointed to by lenp.
|
* also returned, in the integer pointed to by lenp.
|
||||||
*
|
*
|
||||||
|
* Note that this code only works on device tree versions >= 16. fdt_getprop()
|
||||||
|
* works on all versions.
|
||||||
|
*
|
||||||
* returns:
|
* returns:
|
||||||
* pointer to the structure representing the property
|
* pointer to the structure representing the property
|
||||||
* if lenp is non-NULL, *lenp contains the length of the property
|
* if lenp is non-NULL, *lenp contains the length of the property
|
||||||
|
@ -1449,7 +1452,7 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
|
||||||
const void *val, int len);
|
const void *val, int len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fdt_setprop _placeholder - allocate space for a property
|
* fdt_setprop_placeholder - allocate space for a property
|
||||||
* @fdt: pointer to the device tree blob
|
* @fdt: pointer to the device tree blob
|
||||||
* @nodeoffset: offset of the node whose property to change
|
* @nodeoffset: offset of the node whose property to change
|
||||||
* @name: name of the property to change
|
* @name: name of the property to change
|
||||||
|
@ -1896,4 +1899,4 @@ int fdt_overlay_apply(void *fdt, void *fdto);
|
||||||
|
|
||||||
const char *fdt_strerror(int errval);
|
const char *fdt_strerror(int errval);
|
||||||
|
|
||||||
#endif /* _LIBFDT_H */
|
#endif /* LIBFDT_H */
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef _LIBFDT_ENV_H
|
#ifndef LIBFDT_ENV_H
|
||||||
#define _LIBFDT_ENV_H
|
#define LIBFDT_ENV_H
|
||||||
/*
|
/*
|
||||||
* libfdt - Flat Device Tree manipulation
|
* libfdt - Flat Device Tree manipulation
|
||||||
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
||||||
|
@ -109,4 +109,31 @@ static inline fdt64_t cpu_to_fdt64(uint64_t x)
|
||||||
#undef CPU_TO_FDT16
|
#undef CPU_TO_FDT16
|
||||||
#undef EXTRACT_BYTE
|
#undef EXTRACT_BYTE
|
||||||
|
|
||||||
#endif /* _LIBFDT_ENV_H */
|
#ifdef __APPLE__
|
||||||
|
#include <AvailabilityMacros.h>
|
||||||
|
|
||||||
|
/* strnlen() is not available on Mac OS < 10.7 */
|
||||||
|
# if !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < \
|
||||||
|
MAC_OS_X_VERSION_10_7)
|
||||||
|
|
||||||
|
#define strnlen fdt_strnlen
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fdt_strnlen: returns the length of a string or max_count - which ever is
|
||||||
|
* smallest.
|
||||||
|
* Input 1 string: the string whose size is to be determined
|
||||||
|
* Input 2 max_count: the maximum value returned by this function
|
||||||
|
* Output: length of the string or max_count (the smallest of the two)
|
||||||
|
*/
|
||||||
|
static inline size_t fdt_strnlen(const char *string, size_t max_count)
|
||||||
|
{
|
||||||
|
const char *p = memchr(string, 0, max_count);
|
||||||
|
return p ? p - string : max_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED <
|
||||||
|
MAC_OS_X_VERSION_10_7) */
|
||||||
|
|
||||||
|
#endif /* __APPLE__ */
|
||||||
|
|
||||||
|
#endif /* LIBFDT_ENV_H */
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef _LIBFDT_INTERNAL_H
|
#ifndef LIBFDT_INTERNAL_H
|
||||||
#define _LIBFDT_INTERNAL_H
|
#define LIBFDT_INTERNAL_H
|
||||||
/*
|
/*
|
||||||
* libfdt - Flat Device Tree manipulation
|
* libfdt - Flat Device Tree manipulation
|
||||||
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
||||||
|
@ -57,27 +57,27 @@
|
||||||
|
|
||||||
#define FDT_CHECK_HEADER(fdt) \
|
#define FDT_CHECK_HEADER(fdt) \
|
||||||
{ \
|
{ \
|
||||||
int __err; \
|
int err_; \
|
||||||
if ((__err = fdt_check_header(fdt)) != 0) \
|
if ((err_ = fdt_check_header(fdt)) != 0) \
|
||||||
return __err; \
|
return err_; \
|
||||||
}
|
}
|
||||||
|
|
||||||
int _fdt_check_node_offset(const void *fdt, int offset);
|
int fdt_check_node_offset_(const void *fdt, int offset);
|
||||||
int _fdt_check_prop_offset(const void *fdt, int offset);
|
int fdt_check_prop_offset_(const void *fdt, int offset);
|
||||||
const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
|
const char *fdt_find_string_(const char *strtab, int tabsize, const char *s);
|
||||||
int _fdt_node_end_offset(void *fdt, int nodeoffset);
|
int fdt_node_end_offset_(void *fdt, int nodeoffset);
|
||||||
|
|
||||||
static inline const void *_fdt_offset_ptr(const void *fdt, int offset)
|
static inline const void *fdt_offset_ptr_(const void *fdt, int offset)
|
||||||
{
|
{
|
||||||
return (const char *)fdt + fdt_off_dt_struct(fdt) + offset;
|
return (const char *)fdt + fdt_off_dt_struct(fdt) + offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void *_fdt_offset_ptr_w(void *fdt, int offset)
|
static inline void *fdt_offset_ptr_w_(void *fdt, int offset)
|
||||||
{
|
{
|
||||||
return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset);
|
return (void *)(uintptr_t)fdt_offset_ptr_(fdt, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n)
|
static inline const struct fdt_reserve_entry *fdt_mem_rsv_(const void *fdt, int n)
|
||||||
{
|
{
|
||||||
const struct fdt_reserve_entry *rsv_table =
|
const struct fdt_reserve_entry *rsv_table =
|
||||||
(const struct fdt_reserve_entry *)
|
(const struct fdt_reserve_entry *)
|
||||||
|
@ -85,11 +85,11 @@ static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int
|
||||||
|
|
||||||
return rsv_table + n;
|
return rsv_table + n;
|
||||||
}
|
}
|
||||||
static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n)
|
static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n)
|
||||||
{
|
{
|
||||||
return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n);
|
return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FDT_SW_MAGIC (~FDT_MAGIC)
|
#define FDT_SW_MAGIC (~FDT_MAGIC)
|
||||||
|
|
||||||
#endif /* _LIBFDT_INTERNAL_H */
|
#endif /* LIBFDT_INTERNAL_H */
|
||||||
|
|
|
@ -216,7 +216,7 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
|
||||||
return old_node;
|
return old_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_orphan_node(struct node *dt, struct node *new_node, char *ref)
|
struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref)
|
||||||
{
|
{
|
||||||
static unsigned int next_orphan_fragment = 0;
|
static unsigned int next_orphan_fragment = 0;
|
||||||
struct node *node;
|
struct node *node;
|
||||||
|
@ -236,6 +236,7 @@ void add_orphan_node(struct node *dt, struct node *new_node, char *ref)
|
||||||
name_node(node, name);
|
name_node(node, name);
|
||||||
|
|
||||||
add_child(dt, node);
|
add_child(dt, node);
|
||||||
|
return dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct node *chain_node(struct node *first, struct node *list)
|
struct node *chain_node(struct node *first, struct node *list)
|
||||||
|
@ -507,7 +508,7 @@ struct node *get_node_by_path(struct node *tree, const char *path)
|
||||||
|
|
||||||
for_each_child(tree, child) {
|
for_each_child(tree, child) {
|
||||||
if (p && (strlen(child->name) == p-path) &&
|
if (p && (strlen(child->name) == p-path) &&
|
||||||
strneq(path, child->name, p-path))
|
strprefixeq(path, p - path, child->name))
|
||||||
return get_node_by_path(child, p+1);
|
return get_node_by_path(child, p+1);
|
||||||
else if (!p && streq(path, child->name))
|
else if (!p && streq(path, child->name))
|
||||||
return child;
|
return child;
|
||||||
|
@ -540,7 +541,10 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
|
||||||
{
|
{
|
||||||
struct node *child, *node;
|
struct node *child, *node;
|
||||||
|
|
||||||
assert((phandle != 0) && (phandle != -1));
|
if ((phandle == 0) || (phandle == -1)) {
|
||||||
|
assert(generate_fixups);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (tree->phandle == phandle) {
|
if (tree->phandle == phandle) {
|
||||||
if (tree->deleted)
|
if (tree->deleted)
|
||||||
|
|
|
@ -209,8 +209,6 @@ struct srcpos srcpos_empty = {
|
||||||
.file = NULL,
|
.file = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TAB_SIZE 8
|
|
||||||
|
|
||||||
void srcpos_update(struct srcpos *pos, const char *text, int len)
|
void srcpos_update(struct srcpos *pos, const char *text, int len)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -224,9 +222,6 @@ void srcpos_update(struct srcpos *pos, const char *text, int len)
|
||||||
if (text[i] == '\n') {
|
if (text[i] == '\n') {
|
||||||
current_srcfile->lineno++;
|
current_srcfile->lineno++;
|
||||||
current_srcfile->colno = 1;
|
current_srcfile->colno = 1;
|
||||||
} else if (text[i] == '\t') {
|
|
||||||
current_srcfile->colno =
|
|
||||||
ALIGN(current_srcfile->colno, TAB_SIZE);
|
|
||||||
} else {
|
} else {
|
||||||
current_srcfile->colno++;
|
current_srcfile->colno++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
* USA
|
* USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _SRCPOS_H_
|
#ifndef SRCPOS_H
|
||||||
#define _SRCPOS_H_
|
#define SRCPOS_H
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
@ -114,4 +114,4 @@ extern void PRINTF(3, 4) srcpos_error(struct srcpos *pos, const char *prefix,
|
||||||
|
|
||||||
extern void srcpos_set_line(char *f, int l);
|
extern void srcpos_set_line(char *f, int l);
|
||||||
|
|
||||||
#endif /* _SRCPOS_H_ */
|
#endif /* SRCPOS_H */
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#
|
#
|
||||||
# This script assumes that the dtc and the linux git trees are in the
|
# This script assumes that the dtc and the linux git trees are in the
|
||||||
# same directory. After building dtc in the dtc directory, it copies the
|
# same directory. After building dtc in the dtc directory, it copies the
|
||||||
# source files and generated source files into the scripts/dtc directory
|
# source files and generated source file(s) into the scripts/dtc directory
|
||||||
# in the kernel and creates a git commit updating them to the new
|
# in the kernel and creates a git commit updating them to the new
|
||||||
# version.
|
# version.
|
||||||
#
|
#
|
||||||
|
@ -34,7 +34,6 @@ DTC_LINUX_PATH=`pwd`/scripts/dtc
|
||||||
DTC_SOURCE="checks.c data.c dtc.c dtc.h flattree.c fstree.c livetree.c srcpos.c \
|
DTC_SOURCE="checks.c data.c dtc.c dtc.h flattree.c fstree.c livetree.c srcpos.c \
|
||||||
srcpos.h treesource.c util.c util.h version_gen.h Makefile.dtc \
|
srcpos.h treesource.c util.c util.h version_gen.h Makefile.dtc \
|
||||||
dtc-lexer.l dtc-parser.y"
|
dtc-lexer.l dtc-parser.y"
|
||||||
DTC_GENERATED="dtc-lexer.lex.c dtc-parser.tab.c dtc-parser.tab.h"
|
|
||||||
LIBFDT_SOURCE="Makefile.libfdt fdt.c fdt.h fdt_addresses.c fdt_empty_tree.c \
|
LIBFDT_SOURCE="Makefile.libfdt fdt.c fdt.h fdt_addresses.c fdt_empty_tree.c \
|
||||||
fdt_overlay.c fdt_ro.c fdt_rw.c fdt_strerror.c fdt_sw.c \
|
fdt_overlay.c fdt_ro.c fdt_rw.c fdt_strerror.c fdt_sw.c \
|
||||||
fdt_wip.c libfdt.h libfdt_env.h libfdt_internal.h"
|
fdt_wip.c libfdt.h libfdt_env.h libfdt_internal.h"
|
||||||
|
@ -59,10 +58,6 @@ for f in $DTC_SOURCE; do
|
||||||
cp ${DTC_UPSTREAM_PATH}/${f} ${f}
|
cp ${DTC_UPSTREAM_PATH}/${f} ${f}
|
||||||
git add ${f}
|
git add ${f}
|
||||||
done
|
done
|
||||||
for f in $DTC_GENERATED; do
|
|
||||||
cp ${DTC_UPSTREAM_PATH}/$f ${f}_shipped
|
|
||||||
git add ${f}_shipped
|
|
||||||
done
|
|
||||||
for f in $LIBFDT_SOURCE; do
|
for f in $LIBFDT_SOURCE; do
|
||||||
cp ${DTC_UPSTREAM_PATH}/libfdt/${f} libfdt/${f}
|
cp ${DTC_UPSTREAM_PATH}/libfdt/${f} libfdt/${f}
|
||||||
git add libfdt/${f}
|
git add libfdt/${f}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef _UTIL_H
|
#ifndef UTIL_H
|
||||||
#define _UTIL_H
|
#define UTIL_H
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
@ -35,6 +35,9 @@
|
||||||
|
|
||||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
|
|
||||||
|
#define stringify(s) stringify_(s)
|
||||||
|
#define stringify_(s) #s
|
||||||
|
|
||||||
static inline void NORETURN PRINTF(1, 2) die(const char *str, ...)
|
static inline void NORETURN PRINTF(1, 2) die(const char *str, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
@ -260,4 +263,4 @@ void NORETURN util_usage(const char *errmsg, const char *synopsis,
|
||||||
case 'V': util_version(); \
|
case 'V': util_version(); \
|
||||||
case '?': usage("unknown option");
|
case '?': usage("unknown option");
|
||||||
|
|
||||||
#endif /* _UTIL_H */
|
#endif /* UTIL_H */
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
#define DTC_VERSION "DTC 1.4.5-gc1e55a55"
|
#define DTC_VERSION "DTC 1.4.6-gaadd0b65"
|
||||||
|
|
Loading…
Add table
Reference in a new issue