Re: [PATCH v2] libfdt: overlay: ensure that existing phandles are not overwritten

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]



Hello,

On Fri, Feb 16, 2024 at 07:19:20PM +0100, Uwe Kleine-König wrote:
> A phandle in an overlay is not supposed to overwrite a phandle that
> already exists in the base dtb as this breaks references to the
> respective node in the base.
> 
> So add another iteration over the fdto that checks for such overwrites
> and fixes the fdto phandle's value to match the fdt's.
> 
> A test is added that checks that newly added phandles and existing
> phandles work as expected.
> 
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@xxxxxxxxxxxxxx>

After sending the patch out I had a nice idea for an optimisation here.
It doesn't make the process faster, but improves the result.

If phandle with the (shifted) value 17 is changed to 5, there is no
phandle with the value 17 in the end. So while iterating over the fdto
to replace all phandles with value 17 by 5 all values > 17 can be
reduced by one. This way the phandle allocation in the resulting dtb is
continuous if both inputs have continuous numbers.

This can be implemented by the patch below on top of the patch I'm
replying to.

Best regards
Uwe

diff --git a/libfdt/fdt_overlay.c b/libfdt/fdt_overlay.c
index 914acc5b14a6..bfdba50dee50 100644
--- a/libfdt/fdt_overlay.c
+++ b/libfdt/fdt_overlay.c
@@ -529,15 +529,25 @@ static int overlay_adjust_node_conflicting_phandle(void *fdto, int node,
 	int child;
 
 	php = fdt_getprop(fdto, node, "phandle", &len);
-	if (php && len == sizeof(*php) && fdt32_to_cpu(*php) == fdto_phandle) {
-		ret = fdt_setprop_inplace_u32(fdto, node, "phandle", fdt_phandle);
+	if (php && len == sizeof(*php)) {
+		if (fdt32_to_cpu(*php) == fdto_phandle)
+			ret = fdt_setprop_inplace_u32(fdto, node, "phandle", fdt_phandle);
+		else if (fdt32_to_cpu(*php) > fdto_phandle)
+			ret = fdt_setprop_inplace_u32(fdto, node, "phandle", fdt32_to_cpu(*php) - 1);
+		else
+			ret = 0;
 		if (ret)
 			return ret;
 	}
 
 	php = fdt_getprop(fdto, node, "linux,phandle", &len);
-	if (php && len == sizeof(*php) && fdt32_to_cpu(*php) == fdto_phandle) {
-		ret = fdt_setprop_inplace_u32(fdto, node, "linux,phandle", fdt_phandle);
+	if (php && len == sizeof(*php)) {
+		if (fdt32_to_cpu(*php) == fdto_phandle)
+			ret = fdt_setprop_inplace_u32(fdto, node, "linux,phandle", fdt_phandle);
+		else if (fdt32_to_cpu(*php) > fdto_phandle)
+			ret = fdt_setprop_inplace_u32(fdto, node, "phandle", fdt32_to_cpu(*php) - 1);
+		else
+			ret = 0;
 		if (ret)
 			return ret;
 	}
@@ -609,23 +619,27 @@ static int overlay_update_node_conflicting_references(void *fdto, int tree_node,
 			 */
 			memcpy(&adj_val, tree_val + poffset, sizeof(adj_val));
 
-			if (fdt32_to_cpu(adj_val) == fdto_phandle) {
+			if (fdt32_to_cpu(adj_val) < fdto_phandle)
+				continue;
 
+			if (fdt32_to_cpu(adj_val) == fdto_phandle)
 				adj_val = cpu_to_fdt32(fdt_phandle);
+			else
+				adj_val = cpu_to_fdt32(fdt32_to_cpu(adj_val) - 1);
 
-				ret = fdt_setprop_inplace_namelen_partial(fdto,
-									  tree_node,
-									  name,
-									  strlen(name),
-									  poffset,
-									  &adj_val,
-									  sizeof(adj_val));
-				if (ret == -FDT_ERR_NOSPACE)
-					return -FDT_ERR_BADOVERLAY;
 
-				if (ret)
-					return ret;
-			}
+			ret = fdt_setprop_inplace_namelen_partial(fdto,
+								  tree_node,
+								  name,
+								  strlen(name),
+								  poffset,
+								  &adj_val,
+								  sizeof(adj_val));
+			if (ret == -FDT_ERR_NOSPACE)
+				return -FDT_ERR_BADOVERLAY;
+
+			if (ret)
+				return ret;
 		}
 	}
 
-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | https://www.pengutronix.de/ |

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Device Tree]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux