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:
Linus Torvalds 2018-04-05 21:03:42 -07:00
commit 9c2dd8405c
45 changed files with 1213 additions and 5169 deletions

View File

@ -21,7 +21,7 @@ Required Properties:
- "rockchip,rk3399-dw-mshc", "rockchip,rk3288-dw-mshc": for Rockchip RK3399
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.
* 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-
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.
If not specified 0 deg will be used.

View File

@ -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
mcube,mc3230 mCube 3-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-103 Microchip 7-bit Single I2C Digital Potentiometer (10k)
microchip,mcp4531-503 Microchip 7-bit Single I2C Digital Potentiometer (50k)

View File

@ -91,8 +91,8 @@ The API is quite easy to use.
return value is an error or a cookie identifying this overlay.
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
changeset that is stacked by another will not be permitted.
previously created via the call to of_overlay_fdt_apply(). Removal of an
overlay changeset that is stacked by another will not be permitted.
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

View File

@ -4287,6 +4287,7 @@ Q: https://patchwork.kernel.org/project/linux-dmaengine/list/
S: Maintained
F: drivers/dma/
F: include/linux/dmaengine.h
F: include/linux/of_dma.h
F: Documentation/devicetree/bindings/dma/
F: Documentation/driver-api/dmaengine/
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: include/linux/gpio/
F: include/linux/gpio.h
F: include/linux/of_gpio.h
F: include/asm-generic/gpio.h
F: include/uapi/linux/gpio.h
F: tools/gpio/
@ -7295,6 +7297,7 @@ S: Maintained
F: Documentation/devicetree/bindings/iommu/
F: drivers/iommu/
F: include/linux/iommu.h
F: include/linux/of_iommu.h
F: include/linux/iova.h
IP MASQUERADING
@ -10785,6 +10788,7 @@ F: drivers/acpi/pci*
F: drivers/pci/
F: include/asm-generic/pci*
F: include/linux/pci*
F: include/linux/of_pci.h
F: include/uapi/linux/pci*
F: lib/pci*
F: arch/x86/pci/

View File

@ -121,6 +121,16 @@ char *strchr(const char *s, int c)
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
void *memset(void *s, int c, size_t count)

View File

@ -103,6 +103,7 @@ __efistub_strlen = KALLSYMS_HIDE(__pi_strlen);
__efistub_strnlen = KALLSYMS_HIDE(__pi_strnlen);
__efistub_strcmp = KALLSYMS_HIDE(__pi_strcmp);
__efistub_strncmp = KALLSYMS_HIDE(__pi_strncmp);
__efistub_strrchr = KALLSYMS_HIDE(__pi_strrchr);
__efistub___flush_dcache_area = KALLSYMS_HIDE(__pi___flush_dcache_area);
#ifdef CONFIG_KASAN

View File

@ -40,4 +40,4 @@ ENTRY(strrchr)
b 1b
2: mov x0, x3
ret
ENDPROC(strrchr)
ENDPIPROC(strrchr)

View File

@ -21,6 +21,16 @@ size_t strnlen(const char * s, size_t count)
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__
# define do_div(n, base) ({ \

View File

@ -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 *strcat(char *dest, const char *src);
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 strncmp(const char *s1, const char *s2, size_t n);
extern size_t strlen(const char *s);

View File

@ -111,8 +111,8 @@ struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
struct gpio_desc *desc;
int ret;
ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", index,
&gpiospec);
ret = of_parse_phandle_with_args_map(np, propname, "gpio", index,
&gpiospec);
if (ret) {
pr_debug("%s: can't parse '%s' property of node '%pOF[%d]'\n",
__func__, propname, np, index);

View File

@ -91,10 +91,72 @@ int __weak of_node_to_nid(struct device_node *np)
}
#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)
{
struct device_node *np;
of_populate_phandle_cache();
/* Create the kset, and register existing nodes */
mutex_lock(&of_mutex);
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 *np;
struct device_node *np = NULL;
unsigned long flags;
phandle masked_handle;
if (!handle)
return NULL;
raw_spin_lock_irqsave(&devtree_lock, flags);
for_each_of_allnodes(np)
if (np->phandle == handle)
break;
masked_handle = handle & phandle_cache_mask;
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);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
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);
/**
* 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
* @np: pointer to a device tree node containing a list

View File

@ -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.
* @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
* an empty one suitable for further modification. The node data are
* dynamically allocated and all the node flags have the OF_DYNAMIC &
* OF_DETACHED bits set. Returns the newly allocated node or NULL on out of
* memory error.
* Create a device tree node, optionally duplicating the properties of
* another node. The node data are dynamically allocated and all the node
* flags have the OF_DYNAMIC & OF_DETACHED bits set.
*
* 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;
node = kzalloc(sizeof(*node), GFP_KERNEL);
if (!node)
return NULL;
va_start(vargs, fmt);
node->full_name = kvasprintf(GFP_KERNEL, fmt, vargs);
va_end(vargs);
node->full_name = kstrdup(full_name, GFP_KERNEL);
if (!node->full_name) {
kfree(node);
return NULL;

View File

@ -104,7 +104,8 @@ extern void *__unflatten_device_tree(const void *blob,
* own the devtree lock or work on detached trees only.
*/
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,
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,
struct property *prop);
/* illegal phandle value (set when unresolved) */
#define OF_PHANDLE_ILLEGAL 0xdeadbeef
/* iterators for transactions, used for overlays */
/* forward iterator */
#define for_each_transaction_entry(_oft, _te) \

View File

