]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/dtc/fdt.cc
MFC r326276:
[FreeBSD/FreeBSD.git] / usr.bin / dtc / fdt.cc
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2013 David Chisnall
5  * All rights reserved.
6  *
7  * This software was developed by SRI International and the University of
8  * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
9  * ("CTSRD"), as part of the DARPA CRASH research programme.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * $FreeBSD$
33  */
34
35 #define __STDC_LIMIT_MACROS 1
36
37 #include "fdt.hh"
38 #include "dtb.hh"
39
40 #include <algorithm>
41 #include <sstream>
42
43 #include <ctype.h>
44 #include <fcntl.h>
45 #include <inttypes.h>
46 #include <libgen.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <unistd.h>
50 #include <sys/types.h>
51 #include <sys/stat.h>
52 #include <errno.h>
53
54 using std::string;
55
56 namespace dtc
57 {
58
59 namespace fdt
60 {
61
62 uint32_t
63 property_value::get_as_uint32()
64 {
65         if (byte_data.size() != 4)
66         {
67                 return 0;
68         }
69         uint32_t v = 0;
70         v &= byte_data[0] << 24;
71         v &= byte_data[1] << 16;
72         v &= byte_data[2] << 8;
73         v &= byte_data[3] << 0;
74         return v;
75 }
76
77 void
78 property_value::push_to_buffer(byte_buffer &buffer)
79 {
80         if (!byte_data.empty())
81         {
82                 buffer.insert(buffer.end(), byte_data.begin(), byte_data.end());
83         }
84         else
85         {
86                 push_string(buffer, string_data, true);
87                 // Trailing nul
88                 buffer.push_back(0);
89         }
90 }
91
92 void
93 property_value::write_dts(FILE *file)
94 {
95         resolve_type();
96         switch (type)
97         {
98                 default:
99                         assert(0 && "Invalid type");
100                 case STRING:
101                 case STRING_LIST:
102                 case CROSS_REFERENCE:
103                         write_as_string(file);
104                         break;
105                 case PHANDLE:
106                         write_as_cells(file);
107                         break;
108                 case BINARY:
109                         if (byte_data.size() % 4 == 0)
110                         {
111                                 write_as_cells(file);
112                                 break;
113                         }
114                         write_as_bytes(file);
115                         break;
116         }
117 }
118
119 void
120 property_value::resolve_type()
121 {
122         if (type != UNKNOWN)
123         {
124                 return;
125         }
126         if (byte_data.empty())
127         {
128                 type = STRING;
129                 return;
130         }
131         if (byte_data.back() == 0)
132         {
133                 bool is_all_printable = true;
134                 int nuls = 0;
135                 int bytes = 0;
136                 bool lastWasNull = false;
137                 for (auto i : byte_data)
138                 {
139                         bytes++;
140                         is_all_printable &= (i == '\0') || isprint(i);
141                         if (i == '\0')
142                         {
143                                 // If there are two nulls in a row, then we're probably binary.
144                                 if (lastWasNull)
145                                 {
146                                         type = BINARY;
147                                         return;
148                                 }
149                                 nuls++;
150                                 lastWasNull = true;
151                         }
152                         else
153                         {
154                                 lastWasNull = false;
155                         }
156                         if (!is_all_printable)
157                         {
158                                 break;
159                         }
160                 }
161                 if ((is_all_printable && (bytes > nuls)) || bytes == 0)
162                 {
163                         type = STRING;
164                         if (nuls > 1)
165                         {
166                                 type = STRING_LIST;
167                         }
168                         return;
169                 }
170         }
171         type = BINARY;
172 }
173
174 size_t
175 property_value::size()
176 {
177         if (!byte_data.empty())
178         {
179                 return byte_data.size();
180         }
181         return string_data.size() + 1;
182 }
183
184 void
185 property_value::write_as_string(FILE *file)
186 {
187         putc('"', file);
188         if (byte_data.empty())
189         {
190                 fputs(string_data.c_str(), file);
191         }
192         else
193         {
194                 bool hasNull = (byte_data.back() == '\0');
195                 // Remove trailing null bytes from the string before printing as dts.
196                 if (hasNull)
197                 {
198                         byte_data.pop_back();
199                 }
200                 for (auto i : byte_data)
201                 {
202                         // FIXME Escape tabs, newlines, and so on.
203                         if (i == '\0')
204                         {
205                                 fputs("\", \"", file);
206                                 continue;
207                         }
208                         putc(i, file);
209                 }
210                 if (hasNull)
211                 {
212                         byte_data.push_back('\0');
213                 }
214         }
215         putc('"', file);
216 }
217
218 void
219 property_value::write_as_cells(FILE *file)
220 {
221         putc('<', file);
222         assert((byte_data.size() % 4) == 0);
223         for (auto i=byte_data.begin(), e=byte_data.end(); i!=e ; ++i)
224         {
225                 uint32_t v = 0;
226                 v = (v << 8) | *i;
227                 ++i;
228                 v = (v << 8) | *i;
229                 ++i;
230                 v = (v << 8) | *i;
231                 ++i;
232                 v = (v << 8) | *i;
233                 fprintf(file, "0x%" PRIx32, v);
234                 if (i+1 != e)
235                 {
236                         putc(' ', file);
237                 }
238         }
239         putc('>', file);
240 }
241
242 void
243 property_value::write_as_bytes(FILE *file)
244 {
245         putc('[', file);
246         for (auto i=byte_data.begin(), e=byte_data.end(); i!=e ; i++)
247         {
248                 fprintf(file, "%02hhx", *i);
249                 if (i+1 != e)
250                 {
251                         putc(' ', file);
252                 }
253         }
254         putc(']', file);
255 }
256
257 void
258 property::parse_string(text_input_buffer &input)
259 {
260         property_value v;
261         assert(*input == '"');
262         ++input;
263         std::vector<char> bytes;
264         bool isEscaped = false;
265         while (char c = *input)
266         {
267                 if (c == '"' && !isEscaped)
268                 {
269                         input.consume('"');
270                         break;
271                 }
272                 isEscaped = (c == '\\');
273                 bytes.push_back(c);
274                 ++input;
275         }
276         v.string_data = string(bytes.begin(), bytes.end());
277         values.push_back(v);
278 }
279
280 void
281 property::parse_cells(text_input_buffer &input, int cell_size)
282 {
283         assert(*input == '<');
284         ++input;
285         property_value v;
286         input.next_token();
287         while (!input.consume('>'))
288         {
289                 input.next_token();
290                 // If this is a phandle then we need to get the name of the
291                 // referenced node
292                 if (input.consume('&'))
293                 {
294                         if (cell_size != 32)
295                         {
296                                 input.parse_error("reference only permitted in 32-bit arrays");
297                                 valid = false;
298                                 return;
299                         }
300                         input.next_token();
301                         string referenced;
302                         if (!input.consume('{'))
303                         {
304                                 referenced = input.parse_node_name();
305                         }
306                         else
307                         {
308                                 referenced = input.parse_to('}');
309                                 input.consume('}');
310                         }
311                         if (referenced.empty())
312                         {
313                                 input.parse_error("Expected node name");
314                                 valid = false;
315                                 return;
316                         }
317                         input.next_token();
318                         // If we already have some bytes, make the phandle a
319                         // separate component.
320                         if (!v.byte_data.empty())
321                         {
322                                 values.push_back(v);
323                                 v = property_value();
324                         }
325                         v.string_data = referenced;
326                         v.type = property_value::PHANDLE;
327                         values.push_back(v);
328                         v = property_value();
329                 }
330                 else
331                 {
332                         //FIXME: We should support labels in the middle
333                         //of these, but we don't.
334                         unsigned long long val;
335                         if (!input.consume_integer_expression(val))
336                         {
337                                 input.parse_error("Expected numbers in array of cells");
338                                 valid = false;
339                                 return;
340                         }
341                         switch (cell_size)
342                         {
343                                 case 8:
344                                         v.byte_data.push_back(val);
345                                         break;
346                                 case 16:
347                                         push_big_endian(v.byte_data, (uint16_t)val);
348                                         break;
349                                 case 32:
350                                         push_big_endian(v.byte_data, (uint32_t)val);
351                                         break;
352                                 case 64:
353                                         push_big_endian(v.byte_data, (uint64_t)val);
354                                         break;
355                                 default:
356                                         assert(0 && "Invalid cell size!");
357                         }
358                         input.next_token();
359                 }
360         }
361         // Don't store an empty string value here.
362         if (v.byte_data.size() > 0)
363         {
364                 values.push_back(v);
365         }
366 }
367
368 void
369 property::parse_bytes(text_input_buffer &input)
370 {
371         assert(*input == '[');
372         ++input;
373         property_value v;
374         input.next_token();
375         while (!input.consume(']'))
376         {
377                 {
378                         //FIXME: We should support
379                         //labels in the middle of
380                         //these, but we don't.
381                         uint8_t val;
382                         if (!input.consume_hex_byte(val))
383                         {
384                                 input.parse_error("Expected hex bytes in array of bytes");
385                                 valid = false;
386                                 return;
387                         }
388                         v.byte_data.push_back(val);
389                         input.next_token();
390                 }
391         }
392         values.push_back(v);
393 }
394
395 void
396 property::parse_reference(text_input_buffer &input)
397 {
398         assert(*input == '&');
399         ++input;
400         input.next_token();
401         property_value v;
402         v.string_data = input.parse_node_name();
403         if (v.string_data.empty())
404         {
405                 input.parse_error("Expected node name");
406                 valid = false;
407                 return;
408         }
409         v.type = property_value::CROSS_REFERENCE;
410         values.push_back(v);
411 }
412
413 property::property(input_buffer &structs, input_buffer &strings)
414 {
415         uint32_t name_offset;
416         uint32_t length;
417         valid = structs.consume_binary(length) &&
418                 structs.consume_binary(name_offset);
419         if (!valid)
420         {
421                 fprintf(stderr, "Failed to read property\n");
422                 return;
423         }
424         // Find the name
425         input_buffer name_buffer = strings.buffer_from_offset(name_offset);
426         if (name_buffer.finished())
427         {
428                 fprintf(stderr, "Property name offset %" PRIu32
429                         " is past the end of the strings table\n",
430                         name_offset);
431                 valid = false;
432                 return;
433         }
434         key = name_buffer.parse_to(0);
435
436         // If we're empty, do not push anything as value.
437         if (!length)
438                 return;
439
440         // Read the value
441         uint8_t byte;
442         property_value v;
443         for (uint32_t i=0 ; i<length ; i++)
444         {
445                 if (!(valid = structs.consume_binary(byte)))
446                 {
447                         fprintf(stderr, "Failed to read property value\n");
448                         return;
449                 }
450                 v.byte_data.push_back(byte);
451         }
452         values.push_back(v);
453 }
454
455 void property::parse_define(text_input_buffer &input, define_map *defines)
456 {
457         input.consume('$');
458         if (!defines)
459         {
460                 input.parse_error("No predefined properties to match name\n");
461                 valid = false;
462                 return;
463         }
464         string name = input.parse_property_name();
465         define_map::iterator found;
466         if ((name == string()) ||
467             ((found = defines->find(name)) == defines->end()))
468         {
469                 input.parse_error("Undefined property name\n");
470                 valid = false;
471                 return;
472         }
473         values.push_back((*found).second->values[0]);
474 }
475
476 property::property(text_input_buffer &input,
477                    string &&k,
478                    string_set &&l,
479                    bool semicolonTerminated,
480                    define_map *defines) : key(k), labels(l), valid(true)
481 {
482         do {
483                 input.next_token();
484                 switch (*input)
485                 {
486                         case '$':
487                         {
488                                 parse_define(input, defines);
489                                 if (valid)
490                                 {
491                                         break;
492                                 }
493                         }
494                         default:
495                                 input.parse_error("Invalid property value.");
496                                 valid = false;
497                                 return;
498                         case '/':
499                         {
500                                 if (input.consume("/incbin/(\""))
501                                 {
502                                         auto loc = input.location();
503                                         std::string filename = input.parse_to('"');
504                                         if (!(valid = input.consume('"')))
505                                         {
506                                                 loc.report_error("Syntax error, expected '\"' to terminate /incbin/(");
507                                                 return;
508                                         }
509                                         property_value v;
510                                         if (!(valid = input.read_binary_file(filename, v.byte_data)))
511                                         {
512                                                 input.parse_error("Cannot open binary include file");
513                                                 return;
514                                         }
515                                         if (!(valid &= input.consume(')')))
516                                         {
517                                                 input.parse_error("Syntax error, expected ')' to terminate /incbin/(");
518                                                 return;
519                                         }
520                                         values.push_back(v);
521                                         break;
522                                 }
523                                 unsigned long long bits = 0;
524                                 valid = input.consume("/bits/");
525                                 input.next_token();
526                                 valid &= input.consume_integer(bits);
527                                 if ((bits != 8) &&
528                                     (bits != 16) &&
529                                     (bits != 32) &&
530                                     (bits != 64)) {
531                                         input.parse_error("Invalid size for elements");
532                                         valid = false;
533                                 }
534                                 if (!valid) return;
535                                 input.next_token();
536                                 if (*input != '<')
537                                 {
538                                         input.parse_error("/bits/ directive is only valid on arrays");
539                                         valid = false;
540                                         return;
541                                 }
542                                 parse_cells(input, bits);
543                                 break;
544                         }
545                         case '"':
546                                 parse_string(input);
547                                 break;
548                         case '<':
549                                 parse_cells(input, 32);
550                                 break;
551                         case '[':
552                                 parse_bytes(input);
553                                 break;
554                         case '&':
555                                 parse_reference(input);
556                                 break;
557                         case ';':
558                         {
559                                 break;
560                         }
561                 }
562                 input.next_token();
563         } while (input.consume(','));
564         if (semicolonTerminated && !input.consume(';'))
565         {
566                 input.parse_error("Expected ; at end of property");
567                 valid = false;
568         }
569 }
570
571 property_ptr
572 property::parse_dtb(input_buffer &structs, input_buffer &strings)
573 {
574         property_ptr p(new property(structs, strings));
575         if (!p->valid)
576         {
577                 p = nullptr;
578         }
579         return p;
580 }
581
582 property_ptr
583 property::parse(text_input_buffer &input, string &&key, string_set &&label,
584                 bool semicolonTerminated, define_map *defines)
585 {
586         property_ptr p(new property(input,
587                                     std::move(key),
588                                     std::move(label),
589                                     semicolonTerminated,
590                                     defines));
591         if (!p->valid)
592         {
593                 p = nullptr;
594         }
595         return p;
596 }
597
598 void
599 property::write(dtb::output_writer &writer, dtb::string_table &strings)
600 {
601         writer.write_token(dtb::FDT_PROP);
602         byte_buffer value_buffer;
603         for (value_iterator i=begin(), e=end() ; i!=e ; ++i)
604         {
605                 i->push_to_buffer(value_buffer);
606         }
607         writer.write_data((uint32_t)value_buffer.size());
608         writer.write_comment(key);
609         writer.write_data(strings.add_string(key));
610         writer.write_data(value_buffer);
611 }
612
613 bool
614 property_value::try_to_merge(property_value &other)
615 {
616         resolve_type();
617         switch (type)
618         {
619                 case UNKNOWN:
620                         __builtin_unreachable();
621                         assert(0);
622                         return false;
623                 case EMPTY:
624                         *this = other;
625                 case STRING:
626                 case STRING_LIST:
627                 case CROSS_REFERENCE:
628                         return false;
629                 case PHANDLE:
630                 case BINARY:
631                         if (other.type == PHANDLE || other.type == BINARY)
632                         {
633                                 type = BINARY;
634                                 byte_data.insert(byte_data.end(), other.byte_data.begin(),
635                                                  other.byte_data.end());
636                                 return true;
637                         }
638         }
639         return false;
640 }
641
642 void
643 property::write_dts(FILE *file, int indent)
644 {
645         for (int i=0 ; i<indent ; i++)
646         {
647                 putc('\t', file);
648         }
649 #ifdef PRINT_LABELS
650         for (auto &l : labels)
651         {
652                 fputs(l.c_str(), file);
653                 fputs(": ", file);
654         }
655 #endif
656         if (key != string())
657         {
658                 fputs(key.c_str(), file);
659         }
660         if (!values.empty())
661         {
662                 std::vector<property_value> *vals = &values;
663                 std::vector<property_value> v;
664                 // If we've got multiple values then try to merge them all together.
665                 if (values.size() > 1)
666                 {
667                         vals = &v;
668                         v.push_back(values.front());
669                         for (auto i=(++begin()), e=end() ; i!=e ; ++i)
670                         {
671                                 if (!v.back().try_to_merge(*i))
672                                 {
673                                         v.push_back(*i);
674                                 }
675                         }
676                 }
677                 fputs(" = ", file);
678                 for (auto i=vals->begin(), e=vals->end() ; i!=e ; ++i)
679                 {
680                         i->write_dts(file);
681                         if (i+1 != e)
682                         {
683                                 putc(',', file);
684                                 putc(' ', file);
685                         }
686                 }
687         }
688         fputs(";\n", file);
689 }
690
691 size_t
692 property::offset_of_value(property_value &val)
693 {
694         size_t off = 0;
695         for (auto &v : values)
696         {
697                 if (&v == &val)
698                 {
699                         return off;
700                 }
701                 off += v.size();
702         }
703         return -1;
704 }
705
706 string
707 node::parse_name(text_input_buffer &input, bool &is_property, const char *error)
708 {
709         if (!valid)
710         {
711                 return string();
712         }
713         input.next_token();
714         if (is_property)
715         {
716                 return input.parse_property_name();
717         }
718         string n = input.parse_node_or_property_name(is_property);
719         if (n.empty())
720         {
721                 if (n.empty())
722                 {
723                         input.parse_error(error);
724                         valid = false;
725                 }
726         }
727         return n;
728 }
729
730 void
731 node::visit(std::function<void(node&)> fn)
732 {
733         fn(*this);
734         for (auto &&c : children)
735         {
736                 c->visit(fn);
737         }
738 }
739
740 node::node(input_buffer &structs, input_buffer &strings) : valid(true)
741 {
742         std::vector<char> bytes;
743         while (structs[0] != '\0' && structs[0] != '@')
744         {
745                 bytes.push_back(structs[0]);
746                 ++structs;
747         }
748         name = string(bytes.begin(), bytes.end());
749         bytes.clear();
750         if (structs[0] == '@')
751         {
752                 ++structs;
753                 while (structs[0] != '\0')
754                 {
755                         bytes.push_back(structs[0]);
756                         ++structs;
757                 }
758                 unit_address = string(bytes.begin(), bytes.end());
759         }
760         ++structs;
761         uint32_t token;
762         while (structs.consume_binary(token))
763         {
764                 switch (token)
765                 {
766                         default:
767                                 fprintf(stderr, "Unexpected token 0x%" PRIx32
768                                         " while parsing node.\n", token);
769                                 valid = false;
770                                 return;
771                         // Child node, parse it.
772                         case dtb::FDT_BEGIN_NODE:
773                         {
774                                 node_ptr child = node::parse_dtb(structs, strings);
775                                 if (child == 0)
776                                 {
777                                         valid = false;
778                                         return;
779                                 }
780                                 children.push_back(std::move(child));
781                                 break;
782                         }
783                         // End of this node, no errors.
784                         case dtb::FDT_END_NODE:
785                                 return;
786                         // Property, parse it.
787                         case dtb::FDT_PROP:
788                         {
789                                 property_ptr prop = property::parse_dtb(structs, strings);
790                                 if (prop == 0)
791                                 {
792                                         valid = false;
793                                         return;
794                                 }
795                                 props.push_back(prop);
796                                 break;
797                         }
798                                 break;
799                         // End of structs table.  Should appear after
800                         // the end of the last node.
801                         case dtb::FDT_END:
802                                 fprintf(stderr, "Unexpected FDT_END token while parsing node.\n");
803                                 valid = false;
804                                 return;
805                         // NOPs are padding.  Ignore them.
806                         case dtb::FDT_NOP:
807                                 break;
808                 }
809         }
810         fprintf(stderr, "Failed to read token from structs table while parsing node.\n");
811         valid = false;
812         return;
813 }
814
815
816 node::node(const string &n,
817            const std::vector<property_ptr> &p)
818         : name(n)
819 {
820         props.insert(props.begin(), p.begin(), p.end());
821 }
822
823 node_ptr node::create_special_node(const string &name,
824                                    const std::vector<property_ptr> &props)
825 {
826         node_ptr n(new node(name, props));
827         return n;
828 }
829
830 node::node(text_input_buffer &input,
831            string &&n,
832            std::unordered_set<string> &&l,
833            string &&a,
834            define_map *defines)
835         : labels(l), name(n), unit_address(a), valid(true)
836 {
837         if (!input.consume('{'))
838         {
839                 input.parse_error("Expected { to start new device tree node.\n");
840         }
841         input.next_token();
842         while (valid && !input.consume('}'))
843         {
844                 // flag set if we find any characters that are only in
845                 // the property name character set, not the node 
846                 bool is_property = false;
847                 string child_name, child_address;
848                 std::unordered_set<string> child_labels;
849                 auto parse_delete = [&](const char *expected, bool at)
850                 {
851                         if (child_name == string())
852                         {
853                                 input.parse_error(expected);
854                                 valid = false;
855                                 return;
856                         }
857                         input.next_token();
858                         if (at && input.consume('@'))
859                         {
860                                 child_name += '@';
861                                 child_name += parse_name(input, is_property, "Expected unit address");
862                         }
863                         if (!input.consume(';'))
864                         {
865                                 input.parse_error("Expected semicolon");
866                                 valid = false;
867                                 return;
868                         }
869                         input.next_token();
870                 };
871                 if (input.consume("/delete-node/"))
872                 {
873                         input.next_token();
874                         child_name = input.parse_node_name();
875                         parse_delete("Expected node name", true);
876                         if (valid)
877                         {
878                                 deleted_children.insert(child_name);
879                         }
880                         continue;
881                 }
882                 if (input.consume("/delete-property/"))
883                 {
884                         input.next_token();
885                         child_name = input.parse_property_name();
886                         parse_delete("Expected property name", false);
887                         if (valid)
888                         {
889                                 deleted_props.insert(child_name);
890                         }
891                         continue;
892                 }
893                 child_name = parse_name(input, is_property,
894                                 "Expected property or node name");
895                 while (input.consume(':'))
896                 {
897                         // Node labels can contain any characters?  The
898                         // spec doesn't say, so we guess so...
899                         is_property = false;
900                         child_labels.insert(std::move(child_name));
901                         child_name = parse_name(input, is_property, "Expected property or node name");
902                 }
903                 if (input.consume('@'))
904                 {
905                         child_address = parse_name(input, is_property, "Expected unit address");
906                 }
907                 if (!valid)
908                 {
909                         return;
910                 }
911                 input.next_token();
912                 // If we're parsing a property, then we must actually do that.
913                 if (input.consume('='))
914                 {
915                         property_ptr p = property::parse(input, std::move(child_name),
916                                         std::move(child_labels), true, defines);
917                         if (p == 0)
918                         {
919                                 valid = false;
920                         }
921                         else
922                         {
923                                 props.push_back(p);
924                         }
925                 }
926                 else if (!is_property && *input == ('{'))
927                 {
928                         node_ptr child = node::parse(input, std::move(child_name),
929                                         std::move(child_labels), std::move(child_address), defines);
930                         if (child)
931                         {
932                                 children.push_back(std::move(child));
933                         }
934                         else
935                         {
936                                 valid = false;
937                         }
938                 }
939                 else if (input.consume(';'))
940                 {
941                         props.push_back(property_ptr(new property(std::move(child_name), std::move(child_labels))));
942                 }
943                 else
944                 {
945                         input.parse_error("Error parsing property.  Expected property value");
946                         valid = false;
947                 }
948                 input.next_token();
949         }
950         input.next_token();
951         input.consume(';');
952 }
953
954 bool
955 node::cmp_properties(property_ptr &p1, property_ptr &p2)
956 {
957         return p1->get_key() < p2->get_key();
958 }
959
960 bool
961 node::cmp_children(node_ptr &c1, node_ptr &c2)
962 {
963         if (c1->name == c2->name)
964         {
965                 return c1->unit_address < c2->unit_address;
966         }
967         return c1->name < c2->name;
968 }
969
970 void
971 node::sort()
972 {
973         std::sort(property_begin(), property_end(), cmp_properties);
974         std::sort(child_begin(), child_end(), cmp_children);
975         for (auto &c : child_nodes())
976         {
977                 c->sort();
978         }
979 }
980
981 node_ptr
982 node::parse(text_input_buffer &input,
983             string &&name,
984             string_set &&label,
985             string &&address,
986             define_map *defines)
987 {
988         node_ptr n(new node(input,
989                             std::move(name),
990                             std::move(label),
991                             std::move(address),
992                             defines));
993         if (!n->valid)
994         {
995                 n = 0;
996         }
997         return n;
998 }
999
1000 node_ptr
1001 node::parse_dtb(input_buffer &structs, input_buffer &strings)
1002 {
1003         node_ptr n(new node(structs, strings));
1004         if (!n->valid)
1005         {
1006                 n = 0;
1007         }
1008         return n;
1009 }
1010
1011 property_ptr
1012 node::get_property(const string &key)
1013 {
1014         for (auto &i : props)
1015         {
1016                 if (i->get_key() == key)
1017                 {
1018                         return i;
1019                 }
1020         }
1021         return 0;
1022 }
1023
1024 void
1025 node::merge_node(node_ptr &other)
1026 {
1027         for (auto &l : other->labels)
1028         {
1029                 labels.insert(l);
1030         }
1031         // Note: this is an O(n*m) operation.  It might be sensible to
1032         // optimise this if we find that there are nodes with very
1033         // large numbers of properties, but for typical usage the
1034         // entire vector will fit (easily) into cache, so iterating
1035         // over it repeatedly isn't that expensive.
1036         for (auto &p : other->properties())
1037         {
1038                 bool found = false;
1039                 for (auto &mp : properties())
1040                 {
1041                         if (mp->get_key() == p->get_key())
1042                         {
1043                                 mp = p;
1044                                 found = true;
1045                                 break;
1046                         }
1047                 }
1048                 if (!found)
1049                 {
1050                         add_property(p);
1051                 }
1052         }
1053         for (auto &c : other->children)
1054         {
1055                 bool found = false;
1056                 for (auto &i : children)
1057                 {
1058                         if (i->name == c->name && i->unit_address == c->unit_address)
1059                         {
1060                                 i->merge_node(c);
1061                                 found = true;
1062                                 break;
1063                         }
1064                 }
1065                 if (!found)
1066                 {
1067                         children.push_back(std::move(c));
1068                 }
1069         }
1070         children.erase(std::remove_if(children.begin(), children.end(),
1071                         [&](const node_ptr &p) {
1072                                 string full_name = p->name;
1073                                 if (p->unit_address != string())
1074                                 {
1075                                         full_name += '@';
1076                                         full_name += p->unit_address;
1077                                 }
1078                                 if (other->deleted_children.count(full_name) > 0)
1079                                 {
1080                                         other->deleted_children.erase(full_name);
1081                                         return true;
1082                                 }
1083                                 return false;
1084                         }), children.end());
1085         props.erase(std::remove_if(props.begin(), props.end(),
1086                         [&](const property_ptr &p) {
1087                                 if (other->deleted_props.count(p->get_key()) > 0)
1088                                 {
1089                                         other->deleted_props.erase(p->get_key());
1090                                         return true;
1091                                 }
1092                                 return false;
1093                         }), props.end());
1094 }
1095
1096 void
1097 node::write(dtb::output_writer &writer, dtb::string_table &strings)
1098 {
1099         writer.write_token(dtb::FDT_BEGIN_NODE);
1100         byte_buffer name_buffer;
1101         push_string(name_buffer, name);
1102         if (unit_address != string())
1103         {
1104                 name_buffer.push_back('@');
1105                 push_string(name_buffer, unit_address);
1106         }
1107         writer.write_comment(name);
1108         writer.write_data(name_buffer);
1109         writer.write_data((uint8_t)0);
1110         for (auto p : properties())
1111         {
1112                 p->write(writer, strings);
1113         }
1114         for (auto &c : child_nodes())
1115         {
1116                 c->write(writer, strings);
1117         }
1118         writer.write_token(dtb::FDT_END_NODE);
1119 }
1120
1121 void
1122 node::write_dts(FILE *file, int indent)
1123 {
1124         for (int i=0 ; i<indent ; i++)
1125         {
1126                 putc('\t', file);
1127         }
1128 #ifdef PRINT_LABELS
1129         for (auto &label : labels)
1130         {
1131                 fprintf(file, "%s: ", label.c_str());
1132         }
1133 #endif
1134         if (name != string())
1135         {
1136                 fputs(name.c_str(), file);
1137         }
1138         if (unit_address != string())
1139         {
1140                 putc('@', file);
1141                 fputs(unit_address.c_str(), file);
1142         }
1143         fputs(" {\n\n", file);
1144         for (auto p : properties())
1145         {
1146                 p->write_dts(file, indent+1);
1147         }
1148         for (auto &c : child_nodes())
1149         {
1150                 c->write_dts(file, indent+1);
1151         }
1152         for (int i=0 ; i<indent ; i++)
1153         {
1154                 putc('\t', file);
1155         }
1156         fputs("};\n", file);
1157 }
1158
1159 void
1160 device_tree::collect_names_recursive(node_ptr &n, node_path &path)
1161 {
1162         path.push_back(std::make_pair(n->name, n->unit_address));
1163         for (const string &name : n->labels)
1164         {
1165                 if (name != string())
1166                 {
1167                         auto iter = node_names.find(name);
1168                         if (iter == node_names.end())
1169                         {
1170                                 node_names.insert(std::make_pair(name, n.get()));
1171                                 node_paths.insert(std::make_pair(name, path));
1172                         }
1173                         else
1174                         {
1175                                 node_names.erase(iter);
1176                                 auto i = node_paths.find(name);
1177                                 if (i != node_paths.end())
1178                                 {
1179                                         node_paths.erase(name);
1180                                 }
1181                                 fprintf(stderr, "Label not unique: %s.  References to this label will not be resolved.\n", name.c_str());
1182                         }
1183                 }
1184         }
1185         for (auto &c : n->child_nodes())
1186         {
1187                 collect_names_recursive(c, path);
1188         }
1189         // Now we collect the phandles and properties that reference
1190         // other nodes.
1191         for (auto &p : n->properties())
1192         {
1193                 for (auto &v : *p)
1194                 {
1195                         if (v.is_phandle())
1196                         {
1197                                 fixups.push_back({path, p, v});
1198                         }
1199                         if (v.is_cross_reference())
1200                         {
1201                                 cross_references.push_back(&v);
1202                         }
1203                 }
1204                 if ((p->get_key() == "phandle") ||
1205                     (p->get_key() == "linux,phandle"))
1206                 {
1207                         if (p->begin()->byte_data.size() != 4)
1208                         {
1209                                 fprintf(stderr, "Invalid phandle value for node %s.  Should be a 4-byte value.\n", n->name.c_str());
1210                                 valid = false;
1211                         }
1212                         else
1213                         {
1214                                 uint32_t phandle = p->begin()->get_as_uint32();
1215                                 used_phandles.insert(std::make_pair(phandle, n.get()));
1216                         }
1217                 }
1218         }
1219         path.pop_back();
1220 }
1221
1222 void
1223 device_tree::collect_names()
1224 {
1225         node_path p;
1226         node_names.clear();
1227         node_paths.clear();
1228         cross_references.clear();
1229         fixups.clear();
1230         collect_names_recursive(root, p);
1231 }
1232
1233 property_ptr
1234 device_tree::assign_phandle(node *n, uint32_t &phandle)
1235 {
1236         // If there is an existing phandle, use it
1237         property_ptr p = n->get_property("phandle");
1238         if (p == 0)
1239         {
1240                 p = n->get_property("linux,phandle");
1241         }
1242         if (p == 0)
1243         {
1244                 // Otherwise insert a new phandle node
1245                 property_value v;
1246                 while (used_phandles.find(phandle) != used_phandles.end())
1247                 {
1248                         // Note that we only don't need to
1249                         // store this phandle in the set,
1250                         // because we are monotonically
1251                         // increasing the value of phandle and
1252                         // so will only ever revisit this value
1253                         // if we have used 2^32 phandles, at
1254                         // which point our blob won't fit in
1255                         // any 32-bit system and we've done
1256                         // something badly wrong elsewhere
1257                         // already.
1258                         phandle++;
1259                 }
1260                 push_big_endian(v.byte_data, phandle++);
1261                 if (phandle_node_name == BOTH || phandle_node_name == LINUX)
1262                 {
1263                         p.reset(new property("linux,phandle"));
1264                         p->add_value(v);
1265                         n->add_property(p);
1266                 }
1267                 if (phandle_node_name == BOTH || phandle_node_name == EPAPR)
1268                 {
1269                         p.reset(new property("phandle"));
1270                         p->add_value(v);
1271                         n->add_property(p);
1272                 }
1273         }
1274
1275         return (p);
1276 }
1277
1278 void
1279 device_tree::assign_phandles(node_ptr &n, uint32_t &next)
1280 {
1281         if (!n->labels.empty())
1282         {
1283                 assign_phandle(n.get(), next);
1284         }
1285
1286         for (auto &c : n->child_nodes())
1287         {
1288                 assign_phandles(c, next);
1289         }
1290 }
1291
1292 void
1293 device_tree::resolve_cross_references(uint32_t &phandle)
1294 {
1295         for (auto *pv : cross_references)
1296         {
1297                 node_path path = node_paths[pv->string_data];
1298                 auto p = path.begin();
1299                 auto pe = path.end();
1300                 if (p != pe)
1301                 {
1302                         // Skip the first name in the path.  It's always "", and implicitly /
1303                         for (++p ; p!=pe ; ++p)
1304                         {
1305                                 pv->byte_data.push_back('/');
1306                                 push_string(pv->byte_data, p->first);
1307                                 if (!(p->second.empty()))
1308                                 {
1309                                         pv->byte_data.push_back('@');
1310                                         push_string(pv->byte_data, p->second);
1311                                 }
1312                         }
1313                         pv->byte_data.push_back(0);
1314                 }
1315         }
1316         std::unordered_map<property_value*, fixup&> phandle_set;
1317         for (auto &i : fixups)
1318         {
1319                 phandle_set.insert({&i.val, i});
1320         }
1321         std::vector<std::reference_wrapper<fixup>> sorted_phandles;
1322         root->visit([&](node &n) {
1323                 for (auto &p : n.properties())
1324                 {
1325                         for (auto &v : *p)
1326                         {
1327                                 auto i = phandle_set.find(&v);
1328                                 if (i != phandle_set.end())
1329                                 {
1330                                         sorted_phandles.push_back(i->second);
1331                                 }
1332                         }
1333                 }
1334         });
1335         assert(sorted_phandles.size() == fixups.size());
1336
1337         for (auto &i : sorted_phandles)
1338         {
1339                 string target_name = i.get().val.string_data;
1340                 node *target = nullptr;
1341                 string possible;
1342                 // If the node name is a path, then look it up by following the path,
1343                 // otherwise jump directly to the named node.
1344                 if (target_name[0] == '/')
1345                 {
1346                         string path;
1347                         target = root.get();
1348                         std::istringstream ss(target_name);
1349                         string path_element;
1350                         // Read the leading /
1351                         std::getline(ss, path_element, '/');
1352                         // Iterate over path elements
1353                         while (!ss.eof())
1354                         {
1355                                 path += '/';
1356                                 std::getline(ss, path_element, '/');
1357                                 std::istringstream nss(path_element);
1358                                 string node_name, node_address;
1359                                 std::getline(nss, node_name, '@');
1360                                 std::getline(nss, node_address, '@');
1361                                 node *next = nullptr;
1362                                 for (auto &c : target->child_nodes())
1363                                 {
1364                                         if (c->name == node_name)
1365                                         {
1366                                                 if (c->unit_address == node_address)
1367                                                 {
1368                                                         next = c.get();
1369                                                         break;
1370                                                 }
1371                                                 else
1372                                                 {
1373                                                         possible = path + c->name;
1374                                                         if (c->unit_address != string())
1375                                                         {
1376                                                                 possible += '@';
1377                                                                 possible += c->unit_address;
1378                                                         }
1379                                                 }
1380                                         }
1381                                 }
1382                                 path += node_name;
1383                                 if (node_address != string())
1384                                 {
1385                                         path += '@';
1386                                         path += node_address;
1387                                 }
1388                                 target = next;
1389                                 if (target == nullptr)
1390                                 {
1391                                         break;
1392                                 }
1393                         }
1394                 }
1395                 else
1396                 {
1397                         target = node_names[target_name];
1398                 }
1399                 if (target == nullptr)
1400                 {
1401                         if (is_plugin)
1402                         {
1403                                 unresolved_fixups.push_back(i);
1404                                 continue;
1405                         }
1406                         else
1407                         {
1408                                 fprintf(stderr, "Failed to find node with label: %s\n", target_name.c_str());
1409                                 if (possible != string())
1410                                 {
1411                                         fprintf(stderr, "Possible intended match: %s\n", possible.c_str());
1412                                 }
1413                                 valid = 0;
1414                                 return;
1415                         }
1416                 }
1417                 // If there is an existing phandle, use it
1418                 property_ptr p = assign_phandle(target, phandle);
1419                 p->begin()->push_to_buffer(i.get().val.byte_data);
1420                 assert(i.get().val.byte_data.size() == 4);
1421         }
1422 }
1423
1424
1425 void
1426 device_tree::parse_file(text_input_buffer &input,
1427                         std::vector<node_ptr> &roots,
1428                         bool &read_header)
1429 {
1430         input.next_token();
1431         // Read the header
1432         if (input.consume("/dts-v1/;"))
1433         {
1434                 read_header = true;
1435         }
1436         input.next_token();
1437         if (input.consume("/plugin/;"))
1438         {
1439                 is_plugin = true;
1440         }
1441         input.next_token();
1442         if (!read_header)
1443         {
1444                 input.parse_error("Expected /dts-v1/; version string");
1445         }
1446         // Read any memory reservations
1447         while (input.consume("/memreserve/"))
1448         {
1449                 unsigned long long start, len;
1450                 input.next_token();
1451                 // Read the start and length.
1452                 if (!(input.consume_integer_expression(start) &&
1453                     (input.next_token(),
1454                     input.consume_integer_expression(len))))
1455                 {
1456                         input.parse_error("Expected size on /memreserve/ node.");
1457                 }
1458                 input.next_token();
1459                 input.consume(';');
1460                 reservations.push_back(reservation(start, len));
1461                 input.next_token();
1462         }
1463         while (valid && !input.finished())
1464         {
1465                 node_ptr n;
1466                 if (input.consume('/'))
1467                 {
1468                         input.next_token();
1469                         n = node::parse(input, string(), string_set(), string(), &defines);
1470                 }
1471                 else if (input.consume('&'))
1472                 {
1473                         input.next_token();
1474                         string name = input.parse_node_name();
1475                         input.next_token();
1476                         n = node::parse(input, std::move(name), string_set(), string(), &defines);
1477                 }
1478                 else
1479                 {
1480                         input.parse_error("Failed to find root node /.");
1481                 }
1482                 if (n)
1483                 {
1484                         roots.push_back(std::move(n));
1485                 }
1486                 else
1487                 {
1488                         valid = false;
1489                 }
1490                 input.next_token();
1491         }
1492 }
1493
1494 template<class writer> void
1495 device_tree::write(int fd)
1496 {
1497         dtb::string_table st;
1498         dtb::header head;
1499         writer head_writer;
1500         writer reservation_writer;
1501         writer struct_writer;
1502         writer strings_writer;
1503
1504         // Build the reservation table
1505         reservation_writer.write_comment(string("Memory reservations"));
1506         reservation_writer.write_label(string("dt_reserve_map"));
1507         for (auto &i : reservations)
1508         {
1509                 reservation_writer.write_comment(string("Reservation start"));
1510                 reservation_writer.write_data(i.first);
1511                 reservation_writer.write_comment(string("Reservation length"));
1512                 reservation_writer.write_data(i.first);
1513         }
1514         // Write n spare reserve map entries, plus the trailing 0.
1515         for (uint32_t i=0 ; i<=spare_reserve_map_entries ; i++)
1516         {
1517                 reservation_writer.write_data((uint64_t)0);
1518                 reservation_writer.write_data((uint64_t)0);
1519         }
1520
1521
1522         struct_writer.write_comment(string("Device tree"));
1523         struct_writer.write_label(string("dt_struct_start"));
1524         root->write(struct_writer, st);
1525         struct_writer.write_token(dtb::FDT_END);
1526         struct_writer.write_label(string("dt_struct_end"));
1527
1528         st.write(strings_writer);
1529         // Find the strings size before we stick padding on the end.
1530         // Note: We should possibly use a new writer for the padding.
1531         head.size_dt_strings = strings_writer.size();
1532
1533         // Stick the padding in the strings writer, but after the
1534         // marker indicating that it's the end.
1535         // Note: We probably should add a padding call to the writer so
1536         // that the asm back end can write padding directives instead
1537         // of a load of 0 bytes.
1538         for (uint32_t i=0 ; i<blob_padding ; i++)
1539         {
1540                 strings_writer.write_data((uint8_t)0);
1541         }
1542         head.totalsize = sizeof(head) + strings_writer.size() +
1543                 struct_writer.size() + reservation_writer.size();
1544         while (head.totalsize < minimum_blob_size)
1545         {
1546                 head.totalsize++;
1547                 strings_writer.write_data((uint8_t)0);
1548         }
1549         head.off_dt_struct = sizeof(head) + reservation_writer.size();;
1550         head.off_dt_strings = head.off_dt_struct + struct_writer.size();
1551         head.off_mem_rsvmap = sizeof(head);
1552         head.boot_cpuid_phys = boot_cpu;
1553         head.size_dt_struct = struct_writer.size();
1554         head.write(head_writer);
1555
1556         head_writer.write_to_file(fd);
1557         reservation_writer.write_to_file(fd);
1558         struct_writer.write_to_file(fd);
1559         strings_writer.write_label(string("dt_blob_end"));
1560         strings_writer.write_to_file(fd);
1561 }
1562
1563 node*
1564 device_tree::referenced_node(property_value &v)
1565 {
1566         if (v.is_phandle())
1567         {
1568                 return node_names[v.string_data];
1569         }
1570         if (v.is_binary())
1571         {
1572                 return used_phandles[v.get_as_uint32()];
1573         }
1574         return 0;
1575 }
1576
1577 void
1578 device_tree::write_binary(int fd)
1579 {
1580         write<dtb::binary_writer>(fd);
1581 }
1582
1583 void
1584 device_tree::write_asm(int fd)
1585 {
1586         write<dtb::asm_writer>(fd);
1587 }
1588
1589 void
1590 device_tree::write_dts(int fd)
1591 {
1592         FILE *file = fdopen(fd, "w");
1593         fputs("/dts-v1/;\n\n", file);
1594
1595         if (!reservations.empty())
1596         {
1597                 const char msg[] = "/memreserve/";
1598                 fwrite(msg, sizeof(msg), 1, file);
1599                 for (auto &i : reservations)
1600                 {
1601                         fprintf(file, " %" PRIx64 " %" PRIx64, i.first, i.second);
1602                 }
1603                 fputs(";\n\n", file);
1604         }
1605         putc('/', file);
1606         putc(' ', file);
1607         root->write_dts(file, 0);
1608         fclose(file);
1609 }
1610
1611 void
1612 device_tree::parse_dtb(const string &fn, FILE *)
1613 {
1614         auto in = input_buffer::buffer_for_file(fn);
1615         if (in == 0)
1616         {
1617                 valid = false;
1618                 return;
1619         }
1620         input_buffer &input = *in;
1621         dtb::header h;
1622         valid = h.read_dtb(input);
1623         boot_cpu = h.boot_cpuid_phys;
1624         if (h.last_comp_version > 17)
1625         {
1626                 fprintf(stderr, "Don't know how to read this version of the device tree blob");
1627                 valid = false;
1628         }
1629         if (!valid)
1630         {
1631                 return;
1632         }
1633         input_buffer reservation_map =
1634                 input.buffer_from_offset(h.off_mem_rsvmap, 0);
1635         uint64_t start, length;
1636         do
1637         {
1638                 if (!(reservation_map.consume_binary(start) &&
1639                       reservation_map.consume_binary(length)))
1640                 {
1641                         fprintf(stderr, "Failed to read memory reservation table\n");
1642                         valid = false;
1643                         return;
1644                 }
1645         } while (!((start == 0) && (length == 0)));
1646         input_buffer struct_table =
1647                 input.buffer_from_offset(h.off_dt_struct, h.size_dt_struct);
1648         input_buffer strings_table =
1649                 input.buffer_from_offset(h.off_dt_strings, h.size_dt_strings);
1650         uint32_t token;
1651         if (!(struct_table.consume_binary(token) &&
1652                 (token == dtb::FDT_BEGIN_NODE)))
1653         {
1654                 fprintf(stderr, "Expected FDT_BEGIN_NODE token.\n");
1655                 valid = false;
1656                 return;
1657         }
1658         root = node::parse_dtb(struct_table, strings_table);
1659         if (!(struct_table.consume_binary(token) && (token == dtb::FDT_END)))
1660         {
1661                 fprintf(stderr, "Expected FDT_END token after parsing root node.\n");
1662                 valid = false;
1663                 return;
1664         }
1665         valid = (root != 0);
1666 }
1667
1668 string
1669 device_tree::node_path::to_string() const
1670 {
1671         string path;
1672         auto p = begin();
1673         auto pe = end();
1674         if ((p == pe) || (p+1 == pe))
1675         {
1676                 return string("/");
1677         }
1678         // Skip the first name in the path.  It's always "", and implicitly /
1679         for (++p ; p!=pe ; ++p)
1680         {
1681                 path += '/';
1682                 path += p->first;
1683                 if (!(p->second.empty()))
1684                 {
1685                         path += '@';
1686                         path += p->second;
1687                 }
1688         }
1689         return path;
1690 }
1691
1692 node_ptr
1693 device_tree::create_fragment_wrapper(node_ptr &node, int &fragnum)
1694 {
1695         // In a plugin, we can massage these non-/ root nodes into into a fragment
1696         std::string fragment_address = "fragment@" + std::to_string(fragnum);
1697         ++fragnum;
1698
1699         std::vector<property_ptr> symbols;
1700
1701         // Intentionally left empty
1702         node_ptr newroot = node::create_special_node("", symbols);
1703         node_ptr wrapper = node::create_special_node("__overlay__", symbols);
1704
1705         // Generate the fragment with target = <&name>
1706         property_value v;
1707         v.string_data = node->name;
1708         v.type = property_value::PHANDLE;
1709         auto prop = std::make_shared<property>(std::string("target"));
1710         prop->add_value(v);
1711         symbols.push_back(prop);
1712
1713         node_ptr fragment = node::create_special_node(fragment_address, symbols);
1714
1715         wrapper->merge_node(node);
1716         fragment->add_child(std::move(wrapper));
1717         newroot->add_child(std::move(fragment));
1718         return newroot;
1719 }
1720
1721 node_ptr
1722 device_tree::generate_root(node_ptr &node, int &fragnum)
1723 {
1724
1725         string name = node->name;
1726         if (name == string())
1727         {
1728                 return std::move(node);
1729         }
1730         else if (!is_plugin)
1731         {
1732                 return nullptr;
1733         }
1734
1735         return create_fragment_wrapper(node, fragnum);
1736 }
1737
1738 void
1739 device_tree::reassign_fragment_numbers(node_ptr &node, int &delta)
1740 {
1741
1742         for (auto &c : node->child_nodes())
1743         {
1744                 if (c->name == std::string("fragment"))
1745                 {
1746                         int current_address = std::stoi(c->unit_address, nullptr, 16);
1747                         std::ostringstream new_address;
1748                         current_address += delta;
1749                         // It's possible that we hopped more than one somewhere, so just reset
1750                         // delta to the next in sequence.
1751                         delta = current_address + 1;
1752                         new_address << std::hex << current_address;
1753                         c->unit_address = new_address.str();
1754                 }
1755         }
1756 }
1757
1758 void
1759 device_tree::parse_dts(const string &fn, FILE *depfile)
1760 {
1761         auto in = input_buffer::buffer_for_file(fn);
1762         if (!in)
1763         {
1764                 valid = false;
1765                 return;
1766         }
1767         std::vector<node_ptr> roots;
1768         std::unordered_set<string> defnames;
1769         for (auto &i : defines)
1770         {
1771                 defnames.insert(i.first);
1772         }
1773         text_input_buffer input(std::move(in),
1774                                 std::move(defnames),
1775                                 std::vector<string>(include_paths),
1776                                 dirname(fn),
1777                                 depfile);
1778         bool read_header = false;
1779         int fragnum = 0;
1780         parse_file(input, roots, read_header);
1781         switch (roots.size())
1782         {
1783                 case 0:
1784                         valid = false;
1785                         input.parse_error("Failed to find root node /.");
1786                         return;
1787                 case 1:
1788                         root = generate_root(roots[0], fragnum);
1789                         if (!root)
1790                         {
1791                                 valid = false;
1792                                 input.parse_error("Failed to find root node /.");
1793                                 return;
1794                         }
1795                         break;
1796                 default:
1797                 {
1798                         root = generate_root(roots[0], fragnum);
1799                         if (!root)
1800                         {
1801                                 valid = false;
1802                                 input.parse_error("Failed to find root node /.");
1803                                 return;
1804                         }
1805                         for (auto i=++(roots.begin()), e=roots.end() ; i!=e ; ++i)
1806                         {
1807                                 auto &node = *i;
1808                                 string name = node->name;
1809                                 if (name == string())
1810                                 {
1811                                         if (is_plugin)
1812                                         {
1813                                                 // Re-assign any fragment numbers based on a delta of
1814                                                 // fragnum before we merge it
1815                                                 reassign_fragment_numbers(node, fragnum);
1816                                         }
1817                                         root->merge_node(node);
1818                                 }
1819                                 else
1820                                 {
1821                                         auto existing = node_names.find(name);
1822                                         if (existing == node_names.end())
1823                                         {
1824                                                 collect_names();
1825                                                 existing = node_names.find(name);
1826                                         }
1827                                         if (existing == node_names.end())
1828                                         {
1829                                                 if (is_plugin)
1830                                                 {
1831                                                         auto fragment = create_fragment_wrapper(node, fragnum);
1832                                                         root->merge_node(fragment);
1833                                                 }
1834                                                 else
1835                                                 {
1836                                                         fprintf(stderr, "Unable to merge node: %s\n", name.c_str());
1837                                                 }
1838                                         }
1839                                         else
1840                                         {
1841                                                 existing->second->merge_node(node);
1842                                         }
1843                                 }
1844                         }
1845                 }
1846         }
1847         collect_names();
1848         uint32_t phandle = 1;
1849         // If we're writing symbols, go ahead and assign phandles to the entire
1850         // tree. We'll do this before we resolve cross references, just to keep
1851         // order semi-predictable and stable.
1852         if (write_symbols)
1853         {
1854                 assign_phandles(root, phandle);
1855         }
1856         resolve_cross_references(phandle);
1857         if (write_symbols)
1858         {
1859                 std::vector<property_ptr> symbols;
1860                 // Create a symbol table.  Each label  in this device tree may be
1861                 // referenced by other plugins, so we create a __symbols__ node inside
1862                 // the root that contains mappings (properties) from label names to
1863                 // paths.
1864                 for (auto &s : node_paths)
1865                 {
1866                         property_value v;
1867                         v.string_data = s.second.to_string();
1868                         v.type = property_value::STRING;
1869                         string name = s.first;
1870                         auto prop = std::make_shared<property>(std::move(name));
1871                         prop->add_value(v);
1872                         symbols.push_back(prop);
1873                 }
1874                 root->add_child(node::create_special_node("__symbols__", symbols));
1875                 // If this is a plugin, then we also need to create two extra nodes.
1876                 // Internal phandles will need to be renumbered to avoid conflicts with
1877                 // already-loaded nodes and external references will need to be
1878                 // resolved.
1879                 if (is_plugin)
1880                 {
1881                         // Create the fixups entry.  This is of the form:
1882                         // {target} = {path}:{property name}:{offset}
1883                         auto create_fixup_entry = [&](fixup &i, string target)
1884                                 {
1885                                         string value = i.path.to_string();
1886                                         value += ':';
1887                                         value += i.prop->get_key();
1888                                         value += ':';
1889                                         value += std::to_string(i.prop->offset_of_value(i.val));
1890                                         property_value v;
1891                                         v.string_data = value;
1892                                         v.type = property_value::STRING;
1893                                         auto prop = std::make_shared<property>(std::move(target));
1894                                         prop->add_value(v);
1895                                         return prop;
1896                                 };
1897                         // If we have any unresolved phandle references in this plugin,
1898                         // then we must update them to 0xdeadbeef and leave a property in
1899                         // the /__fixups__ node whose key is the label and whose value is
1900                         // as described above.
1901                         if (!unresolved_fixups.empty())
1902                         {
1903                                 symbols.clear();
1904                                 for (auto &i : unresolved_fixups)
1905                                 {
1906                                         auto &val = i.get().val;
1907                                         symbols.push_back(create_fixup_entry(i, val.string_data));
1908                                         val.byte_data.push_back(0xde);
1909                                         val.byte_data.push_back(0xad);
1910                                         val.byte_data.push_back(0xbe);
1911                                         val.byte_data.push_back(0xef);
1912                                         val.type = property_value::BINARY;
1913                                 }
1914                                 root->add_child(node::create_special_node("__fixups__", symbols));
1915                         }
1916                         symbols.clear();
1917                         // If we have any resolved phandle references in this plugin, then
1918                         // we must create a child in the __local_fixups__ node whose path
1919                         // matches the node path from the root and whose value contains the
1920                         // location of the reference within a property.
1921                         
1922                         // Create a local_fixups node that is initially empty.
1923                         node_ptr local_fixups = node::create_special_node("__local_fixups__", symbols);
1924                         for (auto &i : fixups)
1925                         {
1926                                 if (!i.val.is_phandle())
1927                                 {
1928                                         continue;
1929                                 }
1930                                 node *n = local_fixups.get();
1931                                 for (auto &p : i.path)
1932                                 {
1933                                         // Skip the implicit root
1934                                         if (p.first.empty())
1935                                         {
1936                                                 continue;
1937                                         }
1938                                         bool found = false;
1939                                         for (auto &c : n->child_nodes())
1940                                         {
1941                                                 if (c->name == p.first)
1942                                                 {
1943                                                         n = c.get();
1944                                                         found = true;
1945                                                         break;
1946                                                 }
1947                                         }
1948                                         if (!found)
1949                                         {
1950                                                 n->add_child(node::create_special_node(p.first, symbols));
1951                                                 n = (--n->child_end())->get();
1952                                         }
1953                                 }
1954                                 assert(n);
1955                                 property_value pv;
1956                                 push_big_endian(pv.byte_data, static_cast<uint32_t>(i.prop->offset_of_value(i.val)));
1957                                 pv.type = property_value::BINARY;
1958                                 auto key = i.prop->get_key();
1959                                 property_ptr prop = n->get_property(key);
1960                                 // If we don't have an existing property then create one and
1961                                 // use this property value
1962                                 if (!prop)
1963                                 {
1964                                         prop = std::make_shared<property>(std::move(key));
1965                                         n->add_property(prop);
1966                                         prop->add_value(pv);
1967                                 }
1968                                 else
1969                                 {
1970                                         // If we do have an existing property value, try to append
1971                                         // this value.
1972                                         property_value &old_val = *(--prop->end());
1973                                         if (!old_val.try_to_merge(pv))
1974                                         {
1975                                                 prop->add_value(pv);
1976                                         }
1977                                 }
1978                         }
1979                         // We've iterated over all fixups, but only emit the
1980                         // __local_fixups__ if we found some that were resolved internally.
1981                         if (local_fixups->child_begin() != local_fixups->child_end())
1982                         {
1983                                 root->add_child(std::move(local_fixups));
1984                         }
1985                 }
1986         }
1987 }
1988
1989 bool device_tree::parse_define(const char *def)
1990 {
1991         const char *val = strchr(def, '=');
1992         if (!val)
1993         {
1994                 if (strlen(def) != 0)
1995                 {
1996                         string name(def);
1997                         defines[name];
1998                         return true;
1999                 }
2000                 return false;
2001         }
2002         string name(def, val-def);
2003         string name_copy = name;
2004         val++;
2005         std::unique_ptr<input_buffer> raw(new input_buffer(val, strlen(val)));
2006         text_input_buffer in(std::move(raw),
2007                              std::unordered_set<string>(),
2008                              std::vector<string>(),
2009                              string(),
2010                              nullptr);
2011         property_ptr p = property::parse(in, std::move(name_copy), string_set(), false);
2012         if (p)
2013                 defines[name] = p;
2014         return (bool)p;
2015 }
2016
2017 } // namespace fdt
2018
2019 } // namespace dtc
2020