diff options
49 files changed, 1152 insertions, 233 deletions
| diff --git a/Documentation/devicetree/bindings/display/atmel/hlcdc-dc.txt b/Documentation/devicetree/bindings/display/atmel/hlcdc-dc.txt index ebc1a914bda3..ec94468b35be 100644 --- a/Documentation/devicetree/bindings/display/atmel/hlcdc-dc.txt +++ b/Documentation/devicetree/bindings/display/atmel/hlcdc-dc.txt @@ -1,7 +1,7 @@  Device-Tree bindings for Atmel's HLCDC (High LCD Controller) DRM driver  The Atmel HLCDC Display Controller is subdevice of the HLCDC MFD device. -See ../mfd/atmel-hlcdc.txt for more details. +See ../../mfd/atmel-hlcdc.txt for more details.  Required properties:   - compatible: value should be "atmel,hlcdc-display-controller" diff --git a/Documentation/devicetree/bindings/fpga/fpga-region.txt b/Documentation/devicetree/bindings/fpga/fpga-region.txt index 81bf3adba24b..6db8aeda461a 100644 --- a/Documentation/devicetree/bindings/fpga/fpga-region.txt +++ b/Documentation/devicetree/bindings/fpga/fpga-region.txt @@ -193,6 +193,8 @@ Optional properties:  - region-freeze-timeout-us : The maximum time in microseconds to wait for  	bridges to successfully become disabled before the region has been  	programmed. +- config-complete-timeout-us : The maximum time in microseconds time for the +	FPGA to go to operating mode after the region has been programmed.  - child nodes : devices in the FPGA after programming.  In the example below, when an overlay is applied targeting fpga-region0, diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,nvic.txt b/Documentation/devicetree/bindings/interrupt-controller/arm,nvic.txt new file mode 100644 index 000000000000..386ab37a383f --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/arm,nvic.txt @@ -0,0 +1,36 @@ +* ARM Nested Vector Interrupt Controller (NVIC) + +The NVIC provides an interrupt controller that is tightly coupled to +Cortex-M based processor cores.  The NVIC implemented on different SoCs +vary in the number of interrupts and priority bits per interrupt. + +Main node required properties: + +- compatible : should be one of: +	"arm,v6m-nvic" +	"arm,v7m-nvic" +	"arm,v8m-nvic" +- interrupt-controller : Identifies the node as an interrupt controller +- #interrupt-cells : Specifies the number of cells needed to encode an +  interrupt source.  The type shall be a <u32> and the value shall be 2. + +  The 1st cell contains the interrupt number for the interrupt type. + +  The 2nd cell is the priority of the interrupt. + +- reg : Specifies base physical address(s) and size of the NVIC registers. +  This is at a fixed address (0xe000e100) and size (0xc00). + +- arm,num-irq-priority-bits: The number of priority bits implemented by the +  given SoC + +Example: + +	intc: interrupt-controller@e000e100 { +		compatible = "arm,v7m-nvic"; +		#interrupt-cells = <2>; +		#address-cells = <1>; +		interrupt-controller; +		reg = <0xe000e100 0xc00>; +		arm,num-irq-priority-bits = <4>; +	}; diff --git a/Documentation/devicetree/bindings/mfd/atmel-hlcdc.txt b/Documentation/devicetree/bindings/mfd/atmel-hlcdc.txt index 670831b29565..eec40be7f79a 100644 --- a/Documentation/devicetree/bindings/mfd/atmel-hlcdc.txt +++ b/Documentation/devicetree/bindings/mfd/atmel-hlcdc.txt @@ -15,7 +15,7 @@ Required properties:  The HLCDC IP exposes two subdevices:   - a PWM chip: see ../pwm/atmel-hlcdc-pwm.txt - - a Display Controller: see ../display/atmel-hlcdc-dc.txt + - a Display Controller: see ../display/atmel/hlcdc-dc.txt  Example: diff --git a/Documentation/devicetree/bindings/net/moxa,moxart-mac.txt b/Documentation/devicetree/bindings/net/faraday,ftmac.txt index 583418b2c127..be4f55e23bf7 100644 --- a/Documentation/devicetree/bindings/net/moxa,moxart-mac.txt +++ b/Documentation/devicetree/bindings/net/faraday,ftmac.txt @@ -1,8 +1,11 @@ -MOXA ART Ethernet Controller +Faraday Ethernet Controller  Required properties: -- compatible : Must be "moxa,moxart-mac" +- compatible : Must contain "faraday,ftmac", as well as one of +		the SoC specific identifiers: +		"andestech,atmac100" +		"moxa,moxart-mac"  - reg : Should contain register location and length  - interrupts : Should contain the mac interrupt number diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/trivial-devices.txt index ad10fbe61562..ad10fbe61562 100644 --- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt +++ b/Documentation/devicetree/bindings/trivial-devices.txt diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 257ec07cbaa0..ee558477e164 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -80,6 +80,7 @@ denx	Denx Software Engineering  devantech	Devantech, Ltd.  digi	Digi International Inc.  digilent	Diglent, Inc. +dioo	Dioo Microcircuit Co., Ltd  dlg	Dialog Semiconductor  dlink	D-Link Corporation  dmo	Data Modul AG @@ -215,6 +216,7 @@ newhaven	Newhaven Display International  ni	National Instruments  nintendo	Nintendo  nokia	Nokia +nordic	Nordic Semiconductor  nuvoton	Nuvoton Technology Corporation  nvd	New Vision Display  nvidia	NVIDIA @@ -261,6 +263,7 @@ richtek	Richtek Technology Corporation  ricoh	Ricoh Co. Ltd.  rikomagic	Rikomagic Tech Corp. Ltd  rockchip	Fuzhou Rockchip Electronics Co., Ltd +rohm	ROHM Semiconductor Co., Ltd  samsung	Samsung Semiconductor  samtec	Samtec/Softing company  sandisk	Sandisk Corporation diff --git a/arch/powerpc/platforms/pseries/ibmebus.c b/arch/powerpc/platforms/pseries/ibmebus.c index 99a6bf7f3bcf..b363e439ddb9 100644 --- a/arch/powerpc/platforms/pseries/ibmebus.c +++ b/arch/powerpc/platforms/pseries/ibmebus.c @@ -410,10 +410,7 @@ static ssize_t name_show(struct device *dev,  static ssize_t modalias_show(struct device *dev,  				struct device_attribute *attr, char *buf)  { -	ssize_t len = of_device_get_modalias(dev, buf, PAGE_SIZE - 2); -	buf[len] = '\n'; -	buf[len+1] = 0; -	return len+1; +	return of_device_modalias(dev, buf, PAGE_SIZE);  }  static struct device_attribute ibmebus_bus_device_attrs[] = { diff --git a/drivers/base/platform.c b/drivers/base/platform.c index c2456839214a..a102152301c8 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -847,7 +847,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a,  	struct platform_device	*pdev = to_platform_device(dev);  	int len; -	len = of_device_get_modalias(dev, buf, PAGE_SIZE -1); +	len = of_device_modalias(dev, buf, PAGE_SIZE);  	if (len != -ENODEV)  		return len; diff --git a/drivers/macintosh/macio_sysfs.c b/drivers/macintosh/macio_sysfs.c index 8eb40afbd0f5..0b1f9c76c68d 100644 --- a/drivers/macintosh/macio_sysfs.c +++ b/drivers/macintosh/macio_sysfs.c @@ -41,12 +41,7 @@ compatible_show (struct device *dev, struct device_attribute *attr, char *buf)  static ssize_t modalias_show (struct device *dev, struct device_attribute *attr,  			      char *buf)  { -	int len = of_device_get_modalias(dev, buf, PAGE_SIZE - 2); - -	buf[len] = '\n'; -	buf[len+1] = 0; - -	return len+1; +	return of_device_modalias(dev, buf, PAGE_SIZE);  }  static ssize_t devspec_show(struct device *dev, diff --git a/drivers/of/address.c b/drivers/of/address.c index 02b2903fe9d2..72914cdfce2a 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -263,7 +263,7 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,  	if (!parser->range || parser->range + parser->np > parser->end)  		return NULL; -	range->pci_space = parser->range[0]; +	range->pci_space = be32_to_cpup(parser->range);  	range->flags = of_bus_pci_get_flags(parser->range);  	range->pci_addr = of_read_number(parser->range + 1, ns);  	range->cpu_addr = of_translate_address(parser->node, diff --git a/drivers/of/base.c b/drivers/of/base.c index 0ea16bd3c8f1..28d5f53bc631 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -2281,15 +2281,14 @@ EXPORT_SYMBOL_GPL(of_console_check);   */  struct device_node *of_find_next_cache_node(const struct device_node *np)  { -	struct device_node *child; -	const phandle *handle; +	struct device_node *child, *cache_node; -	handle = of_get_property(np, "l2-cache", NULL); -	if (!handle) -		handle = of_get_property(np, "next-level-cache", NULL); +	cache_node = of_parse_phandle(np, "l2-cache", 0); +	if (!cache_node) +		cache_node = of_parse_phandle(np, "next-level-cache", 0); -	if (handle) -		return of_find_node_by_phandle(be32_to_cpup(handle)); +	if (cache_node) +		return cache_node;  	/* OF on pmac has nodes instead of properties named "l2-cache"  	 * beneath CPU nodes. diff --git a/drivers/of/device.c b/drivers/of/device.c index b1e6bebda3f3..6e2f9113b1b7 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -176,7 +176,7 @@ const void *of_device_get_match_data(const struct device *dev)  }  EXPORT_SYMBOL(of_device_get_match_data); -ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len) +static ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len)  {  	const char *compat;  	int cplen, i; @@ -223,9 +223,8 @@ ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len)  			str[i] = '_';  	} -	return tsize; +	return repend;  } -EXPORT_SYMBOL_GPL(of_device_get_modalias);  int of_device_request_module(struct device *dev)  { @@ -251,6 +250,21 @@ int of_device_request_module(struct device *dev)  EXPORT_SYMBOL_GPL(of_device_request_module);  /** + * of_device_modalias - Fill buffer with newline terminated modalias string + */ +ssize_t of_device_modalias(struct device *dev, char *str, ssize_t len) +{ +	ssize_t sl = of_device_get_modalias(dev, str, len - 2); +	if (sl < 0) +		return sl; + +	str[sl++] = '\n'; +	str[sl] = 0; +	return sl; +} +EXPORT_SYMBOL_GPL(of_device_modalias); + +/**   * of_device_uevent - Display OF related uevent information   */  void of_device_uevent(struct device *dev, struct kobj_uevent_env *env) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index e5ce4b59e162..a0972219ccfc 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -31,6 +31,8 @@  #include <asm/setup.h>  /* for COMMAND_LINE_SIZE */  #include <asm/page.h> +#include "of_private.h" +  /*   * of_fdt_limit_memory - limit the number of regions in the /memory node   * @limit: maximum entries @@ -46,8 +48,8 @@ void of_fdt_limit_memory(int limit)  	const void *val;  	int nr_address_cells = OF_ROOT_NODE_ADDR_CELLS_DEFAULT;  	int nr_size_cells = OF_ROOT_NODE_SIZE_CELLS_DEFAULT; -	const uint32_t *addr_prop; -	const uint32_t *size_prop; +	const __be32 *addr_prop; +	const __be32 *size_prop;  	int root_offset;  	int cell_size; @@ -469,11 +471,11 @@ static int unflatten_dt_nodes(const void *blob,   * Returns NULL on failure or the memory chunk containing the unflattened   * device tree on success.   */ -static void *__unflatten_device_tree(const void *blob, -				     struct device_node *dad, -				     struct device_node **mynodes, -				     void *(*dt_alloc)(u64 size, u64 align), -				     bool detached) +void *__unflatten_device_tree(const void *blob, +			      struct device_node *dad, +			      struct device_node **mynodes, +			      void *(*dt_alloc)(u64 size, u64 align), +			      bool detached)  {  	int size;  	void *mem; @@ -1261,6 +1263,8 @@ void __init unflatten_device_tree(void)  	/* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */  	of_alias_scan(early_init_dt_alloc_memory_arch); + +	unittest_unflatten_overlay_base();  }  /** diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 7c56b72d1dc6..d11437cb1187 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -102,7 +102,7 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)  	struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL;  	__be32 initial_match_array[MAX_PHANDLE_ARGS];  	const __be32 *match_array = initial_match_array; -	const __be32 *tmp, *imap, *imask, dummy_imask[] = { [0 ... MAX_PHANDLE_ARGS] = ~0 }; +	const __be32 *tmp, *imap, *imask, dummy_imask[] = { [0 ... MAX_PHANDLE_ARGS] = cpu_to_be32(~0) };  	u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;  	int imaplen, match, i, rc = -EINVAL; diff --git a/drivers/of/of_numa.c b/drivers/of/of_numa.c index a53982a330ea..2db1f7a04baf 100644 --- a/drivers/of/of_numa.c +++ b/drivers/of/of_numa.c @@ -57,6 +57,8 @@ static void __init of_numa_parse_cpu_nodes(void)  		else  			node_set(nid, numa_nodes_parsed);  	} + +	of_node_put(cpus);  }  static int __init of_numa_parse_memory_nodes(void) diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h index 18bbb4517e25..4ebb0149d118 100644 --- a/drivers/of/of_private.h +++ b/drivers/of/of_private.h @@ -55,6 +55,18 @@ static inline int of_property_notify(int action, struct device_node *np,  }  #endif /* CONFIG_OF_DYNAMIC */ +#if defined(CONFIG_OF_UNITTEST) && defined(CONFIG_OF_OVERLAY) +extern void __init unittest_unflatten_overlay_base(void); +#else +static inline void unittest_unflatten_overlay_base(void) {}; +#endif + +extern void *__unflatten_device_tree(const void *blob, +			      struct device_node *dad, +			      struct device_node **mynodes, +			      void *(*dt_alloc)(u64 size, u64 align), +			      bool detached); +  /**   * General utilities for working with live trees.   * diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index d507c3569a88..4dec07ea510f 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -197,7 +197,7 @@ static int __init __reserved_mem_init_node(struct reserved_mem *rmem)  	const struct of_device_id *i;  	for (i = __reservedmem_of_table; i < &__rmem_of_table_sentinel; i++) { -		reservedmem_of_init_fn initfn = i->data; +		int const (*initfn)(struct reserved_mem *rmem) = i->data;  		const char *compat = i->compatible;  		if (!of_flat_dt_is_compatible(rmem->fdt_node, compat)) diff --git a/drivers/of/resolver.c b/drivers/of/resolver.c index 7ae9863cb0a4..771f4844c781 100644 --- a/drivers/of/resolver.c +++ b/drivers/of/resolver.c @@ -92,7 +92,7 @@ static void adjust_overlay_phandles(struct device_node *overlay,  		if (phandle == OF_PHANDLE_ILLEGAL)  			continue; -		*(uint32_t *)prop->value = cpu_to_be32(overlay->phandle); +		*(__be32 *)prop->value = cpu_to_be32(overlay->phandle);  	}  	for_each_child_of_node(overlay, child) diff --git a/drivers/of/unittest-data/Makefile b/drivers/of/unittest-data/Makefile index 1ac5cc01d627..6e00a9c69e58 100644 --- a/drivers/of/unittest-data/Makefile +++ b/drivers/of/unittest-data/Makefile @@ -1,7 +1,18 @@  obj-y += testcases.dtb.o +obj-y += overlay.dtb.o +obj-y += overlay_bad_phandle.dtb.o +obj-y += overlay_base.dtb.o  targets += testcases.dtb testcases.dtb.S +targets += overlay.dtb overlay.dtb.S +targets += overlay_bad_phandle.dtb overlay_bad_phandle.dtb.S +targets += overlay_base.dtb overlay_base.dtb.S -.SECONDARY: \ -	$(obj)/testcases.dtb.S \ -	$(obj)/testcases.dtb +.PRECIOUS: \ +	$(obj)/%.dtb.S \ +	$(obj)/%.dtb + +# enable creation of __symbols__ node +DTC_FLAGS_overlay := -@ +DTC_FLAGS_overlay_bad_phandle := -@ +DTC_FLAGS_overlay_base := -@ diff --git a/drivers/of/unittest-data/overlay.dts b/drivers/of/unittest-data/overlay.dts new file mode 100644 index 000000000000..6cd7e6a0c13e --- /dev/null +++ b/drivers/of/unittest-data/overlay.dts @@ -0,0 +1,53 @@ +/dts-v1/; +/plugin/; + +/ { + +	fragment@0 { +		target = <&electric_1>; + +		__overlay__ { +			status = "ok"; + +			hvac_2: hvac-large-1 { +				compatible = "ot,hvac-large"; +				heat-range = < 40 75 >; +				cool-range = < 65 80 >; +			}; +		}; +	}; + +	fragment@1 { +		target = <&rides_1>; + +		__overlay__ { +			#address-cells = <1>; +			#size-cells = <1>; +			status = "ok"; + +			ride@200 { +				compatible = "ot,ferris-wheel"; +				reg = < 0x00000200 0x100 >; +				hvac-provider = < &hvac_2 >; +				hvac-thermostat = < 27 32 > ; +				hvac-zones = < 12 5 >; +				hvac-zone-names = "operator", "snack-bar"; +				spin-controller = < &spin_ctrl_1 3 >; +				spin-rph = < 30 >; +				gondolas = < 16 >; +				gondola-capacity = < 6 >; +			}; +		}; +	}; + +	fragment@2 { +		target = <&lights_2>; + +		__overlay__ { +			status = "ok"; +			color = "purple", "white", "red", "green"; +			rate = < 3 256 >; +		}; +	}; + +}; diff --git a/drivers/of/unittest-data/overlay_bad_phandle.dts b/drivers/of/unittest-data/overlay_bad_phandle.dts new file mode 100644 index 000000000000..270ee885a623 --- /dev/null +++ b/drivers/of/unittest-data/overlay_bad_phandle.dts @@ -0,0 +1,20 @@ +/dts-v1/; +/plugin/; + +/ { + +	fragment@0 { +		target = <&electric_1>; + +		__overlay__ { + +			// This label should cause an error when the overlay +			// is applied.  There is already a phandle value +			// in the base tree for motor-1. +			spin_ctrl_1_conflict: motor-1 { +				accelerate = < 3 >; +				decelerate = < 5 >; +			}; +		}; +	}; +}; diff --git a/drivers/of/unittest-data/overlay_base.dts b/drivers/of/unittest-data/overlay_base.dts new file mode 100644 index 000000000000..5566b27fb61a --- /dev/null +++ b/drivers/of/unittest-data/overlay_base.dts @@ -0,0 +1,80 @@ +/dts-v1/; +/plugin/; + +/* + * Base device tree that overlays will be applied against. + * + * Do not add any properties in node "/". + * Do not add any nodes other than "/testcase-data-2" in node "/". + * Do not add anything that would result in dtc creating node "/__fixups__". + * dtc will create nodes "/__symbols__" and "/__local_fixups__". + */ + +/ { +	testcase-data-2 { +		#address-cells = <1>; +		#size-cells = <1>; + +		electric_1: substation@100 { +			compatible = "ot,big-volts-control"; +			reg = < 0x00000100 0x100 >; +			status = "disabled"; + +			hvac_1: hvac-medium-1 { +				compatible = "ot,hvac-medium"; +				heat-range = < 50 75 >; +				cool-range = < 60 80 >; +			}; + +			spin_ctrl_1: motor-1 { +				compatible = "ot,ferris-wheel-motor"; +				spin = "clockwise"; +			}; + +			spin_ctrl_2: motor-8 { +				compatible = "ot,roller-coaster-motor"; +			}; +		}; + +		rides_1: fairway-1 { +			#address-cells = <1>; +			#size-cells = <1>; +			compatible = "ot,rides"; +			status = "disabled"; +			orientation = < 127 >; + +			ride@100 { +				compatible = "ot,roller-coaster"; +				reg = < 0x00000100 0x100 >; +				hvac-provider = < &hvac_1 >; +				hvac-thermostat = < 29 > ; +				hvac-zones = < 14 >; +				hvac-zone-names = "operator"; +				spin-controller = < &spin_ctrl_2 5 &spin_ctrl_2 7 >; +				spin-controller-names = "track_1", "track_2"; +				queues = < 2 >; +			}; +		}; + +		lights_1: lights@30000 { +			compatible = "ot,work-lights"; +			reg = < 0x00030000 0x1000 >; +			status = "disabled"; +		}; + +		lights_2: lights@40000 { +			compatible = "ot,show-lights"; +			reg = < 0x00040000 0x1000 >; +			status = "disabled"; +			rate = < 13 138 >; +		}; + +		retail_1: vending@50000 { +			reg = < 0x00050000 0x1000 >; +			compatible = "ot,tickets"; +			status = "disabled"; +		}; + +	}; +}; + diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 62db55b97c10..987a1530282a 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -8,6 +8,7 @@  #include <linux/err.h>  #include <linux/errno.h>  #include <linux/hashtable.h> +#include <linux/libfdt.h>  #include <linux/of.h>  #include <linux/of_fdt.h>  #include <linux/of_irq.h> @@ -1925,6 +1926,324 @@ out:  static inline void __init of_unittest_overlay(void) { }  #endif +/* + * __dtb_ot_begin[] and __dtb_ot_end[] are created by cmd_dt_S_dtb + * in scripts/Makefile.lib + */ + +#define OVERLAY_INFO_EXTERN(name) \ +	extern uint8_t __dtb_##name##_begin[]; \ +	extern uint8_t __dtb_##name##_end[] + +#define OVERLAY_INFO(name, expected) \ +{	.dtb_begin	 = __dtb_##name##_begin, \ +	.dtb_end	 = __dtb_##name##_end, \ +	.expected_result = expected, \ +} + +struct overlay_info { +	uint8_t		   *dtb_begin; +	uint8_t		   *dtb_end; +	void		   *data; +	struct device_node *np_overlay; +	int		   expected_result; +	int		   overlay_id; +}; + +OVERLAY_INFO_EXTERN(overlay_base); +OVERLAY_INFO_EXTERN(overlay); +OVERLAY_INFO_EXTERN(overlay_bad_phandle); + +#ifdef CONFIG_OF_OVERLAY + +/* order of entries is hard-coded into users of overlays[] */ +static struct overlay_info overlays[] = { +	OVERLAY_INFO(overlay_base, -9999), +	OVERLAY_INFO(overlay, 0), +	OVERLAY_INFO(overlay_bad_phandle, -EINVAL), +	{} +}; + +static struct device_node *overlay_base_root; + +/* + * Create base device tree for the overlay unittest. + * + * This is called from very early boot code. + * + * Do as much as possible the same way as done in __unflatten_device_tree + * and other early boot steps for the normal FDT so that the overlay base + * unflattened tree will have the same characteristics as the real tree + * (such as having memory allocated by the early allocator).  The goal + * is to test "the real thing" as much as possible, and test "test setup + * code" as little as possible. + * + * Have to stop before resolving phandles, because that uses kmalloc. + */ +void __init unittest_unflatten_overlay_base(void) +{ +	struct overlay_info *info; +	u32 data_size; +	u32 size; + +	info = &overlays[0]; + +	if (info->expected_result != -9999) { +		pr_err("No dtb 'overlay_base' to attach\n"); +		return; +	} + +	data_size = info->dtb_end - info->dtb_begin; +	if (!data_size) { +		pr_err("No dtb 'overlay_base' to attach\n"); +		return; +	} + +	size = fdt_totalsize(info->dtb_begin); +	if (size != data_size) { +		pr_err("dtb 'overlay_base' header totalsize != actual size"); +		return; +	} + +	info->data = early_init_dt_alloc_memory_arch(size, +					     roundup_pow_of_two(FDT_V17_SIZE)); +	if (!info->data) { +		pr_err("alloc for dtb 'overlay_base' failed"); +		return; +	} + +	memcpy(info->data, info->dtb_begin, size); + +	__unflatten_device_tree(info->data, NULL, &info->np_overlay, +				early_init_dt_alloc_memory_arch, true); +	overlay_base_root = info->np_overlay; +} + +/* + * The purpose of of_unittest_overlay_data_add is to add an + * overlay in the normal fashion.  This is a test of the whole + * picture, instead of testing individual elements. + * + * A secondary purpose is to be able to verify that the contents of + * /proc/device-tree/ contains the updated structure and values from + * the overlay.  That must be verified separately in user space. + * + * Return 0 on unexpected error. + */ +static int __init overlay_data_add(int onum) +{ +	struct overlay_info *info; +	int k; +	int ret; +	u32 size; +	u32 size_from_header; + +	for (k = 0, info = overlays; info; info++, k++) { +		if (k == onum) +			break; +	} +	if (onum > k) +		return 0; + +	size = info->dtb_end - info->dtb_begin; +	if (!size) { +		pr_err("no overlay to attach, %d\n", onum); +		ret = 0; +	} + +	size_from_header = fdt_totalsize(info->dtb_begin); +	if (size_from_header != size) { +		pr_err("overlay header totalsize != actual size, %d", onum); +		return 0; +	} + +	/* +	 * Must create permanent copy of FDT because of_fdt_unflatten_tree() +	 * will create pointers to the passed in FDT in the EDT. +	 */ +	info->data = kmemdup(info->dtb_begin, size, GFP_KERNEL); +	if (!info->data) { +		pr_err("unable to allocate memory for data, %d\n", onum); +		return 0; +	} + +	of_fdt_unflatten_tree(info->data, NULL, &info->np_overlay); +	if (!info->np_overlay) { +		pr_err("unable to unflatten overlay, %d\n", onum); +		ret = 0; +		goto out_free_data; +	} +	of_node_set_flag(info->np_overlay, OF_DETACHED); + +	ret = of_resolve_phandles(info->np_overlay); +	if (ret) { +		pr_err("resolve ot phandles (ret=%d), %d\n", ret, onum); +		goto out_free_np_overlay; +	} + +	ret = of_overlay_create(info->np_overlay); +	if (ret < 0) { +		pr_err("of_overlay_create() (ret=%d), %d\n", ret, onum); +		goto out_free_np_overlay; +	} else { +		info->overlay_id = ret; +		ret = 0; +	} + +	pr_debug("__dtb_overlay_begin applied, overlay id %d\n", ret); + +	goto out; + +out_free_np_overlay: +	/* +	 * info->np_overlay is the unflattened device tree +	 * It has not been spliced into the live tree. +	 */ + +	/* todo: function to free unflattened device tree */ + +out_free_data: +	kfree(info->data); + +out: +	return (ret == info->expected_result); +} + +/* + * The purpose of of_unittest_overlay_high_level is to add an overlay + * in the normal fashion.  This is a test of the whole picture, + * instead of individual elements. + * + * The first part of the function is _not_ normal overlay usage; it is + * finishing splicing the base overlay device tree into the live tree. + */ +static __init void of_unittest_overlay_high_level(void) +{ +	struct device_node *last_sibling; +	struct device_node *np; +	struct device_node *of_symbols; +	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"); +		return; +	} + +	/* +	 * Could not fixup phandles in unittest_unflatten_overlay_base() +	 * because kmalloc() was not yet available. +	 */ +	of_resolve_phandles(overlay_base_root); + +	/* +	 * do not allow overlay_base to duplicate any node already in +	 * tree, this greatly simplifies the code +	 */ + +	/* +	 * remove overlay_base_root node "__local_fixups", after +	 * being used by of_resolve_phandles() +	 */ +	pprev = &overlay_base_root->child; +	for (np = overlay_base_root->child; np; np = np->sibling) { +		if (!of_node_cmp(np->name, "__local_fixups__")) { +			*pprev = np->sibling; +			break; +		} +		pprev = &np->sibling; +	} + +	/* remove overlay_base_root node "__symbols__" if in live tree */ +	of_symbols = of_get_child_by_name(of_root, "__symbols__"); +	if (of_symbols) { +		/* will have to graft properties from node into live tree */ +		pprev = &overlay_base_root->child; +		for (np = overlay_base_root->child; np; np = np->sibling) { +			if (!of_node_cmp(np->name, "__symbols__")) { +				overlay_base_symbols = np; +				*pprev = np->sibling; +				break; +			} +			pprev = &np->sibling; +		} +	} + +	for (np = overlay_base_root->child; np; np = np->sibling) { +		if (of_get_child_by_name(of_root, np->name)) { +			unittest(0, "illegal node name in overlay_base %s", +				np->name); +			return; +		} +	} + +	/* +	 * overlay 'overlay_base' is not allowed to have root +	 * properties, so only need to splice nodes into main device tree. +	 * +	 * root node of *overlay_base_root will not be freed, it is lost +	 * memory. +	 */ + +	for (np = overlay_base_root->child; np; np = np->sibling) +		np->parent = of_root; + +	mutex_lock(&of_mutex); + +	for (last_sibling = np = of_root->child; np; np = np->sibling) +		last_sibling = np; + +	if (last_sibling) +		last_sibling->sibling = overlay_base_root->child; +	else +		of_root->child = overlay_base_root->child; + +	for_each_of_allnodes_from(overlay_base_root, np) +		__of_attach_node_sysfs(np); + +	if (of_symbols) { +		for_each_property_of_node(overlay_base_symbols, prop) { +			ret = __of_add_property(of_symbols, prop); +			if (ret) { +				unittest(0, +					 "duplicate property '%s' in overlay_base node __symbols__", +					 prop->name); +				goto err_unlock; +			} +			ret = __of_add_property_sysfs(of_symbols, prop); +			if (ret) { +				unittest(0, +					 "unable to add property '%s' in overlay_base node __symbols__ to sysfs", +					 prop->name); +				goto err_unlock; +			} +		} +	} + +	mutex_unlock(&of_mutex); + + +	/* now do the normal overlay usage test */ + +	unittest(overlay_data_add(1), +		 "Adding overlay 'overlay' failed\n"); + +	unittest(overlay_data_add(2), +		 "Adding overlay 'overlay_bad_phandle' failed\n"); +	return; + +err_unlock: +	mutex_unlock(&of_mutex); +} + +#else + +static inline __init void of_unittest_overlay_high_level(void) {} + +#endif +  static int __init of_unittest(void)  {  	struct device_node *np; @@ -1962,6 +2281,8 @@ static int __init of_unittest(void)  	/* Double check linkage after removing testcase data */  	of_unittest_check_tree_linkage(); +	of_unittest_overlay_high_level(); +  	pr_info("end of unittest - %i passed, %i failed\n",  		unittest_results.passed, unittest_results.failed); diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c index 1e1cbae3a0ea..1c4829a56351 100644 --- a/drivers/tty/serdev/core.c +++ b/drivers/tty/serdev/core.c @@ -224,10 +224,7 @@ static int serdev_drv_remove(struct device *dev)  static ssize_t modalias_show(struct device *dev,  			     struct device_attribute *attr, char *buf)  { -	ssize_t len = of_device_get_modalias(dev, buf, PAGE_SIZE - 2); -	buf[len] = '\n'; -	buf[len+1] = 0; -	return len+1; +	return of_device_modalias(dev, buf, PAGE_SIZE);  }  static struct device_attribute serdev_device_attrs[] = { diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index c9480d77810c..930e8f35f8df 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -107,7 +107,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,  	int len;  	struct ulpi *ulpi = to_ulpi_dev(dev); -	len = of_device_get_modalias(dev, buf, PAGE_SIZE - 1); +	len = of_device_modalias(dev, buf, PAGE_SIZE);  	if (len != -ENODEV)  		return len; diff --git a/include/linux/of_device.h b/include/linux/of_device.h index c12dace043f3..169ea0bd8eb4 100644 --- a/include/linux/of_device.h +++ b/include/linux/of_device.h @@ -34,8 +34,7 @@ extern void of_device_unregister(struct platform_device *ofdev);  extern const void *of_device_get_match_data(const struct device *dev); -extern ssize_t of_device_get_modalias(struct device *dev, -					char *str, ssize_t len); +extern ssize_t of_device_modalias(struct device *dev, char *str, ssize_t len);  extern int of_device_request_module(struct device *dev);  extern void of_device_uevent(struct device *dev, struct kobj_uevent_env *env); @@ -72,8 +71,8 @@ static inline const void *of_device_get_match_data(const struct device *dev)  	return NULL;  } -static inline int of_device_get_modalias(struct device *dev, -				   char *str, ssize_t len) +static inline int of_device_modalias(struct device *dev, +				     char *str, ssize_t len)  {  	return -ENODEV;  } diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h index 1e0deb8e8494..ec6b11deb773 100644 --- a/include/linux/of_irq.h +++ b/include/linux/of_irq.h @@ -8,7 +8,7 @@  #include <linux/ioport.h>  #include <linux/of.h> -typedef int (*of_irq_init_cb_t)(struct device_node *, struct device_node *); +typedef int const (*of_irq_init_cb_t)(struct device_node *, struct device_node *);  /*   * Workarounds only applied to 32bit powermac machines diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 7234e61e7ce3..c9f975ab9840 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -280,9 +280,21 @@ DTC ?= $(objtree)/scripts/dtc/dtc  # Disable noisy checks by default  ifeq ($(KBUILD_ENABLE_EXTRA_GCC_CHECKS),) -DTC_FLAGS += -Wno-unit_address_vs_reg +DTC_FLAGS += -Wno-unit_address_vs_reg \ +	-Wno-simple_bus_reg \ +	-Wno-unit_address_format \ +	-Wno-pci_bridge \ +	-Wno-pci_device_bus_num \ +	-Wno-pci_device_reg  endif +ifeq ($(KBUILD_ENABLE_EXTRA_GCC_CHECKS),2) +DTC_FLAGS += -Wnode_name_chars_strict \ +	-Wproperty_name_chars_strict +endif + +DTC_FLAGS += $(DTC_FLAGS_$(basetarget)) +  # Generate an assembly file to wrap the output of the device tree compiler  quiet_cmd_dt_S_dtb= DTB     $@  cmd_dt_S_dtb=						\ diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c index 3d18e45374c8..5adfc8f52b4f 100644 --- a/scripts/dtc/checks.c +++ b/scripts/dtc/checks.c @@ -72,17 +72,16 @@ struct check {  #define CHECK(_nm, _fn, _d, ...) \  	CHECK_ENTRY(_nm, _fn, _d, false, false, __VA_ARGS__) -#ifdef __GNUC__ -static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3))); -#endif -static inline void check_msg(struct check *c, const char *fmt, ...) +static inline void  PRINTF(3, 4) check_msg(struct check *c, struct dt_info *dti, +					   const char *fmt, ...)  {  	va_list ap;  	va_start(ap, fmt);  	if ((c->warn && (quiet < 1))  	    || (c->error && (quiet < 2))) { -		fprintf(stderr, "%s (%s): ", +		fprintf(stderr, "%s: %s (%s): ", +			strcmp(dti->outname, "-") ? dti->outname : "<stdout>",  			(c->error) ? "ERROR" : "Warning", c->name);  		vfprintf(stderr, fmt, ap);  		fprintf(stderr, "\n"); @@ -90,11 +89,11 @@ static inline void check_msg(struct check *c, const char *fmt, ...)  	va_end(ap);  } -#define FAIL(c, ...) \ -	do { \ -		TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \ -		(c)->status = FAILED; \ -		check_msg((c), __VA_ARGS__); \ +#define FAIL(c, dti, ...)						\ +	do {								\ +		TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__);	\ +		(c)->status = FAILED;					\ +		check_msg((c), dti, __VA_ARGS__);			\  	} while (0)  static void check_nodes_props(struct check *c, struct dt_info *dti, struct node *node) @@ -127,7 +126,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, "Failed prerequisite '%s'", +			check_msg(c, dti, "Failed prerequisite '%s'",  				  c->prereq[i]->name);  		}  	} @@ -157,7 +156,7 @@ out:  static inline void check_always_fail(struct check *c, struct dt_info *dti,  				     struct node *node)  { -	FAIL(c, "always_fail check"); +	FAIL(c, dti, "always_fail check");  }  CHECK(always_fail, check_always_fail, NULL); @@ -172,7 +171,7 @@ 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, "\"%s\" property in %s is not a string", +		FAIL(c, dti, "\"%s\" property in %s is not a string",  		     propname, node->fullpath);  }  #define WARNING_IF_NOT_STRING(nm, propname) \ @@ -191,7 +190,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, "\"%s\" property in %s is not a single cell", +		FAIL(c, dti, "\"%s\" property in %s is not a single cell",  		     propname, node->fullpath);  }  #define WARNING_IF_NOT_CELL(nm, propname) \ @@ -213,7 +212,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, "Duplicate node name %s", +				FAIL(c, dti, "Duplicate node name %s",  				     child->fullpath);  }  ERROR(duplicate_node_names, check_duplicate_node_names, NULL); @@ -228,7 +227,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, "Duplicate property name %s in %s", +				FAIL(c, dti, "Duplicate property name %s in %s",  				     prop->name, node->fullpath);  		}  	} @@ -239,6 +238,7 @@ ERROR(duplicate_property_names, check_duplicate_property_names, NULL);  #define UPPERCASE	"ABCDEFGHIJKLMNOPQRSTUVWXYZ"  #define DIGITS		"0123456789"  #define PROPNODECHARS	LOWERCASE UPPERCASE DIGITS ",._+*#?-" +#define PROPNODECHARSSTRICT	LOWERCASE UPPERCASE DIGITS ",-"  static void check_node_name_chars(struct check *c, struct dt_info *dti,  				  struct node *node) @@ -246,16 +246,27 @@ 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, "Bad character '%c' in node %s", +		FAIL(c, dti, "Bad character '%c' in node %s",  		     node->name[n], node->fullpath);  }  ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@"); +static void check_node_name_chars_strict(struct check *c, struct dt_info *dti, +					 struct node *node) +{ +	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); +} +CHECK(node_name_chars_strict, check_node_name_chars_strict, PROPNODECHARSSTRICT); +  static void check_node_name_format(struct check *c, struct dt_info *dti,  				   struct node *node)  {  	if (strchr(get_unitname(node), '@')) -		FAIL(c, "Node %s has multiple '@' characters in name", +		FAIL(c, dti, "Node %s has multiple '@' characters in name",  		     node->fullpath);  }  ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars); @@ -274,11 +285,11 @@ static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,  	if (prop) {  		if (!unitname[0]) -			FAIL(c, "Node %s has a reg or ranges property, but no unit name", +			FAIL(c, dti, "Node %s has a reg or ranges property, but no unit name",  			    node->fullpath);  	} else {  		if (unitname[0]) -			FAIL(c, "Node %s has a unit name, but no reg property", +			FAIL(c, dti, "Node %s has a unit name, but no reg property",  			    node->fullpath);  	}  } @@ -293,12 +304,44 @@ 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, "Bad character '%c' in property name \"%s\", node %s", +			FAIL(c, dti, "Bad character '%c' in property name \"%s\", node %s",  			     prop->name[n], prop->name, node->fullpath);  	}  }  ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS); +static void check_property_name_chars_strict(struct check *c, +					     struct dt_info *dti, +					     struct node *node) +{ +	struct property *prop; + +	for_each_property(node, prop) { +		const char *name = prop->name; +		int n = strspn(name, c->data); + +		if (n == strlen(prop->name)) +			continue; + +		/* Certain names are whitelisted */ +		if (streq(name, "device_type")) +			continue; + +		/* +		 * # is only allowed at the beginning of property names not counting +		 * the vendor prefix. +		 */ +		if (name[n] == '#' && ((n == 0) || (name[n-1] == ','))) { +			name += n + 1; +			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); +	} +} +CHECK(property_name_chars_strict, check_property_name_chars_strict, PROPNODECHARSSTRICT); +  #define DESCLABEL_FMT	"%s%s%s%s%s"  #define DESCLABEL_ARGS(node,prop,mark)		\  	((mark) ? "value of " : ""),		\ @@ -327,7 +370,7 @@ static void check_duplicate_label(struct check *c, struct dt_info *dti,  		return;  	if ((othernode != node) || (otherprop != prop) || (othermark != mark)) -		FAIL(c, "Duplicate label '%s' on " DESCLABEL_FMT +		FAIL(c, dti, "Duplicate label '%s' on " DESCLABEL_FMT  		     " and " DESCLABEL_FMT,  		     label, DESCLABEL_ARGS(node, prop, mark),  		     DESCLABEL_ARGS(othernode, otherprop, othermark)); @@ -367,7 +410,7 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,  		return 0;  	if (prop->val.len != sizeof(cell_t)) { -		FAIL(c, "%s has bad length (%d) %s property", +		FAIL(c, dti, "%s has bad length (%d) %s property",  		     node->fullpath, prop->val.len, prop->name);  		return 0;  	} @@ -379,7 +422,7 @@ 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, "%s in %s is a reference to another node", +			FAIL(c, dti, "%s in %s is a reference to another node",  			     prop->name, node->fullpath);  		}  		/* But setting this node's phandle equal to its own @@ -393,7 +436,7 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,  	phandle = propval_cell(prop);  	if ((phandle == 0) || (phandle == -1)) { -		FAIL(c, "%s has bad value (0x%x) in %s property", +		FAIL(c, dti, "%s has bad value (0x%x) in %s property",  		     node->fullpath, phandle, prop->name);  		return 0;  	} @@ -420,7 +463,7 @@ static void check_explicit_phandles(struct check *c, struct dt_info *dti,  		return;  	if (linux_phandle && phandle && (phandle != linux_phandle)) -		FAIL(c, "%s has mismatching 'phandle' and 'linux,phandle'" +		FAIL(c, dti, "%s has mismatching 'phandle' and 'linux,phandle'"  		     " properties", node->fullpath);  	if (linux_phandle && !phandle) @@ -428,7 +471,7 @@ static void check_explicit_phandles(struct check *c, struct dt_info *dti,  	other = get_node_by_phandle(root, phandle);  	if (other && (other != node)) { -		FAIL(c, "%s has duplicated phandle 0x%x (seen before at %s)", +		FAIL(c, dti, "%s has duplicated phandle 0x%x (seen before at %s)",  		     node->fullpath, phandle, other->fullpath);  		return;  	} @@ -453,7 +496,7 @@ 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, "\"name\" property in %s is incorrect (\"%s\" instead" +		FAIL(c, dti, "\"name\" property in %s is incorrect (\"%s\" instead"  		     " of base node name)", node->fullpath, prop->val.val);  	} else {  		/* The name property is correct, and therefore redundant. @@ -488,16 +531,16 @@ 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, "Reference to non-existent node or " +					FAIL(c, dti, "Reference to non-existent node or "  							"label \"%s\"\n", m->ref);  				else /* mark the entry as unresolved */ -					*((cell_t *)(prop->val.val + m->offset)) = +					*((fdt32_t *)(prop->val.val + m->offset)) =  						cpu_to_fdt32(0xffffffff);  				continue;  			}  			phandle = get_node_phandle(dt, refnode); -			*((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle); +			*((fdt32_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);  		}  	}  } @@ -520,7 +563,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, "Reference to non-existent node or label \"%s\"\n", +				FAIL(c, dti, "Reference to non-existent node or label \"%s\"\n",  				     m->ref);  				continue;  			} @@ -579,19 +622,19 @@ static void check_reg_format(struct check *c, struct dt_info *dti,  		return; /* No "reg", that's fine */  	if (!node->parent) { -		FAIL(c, "Root node has a \"reg\" property"); +		FAIL(c, dti, "Root node has a \"reg\" property");  		return;  	}  	if (prop->val.len == 0) -		FAIL(c, "\"reg\" property in %s is empty", node->fullpath); +		FAIL(c, dti, "\"reg\" property in %s is empty", node->fullpath);  	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, "\"reg\" property in %s has invalid length (%d bytes) " +		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);  } @@ -608,7 +651,7 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,  		return;  	if (!node->parent) { -		FAIL(c, "Root node has a \"ranges\" property"); +		FAIL(c, dti, "Root node has a \"ranges\" property");  		return;  	} @@ -620,17 +663,17 @@ 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, "%s has empty \"ranges\" property but its " +			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);  		if (p_size_cells != c_size_cells) -			FAIL(c, "%s has empty \"ranges\" property but its " +			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);  	} else if ((prop->val.len % entrylen) != 0) { -		FAIL(c, "\"ranges\" property in %s has invalid length (%d bytes) " +		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); @@ -638,6 +681,229 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,  }  WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells); +static const struct bus_type pci_bus = { +	.name = "PCI", +}; + +static void check_pci_bridge(struct check *c, struct dt_info *dti, struct node *node) +{ +	struct property *prop; +	cell_t *cells; + +	prop = get_property(node, "device_type"); +	if (!prop || !streq(prop->val.val, "pci")) +		return; + +	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); + +	prop = get_property(node, "ranges"); +	if (!prop) +		FAIL(c, dti, "Node %s missing ranges for PCI bridge (or not a bridge)", +			     node->fullpath); + +	if (node_addr_cells(node) != 3) +		FAIL(c, dti, "Node %s incorrect #address-cells for PCI bridge", +			     node->fullpath); +	if (node_size_cells(node) != 2) +		FAIL(c, dti, "Node %s incorrect #size-cells for PCI bridge", +			     node->fullpath); + +	prop = get_property(node, "bus-range"); +	if (!prop) { +		FAIL(c, dti, "Node %s missing bus-range for PCI bridge", +			     node->fullpath); +		return; +	} +	if (prop->val.len != (sizeof(cell_t) * 2)) { +		FAIL(c, dti, "Node %s bus-range must be 2 cells", +			     node->fullpath); +		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); +	if (fdt32_to_cpu(cells[1]) > 0xff) +		FAIL(c, dti, "Node %s bus-range maximum bus number must be less than 256", +			     node->fullpath); +} +WARNING(pci_bridge, check_pci_bridge, NULL, +	&device_type_is_string, &addr_size_cells); + +static void check_pci_device_bus_num(struct check *c, struct dt_info *dti, struct node *node) +{ +	struct property *prop; +	unsigned int bus_num, min_bus, max_bus; +	cell_t *cells; + +	if (!node->parent || (node->parent->bus != &pci_bus)) +		return; + +	prop = get_property(node, "reg"); +	if (!prop) +		return; + +	cells = (cell_t *)prop->val.val; +	bus_num = (fdt32_to_cpu(cells[0]) & 0x00ff0000) >> 16; + +	prop = get_property(node->parent, "bus-range"); +	if (!prop) { +		min_bus = max_bus = 0; +	} else { +		cells = (cell_t *)prop->val.val; +		min_bus = fdt32_to_cpu(cells[0]); +		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); +} +WARNING(pci_device_bus_num, check_pci_device_bus_num, NULL, ®_format, &pci_bridge); + +static void check_pci_device_reg(struct check *c, struct dt_info *dti, struct node *node) +{ +	struct property *prop; +	const char *unitname = get_unitname(node); +	char unit_addr[5]; +	unsigned int dev, func, reg; +	cell_t *cells; + +	if (!node->parent || (node->parent->bus != &pci_bus)) +		return; + +	prop = get_property(node, "reg"); +	if (!prop) { +		FAIL(c, dti, "Node %s missing PCI reg property", node->fullpath); +		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); + +	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); +	if (reg & 0x000000ff) +		FAIL(c, dti, "Node %s PCI reg config space address register number must be 0", +			     node->fullpath); + +	if (func == 0) { +		snprintf(unit_addr, sizeof(unit_addr), "%x", dev); +		if (streq(unitname, unit_addr)) +			return; +	} + +	snprintf(unit_addr, sizeof(unit_addr), "%x,%x", dev, func); +	if (streq(unitname, unit_addr)) +		return; + +	FAIL(c, dti, "Node %s PCI unit address format error, expected \"%s\"", +	     node->fullpath, unit_addr); +} +WARNING(pci_device_reg, check_pci_device_reg, NULL, ®_format, &pci_bridge); + +static const struct bus_type simple_bus = { +	.name = "simple-bus", +}; + +static bool node_is_compatible(struct node *node, const char *compat) +{ +	struct property *prop; +	const char *str, *end; + +	prop = get_property(node, "compatible"); +	if (!prop) +		return false; + +	for (str = prop->val.val, end = str + prop->val.len; str < end; +	     str += strnlen(str, end - str) + 1) { +		if (strneq(str, compat, end - str)) +			return true; +	} +	return false; +} + +static void check_simple_bus_bridge(struct check *c, struct dt_info *dti, struct node *node) +{ +	if (node_is_compatible(node, "simple-bus")) +		node->bus = &simple_bus; +} +WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL, &addr_size_cells); + +static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct node *node) +{ +	struct property *prop; +	const char *unitname = get_unitname(node); +	char unit_addr[17]; +	unsigned int size; +	uint64_t reg = 0; +	cell_t *cells = NULL; + +	if (!node->parent || (node->parent->bus != &simple_bus)) +		return; + +	prop = get_property(node, "reg"); +	if (prop) +		cells = (cell_t *)prop->val.val; +	else { +		prop = get_property(node, "ranges"); +		if (prop && prop->val.len) +			/* skip of child address */ +			cells = ((cell_t *)prop->val.val) + node_addr_cells(node); +	} + +	if (!cells) { +		if (node->parent->parent && !(node->bus == &simple_bus)) +			FAIL(c, dti, "Node %s missing or empty reg/ranges property", node->fullpath); +		return; +	} + +	size = node_addr_cells(node->parent); +	while (size--) +		reg = (reg << 32) | fdt32_to_cpu(*(cells++)); + +	snprintf(unit_addr, sizeof(unit_addr), "%lx", reg); +	if (!streq(unitname, unit_addr)) +		FAIL(c, dti, "Node %s simple-bus unit address format error, expected \"%s\"", +		     node->fullpath, unit_addr); +} +WARNING(simple_bus_reg, check_simple_bus_reg, NULL, ®_format, &simple_bus_bridge); + +static void check_unit_address_format(struct check *c, struct dt_info *dti, +				      struct node *node) +{ +	const char *unitname = get_unitname(node); + +	if (node->parent && node->parent->bus) +		return; + +	if (!unitname[0]) +		return; + +	if (!strncmp(unitname, "0x", 2)) { +		FAIL(c, dti, "Node %s unit name should not have leading \"0x\"", +		    node->fullpath); +		/* 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); +} +WARNING(unit_address_format, check_unit_address_format, NULL, +	&node_name_format, &pci_bridge, &simple_bus_bridge); +  /*   * Style checks   */ @@ -656,11 +922,11 @@ static void check_avoid_default_addr_size(struct check *c, struct dt_info *dti,  		return;  	if (node->parent->addr_cells == -1) -		FAIL(c, "Relying on default #address-cells value for %s", +		FAIL(c, dti, "Relying on default #address-cells value for %s",  		     node->fullpath);  	if (node->parent->size_cells == -1) -		FAIL(c, "Relying on default #size-cells value for %s", +		FAIL(c, dti, "Relying on default #size-cells value for %s",  		     node->fullpath);  }  WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL, @@ -684,7 +950,7 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c,  	prop = get_property(chosen, "interrupt-controller");  	if (prop) -		FAIL(c, "/chosen has obsolete \"interrupt-controller\" " +		FAIL(c, dti, "/chosen has obsolete \"interrupt-controller\" "  		     "property");  }  WARNING(obsolete_chosen_interrupt_controller, @@ -703,9 +969,20 @@ 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, +	&property_name_chars_strict, +	&node_name_chars_strict, +  	&addr_size_cells, ®_format, &ranges_format,  	&unit_address_vs_reg, +	&unit_address_format, + +	&pci_bridge, +	&pci_device_reg, +	&pci_device_bus_num, + +	&simple_bus_bridge, +	&simple_bus_reg,  	&avoid_default_addr_size,  	&obsolete_chosen_interrupt_controller, diff --git a/scripts/dtc/data.c b/scripts/dtc/data.c index 8cae23746882..aa37a16c8891 100644 --- a/scripts/dtc/data.c +++ b/scripts/dtc/data.c @@ -171,9 +171,9 @@ struct data data_merge(struct data d1, struct data d2)  struct data data_append_integer(struct data d, uint64_t value, int bits)  {  	uint8_t value_8; -	uint16_t value_16; -	uint32_t value_32; -	uint64_t value_64; +	fdt16_t value_16; +	fdt32_t value_32; +	fdt64_t value_64;  	switch (bits) {  	case 8: @@ -197,14 +197,14 @@ struct data data_append_integer(struct data d, uint64_t value, int bits)  	}  } -struct data data_append_re(struct data d, const struct fdt_reserve_entry *re) +struct data data_append_re(struct data d, uint64_t address, uint64_t size)  { -	struct fdt_reserve_entry bere; +	struct fdt_reserve_entry re; -	bere.address = cpu_to_fdt64(re->address); -	bere.size = cpu_to_fdt64(re->size); +	re.address = cpu_to_fdt64(address); +	re.size = cpu_to_fdt64(size); -	return data_append_data(d, &bere, sizeof(bere)); +	return data_append_data(d, &re, sizeof(re));  }  struct data data_append_cell(struct data d, cell_t word) diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l index c600603044f3..fd825ebba69c 100644 --- a/scripts/dtc/dtc-lexer.l +++ b/scripts/dtc/dtc-lexer.l @@ -62,7 +62,8 @@ static int dts_version = 1;  static void push_input_file(const char *filename);  static bool pop_input_file(void); -static void lexical_error(const char *fmt, ...); +static void PRINTF(1, 2) lexical_error(const char *fmt, ...); +  %}  %% diff --git a/scripts/dtc/dtc-lexer.lex.c_shipped b/scripts/dtc/dtc-lexer.lex.c_shipped index 2c862bc86ad0..64c243772398 100644 --- a/scripts/dtc/dtc-lexer.lex.c_shipped +++ b/scripts/dtc/dtc-lexer.lex.c_shipped @@ -655,8 +655,9 @@ static int dts_version = 1;  static void push_input_file(const char *filename);  static bool pop_input_file(void); -static void lexical_error(const char *fmt, ...); -#line 660 "dtc-lexer.lex.c" +static void PRINTF(1, 2) lexical_error(const char *fmt, ...); + +#line 661 "dtc-lexer.lex.c"  #define INITIAL 0  #define BYTESTRING 1 @@ -878,9 +879,9 @@ YY_DECL  		}  	{ -#line 68 "dtc-lexer.l" +#line 69 "dtc-lexer.l" -#line 884 "dtc-lexer.lex.c" +#line 885 "dtc-lexer.lex.c"  	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is reached */  		{ @@ -937,7 +938,7 @@ do_action:	/* This label is used only to access EOF actions. */  case 1:  /* rule 1 can match eol */  YY_RULE_SETUP -#line 69 "dtc-lexer.l" +#line 70 "dtc-lexer.l"  {  			char *name = strchr(yytext, '\"') + 1;  			yytext[yyleng-1] = '\0'; @@ -947,7 +948,7 @@ YY_RULE_SETUP  case 2:  /* rule 2 can match eol */  YY_RULE_SETUP -#line 75 "dtc-lexer.l" +#line 76 "dtc-lexer.l"  {  			char *line, *fnstart, *fnend;  			struct data fn; @@ -981,7 +982,7 @@ case YY_STATE_EOF(INITIAL):  case YY_STATE_EOF(BYTESTRING):  case YY_STATE_EOF(PROPNODENAME):  case YY_STATE_EOF(V1): -#line 104 "dtc-lexer.l" +#line 105 "dtc-lexer.l"  {  			if (!pop_input_file()) {  				yyterminate(); @@ -991,7 +992,7 @@ case YY_STATE_EOF(V1):  case 3:  /* rule 3 can match eol */  YY_RULE_SETUP -#line 110 "dtc-lexer.l" +#line 111 "dtc-lexer.l"  {  			DPRINT("String: %s\n", yytext);  			yylval.data = data_copy_escape_string(yytext+1, @@ -1001,7 +1002,7 @@ YY_RULE_SETUP  	YY_BREAK  case 4:  YY_RULE_SETUP -#line 117 "dtc-lexer.l" +#line 118 "dtc-lexer.l"  {  			DPRINT("Keyword: /dts-v1/\n");  			dts_version = 1; @@ -1011,7 +1012,7 @@ YY_RULE_SETUP  	YY_BREAK  case 5:  YY_RULE_SETUP -#line 124 "dtc-lexer.l" +#line 125 "dtc-lexer.l"  {  			DPRINT("Keyword: /plugin/\n");  			return DT_PLUGIN; @@ -1019,7 +1020,7 @@ YY_RULE_SETUP  	YY_BREAK  case 6:  YY_RULE_SETUP -#line 129 "dtc-lexer.l" +#line 130 "dtc-lexer.l"  {  			DPRINT("Keyword: /memreserve/\n");  			BEGIN_DEFAULT(); @@ -1028,7 +1029,7 @@ YY_RULE_SETUP  	YY_BREAK  case 7:  YY_RULE_SETUP -#line 135 "dtc-lexer.l" +#line 136 "dtc-lexer.l"  {  			DPRINT("Keyword: /bits/\n");  			BEGIN_DEFAULT(); @@ -1037,7 +1038,7 @@ YY_RULE_SETUP  	YY_BREAK  case 8:  YY_RULE_SETUP -#line 141 "dtc-lexer.l" +#line 142 "dtc-lexer.l"  {  			DPRINT("Keyword: /delete-property/\n");  			DPRINT("<PROPNODENAME>\n"); @@ -1047,7 +1048,7 @@ YY_RULE_SETUP  	YY_BREAK  case 9:  YY_RULE_SETUP -#line 148 "dtc-lexer.l" +#line 149 "dtc-lexer.l"  {  			DPRINT("Keyword: /delete-node/\n");  			DPRINT("<PROPNODENAME>\n"); @@ -1057,7 +1058,7 @@ YY_RULE_SETUP  	YY_BREAK  case 10:  YY_RULE_SETUP -#line 155 "dtc-lexer.l" +#line 156 "dtc-lexer.l"  {  			DPRINT("Label: %s\n", yytext);  			yylval.labelref = xstrdup(yytext); @@ -1067,7 +1068,7 @@ YY_RULE_SETUP  	YY_BREAK  case 11:  YY_RULE_SETUP -#line 162 "dtc-lexer.l" +#line 163 "dtc-lexer.l"  {  			char *e;  			DPRINT("Integer Literal: '%s'\n", yytext); @@ -1093,7 +1094,7 @@ YY_RULE_SETUP  case 12:  /* rule 12 can match eol */  YY_RULE_SETUP -#line 184 "dtc-lexer.l" +#line 185 "dtc-lexer.l"  {  			struct data d;  			DPRINT("Character literal: %s\n", yytext); @@ -1117,7 +1118,7 @@ YY_RULE_SETUP  	YY_BREAK  case 13:  YY_RULE_SETUP -#line 205 "dtc-lexer.l" +#line 206 "dtc-lexer.l"  {	/* label reference */  			DPRINT("Ref: %s\n", yytext+1);  			yylval.labelref = xstrdup(yytext+1); @@ -1126,7 +1127,7 @@ YY_RULE_SETUP  	YY_BREAK  case 14:  YY_RULE_SETUP -#line 211 "dtc-lexer.l" +#line 212 "dtc-lexer.l"  {	/* new-style path reference */  			yytext[yyleng-1] = '\0';  			DPRINT("Ref: %s\n", yytext+2); @@ -1136,7 +1137,7 @@ YY_RULE_SETUP  	YY_BREAK  case 15:  YY_RULE_SETUP -#line 218 "dtc-lexer.l" +#line 219 "dtc-lexer.l"  {  			yylval.byte = strtol(yytext, NULL, 16);  			DPRINT("Byte: %02x\n", (int)yylval.byte); @@ -1145,7 +1146,7 @@ YY_RULE_SETUP  	YY_BREAK  case 16:  YY_RULE_SETUP -#line 224 "dtc-lexer.l" +#line 225 "dtc-lexer.l"  {  			DPRINT("/BYTESTRING\n");  			BEGIN_DEFAULT(); @@ -1154,7 +1155,7 @@ YY_RULE_SETUP  	YY_BREAK  case 17:  YY_RULE_SETUP -#line 230 "dtc-lexer.l" +#line 231 "dtc-lexer.l"  {  			DPRINT("PropNodeName: %s\n", yytext);  			yylval.propnodename = xstrdup((yytext[0] == '\\') ? @@ -1165,7 +1166,7 @@ YY_RULE_SETUP  	YY_BREAK  case 18:  YY_RULE_SETUP -#line 238 "dtc-lexer.l" +#line 239 "dtc-lexer.l"  {  			DPRINT("Binary Include\n");  			return DT_INCBIN; @@ -1174,64 +1175,64 @@ YY_RULE_SETUP  case 19:  /* rule 19 can match eol */  YY_RULE_SETUP -#line 243 "dtc-lexer.l" +#line 244 "dtc-lexer.l"  /* eat whitespace */  	YY_BREAK  case 20:  /* rule 20 can match eol */  YY_RULE_SETUP -#line 244 "dtc-lexer.l" +#line 245 "dtc-lexer.l"  /* eat C-style comments */  	YY_BREAK  case 21:  /* rule 21 can match eol */  YY_RULE_SETUP -#line 245 "dtc-lexer.l" +#line 246 "dtc-lexer.l"  /* eat C++-style comments */  	YY_BREAK  case 22:  YY_RULE_SETUP -#line 247 "dtc-lexer.l" +#line 248 "dtc-lexer.l"  { return DT_LSHIFT; };  	YY_BREAK  case 23:  YY_RULE_SETUP -#line 248 "dtc-lexer.l" +#line 249 "dtc-lexer.l"  { return DT_RSHIFT; };  	YY_BREAK  case 24:  YY_RULE_SETUP -#line 249 "dtc-lexer.l" +#line 250 "dtc-lexer.l"  { return DT_LE; };  	YY_BREAK  case 25:  YY_RULE_SETUP -#line 250 "dtc-lexer.l" +#line 251 "dtc-lexer.l"  { return DT_GE; };  	YY_BREAK  case 26:  YY_RULE_SETUP -#line 251 "dtc-lexer.l" +#line 252 "dtc-lexer.l"  { return DT_EQ; };  	YY_BREAK  case 27:  YY_RULE_SETUP -#line 252 "dtc-lexer.l" +#line 253 "dtc-lexer.l"  { return DT_NE; };  	YY_BREAK  case 28:  YY_RULE_SETUP -#line 253 "dtc-lexer.l" +#line 254 "dtc-lexer.l"  { return DT_AND; };  	YY_BREAK  case 29:  YY_RULE_SETUP -#line 254 "dtc-lexer.l" +#line 255 "dtc-lexer.l"  { return DT_OR; };  	YY_BREAK  case 30:  YY_RULE_SETUP -#line 256 "dtc-lexer.l" +#line 257 "dtc-lexer.l"  {  			DPRINT("Char: %c (\\x%02x)\n", yytext[0],  				(unsigned)yytext[0]); @@ -1249,10 +1250,10 @@ YY_RULE_SETUP  	YY_BREAK  case 31:  YY_RULE_SETUP -#line 271 "dtc-lexer.l" +#line 272 "dtc-lexer.l"  ECHO;  	YY_BREAK -#line 1256 "dtc-lexer.lex.c" +#line 1257 "dtc-lexer.lex.c"  	case YY_END_OF_BUFFER:  		{ @@ -2218,7 +2219,7 @@ void yyfree (void * ptr )  #define YYTABLES_NAME "yytables" -#line 271 "dtc-lexer.l" +#line 272 "dtc-lexer.l" diff --git a/scripts/dtc/dtc-parser.tab.c_shipped b/scripts/dtc/dtc-parser.tab.c_shipped index 2965227a1b4a..0a7a5ed86f04 100644 --- a/scripts/dtc/dtc-parser.tab.c_shipped +++ b/scripts/dtc/dtc-parser.tab.c_shipped @@ -1557,10 +1557,10 @@ yyreduce:      {  			struct node *target = get_node_by_ref((yyvsp[-3].node), (yyvsp[-1].labelref)); -			add_label(&target->labels, (yyvsp[-2].labelref)); -			if (target) +			if (target) { +				add_label(&target->labels, (yyvsp[-2].labelref));  				merge_nodes(target, (yyvsp[0].node)); -			else +			} else  				ERROR(&(yylsp[-1]), "Label or path %s not found", (yyvsp[-1].labelref));  			(yyval.node) = (yyvsp[-3].node);  		} diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y index b2fd4d155839..ca3f5003427c 100644 --- a/scripts/dtc/dtc-parser.y +++ b/scripts/dtc/dtc-parser.y @@ -171,10 +171,10 @@ devicetree:  		{  			struct node *target = get_node_by_ref($1, $3); -			add_label(&target->labels, $2); -			if (target) +			if (target) { +				add_label(&target->labels, $2);  				merge_nodes(target, $4); -			else +			} else  				ERROR(&@3, "Label or path %s not found", $3);  			$$ = $1;  		} diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c index a4edf4c7aebf..f5eed9d72c02 100644 --- a/scripts/dtc/dtc.c +++ b/scripts/dtc/dtc.c @@ -138,7 +138,7 @@ static const char *guess_type_by_name(const char *fname, const char *fallback)  static const char *guess_input_format(const char *fname, const char *fallback)  {  	struct stat statbuf; -	uint32_t magic; +	fdt32_t magic;  	FILE *f;  	if (stat(fname, &statbuf) != 0) @@ -159,8 +159,7 @@ static const char *guess_input_format(const char *fname, const char *fallback)  	}  	fclose(f); -	magic = fdt32_to_cpu(magic); -	if (magic == FDT_MAGIC) +	if (fdt32_to_cpu(magic) == FDT_MAGIC)  		return "dtb";  	return guess_type_by_name(fname, fallback); @@ -216,7 +215,7 @@ int main(int argc, char *argv[])  			alignsize = strtol(optarg, NULL, 0);  			if (!is_power_of_2(alignsize))  				die("Invalid argument \"%d\" to -a option\n", -				    optarg); +				    alignsize);  			break;  		case 'f':  			force = true; @@ -309,6 +308,8 @@ int main(int argc, char *argv[])  	else  		die("Unknown input format \"%s\"\n", inform); +	dti->outname = outname; +  	if (depfile) {  		fputc('\n', depfile);  		fclose(depfile); diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h index c6f125c68ba8..fc24e17510fd 100644 --- a/scripts/dtc/dtc.h +++ b/scripts/dtc/dtc.h @@ -43,7 +43,6 @@  #define debug(...)  #endif -  #define DEFAULT_FDT_VERSION	17  /* @@ -114,7 +113,7 @@ struct data data_insert_at_marker(struct data d, struct marker *m,  struct data data_merge(struct data d1, struct data d2);  struct data data_append_cell(struct data d, cell_t word);  struct data data_append_integer(struct data d, uint64_t word, int bits); -struct data data_append_re(struct data d, const struct fdt_reserve_entry *re); +struct data data_append_re(struct data d, uint64_t address, uint64_t size);  struct data data_append_addr(struct data d, uint64_t addr);  struct data data_append_byte(struct data d, uint8_t byte);  struct data data_append_zeroes(struct data d, int len); @@ -136,6 +135,10 @@ struct label {  	struct label *next;  }; +struct bus_type { +	const char *name; +}; +  struct property {  	bool deleted;  	char *name; @@ -162,6 +165,7 @@ struct node {  	int addr_cells, size_cells;  	struct label *labels; +	const struct bus_type *bus;  };  #define for_each_label_withdel(l0, l) \ @@ -227,7 +231,7 @@ uint32_t guess_boot_cpuid(struct node *tree);  /* Boot info (tree plus memreserve information */  struct reserve_info { -	struct fdt_reserve_entry re; +	uint64_t address, size;  	struct reserve_info *next; @@ -246,6 +250,7 @@ struct dt_info {  	struct reserve_info *reservelist;  	uint32_t boot_cpuid_phys;  	struct node *dt;		/* the device tree */ +	const char *outname;		/* filename being written to, "-" for stdout */  };  /* DTS version flags definitions */ diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c index ebac548b3fa8..fcf71541d8a7 100644 --- a/scripts/dtc/flattree.c +++ b/scripts/dtc/flattree.c @@ -49,7 +49,7 @@ static struct version_info {  struct emitter {  	void (*cell)(void *, cell_t); -	void (*string)(void *, char *, int); +	void (*string)(void *, const char *, int);  	void (*align)(void *, int);  	void (*data)(void *, struct data);  	void (*beginnode)(void *, struct label *labels); @@ -64,7 +64,7 @@ static void bin_emit_cell(void *e, cell_t val)  	*dtbuf = data_append_cell(*dtbuf, val);  } -static void bin_emit_string(void *e, char *str, int len) +static void bin_emit_string(void *e, const char *str, int len)  {  	struct data *dtbuf = e; @@ -144,22 +144,14 @@ static void asm_emit_cell(void *e, cell_t val)  		(val >> 8) & 0xff, val & 0xff);  } -static void asm_emit_string(void *e, char *str, int len) +static void asm_emit_string(void *e, const char *str, int len)  {  	FILE *f = e; -	char c = 0; -	if (len != 0) { -		/* XXX: ewww */ -		c = str[len]; -		str[len] = '\0'; -	} - -	fprintf(f, "\t.string\t\"%s\"\n", str); - -	if (len != 0) { -		str[len] = c; -	} +	if (len != 0) +		fprintf(f, "\t.string\t\"%.*s\"\n", len, str); +	else +		fprintf(f, "\t.string\t\"%s\"\n", str);  }  static void asm_emit_align(void *e, int a) @@ -179,7 +171,7 @@ static void asm_emit_data(void *e, struct data d)  		emit_offset_label(f, m->ref, m->offset);  	while ((d.len - off) >= sizeof(uint32_t)) { -		asm_emit_cell(e, fdt32_to_cpu(*((uint32_t *)(d.val+off)))); +		asm_emit_cell(e, fdt32_to_cpu(*((fdt32_t *)(d.val+off))));  		off += sizeof(uint32_t);  	} @@ -318,17 +310,16 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist,  {  	struct reserve_info *re;  	struct data d = empty_data; -	static struct fdt_reserve_entry null_re = {0,0};  	int    j;  	for (re = reservelist; re; re = re->next) { -		d = data_append_re(d, &re->re); +		d = data_append_re(d, re->address, re->size);  	}  	/*  	 * Add additional reserved slots if the user asked for them.  	 */  	for (j = 0; j < reservenum; j++) { -		d = data_append_re(d, &null_re); +		d = data_append_re(d, 0, 0);  	}  	return d; @@ -544,11 +535,11 @@ void dt_to_asm(FILE *f, struct dt_info *dti, int version)  			fprintf(f, "\t.globl\t%s\n", l->label);  			fprintf(f, "%s:\n", l->label);  		} -		ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.address >> 32)); +		ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->address >> 32));  		ASM_EMIT_BELONG(f, "0x%08x", -				(unsigned int)(re->re.address & 0xffffffff)); -		ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size >> 32)); -		ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size & 0xffffffff)); +				(unsigned int)(re->address & 0xffffffff)); +		ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size >> 32)); +		ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size & 0xffffffff));  	}  	for (i = 0; i < reservenum; i++) {  		fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n"); @@ -609,7 +600,7 @@ static void flat_read_chunk(struct inbuf *inb, void *p, int len)  static uint32_t flat_read_word(struct inbuf *inb)  { -	uint32_t val; +	fdt32_t val;  	assert(((inb->ptr - inb->base) % sizeof(val)) == 0); @@ -718,13 +709,15 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)  	 * First pass, count entries.  	 */  	while (1) { +		uint64_t address, size; +  		flat_read_chunk(inb, &re, sizeof(re)); -		re.address  = fdt64_to_cpu(re.address); -		re.size = fdt64_to_cpu(re.size); -		if (re.size == 0) +		address  = fdt64_to_cpu(re.address); +		size = fdt64_to_cpu(re.size); +		if (size == 0)  			break; -		new = build_reserve_entry(re.address, re.size); +		new = build_reserve_entry(address, size);  		reservelist = add_reserve_entry(reservelist, new);  	} @@ -817,6 +810,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,  struct dt_info *dt_from_blob(const char *fname)  {  	FILE *f; +	fdt32_t magic_buf, totalsize_buf;  	uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys;  	uint32_t off_dt, off_str, off_mem_rsvmap;  	int rc; @@ -833,7 +827,7 @@ struct dt_info *dt_from_blob(const char *fname)  	f = srcfile_relative_open(fname, NULL); -	rc = fread(&magic, sizeof(magic), 1, f); +	rc = fread(&magic_buf, sizeof(magic_buf), 1, f);  	if (ferror(f))  		die("Error reading DT blob magic number: %s\n",  		    strerror(errno)); @@ -844,11 +838,11 @@ struct dt_info *dt_from_blob(const char *fname)  			die("Mysterious short read reading magic number\n");  	} -	magic = fdt32_to_cpu(magic); +	magic = fdt32_to_cpu(magic_buf);  	if (magic != FDT_MAGIC)  		die("Blob has incorrect magic number\n"); -	rc = fread(&totalsize, sizeof(totalsize), 1, f); +	rc = fread(&totalsize_buf, sizeof(totalsize_buf), 1, f);  	if (ferror(f))  		die("Error reading DT blob size: %s\n", strerror(errno));  	if (rc < 1) { @@ -858,7 +852,7 @@ struct dt_info *dt_from_blob(const char *fname)  			die("Mysterious short read reading blob size\n");  	} -	totalsize = fdt32_to_cpu(totalsize); +	totalsize = fdt32_to_cpu(totalsize_buf);  	if (totalsize < FDT_V1_SIZE)  		die("DT blob size (%d) is too small\n", totalsize); diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c index 2eed4f58387c..3fd5847377c9 100644 --- a/scripts/dtc/libfdt/fdt_rw.c +++ b/scripts/dtc/libfdt/fdt_rw.c @@ -283,7 +283,8 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,  	if (err)  		return err; -	memcpy(prop->data, val, len); +	if (len) +		memcpy(prop->data, val, len);  	return 0;  } diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h index b842b156fa17..ba86caa73d01 100644 --- a/scripts/dtc/libfdt/libfdt.h +++ b/scripts/dtc/libfdt/libfdt.h @@ -143,7 +143,9 @@  /* Low-level functions (you probably don't need these)                */  /**********************************************************************/ +#ifndef SWIG /* This function is not useful in Python */  const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen); +#endif  static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)  {  	return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen); @@ -210,7 +212,6 @@ int fdt_next_subnode(const void *fdt, int offset);  /**********************************************************************/  /* General functions                                                  */  /**********************************************************************/ -  #define fdt_get_header(fdt, field) \  	(fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))  #define fdt_magic(fdt)			(fdt_get_header(fdt, magic)) @@ -354,8 +355,10 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size);   * useful for finding subnodes based on a portion of a larger string,   * such as a full path.   */ +#ifndef SWIG /* Not available in Python */  int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,  			       const char *name, int namelen); +#endif  /**   * fdt_subnode_offset - find a subnode of a given node   * @fdt: pointer to the device tree blob @@ -391,7 +394,9 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);   * Identical to fdt_path_offset(), but only consider the first namelen   * characters of path as the path name.   */ +#ifndef SWIG /* Not available in Python */  int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen); +#endif  /**   * fdt_path_offset - find a tree node by its full path @@ -550,10 +555,12 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,   * Identical to fdt_get_property(), but only examine the first namelen   * characters of name for matching the property name.   */ +#ifndef SWIG /* Not available in Python */  const struct fdt_property *fdt_get_property_namelen(const void *fdt,  						    int nodeoffset,  						    const char *name,  						    int namelen, int *lenp); +#endif  /**   * fdt_get_property - find a given property in a given node @@ -624,8 +631,10 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,   *		-FDT_ERR_BADSTRUCTURE,   *		-FDT_ERR_TRUNCATED, standard meanings   */ +#ifndef SWIG /* This function is not useful in Python */  const void *fdt_getprop_by_offset(const void *fdt, int offset,  				  const char **namep, int *lenp); +#endif  /**   * fdt_getprop_namelen - get property value based on substring @@ -638,6 +647,7 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,   * Identical to fdt_getprop(), but only examine the first namelen   * characters of name for matching the property name.   */ +#ifndef SWIG /* Not available in Python */  const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,  				const char *name, int namelen, int *lenp);  static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset, @@ -647,6 +657,7 @@ static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,  	return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name,  						      namelen, lenp);  } +#endif  /**   * fdt_getprop - retrieve the value of a given property @@ -707,8 +718,10 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);   * Identical to fdt_get_alias(), but only examine the first namelen   * characters of name for matching the alias name.   */ +#ifndef SWIG /* Not available in Python */  const char *fdt_get_alias_namelen(const void *fdt,  				  const char *name, int namelen); +#endif  /**   * fdt_get_alias - retrieve the path referenced by a given alias @@ -1106,10 +1119,12 @@ int fdt_size_cells(const void *fdt, int nodeoffset);   * of the name. It is useful when you want to manipulate only one value of   * an array and you have a string that doesn't end with \0.   */ +#ifndef SWIG /* Not available in Python */  int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,  					const char *name, int namelen,  					uint32_t idx, const void *val,  					int len); +#endif  /**   * fdt_setprop_inplace - change a property's value, but not its size @@ -1139,8 +1154,10 @@ int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,   *	-FDT_ERR_BADSTRUCTURE,   *	-FDT_ERR_TRUNCATED, standard meanings   */ +#ifndef SWIG /* Not available in Python */  int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,  			const void *val, int len); +#endif  /**   * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property @@ -1527,6 +1544,36 @@ static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,  #define fdt_setprop_string(fdt, nodeoffset, name, str) \  	fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) + +/** + * fdt_setprop_empty - set a property to an empty value + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * + * fdt_setprop_empty() sets the value of the named property in the + * given node to an empty (zero length) value, or creates a new empty + * property if it does not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + *	0, on success + *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to + *		contain the new property value + *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + *	-FDT_ERR_BADLAYOUT, + *	-FDT_ERR_BADMAGIC, + *	-FDT_ERR_BADVERSION, + *	-FDT_ERR_BADSTATE, + *	-FDT_ERR_BADSTRUCTURE, + *	-FDT_ERR_BADLAYOUT, + *	-FDT_ERR_TRUNCATED, standard meanings + */ +#define fdt_setprop_empty(fdt, nodeoffset, name) \ +	fdt_setprop((fdt), (nodeoffset), (name), NULL, 0) +  /**   * fdt_appendprop - append to or create a property   * @fdt: pointer to the device tree blob @@ -1704,8 +1751,10 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name);   * creating subnodes based on a portion of a larger string, such as a   * full path.   */ +#ifndef SWIG /* Not available in Python */  int fdt_add_subnode_namelen(void *fdt, int parentoffset,  			    const char *name, int namelen); +#endif  /**   * fdt_add_subnode - creates a new node diff --git a/scripts/dtc/libfdt/libfdt_env.h b/scripts/dtc/libfdt/libfdt_env.h index 99f936dacc60..952056cddf09 100644 --- a/scripts/dtc/libfdt/libfdt_env.h +++ b/scripts/dtc/libfdt/libfdt_env.h @@ -58,16 +58,16 @@  #include <string.h>  #ifdef __CHECKER__ -#define __force __attribute__((force)) -#define __bitwise __attribute__((bitwise)) +#define FDT_FORCE __attribute__((force)) +#define FDT_BITWISE __attribute__((bitwise))  #else -#define __force -#define __bitwise +#define FDT_FORCE +#define FDT_BITWISE  #endif -typedef uint16_t __bitwise fdt16_t; -typedef uint32_t __bitwise fdt32_t; -typedef uint64_t __bitwise fdt64_t; +typedef uint16_t FDT_BITWISE fdt16_t; +typedef uint32_t FDT_BITWISE fdt32_t; +typedef uint64_t FDT_BITWISE fdt64_t;  #define EXTRACT_BYTE(x, n)	((unsigned long long)((uint8_t *)&x)[n])  #define CPU_TO_FDT16(x) ((EXTRACT_BYTE(x, 0) << 8) | EXTRACT_BYTE(x, 1)) @@ -80,29 +80,29 @@ typedef uint64_t __bitwise fdt64_t;  static inline uint16_t fdt16_to_cpu(fdt16_t x)  { -	return (__force uint16_t)CPU_TO_FDT16(x); +	return (FDT_FORCE uint16_t)CPU_TO_FDT16(x);  }  static inline fdt16_t cpu_to_fdt16(uint16_t x)  { -	return (__force fdt16_t)CPU_TO_FDT16(x); +	return (FDT_FORCE fdt16_t)CPU_TO_FDT16(x);  }  static inline uint32_t fdt32_to_cpu(fdt32_t x)  { -	return (__force uint32_t)CPU_TO_FDT32(x); +	return (FDT_FORCE uint32_t)CPU_TO_FDT32(x);  }  static inline fdt32_t cpu_to_fdt32(uint32_t x)  { -	return (__force fdt32_t)CPU_TO_FDT32(x); +	return (FDT_FORCE fdt32_t)CPU_TO_FDT32(x);  }  static inline uint64_t fdt64_to_cpu(fdt64_t x)  { -	return (__force uint64_t)CPU_TO_FDT64(x); +	return (FDT_FORCE uint64_t)CPU_TO_FDT64(x);  }  static inline fdt64_t cpu_to_fdt64(uint64_t x)  { -	return (__force fdt64_t)CPU_TO_FDT64(x); +	return (FDT_FORCE fdt64_t)CPU_TO_FDT64(x);  }  #undef CPU_TO_FDT64  #undef CPU_TO_FDT32 diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c index afa2f67b142a..3673de07e4e5 100644 --- a/scripts/dtc/livetree.c +++ b/scripts/dtc/livetree.c @@ -242,7 +242,7 @@ void delete_property_by_name(struct node *node, char *name)  	struct property *prop = node->proplist;  	while (prop) { -		if (!strcmp(prop->name, name)) { +		if (streq(prop->name, name)) {  			delete_property(prop);  			return;  		} @@ -275,7 +275,7 @@ void delete_node_by_name(struct node *parent, char *name)  	struct node *node = parent->children;  	while (node) { -		if (!strcmp(node->name, name)) { +		if (streq(node->name, name)) {  			delete_node(node);  			return;  		} @@ -319,8 +319,8 @@ struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)  	memset(new, 0, sizeof(*new)); -	new->re.address = address; -	new->re.size = size; +	new->address = address; +	new->size = size;  	return new;  } @@ -393,7 +393,7 @@ struct property *get_property(struct node *node, const char *propname)  cell_t propval_cell(struct property *prop)  {  	assert(prop->val.len == sizeof(cell_t)); -	return fdt32_to_cpu(*((cell_t *)prop->val.val)); +	return fdt32_to_cpu(*((fdt32_t *)prop->val.val));  }  struct property *get_property_by_label(struct node *tree, const char *label, @@ -599,13 +599,13 @@ static int cmp_reserve_info(const void *ax, const void *bx)  	a = *((const struct reserve_info * const *)ax);  	b = *((const struct reserve_info * const *)bx); -	if (a->re.address < b->re.address) +	if (a->address < b->address)  		return -1; -	else if (a->re.address > b->re.address) +	else if (a->address > b->address)  		return 1; -	else if (a->re.size < b->re.size) +	else if (a->size < b->size)  		return -1; -	else if (a->re.size > b->re.size) +	else if (a->size > b->size)  		return 1;  	else  		return 0; @@ -847,6 +847,8 @@ static void add_fixup_entry(struct dt_info *dti, struct node *fn,  	xasprintf(&entry, "%s:%s:%u",  			node->fullpath, prop->name, m->offset);  	append_to_property(fn, m->ref, entry, strlen(entry) + 1); + +	free(entry);  }  static void generate_fixups_tree_internal(struct dt_info *dti, @@ -900,7 +902,7 @@ static void add_local_fixup_entry(struct dt_info *dti,  		struct node *refnode)  {  	struct node *wn, *nwn;	/* local fixup node, walk node, new */ -	uint32_t value_32; +	fdt32_t value_32;  	char **compp;  	int i, depth; diff --git a/scripts/dtc/srcpos.c b/scripts/dtc/srcpos.c index aa3aad04cec4..9d38459902f3 100644 --- a/scripts/dtc/srcpos.c +++ b/scripts/dtc/srcpos.c @@ -252,7 +252,7 @@ srcpos_string(struct srcpos *pos)  	const char *fname = "<no-file>";  	char *pos_str; -	if (pos) +	if (pos->file && pos->file->name)  		fname = pos->file->name; diff --git a/scripts/dtc/srcpos.h b/scripts/dtc/srcpos.h index 2cdfcd82e95e..7caca8257c6d 100644 --- a/scripts/dtc/srcpos.h +++ b/scripts/dtc/srcpos.h @@ -22,6 +22,7 @@  #include <stdio.h>  #include <stdbool.h> +#include "util.h"  struct srcfile_state {  	FILE *f; @@ -106,12 +107,10 @@ extern void srcpos_update(struct srcpos *pos, const char *text, int len);  extern struct srcpos *srcpos_copy(struct srcpos *pos);  extern char *srcpos_string(struct srcpos *pos); -extern void srcpos_verror(struct srcpos *pos, const char *prefix, -			  const char *fmt, va_list va) -	__attribute__((format(printf, 3, 0))); -extern void srcpos_error(struct srcpos *pos, const char *prefix, -			 const char *fmt, ...) -	__attribute__((format(printf, 3, 4))); +extern void PRINTF(3, 0) srcpos_verror(struct srcpos *pos, const char *prefix, +					const char *fmt, va_list va); +extern void PRINTF(3, 4) srcpos_error(struct srcpos *pos, const char *prefix, +				      const char *fmt, ...);  extern void srcpos_set_line(char *f, int l); diff --git a/scripts/dtc/treesource.c b/scripts/dtc/treesource.c index c9d8967969f9..2461a3d068a0 100644 --- a/scripts/dtc/treesource.c +++ b/scripts/dtc/treesource.c @@ -137,7 +137,7 @@ static void write_propval_string(FILE *f, struct data val)  static void write_propval_cells(FILE *f, struct data val)  {  	void *propend = val.val + val.len; -	cell_t *cp = (cell_t *)val.val; +	fdt32_t *cp = (fdt32_t *)val.val;  	struct marker *m = val.markers;  	fprintf(f, "<"); @@ -275,8 +275,8 @@ void dt_to_source(FILE *f, struct dt_info *dti)  		for_each_label(re->labels, l)  			fprintf(f, "%s: ", l->label);  		fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n", -			(unsigned long long)re->re.address, -			(unsigned long long)re->re.size); +			(unsigned long long)re->address, +			(unsigned long long)re->size);  	}  	write_tree_source_node(f, dti->dt, 0); diff --git a/scripts/dtc/update-dtc-source.sh b/scripts/dtc/update-dtc-source.sh index f5cde799db03..b8ebcc6722d2 100755 --- a/scripts/dtc/update-dtc-source.sh +++ b/scripts/dtc/update-dtc-source.sh @@ -36,10 +36,19 @@ DTC_SOURCE="checks.c data.c dtc.c dtc.h flattree.c fstree.c livetree.c srcpos.c  DTC_GENERATED="dtc-lexer.lex.c dtc-parser.tab.c dtc-parser.tab.h"  LIBFDT_SOURCE="Makefile.libfdt fdt.c fdt.h fdt_empty_tree.c fdt_ro.c fdt_rw.c fdt_strerror.c fdt_sw.c fdt_wip.c libfdt.h libfdt_env.h libfdt_internal.h" +get_last_dtc_version() { +	git log --oneline scripts/dtc/ | grep 'upstream' | head -1 | sed -e 's/^.* \(.*\)/\1/' +} + +last_dtc_ver=$(get_last_dtc_version) +  # Build DTC  cd $DTC_UPSTREAM_PATH  make clean  make check +dtc_version=$(git describe HEAD) +dtc_log=$(git log --oneline ${last_dtc_ver}..) +  # Copy the files into the Linux tree  cd $DTC_LINUX_PATH @@ -60,4 +69,13 @@ sed -i -- 's/#include <libfdt_env.h>/#include "libfdt_env.h"/g' ./libfdt/libfdt.  sed -i -- 's/#include <fdt.h>/#include "fdt.h"/g' ./libfdt/libfdt.h  git add ./libfdt/libfdt.h -git commit -e -v -m "scripts/dtc: Update to upstream version [CHANGEME]" +commit_msg=$(cat << EOF +scripts/dtc: Update to upstream version ${dtc_version} + +This adds the following commits from upstream: + +${dtc_log} +EOF +) + +git commit -e -v -s -m "${commit_msg}" diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c index 3550f86bd6df..9953c32a0244 100644 --- a/scripts/dtc/util.c +++ b/scripts/dtc/util.c @@ -396,7 +396,7 @@ void utilfdt_print_data(const char *data, int len)  		} while (s < data + len);  	} else if ((len % 4) == 0) { -		const uint32_t *cell = (const uint32_t *)data; +		const fdt32_t *cell = (const fdt32_t *)data;  		printf(" = <");  		for (i = 0, len /= 4; i < len; i++) @@ -412,15 +412,16 @@ void utilfdt_print_data(const char *data, int len)  	}  } -void util_version(void) +void NORETURN util_version(void)  {  	printf("Version: %s\n", DTC_VERSION);  	exit(0);  } -void util_usage(const char *errmsg, const char *synopsis, -		const char *short_opts, struct option const long_opts[], -		const char * const opts_help[]) +void NORETURN util_usage(const char *errmsg, const char *synopsis, +			 const char *short_opts, +			 struct option const long_opts[], +			 const char * const opts_help[])  {  	FILE *fp = errmsg ? stderr : stdout;  	const char a_arg[] = "<arg>"; diff --git a/scripts/dtc/util.h b/scripts/dtc/util.h index f5c4f1b50d30..ad5f41199edb 100644 --- a/scripts/dtc/util.h +++ b/scripts/dtc/util.h @@ -25,9 +25,17 @@   *                                                                   USA   */ +#ifdef __GNUC__ +#define PRINTF(i, j)	__attribute__((format (printf, i, j))) +#define NORETURN	__attribute__((noreturn)) +#else +#define PRINTF(i, j) +#define NORETURN +#endif +  #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) -static inline void __attribute__((noreturn)) die(const char *str, ...) +static inline void NORETURN PRINTF(1, 2) die(const char *str, ...)  {  	va_list ap; @@ -53,13 +61,14 @@ static inline void *xrealloc(void *p, size_t len)  	void *new = realloc(p, len);  	if (!new) -		die("realloc() failed (len=%d)\n", len); +		die("realloc() failed (len=%zd)\n", len);  	return new;  }  extern char *xstrdup(const char *s); -extern int xasprintf(char **strp, const char *fmt, ...); + +extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...);  extern char *join_path(const char *path, const char *name);  /** @@ -188,7 +197,7 @@ void utilfdt_print_data(const char *data, int len);  /**   * Show source version and exit   */ -void util_version(void) __attribute__((noreturn)); +void NORETURN util_version(void);  /**   * Show usage and exit @@ -202,9 +211,10 @@ void util_version(void) __attribute__((noreturn));   * @param long_opts	The structure of long options   * @param opts_help	An array of help strings (should align with long_opts)   */ -void util_usage(const char *errmsg, const char *synopsis, -		const char *short_opts, struct option const long_opts[], -		const char * const opts_help[]) __attribute__((noreturn)); +void NORETURN util_usage(const char *errmsg, const char *synopsis, +			 const char *short_opts, +			 struct option const long_opts[], +			 const char * const opts_help[]);  /**   * Show usage and exit diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h index 16c2e53a85e3..1229e07b4912 100644 --- a/scripts/dtc/version_gen.h +++ b/scripts/dtc/version_gen.h @@ -1 +1 @@ -#define DTC_VERSION "DTC 1.4.2-g0931cea3" +#define DTC_VERSION "DTC 1.4.4-g756ffc4f" |