@ -312,7 +312,20 @@ static int add_changeset_property(struct overlay_changeset *ovcs,
* If @node has child nodes, add the children recursively via
* 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
* 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
@ -339,8 +352,7 @@ static int add_changeset_node(struct overlay_changeset *ovcs,
break;
if (!tchild) {
tchild = __of_node_dup(node, "%pOF/%s",
target_node, node_kbasename);
tchild = __of_node_dup(node, node_kbasename);
if (!tchild)
return -ENOMEM;
@ -958,7 +970,7 @@ static int overlay_removal_is_ok(struct overlay_changeset *remove_ovcs)
* @ovcs_id: Pointer to overlay changeset id
*
* 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,
* then an attempt is made to re-apply any changeset entry that was

View File

@ -19,9 +19,6 @@
#include "of_private.h"
/* illegal phandle value (set when unresolved) */
#define OF_PHANDLE_ILLEGAL 0xdeadbeef
static phandle live_tree_max_phandle(void)
{
struct device_node *node;

View File

@ -26,6 +26,18 @@
#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 {
phandle-list = <&provider1 1>,
<&provider2 2 0>,
@ -44,6 +56,19 @@
unterminated-string = [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>;
};
};
};
};

View File

@ -45,8 +45,6 @@ static struct unittest_results {
failed; \
})
static int __init overlay_data_apply(const char *overlay_name, int *overlay_id);
static void __init of_unittest_find_node_by_name(void)
{
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,
const char *expected)
{
unsigned char buf[strlen(expected)+10];
unsigned char *buf;
int buf_size;
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 */
memset(buf, 0xff, sizeof(buf));
size = snprintf(buf, sizeof(buf) - 2, fmt, np);
memset(buf, 0xff, buf_size);
size = snprintf(buf, buf_size - 2, fmt, np);
/* use strcmp() instead of strncmp() here to be absolutely sure strings match */
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++;
for (i = 0; i < 2; i++, size--) {
/* 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);
unittest(strncmp(buf, expected, size) == 0 && (buf[size+1] == 0xff),
"snprintf failed; size=%i fmt='%s' expected='%s' rslt='%s'\n",
size, fmt, expected, buf);
}
kfree(buf);
}
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);
}
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)
{
const char *strings[4];
@ -564,42 +688,72 @@ static void __init of_unittest_property_copy(void)
static void __init of_unittest_changeset(void)
{
#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 *ppremove;
struct device_node *n1, *n2, *n21, *nremove, *parent, *np;
struct device_node *n1, *n2, *n21, *nchangeset, *nremove, *parent, *np;
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");
n2 = __of_node_dup(NULL, "/testcase-data/changeset/n2");
n2 = __of_node_dup(NULL, "n2");
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);
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");
ppadd = __of_prop_dup(&padd, GFP_KERNEL);
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);
unittest(ppupdate, "testcase setup failure\n");
parent = nremove->parent;
parent = nchangeset;
n1->parent = parent;
n2->parent = parent;
n21->parent = n2;
n2->child = n21;
ppremove = of_find_property(parent, "prop-remove", NULL);
unittest(ppremove, "failed to find removal prop");
of_changeset_init(&chgset);
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_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_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_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_remove_property(&chgset, parent, ppremove), "fail remove prop\n");
unittest(!of_changeset_apply(&chgset), "apply failed\n");
of_node_put(nchangeset);
/* Make sure node names are constructed correctly */
unittest((np = of_find_node_by_path("/testcase-data/changeset/n2/n21")),
"'%pOF' not added\n", n21);
@ -1036,6 +1190,7 @@ static int __init unittest_data_add(void)
}
#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)
{
@ -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,
int *overlay_id)
{
struct device_node *np = NULL;
const char *overlay_name;
int ret;
overlay_name = overlay_name_from_nr(overlay_nr);
ret = overlay_data_apply(overlay_name, overlay_id);
if (!ret) {
if (!overlay_data_apply(overlay_name, overlay_id)) {
unittest(0, "could not apply overlay \"%s\"\n",
overlay_name);
goto out;
return -EFAULT;
}
of_unittest_track_overlay(*overlay_id);
ret = 0;
out:
of_node_put(np);
return ret;
return 0;
}
/* 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 */
static void __init of_unittest_overlay_0(void)
{
int ret;
/* device should enable */
ret = of_unittest_apply_overlay_check(0, 0, 0, 1, PDEV_OVERLAY);
if (ret != 0)
if (of_unittest_apply_overlay_check(0, 0, 0, 1, PDEV_OVERLAY))
return;
unittest(1, "overlay test %d passed\n", 0);
@ -1393,11 +1537,8 @@ static void __init of_unittest_overlay_0(void)
/* test deactivation of device */
static void __init of_unittest_overlay_1(void)
{
int ret;
/* device should disable */
ret = of_unittest_apply_overlay_check(1, 1, 1, 0, PDEV_OVERLAY);
if (ret != 0)
if (of_unittest_apply_overlay_check(1, 1, 1, 0, PDEV_OVERLAY))
return;
unittest(1, "overlay test %d passed\n", 1);
@ -1406,11 +1547,8 @@ static void __init of_unittest_overlay_1(void)
/* test activation of device */
static void __init of_unittest_overlay_2(void)
{
int ret;
/* device should enable */
ret = of_unittest_apply_overlay_check(2, 2, 0, 1, PDEV_OVERLAY);
if (ret != 0)
if (of_unittest_apply_overlay_check(2, 2, 0, 1, PDEV_OVERLAY))
return;
unittest(1, "overlay test %d passed\n", 2);
@ -1419,11 +1557,8 @@ static void __init of_unittest_overlay_2(void)
/* test deactivation of device */
static void __init of_unittest_overlay_3(void)
{
int ret;
/* device should disable */
ret = of_unittest_apply_overlay_check(3, 3, 1, 0, PDEV_OVERLAY);
if (ret != 0)
if (of_unittest_apply_overlay_check(3, 3, 1, 0, PDEV_OVERLAY))
return;
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 */
static void __init of_unittest_overlay_4(void)
{
int ret;
/* device should disable */
ret = of_unittest_apply_overlay_check(4, 4, 0, 1, PDEV_OVERLAY);
if (ret != 0)
if (of_unittest_apply_overlay_check(4, 4, 0, 1, PDEV_OVERLAY))
return;
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 */
static void __init of_unittest_overlay_5(void)
{
int ret;
/* device should disable */
ret = of_unittest_apply_revert_overlay_check(5, 5, 0, 1, PDEV_OVERLAY);
if (ret != 0)
if (of_unittest_apply_revert_overlay_check(5, 5, 0, 1, PDEV_OVERLAY))
return;
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 */
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 before = 0, after = 1;
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);
ret = overlay_data_apply(overlay_name, &ovcs_id);
if (!ret) {
if (!overlay_data_apply(overlay_name, &ovcs_id)) {
unittest(0, "could not apply overlay \"%s\"\n",
overlay_name);
return;
@ -1506,8 +1634,7 @@ static void __init of_unittest_overlay_6(void)
for (i = 1; i >= 0; i--) {
ovcs_id = ov_id[i];
ret = of_overlay_remove(&ovcs_id);
if (ret != 0) {
if (of_overlay_remove(&ovcs_id)) {
unittest(0, "%s failed destroy @\"%s\"\n",
overlay_name_from_nr(overlay_nr + i),
unittest_path(unittest_nr + i,
@ -1536,7 +1663,7 @@ static void __init of_unittest_overlay_6(void)
/* test overlay application in sequence */
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;
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);
ret = overlay_data_apply(overlay_name, &ovcs_id);
if (ret < 0) {
if (!overlay_data_apply(overlay_name, &ovcs_id)) {
unittest(0, "could not apply overlay \"%s\"\n",
overlay_name);
return;
@ -1559,8 +1685,7 @@ static void __init of_unittest_overlay_8(void)
/* now try to remove first overlay (it should fail) */
ovcs_id = ov_id[0];
ret = of_overlay_remove(&ovcs_id);
if (ret == 0) {
if (!of_overlay_remove(&ovcs_id)) {
unittest(0, "%s was destroyed @\"%s\"\n",
overlay_name_from_nr(overlay_nr + 0),
unittest_path(unittest_nr,
@ -1571,8 +1696,7 @@ static void __init of_unittest_overlay_8(void)
/* removing them in order should work */
for (i = 1; i >= 0; i--) {
ovcs_id = ov_id[i];
ret = of_overlay_remove(&ovcs_id);
if (ret != 0) {
if (of_overlay_remove(&ovcs_id)) {
unittest(0, "%s not destroyed @\"%s\"\n",
overlay_name_from_nr(overlay_nr + i),
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);
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) */
@ -1616,9 +1740,7 @@ static void __init of_unittest_overlay_11(void)
/* device should disable */
ret = of_unittest_apply_revert_overlay_check(11, 11, 0, 1,
PDEV_OVERLAY);
if (unittest(ret == 0,
"overlay test %d failed; overlay application\n", 11))
return;
unittest(ret == 0, "overlay test %d failed; overlay apply\n", 11);
}
#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,
const struct i2c_device_id *id)
{
int ret, i, nchans;
int i, nchans;
struct device *dev = &client->dev;
struct i2c_adapter *adap = to_i2c_adapter(dev->parent);
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;
for_each_child_of_node(np, child) {
ret = of_property_read_u32(child, "reg", &reg);
if (ret)
if (of_property_read_u32(child, "reg", &reg))
continue;
if (max_reg == (u32)-1 || reg > max_reg)
max_reg = reg;
@ -1802,8 +1923,7 @@ static int unittest_i2c_mux_probe(struct i2c_client *client,
if (!muxc)
return -ENOMEM;
for (i = 0; i < nchans; i++) {
ret = i2c_mux_add_adapter(muxc, 0, i, 0);
if (ret) {
if (i2c_mux_add_adapter(muxc, 0, i, 0)) {
dev_err(dev, "Failed to register mux #%d\n", i);
i2c_mux_del_adapters(muxc);
return -ENODEV;
@ -1877,11 +1997,8 @@ static void of_unittest_overlay_i2c_cleanup(void)
static void __init of_unittest_overlay_i2c_12(void)
{
int ret;
/* device should enable */
ret = of_unittest_apply_overlay_check(12, 12, 0, 1, I2C_OVERLAY);
if (ret != 0)
if (of_unittest_apply_overlay_check(12, 12, 0, 1, I2C_OVERLAY))
return;
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 */
static void __init of_unittest_overlay_i2c_13(void)
{
int ret;
/* device should disable */
ret = of_unittest_apply_overlay_check(13, 13, 1, 0, I2C_OVERLAY);
if (ret != 0)
if (of_unittest_apply_overlay_check(13, 13, 1, 0, I2C_OVERLAY))
return;
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)
{
int ret;
/* device should enable */
ret = of_unittest_apply_overlay_check(15, 15, 0, 1, I2C_OVERLAY);
if (ret != 0)
if (of_unittest_apply_overlay_check(15, 15, 0, 1, I2C_OVERLAY))
return;
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)
{
struct device_node *bus_np = NULL;
int ret;
ret = platform_driver_register(&unittest_driver);
if (ret != 0) {
if (platform_driver_register(&unittest_driver)) {
unittest(0, "could not register unittest driver\n");
goto out;
}
@ -1941,8 +2050,7 @@ static void __init of_unittest_overlay(void)
goto out;
}
ret = of_platform_default_populate(bus_np, NULL, NULL);
if (ret != 0) {
if (of_platform_default_populate(bus_np, NULL, NULL)) {
unittest(0, "could not populate bus @ \"%s\"\n", bus_path);
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;
if (!size) {
if (!size)
pr_err("no overlay data for %s\n", overlay_name);
ret = 0;
}
ret = of_overlay_fdt_apply(info->dtb_begin, size, &info->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 **pprev;
struct property *prop;
int ret;
if (!overlay_base_root) {
unittest(0, "overlay_base_root not initialized\n");
@ -2284,19 +2389,15 @@ static __init void of_unittest_overlay_high_level(void)
prop->name);
goto err_unlock;
}
ret = __of_add_property(of_symbols, new_prop);
if (ret) {
if (!strcmp(new_prop->name, "name")) {
/* auto-generated by unflatten */
ret = 0;
if (__of_add_property(of_symbols, new_prop)) {
/* "name" auto-generated by unflatten */
if (!strcmp(new_prop->name, "name"))
continue;
}
unittest(0, "duplicate property '%s' in overlay_base node __symbols__",
prop->name);
goto err_unlock;
}
ret = __of_add_property_sysfs(of_symbols, new_prop);
if (ret) {
if (__of_add_property_sysfs(of_symbols, new_prop)) {
unittest(0, "unable to add property '%s' in overlay_base node __symbols__ to sysfs",
prop->name);
goto err_unlock;
@ -2355,6 +2456,7 @@ static int __init of_unittest(void)
of_unittest_find_node_by_name();
of_unittest_dynamic();
of_unittest_parse_phandle_with_args();
of_unittest_parse_phandle_with_args_map();
of_unittest_printf();
of_unittest_property_string();
of_unittest_property_copy();

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LIBFDT_ENV_H
#define _LIBFDT_ENV_H
#ifndef LIBFDT_ENV_H
#define LIBFDT_ENV_H
#include <linux/string.h>
@ -15,4 +15,4 @@ typedef __be64 fdt64_t;
#define fdt64_to_cpu(x) be64_to_cpu(x)
#define cpu_to_fdt64(x) cpu_to_be64(x)
#endif /* _LIBFDT_ENV_H */
#endif /* LIBFDT_ENV_H */

View File

@ -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,
const char *list_name, const char *cells_name, int index,
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,
const char *list_name, int cells_count, int index,
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;
}
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,
const char *list_name, int cells_count, int index,
struct of_phandle_args *out_args)

View File

@ -210,7 +210,7 @@ $(filter %.tab.c,$(targets)): $(obj)/%.tab.c: $(src)/%.y FORCE
$(call if_changed,bison)
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
.PRECIOUS: $(src)/%.tab.h_shipped
@ -269,10 +269,9 @@ DTC ?= $(objtree)/scripts/dtc/dtc
# Disable noisy checks by default
ifeq ($(findstring 1,$(KBUILD_ENABLE_EXTRA_GCC_CHECKS)),)
DTC_FLAGS += -Wno-unit_address_vs_reg \
-Wno-simple_bus_reg \
-Wno-unit_address_format \
-Wno-pci_bridge \
-Wno-pci_device_bus_num \
-Wno-avoid_unnecessary_addr_size \
-Wno-alias_paths \
-Wno-pci_device_reg
endif
@ -309,7 +308,7 @@ cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \
-d $(depfile).dtc.tmp $(dtc-tmp) ; \
cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile)
$(obj)/%.dtb: $(src)/%.dts FORCE
$(obj)/%.dtb: $(src)/%.dts $(DTC) FORCE
$(call if_changed_dep,dtc)
dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp)

View File

@ -28,5 +28,7 @@ HOSTCFLAGS_dtc-parser.tab.o := $(HOSTCFLAGS_DTC)
# dependencies on generated files need to be listed explicitly
$(obj)/dtc-lexer.lex.o: $(obj)/dtc-parser.tab.h
# generated files need to be cleaned explicitly
clean-files := dtc-lexer.lex.c dtc-parser.tab.c dtc-parser.tab.h
# generated files need to include *.cmd and be cleaned explicitly
generated-files := dtc-lexer.lex.c dtc-parser.tab.c dtc-parser.tab.h
targets := $(generated-files)
clean-files := $(generated-files)

View File

@ -53,26 +53,28 @@ struct check {
struct check **prereq;
};
#define CHECK_ENTRY(_nm, _fn, _d, _w, _e, ...) \
static struct check *_nm##_prereqs[] = { __VA_ARGS__ }; \
static struct check _nm = { \
.name = #_nm, \
.fn = (_fn), \
.data = (_d), \
.warn = (_w), \
.error = (_e), \
#define CHECK_ENTRY(nm_, fn_, d_, w_, e_, ...) \
static struct check *nm_##_prereqs[] = { __VA_ARGS__ }; \
static struct check nm_ = { \
.name = #nm_, \
.fn = (fn_), \
.data = (d_), \
.warn = (w_), \
.error = (e_), \
.status = UNCHECKED, \
.num_prereqs = ARRAY_SIZE(_nm##_prereqs), \
.prereq = _nm##_prereqs, \
.num_prereqs = ARRAY_SIZE(nm_##_prereqs), \
.prereq = nm_##_prereqs, \
};
#define WARNING(_nm, _fn, _d, ...) \
CHECK_ENTRY(_nm, _fn, _d, true, false, __VA_ARGS__)
#define ERROR(_nm, _fn, _d, ...) \
CHECK_ENTRY(_nm, _fn, _d, false, true, __VA_ARGS__)
#define CHECK(_nm, _fn, _d, ...) \
CHECK_ENTRY(_nm, _fn, _d, false, false, __VA_ARGS__)
#define WARNING(nm_, fn_, d_, ...) \
CHECK_ENTRY(nm_, fn_, d_, true, false, __VA_ARGS__)
#define ERROR(nm_, fn_, d_, ...) \
CHECK_ENTRY(nm_, fn_, d_, false, true, __VA_ARGS__)
#define CHECK(nm_, fn_, d_, ...) \
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, ...)
{
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): ",
strcmp(dti->outname, "-") ? dti->outname : "<stdout>",
(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);
fprintf(stderr, "\n");
}
va_end(ap);
}
#define FAIL(c, dti, ...) \
#define FAIL(c, dti, node, ...) \
do { \
TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
(c)->status = FAILED; \
check_msg((c), dti, __VA_ARGS__); \
check_msg((c), dti, node, NULL, __VA_ARGS__); \
} 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)
{
struct node *child;
@ -126,7 +142,7 @@ static bool run_check(struct check *c, struct dt_info *dti)
error = error || run_check(prq, dti);
if (prq->status != PASSED) {
c->status = PREREQ;
check_msg(c, dti, "Failed prerequisite '%s'",
check_msg(c, dti, NULL, NULL, "Failed prerequisite '%s'",
c->prereq[i]->name);
}
}
@ -156,7 +172,7 @@ out:
static inline void check_always_fail(struct check *c, struct dt_info *dti,
struct node *node)
{
FAIL(c, dti, "always_fail check");
FAIL(c, dti, node, "always_fail check");
}
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 */
if (!data_is_one_string(prop->val))
FAIL(c, dti, "\"%s\" property in %s is not a string",
propname, node->fullpath);
FAIL_PROP(c, dti, node, prop, "property is not a string");
}
#define WARNING_IF_NOT_STRING(nm, propname) \
WARNING(nm, check_is_string, (propname))
#define ERROR_IF_NOT_STRING(nm, 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,
struct node *node)
{
@ -190,8 +234,7 @@ static void check_is_cell(struct check *c, struct dt_info *dti,
return; /* Not present, assumed ok */
if (prop->val.len != sizeof(cell_t))
FAIL(c, dti, "\"%s\" property in %s is not a single cell",
propname, node->fullpath);
FAIL_PROP(c, dti, node, prop, "property is not a single cell");
}
#define WARNING_IF_NOT_CELL(nm, 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->next_sibling)
if (streq(child->name, child2->name))
FAIL(c, dti, "Duplicate node name %s",
child->fullpath);
FAIL(c, dti, node, "Duplicate node name");
}
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)
continue;
if (streq(prop->name, prop2->name))
FAIL(c, dti, "Duplicate property name %s in %s",
prop->name, node->fullpath);
FAIL_PROP(c, dti, node, prop, "Duplicate property name");
}
}
}
@ -246,8 +287,8 @@ static void check_node_name_chars(struct check *c, struct dt_info *dti,
int n = strspn(node->name, c->data);
if (n < strlen(node->name))
FAIL(c, dti, "Bad character '%c' in node %s",
node->name[n], node->fullpath);
FAIL(c, dti, node, "Bad character '%c' in node name",
node->name[n]);
}
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);
if (n < node->basenamelen)
FAIL(c, dti, "Character '%c' not recommended in node %s",
node->name[n], node->fullpath);
FAIL(c, dti, node, "Character '%c' not recommended in node name",
node->name[n]);
}
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)
{
if (strchr(get_unitname(node), '@'))
FAIL(c, dti, "Node %s has multiple '@' characters in name",
node->fullpath);
FAIL(c, dti, node, "multiple '@' characters in node name");
}
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 (!unitname[0])
FAIL(c, dti, "Node %s has a reg or ranges property, but no unit name",
node->fullpath);
FAIL(c, dti, node, "node has a reg or ranges property, but no unit name");
} else {
if (unitname[0])
FAIL(c, dti, "Node %s has a unit name, but no reg property",
node->fullpath);
FAIL(c, dti, node, "node has a unit name, but no reg property");
}
}
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);
if (n < strlen(prop->name))
FAIL(c, dti, "Bad character '%c' in property name \"%s\", node %s",
prop->name[n], prop->name, node->fullpath);
FAIL_PROP(c, dti, node, prop, "Bad character '%c' in property name",
prop->name[n]);
}
}
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);
}
if (n < strlen(name))
FAIL(c, dti, "Character '%c' not recommended in property name \"%s\", node %s",
name[n], prop->name, node->fullpath);
FAIL_PROP(c, dti, node, prop, "Character '%c' not recommended in property name",
name[n]);
}
}
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;
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,
label, DESCLABEL_ARGS(node, prop, mark),
DESCLABEL_ARGS(othernode, otherprop, othermark));
@ -410,8 +448,8 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
return 0;
if (prop->val.len != sizeof(cell_t)) {
FAIL(c, dti, "%s has bad length (%d) %s property",
node->fullpath, prop->val.len, prop->name);
FAIL_PROP(c, dti, node, prop, "bad length (%d) %s property",
prop->val.len, prop->name);
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
* other node's phandle". That's nonsensical
* by construction. */ {
FAIL(c, dti, "%s in %s is a reference to another node",
prop->name, node->fullpath);
FAIL(c, dti, node, "%s is a reference to another node",
prop->name);
}
/* But setting this node's phandle equal to its own
* 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);
if ((phandle == 0) || (phandle == -1)) {
FAIL(c, dti, "%s has bad value (0x%x) in %s property",
node->fullpath, phandle, prop->name);
FAIL_PROP(c, dti, node, prop, "bad value (0x%x) in %s property",
phandle, prop->name);
return 0;
}
@ -463,16 +501,16 @@ static void check_explicit_phandles(struct check *c, struct dt_info *dti,
return;
if (linux_phandle && phandle && (phandle != linux_phandle))
FAIL(c, dti, "%s has mismatching 'phandle' and 'linux,phandle'"
" properties", node->fullpath);
FAIL(c, dti, node, "mismatching 'phandle' and 'linux,phandle'"
" properties");
if (linux_phandle && !phandle)
phandle = linux_phandle;
other = get_node_by_phandle(root, phandle);
if (other && (other != node)) {
FAIL(c, dti, "%s has duplicated phandle 0x%x (seen before at %s)",
node->fullpath, phandle, other->fullpath);
FAIL(c, dti, node, "duplicated phandle 0x%x (seen before at %s)",
phandle, other->fullpath);
return;
}
@ -496,8 +534,8 @@ static void check_name_properties(struct check *c, struct dt_info *dti,
if ((prop->val.len != node->basenamelen+1)
|| (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
FAIL(c, dti, "\"name\" property in %s is incorrect (\"%s\" instead"
" of base node name)", node->fullpath, prop->val.val);
FAIL(c, dti, node, "\"name\" property is incorrect (\"%s\" instead"
" of base node name)", prop->val.val);
} else {
/* The name property is correct, and therefore redundant.
* 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);
if (! refnode) {
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);
else /* mark the entry as unresolved */
*((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);
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);
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(model_is_string, "model");
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,
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 */
if (!node->parent) {
FAIL(c, dti, "Root node has a \"reg\" property");
FAIL(c, dti, node, "Root node has a \"reg\" property");
return;
}
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);
size_cells = node_size_cells(node->parent);
entrylen = (addr_cells + size_cells) * sizeof(cell_t);
if (!entrylen || (prop->val.len % entrylen) != 0)
FAIL(c, dti, "\"reg\" property in %s has invalid length (%d bytes) "
"(#address-cells == %d, #size-cells == %d)",
node->fullpath, prop->val.len, addr_cells, size_cells);
FAIL_PROP(c, dti, node, prop, "property has invalid length (%d bytes) "
"(#address-cells == %d, #size-cells == %d)",
prop->val.len, addr_cells, 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;
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;
}
@ -663,20 +740,20 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,
if (prop->val.len == 0) {
if (p_addr_cells != c_addr_cells)
FAIL(c, dti, "%s has empty \"ranges\" property but its "
"#address-cells (%d) differs from %s (%d)",
node->fullpath, c_addr_cells, node->parent->fullpath,
p_addr_cells);
FAIL_PROP(c, dti, node, prop, "empty \"ranges\" property but its "
"#address-cells (%d) differs from %s (%d)",
c_addr_cells, node->parent->fullpath,
p_addr_cells);
if (p_size_cells != c_size_cells)
FAIL(c, dti, "%s has empty \"ranges\" property but its "
"#size-cells (%d) differs from %s (%d)",
node->fullpath, c_size_cells, node->parent->fullpath,
p_size_cells);
FAIL_PROP(c, dti, node, prop, "empty \"ranges\" property but its "
"#size-cells (%d) differs from %s (%d)",
c_size_cells, node->parent->fullpath,
p_size_cells);
} else if ((prop->val.len % entrylen) != 0) {
FAIL(c, dti, "\"ranges\" property in %s has invalid length (%d bytes) "
"(parent #address-cells == %d, child #address-cells == %d, "
"#size-cells == %d)", node->fullpath, prop->val.len,
p_addr_cells, c_addr_cells, c_size_cells);
FAIL_PROP(c, dti, node, prop, "\"ranges\" property has invalid length (%d bytes) "
"(parent #address-cells == %d, child #address-cells == %d, "
"#size-cells == %d)", prop->val.len,
p_addr_cells, c_addr_cells, c_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;
if (!strneq(node->name, "pci", node->basenamelen) &&
!strneq(node->name, "pcie", node->basenamelen))
FAIL(c, dti, "Node %s node name is not \"pci\" or \"pcie\"",
node->fullpath);
if (!strprefixeq(node->name, node->basenamelen, "pci") &&
!strprefixeq(node->name, node->basenamelen, "pcie"))
FAIL(c, dti, node, "node name is not \"pci\" or \"pcie\"");
prop = get_property(node, "ranges");
if (!prop)
FAIL(c, dti, "Node %s missing ranges for PCI bridge (or not a bridge)",
node->fullpath);
FAIL(c, dti, node, "missing ranges for PCI bridge (or not a bridge)");
if (node_addr_cells(node) != 3)
FAIL(c, dti, "Node %s incorrect #address-cells for PCI bridge",
node->fullpath);
FAIL(c, dti, node, "incorrect #address-cells for PCI bridge");
if (node_size_cells(node) != 2)
FAIL(c, dti, "Node %s incorrect #size-cells for PCI bridge",
node->fullpath);
FAIL(c, dti, node, "incorrect #size-cells for PCI bridge");
prop = get_property(node, "bus-range");
if (!prop) {
FAIL(c, dti, "Node %s missing bus-range for PCI bridge",
node->fullpath);
FAIL(c, dti, node, "missing bus-range for PCI bridge");
return;
}
if (prop->val.len != (sizeof(cell_t) * 2)) {
FAIL(c, dti, "Node %s bus-range must be 2 cells",
node->fullpath);
FAIL_PROP(c, dti, node, prop, "value must be 2 cells");
return;
}
cells = (cell_t *)prop->val.val;
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",
node->fullpath);
FAIL_PROP(c, dti, node, prop, "1st cell must be less than or equal to 2nd cell");
if (fdt32_to_cpu(cells[1]) > 0xff)
FAIL(c, dti, "Node %s bus-range maximum bus number must be less than 256",
node->fullpath);
FAIL_PROP(c, dti, node, prop, "maximum bus number must be less than 256");
}
WARNING(pci_bridge, check_pci_bridge, NULL,
&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]);
}
if ((bus_num < min_bus) || (bus_num > max_bus))
FAIL(c, dti, "Node %s PCI bus number %d out of range, expected (%d - %d)",
node->fullpath, bus_num, min_bus, max_bus);
FAIL_PROP(c, dti, node, prop, "PCI bus number %d out of range, expected (%d - %d)",
bus_num, min_bus, max_bus);
}
WARNING(pci_device_bus_num, check_pci_device_bus_num, NULL, &reg_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");
if (!prop) {
FAIL(c, dti, "Node %s missing PCI reg property", node->fullpath);
FAIL(c, dti, node, "missing PCI reg property");
return;
}
cells = (cell_t *)prop->val.val;
if (cells[1] || cells[2])
FAIL(c, dti, "Node %s PCI reg config space address cells 2 and 3 must be 0",
node->fullpath);
FAIL_PROP(c, dti, node, prop, "PCI reg config space address cells 2 and 3 must be 0");
reg = fdt32_to_cpu(cells[0]);
dev = (reg & 0xf800) >> 11;
func = (reg & 0x700) >> 8;
if (reg & 0xff000000)
FAIL(c, dti, "Node %s PCI reg address is not configuration space",
node->fullpath);
FAIL_PROP(c, dti, node, prop, "PCI reg address is not configuration space");
if (reg & 0x000000ff)
FAIL(c, dti, "Node %s PCI reg config space address register number must be 0",
node->fullpath);
FAIL_PROP(c, dti, node, prop, "PCI reg config space address register number must be 0");
if (func == 0) {
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))
return;
FAIL(c, dti, "Node %s PCI unit address format error, expected \"%s\"",
node->fullpath, unit_addr);
FAIL(c, dti, node, "PCI unit address format error, expected \"%s\"",
unit_addr);
}
WARNING(pci_device_reg, check_pci_device_reg, NULL, &reg_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;
str += strnlen(str, end - str) + 1) {
if (strneq(str, compat, end - str))
if (strprefixeq(str, end - str, compat))
return true;
}
return false;
@ -865,7 +931,7 @@ static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct no
if (!cells) {
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;
}
@ -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);
if (!streq(unitname, unit_addr))
FAIL(c, dti, "Node %s simple-bus unit address format error, expected \"%s\"",
node->fullpath, unit_addr);
FAIL(c, dti, node, "simple-bus unit address format error, expected \"%s\"",
unit_addr);
}
WARNING(simple_bus_reg, check_simple_bus_reg, NULL, &reg_format, &simple_bus_bridge);
@ -892,14 +958,12 @@ static void check_unit_address_format(struct check *c, struct dt_info *dti,
return;
if (!strncmp(unitname, "0x", 2)) {
FAIL(c, dti, "Node %s unit name should not have leading \"0x\"",
node->fullpath);
FAIL(c, dti, node, "unit name should not have leading \"0x\"");
/* skip over 0x for next test */
unitname += 2;
}
if (unitname[0] == '0' && isxdigit(unitname[1]))
FAIL(c, dti, "Node %s unit name should not have leading 0s",
node->fullpath);
FAIL(c, dti, node, "unit name should not have leading 0s");
}
WARNING(unit_address_format, check_unit_address_format, NULL,
&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;
if (node->parent->addr_cells == -1)
FAIL(c, dti, "Relying on default #address-cells value for %s",
node->fullpath);
FAIL(c, dti, node, "Relying on default #address-cells value");
if (node->parent->size_cells == -1)
FAIL(c, dti, "Relying on default #size-cells value for %s",
node->fullpath);
FAIL(c, dti, node, "Relying on default #size-cells value");
}
WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL,
&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,
struct dt_info *dti,
struct node *node)
@ -950,12 +1036,61 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c,
prop = get_property(chosen, "interrupt-controller");
if (prop)
FAIL(c, dti, "/chosen has obsolete \"interrupt-controller\" "
"property");
FAIL_PROP(c, dti, node, prop,
"/chosen has obsolete \"interrupt-controller\" property");
}
WARNING(obsolete_chosen_interrupt_controller,
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 {
const char *prop_name;
const char *cell_name;
@ -972,8 +1107,9 @@ static void check_property_phandle_args(struct check *c,
int cell, cellsize = 0;
if (prop->val.len % sizeof(cell_t)) {
FAIL(c, dti, "property '%s' size (%d) is invalid, expected multiple of %zu in node %s",
prop->name, prop->val.len, sizeof(cell_t), node->fullpath);
FAIL_PROP(c, dti, node, prop,
"property size (%d) is invalid, expected multiple of %zu",
prop->val.len, sizeof(cell_t));
return;
}
@ -1004,14 +1140,16 @@ static void check_property_phandle_args(struct check *c,
break;
}
if (!m)
FAIL(c, dti, "Property '%s', cell %d is not a phandle reference in %s",
prop->name, cell, node->fullpath);
FAIL_PROP(c, dti, node, prop,
"cell %d is not a phandle reference",
cell);
}
provider_node = get_node_by_phandle(root, phandle);
if (!provider_node) {
FAIL(c, dti, "Could not get phandle node for %s:%s(cell %d)",
node->fullpath, prop->name, cell);
FAIL_PROP(c, dti, node, prop,
"Could not get phandle node for (cell %d)",
cell);
break;
}
@ -1021,16 +1159,17 @@ static void check_property_phandle_args(struct check *c,
} else if (provider->optional) {
cellsize = 0;
} 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_node->fullpath,
node->fullpath, prop->name, cell);
prop->name, cell);
break;
}
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",
prop->name, prop->val.len, cellsize, node->fullpath);
FAIL_PROP(c, dti, node, prop,
"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(pwms, "pwms", "#pwm-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");
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"))
continue;
FAIL(c, dti, "'[*-]gpio' is deprecated, use '[*-]gpios' instead for %s:%s",
node->fullpath, prop->name);
FAIL_PROP(c, dti, node, prop,
"'[*-]gpio' is deprecated, use '[*-]gpios' instead");
}
}
@ -1167,9 +1306,8 @@ static void check_interrupts_property(struct check *c,
return;
if (irq_prop->val.len % sizeof(cell_t))
FAIL(c, dti, "property '%s' size (%d) is invalid, expected multiple of %zu in node %s",
irq_prop->name, irq_prop->val.len, sizeof(cell_t),
node->fullpath);
FAIL_PROP(c, dti, node, irq_prop, "size (%d) is invalid, expected multiple of %zu",
irq_prop->val.len, sizeof(cell_t));
while (parent && !prop) {
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);
if (!irq_node) {
FAIL(c, dti, "Bad interrupt-parent phandle for %s",
node->fullpath);
FAIL_PROP(c, dti, parent, prop, "Bad phandle");
return;
}
if (!node_is_interrupt_provider(irq_node))
FAIL(c, dti,
"Missing interrupt-controller or interrupt-map property in %s",
irq_node->fullpath);
FAIL(c, dti, irq_node,
"Missing interrupt-controller or interrupt-map property");
break;
}
@ -1203,23 +1339,21 @@ static void check_interrupts_property(struct check *c,
}
if (!irq_node) {
FAIL(c, dti, "Missing interrupt-parent for %s", node->fullpath);
FAIL(c, dti, node, "Missing interrupt-parent");
return;
}
prop = get_property(irq_node, "#interrupt-cells");
if (!prop) {
FAIL(c, dti, "Missing #interrupt-cells in interrupt-parent %s",
irq_node->fullpath);
FAIL(c, dti, irq_node, "Missing #interrupt-cells in interrupt-parent");
return;
}
irq_cells = propval_cell(prop);
if (irq_prop->val.len % (irq_cells * sizeof(cell_t))) {
FAIL(c, dti,
"interrupts size is (%d), expected multiple of %d in %s",
irq_prop->val.len, (int)(irq_cells * sizeof(cell_t)),
node->fullpath);
FAIL_PROP(c, dti, node, prop,
"size is (%d), expected multiple of %d",
irq_prop->val.len, (int)(irq_cells * sizeof(cell_t)));
}
}
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,
&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,
&node_name_chars_strict,
@ -1253,7 +1390,9 @@ static struct check *check_table[] = {
&simple_bus_reg,
&avoid_default_addr_size,
&avoid_unnecessary_addr_size,
&obsolete_chosen_interrupt_controller,
&chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path,
&clocks_property,
&cooling_device_property,
@ -1269,13 +1408,15 @@ static struct check *check_table[] = {
&power_domains_property,
&pwms_property,
&resets_property,
&sound_dais_property,
&sound_dai_property,
&thermal_sensors_property,
&deprecated_gpio_property,
&gpios_property,
&interrupts_property,
&alias_paths,
&always_fail,
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -166,7 +166,17 @@ devicetree:
{
$$ = 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
{
struct node *target = get_node_by_ref($1, $3);
@ -209,11 +219,6 @@ devicetree:
$$ = $1;
}
| /* empty */
{
/* build empty node */
$$ = name_node(build_node(NULL, NULL), "");
}
;
nodedef:

View File

@ -59,8 +59,6 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
}
/* 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_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@Ahv";
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\tdtb - device tree blob\n"
"\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\tMake space for <number> reserve map entries (for dtb and asm output)",
"\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;
fill_fullpaths(dti->dt, "");
process_checks(force, dti);
/* on a plugin, generate by default */
if (dti->dtsflags & DTSF_PLUGIN) {
generate_fixups = 1;
}
process_checks(force, dti);
if (auto_label_aliases)
generate_label_tree(dti, "aliases", false);

View File

@ -1,5 +1,5 @@
#ifndef _DTC_H
#define _DTC_H
#ifndef DTC_H
#define DTC_H
/*
* (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 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))
@ -203,7 +204,7 @@ struct node *build_node_delete(void);
struct node *name_node(struct node *node, char *name);
struct node *chain_node(struct node *first, struct node *list);
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 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);
#endif /* _DTC_H */
#endif /* DTC_H */

View File

@ -731,7 +731,7 @@ static char *nodename_from_path(const char *ppath, const char *cpath)
plen = strlen(ppath);
if (!strneq(ppath, cpath, plen))
if (!strstarts(cpath, ppath))
die("Path \"%s\" is not valid as a child of \"%s\"\n",
cpath, ppath);

View File

@ -88,7 +88,7 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
|| ((offset + len) > fdt_size_dt_struct(fdt)))
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)
@ -123,6 +123,9 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
/* skip-name offset, length and value */
offset += sizeof(struct fdt_property) - FDT_TAGSIZE
+ fdt32_to_cpu(*lenp);
if (fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
offset += 4;
break;
case FDT_END:
@ -141,7 +144,7 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
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)
|| (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;
}
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)
|| (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;
if (offset >= 0)
if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0)
if ((nextoffset = fdt_check_node_offset_(fdt, offset)) < 0)
return nextoffset;
do {
@ -227,7 +230,7 @@ int fdt_next_subnode(const void *fdt, int 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;
const char *last = strtab + tabsize - len;

View File

@ -1,5 +1,5 @@
#ifndef _FDT_H
#define _FDT_H
#ifndef FDT_H
#define FDT_H
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
@ -108,4 +108,4 @@ struct fdt_property {
#define FDT_V16_SIZE FDT_V3_SIZE
#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(fdt32_t))
#endif /* _FDT_H */
#endif /* FDT_H */

View File

@ -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 <fdt.h>

View File

@ -55,12 +55,13 @@
#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 *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 */
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;
}
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 *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)
{
FDT_CHECK_HEADER(fdt);
*address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address);
*size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size);
*address = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->address);
*size = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->size);
return 0;
}
@ -126,12 +127,12 @@ int fdt_num_mem_rsv(const void *fdt)
{
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++;
return i;
}
static int _nextprop(const void *fdt, int offset)
static int nextprop_(const void *fdt, int offset)
{
uint32_t tag;
int nextoffset;
@ -166,7 +167,7 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset,
(offset >= 0) && (depth >= 0);
offset = fdt_next_node(fdt, offset, &depth))
if ((depth == 1)
&& _fdt_nodename_eq(fdt, offset, name, namelen))
&& fdt_nodename_eq_(fdt, offset, name, namelen))
return offset;
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 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;
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;
if (len)
*len = strlen(nh->name);
nameptr = 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:
if (len)
@ -254,34 +273,34 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset)
{
int offset;
if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
if ((offset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
return offset;
return _nextprop(fdt, offset);
return nextprop_(fdt, 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 _nextprop(fdt, offset);
return nextprop_(fdt, offset);
}
const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
int offset,
int *lenp)
static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
int offset,
int *lenp)
{
int err;
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)
*lenp = err;
return NULL;
}
prop = _fdt_offset_ptr(fdt, offset);
prop = fdt_offset_ptr_(fdt, offset);
if (lenp)
*lenp = fdt32_to_cpu(prop->len);
@ -289,23 +308,44 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
return prop;
}
const struct fdt_property *fdt_get_property_namelen(const void *fdt,
int offset,
const char *name,
int namelen, int *lenp)
const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
int offset,
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);
(offset >= 0);
(offset = fdt_next_property_offset(fdt, offset))) {
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;
break;
}
if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff),
name, namelen))
if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff),
name, namelen)) {
if (poffset)
*poffset = offset;
return prop;
}
}
if (lenp)
@ -313,6 +353,25 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt,
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,
int nodeoffset,
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 char *name, int namelen, int *lenp)
{
int poffset;
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)
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;
}
@ -338,11 +403,16 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
{
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)
return NULL;
if (namep)
*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;
}

