On Thu, Feb 22, 2024 at 10:38:54AM +0100, Uwe Kleine-König wrote: > On Thu, Feb 22, 2024 at 05:32:10PM +1100, David Gibson wrote: > > On Fri, Feb 16, 2024 at 07:19:20PM +0100, Uwe Kleine-König wrote: > > > +static int overlay_update_node_conflicting_references(void *fdto, int tree_node, > > > + int fixup_node, > > > + uint32_t fdt_phandle, > > > + uint32_t fdto_phandle) > > > +{ > > > + int fixup_prop; > > > + int fixup_child; > > > + int ret; > > > + > > > + fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) { > > > + > > > + const fdt32_t *fixup_val; > > > + const char *tree_val; > > > + const char *name; > > > + int fixup_len; > > > + int tree_len; > > > + int i; > > > + > > > + fixup_val = fdt_getprop_by_offset(fdto, fixup_prop, > > > + &name, &fixup_len); > > > + if (!fixup_val) > > > + return fixup_len; > > > + > > > + if (fixup_len % sizeof(uint32_t)) > > > + return -FDT_ERR_BADOVERLAY; > > > + fixup_len /= sizeof(uint32_t); > > > + > > > + tree_val = fdt_getprop(fdto, tree_node, name, &tree_len); > > > + if (!tree_val) { > > > + if (tree_len == -FDT_ERR_NOTFOUND) > > > + return -FDT_ERR_BADOVERLAY; > > > + > > > + return tree_len; > > > + } > > > + > > > + for (i = 0; i < fixup_len; i++) { > > > + fdt32_t adj_val; > > > + uint32_t poffset; > > > + > > > + poffset = fdt32_to_cpu(fixup_val[i]); > > > > You can use fdt32_ld_() here to slightly simplify this > > I don't see what you suggest here. fixup_val is assigned to in > fdt_getprop_by_offset() which I need to get fixup_len and then fixup_val > is already around. If you still think this could be improved, please be > more explicit. poffset = fdt32_ld_(fixup_val + i); Thus combining the memory read and the byteswap into one operation. I guess it doesn't really simplify the code, but correctly handling reads and writes to memory within the dtb is what the fdt*_ld() and fdt*_st() helpers are for. > > > + > > > + /* > > > + * phandles to fixup can be unaligned. > > > + * > > > + * Use a memcpy for the architectures that do > > > + * not support unaligned accesses. > > > + */ > > > + memcpy(&adj_val, tree_val + poffset, sizeof(adj_val)); > > > > And here you can use fdt32_ld() which has unaligned access handling > > built in. Specifically adj_val = fdt32_ld(tree_val + poffset) And then replacing fdt32_to_cpu(adj_val) with just adj_val below. > > > > > + > > > + if (fdt32_to_cpu(adj_val) == fdto_phandle) { > > > + > > > + adj_val = cpu_to_fdt32(fdt_phandle); > > > + > > > + 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; > > > > And here you can use fdt32_st() on (tree_val + poffset), avoiding > > quite some complexity. > > There is some complexity because tree_val is a const char * (as this is > what fdt_getprop() returns) and fdt32_st() obviously doens't take a > const pointer. Ah, right. You can use fdt_getprop_w() to get a writable pointer instead. If there was a way to have fdt_getprop() return a const pointer only if the fdt pointer it was given was const, I'd do that. > If you want to play around with that, the code is mostly a copy of > overlay_update_local_node_references() which could benefit from your > suggestions in the same way. That's quite plausible. > Can I lure you in improving overlay_update_local_node_references()? Then Fair point.. https://github.com/dgibson/dtc/commit/24f60011fd43683d8e3916435c4c726e9baac9c9 > I could copy from the improved function for my patch. (Or maybe refactor > the function to take a function as parameter which is Eh... I'd prefer to avoid higher order functions in something this low level. > uint32_t delta; > uint32_t increase_by_delta(uint32_t phandle) > { > return phandle + delta; > } > > for the overlay_update_local_node_references() case and > > uint32_t fdt_phandle; > uint32_t fdto_phandle; > uint32_t resolve_fdt_conflict(uint32_t phandle) > { > if (phandle == fdto_phandle) > return fdt_phandle; > else > return phandle; > } > > for my function (maybe passing the data stored in global vars here in a > context parameter). > > Best regards > Uwe > -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson