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