View File

@ -55,8 +55,8 @@
#include "libfdt_internal.h"
static int _fdt_blocks_misordered(const void *fdt,
int mem_rsv_size, int struct_size)
static int fdt_blocks_misordered_(const void *fdt,
int mem_rsv_size, int struct_size)
{
return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8))
|| (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)));
}
static int _fdt_rw_check_header(void *fdt)
static int fdt_rw_check_header_(void *fdt)
{
FDT_CHECK_HEADER(fdt);
if (fdt_version(fdt) < 17)
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)))
return -FDT_ERR_BADLAYOUT;
if (fdt_version(fdt) > 17)
@ -84,20 +84,20 @@ static int _fdt_rw_check_header(void *fdt)
#define FDT_RW_CHECK_HEADER(fdt) \
{ \
int __err; \
if ((__err = _fdt_rw_check_header(fdt)) != 0) \
return __err; \
int err_; \
if ((err_ = fdt_rw_check_header_(fdt)) != 0) \
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);
}
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 *end = (char *)fdt + _fdt_data_size(fdt);
char *end = (char *)fdt + fdt_data_size_(fdt);
if (((p + oldlen) < p) || ((p + oldlen) > end))
return -FDT_ERR_BADOFFSET;
@ -109,12 +109,12 @@ static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)
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 delta = (newn - oldn) * sizeof(*p);
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)
return err;
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;
}
static int _fdt_splice_struct(void *fdt, void *p,
static int fdt_splice_struct_(void *fdt, void *p,
int oldlen, int newlen)
{
int delta = newlen - oldlen;
int err;
if ((err = _fdt_splice(fdt, p, oldlen, newlen)))
if ((err = fdt_splice_(fdt, p, oldlen, newlen)))
return err;
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;
}
static int _fdt_splice_string(void *fdt, int newlen)
static int fdt_splice_string_(void *fdt, int newlen)
{
void *p = (char *)fdt
+ fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
int err;
if ((err = _fdt_splice(fdt, p, 0, newlen)))
if ((err = fdt_splice_(fdt, p, 0, newlen)))
return err;
fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);
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);
const char *p;
@ -157,13 +157,13 @@ static int _fdt_find_add_string(void *fdt, const char *s)
int len = strlen(s) + 1;
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)
/* found it */
return (p - strtab);
new = strtab + fdt_size_dt_strings(fdt);
err = _fdt_splice_string(fdt, len);
err = fdt_splice_string_(fdt, len);
if (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);
re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt));
err = _fdt_splice_mem_rsv(fdt, re, 0, 1);
re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt));
err = fdt_splice_mem_rsv_(fdt, re, 0, 1);
if (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)
{
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);
if (n >= fdt_num_mem_rsv(fdt))
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 oldlen;
@ -210,7 +210,7 @@ static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
if (!*prop)
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))))
return err;
@ -218,7 +218,7 @@ static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
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 proplen;
@ -226,17 +226,17 @@ static int _fdt_add_property(void *fdt, int nodeoffset, const char *name,
int namestroff;
int err;
if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
return nextoffset;
namestroff = _fdt_find_add_string(fdt, name);
namestroff = fdt_find_add_string_(fdt, name);
if (namestroff < 0)
return namestroff;
*prop = _fdt_offset_ptr_w(fdt, nextoffset);
*prop = fdt_offset_ptr_w_(fdt, nextoffset);
proplen = sizeof(**prop) + FDT_TAGALIGN(len);
err = _fdt_splice_struct(fdt, *prop, 0, proplen);
err = fdt_splice_struct_(fdt, *prop, 0, proplen);
if (err)
return err;
@ -260,7 +260,7 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *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));
if (err)
return err;
@ -277,9 +277,9 @@ int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
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)
err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
err = fdt_add_property_(fdt, nodeoffset, name, len, &prop);
if (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);
if (prop) {
newlen = len + oldlen;
err = _fdt_splice_struct(fdt, prop->data,
err = fdt_splice_struct_(fdt, prop->data,
FDT_TAGALIGN(oldlen),
FDT_TAGALIGN(newlen));
if (err)
@ -321,7 +321,7 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
prop->len = cpu_to_fdt32(newlen);
memcpy(prop->data + oldlen, val, len);
} else {
err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
err = fdt_add_property_(fdt, nodeoffset, name, len, &prop);
if (err)
return err;
memcpy(prop->data, val, len);
@ -341,7 +341,7 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name)
return 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,
@ -369,10 +369,10 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
tag = fdt_next_tag(fdt, offset, &nextoffset);
} 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;
err = _fdt_splice_struct(fdt, nh, 0, nodelen);
err = fdt_splice_struct_(fdt, nh, 0, nodelen);
if (err)
return err;
@ -396,15 +396,15 @@ int fdt_del_node(void *fdt, int nodeoffset)
FDT_RW_CHECK_HEADER(fdt);
endoffset = _fdt_node_end_offset(fdt, nodeoffset);
endoffset = fdt_node_end_offset_(fdt, nodeoffset);
if (endoffset < 0)
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);
}
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_off, struct_off, strings_off;
@ -450,7 +450,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
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 */
err = fdt_move(fdt, buf, bufsize);
if (err)
@ -478,7 +478,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
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);
fdt_set_magic(buf, FDT_MAGIC);
@ -498,8 +498,8 @@ int fdt_pack(void *fdt)
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
* sizeof(struct fdt_reserve_entry);
_fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
fdt_set_totalsize(fdt, _fdt_data_size(fdt));
fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
fdt_set_totalsize(fdt, fdt_data_size_(fdt));
return 0;
}

