@@ -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
10181111int 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