generic: 5.15: move dtc drop interrupt check from pending to backport
Move dtc drop interrupto check from pending to backport as it got merged upstream. Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
This commit is contained in:
		| @@ -0,0 +1,997 @@ | |||||||
|  | From a77725a9a3c5924e2fd4cd5b3557dd92a8e46f87 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Rob Herring <robh@kernel.org> | ||||||
|  | Date: Mon, 25 Oct 2021 11:05:45 -0500 | ||||||
|  | Subject: [PATCH 1/1] scripts/dtc: Update to upstream version | ||||||
|  |  v1.6.1-19-g0a3a9d3449c8 | ||||||
|  |  | ||||||
|  | This adds the following commits from upstream: | ||||||
|  |  | ||||||
|  | 0a3a9d3449c8 checks: Add an interrupt-map check | ||||||
|  | 8fd24744e361 checks: Ensure '#interrupt-cells' only exists in interrupt providers | ||||||
|  | d8d1a9a77863 checks: Drop interrupt provider '#address-cells' check | ||||||
|  | 52a16fd72824 checks: Make interrupt_provider check dependent on interrupts_extended_is_cell | ||||||
|  | 37fd700685da treesource: Maintain phandle label/path on output | ||||||
|  | e33ce1d6a8c7 flattree: Use '\n', not ';' to separate asm pseudo-ops | ||||||
|  | d24cc189dca6 asm: Use assembler macros instead of cpp macros | ||||||
|  | ff3a30c115ad asm: Use .asciz and .ascii instead of .string | ||||||
|  | 5eb5927d81ee fdtdump: fix -Werror=int-to-pointer-cast | ||||||
|  | 0869f8269161 libfdt: Add ALIGNMENT error string | ||||||
|  | 69595a167f06 checks: Fix bus-range check | ||||||
|  | 72d09e2682a4 Makefile: add -Wsign-compare to warning options | ||||||
|  | b587787ef388 checks: Fix signedness comparisons warnings | ||||||
|  | 69bed6c2418f dtc: Wrap phandle validity check | ||||||
|  | 910221185560 fdtget: Fix signedness comparisons warnings | ||||||
|  | d966f08fcd21 tests: Fix signedness comparisons warnings | ||||||
|  | ecfb438c07fa dtc: Fix signedness comparisons warnings: pointer diff | ||||||
|  | 5bec74a6d135 dtc: Fix signedness comparisons warnings: reservednum | ||||||
|  | 24e7f511fd4a fdtdump: Fix signedness comparisons warnings | ||||||
|  | b6910bec1161 Bump version to v1.6.1 | ||||||
|  | 21d61d18f968 Fix CID 1461557 | ||||||
|  | 4c2ef8f4d14c checks: Introduce is_multiple_of() | ||||||
|  | e59ca36fb70e Make handling of cpp line information more tolerant | ||||||
|  | 0c3fd9b6aceb checks: Drop interrupt_cells_is_cell check | ||||||
|  | 6b3081abc4ac checks: Add check_is_cell() for all phandle+arg properties | ||||||
|  | 2dffc192a77f yamltree: Remove marker ordering dependency | ||||||
|  | 61e513439e40 pylibfdt: Rework "avoid unused variable warning" lines | ||||||
|  | c8bddd106095 tests: add a positive gpio test case | ||||||
|  | ad4abfadb687 checks: replace strstr and strrchr with strends | ||||||
|  | 09c6a6e88718 dtc.h: add strends for suffix matching | ||||||
|  | 9bb9b8d0b4a0 checks: tigthen up nr-gpios prop exception | ||||||
|  | b07b62ee3342 libfdt: Add FDT alignment check to fdt_check_header() | ||||||
|  | a2def5479950 libfdt: Check that the root-node name is empty | ||||||
|  | 4ca61f84dc21 libfdt: Check that there is only one root node | ||||||
|  | 34d708249a91 dtc: Remove -O dtbo support | ||||||
|  | 8e7ff260f755 libfdt: Fix a possible "unchecked return value" warning | ||||||
|  | 88875268c05c checks: Warn on node-name and property name being the same | ||||||
|  | 9d2279e7e6ee checks: Change node-name check to match devicetree spec | ||||||
|  | f527c867a8c6 util: limit gnu_printf format attribute to gcc >= 4.4.0 | ||||||
|  |  | ||||||
|  | Reviewed-by: Frank Rowand <frank.rowand@sony.com> | ||||||
|  | Tested-by: Frank Rowand <frank.rowand@sony.com> | ||||||
|  | Signed-off-by: Rob Herring <robh@kernel.org> | ||||||
|  | --- | ||||||
|  |  scripts/dtc/checks.c              | 222 ++++++++++++++++++++++-------- | ||||||
|  |  scripts/dtc/dtc-lexer.l           |   2 +- | ||||||
|  |  scripts/dtc/dtc.c                 |   6 +- | ||||||
|  |  scripts/dtc/dtc.h                 |  40 +++++- | ||||||
|  |  scripts/dtc/flattree.c            |  11 +- | ||||||
|  |  scripts/dtc/libfdt/fdt.c          |   4 + | ||||||
|  |  scripts/dtc/libfdt/fdt_rw.c       |  18 ++- | ||||||
|  |  scripts/dtc/libfdt/fdt_strerror.c |   1 + | ||||||
|  |  scripts/dtc/libfdt/libfdt.h       |   7 + | ||||||
|  |  scripts/dtc/livetree.c            |   6 +- | ||||||
|  |  scripts/dtc/treesource.c          |  48 +++---- | ||||||
|  |  scripts/dtc/util.h                |   6 +- | ||||||
|  |  scripts/dtc/version_gen.h         |   2 +- | ||||||
|  |  scripts/dtc/yamltree.c            |  16 ++- | ||||||
|  |  14 files changed, 275 insertions(+), 114 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/scripts/dtc/checks.c | ||||||
|  | +++ b/scripts/dtc/checks.c | ||||||
|  | @@ -143,6 +143,14 @@ static void check_nodes_props(struct che | ||||||
|  |  		check_nodes_props(c, dti, child); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static bool is_multiple_of(int multiple, int divisor) | ||||||
|  | +{ | ||||||
|  | +	if (divisor == 0) | ||||||
|  | +		return multiple == 0; | ||||||
|  | +	else | ||||||
|  | +		return (multiple % divisor) == 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static bool run_check(struct check *c, struct dt_info *dti) | ||||||
|  |  { | ||||||
|  |  	struct node *dt = dti->dt; | ||||||
|  | @@ -297,19 +305,20 @@ ERROR(duplicate_property_names, check_du | ||||||
|  |  #define LOWERCASE	"abcdefghijklmnopqrstuvwxyz" | ||||||
|  |  #define UPPERCASE	"ABCDEFGHIJKLMNOPQRSTUVWXYZ" | ||||||
|  |  #define DIGITS		"0123456789" | ||||||
|  | -#define PROPNODECHARS	LOWERCASE UPPERCASE DIGITS ",._+*#?-" | ||||||
|  | +#define NODECHARS	LOWERCASE UPPERCASE DIGITS ",._+-@" | ||||||
|  | +#define PROPCHARS	LOWERCASE UPPERCASE DIGITS ",._+*#?-" | ||||||
|  |  #define PROPNODECHARSSTRICT	LOWERCASE UPPERCASE DIGITS ",-" | ||||||
|  |   | ||||||
|  |  static void check_node_name_chars(struct check *c, struct dt_info *dti, | ||||||
|  |  				  struct node *node) | ||||||
|  |  { | ||||||
|  | -	int n = strspn(node->name, c->data); | ||||||
|  | +	size_t n = strspn(node->name, c->data); | ||||||
|  |   | ||||||
|  |  	if (n < strlen(node->name)) | ||||||
|  |  		FAIL(c, dti, node, "Bad character '%c' in node name", | ||||||
|  |  		     node->name[n]); | ||||||
|  |  } | ||||||
|  | -ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@"); | ||||||
|  | +ERROR(node_name_chars, check_node_name_chars, NODECHARS); | ||||||
|  |   | ||||||
|  |  static void check_node_name_chars_strict(struct check *c, struct dt_info *dti, | ||||||
|  |  					 struct node *node) | ||||||
|  | @@ -330,6 +339,20 @@ static void check_node_name_format(struc | ||||||
|  |  } | ||||||
|  |  ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars); | ||||||
|  |   | ||||||
|  | +static void check_node_name_vs_property_name(struct check *c, | ||||||
|  | +					     struct dt_info *dti, | ||||||
|  | +					     struct node *node) | ||||||
|  | +{ | ||||||
|  | +	if (!node->parent) | ||||||
|  | +		return; | ||||||
|  | + | ||||||
|  | +	if (get_property(node->parent, node->name)) { | ||||||
|  | +		FAIL(c, dti, node, "node name and property name conflict"); | ||||||
|  | +	} | ||||||
|  | +} | ||||||
|  | +WARNING(node_name_vs_property_name, check_node_name_vs_property_name, | ||||||
|  | +	NULL, &node_name_chars); | ||||||
|  | + | ||||||
|  |  static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti, | ||||||
|  |  				      struct node *node) | ||||||
|  |  { | ||||||
|  | @@ -363,14 +386,14 @@ static void check_property_name_chars(st | ||||||
|  |  	struct property *prop; | ||||||
|  |   | ||||||
|  |  	for_each_property(node, prop) { | ||||||
|  | -		int n = strspn(prop->name, c->data); | ||||||
|  | +		size_t n = strspn(prop->name, c->data); | ||||||
|  |   | ||||||
|  |  		if (n < strlen(prop->name)) | ||||||
|  |  			FAIL_PROP(c, dti, node, prop, "Bad character '%c' in property name", | ||||||
|  |  				  prop->name[n]); | ||||||
|  |  	} | ||||||
|  |  } | ||||||
|  | -ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS); | ||||||
|  | +ERROR(property_name_chars, check_property_name_chars, PROPCHARS); | ||||||
|  |   | ||||||
|  |  static void check_property_name_chars_strict(struct check *c, | ||||||
|  |  					     struct dt_info *dti, | ||||||
|  | @@ -380,7 +403,7 @@ static void check_property_name_chars_st | ||||||
|  |   | ||||||
|  |  	for_each_property(node, prop) { | ||||||
|  |  		const char *name = prop->name; | ||||||
|  | -		int n = strspn(name, c->data); | ||||||
|  | +		size_t n = strspn(name, c->data); | ||||||
|  |   | ||||||
|  |  		if (n == strlen(prop->name)) | ||||||
|  |  			continue; | ||||||
|  | @@ -497,7 +520,7 @@ static cell_t check_phandle_prop(struct | ||||||
|  |   | ||||||
|  |  	phandle = propval_cell(prop); | ||||||
|  |   | ||||||
|  | -	if ((phandle == 0) || (phandle == -1)) { | ||||||
|  | +	if (!phandle_is_valid(phandle)) { | ||||||
|  |  		FAIL_PROP(c, dti, node, prop, "bad value (0x%x) in %s property", | ||||||
|  |  		     phandle, prop->name); | ||||||
|  |  		return 0; | ||||||
|  | @@ -556,7 +579,7 @@ static void check_name_properties(struct | ||||||
|  |  	if (!prop) | ||||||
|  |  		return; /* No name property, that's fine */ | ||||||
|  |   | ||||||
|  | -	if ((prop->val.len != node->basenamelen+1) | ||||||
|  | +	if ((prop->val.len != node->basenamelen + 1U) | ||||||
|  |  	    || (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) { | ||||||
|  |  		FAIL(c, dti, node, "\"name\" property is incorrect (\"%s\" instead" | ||||||
|  |  		     " of base node name)", prop->val.val); | ||||||
|  | @@ -657,7 +680,6 @@ ERROR(omit_unused_nodes, fixup_omit_unus | ||||||
|  |   */ | ||||||
|  |  WARNING_IF_NOT_CELL(address_cells_is_cell, "#address-cells"); | ||||||
|  |  WARNING_IF_NOT_CELL(size_cells_is_cell, "#size-cells"); | ||||||
|  | -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"); | ||||||
|  | @@ -672,8 +694,7 @@ static void check_names_is_string_list(s | ||||||
|  |  	struct property *prop; | ||||||
|  |   | ||||||
|  |  	for_each_property(node, prop) { | ||||||
|  | -		const char *s = strrchr(prop->name, '-'); | ||||||
|  | -		if (!s || !streq(s, "-names")) | ||||||
|  | +		if (!strends(prop->name, "-names")) | ||||||
|  |  			continue; | ||||||
|  |   | ||||||
|  |  		c->data = prop->name; | ||||||
|  | @@ -753,7 +774,7 @@ static void check_reg_format(struct chec | ||||||
|  |  	size_cells = node_size_cells(node->parent); | ||||||
|  |  	entrylen = (addr_cells + size_cells) * sizeof(cell_t); | ||||||
|  |   | ||||||
|  | -	if (!entrylen || (prop->val.len % entrylen) != 0) | ||||||
|  | +	if (!is_multiple_of(prop->val.len, entrylen)) | ||||||
|  |  		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); | ||||||
|  | @@ -794,7 +815,7 @@ static void check_ranges_format(struct c | ||||||
|  |  				  "#size-cells (%d) differs from %s (%d)", | ||||||
|  |  				  ranges, c_size_cells, node->parent->fullpath, | ||||||
|  |  				  p_size_cells); | ||||||
|  | -	} else if ((prop->val.len % entrylen) != 0) { | ||||||
|  | +	} else if (!is_multiple_of(prop->val.len, entrylen)) { | ||||||
|  |  		FAIL_PROP(c, dti, node, prop, "\"%s\" property has invalid length (%d bytes) " | ||||||
|  |  			  "(parent #address-cells == %d, child #address-cells == %d, " | ||||||
|  |  			  "#size-cells == %d)", ranges, prop->val.len, | ||||||
|  | @@ -871,7 +892,7 @@ static void check_pci_device_bus_num(str | ||||||
|  |  	} else { | ||||||
|  |  		cells = (cell_t *)prop->val.val; | ||||||
|  |  		min_bus = fdt32_to_cpu(cells[0]); | ||||||
|  | -		max_bus = fdt32_to_cpu(cells[0]); | ||||||
|  | +		max_bus = fdt32_to_cpu(cells[1]); | ||||||
|  |  	} | ||||||
|  |  	if ((bus_num < min_bus) || (bus_num > max_bus)) | ||||||
|  |  		FAIL_PROP(c, dti, node, prop, "PCI bus number %d out of range, expected (%d - %d)", | ||||||
|  | @@ -1367,9 +1388,9 @@ static void check_property_phandle_args( | ||||||
|  |  				          const struct provider *provider) | ||||||
|  |  { | ||||||
|  |  	struct node *root = dti->dt; | ||||||
|  | -	int cell, cellsize = 0; | ||||||
|  | +	unsigned int cell, cellsize = 0; | ||||||
|  |   | ||||||
|  | -	if (prop->val.len % sizeof(cell_t)) { | ||||||
|  | +	if (!is_multiple_of(prop->val.len, sizeof(cell_t))) { | ||||||
|  |  		FAIL_PROP(c, dti, node, prop, | ||||||
|  |  			  "property size (%d) is invalid, expected multiple of %zu", | ||||||
|  |  			  prop->val.len, sizeof(cell_t)); | ||||||
|  | @@ -1379,14 +1400,14 @@ static void check_property_phandle_args( | ||||||
|  |  	for (cell = 0; cell < prop->val.len / sizeof(cell_t); cell += cellsize + 1) { | ||||||
|  |  		struct node *provider_node; | ||||||
|  |  		struct property *cellprop; | ||||||
|  | -		int phandle; | ||||||
|  | +		cell_t phandle; | ||||||
|  |   | ||||||
|  |  		phandle = propval_cell_n(prop, cell); | ||||||
|  |  		/* | ||||||
|  |  		 * Some bindings use a cell value 0 or -1 to skip over optional | ||||||
|  |  		 * entries when each index position has a specific definition. | ||||||
|  |  		 */ | ||||||
|  | -		if (phandle == 0 || phandle == -1) { | ||||||
|  | +		if (!phandle_is_valid(phandle)) { | ||||||
|  |  			/* Give up if this is an overlay with external references */ | ||||||
|  |  			if (dti->dtsflags & DTSF_PLUGIN) | ||||||
|  |  				break; | ||||||
|  | @@ -1452,7 +1473,8 @@ static void check_provider_cells_propert | ||||||
|  |  } | ||||||
|  |  #define WARNING_PROPERTY_PHANDLE_CELLS(nm, propname, cells_name, ...) \ | ||||||
|  |  	static struct provider nm##_provider = { (propname), (cells_name), __VA_ARGS__ }; \ | ||||||
|  | -	WARNING(nm##_property, check_provider_cells_property, &nm##_provider, &phandle_references); | ||||||
|  | +	WARNING_IF_NOT_CELL(nm##_is_cell, cells_name); \ | ||||||
|  | +	WARNING(nm##_property, check_provider_cells_property, &nm##_provider, &nm##_is_cell, &phandle_references); | ||||||
|  |   | ||||||
|  |  WARNING_PROPERTY_PHANDLE_CELLS(clocks, "clocks", "#clock-cells"); | ||||||
|  |  WARNING_PROPERTY_PHANDLE_CELLS(cooling_device, "cooling-device", "#cooling-cells"); | ||||||
|  | @@ -1473,24 +1495,17 @@ WARNING_PROPERTY_PHANDLE_CELLS(thermal_s | ||||||
|  |   | ||||||
|  |  static bool prop_is_gpio(struct property *prop) | ||||||
|  |  { | ||||||
|  | -	char *str; | ||||||
|  | - | ||||||
|  |  	/* | ||||||
|  |  	 * *-gpios and *-gpio can appear in property names, | ||||||
|  |  	 * so skip over any false matches (only one known ATM) | ||||||
|  |  	 */ | ||||||
|  | -	if (strstr(prop->name, "nr-gpio")) | ||||||
|  | +	if (strends(prop->name, ",nr-gpios")) | ||||||
|  |  		return false; | ||||||
|  |   | ||||||
|  | -	str = strrchr(prop->name, '-'); | ||||||
|  | -	if (str) | ||||||
|  | -		str++; | ||||||
|  | -	else | ||||||
|  | -		str = prop->name; | ||||||
|  | -	if (!(streq(str, "gpios") || streq(str, "gpio"))) | ||||||
|  | -		return false; | ||||||
|  | - | ||||||
|  | -	return true; | ||||||
|  | +	return strends(prop->name, "-gpios") || | ||||||
|  | +		streq(prop->name, "gpios") || | ||||||
|  | +		strends(prop->name, "-gpio") || | ||||||
|  | +		streq(prop->name, "gpio"); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static void check_gpios_property(struct check *c, | ||||||
|  | @@ -1525,13 +1540,10 @@ static void check_deprecated_gpio_proper | ||||||
|  |  	struct property *prop; | ||||||
|  |   | ||||||
|  |  	for_each_property(node, prop) { | ||||||
|  | -		char *str; | ||||||
|  | - | ||||||
|  |  		if (!prop_is_gpio(prop)) | ||||||
|  |  			continue; | ||||||
|  |   | ||||||
|  | -		str = strstr(prop->name, "gpio"); | ||||||
|  | -		if (!streq(str, "gpio")) | ||||||
|  | +		if (!strends(prop->name, "gpio")) | ||||||
|  |  			continue; | ||||||
|  |   | ||||||
|  |  		FAIL_PROP(c, dti, node, prop, | ||||||
|  | @@ -1561,21 +1573,106 @@ static void check_interrupt_provider(str | ||||||
|  |  				     struct node *node) | ||||||
|  |  { | ||||||
|  |  	struct property *prop; | ||||||
|  | +	bool irq_provider = node_is_interrupt_provider(node); | ||||||
|  |   | ||||||
|  | -	if (!node_is_interrupt_provider(node)) | ||||||
|  | +	prop = get_property(node, "#interrupt-cells"); | ||||||
|  | +	if (irq_provider && !prop) { | ||||||
|  | +		FAIL(c, dti, node, | ||||||
|  | +		     "Missing '#interrupt-cells' in interrupt provider"); | ||||||
|  |  		return; | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  | -	prop = get_property(node, "#interrupt-cells"); | ||||||
|  | -	if (!prop) | ||||||
|  | +	if (!irq_provider && prop) { | ||||||
|  |  		FAIL(c, dti, node, | ||||||
|  | -		     "Missing #interrupt-cells in interrupt provider"); | ||||||
|  | +		     "'#interrupt-cells' found, but node is not an interrupt provider"); | ||||||
|  | +		return; | ||||||
|  | +	} | ||||||
|  | +} | ||||||
|  | +WARNING(interrupt_provider, check_interrupt_provider, NULL, &interrupts_extended_is_cell); | ||||||
|  |   | ||||||
|  | -	prop = get_property(node, "#address-cells"); | ||||||
|  | -	if (!prop) | ||||||
|  | +static void check_interrupt_map(struct check *c, | ||||||
|  | +				struct dt_info *dti, | ||||||
|  | +				struct node *node) | ||||||
|  | +{ | ||||||
|  | +	struct node *root = dti->dt; | ||||||
|  | +	struct property *prop, *irq_map_prop; | ||||||
|  | +	size_t cellsize, cell, map_cells; | ||||||
|  | + | ||||||
|  | +	irq_map_prop = get_property(node, "interrupt-map"); | ||||||
|  | +	if (!irq_map_prop) | ||||||
|  | +		return; | ||||||
|  | + | ||||||
|  | +	if (node->addr_cells < 0) { | ||||||
|  |  		FAIL(c, dti, node, | ||||||
|  | -		     "Missing #address-cells in interrupt provider"); | ||||||
|  | +		     "Missing '#address-cells' in interrupt-map provider"); | ||||||
|  | +		return; | ||||||
|  | +	} | ||||||
|  | +	cellsize = node_addr_cells(node); | ||||||
|  | +	cellsize += propval_cell(get_property(node, "#interrupt-cells")); | ||||||
|  | + | ||||||
|  | +	prop = get_property(node, "interrupt-map-mask"); | ||||||
|  | +	if (prop && (prop->val.len != (cellsize * sizeof(cell_t)))) | ||||||
|  | +		FAIL_PROP(c, dti, node, prop, | ||||||
|  | +			  "property size (%d) is invalid, expected %zu", | ||||||
|  | +			  prop->val.len, cellsize * sizeof(cell_t)); | ||||||
|  | + | ||||||
|  | +	if (!is_multiple_of(irq_map_prop->val.len, sizeof(cell_t))) { | ||||||
|  | +		FAIL_PROP(c, dti, node, irq_map_prop, | ||||||
|  | +			  "property size (%d) is invalid, expected multiple of %zu", | ||||||
|  | +			  irq_map_prop->val.len, sizeof(cell_t)); | ||||||
|  | +		return; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	map_cells = irq_map_prop->val.len / sizeof(cell_t); | ||||||
|  | +	for (cell = 0; cell < map_cells; ) { | ||||||
|  | +		struct node *provider_node; | ||||||
|  | +		struct property *cellprop; | ||||||
|  | +		int phandle; | ||||||
|  | +		size_t parent_cellsize; | ||||||
|  | + | ||||||
|  | +		if ((cell + cellsize) >= map_cells) { | ||||||
|  | +			FAIL_PROP(c, dti, node, irq_map_prop, | ||||||
|  | +				  "property size (%d) too small, expected > %zu", | ||||||
|  | +				  irq_map_prop->val.len, (cell + cellsize) * sizeof(cell_t)); | ||||||
|  | +			break; | ||||||
|  | +		} | ||||||
|  | +		cell += cellsize; | ||||||
|  | + | ||||||
|  | +		phandle = propval_cell_n(irq_map_prop, cell); | ||||||
|  | +		if (!phandle_is_valid(phandle)) { | ||||||
|  | +			/* Give up if this is an overlay with external references */ | ||||||
|  | +			if (!(dti->dtsflags & DTSF_PLUGIN)) | ||||||
|  | +				FAIL_PROP(c, dti, node, irq_map_prop, | ||||||
|  | +					  "Cell %zu is not a phandle(%d)", | ||||||
|  | +					  cell, phandle); | ||||||
|  | +			break; | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  | +		provider_node = get_node_by_phandle(root, phandle); | ||||||
|  | +		if (!provider_node) { | ||||||
|  | +			FAIL_PROP(c, dti, node, irq_map_prop, | ||||||
|  | +				  "Could not get phandle(%d) node for (cell %zu)", | ||||||
|  | +				  phandle, cell); | ||||||
|  | +			break; | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  | +		cellprop = get_property(provider_node, "#interrupt-cells"); | ||||||
|  | +		if (cellprop) { | ||||||
|  | +			parent_cellsize = propval_cell(cellprop); | ||||||
|  | +		} else { | ||||||
|  | +			FAIL(c, dti, node, "Missing property '#interrupt-cells' in node %s or bad phandle (referred from interrupt-map[%zu])", | ||||||
|  | +			     provider_node->fullpath, cell); | ||||||
|  | +			break; | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  | +		cellprop = get_property(provider_node, "#address-cells"); | ||||||
|  | +		if (cellprop) | ||||||
|  | +			parent_cellsize += propval_cell(cellprop); | ||||||
|  | + | ||||||
|  | +		cell += 1 + parent_cellsize; | ||||||
|  | +	} | ||||||
|  |  } | ||||||
|  | -WARNING(interrupt_provider, check_interrupt_provider, NULL); | ||||||
|  | +WARNING(interrupt_map, check_interrupt_map, NULL, &phandle_references, &addr_size_cells, &interrupt_provider); | ||||||
|  |   | ||||||
|  |  static void check_interrupts_property(struct check *c, | ||||||
|  |  				      struct dt_info *dti, | ||||||
|  | @@ -1584,13 +1681,13 @@ static void check_interrupts_property(st | ||||||
|  |  	struct node *root = dti->dt; | ||||||
|  |  	struct node *irq_node = NULL, *parent = node; | ||||||
|  |  	struct property *irq_prop, *prop = NULL; | ||||||
|  | -	int irq_cells, phandle; | ||||||
|  | +	cell_t irq_cells, phandle; | ||||||
|  |   | ||||||
|  |  	irq_prop = get_property(node, "interrupts"); | ||||||
|  |  	if (!irq_prop) | ||||||
|  |  		return; | ||||||
|  |   | ||||||
|  | -	if (irq_prop->val.len % sizeof(cell_t)) | ||||||
|  | +	if (!is_multiple_of(irq_prop->val.len, sizeof(cell_t))) | ||||||
|  |  		FAIL_PROP(c, dti, node, irq_prop, "size (%d) is invalid, expected multiple of %zu", | ||||||
|  |  		     irq_prop->val.len, sizeof(cell_t)); | ||||||
|  |   | ||||||
|  | @@ -1603,7 +1700,7 @@ static void check_interrupts_property(st | ||||||
|  |  		prop = get_property(parent, "interrupt-parent"); | ||||||
|  |  		if (prop) { | ||||||
|  |  			phandle = propval_cell(prop); | ||||||
|  | -			if ((phandle == 0) || (phandle == -1)) { | ||||||
|  | +			if (!phandle_is_valid(phandle)) { | ||||||
|  |  				/* Give up if this is an overlay with | ||||||
|  |  				 * external references */ | ||||||
|  |  				if (dti->dtsflags & DTSF_PLUGIN) | ||||||
|  | @@ -1639,7 +1736,7 @@ static void check_interrupts_property(st | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	irq_cells = propval_cell(prop); | ||||||
|  | -	if (irq_prop->val.len % (irq_cells * sizeof(cell_t))) { | ||||||
|  | +	if (!is_multiple_of(irq_prop->val.len, irq_cells * sizeof(cell_t))) { | ||||||
|  |  		FAIL_PROP(c, dti, node, prop, | ||||||
|  |  			  "size is (%d), expected multiple of %d", | ||||||
|  |  			  irq_prop->val.len, (int)(irq_cells * sizeof(cell_t))); | ||||||
|  | @@ -1750,7 +1847,7 @@ WARNING(graph_port, check_graph_port, NU | ||||||
|  |  static struct node *get_remote_endpoint(struct check *c, struct dt_info *dti, | ||||||
|  |  					struct node *endpoint) | ||||||
|  |  { | ||||||
|  | -	int phandle; | ||||||
|  | +	cell_t phandle; | ||||||
|  |  	struct node *node; | ||||||
|  |  	struct property *prop; | ||||||
|  |   | ||||||
|  | @@ -1760,7 +1857,7 @@ static struct node *get_remote_endpoint( | ||||||
|  |   | ||||||
|  |  	phandle = propval_cell(prop); | ||||||
|  |  	/* Give up if this is an overlay with external references */ | ||||||
|  | -	if (phandle == 0 || phandle == -1) | ||||||
|  | +	if (!phandle_is_valid(phandle)) | ||||||
|  |  		return NULL; | ||||||
|  |   | ||||||
|  |  	node = get_node_by_phandle(dti->dt, phandle); | ||||||
|  | @@ -1796,7 +1893,7 @@ WARNING(graph_endpoint, check_graph_endp | ||||||
|  |  static struct check *check_table[] = { | ||||||
|  |  	&duplicate_node_names, &duplicate_property_names, | ||||||
|  |  	&node_name_chars, &node_name_format, &property_name_chars, | ||||||
|  | -	&name_is_string, &name_properties, | ||||||
|  | +	&name_is_string, &name_properties, &node_name_vs_property_name, | ||||||
|  |   | ||||||
|  |  	&duplicate_label, | ||||||
|  |   | ||||||
|  | @@ -1804,7 +1901,7 @@ static struct check *check_table[] = { | ||||||
|  |  	&phandle_references, &path_references, | ||||||
|  |  	&omit_unused_nodes, | ||||||
|  |   | ||||||
|  | -	&address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell, | ||||||
|  | +	&address_cells_is_cell, &size_cells_is_cell, | ||||||
|  |  	&device_type_is_string, &model_is_string, &status_is_string, | ||||||
|  |  	&label_is_string, | ||||||
|  |   | ||||||
|  | @@ -1839,26 +1936,43 @@ static struct check *check_table[] = { | ||||||
|  |  	&chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path, | ||||||
|  |   | ||||||
|  |  	&clocks_property, | ||||||
|  | +	&clocks_is_cell, | ||||||
|  |  	&cooling_device_property, | ||||||
|  | +	&cooling_device_is_cell, | ||||||
|  |  	&dmas_property, | ||||||
|  | +	&dmas_is_cell, | ||||||
|  |  	&hwlocks_property, | ||||||
|  | +	&hwlocks_is_cell, | ||||||
|  |  	&interrupts_extended_property, | ||||||
|  | +	&interrupts_extended_is_cell, | ||||||
|  |  	&io_channels_property, | ||||||
|  | +	&io_channels_is_cell, | ||||||
|  |  	&iommus_property, | ||||||
|  | +	&iommus_is_cell, | ||||||
|  |  	&mboxes_property, | ||||||
|  | +	&mboxes_is_cell, | ||||||
|  |  	&msi_parent_property, | ||||||
|  | +	&msi_parent_is_cell, | ||||||
|  |  	&mux_controls_property, | ||||||
|  | +	&mux_controls_is_cell, | ||||||
|  |  	&phys_property, | ||||||
|  | +	&phys_is_cell, | ||||||
|  |  	&power_domains_property, | ||||||
|  | +	&power_domains_is_cell, | ||||||
|  |  	&pwms_property, | ||||||
|  | +	&pwms_is_cell, | ||||||
|  |  	&resets_property, | ||||||
|  | +	&resets_is_cell, | ||||||
|  |  	&sound_dai_property, | ||||||
|  | +	&sound_dai_is_cell, | ||||||
|  |  	&thermal_sensors_property, | ||||||
|  | +	&thermal_sensors_is_cell, | ||||||
|  |   | ||||||
|  |  	&deprecated_gpio_property, | ||||||
|  |  	&gpios_property, | ||||||
|  |  	&interrupts_property, | ||||||
|  |  	&interrupt_provider, | ||||||
|  | +	&interrupt_map, | ||||||
|  |   | ||||||
|  |  	&alias_paths, | ||||||
|  |   | ||||||
|  | @@ -1882,7 +1996,7 @@ static void enable_warning_error(struct | ||||||
|  |   | ||||||
|  |  static void disable_warning_error(struct check *c, bool warn, bool error) | ||||||
|  |  { | ||||||
|  | -	int i; | ||||||
|  | +	unsigned int i; | ||||||
|  |   | ||||||
|  |  	/* Lowering level, also lower it for things this is the prereq | ||||||
|  |  	 * for */ | ||||||
|  | @@ -1903,7 +2017,7 @@ static void disable_warning_error(struct | ||||||
|  |   | ||||||
|  |  void parse_checks_option(bool warn, bool error, const char *arg) | ||||||
|  |  { | ||||||
|  | -	int i; | ||||||
|  | +	unsigned int i; | ||||||
|  |  	const char *name = arg; | ||||||
|  |  	bool enable = true; | ||||||
|  |   | ||||||
|  | @@ -1930,7 +2044,7 @@ void parse_checks_option(bool warn, bool | ||||||
|  |   | ||||||
|  |  void process_checks(bool force, struct dt_info *dti) | ||||||
|  |  { | ||||||
|  | -	int i; | ||||||
|  | +	unsigned int i; | ||||||
|  |  	int error = 0; | ||||||
|  |   | ||||||
|  |  	for (i = 0; i < ARRAY_SIZE(check_table); i++) { | ||||||
|  | --- a/scripts/dtc/dtc-lexer.l | ||||||
|  | +++ b/scripts/dtc/dtc-lexer.l | ||||||
|  | @@ -57,7 +57,7 @@ static void PRINTF(1, 2) lexical_error(c | ||||||
|  |  			push_input_file(name); | ||||||
|  |  		} | ||||||
|  |   | ||||||
|  | -<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? { | ||||||
|  | +<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)* { | ||||||
|  |  			char *line, *fnstart, *fnend; | ||||||
|  |  			struct data fn; | ||||||
|  |  			/* skip text before line # */ | ||||||
|  | --- a/scripts/dtc/dtc.c | ||||||
|  | +++ b/scripts/dtc/dtc.c | ||||||
|  | @@ -12,7 +12,7 @@ | ||||||
|  |   * Command line options | ||||||
|  |   */ | ||||||
|  |  int quiet;		/* Level of quietness */ | ||||||
|  | -int reservenum;		/* Number of memory reservation slots */ | ||||||
|  | +unsigned int reservenum;/* Number of memory reservation slots */ | ||||||
|  |  int minsize;		/* Minimum blob size */ | ||||||
|  |  int padsize;		/* Additional padding to blob */ | ||||||
|  |  int alignsize;		/* Additional padding to blob accroding to the alignsize */ | ||||||
|  | @@ -197,7 +197,7 @@ int main(int argc, char *argv[]) | ||||||
|  |  			depname = optarg; | ||||||
|  |  			break; | ||||||
|  |  		case 'R': | ||||||
|  | -			reservenum = strtol(optarg, NULL, 0); | ||||||
|  | +			reservenum = strtoul(optarg, NULL, 0); | ||||||
|  |  			break; | ||||||
|  |  		case 'S': | ||||||
|  |  			minsize = strtol(optarg, NULL, 0); | ||||||
|  | @@ -359,8 +359,6 @@ int main(int argc, char *argv[]) | ||||||
|  |  #endif | ||||||
|  |  	} else if (streq(outform, "dtb")) { | ||||||
|  |  		dt_to_blob(outf, dti, outversion); | ||||||
|  | -	} else if (streq(outform, "dtbo")) { | ||||||
|  | -		dt_to_blob(outf, dti, outversion); | ||||||
|  |  	} else if (streq(outform, "asm")) { | ||||||
|  |  		dt_to_asm(outf, dti, outversion); | ||||||
|  |  	} else if (streq(outform, "null")) { | ||||||
|  | --- a/scripts/dtc/dtc.h | ||||||
|  | +++ b/scripts/dtc/dtc.h | ||||||
|  | @@ -35,7 +35,7 @@ | ||||||
|  |   * Command line options | ||||||
|  |   */ | ||||||
|  |  extern int quiet;		/* Level of quietness */ | ||||||
|  | -extern int reservenum;		/* Number of memory reservation slots */ | ||||||
|  | +extern unsigned int reservenum;	/* Number of memory reservation slots */ | ||||||
|  |  extern int minsize;		/* Minimum blob size */ | ||||||
|  |  extern int padsize;		/* Additional padding to blob */ | ||||||
|  |  extern int alignsize;		/* Additional padding to blob accroding to the alignsize */ | ||||||
|  | @@ -51,6 +51,11 @@ extern int annotate;		/* annotate .dts w | ||||||
|  |   | ||||||
|  |  typedef uint32_t cell_t; | ||||||
|  |   | ||||||
|  | +static inline bool phandle_is_valid(cell_t phandle) | ||||||
|  | +{ | ||||||
|  | +	return phandle != 0 && phandle != ~0U; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static inline uint16_t dtb_ld16(const void *p) | ||||||
|  |  { | ||||||
|  |  	const uint8_t *bp = (const uint8_t *)p; | ||||||
|  | @@ -86,6 +91,16 @@ static inline uint64_t dtb_ld64(const vo | ||||||
|  |  #define streq(a, b)	(strcmp((a), (b)) == 0) | ||||||
|  |  #define strstarts(s, prefix)	(strncmp((s), (prefix), strlen(prefix)) == 0) | ||||||
|  |  #define strprefixeq(a, n, b)	(strlen(b) == (n) && (memcmp(a, b, n) == 0)) | ||||||
|  | +static inline bool strends(const char *str, const char *suffix) | ||||||
|  | +{ | ||||||
|  | +	unsigned int len, suffix_len; | ||||||
|  | + | ||||||
|  | +	len = strlen(str); | ||||||
|  | +	suffix_len = strlen(suffix); | ||||||
|  | +	if (len < suffix_len) | ||||||
|  | +		return false; | ||||||
|  | +	return streq(str + len - suffix_len, suffix); | ||||||
|  | +} | ||||||
|  |   | ||||||
|  |  #define ALIGN(x, a)	(((x) + (a) - 1) & ~((a) - 1)) | ||||||
|  |   | ||||||
|  | @@ -101,6 +116,12 @@ enum markertype { | ||||||
|  |  	TYPE_UINT64, | ||||||
|  |  	TYPE_STRING, | ||||||
|  |  }; | ||||||
|  | + | ||||||
|  | +static inline bool is_type_marker(enum markertype type) | ||||||
|  | +{ | ||||||
|  | +	return type >= TYPE_UINT8; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  extern const char *markername(enum markertype markertype); | ||||||
|  |   | ||||||
|  |  struct  marker { | ||||||
|  | @@ -125,7 +146,22 @@ struct data { | ||||||
|  |  	for_each_marker(m) \ | ||||||
|  |  		if ((m)->type == (t)) | ||||||
|  |   | ||||||
|  | -size_t type_marker_length(struct marker *m); | ||||||
|  | +static inline struct marker *next_type_marker(struct marker *m) | ||||||
|  | +{ | ||||||
|  | +	for_each_marker(m) | ||||||
|  | +		if (is_type_marker(m->type)) | ||||||
|  | +			break; | ||||||
|  | +	return m; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static inline size_t type_marker_length(struct marker *m) | ||||||
|  | +{ | ||||||
|  | +	struct marker *next = next_type_marker(m->next); | ||||||
|  | + | ||||||
|  | +	if (next) | ||||||
|  | +		return next->offset - m->offset; | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  |   | ||||||
|  |  void data_free(struct data d); | ||||||
|  |   | ||||||
|  | --- a/scripts/dtc/flattree.c | ||||||
|  | +++ b/scripts/dtc/flattree.c | ||||||
|  | @@ -124,7 +124,8 @@ static void asm_emit_cell(void *e, cell_ | ||||||
|  |  { | ||||||
|  |  	FILE *f = e; | ||||||
|  |   | ||||||
|  | -	fprintf(f, "\t.byte 0x%02x; .byte 0x%02x; .byte 0x%02x; .byte 0x%02x\n", | ||||||
|  | +	fprintf(f, "\t.byte\t0x%02x\n" "\t.byte\t0x%02x\n" | ||||||
|  | +		"\t.byte\t0x%02x\n" "\t.byte\t0x%02x\n", | ||||||
|  |  		(val >> 24) & 0xff, (val >> 16) & 0xff, | ||||||
|  |  		(val >> 8) & 0xff, val & 0xff); | ||||||
|  |  } | ||||||
|  | @@ -134,9 +135,9 @@ static void asm_emit_string(void *e, con | ||||||
|  |  	FILE *f = e; | ||||||
|  |   | ||||||
|  |  	if (len != 0) | ||||||
|  | -		fprintf(f, "\t.string\t\"%.*s\"\n", len, str); | ||||||
|  | +		fprintf(f, "\t.asciz\t\"%.*s\"\n", len, str); | ||||||
|  |  	else | ||||||
|  | -		fprintf(f, "\t.string\t\"%s\"\n", str); | ||||||
|  | +		fprintf(f, "\t.asciz\t\"%s\"\n", str); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static void asm_emit_align(void *e, int a) | ||||||
|  | @@ -295,7 +296,7 @@ static struct data flatten_reserve_list( | ||||||
|  |  { | ||||||
|  |  	struct reserve_info *re; | ||||||
|  |  	struct data d = empty_data; | ||||||
|  | -	int    j; | ||||||
|  | +	unsigned int j; | ||||||
|  |   | ||||||
|  |  	for (re = reservelist; re; re = re->next) { | ||||||
|  |  		d = data_append_re(d, re->address, re->size); | ||||||
|  | @@ -438,7 +439,7 @@ static void dump_stringtable_asm(FILE *f | ||||||
|  |   | ||||||
|  |  	while (p < (strbuf.val + strbuf.len)) { | ||||||
|  |  		len = strlen(p); | ||||||
|  | -		fprintf(f, "\t.string \"%s\"\n", p); | ||||||
|  | +		fprintf(f, "\t.asciz \"%s\"\n", p); | ||||||
|  |  		p += len+1; | ||||||
|  |  	} | ||||||
|  |  } | ||||||
|  | --- a/scripts/dtc/libfdt/fdt.c | ||||||
|  | +++ b/scripts/dtc/libfdt/fdt.c | ||||||
|  | @@ -90,6 +90,10 @@ int fdt_check_header(const void *fdt) | ||||||
|  |  { | ||||||
|  |  	size_t hdrsize; | ||||||
|  |   | ||||||
|  | +	/* The device tree must be at an 8-byte aligned address */ | ||||||
|  | +	if ((uintptr_t)fdt & 7) | ||||||
|  | +		return -FDT_ERR_ALIGNMENT; | ||||||
|  | + | ||||||
|  |  	if (fdt_magic(fdt) != FDT_MAGIC) | ||||||
|  |  		return -FDT_ERR_BADMAGIC; | ||||||
|  |  	if (!can_assume(LATEST)) { | ||||||
|  | --- a/scripts/dtc/libfdt/fdt_rw.c | ||||||
|  | +++ b/scripts/dtc/libfdt/fdt_rw.c | ||||||
|  | @@ -349,7 +349,10 @@ int fdt_add_subnode_namelen(void *fdt, i | ||||||
|  |  		return offset; | ||||||
|  |   | ||||||
|  |  	/* Try to place the new node after the parent's properties */ | ||||||
|  | -	fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */ | ||||||
|  | +	tag = fdt_next_tag(fdt, parentoffset, &nextoffset); | ||||||
|  | +	/* the fdt_subnode_offset_namelen() should ensure this never hits */ | ||||||
|  | +	if (!can_assume(LIBFDT_FLAWLESS) && (tag != FDT_BEGIN_NODE)) | ||||||
|  | +		return -FDT_ERR_INTERNAL; | ||||||
|  |  	do { | ||||||
|  |  		offset = nextoffset; | ||||||
|  |  		tag = fdt_next_tag(fdt, offset, &nextoffset); | ||||||
|  | @@ -391,7 +394,9 @@ int fdt_del_node(void *fdt, int nodeoffs | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static void fdt_packblocks_(const char *old, char *new, | ||||||
|  | -			    int mem_rsv_size, int struct_size) | ||||||
|  | +			    int mem_rsv_size, | ||||||
|  | +			    int struct_size, | ||||||
|  | +			    int strings_size) | ||||||
|  |  { | ||||||
|  |  	int mem_rsv_off, struct_off, strings_off; | ||||||
|  |   | ||||||
|  | @@ -406,8 +411,7 @@ static void fdt_packblocks_(const char * | ||||||
|  |  	fdt_set_off_dt_struct(new, struct_off); | ||||||
|  |  	fdt_set_size_dt_struct(new, struct_size); | ||||||
|  |   | ||||||
|  | -	memmove(new + strings_off, old + fdt_off_dt_strings(old), | ||||||
|  | -		fdt_size_dt_strings(old)); | ||||||
|  | +	memmove(new + strings_off, old + fdt_off_dt_strings(old), strings_size); | ||||||
|  |  	fdt_set_off_dt_strings(new, strings_off); | ||||||
|  |  	fdt_set_size_dt_strings(new, fdt_size_dt_strings(old)); | ||||||
|  |  } | ||||||
|  | @@ -467,7 +471,8 @@ int fdt_open_into(const void *fdt, void | ||||||
|  |  			return -FDT_ERR_NOSPACE; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size); | ||||||
|  | +	fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size, | ||||||
|  | +			fdt_size_dt_strings(fdt)); | ||||||
|  |  	memmove(buf, tmp, newsize); | ||||||
|  |   | ||||||
|  |  	fdt_set_magic(buf, FDT_MAGIC); | ||||||
|  | @@ -487,7 +492,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_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt), | ||||||
|  | +			fdt_size_dt_strings(fdt)); | ||||||
|  |  	fdt_set_totalsize(fdt, fdt_data_size_(fdt)); | ||||||
|  |   | ||||||
|  |  	return 0; | ||||||
|  | --- a/scripts/dtc/libfdt/fdt_strerror.c | ||||||
|  | +++ b/scripts/dtc/libfdt/fdt_strerror.c | ||||||
|  | @@ -39,6 +39,7 @@ static struct fdt_errtabent fdt_errtable | ||||||
|  |  	FDT_ERRTABENT(FDT_ERR_BADOVERLAY), | ||||||
|  |  	FDT_ERRTABENT(FDT_ERR_NOPHANDLES), | ||||||
|  |  	FDT_ERRTABENT(FDT_ERR_BADFLAGS), | ||||||
|  | +	FDT_ERRTABENT(FDT_ERR_ALIGNMENT), | ||||||
|  |  }; | ||||||
|  |  #define FDT_ERRTABSIZE	((int)(sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))) | ||||||
|  |   | ||||||
|  | --- a/scripts/dtc/libfdt/libfdt.h | ||||||
|  | +++ b/scripts/dtc/libfdt/libfdt.h | ||||||
|  | @@ -131,6 +131,13 @@ uint32_t fdt_next_tag(const void *fdt, i | ||||||
|  |   * to work even with unaligned pointers on platforms (such as ARMv5) that don't | ||||||
|  |   * like unaligned loads and stores. | ||||||
|  |   */ | ||||||
|  | +static inline uint16_t fdt16_ld(const fdt16_t *p) | ||||||
|  | +{ | ||||||
|  | +	const uint8_t *bp = (const uint8_t *)p; | ||||||
|  | + | ||||||
|  | +	return ((uint16_t)bp[0] << 8) | bp[1]; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static inline uint32_t fdt32_ld(const fdt32_t *p) | ||||||
|  |  { | ||||||
|  |  	const uint8_t *bp = (const uint8_t *)p; | ||||||
|  | --- a/scripts/dtc/livetree.c | ||||||
|  | +++ b/scripts/dtc/livetree.c | ||||||
|  | @@ -526,7 +526,7 @@ struct node *get_node_by_path(struct nod | ||||||
|  |  	p = strchr(path, '/'); | ||||||
|  |   | ||||||
|  |  	for_each_child(tree, child) { | ||||||
|  | -		if (p && strprefixeq(path, p - path, child->name)) | ||||||
|  | +		if (p && strprefixeq(path, (size_t)(p - path), child->name)) | ||||||
|  |  			return get_node_by_path(child, p+1); | ||||||
|  |  		else if (!p && streq(path, child->name)) | ||||||
|  |  			return child; | ||||||
|  | @@ -559,7 +559,7 @@ struct node *get_node_by_phandle(struct | ||||||
|  |  { | ||||||
|  |  	struct node *child, *node; | ||||||
|  |   | ||||||
|  | -	if ((phandle == 0) || (phandle == -1)) { | ||||||
|  | +	if (!phandle_is_valid(phandle)) { | ||||||
|  |  		assert(generate_fixups); | ||||||
|  |  		return NULL; | ||||||
|  |  	} | ||||||
|  | @@ -594,7 +594,7 @@ cell_t get_node_phandle(struct node *roo | ||||||
|  |  	static cell_t phandle = 1; /* FIXME: ick, static local */ | ||||||
|  |  	struct data d = empty_data; | ||||||
|  |   | ||||||
|  | -	if ((node->phandle != 0) && (node->phandle != -1)) | ||||||
|  | +	if (phandle_is_valid(node->phandle)) | ||||||
|  |  		return node->phandle; | ||||||
|  |   | ||||||
|  |  	while (get_node_by_phandle(root, phandle)) | ||||||
|  | --- a/scripts/dtc/treesource.c | ||||||
|  | +++ b/scripts/dtc/treesource.c | ||||||
|  | @@ -124,27 +124,6 @@ static void write_propval_int(FILE *f, c | ||||||
|  |  	} | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static bool has_data_type_information(struct marker *m) | ||||||
|  | -{ | ||||||
|  | -	return m->type >= TYPE_UINT8; | ||||||
|  | -} | ||||||
|  | - | ||||||
|  | -static struct marker *next_type_marker(struct marker *m) | ||||||
|  | -{ | ||||||
|  | -	while (m && !has_data_type_information(m)) | ||||||
|  | -		m = m->next; | ||||||
|  | -	return m; | ||||||
|  | -} | ||||||
|  | - | ||||||
|  | -size_t type_marker_length(struct marker *m) | ||||||
|  | -{ | ||||||
|  | -	struct marker *next = next_type_marker(m->next); | ||||||
|  | - | ||||||
|  | -	if (next) | ||||||
|  | -		return next->offset - m->offset; | ||||||
|  | -	return 0; | ||||||
|  | -} | ||||||
|  | - | ||||||
|  |  static const char *delim_start[] = { | ||||||
|  |  	[TYPE_UINT8] = "[", | ||||||
|  |  	[TYPE_UINT16] = "/bits/ 16 <", | ||||||
|  | @@ -229,26 +208,39 @@ static void write_propval(FILE *f, struc | ||||||
|  |  		size_t chunk_len = (m->next ? m->next->offset : len) - m->offset; | ||||||
|  |  		size_t data_len = type_marker_length(m) ? : len - m->offset; | ||||||
|  |  		const char *p = &prop->val.val[m->offset]; | ||||||
|  | +		struct marker *m_phandle; | ||||||
|  |   | ||||||
|  | -		if (has_data_type_information(m)) { | ||||||
|  | +		if (is_type_marker(m->type)) { | ||||||
|  |  			emit_type = m->type; | ||||||
|  |  			fprintf(f, " %s", delim_start[emit_type]); | ||||||
|  |  		} else if (m->type == LABEL) | ||||||
|  |  			fprintf(f, " %s:", m->ref); | ||||||
|  | -		else if (m->offset) | ||||||
|  | -			fputc(' ', f); | ||||||
|  |   | ||||||
|  | -		if (emit_type == TYPE_NONE) { | ||||||
|  | -			assert(chunk_len == 0); | ||||||
|  | +		if (emit_type == TYPE_NONE || chunk_len == 0) | ||||||
|  |  			continue; | ||||||
|  | -		} | ||||||
|  |   | ||||||
|  |  		switch(emit_type) { | ||||||
|  |  		case TYPE_UINT16: | ||||||
|  |  			write_propval_int(f, p, chunk_len, 2); | ||||||
|  |  			break; | ||||||
|  |  		case TYPE_UINT32: | ||||||
|  | -			write_propval_int(f, p, chunk_len, 4); | ||||||
|  | +			m_phandle = prop->val.markers; | ||||||
|  | +			for_each_marker_of_type(m_phandle, REF_PHANDLE) | ||||||
|  | +				if (m->offset == m_phandle->offset) | ||||||
|  | +					break; | ||||||
|  | + | ||||||
|  | +			if (m_phandle) { | ||||||
|  | +				if (m_phandle->ref[0] == '/') | ||||||
|  | +					fprintf(f, "&{%s}", m_phandle->ref); | ||||||
|  | +				else | ||||||
|  | +					fprintf(f, "&%s", m_phandle->ref); | ||||||
|  | +				if (chunk_len > 4) { | ||||||
|  | +					fputc(' ', f); | ||||||
|  | +					write_propval_int(f, p + 4, chunk_len - 4, 4); | ||||||
|  | +				} | ||||||
|  | +			} else { | ||||||
|  | +				write_propval_int(f, p, chunk_len, 4); | ||||||
|  | +			} | ||||||
|  |  			break; | ||||||
|  |  		case TYPE_UINT64: | ||||||
|  |  			write_propval_int(f, p, chunk_len, 8); | ||||||
|  | --- a/scripts/dtc/util.h | ||||||
|  | +++ b/scripts/dtc/util.h | ||||||
|  | @@ -13,10 +13,10 @@ | ||||||
|  |   */ | ||||||
|  |   | ||||||
|  |  #ifdef __GNUC__ | ||||||
|  | -#ifdef __clang__ | ||||||
|  | -#define PRINTF(i, j)	__attribute__((format (printf, i, j))) | ||||||
|  | -#else | ||||||
|  | +#if __GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) | ||||||
|  |  #define PRINTF(i, j)	__attribute__((format (gnu_printf, i, j))) | ||||||
|  | +#else | ||||||
|  | +#define PRINTF(i, j)	__attribute__((format (printf, i, j))) | ||||||
|  |  #endif | ||||||
|  |  #define NORETURN	__attribute__((noreturn)) | ||||||
|  |  #else | ||||||
|  | --- a/scripts/dtc/version_gen.h | ||||||
|  | +++ b/scripts/dtc/version_gen.h | ||||||
|  | @@ -1 +1 @@ | ||||||
|  | -#define DTC_VERSION "DTC 1.6.0-g183df9e9" | ||||||
|  | +#define DTC_VERSION "DTC 1.6.1-g0a3a9d34" | ||||||
|  | --- a/scripts/dtc/yamltree.c | ||||||
|  | +++ b/scripts/dtc/yamltree.c | ||||||
|  | @@ -29,11 +29,12 @@ char *yaml_error_name[] = { | ||||||
|  |  		    (emitter)->problem, __func__, __LINE__);		\ | ||||||
|  |  }) | ||||||
|  |   | ||||||
|  | -static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, char *data, unsigned int len, int width) | ||||||
|  | +static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, | ||||||
|  | +	char *data, unsigned int seq_offset, unsigned int len, int width) | ||||||
|  |  { | ||||||
|  |  	yaml_event_t event; | ||||||
|  |  	void *tag; | ||||||
|  | -	unsigned int off, start_offset = markers->offset; | ||||||
|  | +	unsigned int off; | ||||||
|  |   | ||||||
|  |  	switch(width) { | ||||||
|  |  		case 1: tag = "!u8"; break; | ||||||
|  | @@ -66,7 +67,7 @@ static void yaml_propval_int(yaml_emitte | ||||||
|  |  			m = markers; | ||||||
|  |  			is_phandle = false; | ||||||
|  |  			for_each_marker_of_type(m, REF_PHANDLE) { | ||||||
|  | -				if (m->offset == (start_offset + off)) { | ||||||
|  | +				if (m->offset == (seq_offset + off)) { | ||||||
|  |  					is_phandle = true; | ||||||
|  |  					break; | ||||||
|  |  				} | ||||||
|  | @@ -114,6 +115,7 @@ static void yaml_propval(yaml_emitter_t | ||||||
|  |  	yaml_event_t event; | ||||||
|  |  	unsigned int len = prop->val.len; | ||||||
|  |  	struct marker *m = prop->val.markers; | ||||||
|  | +	struct marker *markers = prop->val.markers; | ||||||
|  |   | ||||||
|  |  	/* Emit the property name */ | ||||||
|  |  	yaml_scalar_event_initialize(&event, NULL, | ||||||
|  | @@ -151,19 +153,19 @@ static void yaml_propval(yaml_emitter_t | ||||||
|  |   | ||||||
|  |  		switch(m->type) { | ||||||
|  |  		case TYPE_UINT16: | ||||||
|  | -			yaml_propval_int(emitter, m, data, chunk_len, 2); | ||||||
|  | +			yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 2); | ||||||
|  |  			break; | ||||||
|  |  		case TYPE_UINT32: | ||||||
|  | -			yaml_propval_int(emitter, m, data, chunk_len, 4); | ||||||
|  | +			yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 4); | ||||||
|  |  			break; | ||||||
|  |  		case TYPE_UINT64: | ||||||
|  | -			yaml_propval_int(emitter, m, data, chunk_len, 8); | ||||||
|  | +			yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 8); | ||||||
|  |  			break; | ||||||
|  |  		case TYPE_STRING: | ||||||
|  |  			yaml_propval_string(emitter, data, chunk_len); | ||||||
|  |  			break; | ||||||
|  |  		default: | ||||||
|  | -			yaml_propval_int(emitter, m, data, chunk_len, 1); | ||||||
|  | +			yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 1); | ||||||
|  |  			break; | ||||||
|  |  		} | ||||||
|  |  	} | ||||||
| @@ -1,28 +0,0 @@ | |||||||
| From d8d1a9a77863a8c7031ae82a1d461aa78eb72a7b Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Rob Herring <robh@kernel.org> |  | ||||||
| Date: Mon, 11 Oct 2021 14:12:43 -0500 |  | ||||||
| Subject: [PATCH] checks: Drop interrupt provider '#address-cells' check |  | ||||||
|  |  | ||||||
| '#address-cells' is only needed when parsing 'interrupt-map' properties, so |  | ||||||
| remove it from the common interrupt-provider test. |  | ||||||
|  |  | ||||||
| Cc: Andre Przywara <andre.przywara@arm.com> |  | ||||||
| Reviewed-by: David Gibson <david@gibson.dropbear.id.au> |  | ||||||
| Signed-off-by: Rob Herring <robh@kernel.org> |  | ||||||
| Message-Id: <20211011191245.1009682-3-robh@kernel.org> |  | ||||||
| Signed-off-by: David Gibson <david@gibson.dropbear.id.au> |  | ||||||
| --- |  | ||||||
| --- a/scripts/dtc/checks.c |  | ||||||
| +++ b/scripts/dtc/checks.c |  | ||||||
| @@ -1569,11 +1569,6 @@ static void check_interrupt_provider(str |  | ||||||
|  	if (!prop) |  | ||||||
|  		FAIL(c, dti, node, |  | ||||||
|  		     "Missing #interrupt-cells in interrupt provider"); |  | ||||||
| - |  | ||||||
| -	prop = get_property(node, "#address-cells"); |  | ||||||
| -	if (!prop) |  | ||||||
| -		FAIL(c, dti, node, |  | ||||||
| -		     "Missing #address-cells in interrupt provider"); |  | ||||||
|  } |  | ||||||
|  WARNING(interrupt_provider, check_interrupt_provider, NULL); |  | ||||||
|   |  | ||||||
		Reference in New Issue
	
	Block a user
	 Christian Marangi
					Christian Marangi