|
@@ -3049,6 +3049,133 @@ int fit_check_format(const void *fit)
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * fit_conf_find_compat
|
|
|
|
+ * @fit: pointer to the FIT format image header
|
|
|
|
+ * @fdt: pointer to the device tree to compare against
|
|
|
|
+ *
|
|
|
|
+ * fit_conf_find_compat() attempts to find the configuration whose fdt is the
|
|
|
|
+ * most compatible with the passed in device tree.
|
|
|
|
+ *
|
|
|
|
+ * Example:
|
|
|
|
+ *
|
|
|
|
+ * / o image-tree
|
|
|
|
+ * |-o images
|
|
|
|
+ * | |-o fdt@1
|
|
|
|
+ * | |-o fdt@2
|
|
|
|
+ * |
|
|
|
|
+ * |-o configurations
|
|
|
|
+ * |-o config@1
|
|
|
|
+ * | |-fdt = fdt@1
|
|
|
|
+ * |
|
|
|
|
+ * |-o config@2
|
|
|
|
+ * |-fdt = fdt@2
|
|
|
|
+ *
|
|
|
|
+ * / o U-Boot fdt
|
|
|
|
+ * |-compatible = "foo,bar", "bim,bam"
|
|
|
|
+ *
|
|
|
|
+ * / o kernel fdt1
|
|
|
|
+ * |-compatible = "foo,bar",
|
|
|
|
+ *
|
|
|
|
+ * / o kernel fdt2
|
|
|
|
+ * |-compatible = "bim,bam", "baz,biz"
|
|
|
|
+ *
|
|
|
|
+ * Configuration 1 would be picked because the first string in U-Boot's
|
|
|
|
+ * compatible list, "foo,bar", matches a compatible string in the root of fdt1.
|
|
|
|
+ * "bim,bam" in fdt2 matches the second string which isn't as good as fdt1.
|
|
|
|
+ *
|
|
|
|
+ * returns:
|
|
|
|
+ * offset to the configuration to use if one was found
|
|
|
|
+ * -1 otherwise
|
|
|
|
+ */
|
|
|
|
+int fit_conf_find_compat(const void *fit, const void *fdt)
|
|
|
|
+{
|
|
|
|
+ int ndepth = 0;
|
|
|
|
+ int noffset, confs_noffset, images_noffset;
|
|
|
|
+ const void *fdt_compat;
|
|
|
|
+ int fdt_compat_len;
|
|
|
|
+ int best_match_offset = 0;
|
|
|
|
+ int best_match_pos = 0;
|
|
|
|
+
|
|
|
|
+ confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
|
|
|
|
+ images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
|
|
|
|
+ if (confs_noffset < 0 || images_noffset < 0) {
|
|
|
|
+ debug("Can't find configurations or images nodes.\n");
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fdt_compat = fdt_getprop(fdt, 0, "compatible", &fdt_compat_len);
|
|
|
|
+ if (!fdt_compat) {
|
|
|
|
+ debug("Fdt for comparison has no \"compatible\" property.\n");
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Loop over the configurations in the FIT image.
|
|
|
|
+ */
|
|
|
|
+ for (noffset = fdt_next_node(fit, confs_noffset, &ndepth);
|
|
|
|
+ (noffset >= 0) && (ndepth > 0);
|
|
|
|
+ noffset = fdt_next_node(fit, noffset, &ndepth)) {
|
|
|
|
+ const void *kfdt;
|
|
|
|
+ const char *kfdt_name;
|
|
|
|
+ int kfdt_noffset;
|
|
|
|
+ const char *cur_fdt_compat;
|
|
|
|
+ int len;
|
|
|
|
+ size_t size;
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ if (ndepth > 1)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ kfdt_name = fdt_getprop(fit, noffset, "fdt", &len);
|
|
|
|
+ if (!kfdt_name) {
|
|
|
|
+ debug("No fdt property found.\n");
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ kfdt_noffset = fdt_subnode_offset(fit, images_noffset,
|
|
|
|
+ kfdt_name);
|
|
|
|
+ if (kfdt_noffset < 0) {
|
|
|
|
+ debug("No image node named \"%s\" found.\n",
|
|
|
|
+ kfdt_name);
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ /*
|
|
|
|
+ * Get a pointer to this configuration's fdt.
|
|
|
|
+ */
|
|
|
|
+ if (fit_image_get_data(fit, kfdt_noffset, &kfdt, &size)) {
|
|
|
|
+ debug("Failed to get fdt \"%s\".\n", kfdt_name);
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ len = fdt_compat_len;
|
|
|
|
+ cur_fdt_compat = fdt_compat;
|
|
|
|
+ /*
|
|
|
|
+ * Look for a match for each U-Boot compatibility string in
|
|
|
|
+ * turn in this configuration's fdt.
|
|
|
|
+ */
|
|
|
|
+ for (i = 0; len > 0 &&
|
|
|
|
+ (!best_match_offset || best_match_pos > i); i++) {
|
|
|
|
+ int cur_len = strlen(cur_fdt_compat) + 1;
|
|
|
|
+
|
|
|
|
+ if (!fdt_node_check_compatible(kfdt, 0,
|
|
|
|
+ cur_fdt_compat)) {
|
|
|
|
+ best_match_offset = noffset;
|
|
|
|
+ best_match_pos = i;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ len -= cur_len;
|
|
|
|
+ cur_fdt_compat += cur_len;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (!best_match_offset) {
|
|
|
|
+ debug("No match found.\n");
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return best_match_offset;
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* fit_conf_get_node - get node offset for configuration of a given unit name
|
|
* fit_conf_get_node - get node offset for configuration of a given unit name
|
|
* @fit: pointer to the FIT format image header
|
|
* @fit: pointer to the FIT format image header
|