15168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju/*
25168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju * Copyright (C) 2018 The Android Open Source Project
35168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju *
45168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju * Licensed under the Apache License, Version 2.0 (the "License");
55168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju * you may not use this file except in compliance with the License.
65168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju * You may obtain a copy of the License at
75168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju *
85168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju *      http://www.apache.org/licenses/LICENSE-2.0
95168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju *
105168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju * Unless required by applicable law or agreed to in writing, software
115168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju * distributed under the License is distributed on an "AS IS" BASIS,
125168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju * See the License for the specific language governing permissions and
145168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju * limitations under the License.
155168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju */
165168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
175168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju#include <string>
184c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju#include <unordered_map>
195168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
205168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsarajuextern "C" {
215168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
225168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju#include "libufdt.h"
235168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju#include "ufdt_node_pool.h"
245168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju#include "ufdt_overlay.h"
255168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju#include "ufdt_overlay_internal.h"
265168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
275168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju}
285168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
295168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju#include "ufdt_test_overlay.h"
305168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
315168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsarajustatic bool ufdt_node_compare(struct ufdt_node *node_a, struct ufdt_node *node_b,
325168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                              struct ufdt* tree_a, struct ufdt* tree_b);
335168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
345168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju/*
355168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju * Helper method to check if the tree rooted at node_b is a subset of the tree rooted
365168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju * at node_a.
375168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju */
385168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsarajustatic bool compare_child_nodes(struct ufdt_node *node_a, struct ufdt_node *node_b,
395168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                                struct ufdt * tree_a, struct ufdt * tree_b) {
405168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    bool result = true;
415168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    struct ufdt_node *it;
425168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
435168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    for (it = ((struct ufdt_node_fdt_node *)node_b)->child; it; it = it->sibling) {
445168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        struct ufdt_node *cur_node = it;
455168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        struct ufdt_node *target_node = NULL;
465168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
475168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        if (ufdt_node_tag(cur_node) == FDT_BEGIN_NODE) {
485168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju            target_node =
495168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                    ufdt_node_get_subnode_by_name(node_a, ufdt_node_name(cur_node));
505168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        } else {
515168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju            target_node =
525168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                    ufdt_node_get_property_by_name(node_a, ufdt_node_name(cur_node));
535168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        }
545168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
555168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        if (target_node == NULL) {
565168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju            result = false;
575168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        } else {
585168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju            result = ufdt_node_compare(target_node, cur_node, tree_a, tree_b);
595168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        }
605168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
615168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        if (!result) {
625168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju            break;
635168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        }
645168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    }
655168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
665168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    return result;
675168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju}
685168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
695168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju/*
705168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju * Method to compare two nodes with tag FDT_PROP. Also accounts for the cases where
715168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju * the property type is phandle.
725168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju */
735168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsarajustatic bool ufdt_compare_property(struct ufdt_node* node_final, struct ufdt_node* node_overlay,
745168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                                  struct ufdt* tree_final, struct ufdt* tree_overlay) {
755168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    if (ufdt_node_tag(node_final) == FDT_PROP) {
765168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        /* Return -1 if property names are differemt */
775168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        if (strcmp(ufdt_node_name(node_final), ufdt_node_name(node_overlay)) != 0)
785168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju            return false;
795168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
805168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        int length_data_final = 0, length_data_overlay = 0;
815168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        char *prop_data_final = ufdt_node_get_fdt_prop_data(node_final, &length_data_final);
825168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        char *prop_data_overlay = ufdt_node_get_fdt_prop_data(node_overlay,
835168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                                                              &length_data_overlay);
845168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
855168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        /* Confirm length for the property values are the same */
865168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        if (length_data_final != length_data_overlay) {
875168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju            return false;
885168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        }
895168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
905168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        if (((length_data_final == 0) && (length_data_overlay ==0)) ||
915168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju            (memcmp(prop_data_final, prop_data_overlay, length_data_final) == 0)) {
925168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju            // Return if the properties have same value.
935168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju            return true;
945168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        } else {
955168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju            /* check for the presence of phandles */
965168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju            for (int i = 0; i < length_data_final; i += sizeof(fdt32_t)) {
975168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                int offset_data_a = fdt32_to_cpu(
985168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                        *reinterpret_cast<fdt32_t *>(prop_data_final + i));
995168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                int offset_data_b = fdt32_to_cpu(
1005168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                        *reinterpret_cast<fdt32_t *>(prop_data_overlay + i));
1015168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                if (offset_data_a == offset_data_b) continue;
1025168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                /* If the offsets have phandles, they would have valid target nodes */
1035168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                struct ufdt_node * target_node_a = ufdt_get_node_by_phandle(tree_final,
1045168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                                                                            offset_data_a);
1055168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                struct ufdt_node * target_node_b = ufdt_get_node_by_phandle(tree_overlay,
1065168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                                                                            offset_data_b);
1075168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
1085168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                /*
1095168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                 * verify that the target nodes are valid and point to the same node.
1105168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                 */
1115168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                if ((target_node_a == NULL) || (target_node_b == NULL) ||
1125168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                    strcmp(ufdt_node_name(target_node_a),
1135168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                           ufdt_node_name(target_node_b)) != 0) {
1145168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                    return false;
1155168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                }
1165168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju            }
1175168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        }
1185168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    }
1195168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
1205168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    return true;
1215168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju}
1225168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
1235168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju/*
1245168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju * Checks if the ufdt tree rooted at node_b is a subtree of the tree rooted at
1255168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju * node_a.
1265168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju */
1275168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsarajustatic bool ufdt_node_compare(struct ufdt_node *node_final, struct ufdt_node *node_overlay,
1285168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                              struct ufdt * tree_final, struct ufdt * tree_overlay) {
1295168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    if (ufdt_node_tag(node_final) == FDT_PROP) {
1305168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        return ufdt_compare_property(node_final, node_overlay, tree_final, tree_overlay);
1315168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    }
1325168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
1335168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    return compare_child_nodes(node_final, node_overlay, tree_final, tree_overlay);
1345168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju}
1355168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
1365168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
1375168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju/*
1385168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju * Multiple fragments may fixup to the same node on the base device tree.
1395168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju * Combine these fragments for easier verification.
1405168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju */
1415168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsarajuvoid ufdt_combine_fixup(struct ufdt *tree, const char *fixup,
1425168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                        struct ufdt_node **prev_node, struct ufdt_node_pool *node_pool) {
1435168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    char *path, *prop_ptr, *offset_ptr;
1445168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    char path_buf[1024];
1455168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    char *path_mem = NULL;
1465168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    int result = 0;
1475168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
1485168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    size_t fixup_len = strlen(fixup) + 1;
1495168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    if (fixup_len > sizeof(path_buf)) {
1505168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        path_mem = static_cast<char *>(dto_malloc(fixup_len));
1515168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        path = path_mem;
1525168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    } else {
1535168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        path = path_buf;
1545168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    }
1555168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    dto_memcpy(path, fixup, fixup_len);
1565168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
1575168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    prop_ptr = dto_strchr(path, ':');
1585168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    if (prop_ptr == NULL) {
1595168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        dto_error("Missing property part in '%s'\n", path);
1605168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        goto fail;
1615168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    }
1625168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
1635168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    *prop_ptr = '\0';
1645168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    prop_ptr++;
1655168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
1665168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    offset_ptr = dto_strchr(prop_ptr, ':');
1675168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    if (offset_ptr == NULL) {
1685168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        dto_error("Missing offset part in '%s'\n", path);
1695168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        goto fail;
1705168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    }
1715168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
1725168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    *offset_ptr = '\0';
1735168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    offset_ptr++;
1745168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
1755168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    result = dto_strcmp(prop_ptr, "target");
1765168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    /* If the property being fixed up is not target, ignore and return */
1775168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    if (result == 0) {
1785168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        struct ufdt_node *target_node;
1795168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        target_node = ufdt_get_node_by_path(tree, path);
1805168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        if (target_node == NULL) {
1815168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju            dto_error("Path '%s' not found\n", path);
1825168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        } else {
1835168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju            /* The goal is to combine fragments that have a common target */
1845168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju            if (*prev_node != NULL) {
1855168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                ufdt_node_merge_into(*prev_node, target_node, node_pool);
1865168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju            } else {
1875168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                *prev_node = target_node;
1885168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju            }
1895168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        }
1905168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    }
1915168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
1925168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsarajufail:
1935168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    if (path_mem) {
1945168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        dto_free(path_mem);
1955168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    }
1965168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
1975168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    return;
1985168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju}
1995168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
2005168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju/*
201faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju * Creates a table of node paths to their corresponding phandles by walking
202faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju * through the 'symbols' node of the main device tree. The table would be
203faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju * used in combining overlay nodes that map to the same nodes in the
204faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju * main device tree.
2055168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju */
206faecc11b175869e12cc387c14c395341e480f12aHridya Valsarajuvoid create_path_phandle_map(std::unordered_map<uint32_t, std::string>* phandle_path_map,
207faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju                             struct ufdt* main_tree) {
208faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju    int len = 0;
209faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju    struct ufdt_node *main_symbols_node =
210faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju            ufdt_get_node_by_path(main_tree, "/__symbols__");
211faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju    if (!main_symbols_node) {
212faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju        dto_error("No node __symbols__ in main dtb.\n");
213faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju        return;
2145168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    }
2155168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
216faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju    struct ufdt_node **it = nullptr;
217faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju    for_each_prop(it, main_symbols_node) {
218faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju        const char* symbol_path = ufdt_node_get_fdt_prop_data(*it, &len);
219faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju        struct ufdt_node* symbol_node = ufdt_get_node_by_path(main_tree, symbol_path);
220faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju        uint32_t phandle = ufdt_node_get_phandle(symbol_node);
221faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju        (*phandle_path_map)[phandle] = std::string(symbol_path);
222faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju    }
2235168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju}
2245168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
2255168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju/*
226faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju * Recursively checks whether a node from another overlay fragment had overlaid the
227faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju * target node and if so merges the node into the previous node.
2285168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju */
229faecc11b175869e12cc387c14c395341e480f12aHridya Valsarajustatic void combine_overlay_node(std::unordered_map<std::string,
230faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju                                 struct ufdt_node*>* path_node_map,
231faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju                                 std::string path,
232faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju                                 struct ufdt_node* node,
233faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju                                 struct ufdt_node_pool* pool) {
234faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju    struct ufdt_node **it = nullptr;
235faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju    for_each_node(it, node) {
236faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju        //skips properties
237faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju        if (ufdt_node_tag(*it) == FDT_BEGIN_NODE) {
238faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju            combine_overlay_node(path_node_map, path + "/" + ufdt_node_name(*it), *it, pool);
239faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju        }
2405168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    }
2415168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
242faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju    if (path_node_map->find(path) != path_node_map->end()) {
243faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju        ufdt_node_merge_into((*path_node_map)[path], node, pool);
244faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju    } else {
245faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju        //This is the first node overlaying the target node, add the same to the
246faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju        //table.
247faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju        (*path_node_map)[path] = node;
2485168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    }
2495168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju}
250faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju
2515168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju/* END of doing fixup in the overlay ufdt. */
2525168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
2535168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsarajustatic bool ufdt_verify_overlay_node(struct ufdt_node *target_node,
2545168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                                     struct ufdt_node *overlay_node,
2555168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                                     struct ufdt * target_tree,
2565168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                                     struct ufdt * overlay_tree) {
2575168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    return ufdt_node_compare(target_node, overlay_node, target_tree, overlay_tree);
2585168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju}
2595168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
2605168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju/*
2615168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju * verify one overlay fragment (subtree).
2625168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju */
2635168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsarajustatic int ufdt_verify_fragment(struct ufdt *tree,
2645168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                                struct ufdt *overlay_tree,
2655168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                                struct ufdt_node *frag_node) {
2665168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    struct ufdt_node *target_node = NULL;
2675168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    struct ufdt_node *overlay_node = NULL;
268c0957f2fa7c1b47b61044b3af3d7d82ca44e0680Hridya Valsaraju    enum overlay_result target_search_result = ufdt_overlay_get_target(tree, frag_node,
269c0957f2fa7c1b47b61044b3af3d7d82ca44e0680Hridya Valsaraju                                                                       &target_node);
2705168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    if (target_node == NULL) {
271c0957f2fa7c1b47b61044b3af3d7d82ca44e0680Hridya Valsaraju        return target_search_result;
2725168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    }
2735168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
2745168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    overlay_node = ufdt_node_get_node_by_path(frag_node, "__overlay__");
2755168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    if (overlay_node == NULL) {
2765168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        dto_error("missing __overlay__ sub-node\n");
2775168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        return OVERLAY_RESULT_MISSING_OVERLAY;
2785168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    }
2795168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
2805168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    bool result = ufdt_verify_overlay_node(target_node, overlay_node, tree, overlay_tree);
2815168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
2825168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    if (!result) {
2835168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        dto_error("failed to verify overlay node %s to target %s\n",
2845168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                  ufdt_node_name(overlay_node), ufdt_node_name(target_node));
2855168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        return OVERLAY_RESULT_VERIFY_FAIL;
2865168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    }
2875168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
2885168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    return OVERLAY_RESULT_OK;
2895168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju}
2905168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
2915168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju/*
2925168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju * verify each fragment in overlay.
2935168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju */
2945168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsarajustatic int ufdt_overlay_verify_fragments(struct ufdt *final_tree,
2955168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                                         struct ufdt *overlay_tree) {
2965168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    enum overlay_result err;
2975168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    struct ufdt_node **it;
2985168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    for_each_node(it, overlay_tree->root) {
2995168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        err = static_cast<enum overlay_result>(ufdt_verify_fragment(final_tree, overlay_tree,
3005168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju                                                                    *it));
3015168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        if (err == OVERLAY_RESULT_VERIFY_FAIL) {
3025168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju            return -1;
3035168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        }
3045168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    }
3055168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    return 0;
3065168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju}
3075168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
3084c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju/*
3094c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju * Examine target nodes for fragments in all overlays and combine ones with the
3104c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju * same target.
3114c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju */
312faecc11b175869e12cc387c14c395341e480f12aHridya Valsarajustatic void ufdt_overlay_combine_common_nodes(struct ufdt** overlay_trees,
313faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju                                              size_t overlay_count,
314faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju                                              struct ufdt* final_tree,
315faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju                                              struct ufdt_node_pool* pool
316faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju                                             ) {
317faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju    std::unordered_map<std::string, struct ufdt_node*> path_node_map;
318faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju    std::unordered_map<uint32_t, std::string> phandle_path_map;
319faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju
320faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju    create_path_phandle_map(&phandle_path_map, final_tree);
321faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju
322faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju    struct ufdt_node **it = nullptr;
3234c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    for (size_t i = 0; i < overlay_count; i++) {
324faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju        for_each_node(it, overlay_trees[i]->root) {
325faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju            uint32_t target = 0;
3264c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju            const void* val = ufdt_node_get_fdt_prop_data_by_name(*it, "target", NULL);
3274c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju            if (val) {
3284c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju                dto_memcpy(&target, val, sizeof(target));
3294c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju                target = fdt32_to_cpu(target);
330faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju                std::string path = phandle_path_map[target];
331faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju                struct ufdt_node* overlay_node = ufdt_node_get_node_by_path(*it, "__overlay__");
332faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju                if (overlay_node != nullptr) {
333faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju                    combine_overlay_node(&path_node_map, path, overlay_node, pool);
3344c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju                }
3354c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju            }
3364c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju        }
3374c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    }
3384c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju}
3394c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju
3404c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju/*
3414c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju * Makes sure that all phandles in the overlays are unique since they will be
3424c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju * combined before verification.
3434c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju */
3444c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsarajuint ufdt_resolve_duplicate_phandles(ufdt** overlay_tree, size_t overlay_count) {
3454c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju  size_t phandle_offset = 0;
3464c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju  for (size_t i = 0; i < overlay_count; i++) {
3474c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju        ufdt_try_increase_phandle(overlay_tree[i], phandle_offset);
3484c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju        if (ufdt_overlay_do_local_fixups(overlay_tree[i], phandle_offset) < 0) {
3494c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju            return -1;
3504c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju        }
3514c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju        phandle_offset = ufdt_get_max_phandle(overlay_tree[i]);
3524c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju  }
3534c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju
3544c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju  return 0;
3554c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju}
3564c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju
3574c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju/*
3584c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju * Combines all overlays into a single tree at overlay_trees[0]
3594c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju */
3604c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsarajuint ufdt_combine_all_overlays(struct ufdt** overlay_trees, size_t overlay_count,
3614c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju                              struct ufdt* final_tree, struct ufdt_node_pool* pool) {
3624c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    struct ufdt* combined_overlay_tree = nullptr;
3634c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju
3644c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    if (!overlay_trees || !overlay_count || !final_tree || !pool) {
3655168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        return -1;
3665168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    }
3675168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
3684c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    /*
3694c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju     * If there are duplicate phandles amongst the overlays, replace them with
3704c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju     * unique ones.
3714c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju     */
3724c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    if (ufdt_resolve_duplicate_phandles(overlay_trees, overlay_count) < 0) {
3735168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        return -1;
3745168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    }
3755168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
3764c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    /*
377faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju     * For each overlay, perform fixup for each fragment.
3784c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju     */
3794c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    for (size_t i = 0; i < overlay_count; i++) {
380faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju        if (ufdt_overlay_do_fixups(final_tree, overlay_trees[i]) < 0) {
3814c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju            dto_error("failed to perform fixups in overlay\n");
3824c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju            return -1;
3834c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju        }
3844c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    }
3854c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju
3864c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    /*
3874c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju     * Iterate through each overlay and combine all nodes with the same target
3884c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju     * node.
3894c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju     */
390faecc11b175869e12cc387c14c395341e480f12aHridya Valsaraju    ufdt_overlay_combine_common_nodes(overlay_trees, overlay_count, final_tree, pool);
3914c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju
3924c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    /*
3934c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju     * Combine all overlays into the tree at overlay_trees[0] for easy
3944c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju     * verification.
3954c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju     */
3964c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    combined_overlay_tree = overlay_trees[0];
3974c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    struct ufdt_node* combined_root_node = combined_overlay_tree->root;
3984c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju
3994c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    for (size_t i = 1; i < overlay_count; i++) {
4004c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju        struct ufdt_node** it = nullptr;
4014c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju        struct ufdt_node* root_node = overlay_trees[i]->root;
4024c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju        for_each_node(it, root_node) {
4034c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju            ufdt_node_add_child(combined_root_node, *it);
4044c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju        }
4054c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju        ((struct ufdt_node_fdt_node *)root_node)->child = nullptr;
4064c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    }
4074c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju
4084c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    /*
4094c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju     * Rebuild the phandle_table for the combined tree.
4104c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju     */
4114c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    combined_overlay_tree->phandle_table = build_phandle_table(combined_overlay_tree);
4124c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju
4135168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    return 0;
4145168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju}
4155168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
4165168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsarajuint ufdt_verify_dtbo(struct fdt_header* final_fdt_header,
4174c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju                     size_t final_fdt_size, void** overlay_arr,
4184c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju                     size_t overlay_count) {
4195168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    const size_t min_fdt_size = 8;
4205168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    struct ufdt_node_pool pool;
4215168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    struct ufdt* final_tree = nullptr;
4224c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    struct ufdt** overlay_trees = nullptr;
4235168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    int result = 1;
4245168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
4255168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    if (final_fdt_header == NULL) {
4265168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        goto fail;
4275168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    }
4285168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
4294c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    if (final_fdt_size < min_fdt_size || final_fdt_size != fdt_totalsize(final_fdt_header)) {
4304c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju        dto_error("Bad fdt size!\n");
4315168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        goto fail;
4325168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    }
4335168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
4344c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    ufdt_node_pool_construct(&pool);
4354c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    final_tree = ufdt_from_fdt(final_fdt_header, final_fdt_size, &pool);
4364c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju
4374c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    overlay_trees = new ufdt*[overlay_count];
4384c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    for (size_t i = 0; i < overlay_count; i++) {
4394c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju        size_t fdt_size = fdt_totalsize(overlay_arr[i]);
4404c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju        overlay_trees[i] = ufdt_from_fdt(overlay_arr[i], fdt_size, &pool);
4414c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    }
4424c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju
4434c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    if (ufdt_combine_all_overlays(overlay_trees, overlay_count, final_tree, &pool) < 0) {
4444c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju        dto_error("Unable to combine overlays\n");
4455168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        goto fail;
4465168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    }
4474c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    if (ufdt_overlay_verify_fragments(final_tree, overlay_trees[0]) < 0) {
4484c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju        dto_error("Failed to verify overlay application\n");
4495168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju        goto fail;
4504c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    } else {
4514c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju        result = 0;
4525168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    }
4535168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
4544c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsarajufail:
4554c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    if (overlay_trees) {
4564c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju        for (size_t i = 0; i < overlay_count; i++) {
4574c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju            ufdt_destruct(overlay_trees[i], &pool);
4584c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju        }
4594c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju        delete[] overlay_trees;
4604c7735ac0173b71aceb489470fca15b56e64c4d4Hridya Valsaraju    }
4615168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju
4625168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    ufdt_destruct(final_tree, &pool);
4635168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    ufdt_node_pool_destruct(&pool);
4645168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju    return result;
4655168cab4cb068dc964e6354167bc857a0e948ff7Hridya Valsaraju}
466