View File

@ -55,7 +55,7 @@
#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)
return -FDT_ERR_BADMAGIC;
@ -66,11 +66,11 @@ static int _fdt_sw_check_header(void *fdt)
#define FDT_SW_CHECK_HEADER(fdt) \
{ \
int err; \
if ((err = _fdt_sw_check_header(fdt)) != 0) \
if ((err = fdt_sw_check_header_(fdt)) != 0) \
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 spaceleft;
@ -82,7 +82,7 @@ static void *_fdt_grab_space(void *fdt, size_t len)
return NULL;
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)
@ -174,7 +174,7 @@ int fdt_begin_node(void *fdt, const char *name)
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)
return -FDT_ERR_NOSPACE;
@ -189,7 +189,7 @@ int fdt_end_node(void *fdt)
FDT_SW_CHECK_HEADER(fdt);
en = _fdt_grab_space(fdt, FDT_TAGSIZE);
en = fdt_grab_space_(fdt, FDT_TAGSIZE);
if (! en)
return -FDT_ERR_NOSPACE;
@ -197,7 +197,7 @@ int fdt_end_node(void *fdt)
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);
const char *p;
@ -205,7 +205,7 @@ static int _fdt_find_add_string(void *fdt, const char *s)
int len = strlen(s) + 1;
int struct_top, offset;
p = _fdt_find_string(strtab - strtabsize, strtabsize, s);
p = fdt_find_string_(strtab - strtabsize, strtabsize, s);
if (p)
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);
nameoff = _fdt_find_add_string(fdt, name);
nameoff = fdt_find_add_string_(fdt, name);
if (nameoff == 0)
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)
return -FDT_ERR_NOSPACE;
@ -265,7 +265,7 @@ int fdt_finish(void *fdt)
FDT_SW_CHECK_HEADER(fdt);
/* Add terminator */
end = _fdt_grab_space(fdt, sizeof(*end));
end = fdt_grab_space_(fdt, sizeof(*end));
if (! end)
return -FDT_ERR_NOSPACE;
*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) {
if (tag == FDT_PROP) {
struct fdt_property *prop =
_fdt_offset_ptr_w(fdt, offset);
fdt_offset_ptr_w_(fdt, offset);
int nameoff;
nameoff = fdt32_to_cpu(prop->nameoff);

View File

@ -93,7 +93,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
val, len);
}
static void _fdt_nop_region(void *start, int len)
static void fdt_nop_region_(void *start, int len)
{
fdt32_t *p;
@ -110,12 +110,12 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
if (!prop)
return len;
_fdt_nop_region(prop, len + sizeof(*prop));
fdt_nop_region_(prop, len + sizeof(*prop));
return 0;
}
int _fdt_node_end_offset(void *fdt, int offset)
int fdt_node_end_offset_(void *fdt, int offset)
{
int depth = 0;
@ -129,11 +129,11 @@ int fdt_nop_node(void *fdt, int nodeoffset)
{
int endoffset;
endoffset = _fdt_node_end_offset(fdt, nodeoffset);
endoffset = fdt_node_end_offset_(fdt, nodeoffset);
if (endoffset < 0)
return endoffset;
_fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0),
fdt_nop_region_(fdt_offset_ptr_w(fdt, nodeoffset, 0),
endoffset - nodeoffset);
return 0;
}

