^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * libfdt - Flat Device Tree manipulation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2016 Free Electrons
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2016 NextThing Co.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include "libfdt_env.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <fdt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <libfdt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "libfdt_internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * overlay_get_target_phandle - retrieves the target phandle of a fragment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * @fdto: pointer to the device tree overlay blob
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * @fragment: node offset of the fragment in the overlay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * overlay_get_target_phandle() retrieves the target phandle of an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * overlay fragment when that fragment uses a phandle (target
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * property) instead of a path (target-path property).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * the phandle pointed by the target property
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * 0, if the phandle was not found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * -1, if the phandle was malformed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) const fdt32_t *val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) val = fdt_getprop(fdto, fragment, "target", &len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) if (!val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if ((len != sizeof(*val)) || (fdt32_to_cpu(*val) == (uint32_t)-1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) return (uint32_t)-1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return fdt32_to_cpu(*val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * overlay_get_target - retrieves the offset of a fragment's target
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * @fdt: Base device tree blob
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * @fdto: Device tree overlay blob
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * @fragment: node offset of the fragment in the overlay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * @pathp: pointer which receives the path of the target (or NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * overlay_get_target() retrieves the target offset in the base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * device tree of a fragment, no matter how the actual targeting is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * done (through a phandle or a path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * the targeted node offset in the base device tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * Negative error code on error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static int overlay_get_target(const void *fdt, const void *fdto,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) int fragment, char const **pathp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) uint32_t phandle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) const char *path = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) int path_len = 0, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /* Try first to do a phandle based lookup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) phandle = overlay_get_target_phandle(fdto, fragment);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (phandle == (uint32_t)-1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return -FDT_ERR_BADPHANDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /* no phandle, try path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (!phandle) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /* And then a path based lookup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) path = fdt_getprop(fdto, fragment, "target-path", &path_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) ret = fdt_path_offset(fdt, path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) ret = path_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) ret = fdt_node_offset_by_phandle(fdt, phandle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * If we haven't found either a target or a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * target-path property in a node that contains a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * __overlay__ subnode (we wouldn't be called
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * otherwise), consider it a improperly written
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * overlay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (ret < 0 && path_len == -FDT_ERR_NOTFOUND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) ret = -FDT_ERR_BADOVERLAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) /* return on error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /* return pointer to path (if available) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (pathp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) *pathp = path ? path : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * overlay_phandle_add_offset - Increases a phandle by an offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * @fdt: Base device tree blob
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * @node: Device tree overlay blob
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * @name: Name of the property to modify (phandle or linux,phandle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * @delta: offset to apply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * overlay_phandle_add_offset() increments a node phandle by a given
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * offset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * 0 on success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * Negative error code on error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static int overlay_phandle_add_offset(void *fdt, int node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) const char *name, uint32_t delta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) const fdt32_t *val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) uint32_t adj_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) val = fdt_getprop(fdt, node, name, &len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (!val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (len != sizeof(*val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return -FDT_ERR_BADPHANDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) adj_val = fdt32_to_cpu(*val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if ((adj_val + delta) < adj_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return -FDT_ERR_NOPHANDLES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) adj_val += delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (adj_val == (uint32_t)-1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return -FDT_ERR_NOPHANDLES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return fdt_setprop_inplace_u32(fdt, node, name, adj_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * overlay_adjust_node_phandles - Offsets the phandles of a node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * @fdto: Device tree overlay blob
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * @node: Offset of the node we want to adjust
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * @delta: Offset to shift the phandles of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * overlay_adjust_node_phandles() adds a constant to all the phandles
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * of a given node. This is mainly use as part of the overlay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * application process, when we want to update all the overlay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * phandles to not conflict with the overlays of the base device tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * 0 on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * Negative error code on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static int overlay_adjust_node_phandles(void *fdto, int node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) uint32_t delta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) int child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) ret = overlay_phandle_add_offset(fdto, node, "phandle", delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (ret && ret != -FDT_ERR_NOTFOUND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (ret && ret != -FDT_ERR_NOTFOUND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) fdt_for_each_subnode(child, fdto, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) ret = overlay_adjust_node_phandles(fdto, child, delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * overlay_adjust_local_phandles - Adjust the phandles of a whole overlay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * @fdto: Device tree overlay blob
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * @delta: Offset to shift the phandles of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * overlay_adjust_local_phandles() adds a constant to all the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * phandles of an overlay. This is mainly use as part of the overlay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * application process, when we want to update all the overlay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * phandles to not conflict with the overlays of the base device tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * 0 on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * Negative error code on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) static int overlay_adjust_local_phandles(void *fdto, uint32_t delta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * Start adjusting the phandles from the overlay root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return overlay_adjust_node_phandles(fdto, 0, delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * overlay_update_local_node_references - Adjust the overlay references
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * @fdto: Device tree overlay blob
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * @tree_node: Node offset of the node to operate on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * @fixup_node: Node offset of the matching local fixups node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * @delta: Offset to shift the phandles of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * overlay_update_local_nodes_references() update the phandles
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * pointing to a node within the device tree overlay by adding a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * constant delta.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * This is mainly used as part of a device tree application process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * where you want the device tree overlays phandles to not conflict
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * with the ones from the base device tree before merging them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * 0 on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * Negative error code on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static int overlay_update_local_node_references(void *fdto,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) int tree_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) int fixup_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) uint32_t delta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) int fixup_prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) int fixup_child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) const fdt32_t *fixup_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) const char *tree_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) int fixup_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) int tree_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) fixup_val = fdt_getprop_by_offset(fdto, fixup_prop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) &name, &fixup_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (!fixup_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return fixup_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (fixup_len % sizeof(uint32_t))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return -FDT_ERR_BADOVERLAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) fixup_len /= sizeof(uint32_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) tree_val = fdt_getprop(fdto, tree_node, name, &tree_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (!tree_val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (tree_len == -FDT_ERR_NOTFOUND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return -FDT_ERR_BADOVERLAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return tree_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) for (i = 0; i < fixup_len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) fdt32_t adj_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) uint32_t poffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) poffset = fdt32_to_cpu(fixup_val[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * phandles to fixup can be unaligned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * Use a memcpy for the architectures that do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * not support unaligned accesses.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) memcpy(&adj_val, tree_val + poffset, sizeof(adj_val));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) adj_val = cpu_to_fdt32(fdt32_to_cpu(adj_val) + delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) ret = fdt_setprop_inplace_namelen_partial(fdto,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) tree_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) strlen(name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) poffset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) &adj_val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) sizeof(adj_val));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (ret == -FDT_ERR_NOSPACE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return -FDT_ERR_BADOVERLAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) fdt_for_each_subnode(fixup_child, fdto, fixup_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) const char *fixup_child_name = fdt_get_name(fdto, fixup_child,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) int tree_child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) tree_child = fdt_subnode_offset(fdto, tree_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) fixup_child_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (tree_child == -FDT_ERR_NOTFOUND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return -FDT_ERR_BADOVERLAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (tree_child < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return tree_child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) ret = overlay_update_local_node_references(fdto,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) tree_child,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) fixup_child,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * overlay_update_local_references - Adjust the overlay references
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) * @fdto: Device tree overlay blob
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) * @delta: Offset to shift the phandles of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * overlay_update_local_references() update all the phandles pointing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) * to a node within the device tree overlay by adding a constant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) * delta to not conflict with the base overlay.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) * This is mainly used as part of a device tree application process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) * where you want the device tree overlays phandles to not conflict
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) * with the ones from the base device tree before merging them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) * returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) * 0 on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) * Negative error code on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) static int overlay_update_local_references(void *fdto, uint32_t delta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) int fixups;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) fixups = fdt_path_offset(fdto, "/__local_fixups__");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (fixups < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) /* There's no local phandles to adjust, bail out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (fixups == -FDT_ERR_NOTFOUND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) return fixups;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) * Update our local references from the root of the tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) return overlay_update_local_node_references(fdto, 0, fixups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) * overlay_fixup_one_phandle - Set an overlay phandle to the base one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * @fdt: Base Device Tree blob
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) * @fdto: Device tree overlay blob
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) * @symbols_off: Node offset of the symbols node in the base device tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) * @path: Path to a node holding a phandle in the overlay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) * @path_len: number of path characters to consider
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) * @name: Name of the property holding the phandle reference in the overlay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * @name_len: number of name characters to consider
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * @poffset: Offset within the overlay property where the phandle is stored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * @label: Label of the node referenced by the phandle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * overlay_fixup_one_phandle() resolves an overlay phandle pointing to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * a node in the base device tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) * This is part of the device tree overlay application process, when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) * you want all the phandles in the overlay to point to the actual
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) * base dt nodes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) * returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * 0 on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) * Negative error code on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) static int overlay_fixup_one_phandle(void *fdt, void *fdto,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) int symbols_off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) const char *path, uint32_t path_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) const char *name, uint32_t name_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) int poffset, const char *label)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) const char *symbol_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) uint32_t phandle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) fdt32_t phandle_prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) int symbol_off, fixup_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) int prop_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (symbols_off < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return symbols_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) symbol_path = fdt_getprop(fdt, symbols_off, label,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) &prop_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (!symbol_path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return prop_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) symbol_off = fdt_path_offset(fdt, symbol_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (symbol_off < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) return symbol_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) phandle = fdt_get_phandle(fdt, symbol_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (!phandle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return -FDT_ERR_NOTFOUND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (fixup_off == -FDT_ERR_NOTFOUND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) return -FDT_ERR_BADOVERLAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (fixup_off < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) return fixup_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) phandle_prop = cpu_to_fdt32(phandle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) return fdt_setprop_inplace_namelen_partial(fdto, fixup_off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) name, name_len, poffset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) &phandle_prop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) sizeof(phandle_prop));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) * overlay_fixup_phandle - Set an overlay phandle to the base one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) * @fdt: Base Device Tree blob
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) * @fdto: Device tree overlay blob
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) * @symbols_off: Node offset of the symbols node in the base device tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) * @property: Property offset in the overlay holding the list of fixups
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) * overlay_fixup_phandle() resolves all the overlay phandles pointed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * to in a __fixups__ property, and updates them to match the phandles
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * in use in the base device tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) * This is part of the device tree overlay application process, when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) * you want all the phandles in the overlay to point to the actual
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) * base dt nodes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) * 0 on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) * Negative error code on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) int property)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) const char *value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) const char *label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) value = fdt_getprop_by_offset(fdto, property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) &label, &len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (!value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (len == -FDT_ERR_NOTFOUND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) return -FDT_ERR_INTERNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) const char *path, *name, *fixup_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) const char *fixup_str = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) uint32_t path_len, name_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) uint32_t fixup_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) char *sep, *endptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) int poffset, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) fixup_end = memchr(value, '\0', len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (!fixup_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) return -FDT_ERR_BADOVERLAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) fixup_len = fixup_end - fixup_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) len -= fixup_len + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) value += fixup_len + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) path = fixup_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) sep = memchr(fixup_str, ':', fixup_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) if (!sep || *sep != ':')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return -FDT_ERR_BADOVERLAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) path_len = sep - path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (path_len == (fixup_len - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) return -FDT_ERR_BADOVERLAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) fixup_len -= path_len + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) name = sep + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) sep = memchr(name, ':', fixup_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) if (!sep || *sep != ':')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) return -FDT_ERR_BADOVERLAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) name_len = sep - name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) if (!name_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) return -FDT_ERR_BADOVERLAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) poffset = strtoul(sep + 1, &endptr, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) if ((*endptr != '\0') || (endptr <= (sep + 1)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return -FDT_ERR_BADOVERLAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) path, path_len, name, name_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) poffset, label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) } while (len > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) * overlay_fixup_phandles - Resolve the overlay phandles to the base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) * device tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) * @fdt: Base Device Tree blob
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) * @fdto: Device tree overlay blob
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) * overlay_fixup_phandles() resolves all the overlay phandles pointing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) * to nodes in the base device tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) * This is one of the steps of the device tree overlay application
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) * process, when you want all the phandles in the overlay to point to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) * the actual base dt nodes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) * returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) * 0 on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) * Negative error code on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) static int overlay_fixup_phandles(void *fdt, void *fdto)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) int fixups_off, symbols_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) int property;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) /* We can have overlays without any fixups */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) fixups_off = fdt_path_offset(fdto, "/__fixups__");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (fixups_off == -FDT_ERR_NOTFOUND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return 0; /* nothing to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) if (fixups_off < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) return fixups_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /* And base DTs without symbols */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) symbols_off = fdt_path_offset(fdt, "/__symbols__");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if ((symbols_off < 0 && (symbols_off != -FDT_ERR_NOTFOUND)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return symbols_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) fdt_for_each_property_offset(property, fdto, fixups_off) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) ret = overlay_fixup_phandle(fdt, fdto, symbols_off, property);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) * overlay_apply_node - Merges a node into the base device tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) * @fdt: Base Device Tree blob
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) * @target: Node offset in the base device tree to apply the fragment to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) * @fdto: Device tree overlay blob
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) * @node: Node offset in the overlay holding the changes to merge
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) * overlay_apply_node() merges a node into a target base device tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) * node pointed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) * This is part of the final step in the device tree overlay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) * application process, when all the phandles have been adjusted and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) * resolved and you just have to merge overlay into the base device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) * tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) * returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) * 0 on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) * Negative error code on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) static int overlay_apply_node(void *fdt, int target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) void *fdto, int node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) int property;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) int subnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) fdt_for_each_property_offset(property, fdto, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) const void *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) int prop_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) prop = fdt_getprop_by_offset(fdto, property, &name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) &prop_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (prop_len == -FDT_ERR_NOTFOUND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) return -FDT_ERR_INTERNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) if (prop_len < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) return prop_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) ret = fdt_setprop(fdt, target, name, prop, prop_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) fdt_for_each_subnode(subnode, fdto, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) const char *name = fdt_get_name(fdto, subnode, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) int nnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) nnode = fdt_add_subnode(fdt, target, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) if (nnode == -FDT_ERR_EXISTS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) nnode = fdt_subnode_offset(fdt, target, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) if (nnode == -FDT_ERR_NOTFOUND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) return -FDT_ERR_INTERNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (nnode < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return nnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) ret = overlay_apply_node(fdt, nnode, fdto, subnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) * overlay_merge - Merge an overlay into its base device tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) * @fdt: Base Device Tree blob
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) * @fdto: Device tree overlay blob
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) * overlay_merge() merges an overlay into its base device tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) * This is the next to last step in the device tree overlay application
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) * process, when all the phandles have been adjusted and resolved and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) * you just have to merge overlay into the base device tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) * returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) * 0 on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) * Negative error code on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) static int overlay_merge(void *fdt, void *fdto)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) int fragment;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) fdt_for_each_subnode(fragment, fdto, 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) int overlay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) int target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) * Each fragments will have an __overlay__ node. If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) * they don't, it's not supposed to be merged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) overlay = fdt_subnode_offset(fdto, fragment, "__overlay__");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (overlay == -FDT_ERR_NOTFOUND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) if (overlay < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) return overlay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) target = overlay_get_target(fdt, fdto, fragment, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) if (target < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) return target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) ret = overlay_apply_node(fdt, target, fdto, overlay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) static int get_path_len(const void *fdt, int nodeoffset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) int len = 0, namelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) FDT_RO_PROBE(fdt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) name = fdt_get_name(fdt, nodeoffset, &namelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) if (!name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) return namelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) /* root? we're done */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) if (namelen == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) nodeoffset = fdt_parent_offset(fdt, nodeoffset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) if (nodeoffset < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) return nodeoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) len += namelen + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) /* in case of root pretend it's "/" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) if (len == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) len++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) * overlay_symbol_update - Update the symbols of base tree after a merge
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) * @fdt: Base Device Tree blob
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) * @fdto: Device tree overlay blob
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) * overlay_symbol_update() updates the symbols of the base tree with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) * symbols of the applied overlay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) * This is the last step in the device tree overlay application
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) * process, allowing the reference of overlay symbols by subsequent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) * overlay operations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) * returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) * 0 on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) * Negative error code on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) static int overlay_symbol_update(void *fdt, void *fdto)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) int root_sym, ov_sym, prop, path_len, fragment, target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) int len, frag_name_len, ret, rel_path_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) const char *s, *e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) const char *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) const char *frag_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) const char *rel_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) const char *target_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) void *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) ov_sym = fdt_subnode_offset(fdto, 0, "__symbols__");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) /* if no overlay symbols exist no problem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) if (ov_sym < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) root_sym = fdt_subnode_offset(fdt, 0, "__symbols__");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) /* it no root symbols exist we should create them */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (root_sym == -FDT_ERR_NOTFOUND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) root_sym = fdt_add_subnode(fdt, 0, "__symbols__");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) /* any error is fatal now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) if (root_sym < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) return root_sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) /* iterate over each overlay symbol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) fdt_for_each_property_offset(prop, fdto, ov_sym) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) path = fdt_getprop_by_offset(fdto, prop, &name, &path_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) if (!path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) return path_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) /* verify it's a string property (terminated by a single \0) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) if (path_len < 1 || memchr(path, '\0', path_len) != &path[path_len - 1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) return -FDT_ERR_BADVALUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) /* keep end marker to avoid strlen() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) e = path + path_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) if (*path != '/')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) return -FDT_ERR_BADVALUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) /* get fragment name first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) s = strchr(path + 1, '/');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) if (!s) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) /* Symbol refers to something that won't end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) * up in the target tree */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) frag_name = path + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) frag_name_len = s - path - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) /* verify format; safe since "s" lies in \0 terminated prop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) len = sizeof("/__overlay__/") - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) if ((e - s) > len && (memcmp(s, "/__overlay__/", len) == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) /* /<fragment-name>/__overlay__/<relative-subnode-path> */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) rel_path = s + len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) rel_path_len = e - rel_path - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) } else if ((e - s) == len
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) && (memcmp(s, "/__overlay__", len - 1) == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) /* /<fragment-name>/__overlay__ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) rel_path = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) rel_path_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) /* Symbol refers to something that won't end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) * up in the target tree */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) /* find the fragment index in which the symbol lies */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) ret = fdt_subnode_offset_namelen(fdto, 0, frag_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) frag_name_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) /* not found? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) return -FDT_ERR_BADOVERLAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) fragment = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) /* an __overlay__ subnode must exist */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) ret = fdt_subnode_offset(fdto, fragment, "__overlay__");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) return -FDT_ERR_BADOVERLAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) /* get the target of the fragment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) ret = overlay_get_target(fdt, fdto, fragment, &target_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) target = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) /* if we have a target path use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) if (!target_path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) ret = get_path_len(fdt, target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) len = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) len = strlen(target_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) ret = fdt_setprop_placeholder(fdt, root_sym, name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) len + (len > 1) + rel_path_len + 1, &p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (!target_path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) /* again in case setprop_placeholder changed it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) ret = overlay_get_target(fdt, fdto, fragment, &target_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) target = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) buf = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) if (len > 1) { /* target is not root */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) if (!target_path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) ret = fdt_get_path(fdt, target, buf, len + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) memcpy(buf, target_path, len + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) len--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) buf[len] = '/';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) memcpy(buf + len + 1, rel_path, rel_path_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) buf[len + 1 + rel_path_len] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) int fdt_overlay_apply(void *fdt, void *fdto)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) uint32_t delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) FDT_RO_PROBE(fdt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) FDT_RO_PROBE(fdto);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) ret = fdt_find_max_phandle(fdt, &delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) ret = overlay_adjust_local_phandles(fdto, delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) ret = overlay_update_local_references(fdto, delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) ret = overlay_fixup_phandles(fdt, fdto);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) ret = overlay_merge(fdt, fdto);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) ret = overlay_symbol_update(fdt, fdto);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) * The overlay has been damaged, erase its magic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) fdt_set_magic(fdto, ~0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) * The overlay might have been damaged, erase its magic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) fdt_set_magic(fdto, ~0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) * The base device tree might have been damaged, erase its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) * magic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) fdt_set_magic(fdt, ~0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) }