]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - usr.bin/dtc/fdt.cc
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / usr.bin / dtc / fdt.cc
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  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * $FreeBSD$
31  */
32
33 #define __STDC_LIMIT_MACROS 1
34
35 #include "fdt.hh"
36
37 #include <algorithm>
38 #include <ctype.h>
39 #include <fcntl.h>
40 #include <inttypes.h>
41 #include <libgen.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <unistd.h>
45 #include "dtb.hh"
46
47 namespace dtc
48 {
49
50 namespace fdt
51 {
52
53 uint32_t
54 property_value::get_as_uint32()
55 {
56         if (byte_data.size() != 4)
57         {
58                 return 0;
59         }
60         uint32_t v = 0;
61         v &= byte_data[0] << 24;
62         v &= byte_data[1] << 16;
63         v &= byte_data[2] << 8;
64         v &= byte_data[3] << 0;
65         return v;
66 }
67
68 void
69 property_value::push_to_buffer(byte_buffer &buffer)
70 {
71         if (!byte_data.empty())
72         {
73                 buffer.insert(buffer.end(), byte_data.begin(), byte_data.end());
74         }
75         else
76         {
77                 string_data.push_to_buffer(buffer, true);
78                 // Trailing nul
79                 buffer.push_back(0);
80         }
81 }
82
83 void
84 property_value::write_dts(FILE *file)
85 {
86         resolve_type();
87         switch (type)
88         {
89                 default:
90                         assert(0 && "Invalid type");
91                 case STRING:
92                 case STRING_LIST:
93                 case CROSS_REFERENCE:
94                         write_as_string(file);
95                         break;
96                 case PHANDLE:
97                         write_as_cells(file);
98                         break;
99                 case BINARY:
100                         if (byte_data.size() % 4 == 0)
101                         {
102                                 write_as_cells(file);
103                                 break;
104                         }
105                         write_as_bytes(file);
106                         break;
107         }
108 }
109
110 void
111 property_value::resolve_type()
112 {
113         if (type != UNKNOWN)
114         {
115                 return;
116         }
117         if (byte_data.empty())
118         {
119                 type = STRING;
120                 return;
121         }
122         if (byte_data.back() == 0)
123         {
124                 bool is_all_printable = true;
125                 int nuls = 0;
126                 int bytes = 0;
127                 for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end()-1; i<e ; i++)
128                 {
129                         bytes++;
130                         is_all_printable &= (*i == '\0') || isprint(*i);
131                         if (*i == '\0')
132                         {
133                                 nuls++;
134                         }
135                         if (!is_all_printable)
136                         {
137                                 break;
138                         }
139                 }
140                 if (is_all_printable && (bytes > nuls))
141                 {
142                         type = STRING;
143                         if (nuls > 0)
144                         {
145                                 type = STRING_LIST;
146                         }
147                         return;
148                 }
149         }
150         type = BINARY;
151 }
152
153 void
154 property_value::write_as_string(FILE *file)
155 {
156         putc('"', file);
157         if (byte_data.empty())
158         {
159                 string_data.print(file);
160         }
161         else
162         {
163                 for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end()-1; i!=e ; ++i)
164                 {
165                         // FIXME Escape tabs, newlines, and so on.
166                         if (*i == '\0')
167                         {
168                                 fputs("\", \"", file);
169                                 continue;
170                         }
171                         putc(*i, file);
172                 }
173         }
174         putc('"', file);
175 }
176
177 void
178 property_value::write_as_cells(FILE *file)
179 {
180         putc('<', file);
181         assert((byte_data.size() % 4) == 0);
182         for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end(); i!=e ; ++i)
183         {
184                 uint32_t v = 0;
185                 v = (v << 8) | *i;
186                 ++i;
187                 v = (v << 8) | *i;
188                 ++i;
189                 v = (v << 8) | *i;
190                 ++i;
191                 v = (v << 8) | *i;
192                 fprintf(file, "0x%" PRIx32, v);
193                 if (i+1 != e)
194                 {
195                         putc(' ', file);
196                 }
197         }
198         putc('>', file);
199 }
200
201 void
202 property_value::write_as_bytes(FILE *file)
203 {
204         putc('[', file);
205         for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end(); i!=e ; i++)
206         {
207                 fprintf(file, "%hhx", *i);
208                 if (i+1 != e)
209                 {
210                         putc(' ', file);
211                 }
212         }
213         putc(']', file);
214 }
215
216 void
217 property::parse_string(input_buffer &input)
218 {
219         property_value v;
220         assert(input[0] == '"');
221         ++input;
222         const char *start = (const char*)input;
223         int length = 0;
224         while (char c = input[0])
225         {
226                 if (c == '"' && input[-1] != '\\')
227                 {
228                         input.consume('"');
229                         break;
230                 }
231                 ++input;
232                 ++length;
233         }
234         v.string_data = string(start, length);
235         values.push_back(v);
236 }
237
238 void
239 property::parse_cells(input_buffer &input)
240 {
241         assert(input[0] == '<');
242         ++input;
243         property_value v;
244         input.next_token();
245         while (!input.consume('>'))
246         {
247                 input.next_token();
248                 // If this is a phandle then we need to get the name of the
249                 // referenced node
250                 if (input.consume('&'))
251                 {
252                         input.next_token();
253                         // FIXME: We should support full paths here, but we
254                         // don't.
255                         string referenced = string::parse_node_name(input);
256                         if (referenced.empty())
257                         {
258                                 input.parse_error("Expected node name");
259                                 valid = false;
260                                 return;
261                         }
262                         input.next_token();
263                         // If we already have some bytes, make the phandle a
264                         // separate component.
265                         if (!v.byte_data.empty())
266                         {
267                                 values.push_back(v);
268                                 v = property_value();
269                         }
270                         v.string_data = referenced;
271                         v.type = property_value::PHANDLE;
272                         values.push_back(v);
273                         v = property_value();
274                 }
275                 else
276                 {
277                         //FIXME: We should support labels in the middle
278                         //of these, but we don't.
279                         long long val;
280                         if (!input.consume_integer(val))
281                         {
282                                 input.parse_error("Expected numbers in array of cells");
283                                 valid = false;
284                                 return;
285                         }
286                         if ((val < 0) || (val > UINT32_MAX))
287                         {
288                                 input.parse_error("Value out of range");
289                                 valid = false;
290                                 return;
291                         }
292                         push_big_endian(v.byte_data, (uint32_t)val);
293                         input.next_token();
294                 }
295         }
296         // Don't store an empty string value here.
297         if (v.byte_data.size() > 0)
298         {
299                 values.push_back(v);
300         }
301 }
302
303 void
304 property::parse_bytes(input_buffer &input)
305 {
306         assert(input[0] == '[');
307         ++input;
308         property_value v;
309         input.next_token();
310         while (!input.consume(']'))
311         {
312                 {
313                         //FIXME: We should support
314                         //labels in the middle of
315                         //these, but we don't.
316                         uint8_t val;
317                         if (!input.consume_hex_byte(val))
318                         {
319                                 input.parse_error("Expected hex bytes in array of bytes");
320                                 valid = false;
321                                 return;
322                         }
323                         v.byte_data.push_back(val);
324                         input.next_token();
325                 }
326         }
327         values.push_back(v);
328 }
329
330 void
331 property::parse_reference(input_buffer &input)
332 {
333         assert(input[0] == '&');
334         ++input;
335         input.next_token();
336         property_value v;
337         v.string_data = string::parse_node_name(input);
338         if (v.string_data.empty())
339         {
340                 input.parse_error("Expected node name");
341                 valid = false;
342                 return;
343         }
344         v.type = property_value::CROSS_REFERENCE;
345         values.push_back(v);
346 }
347
348 property::property(input_buffer &structs, input_buffer &strings)
349 {
350         uint32_t name_offset;
351         uint32_t length;
352         valid = structs.consume_binary(length) &&
353                 structs.consume_binary(name_offset);
354         if (!valid)
355         {
356                 fprintf(stderr, "Failed to read property\n");
357                 return;
358         }
359         // Find the name
360         input_buffer name_buffer = strings.buffer_from_offset(name_offset);
361         if (name_buffer.empty())
362         {
363                 fprintf(stderr, "Property name offset %" PRIu32
364                         " is past the end of the strings table\n",
365                         name_offset);
366                 valid = false;
367                 return;
368         }
369         key = string(name_buffer);
370         // Read the value
371         uint8_t byte;
372         property_value v;
373         for (uint32_t i=0 ; i<length ; i++)
374         {
375                 if (!(valid = structs.consume_binary(byte)))
376                 {
377                         fprintf(stderr, "Failed to read property value\n");
378                         return;
379                 }
380                 v.byte_data.push_back(byte);
381         }
382         values.push_back(v);
383 }
384
385 void property::parse_define(input_buffer &input, define_map *defines)
386 {
387         input.consume('$');
388         if (!defines)
389         {
390                 input.parse_error("No predefined properties to match name\n");
391                 valid = false;
392                 return;
393         }
394         string name = string::parse_property_name(input);
395         define_map::iterator found;
396         if ((name == string()) ||
397             ((found = defines->find(name)) == defines->end()))
398         {
399                 input.parse_error("Undefined property name\n");
400                 valid = false;
401                 return;
402         }
403         values.push_back((*found).second->values[0]);
404 }
405
406 property::property(input_buffer &input,
407                    string k,
408                    string l,
409                    bool semicolonTerminated,
410                    define_map *defines) : key(k), label(l), valid(true)
411 {
412         do {
413                 input.next_token();
414                 switch (input[0])
415                 {
416                         case '$':
417                         {
418                                 parse_define(input, defines);
419                                 if (valid)
420                                 {
421                                         break;
422                                 }
423                         }
424                         default:
425                                 input.parse_error("Invalid property value.");
426                                 valid = false;
427                                 return;
428                         case '"':
429                                 parse_string(input);
430                                 break;
431                         case '<':
432                                 parse_cells(input);
433                                 break;
434                         case '[':
435                                 parse_bytes(input);
436                                 break;
437                         case '&':
438                                 parse_reference(input);
439                                 break;
440                         case ';':
441                         {
442                                 break;
443                         }
444                 }
445                 input.next_token();
446         } while (input.consume(','));
447         if (semicolonTerminated && !input.consume(';'))
448         {
449                 input.parse_error("Expected ; at end of property");
450                 valid = false;
451         }
452 }
453
454 property*
455 property::parse_dtb(input_buffer &structs, input_buffer &strings)
456 {
457         property *p = new property(structs, strings);
458         if (!p->valid)
459         {
460                 delete p;
461                 p = 0;
462         }
463         return p;
464 }
465
466 property*
467 property::parse(input_buffer &input, string key, string label,
468                 bool semicolonTerminated, define_map *defines)
469 {
470         property *p = new property(input, key, label, semicolonTerminated, defines);
471         if (!p->valid)
472         {
473                 delete p;
474                 p = 0;
475         }
476         return p;
477 }
478
479 void
480 property::write(dtb::output_writer &writer, dtb::string_table &strings)
481 {
482         writer.write_token(dtb::FDT_PROP);
483         byte_buffer value_buffer;
484         for (value_iterator i=begin(), e=end() ; i!=e ; ++i)
485         {
486                 i->push_to_buffer(value_buffer);
487         }
488         writer.write_data((uint32_t)value_buffer.size());
489         writer.write_comment(key);
490         writer.write_data(strings.add_string(key));
491         writer.write_data(value_buffer);
492 }
493
494 void
495 property::write_dts(FILE *file, int indent)
496 {
497         for (int i=0 ; i<indent ; i++)
498         {
499                 putc('\t', file);
500         }
501         if (label != string())
502         {
503                 label.print(file);
504                 fputs(": ", file);
505         }
506         if (key != string())
507         {
508                 key.print(file);
509         }
510         if (!values.empty())
511         {
512                 fputs(" = ", file);
513                 for (value_iterator i=begin(), e=end() ; i!=e ; ++i)
514                 {
515                         i->write_dts(file);
516                         if (i+1 != e)
517                         {
518                                 putc(',', file);
519                                 putc(' ', file);
520                         }
521                 }
522         }
523         fputs(";\n", file);
524 }
525
526 string
527 node::parse_name(input_buffer &input, bool &is_property, const char *error)
528 {
529         if (!valid)
530         {
531                 return string();
532         }
533         input.next_token();
534         if (is_property)
535         {
536                 return string::parse_property_name(input);
537         }
538         string n = string::parse_node_or_property_name(input, is_property);
539         if (n.empty())
540         {
541                 if (n.empty())
542                 {
543                         input.parse_error(error);
544                         valid = false;
545                 }
546         }
547         return n;
548 }
549
550 node::node(input_buffer &structs, input_buffer &strings) : valid(true)
551 {
552         const char *name_start = (const char*)structs;
553         int name_length = 0;
554         while (structs[0] != '\0' && structs[0] != '@')
555         {
556                 name_length++;
557                 ++structs;
558         }
559         name = string(name_start, name_length);
560         if (structs[0] == '@')
561         {
562                 ++structs;
563                 name_start = (const char*)structs;
564                 name_length = 0;
565                 while (structs[0] != '\0')
566                 {
567                         name_length++;
568                         ++structs;
569                 }
570                 unit_address = string(name_start, name_length);
571         }
572         ++structs;
573         uint32_t token;
574         while (structs.consume_binary(token))
575         {
576                 switch (token)
577                 {
578                         default:
579                                 fprintf(stderr, "Unexpected token 0x%" PRIx32
580                                         " while parsing node.\n", token);
581                                 valid = false;
582                                 return;
583                         // Child node, parse it.
584                         case dtb::FDT_BEGIN_NODE:
585                         {
586                                 node *child = node::parse_dtb(structs, strings);
587                                 if (child == 0)
588                                 {
589                                         valid = false;
590                                         return;
591                                 }
592                                 children.push_back(child);
593                                 break;
594                         }
595                         // End of this node, no errors.
596                         case dtb::FDT_END_NODE:
597                                 return;
598                         // Property, parse it.
599                         case dtb::FDT_PROP:
600                         {
601                                 property *prop = property::parse_dtb(structs, strings);
602                                 if (prop == 0)
603                                 {
604                                         valid = false;
605                                         return;
606                                 }
607                                 properties.push_back(prop);
608                                 break;
609                         }
610                                 break;
611                         // End of structs table.  Should appear after
612                         // the end of the last node.
613                         case dtb::FDT_END:
614                                 fprintf(stderr, "Unexpected FDT_END token while parsing node.\n");
615                                 valid = false;
616                                 return;
617                         // NOPs are padding.  Ignore them.
618                         case dtb::FDT_NOP:
619                                 break;
620                 }
621         }
622         fprintf(stderr, "Failed to read token from structs table while parsing node.\n");
623         valid = false;
624         return;
625 }
626
627 node::node(input_buffer &input, string n, string l, string a, define_map *defines) : 
628         label(l), name(n), unit_address(a), valid(true)
629 {
630         if (!input.consume('{'))
631         {
632                 input.parse_error("Expected { to start new device tree node.\n");
633         }
634         input.next_token();
635         while (valid && !input.consume('}'))
636         {
637                 // flag set if we find any characters that are only in
638                 // the property name character set, not the node 
639                 bool is_property = false;
640                 string child_name, child_label, child_address;
641                 child_name = parse_name(input, is_property,
642                                 "Expected property or node name");
643                 if (input.consume(':'))
644                 {
645                         // Node labels can contain any characters?  The
646                         // spec doesn't say, so we guess so...
647                         is_property = false;
648                         child_label = child_name;
649                         child_name = parse_name(input, is_property, "Expected property or node name");
650                 }
651                 if (input.consume('@'))
652                 {
653                         child_address = parse_name(input, is_property, "Expected unit address");
654                 }
655                 if (!valid)
656                 {
657                         return;
658                 }
659                 input.next_token();
660                 // If we're parsing a property, then we must actually do that.
661                 if (input.consume('='))
662                 {
663                         property *p= property::parse(input, child_name,
664                                         child_label, true, defines);
665                         if (p == 0)
666                         {
667                                 valid = false;
668                         }
669                         else
670                         {
671                                 properties.push_back(p);
672                         }
673                 }
674                 else if (!is_property && input[0] == ('{'))
675                 {
676                         node *child = node::parse(input, child_name,
677                                         child_label, child_address, defines);
678                         if (child)
679                         {
680                                 children.push_back(child);
681                         }
682                         else
683                         {
684                                 valid = false;
685                         }
686                 }
687                 else if (input.consume(';'))
688                 {
689                         properties.push_back(new property(child_name, child_label));
690                 }
691                 else
692                 {
693                         input.parse_error("Error parsing property.");
694                         valid = false;
695                 }
696                 input.next_token();
697         }
698         input.consume(';');
699 }
700
701 bool
702 node::cmp_properties(property *p1, property *p2)
703 {
704         return p1->get_key() < p2->get_key();
705 }
706
707 bool
708 node::cmp_children(node *c1, node *c2)
709 {
710         if (c1->name == c2->name)
711         {
712                 return c1->unit_address < c2->unit_address;
713         }
714         return c1->name < c2->name;
715 }
716
717 void
718 node::sort()
719 {
720         std::sort(property_begin(), property_end(), cmp_properties);
721         std::sort(child_begin(), child_end(), cmp_children);
722         for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i)
723         {
724                 (*i)->sort();
725         }
726 }
727
728 node*
729 node::parse(input_buffer &input,
730             string name,
731             string label,
732             string address,
733             define_map *defines)
734 {
735         node *n = new node(input, name, label, address, defines);
736         if (!n->valid)
737         {
738                 delete n;
739                 n = 0;
740         }
741         return n;
742 }
743
744 node*
745 node::parse_dtb(input_buffer &structs, input_buffer &strings)
746 {
747         node *n = new node(structs, strings);
748         if (!n->valid)
749         {
750                 delete n;
751                 n = 0;
752         }
753         return n;
754 }
755
756 node::~node()
757 {
758         while (!children.empty())
759         {
760                 delete children.back();
761                 children.pop_back();
762         }
763         while (!properties.empty())
764         {
765                 delete properties.back();
766                 properties.pop_back();
767         }
768 }
769
770 property*
771 node::get_property(string key)
772 {
773         for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i)
774         {
775                 if ((*i)->get_key() == key)
776                 {
777                         return *i;
778                 }
779         }
780         return 0;
781 }
782
783 void
784 node::merge_node(node *other)
785 {
786         if (!other->label.empty())
787         {
788                 label = other->label;
789         }
790         // Note: this is an O(n*m) operation.  It might be sensible to
791         // optimise this if we find that there are nodes with very
792         // large numbers of properties, but for typical usage the
793         // entire vector will fit (easily) into cache, so iterating
794         // over it repeatedly isn't that expensive.
795         while (!other->properties.empty())
796         {
797                 property *p = other->properties.front();
798                 for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i)
799                 {
800                         if ((*i)->get_key() == p->get_key())
801                         {
802                                 delete *i;
803                                 properties.erase(i);
804                                 break;
805                         }
806                 }
807                 add_property(p);
808                 other->properties.erase(other->properties.begin());
809         }
810         while (!other->children.empty())
811         {
812                 node *c = other->children.front();
813                 bool found = false;
814                 for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i)
815                 {
816                         if ((*i)->name == c->name && (*i)->unit_address == c->unit_address)
817                         {
818                                 (*i)->merge_node(c);
819                                 delete c;
820                                 found = true;
821                                 break;
822                         }
823                 }
824                 if (!found)
825                 {
826                         children.push_back(c);
827                 }
828                 other->children.erase(other->children.begin());
829         }
830 }
831
832 void
833 node::write(dtb::output_writer &writer, dtb::string_table &strings)
834 {
835         writer.write_token(dtb::FDT_BEGIN_NODE);
836         byte_buffer name_buffer;
837         name.push_to_buffer(name_buffer);
838         if (unit_address != string())
839         {
840                 name_buffer.push_back('@');
841                 unit_address.push_to_buffer(name_buffer);
842         }
843         writer.write_comment(name);
844         writer.write_data(name_buffer);
845         writer.write_data((uint8_t)0);
846         for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i)
847         {
848                 (*i)->write(writer, strings);
849         }
850         for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i)
851         {
852                 (*i)->write(writer, strings);
853         }
854         writer.write_token(dtb::FDT_END_NODE);
855 }
856
857 void
858 node::write_dts(FILE *file, int indent)
859 {
860         for (int i=0 ; i<indent ; i++)
861         {
862                 putc('\t', file);
863         }
864         if (label != string())
865         {
866                 label.print(file);
867                 fputs(": ", file);
868         }
869         if (name != string())
870         {
871                 name.print(file);
872         }
873         if (unit_address != string())
874         {
875                 putc('@', file);
876                 unit_address.print(file);
877         }
878         fputs(" {\n\n", file);
879         for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i)
880         {
881                 (*i)->write_dts(file, indent+1);
882         }
883         for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i)
884         {
885                 (*i)->write_dts(file, indent+1);
886         }
887         for (int i=0 ; i<indent ; i++)
888         {
889                 putc('\t', file);
890         }
891         fputs("};\n", file);
892 }
893
894 void
895 device_tree::collect_names_recursive(node* n, node_path &path)
896 {
897         string name = n->label;
898         path.push_back(std::make_pair(n->name, n->unit_address));
899         if (name != string())
900         {
901                 if (node_names.find(name) == node_names.end())
902                 {
903                         node_names.insert(std::make_pair(name, n));
904                         node_paths.insert(std::make_pair(name, path));
905                 }
906                 else
907                 {
908                         node_names[name] = (node*)-1;
909                         std::map<string, node_path>::iterator i = node_paths.find(name);
910                         if (i != node_paths.end())
911                         {
912                                 node_paths.erase(name);
913                         }
914                         fprintf(stderr, "Label not unique: ");
915                         name.dump();
916                         fprintf(stderr, ".  References to this label will not be resolved.");
917                 }
918         }
919         for (node::child_iterator i=n->child_begin(), e=n->child_end() ; i!=e ; ++i)
920         {
921                 collect_names_recursive(*i, path);
922         }
923         path.pop_back();
924         // Now we collect the phandles and properties that reference
925         // other nodes.
926         for (node::property_iterator i=n->property_begin(), e=n->property_end() ; i!=e ; ++i)
927         {
928                 for (property::value_iterator p=(*i)->begin(),pe=(*i)->end() ; p!=pe ; ++p)
929                 {
930                         if (p->is_phandle())
931                         {
932                                 phandles.push_back(&*p);
933                         }
934                         if (p->is_cross_reference())
935                         {
936                                 cross_references.push_back(&*p);
937                         }
938                 }
939                 if ((*i)->get_key() == string("phandle") ||
940                     (*i)->get_key() == string("linux,phandle"))
941                 {
942                         if ((*i)->begin()->byte_data.size() != 4)
943                         {
944                                 fprintf(stderr, "Invalid phandle value for node ");
945                                 n->name.dump();
946                                 fprintf(stderr, ".  Should be a 4-byte value.\n");
947                                 valid = false;
948                         }
949                         else
950                         {
951                                 uint32_t phandle = (*i)->begin()->get_as_uint32();
952                                 used_phandles.insert(std::make_pair(phandle, n));
953                         }
954                 }
955         }
956 }
957
958 void
959 device_tree::collect_names()
960 {
961         node_path p;
962         collect_names_recursive(root, p);
963 }
964
965 void
966 device_tree::resolve_cross_references()
967 {
968         for (std::vector<property_value*>::iterator i=cross_references.begin(), e=cross_references.end() ; i!=e ; ++i)
969         {
970                 property_value* pv = *i;
971                 node_path path = node_paths[pv->string_data];
972                 // Skip the first name in the path.  It's always "", and implicitly /
973                 for (node_path::iterator p=path.begin()+1, pe=path.end() ; p!=pe ; ++p)
974                 {
975                         pv->byte_data.push_back('/');
976                         p->first.push_to_buffer(pv->byte_data);
977                         if (!(p->second.empty()))
978                         {
979                                 pv->byte_data.push_back('@');
980                                 p->second.push_to_buffer(pv->byte_data);
981                         }
982                 }
983                 pv->byte_data.push_back(0);
984         }
985         uint32_t phandle = 1;
986         for (std::vector<property_value*>::iterator i=phandles.begin(), e=phandles.end() ; i!=e ; ++i)
987         {
988                 string target_name = (*i)->string_data;
989                 node *target = node_names[target_name];
990                 if (target == 0)
991                 {
992                         fprintf(stderr, "Failed to find node with label:");
993                         target_name.dump();
994                         fprintf(stderr, "\n");
995                         valid = 0;
996                         return;
997                 }
998                 // If there is an existing phandle, use it
999                 property *p = target->get_property("phandle");
1000                 if (p == 0)
1001                 {
1002                         p = target->get_property("linux,phandle");
1003                 }
1004                 if (p == 0)
1005                 {
1006                         // Otherwise insert a new phandle node
1007                         property_value v;
1008                         while (used_phandles.find(phandle) != used_phandles.end())
1009                         {
1010                                 // Note that we only don't need to
1011                                 // store this phandle in the set,
1012                                 // because we are monotonically
1013                                 // increasing the value of phandle and
1014                                 // so will only ever revisit this value
1015                                 // if we have used 2^32 phandles, at
1016                                 // which point our blob won't fit in
1017                                 // any 32-bit system and we've done
1018                                 // something badly wrong elsewhere
1019                                 // already.
1020                                 phandle++;
1021                         }
1022                         push_big_endian(v.byte_data, phandle++);
1023                         if (phandle_node_name == BOTH || phandle_node_name == LINUX)
1024                         {
1025                                 p = new property(string("linux,phandle"));
1026                                 p->add_value(v);
1027                                 target->add_property(p);
1028                         }
1029                         if (phandle_node_name == BOTH || phandle_node_name == EPAPR)
1030                         {
1031                                 p = new property(string("phandle"));
1032                                 p->add_value(v);
1033                                 target->add_property(p);
1034                         }
1035                 }
1036                 p->begin()->push_to_buffer((*i)->byte_data);
1037                 assert((*i)->byte_data.size() == 4);
1038         }
1039 }
1040
1041 void
1042 device_tree::parse_roots(input_buffer &input, std::vector<node*> &roots)
1043 {
1044         input.next_token();
1045         while (valid && input.consume('/'))
1046         {
1047                 input.next_token();
1048                 node *n = node::parse(input, string("", 1), string(), string(), &defines);
1049                 if (n)
1050                 {
1051                         roots.push_back(n);
1052                 }
1053                 else
1054                 {
1055                         valid = false;
1056                 }
1057                 input.next_token();
1058         }
1059 }
1060
1061 input_buffer*
1062 device_tree::buffer_for_file(const char *path)
1063 {
1064         if (string(path) == string("-"))
1065         {
1066                 input_buffer *b = new stream_input_buffer();
1067                 buffers.push_back(b);
1068                 return b;
1069         }
1070         int source = open(path, O_RDONLY);
1071         if (source == -1)
1072         {
1073                 fprintf(stderr, "Unable to open file %s\n", path);
1074                 return 0;
1075         }
1076         input_buffer *b = new mmap_input_buffer(source);
1077         // Keep the buffer that owns the memory around for the lifetime
1078         // of this FDT.  Ones simply referring to it may have shorter
1079         // lifetimes.
1080         buffers.push_back(b);
1081         close(source);
1082         return b;
1083 }
1084
1085 template<class writer> void
1086 device_tree::write(int fd)
1087 {
1088         dtb::string_table st;
1089         dtb::header head;
1090         writer head_writer;
1091         writer reservation_writer;
1092         writer struct_writer;
1093         writer strings_writer;
1094
1095         // Build the reservation table
1096         reservation_writer.write_comment(string("Memory reservations"));
1097         reservation_writer.write_label(string("dt_reserve_map"));
1098         for (std::vector<reservation>::iterator i=reservations.begin(),
1099              e=reservations.end() ; i!=e ; ++i)
1100         {
1101                 reservation_writer.write_comment(string("Reservation start"));
1102                 reservation_writer.write_data(i->first);
1103                 reservation_writer.write_comment(string("Reservation length"));
1104                 reservation_writer.write_data(i->first);
1105         }
1106         // Write n spare reserve map entries, plus the trailing 0.
1107         for (uint32_t i=0 ; i<=spare_reserve_map_entries ; i++)
1108         {
1109                 reservation_writer.write_data((uint64_t)0);
1110                 reservation_writer.write_data((uint64_t)0);
1111         }
1112
1113
1114         struct_writer.write_comment(string("Device tree"));
1115         struct_writer.write_label(string("dt_struct_start"));
1116         root->write(struct_writer, st);
1117         struct_writer.write_token(dtb::FDT_END);
1118         struct_writer.write_label(string("dt_struct_end"));
1119
1120         st.write(strings_writer);
1121         // Find the strings size before we stick padding on the end.
1122         // Note: We should possibly use a new writer for the padding.
1123         head.size_dt_strings = strings_writer.size();
1124
1125         // Stick the padding in the strings writer, but after the
1126         // marker indicating that it's the end.
1127         // Note: We probably should add a padding call to the writer so
1128         // that the asm back end can write padding directives instead
1129         // of a load of 0 bytes.
1130         for (uint32_t i=0 ; i<blob_padding ; i++)
1131         {
1132                 strings_writer.write_data((uint8_t)0);
1133         }
1134         head.totalsize = sizeof(head) + strings_writer.size() +
1135                 struct_writer.size() + reservation_writer.size();
1136         while (head.totalsize < minimum_blob_size)
1137         {
1138                 head.totalsize++;
1139                 strings_writer.write_data((uint8_t)0);
1140         }
1141         head.off_dt_struct = sizeof(head) + reservation_writer.size();;
1142         head.off_dt_strings = head.off_dt_struct + struct_writer.size();
1143         head.off_mem_rsvmap = sizeof(head);
1144         head.boot_cpuid_phys = boot_cpu;
1145         head.size_dt_struct = struct_writer.size();
1146         head.write(head_writer);
1147
1148         head_writer.write_to_file(fd);
1149         reservation_writer.write_to_file(fd);
1150         struct_writer.write_to_file(fd);
1151         strings_writer.write_label(string("dt_blob_end"));
1152         strings_writer.write_to_file(fd);
1153 }
1154
1155 node*
1156 device_tree::referenced_node(property_value &v)
1157 {
1158         if (v.is_phandle())
1159         {
1160                 return node_names[v.string_data];
1161         }
1162         if (v.is_binary())
1163         {
1164                 return used_phandles[v.get_as_uint32()];
1165         }
1166         return 0;
1167 }
1168
1169 void
1170 device_tree::write_binary(int fd)
1171 {
1172         write<dtb::binary_writer>(fd);
1173 }
1174
1175 void
1176 device_tree::write_asm(int fd)
1177 {
1178         write<dtb::asm_writer>(fd);
1179 }
1180
1181 void
1182 device_tree::write_dts(int fd)
1183 {
1184         FILE *file = fdopen(fd, "w");
1185         fputs("/dtc-v1/;\n\n", file);
1186
1187         if (!reservations.empty())
1188         {
1189                 const char msg[] = "/memreserve/";
1190                 fwrite(msg, sizeof(msg), 1, file);
1191                 for (std::vector<reservation>::iterator i=reservations.begin(),
1192                      e=reservations.end() ; i!=e ; ++i)
1193                 {
1194                         fprintf(stderr, " %" PRIx64 " %" PRIx64, i->first, i->second);
1195                 }
1196                 fputs(";\n\n", file);
1197         }
1198         putc('/', file);
1199         putc(' ', file);
1200         root->write_dts(file, 0);
1201         fclose(file);
1202 }
1203
1204 void
1205 device_tree::parse_dtb(const char *fn, FILE *depfile)
1206 {
1207         input_buffer *in = buffer_for_file(fn);
1208         if (in == 0)
1209         {
1210                 valid = false;
1211                 return;
1212         }
1213         input_buffer &input = *in;
1214         dtb::header h;
1215         valid = h.read_dtb(input);
1216         boot_cpu = h.boot_cpuid_phys;
1217         if (h.last_comp_version > 17)
1218         {
1219                 fprintf(stderr, "Don't know how to read this version of the device tree blob");
1220                 valid = false;
1221         }
1222         if (!valid)
1223         {
1224                 return;
1225         }
1226         input_buffer reservation_map =
1227                 input.buffer_from_offset(h.off_mem_rsvmap, 0);
1228         uint64_t start, length;
1229         do
1230         {
1231                 if (!(reservation_map.consume_binary(start) &&
1232                       reservation_map.consume_binary(length)))
1233                 {
1234                         fprintf(stderr, "Failed to read memory reservation table\n");
1235                         valid = false;
1236                         return;
1237                 }
1238         } while (!((start == 0) && (length == 0)));
1239         input_buffer struct_table =
1240                 input.buffer_from_offset(h.off_dt_struct, h.size_dt_struct);
1241         input_buffer strings_table =
1242                 input.buffer_from_offset(h.off_dt_strings, h.size_dt_strings);
1243         uint32_t token;
1244         if (!(struct_table.consume_binary(token) &&
1245                 (token == dtb::FDT_BEGIN_NODE)))
1246         {
1247                 fprintf(stderr, "Expected FDT_BEGIN_NODE token.\n");
1248                 valid = false;
1249                 return;
1250         }
1251         root = node::parse_dtb(struct_table, strings_table);
1252         if (!(struct_table.consume_binary(token) && (token == dtb::FDT_END)))
1253         {
1254                 fprintf(stderr, "Expected FDT_END token after parsing root node.\n");
1255                 valid = false;
1256                 return;
1257         }
1258         valid = (root != 0);
1259 }
1260
1261 void
1262 device_tree::parse_dts(const char *fn, FILE *depfile)
1263 {
1264         input_buffer *in = buffer_for_file(fn);
1265         if (in == 0)
1266         {
1267                 valid = false;
1268                 return;
1269         }
1270         std::vector<node*> roots;
1271         input_buffer &input = *in;
1272         input.next_token();
1273         bool read_header = false;
1274         // Read the header
1275         if (input.consume("/dts-v1/;"))
1276         {
1277                 read_header = true;
1278         }
1279         input.next_token();
1280         while(input.consume("/include/"))
1281         {
1282                 bool reallyInclude = true;
1283                 if (input.consume("if "))
1284                 {
1285                         input.next_token();
1286                         string name = string::parse_property_name(input);
1287                         // XXX: Error handling
1288                         if (defines.find(name) == defines.end())
1289                         {
1290                                 reallyInclude = false;
1291                         }
1292                         input.consume('/');
1293                 }
1294                 input.next_token();
1295                 if (!input.consume('"'))
1296                 {
1297                         input.parse_error("Expected quoted filename");
1298                         valid = false;
1299                         return;
1300                 }
1301                 int length = 0;
1302                 while (input[length] != '"') length++;
1303
1304                 const char *file = (const char*)input;
1305                 const char *dir = dirname(fn);
1306                 int dir_length = strlen(dir);
1307                 char *include_file = (char*)malloc(strlen(dir) + length + 2);
1308                 memcpy(include_file, dir, dir_length);
1309                 include_file[dir_length] = '/';
1310                 memcpy(include_file+dir_length+1, file, length);
1311                 include_file[dir_length+length+1] = 0;
1312
1313                 input.consume(include_file+dir_length+1);
1314                 input.consume('"');
1315                 if (!reallyInclude)
1316                 {
1317                         continue;
1318                 }
1319
1320                 input_buffer *include_buffer = buffer_for_file(include_file);
1321
1322                 if (include_buffer == 0)
1323                 {
1324                         for (std::vector<const char*>::iterator i=include_paths.begin(), e=include_paths.end() ; e!=i ; ++i)
1325                         {
1326                                 free(include_file);
1327                                 dir = *i;
1328                                 dir_length = strlen(dir);
1329                                 include_file = (char*)malloc(strlen(dir) +
1330                                                 length + 2);
1331                                 memcpy(include_file, dir, dir_length);
1332                                 include_file[dir_length] = '/';
1333                                 memcpy(include_file+dir_length+1, file, length);
1334                                 include_file[dir_length+length+1] = 0;
1335                                 include_buffer = buffer_for_file(include_file);
1336                                 if (include_buffer != 0)
1337                                 {
1338                                         break;
1339                                 }
1340                         }
1341                 }
1342                 if (depfile != 0)
1343                 {
1344                         putc(' ', depfile);
1345                         fputs(include_file, depfile);
1346                 }
1347                 if (include_buffer == 0)
1348                 {
1349                         valid = false;
1350                         return;
1351                 }
1352                 input_buffer &include = *include_buffer;
1353                 free((void*)include_file);
1354
1355                 if (!read_header)
1356                 {
1357                         include.next_token();
1358                         read_header = include.consume("/dts-v1/;");
1359                 }
1360                 parse_roots(include, roots);
1361         }
1362         input.next_token();
1363         if (!read_header)
1364         {
1365                 input.parse_error("Expected /dts-v1/; version string");
1366         }
1367         // Read any memory reservations
1368         while(input.consume("/memreserve/"))
1369         {
1370                 long long start, len;
1371                 input.next_token();
1372                 // Read the start and length.
1373                 if (!(input.consume_integer(start) &&
1374                     (input.next_token(),
1375                     input.consume_integer(len))))
1376                 {
1377                         input.parse_error("Expected size on /memreserve/ node.");
1378                 }
1379                 input.next_token();
1380                 input.consume(';');
1381                 reservations.push_back(reservation(start, len));
1382         }
1383         parse_roots(input, roots);
1384         switch (roots.size())
1385         {
1386                 case 0:
1387                         valid = false;
1388                         input.parse_error("Failed to find root node /.");
1389                         return;
1390                 case 1:
1391                         root = roots[0];
1392                         break;
1393                 default:
1394                 {
1395                         root = roots[0];
1396                         for (std::vector<node*>::iterator i=roots.begin()+1,
1397                              e=roots.end() ; i!=e ; ++i)
1398                         {
1399                                 root->merge_node(*i);
1400                                 delete *i;
1401                         }
1402                         roots.resize(1);
1403                 }
1404         }
1405         collect_names();
1406         resolve_cross_references();
1407 }
1408
1409 device_tree::~device_tree()
1410 {
1411         if (root != 0)
1412         {
1413                 delete root;
1414         }
1415         while (!buffers.empty())
1416         {
1417                 delete buffers.back();
1418                 buffers.pop_back();
1419         }
1420         for (define_map::iterator i=defines.begin(), e=defines.end() ;
1421              i!=e ; ++i)
1422         {
1423                 delete i->second;
1424         }
1425 }
1426
1427 bool device_tree::parse_define(const char *def)
1428 {
1429         char *val = strchr(def, '=');
1430         if (!val)
1431         {
1432                 if (strlen(def) != 0)
1433                 {
1434                         string name(def);
1435                         defines[name];
1436                         return true;
1437                 }
1438                 return false;
1439         }
1440         string name(def, val-def);
1441         val++;
1442         input_buffer in = input_buffer(val, strlen(val));
1443         property *p = property::parse(in, name, string(), false);
1444         if (p)
1445                 defines[name] = p;
1446         return p;
1447 }
1448
1449 } // namespace fdt
1450
1451 } // namespace dtc
1452