View File

@ -1,5 +1,5 @@
#ifndef _LIBFDT_H
#define _LIBFDT_H
#ifndef LIBFDT_H
#define LIBFDT_H
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
@ -54,7 +54,7 @@
#include "libfdt_env.h"
#include "fdt.h"
#define FDT_FIRST_SUPPORTED_VERSION 0x10
#define FDT_FIRST_SUPPORTED_VERSION 0x02
#define FDT_LAST_SUPPORTED_VERSION 0x11
/* 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_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) \
{ \
struct fdt_header *fdth = (struct fdt_header *)fdt; \
fdth->name = cpu_to_fdt32(val); \
}
__fdt_set_hdr(magic);
__fdt_set_hdr(totalsize);
__fdt_set_hdr(off_dt_struct);
__fdt_set_hdr(off_dt_strings);
__fdt_set_hdr(off_mem_rsvmap);
__fdt_set_hdr(version);
__fdt_set_hdr(last_comp_version);
__fdt_set_hdr(boot_cpuid_phys);
__fdt_set_hdr(size_dt_strings);
__fdt_set_hdr(size_dt_struct);
#undef __fdt_set_hdr
fdt_set_hdr_(magic);
fdt_set_hdr_(totalsize);
fdt_set_hdr_(off_dt_struct);
fdt_set_hdr_(off_dt_strings);
fdt_set_hdr_(off_mem_rsvmap);
fdt_set_hdr_(version);
fdt_set_hdr_(last_comp_version);
fdt_set_hdr_(boot_cpuid_phys);
fdt_set_hdr_(size_dt_strings);
fdt_set_hdr_(size_dt_struct);
#undef fdt_set_hdr_
/**
* 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
* 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:
* pointer to the structure representing 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);
/**
* fdt_setprop _placeholder - allocate space for a property
* fdt_setprop_placeholder - allocate space for a property
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose 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);
#endif /* _LIBFDT_H */
#endif /* LIBFDT_H */

