Skip to content
This repository was archived by the owner on Aug 27, 2025. It is now read-only.

Commit affef1e

Browse files
pelwellpopcornmix
authored andcommitted
dtoverlay: Rebase aliases in overlays like labels
Aliases and labels/symbols are stored in the same way - as path strings. The overlay application code already knows how to rewrite exported symbol paths so they are correct in the base DTB (rebasing), so use the same logic to rebase aliases as they are applied.
1 parent a70a742 commit affef1e

File tree

1 file changed

+103
-78
lines changed

1 file changed

+103
-78
lines changed

helpers/dtoverlay/dtoverlay.c

Lines changed: 103 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,6 +1014,99 @@ static int dtoverlay_get_target_offset(DTBLOB_T *base_dtb,
10141014
return target_off;
10151015
}
10161016

1017+
// Copy a node full of path strings (__symbols__, aliases) from an overlay to
1018+
// the base dtb, rebasing any fragment-relative paths to make them relative
1019+
// to the respective fragment target. Note that this should not be called for
1020+
// intra-overlay fragments, and that overlay_dtb is not modified.
1021+
static int dtoverlay_apply_overlay_paths(DTBLOB_T *base_dtb, int strings_off,
1022+
DTBLOB_T *overlay_dtb, int frag_off,
1023+
const char *type)
1024+
{
1025+
int sym_off;
1026+
int err = 0;
1027+
1028+
fdt_for_each_property_offset(sym_off, overlay_dtb->fdt, frag_off)
1029+
{
1030+
char target_path[DTOVERLAY_MAX_PATH];
1031+
const char *sym_name = NULL;
1032+
const char *sym_path;
1033+
const char *p;
1034+
int sym_len;
1035+
int sym_frag_off;
1036+
int target_off;
1037+
int target_path_len;
1038+
int new_path_len;
1039+
1040+
sym_path = fdt_getprop_by_offset(overlay_dtb->fdt, sym_off,
1041+
&sym_name, &sym_len);
1042+
if (!sym_path)
1043+
break;
1044+
1045+
/* Skip non-overlay symbols
1046+
* Overlay symbol paths should be of the form:
1047+
* /<fragment>/__overlay__/<something>
1048+
* It doesn't actually matter what <fragment> is.
1049+
*/
1050+
if (sym_path[0] != '/')
1051+
goto copy_verbatim;
1052+
1053+
p = strchr(sym_path + 1, '/');
1054+
if (!p || strncmp(p + 1, "__overlay__", 11) != 0 ||
1055+
(p[11] != '/' && p[11] != '\0'))
1056+
goto copy_verbatim;
1057+
1058+
/* Rebase the symbol path so that
1059+
* /fragment@0/__overlay__/<something>
1060+
* becomes
1061+
* <path-to-fragment-target>/<something>
1062+
*/
1063+
1064+
/* Find the offset to the fragment */
1065+
sym_frag_off = dtoverlay_find_node(overlay_dtb, sym_path,
1066+
p - sym_path);
1067+
1068+
p += 12; /* p points to /<something> */
1069+
1070+
/* Locate the path to the fragment target */
1071+
target_off = dtoverlay_get_target_offset(base_dtb, overlay_dtb,
1072+
sym_frag_off);
1073+
if (target_off < 0)
1074+
return target_off;
1075+
1076+
err = fdt_get_path(base_dtb->fdt, target_off,
1077+
target_path, sizeof(target_path));
1078+
if (err)
1079+
{
1080+
dtoverlay_error("bad target path for %s", sym_path);
1081+
break;
1082+
}
1083+
1084+
/* Append the fragment-relative path to the target path */
1085+
target_path_len = strlen(target_path);
1086+
if (strcmp(target_path, "/") == 0)
1087+
p++; // Avoid a '//' if the target is the root
1088+
new_path_len = target_path_len + (sym_path + sym_len - p);
1089+
if (new_path_len >= sizeof(target_path))
1090+
{
1091+
dtoverlay_error("exported symbol path too long for %s", sym_path);
1092+
err = -FDT_ERR_NOSPACE;
1093+
break;
1094+
}
1095+
strcpy(target_path + target_path_len, p);
1096+
fdt_setprop(base_dtb->fdt, strings_off,
1097+
sym_name, target_path, new_path_len);
1098+
dtoverlay_debug("set %s '%s' path to '%s'", type,
1099+
sym_name, target_path);
1100+
continue;
1101+
1102+
copy_verbatim:
1103+
fdt_setprop(base_dtb->fdt, strings_off,
1104+
sym_name, sym_path, sym_len);
1105+
}
1106+
1107+
return err;
1108+
}
1109+
10171110
// Returns 0 on success, -ve for fatal errors and +ve for non-fatal errors
10181111
int dtoverlay_merge_overlay(DTBLOB_T *base_dtb, DTBLOB_T *overlay_dtb)
10191112
{
@@ -1119,82 +1212,9 @@ int dtoverlay_merge_overlay(DTBLOB_T *base_dtb, DTBLOB_T *overlay_dtb)
11191212
if (strcmp(node_name, "__symbols__") == 0)
11201213
{
11211214
/* At this point, only exported symbols should remain */
1122-
int sym_off;
1123-
1124-
fdt_for_each_property_offset(sym_off, overlay_dtb->fdt, frag_off)
1125-
{
1126-
char target_path[DTOVERLAY_MAX_PATH];
1127-
const char *sym_name = NULL;
1128-
const char *sym_path;
1129-
const char *p;
1130-
int sym_len;
1131-
int sym_frag_off;
1132-
int target_path_len;
1133-
int new_path_len;
1134-
int base_symbols;
1135-
1136-
sym_path = fdt_getprop_by_offset(overlay_dtb->fdt, sym_off,
1137-
&sym_name, &sym_len);
1138-
if (!sym_path)
1139-
break;
1140-
1141-
/* Rebase the symbol path so that
1142-
* /fragment@0/__overlay__/<something>
1143-
* becomes
1144-
* <path-to-fragment-target>/<something>
1145-
*/
1146-
1147-
/* Skip non-overlay symbols
1148-
* Overlay symbol paths should be of the form:
1149-
* /<fragment>/__overlay__/<something>
1150-
* It doesn't actually matter what <fragment> is.
1151-
*/
1152-
if (sym_path[0] != '/')
1153-
continue;
1154-
1155-
p = strchr(sym_path + 1, '/');
1156-
if (!p || strncmp(p + 1, "__overlay__/", 12) != 0)
1157-
continue;
1158-
1159-
/* Find the offset to the fragment */
1160-
sym_frag_off = dtoverlay_find_node(overlay_dtb, sym_path,
1161-
p - sym_path);
1162-
1163-
p += 12; /* p points to /<something> */
1164-
1165-
/* Locate the path to the fragment target */
1166-
target_off = dtoverlay_get_target_offset(base_dtb, overlay_dtb,
1167-
sym_frag_off);
1168-
if (target_off < 0)
1169-
return target_off;
1170-
1171-
err = fdt_get_path(base_dtb->fdt, target_off,
1172-
target_path, sizeof(target_path));
1173-
if (err)
1174-
{
1175-
dtoverlay_error("bad target path for %s", sym_path);
1176-
break;
1177-
}
1178-
1179-
/* Append the fragment-relative path to the target path */
1180-
target_path_len = strlen(target_path);
1181-
if (strcmp(target_path, "/") == 0)
1182-
p++; // Avoid a '//' if the target is the root
1183-
new_path_len = target_path_len + (sym_path + sym_len - p);
1184-
if (new_path_len >= sizeof(target_path))
1185-
{
1186-
dtoverlay_error("exported symbol path too long for %s", sym_path);
1187-
err = -FDT_ERR_NOSPACE;
1188-
break;
1189-
}
1190-
strcpy(target_path + target_path_len, p);
1191-
1192-
base_symbols = fdt_path_offset(base_dtb->fdt, "/__symbols__");
1193-
fdt_setprop(base_dtb->fdt, base_symbols,
1194-
sym_name, target_path, new_path_len);
1195-
dtoverlay_debug("set label '%s' path to '%s'",
1196-
sym_name, target_path);
1197-
}
1215+
int symbols_off = dtoverlay_find_node(base_dtb, "/__symbols__", 0);
1216+
dtoverlay_apply_overlay_paths(base_dtb, symbols_off,
1217+
overlay_dtb, frag_off, "label");
11981218
continue;
11991219
}
12001220
else if (strncmp(node_name, "fragment@", 9) != 0 &&
@@ -1224,8 +1244,13 @@ int dtoverlay_merge_overlay(DTBLOB_T *base_dtb, DTBLOB_T *overlay_dtb)
12241244
}
12251245

12261246
// Now do the merge
1227-
err = dtoverlay_merge_fragment(base_dtb, target_off, overlay_dtb,
1228-
overlay_off, 0);
1247+
node_name = fdt_get_name(base_dtb->fdt, target_off, NULL);
1248+
if (node_name && strcmp(node_name, "aliases") == 0)
1249+
err = dtoverlay_apply_overlay_paths(base_dtb, target_off, overlay_dtb,
1250+
overlay_off, "alias");
1251+
else
1252+
err = dtoverlay_merge_fragment(base_dtb, target_off, overlay_dtb,
1253+
overlay_off, 0);
12291254
}
12301255

12311256
if (err == 0)

0 commit comments

Comments
 (0)