]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/dtc/fdt.cc
Upgrade to OpenSSH 6.6p1.
[FreeBSD/FreeBSD.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)) || bytes == 0)
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, "%02hhx", *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
371         // If we're empty, do not push anything as value.
372         if (!length)
373                 return;
374
375         // Read the value
376         uint8_t byte;
377         property_value v;
378         for (uint32_t i=0 ; i<length ; i++)
379         {
380                 if (!(valid = structs.consume_binary(byte)))
381                 {
382                         fprintf(stderr, "Failed to read property value\n");
383                         return;
384                 }
385                 v.byte_data.push_back(byte);
386         }
387         values.push_back(v);
388 }
389
390 void property::parse_define(input_buffer &input, define_map *defines)
391 {
392         input.consume('$');
393         if (!defines)
394         {
395                 input.parse_error("No predefined properties to match name\n");
396                 valid = false;
397                 return;
398         }
399         string name = string::parse_property_name(input);
400         define_map::iterator found;
401         if ((name == string()) ||
402             ((found = defines->find(name)) == defines->end()))
403         {
404                 input.parse_error("Undefined property name\n");
405                 valid = false;
406                 return;
407         }
408         values.push_back((*found).second->values[0]);
409 }
410
411 property::property(input_buffer &input,
412                    string k,
413                    string l,
414                    bool semicolonTerminated,
415                    define_map *defines) : key(k), label(l), valid(true)
416 {
417         do {
418                 input.next_token();
419                 switch (input[0])
420                 {
421                         case '$':
422                         {
423                                 parse_define(input, defines);
424                                 if (valid)
425                                 {
426                                         break;
427                                 }
428                         }
429                         default:
430                                 input.parse_error("Invalid property value.");
431                                 valid = false;
432                                 return;
433                         case '"':
434                                 parse_string(input);
435                                 break;
436                         case '<':
437                                 parse_cells(input);
438                                 break;
439                         case '[':
440                                 parse_bytes(input);
441                                 break;
442                         case '&':
443                                 parse_reference(input);
444                                 break;
445                         case ';':
446                         {
447                                 break;
448                         }
449                 }
450                 input.next_token();
451         } while (input.consume(','));
452         if (semicolonTerminated && !input.consume(';'))
453         {
454                 input.parse_error("Expected ; at end of property");
455                 valid = false;
456         }
457 }
458
459 property*
460 property::parse_dtb(input_buffer &structs, input_buffer &strings)
461 {
462         property *p = new property(structs, strings);
463         if (!p->valid)
464         {
465                 delete p;
466                 p = 0;
467         }
468         return p;
469 }
470
471 property*
472 property::parse(input_buffer &input, string key, string label,
473                 bool semicolonTerminated, define_map *defines)
474 {
475         property *p = new property(input, key, label, semicolonTerminated, defines);
476         if (!p->valid)
477         {
478                 delete p;
479                 p = 0;
480         }
481         return p;
482 }
483
484 void
485 property::write(dtb::output_writer &writer, dtb::string_table &strings)
486 {
487         writer.write_token(dtb::FDT_PROP);
488         byte_buffer value_buffer;
489         for (value_iterator i=begin(), e=end() ; i!=e ; ++i)
490         {
491                 i->push_to_buffer(value_buffer);
492         }
493         writer.write_data((uint32_t)value_buffer.size());
494         writer.write_comment(key);
495         writer.write_data(strings.add_string(key));
496         writer.write_data(value_buffer);
497 }
498
499 void
500 property::write_dts(FILE *file, int indent)
501 {
502         for (int i=0 ; i<indent ; i++)
503         {
504                 putc('\t', file);
505         }
506         if (label != string())
507         {
508                 label.print(file);
509                 fputs(": ", file);
510         }
511         if (key != string())
512         {
513                 key.print(file);
514         }
515         if (!values.empty())
516         {
517                 fputs(" = ", file);
518                 for (value_iterator i=begin(), e=end() ; i!=e ; ++i)
519                 {
520                         i->write_dts(file);
521                         if (i+1 != e)
522                         {
523                                 putc(',', file);
524                                 putc(' ', file);
525                         }
526                 }
527         }
528         fputs(";\n", file);
529 }
530
531 string
532 node::parse_name(input_buffer &input, bool &is_property, const char *error)
533 {
534         if (!valid)
535         {
536                 return string();
537         }
538         input.next_token();
539         if (is_property)
540         {
541                 return string::parse_property_name(input);
542         }
543         string n = string::parse_node_or_property_name(input, is_property);
544         if (n.empty())
545         {
546                 if (n.empty())
547                 {
548                         input.parse_error(error);
549                         valid = false;
550                 }
551         }
552         return n;
553 }
554
555 node::node(input_buffer &structs, input_buffer &strings) : valid(true)
556 {
557         const char *name_start = (const char*)structs;
558         int name_length = 0;
559         while (structs[0] != '\0' && structs[0] != '@')
560         {
561                 name_length++;
562                 ++structs;
563         }
564         name = string(name_start, name_length);
565         if (structs[0] == '@')
566         {
567                 ++structs;
568                 name_start = (const char*)structs;
569                 name_length = 0;
570                 while (structs[0] != '\0')
571                 {
572                         name_length++;
573                         ++structs;
574                 }
575                 unit_address = string(name_start, name_length);
576         }
577         ++structs;
578         uint32_t token;
579         while (structs.consume_binary(token))
580         {
581                 switch (token)
582                 {
583                         default:
584                                 fprintf(stderr, "Unexpected token 0x%" PRIx32
585                                         " while parsing node.\n", token);
586                                 valid = false;
587                                 return;
588                         // Child node, parse it.
589                         case dtb::FDT_BEGIN_NODE:
590                         {
591                                 node *child = node::parse_dtb(structs, strings);
592                                 if (child == 0)
593                                 {
594                                         valid = false;
595                                         return;
596                                 }
597                                 children.push_back(child);
598                                 break;
599                         }
600                         // End of this node, no errors.
601                         case dtb::FDT_END_NODE:
602                                 return;
603                         // Property, parse it.
604                         case dtb::FDT_PROP:
605                         {
606                                 property *prop = property::parse_dtb(structs, strings);
607                                 if (prop == 0)
608                                 {
609                                         valid = false;
610                                         return;
611                                 }
612                                 properties.push_back(prop);
613                                 break;
614                         }
615                                 break;
616                         // End of structs table.  Should appear after
617                         // the end of the last node.
618                         case dtb::FDT_END:
619                                 fprintf(stderr, "Unexpected FDT_END token while parsing node.\n");
620                                 valid = false;
621                                 return;
622                         // NOPs are padding.  Ignore them.
623                         case dtb::FDT_NOP:
624                                 break;
625                 }
626         }
627         fprintf(stderr, "Failed to read token from structs table while parsing node.\n");
628         valid = false;
629         return;
630 }
631
632 node::node(input_buffer &input, string n, string l, string a, define_map *defines) : 
633         label(l), name(n), unit_address(a), valid(true)
634 {
635         if (!input.consume('{'))
636         {
637                 input.parse_error("Expected { to start new device tree node.\n");
638         }
639         input.next_token();
640         while (valid && !input.consume('}'))
641         {
642                 // flag set if we find any characters that are only in
643                 // the property name character set, not the node 
644                 bool is_property = false;
645                 string child_name, child_label, child_address;
646                 child_name = parse_name(input, is_property,
647                                 "Expected property or node name");
648                 if (input.consume(':'))
649                 {
650                         // Node labels can contain any characters?  The
651                         // spec doesn't say, so we guess so...
652                         is_property = false;
653                         child_label = child_name;
654                         child_name = parse_name(input, is_property, "Expected property or node name");
655                 }
656                 if (input.consume('@'))
657                 {
658                         child_address = parse_name(input, is_property, "Expected unit address");
659                 }
660                 if (!valid)
661                 {
662                         return;
663                 }
664                 input.next_token();
665                 // If we're parsing a property, then we must actually do that.
666                 if (input.consume('='))
667                 {
668                         property *p= property::parse(input, child_name,
669                                         child_label, true, defines);
670                         if (p == 0)
671                         {
672                                 valid = false;
673                         }
674                         else
675                         {
676                                 properties.push_back(p);
677                         }
678                 }
679                 else if (!is_property && input[0] == ('{'))
680                 {
681                         node *child = node::parse(input, child_name,
682                                         child_label, child_address, defines);
683                         if (child)
684                         {
685                                 children.push_back(child);
686                         }
687                         else
688                         {
689                                 valid = false;
690                         }
691                 }
692                 else if (input.consume(';'))
693                 {
694                         properties.push_back(new property(child_name, child_label));
695                 }
696                 else
697                 {
698                         input.parse_error("Error parsing property.");
699                         valid = false;
700                 }
701                 input.next_token();
702         }
703         input.consume(';');
704 }
705
706 bool
707 node::cmp_properties(property *p1, property *p2)
708 {
709         return p1->get_key() < p2->get_key();
710 }
711
712 bool
713 node::cmp_children(node *c1, node *c2)
714 {
715         if (c1->name == c2->name)
716         {
717                 return c1->unit_address < c2->unit_address;
718         }
719         return c1->name < c2->name;
720 }
721
722 void
723 node::sort()
724 {
725         std::sort(property_begin(), property_end(), cmp_properties);
726         std::sort(child_begin(), child_end(), cmp_children);
727         for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i)
728         {
729                 (*i)->sort();
730         }
731 }
732
733 node*
734 node::parse(input_buffer &input,
735             string name,
736             string label,
737             string address,
738             define_map *defines)
739 {
740         node *n = new node(input, name, label, address, defines);
741         if (!n->valid)
742         {
743                 delete n;
744                 n = 0;
745         }
746         return n;
747 }
748
749 node*
750 node::parse_dtb(input_buffer &structs, input_buffer &strings)
751 {
752         node *n = new node(structs, strings);
753         if (!n->valid)
754         {
755                 delete n;
756                 n = 0;
757         }
758         return n;
759 }
760
761 node::~node()
762 {
763         while (!children.empty())
764         {
765                 delete children.back();
766                 children.pop_back();
767         }
768         while (!properties.empty())
769         {
770                 delete properties.back();
771                 properties.pop_back();
772         }
773 }
774
775 property*
776 node::get_property(string key)
777 {
778         for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i)
779         {
780                 if ((*i)->get_key() == key)
781                 {
782                         return *i;
783                 }
784         }
785         return 0;
786 }
787
788 void
789 node::merge_node(node *other)
790 {
791         if (!other->label.empty())
792         {
793                 label = other->label;
794         }
795         // Note: this is an O(n*m) operation.  It might be sensible to
796         // optimise this if we find that there are nodes with very
797         // large numbers of properties, but for typical usage the
798         // entire vector will fit (easily) into cache, so iterating
799         // over it repeatedly isn't that expensive.
800         while (!other->properties.empty())
801         {
802                 property *p = other->properties.front();
803                 for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i)
804                 {
805                         if ((*i)->get_key() == p->get_key())
806                         {
807                                 delete *i;
808                                 properties.erase(i);
809                                 break;
810                         }
811                 }
812                 add_property(p);
813                 other->properties.erase(other->properties.begin());
814         }
815         while (!other->children.empty())
816         {
817                 node *c = other->children.front();
818                 bool found = false;
819                 for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i)
820                 {
821                         if ((*i)->name == c->name && (*i)->unit_address == c->unit_address)
822                         {
823                                 (*i)->merge_node(c);
824                                 delete c;
825                                 found = true;
826                                 break;
827                         }
828                 }
829                 if (!found)
830                 {
831                         children.push_back(c);
832                 }
833                 other->children.erase(other->children.begin());
834         }
835 }
836
837 void
838 node::write(dtb::output_writer &writer, dtb::string_table &strings)
839 {
840         writer.write_token(dtb::FDT_BEGIN_NODE);
841         byte_buffer name_buffer;
842         name.push_to_buffer(name_buffer);
843         if (unit_address != string())
844         {
845                 name_buffer.push_back('@');
846                 unit_address.push_to_buffer(name_buffer);
847         }
848         writer.write_comment(name);
849         writer.write_data(name_buffer);
850         writer.write_data((uint8_t)0);
851         for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i)
852         {
853                 (*i)->write(writer, strings);
854         }
855         for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i)
856         {
857                 (*i)->write(writer, strings);
858         }
859         writer.write_token(dtb::FDT_END_NODE);
860 }
861
862 void
863 node::write_dts(FILE *file, int indent)
864 {
865         for (int i=0 ; i<indent ; i++)
866         {
867                 putc('\t', file);
868         }
869         if (label != string())
870         {
871                 label.print(file);
872                 fputs(": ", file);
873         }
874         if (name != string())
875         {
876                 name.print(file);
877         }
878         if (unit_address != string())
879         {
880                 putc('@', file);
881                 unit_address.print(file);
882         }
883         fputs(" {\n\n", file);
884         for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i)
885         {
886                 (*i)->write_dts(file, indent+1);
887         }
888         for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i)
889         {
890                 (*i)->write_dts(file, indent+1);
891         }
892         for (int i=0 ; i<indent ; i++)
893         {
894                 putc('\t', file);
895         }
896         fputs("};\n", file);
897 }
898
899 void
900 device_tree::collect_names_recursive(node* n, node_path &path)
901 {
902         string name = n->label;
903         path.push_back(std::make_pair(n->name, n->unit_address));
904         if (name != string())
905         {
906                 if (node_names.find(name) == node_names.end())
907                 {
908                         node_names.insert(std::make_pair(name, n));
909                         node_paths.insert(std::make_pair(name, path));
910                 }
911                 else
912                 {
913                         node_names[name] = (node*)-1;
914                         std::map<string, node_path>::iterator i = node_paths.find(name);
915                         if (i != node_paths.end())
916                         {
917                                 node_paths.erase(name);
918                         }
919                         fprintf(stderr, "Label not unique: ");
920                         name.dump();
921                         fprintf(stderr, ".  References to this label will not be resolved.");
922                 }
923         }
924         for (node::child_iterator i=n->child_begin(), e=n->child_end() ; i!=e ; ++i)
925         {
926                 collect_names_recursive(*i, path);
927         }
928         path.pop_back();
929         // Now we collect the phandles and properties that reference
930         // other nodes.
931         for (node::property_iterator i=n->property_begin(), e=n->property_end() ; i!=e ; ++i)
932         {
933                 for (property::value_iterator p=(*i)->begin(),pe=(*i)->end() ; p!=pe ; ++p)
934                 {
935                         if (p->is_phandle())
936                         {
937                                 phandles.push_back(&*p);
938                         }
939                         if (p->is_cross_reference())
940                         {
941                                 cross_references.push_back(&*p);
942                         }
943                 }
944                 if ((*i)->get_key() == string("phandle") ||
945                     (*i)->get_key() == string("linux,phandle"))
946                 {
947                         if ((*i)->begin()->byte_data.size() != 4)
948                         {
949                                 fprintf(stderr, "Invalid phandle value for node ");
950                                 n->name.dump();
951                                 fprintf(stderr, ".  Should be a 4-byte value.\n");
952                                 valid = false;
953                         }
954                         else
955                         {
956                                 uint32_t phandle = (*i)->begin()->get_as_uint32();
957                                 used_phandles.insert(std::make_pair(phandle, n));
958                         }
959                 }
960         }
961 }
962
963 void
964 device_tree::collect_names()
965 {
966         node_path p;
967         collect_names_recursive(root, p);
968 }
969
970 void
971 device_tree::resolve_cross_references()
972 {
973         for (std::vector<property_value*>::iterator i=cross_references.begin(), e=cross_references.end() ; i!=e ; ++i)
974         {
975                 property_value* pv = *i;
976                 node_path path = node_paths[pv->string_data];
977                 // Skip the first name in the path.  It's always "", and implicitly /
978                 for (node_path::iterator p=path.begin()+1, pe=path.end() ; p!=pe ; ++p)
979                 {
980                         pv->byte_data.push_back('/');
981                         p->first.push_to_buffer(pv->byte_data);
982                         if (!(p->second.empty()))
983                         {
984                                 pv->byte_data.push_back('@');
985                                 p->second.push_to_buffer(pv->byte_data);
986                         }
987                 }
988                 pv->byte_data.push_back(0);
989         }
990         uint32_t phandle = 1;
991         for (std::vector<property_value*>::iterator i=phandles.begin(), e=phandles.end() ; i!=e ; ++i)
992         {
993                 string target_name = (*i)->string_data;
994                 node *target = node_names[target_name];
995                 if (target == 0)
996                 {
997                         fprintf(stderr, "Failed to find node with label:");
998                         target_name.dump();
999                         fprintf(stderr, "\n");
1000                         valid = 0;
1001                         return;
1002                 }
1003                 // If there is an existing phandle, use it
1004                 property *p = target->get_property("phandle");
1005                 if (p == 0)
1006                 {
1007                         p = target->get_property("linux,phandle");
1008                 }
1009                 if (p == 0)
1010                 {
1011                         // Otherwise insert a new phandle node
1012                         property_value v;
1013                         while (used_phandles.find(phandle) != used_phandles.end())
1014                         {
1015                                 // Note that we only don't need to
1016                                 // store this phandle in the set,
1017                                 // because we are monotonically
1018                                 // increasing the value of phandle and
1019                                 // so will only ever revisit this value
1020                                 // if we have used 2^32 phandles, at
1021                                 // which point our blob won't fit in
1022                                 // any 32-bit system and we've done
1023                                 // something badly wrong elsewhere
1024                                 // already.
1025                                 phandle++;
1026                         }
1027                         push_big_endian(v.byte_data, phandle++);
1028                         if (phandle_node_name == BOTH || phandle_node_name == LINUX)
1029                         {
1030                                 p = new property(string("linux,phandle"));
1031                                 p->add_value(v);
1032                                 target->add_property(p);
1033                         }
1034                         if (phandle_node_name == BOTH || phandle_node_name == EPAPR)
1035                         {
1036                                 p = new property(string("phandle"));
1037                                 p->add_value(v);
1038                                 target->add_property(p);
1039                         }
1040                 }
1041                 p->begin()->push_to_buffer((*i)->byte_data);
1042                 assert((*i)->byte_data.size() == 4);
1043         }
1044 }
1045
1046 void
1047 device_tree::parse_roots(input_buffer &input, std::vector<node*> &roots)
1048 {
1049         input.next_token();
1050         while (valid && input.consume('/'))
1051         {
1052                 input.next_token();
1053                 node *n = node::parse(input, string("", 1), string(), string(), &defines);
1054                 if (n)
1055                 {
1056                         roots.push_back(n);
1057                 }
1058                 else
1059                 {
1060                         valid = false;
1061                 }
1062                 input.next_token();
1063         }
1064 }
1065
1066 input_buffer*
1067 device_tree::buffer_for_file(const char *path)
1068 {
1069         if (string(path) == string("-"))
1070         {
1071                 input_buffer *b = new stream_input_buffer();
1072                 buffers.push_back(b);
1073                 return b;
1074         }
1075         int source = open(path, O_RDONLY);
1076         if (source == -1)
1077         {
1078                 fprintf(stderr, "Unable to open file %s\n", path);
1079                 return 0;
1080         }
1081         input_buffer *b = new mmap_input_buffer(source);
1082         // Keep the buffer that owns the memory around for the lifetime
1083         // of this FDT.  Ones simply referring to it may have shorter
1084         // lifetimes.
1085         buffers.push_back(b);
1086         close(source);
1087         return b;
1088 }
1089
1090 template<class writer> void
1091 device_tree::write(int fd)
1092 {
1093         dtb::string_table st;
1094         dtb::header head;
1095         writer head_writer;
1096         writer reservation_writer;
1097         writer struct_writer;
1098         writer strings_writer;
1099
1100         // Build the reservation table
1101         reservation_writer.write_comment(string("Memory reservations"));
1102         reservation_writer.write_label(string("dt_reserve_map"));
1103         for (std::vector<reservation>::iterator i=reservations.begin(),
1104              e=reservations.end() ; i!=e ; ++i)
1105         {
1106                 reservation_writer.write_comment(string("Reservation start"));
1107                 reservation_writer.write_data(i->first);
1108                 reservation_writer.write_comment(string("Reservation length"));
1109                 reservation_writer.write_data(i->first);
1110         }
1111         // Write n spare reserve map entries, plus the trailing 0.
1112         for (uint32_t i=0 ; i<=spare_reserve_map_entries ; i++)
1113         {
1114                 reservation_writer.write_data((uint64_t)0);
1115                 reservation_writer.write_data((uint64_t)0);
1116         }
1117
1118
1119         struct_writer.write_comment(string("Device tree"));
1120         struct_writer.write_label(string("dt_struct_start"));
1121         root->write(struct_writer, st);
1122         struct_writer.write_token(dtb::FDT_END);
1123         struct_writer.write_label(string("dt_struct_end"));
1124
1125         st.write(strings_writer);
1126         // Find the strings size before we stick padding on the end.
1127         // Note: We should possibly use a new writer for the padding.
1128         head.size_dt_strings = strings_writer.size();
1129
1130         // Stick the padding in the strings writer, but after the
1131         // marker indicating that it's the end.
1132         // Note: We probably should add a padding call to the writer so
1133         // that the asm back end can write padding directives instead
1134         // of a load of 0 bytes.
1135         for (uint32_t i=0 ; i<blob_padding ; i++)
1136         {
1137                 strings_writer.write_data((uint8_t)0);
1138         }
1139         head.totalsize = sizeof(head) + strings_writer.size() +
1140                 struct_writer.size() + reservation_writer.size();
1141         while (head.totalsize < minimum_blob_size)
1142         {
1143                 head.totalsize++;
1144                 strings_writer.write_data((uint8_t)0);
1145         }
1146         head.off_dt_struct = sizeof(head) + reservation_writer.size();;
1147         head.off_dt_strings = head.off_dt_struct + struct_writer.size();
1148         head.off_mem_rsvmap = sizeof(head);
1149         head.boot_cpuid_phys = boot_cpu;
1150         head.size_dt_struct = struct_writer.size();
1151         head.write(head_writer);
1152
1153         head_writer.write_to_file(fd);
1154         reservation_writer.write_to_file(fd);
1155         struct_writer.write_to_file(fd);
1156         strings_writer.write_label(string("dt_blob_end"));
1157         strings_writer.write_to_file(fd);
1158 }
1159
1160 node*
1161 device_tree::referenced_node(property_value &v)
1162 {
1163         if (v.is_phandle())
1164         {
1165                 return node_names[v.string_data];
1166         }
1167         if (v.is_binary())
1168         {
1169                 return used_phandles[v.get_as_uint32()];
1170         }
1171         return 0;
1172 }
1173
1174 void
1175 device_tree::write_binary(int fd)
1176 {
1177         write<dtb::binary_writer>(fd);
1178 }
1179
1180 void
1181 device_tree::write_asm(int fd)
1182 {
1183         write<dtb::asm_writer>(fd);
1184 }
1185
1186 void
1187 device_tree::write_dts(int fd)
1188 {
1189         FILE *file = fdopen(fd, "w");
1190         fputs("/dts-v1/;\n\n", file);
1191
1192         if (!reservations.empty())
1193         {
1194                 const char msg[] = "/memreserve/";
1195                 fwrite(msg, sizeof(msg), 1, file);
1196                 for (std::vector<reservation>::iterator i=reservations.begin(),
1197                      e=reservations.end() ; i!=e ; ++i)
1198                 {
1199                         fprintf(file, " %" PRIx64 " %" PRIx64, i->first, i->second);
1200                 }
1201                 fputs(";\n\n", file);
1202         }
1203         putc('/', file);
1204         putc(' ', file);
1205         root->write_dts(file, 0);
1206         fclose(file);
1207 }
1208
1209 void
1210 device_tree::parse_dtb(const char *fn, FILE *depfile)
1211 {
1212         input_buffer *in = buffer_for_file(fn);
1213         if (in == 0)
1214         {
1215                 valid = false;
1216                 return;
1217         }
1218         input_buffer &input = *in;
1219         dtb::header h;
1220         valid = h.read_dtb(input);
1221         boot_cpu = h.boot_cpuid_phys;
1222         if (h.last_comp_version > 17)
1223         {
1224                 fprintf(stderr, "Don't know how to read this version of the device tree blob");
1225                 valid = false;
1226         }
1227         if (!valid)
1228         {
1229                 return;
1230         }
1231         input_buffer reservation_map =
1232                 input.buffer_from_offset(h.off_mem_rsvmap, 0);
1233         uint64_t start, length;
1234         do
1235         {
1236                 if (!(reservation_map.consume_binary(start) &&
1237                       reservation_map.consume_binary(length)))
1238                 {
1239                         fprintf(stderr, "Failed to read memory reservation table\n");
1240                         valid = false;
1241                         return;
1242                 }
1243         } while (!((start == 0) && (length == 0)));
1244         input_buffer struct_table =
1245                 input.buffer_from_offset(h.off_dt_struct, h.size_dt_struct);
1246         input_buffer strings_table =
1247                 input.buffer_from_offset(h.off_dt_strings, h.size_dt_strings);
1248         uint32_t token;
1249         if (!(struct_table.consume_binary(token) &&
1250                 (token == dtb::FDT_BEGIN_NODE)))
1251         {
1252                 fprintf(stderr, "Expected FDT_BEGIN_NODE token.\n");
1253                 valid = false;
1254                 return;
1255         }
1256         root = node::parse_dtb(struct_table, strings_table);
1257         if (!(struct_table.consume_binary(token) && (token == dtb::FDT_END)))
1258         {
1259                 fprintf(stderr, "Expected FDT_END token after parsing root node.\n");
1260                 valid = false;
1261                 return;
1262         }
1263         valid = (root != 0);
1264 }
1265
1266 void
1267 device_tree::parse_dts(const char *fn, FILE *depfile)
1268 {
1269         input_buffer *in = buffer_for_file(fn);
1270         if (in == 0)
1271         {
1272                 valid = false;
1273                 return;
1274         }
1275         std::vector<node*> roots;
1276         input_buffer &input = *in;
1277         input.next_token();
1278         bool read_header = false;
1279         // Read the header
1280         if (input.consume("/dts-v1/;"))
1281         {
1282                 read_header = true;
1283         }
1284         input.next_token();
1285         while(input.consume("/include/"))
1286         {
1287                 bool reallyInclude = true;
1288                 if (input.consume("if "))
1289                 {
1290                         input.next_token();
1291                         string name = string::parse_property_name(input);
1292                         // XXX: Error handling
1293                         if (defines.find(name) == defines.end())
1294                         {
1295                                 reallyInclude = false;
1296                         }
1297                         input.consume('/');
1298                 }
1299                 input.next_token();
1300                 if (!input.consume('"'))
1301                 {
1302                         input.parse_error("Expected quoted filename");
1303                         valid = false;
1304                         return;
1305                 }
1306                 int length = 0;
1307                 while (input[length] != '"') length++;
1308
1309                 const char *file = (const char*)input;
1310                 const char *dir = dirname(fn);
1311                 int dir_length = strlen(dir);
1312                 char *include_file = (char*)malloc(strlen(dir) + length + 2);
1313                 memcpy(include_file, dir, dir_length);
1314                 include_file[dir_length] = '/';
1315                 memcpy(include_file+dir_length+1, file, length);
1316                 include_file[dir_length+length+1] = 0;
1317
1318                 input.consume(include_file+dir_length+1);
1319                 input.consume('"');
1320                 if (!reallyInclude)
1321                 {
1322                         continue;
1323                 }
1324
1325                 input_buffer *include_buffer = buffer_for_file(include_file);
1326
1327                 if (include_buffer == 0)
1328                 {
1329                         for (std::vector<const char*>::iterator i=include_paths.begin(), e=include_paths.end() ; e!=i ; ++i)
1330                         {
1331                                 free(include_file);
1332                                 dir = *i;
1333                                 dir_length = strlen(dir);
1334                                 include_file = (char*)malloc(strlen(dir) +
1335                                                 length + 2);
1336                                 memcpy(include_file, dir, dir_length);
1337                                 include_file[dir_length] = '/';
1338                                 memcpy(include_file+dir_length+1, file, length);
1339                                 include_file[dir_length+length+1] = 0;
1340                                 include_buffer = buffer_for_file(include_file);
1341                                 if (include_buffer != 0)
1342                                 {
1343                                         break;
1344                                 }
1345                         }
1346                 }
1347                 if (depfile != 0)
1348                 {
1349                         putc(' ', depfile);
1350                         fputs(include_file, depfile);
1351                 }
1352                 if (include_buffer == 0)
1353                 {
1354                         valid = false;
1355                         return;
1356                 }
1357                 input_buffer &include = *include_buffer;
1358                 free((void*)include_file);
1359
1360                 if (!read_header)
1361                 {
1362                         include.next_token();
1363                         read_header = include.consume("/dts-v1/;");
1364                 }
1365                 parse_roots(include, roots);
1366         }
1367         input.next_token();
1368         if (!read_header)
1369         {
1370                 input.parse_error("Expected /dts-v1/; version string");
1371         }
1372         // Read any memory reservations
1373         while(input.consume("/memreserve/"))
1374         {
1375                 long long start, len;
1376                 input.next_token();
1377                 // Read the start and length.
1378                 if (!(input.consume_integer(start) &&
1379                     (input.next_token(),
1380                     input.consume_integer(len))))
1381                 {
1382                         input.parse_error("Expected size on /memreserve/ node.");
1383                 }
1384                 input.next_token();
1385                 input.consume(';');
1386                 reservations.push_back(reservation(start, len));
1387         }
1388         parse_roots(input, roots);
1389         switch (roots.size())
1390         {
1391                 case 0:
1392                         valid = false;
1393                         input.parse_error("Failed to find root node /.");
1394                         return;
1395                 case 1:
1396                         root = roots[0];
1397                         break;
1398                 default:
1399                 {
1400                         root = roots[0];
1401                         for (std::vector<node*>::iterator i=roots.begin()+1,
1402                              e=roots.end() ; i!=e ; ++i)
1403                         {
1404                                 root->merge_node(*i);
1405                                 delete *i;
1406                         }
1407                         roots.resize(1);
1408                 }
1409         }
1410         collect_names();
1411         resolve_cross_references();
1412 }
1413
1414 device_tree::~device_tree()
1415 {
1416         if (root != 0)
1417         {
1418                 delete root;
1419         }
1420         while (!buffers.empty())
1421         {
1422                 delete buffers.back();
1423                 buffers.pop_back();
1424         }
1425         for (define_map::iterator i=defines.begin(), e=defines.end() ;
1426              i!=e ; ++i)
1427         {
1428                 delete i->second;
1429         }
1430 }
1431
1432 bool device_tree::parse_define(const char *def)
1433 {
1434         char *val = strchr(def, '=');
1435         if (!val)
1436         {
1437                 if (strlen(def) != 0)
1438                 {
1439                         string name(def);
1440                         defines[name];
1441                         return true;
1442                 }
1443                 return false;
1444         }
1445         string name(def, val-def);
1446         val++;
1447         input_buffer in = input_buffer(val, strlen(val));
1448         property *p = property::parse(in, name, string(), false);
1449         if (p)
1450                 defines[name] = p;
1451         return p;
1452 }
1453
1454 } // namespace fdt
1455
1456 } // namespace dtc
1457