View File

@ -1,5 +1,5 @@
#ifndef _LIBFDT_ENV_H
#define _LIBFDT_ENV_H
#ifndef LIBFDT_ENV_H
#define LIBFDT_ENV_H
/*
* libfdt - Flat Device Tree manipulation
* 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 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 */

View File

@ -1,5 +1,5 @@
#ifndef _LIBFDT_INTERNAL_H
#define _LIBFDT_INTERNAL_H
#ifndef LIBFDT_INTERNAL_H
#define LIBFDT_INTERNAL_H
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
@ -57,27 +57,27 @@
#define FDT_CHECK_HEADER(fdt) \
{ \
int __err; \
if ((__err = fdt_check_header(fdt)) != 0) \
return __err; \
int err_; \
if ((err_ = fdt_check_header(fdt)) != 0) \
return err_; \
}
int _fdt_check_node_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);
int _fdt_node_end_offset(void *fdt, int nodeoffset);
int fdt_check_node_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);
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;
}
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 *)
@ -85,11 +85,11 @@ static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int
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)
#endif /* _LIBFDT_INTERNAL_H */
#endif /* LIBFDT_INTERNAL_H */

View File

@ -216,7 +216,7 @@ struct node *merge_nodes(struct node *old_node, struct node *new_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;
struct node *node;
@ -236,6 +236,7 @@ void add_orphan_node(struct node *dt, struct node *new_node, char *ref)
name_node(node, name);
add_child(dt, node);
return dt;
}
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) {
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);
else if (!p && streq(path, child->name))
return child;
@ -540,7 +541,10 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
{
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->deleted)

