fdt.cc (d6d16831c555d9c626ed2b49977241abd0d5f97e) | fdt.cc (21d5d37ba4c0131d6c141695366e266e32cc3bc1) |
---|---|
1/*- 2 * Copyright (c) 2013 David Chisnall 3 * All rights reserved. 4 * 5 * This software was developed by SRI International and the University of 6 * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) 7 * ("CTSRD"), as part of the DARPA CRASH research programme. 8 * --- 155 unchanged lines hidden (view full) --- 164 type = STRING_LIST; 165 } 166 return; 167 } 168 } 169 type = BINARY; 170} 171 | 1/*- 2 * Copyright (c) 2013 David Chisnall 3 * All rights reserved. 4 * 5 * This software was developed by SRI International and the University of 6 * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) 7 * ("CTSRD"), as part of the DARPA CRASH research programme. 8 * --- 155 unchanged lines hidden (view full) --- 164 type = STRING_LIST; 165 } 166 return; 167 } 168 } 169 type = BINARY; 170} 171 |
172size_t 173property_value::size() 174{ 175 if (!byte_data.empty()) 176 { 177 return byte_data.size(); 178 } 179 return string_data.size() + 1; 180} 181 |
|
172void 173property_value::write_as_string(FILE *file) 174{ 175 putc('"', file); 176 if (byte_data.empty()) 177 { 178 fputs(string_data.c_str(), file); 179 } --- 101 unchanged lines hidden (view full) --- 281 { 282 if (cell_size != 32) 283 { 284 input.parse_error("reference only permitted in 32-bit arrays"); 285 valid = false; 286 return; 287 } 288 input.next_token(); | 182void 183property_value::write_as_string(FILE *file) 184{ 185 putc('"', file); 186 if (byte_data.empty()) 187 { 188 fputs(string_data.c_str(), file); 189 } --- 101 unchanged lines hidden (view full) --- 291 { 292 if (cell_size != 32) 293 { 294 input.parse_error("reference only permitted in 32-bit arrays"); 295 valid = false; 296 return; 297 } 298 input.next_token(); |
289 bool isPath = false; | |
290 string referenced; 291 if (!input.consume('{')) 292 { 293 referenced = input.parse_node_name(); 294 } 295 else 296 { 297 referenced = input.parse_to('}'); 298 input.consume('}'); | 299 string referenced; 300 if (!input.consume('{')) 301 { 302 referenced = input.parse_node_name(); 303 } 304 else 305 { 306 referenced = input.parse_to('}'); 307 input.consume('}'); |
299 isPath = true; | |
300 } 301 if (referenced.empty()) 302 { 303 input.parse_error("Expected node name"); 304 valid = false; 305 return; 306 } 307 input.next_token(); --- 342 unchanged lines hidden (view full) --- 650 putc(',', file); 651 putc(' ', file); 652 } 653 } 654 } 655 fputs(";\n", file); 656} 657 | 308 } 309 if (referenced.empty()) 310 { 311 input.parse_error("Expected node name"); 312 valid = false; 313 return; 314 } 315 input.next_token(); --- 342 unchanged lines hidden (view full) --- 658 putc(',', file); 659 putc(' ', file); 660 } 661 } 662 } 663 fputs(";\n", file); 664} 665 |
666size_t 667property::offset_of_value(property_value &val) 668{ 669 size_t off = 0; 670 for (auto &v : values) 671 { 672 if (&v == &val) 673 { 674 return off; 675 } 676 off += v.size(); 677 } 678 return -1; 679} 680 |
|
658string 659node::parse_name(text_input_buffer &input, bool &is_property, const char *error) 660{ 661 if (!valid) 662 { 663 return string(); 664 } 665 input.next_token(); --- 93 unchanged lines hidden (view full) --- 759 break; 760 } 761 } 762 fprintf(stderr, "Failed to read token from structs table while parsing node.\n"); 763 valid = false; 764 return; 765} 766 | 681string 682node::parse_name(text_input_buffer &input, bool &is_property, const char *error) 683{ 684 if (!valid) 685 { 686 return string(); 687 } 688 input.next_token(); --- 93 unchanged lines hidden (view full) --- 782 break; 783 } 784 } 785 fprintf(stderr, "Failed to read token from structs table while parsing node.\n"); 786 valid = false; 787 return; 788} 789 |
790 791node::node(const string &n, 792 const std::vector<property_ptr> &p) 793 : name(n) 794{ 795 props.insert(props.begin(), p.begin(), p.end()); 796} 797 798node_ptr node::create_special_node(const string &name, 799 const std::vector<property_ptr> &props) 800{ 801 node_ptr n(new node(name, props)); 802 return n; 803} 804 |
|
767node::node(text_input_buffer &input, 768 string &&n, 769 std::unordered_set<string> &&l, 770 string &&a, 771 define_map *defines) 772 : labels(l), name(n), unit_address(a), valid(true) 773{ 774 if (!input.consume('{')) --- 343 unchanged lines hidden (view full) --- 1118 fprintf(stderr, "Label not unique: %s. References to this label will not be resolved.\n", name.c_str()); 1119 } 1120 } 1121 } 1122 for (auto &c : n->child_nodes()) 1123 { 1124 collect_names_recursive(c, path); 1125 } | 805node::node(text_input_buffer &input, 806 string &&n, 807 std::unordered_set<string> &&l, 808 string &&a, 809 define_map *defines) 810 : labels(l), name(n), unit_address(a), valid(true) 811{ 812 if (!input.consume('{')) --- 343 unchanged lines hidden (view full) --- 1156 fprintf(stderr, "Label not unique: %s. References to this label will not be resolved.\n", name.c_str()); 1157 } 1158 } 1159 } 1160 for (auto &c : n->child_nodes()) 1161 { 1162 collect_names_recursive(c, path); 1163 } |
1126 path.pop_back(); | |
1127 // Now we collect the phandles and properties that reference 1128 // other nodes. 1129 for (auto &p : n->properties()) 1130 { 1131 for (auto &v : *p) 1132 { 1133 if (v.is_phandle()) 1134 { | 1164 // Now we collect the phandles and properties that reference 1165 // other nodes. 1166 for (auto &p : n->properties()) 1167 { 1168 for (auto &v : *p) 1169 { 1170 if (v.is_phandle()) 1171 { |
1135 phandles.push_back(&v); | 1172 fixups.push_back({path, p, v}); |
1136 } 1137 if (v.is_cross_reference()) 1138 { 1139 cross_references.push_back(&v); 1140 } 1141 } 1142 if ((p->get_key() == "phandle") || 1143 (p->get_key() == "linux,phandle")) --- 5 unchanged lines hidden (view full) --- 1149 } 1150 else 1151 { 1152 uint32_t phandle = p->begin()->get_as_uint32(); 1153 used_phandles.insert(std::make_pair(phandle, n.get())); 1154 } 1155 } 1156 } | 1173 } 1174 if (v.is_cross_reference()) 1175 { 1176 cross_references.push_back(&v); 1177 } 1178 } 1179 if ((p->get_key() == "phandle") || 1180 (p->get_key() == "linux,phandle")) --- 5 unchanged lines hidden (view full) --- 1186 } 1187 else 1188 { 1189 uint32_t phandle = p->begin()->get_as_uint32(); 1190 used_phandles.insert(std::make_pair(phandle, n.get())); 1191 } 1192 } 1193 } |
1194 path.pop_back(); |
|
1157} 1158 1159void 1160device_tree::collect_names() 1161{ 1162 node_path p; 1163 node_names.clear(); 1164 node_paths.clear(); 1165 cross_references.clear(); | 1195} 1196 1197void 1198device_tree::collect_names() 1199{ 1200 node_path p; 1201 node_names.clear(); 1202 node_paths.clear(); 1203 cross_references.clear(); |
1166 phandles.clear(); | 1204 fixups.clear(); |
1167 collect_names_recursive(root, p); 1168} 1169 1170void 1171device_tree::resolve_cross_references() 1172{ 1173 for (auto *pv : cross_references) 1174 { --- 11 unchanged lines hidden (view full) --- 1186 { 1187 pv->byte_data.push_back('@'); 1188 push_string(pv->byte_data, p->second); 1189 pv->byte_data.push_back(0); 1190 } 1191 } 1192 } 1193 } | 1205 collect_names_recursive(root, p); 1206} 1207 1208void 1209device_tree::resolve_cross_references() 1210{ 1211 for (auto *pv : cross_references) 1212 { --- 11 unchanged lines hidden (view full) --- 1224 { 1225 pv->byte_data.push_back('@'); 1226 push_string(pv->byte_data, p->second); 1227 pv->byte_data.push_back(0); 1228 } 1229 } 1230 } 1231 } |
1194 std::unordered_set<property_value*> phandle_set; 1195 for (auto &i : phandles) | 1232 std::unordered_map<property_value*, fixup&> phandle_set; 1233 for (auto &i : fixups) |
1196 { | 1234 { |
1197 phandle_set.insert(i); | 1235 phandle_set.insert({&i.val, i}); |
1198 } | 1236 } |
1199 std::vector<property_value*> sorted_phandles; | 1237 std::vector<std::reference_wrapper<fixup>> sorted_phandles; |
1200 root->visit([&](node &n) { 1201 for (auto &p : n.properties()) 1202 { 1203 for (auto &v : *p) 1204 { | 1238 root->visit([&](node &n) { 1239 for (auto &p : n.properties()) 1240 { 1241 for (auto &v : *p) 1242 { |
1205 if (phandle_set.count(&v)) | 1243 auto i = phandle_set.find(&v); 1244 if (i != phandle_set.end()) |
1206 { | 1245 { |
1207 sorted_phandles.push_back(&v); | 1246 sorted_phandles.push_back(i->second); |
1208 } 1209 } 1210 } 1211 }); | 1247 } 1248 } 1249 } 1250 }); |
1212 assert(sorted_phandles.size() == phandles.size()); | 1251 assert(sorted_phandles.size() == fixups.size()); |
1213 1214 uint32_t phandle = 1; 1215 for (auto &i : sorted_phandles) 1216 { | 1252 1253 uint32_t phandle = 1; 1254 for (auto &i : sorted_phandles) 1255 { |
1217 string target_name = i->string_data; | 1256 string target_name = i.get().val.string_data; |
1218 node *target = nullptr; 1219 string possible; 1220 // If the node name is a path, then look it up by following the path, 1221 // otherwise jump directly to the named node. 1222 if (target_name[0] == '/') 1223 { | 1257 node *target = nullptr; 1258 string possible; 1259 // If the node name is a path, then look it up by following the path, 1260 // otherwise jump directly to the named node. 1261 if (target_name[0] == '/') 1262 { |
1224 std::string path; | 1263 string path; |
1225 target = root.get(); 1226 std::istringstream ss(target_name); 1227 string path_element; 1228 // Read the leading / 1229 std::getline(ss, path_element, '/'); 1230 // Iterate over path elements 1231 while (!ss.eof()) 1232 { --- 38 unchanged lines hidden (view full) --- 1271 } 1272 } 1273 else 1274 { 1275 target = node_names[target_name]; 1276 } 1277 if (target == nullptr) 1278 { | 1264 target = root.get(); 1265 std::istringstream ss(target_name); 1266 string path_element; 1267 // Read the leading / 1268 std::getline(ss, path_element, '/'); 1269 // Iterate over path elements 1270 while (!ss.eof()) 1271 { --- 38 unchanged lines hidden (view full) --- 1310 } 1311 } 1312 else 1313 { 1314 target = node_names[target_name]; 1315 } 1316 if (target == nullptr) 1317 { |
1279 fprintf(stderr, "Failed to find node with label: %s\n", target_name.c_str()); 1280 if (possible != string()) | 1318 if (is_plugin) |
1281 { | 1319 { |
1282 fprintf(stderr, "Possible intended match: %s\n", possible.c_str()); | 1320 unresolved_fixups.push_back(i); 1321 continue; |
1283 } | 1322 } |
1284 valid = 0; 1285 return; | 1323 else 1324 { 1325 fprintf(stderr, "Failed to find node with label: %s\n", target_name.c_str()); 1326 if (possible != string()) 1327 { 1328 fprintf(stderr, "Possible intended match: %s\n", possible.c_str()); 1329 } 1330 valid = 0; 1331 return; 1332 } |
1286 } 1287 // If there is an existing phandle, use it 1288 property_ptr p = target->get_property("phandle"); 1289 if (p == 0) 1290 { 1291 p = target->get_property("linux,phandle"); 1292 } 1293 if (p == 0) --- 23 unchanged lines hidden (view full) --- 1317 } 1318 if (phandle_node_name == BOTH || phandle_node_name == EPAPR) 1319 { 1320 p.reset(new property("phandle")); 1321 p->add_value(v); 1322 target->add_property(p); 1323 } 1324 } | 1333 } 1334 // If there is an existing phandle, use it 1335 property_ptr p = target->get_property("phandle"); 1336 if (p == 0) 1337 { 1338 p = target->get_property("linux,phandle"); 1339 } 1340 if (p == 0) --- 23 unchanged lines hidden (view full) --- 1364 } 1365 if (phandle_node_name == BOTH || phandle_node_name == EPAPR) 1366 { 1367 p.reset(new property("phandle")); 1368 p->add_value(v); 1369 target->add_property(p); 1370 } 1371 } |
1325 p->begin()->push_to_buffer(i->byte_data); 1326 assert(i->byte_data.size() == 4); | 1372 p->begin()->push_to_buffer(i.get().val.byte_data); 1373 assert(i.get().val.byte_data.size() == 4); |
1327 } 1328} 1329 1330 1331void 1332device_tree::parse_file(text_input_buffer &input, 1333 std::vector<node_ptr> &roots, 1334 bool &read_header) 1335{ 1336 input.next_token(); 1337 // Read the header 1338 if (input.consume("/dts-v1/;")) 1339 { 1340 read_header = true; 1341 } 1342 input.next_token(); | 1374 } 1375} 1376 1377 1378void 1379device_tree::parse_file(text_input_buffer &input, 1380 std::vector<node_ptr> &roots, 1381 bool &read_header) 1382{ 1383 input.next_token(); 1384 // Read the header 1385 if (input.consume("/dts-v1/;")) 1386 { 1387 read_header = true; 1388 } 1389 input.next_token(); |
1390 if (input.consume("/plugin/;")) 1391 { 1392 is_plugin = true; 1393 } |
|
1343 input.next_token(); 1344 if (!read_header) 1345 { 1346 input.parse_error("Expected /dts-v1/; version string"); 1347 } 1348 // Read any memory reservations 1349 while (input.consume("/memreserve/")) 1350 { --- 211 unchanged lines hidden (view full) --- 1562 { 1563 fprintf(stderr, "Expected FDT_END token after parsing root node.\n"); 1564 valid = false; 1565 return; 1566 } 1567 valid = (root != 0); 1568} 1569 | 1394 input.next_token(); 1395 if (!read_header) 1396 { 1397 input.parse_error("Expected /dts-v1/; version string"); 1398 } 1399 // Read any memory reservations 1400 while (input.consume("/memreserve/")) 1401 { --- 211 unchanged lines hidden (view full) --- 1613 { 1614 fprintf(stderr, "Expected FDT_END token after parsing root node.\n"); 1615 valid = false; 1616 return; 1617 } 1618 valid = (root != 0); 1619} 1620 |
1621string 1622device_tree::node_path::to_string() const 1623{ 1624 string path; 1625 auto p = begin(); 1626 auto pe = end(); 1627 if ((p == pe) || (p+1 == pe)) 1628 { 1629 return string("/"); 1630 } 1631 // Skip the first name in the path. It's always "", and implicitly / 1632 for (++p ; p!=pe ; ++p) 1633 { 1634 path += '/'; 1635 path += p->first; 1636 if (!(p->second.empty())) 1637 { 1638 path += '@'; 1639 path += p->second; 1640 } 1641 } 1642 return path; 1643} 1644 |
|
1570void 1571device_tree::parse_dts(const string &fn, FILE *depfile) 1572{ 1573 auto in = input_buffer::buffer_for_file(fn); 1574 if (!in) 1575 { 1576 valid = false; 1577 return; --- 48 unchanged lines hidden (view full) --- 1626 existing->second->merge_node(std::move(node)); 1627 } 1628 } 1629 } 1630 } 1631 } 1632 collect_names(); 1633 resolve_cross_references(); | 1645void 1646device_tree::parse_dts(const string &fn, FILE *depfile) 1647{ 1648 auto in = input_buffer::buffer_for_file(fn); 1649 if (!in) 1650 { 1651 valid = false; 1652 return; --- 48 unchanged lines hidden (view full) --- 1701 existing->second->merge_node(std::move(node)); 1702 } 1703 } 1704 } 1705 } 1706 } 1707 collect_names(); 1708 resolve_cross_references(); |
1709 if (write_symbols) 1710 { 1711 std::vector<property_ptr> symbols; 1712 // Create a symbol table. Each label in this device tree may be 1713 // referenced by other plugins, so we create a __symbols__ node inside 1714 // the root that contains mappings (properties) from label names to 1715 // paths. 1716 for (auto &s : node_paths) 1717 { 1718 property_value v; 1719 v.string_data = s.second.to_string(); 1720 v.type = property_value::STRING; 1721 string name = s.first; 1722 auto prop = std::make_shared<property>(std::move(name)); 1723 prop->add_value(v); 1724 symbols.push_back(prop); 1725 } 1726 root->add_child(node::create_special_node("__symbols__", symbols)); 1727 // If this is a plugin, then we also need to create two extra nodes. 1728 // Internal phandles will need to be renumbered to avoid conflicts with 1729 // already-loaded nodes and external references will need to be 1730 // resolved. 1731 if (is_plugin) 1732 { 1733 // Create the fixups entry. This is of the form: 1734 // {target} = {path}:{property name}:{offset} 1735 auto create_fixup_entry = [&](fixup &i, string target) 1736 { 1737 string value = i.path.to_string(); 1738 value += ':'; 1739 value += i.prop->get_key(); 1740 value += ':'; 1741 value += std::to_string(i.prop->offset_of_value(i.val)); 1742 property_value v; 1743 v.string_data = value; 1744 v.type = property_value::STRING; 1745 auto prop = std::make_shared<property>(std::move(target)); 1746 prop->add_value(v); 1747 return prop; 1748 }; 1749 // If we have any unresolved phandle references in this plugin, 1750 // then we must update them to 0xdeadbeef and leave a property in 1751 // the /__fixups__ node whose key is the label and whose value is 1752 // as described above. 1753 if (!unresolved_fixups.empty()) 1754 { 1755 symbols.clear(); 1756 for (auto &i : unresolved_fixups) 1757 { 1758 auto &val = i.get().val; 1759 symbols.push_back(create_fixup_entry(i, val.string_data)); 1760 val.byte_data.push_back(0xde); 1761 val.byte_data.push_back(0xad); 1762 val.byte_data.push_back(0xbe); 1763 val.byte_data.push_back(0xef); 1764 val.type = property_value::BINARY; 1765 } 1766 root->add_child(node::create_special_node("__fixups__", symbols)); 1767 } 1768 symbols.clear(); 1769 // If we have any resolved phandle references in this plugin, then 1770 // we must leave a property in the /__local_fixups__ node whose key 1771 // is 'fixup' and whose value is as described above. 1772 for (auto &i : fixups) 1773 { 1774 if (!i.val.is_phandle()) 1775 { 1776 continue; 1777 } 1778 symbols.push_back(create_fixup_entry(i, "fixup")); 1779 } 1780 // We've iterated over all fixups, but only emit the 1781 // __local_fixups__ if we found some that were resolved internally. 1782 if (!symbols.empty()) 1783 { 1784 root->add_child(node::create_special_node("__local_fixups__", symbols)); 1785 } 1786 } 1787 } |
|
1634} 1635 1636bool device_tree::parse_define(const char *def) 1637{ 1638 const char *val = strchr(def, '='); 1639 if (!val) 1640 { 1641 if (strlen(def) != 0) --- 6 unchanged lines hidden (view full) --- 1648 } 1649 string name(def, val-def); 1650 string name_copy = name; 1651 val++; 1652 std::unique_ptr<input_buffer> raw(new input_buffer(val, strlen(val))); 1653 text_input_buffer in(std::move(raw), 1654 std::unordered_set<string>(), 1655 std::vector<string>(), | 1788} 1789 1790bool device_tree::parse_define(const char *def) 1791{ 1792 const char *val = strchr(def, '='); 1793 if (!val) 1794 { 1795 if (strlen(def) != 0) --- 6 unchanged lines hidden (view full) --- 1802 } 1803 string name(def, val-def); 1804 string name_copy = name; 1805 val++; 1806 std::unique_ptr<input_buffer> raw(new input_buffer(val, strlen(val))); 1807 text_input_buffer in(std::move(raw), 1808 std::unordered_set<string>(), 1809 std::vector<string>(), |
1656 std::string(), | 1810 string(), |
1657 nullptr); 1658 property_ptr p = property::parse(in, std::move(name_copy), string_set(), false); 1659 if (p) 1660 defines[name] = p; 1661 return (bool)p; 1662} 1663 1664} // namespace fdt 1665 1666} // namespace dtc 1667 | 1811 nullptr); 1812 property_ptr p = property::parse(in, std::move(name_copy), string_set(), false); 1813 if (p) 1814 defines[name] = p; 1815 return (bool)p; 1816} 1817 1818} // namespace fdt 1819 1820} // namespace dtc 1821 |