View File

@ -209,8 +209,6 @@ struct srcpos srcpos_empty = {
.file = NULL,
};
#define TAB_SIZE 8
void srcpos_update(struct srcpos *pos, const char *text, int len)
{
int i;
@ -224,9 +222,6 @@ void srcpos_update(struct srcpos *pos, const char *text, int len)
if (text[i] == '\n') {
current_srcfile->lineno++;
current_srcfile->colno = 1;
} else if (text[i] == '\t') {
current_srcfile->colno =
ALIGN(current_srcfile->colno, TAB_SIZE);
} else {
current_srcfile->colno++;
}

View File

@ -17,8 +17,8 @@
* USA
*/
#ifndef _SRCPOS_H_
#define _SRCPOS_H_
#ifndef SRCPOS_H
#define SRCPOS_H
#include <stdio.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);
#endif /* _SRCPOS_H_ */
#endif /* SRCPOS_H */

View File

@ -4,7 +4,7 @@
#
# 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
# 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
# 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 \
srcpos.h treesource.c util.c util.h version_gen.h Makefile.dtc \
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 \
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"
@ -59,10 +58,6 @@ for f in $DTC_SOURCE; do
cp ${DTC_UPSTREAM_PATH}/${f} ${f}
git add ${f}
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
cp ${DTC_UPSTREAM_PATH}/libfdt/${f} libfdt/${f}
git add libfdt/${f}

View File

@ -1,5 +1,5 @@
#ifndef _UTIL_H
#define _UTIL_H
#ifndef UTIL_H
#define UTIL_H
#include <stdarg.h>
#include <stdbool.h>
@ -35,6 +35,9 @@
#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, ...)
{
va_list ap;
@ -260,4 +263,4 @@ void NORETURN util_usage(const char *errmsg, const char *synopsis,
case 'V': util_version(); \
case '?': usage("unknown option");
#endif /* _UTIL_H */
#endif /* UTIL_H */

View File

@ -1 +1 @@
#define DTC_VERSION "DTC 1.4.5-gc1e55a55"
#define DTC_VERSION "DTC 1.4.6-gaadd0b65"