]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - usr.bin/dtc/dtb.cc
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / usr.bin / dtc / dtb.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 #include "dtb.hh"
34 #include <sys/types.h>
35 #include <inttypes.h>
36 #include <stdio.h>
37 #include <unistd.h>
38
39
40 namespace dtc
41 {
42 namespace dtb
43 {
44
45 void output_writer::write_data(byte_buffer b)
46 {
47         for (byte_buffer::iterator i=b.begin(), e=b.end(); i!=e ; i++)
48         {
49                 write_data(*i);
50         }
51 }
52
53 void
54 binary_writer::write_string(string name)
55 {
56         name.push_to_buffer(buffer);
57         // Trailing nul
58         buffer.push_back(0);
59 }
60
61 void
62 binary_writer::write_data(uint8_t v)
63 {
64         buffer.push_back(v);
65 }
66
67 void
68 binary_writer::write_data(uint32_t v)
69 {
70         while (buffer.size() % 4 != 0)
71         {
72                 buffer.push_back(0);
73         }
74         push_big_endian(buffer, v);
75 }
76
77 void
78 binary_writer::write_data(uint64_t v)
79 {
80         while (buffer.size() % 8 != 0)
81         {
82                 buffer.push_back(0);
83         }
84         push_big_endian(buffer, v);
85 }
86
87 void
88 binary_writer::write_to_file(int fd)
89 {
90         // FIXME: Check return
91         write(fd, buffer.data(), buffer.size());
92 }
93
94 uint32_t
95 binary_writer::size()
96 {
97         return buffer.size();
98 }
99
100 void
101 asm_writer::write_string(const char *c)
102 {
103         while (*c)
104         {
105                 buffer.push_back((uint8_t)*(c++));
106         }
107 }
108
109 void
110 asm_writer::write_line(const char *c)
111 {
112         if (byte_count != 0)
113         {
114                 byte_count = 0;
115                 buffer.push_back('\n');
116         }
117         write_string(c);
118 }
119
120 void
121 asm_writer::write_byte(uint8_t b)
122 {
123         char out[3] = {0};
124         if (byte_count++ == 0)
125         {
126                 buffer.push_back('\t');
127         }
128         write_string(".byte 0x");
129         snprintf(out, 3, "%.2hhx", b);
130         buffer.push_back(out[0]);
131         buffer.push_back(out[1]);
132         if (byte_count == 4)
133         {
134                 buffer.push_back('\n');
135                 byte_count = 0;
136         }
137         else
138         {
139                 buffer.push_back(';');
140                 buffer.push_back(' ');
141         }
142 }
143
144 void
145 asm_writer::write_label(string name)
146 {
147         write_line("\t.globl ");
148         name.push_to_buffer(buffer);
149         buffer.push_back('\n');
150         name.push_to_buffer(buffer);
151         buffer.push_back(':');
152         buffer.push_back('\n');
153         buffer.push_back('_');
154         name.push_to_buffer(buffer);
155         buffer.push_back(':');
156         buffer.push_back('\n');
157         
158 }
159
160 void
161 asm_writer::write_comment(string name)
162 {
163         write_line("\t/* ");
164         name.push_to_buffer(buffer);
165         write_string(" */\n");
166 }
167
168 void
169 asm_writer::write_string(string name)
170 {
171         write_line("\t.string \"");
172         name.push_to_buffer(buffer);
173         write_line("\"\n");
174         bytes_written += name.size() + 1;
175 }
176
177 void
178 asm_writer::write_data(uint8_t v)
179 {
180         write_byte(v);
181         bytes_written++;
182 }
183
184 void
185 asm_writer::write_data(uint32_t v)
186 {
187         if (bytes_written % 4 != 0)
188         {
189                 write_line("\t.balign 4\n");
190                 bytes_written += (4 - (bytes_written % 4));
191         }
192         write_byte((v >> 24) & 0xff);
193         write_byte((v >> 16) & 0xff);
194         write_byte((v >> 8) & 0xff);
195         write_byte((v >> 0) & 0xff);
196         bytes_written += 4;
197 }
198
199 void
200 asm_writer::write_data(uint64_t v)
201 {
202         if (bytes_written % 8 != 0)
203         {
204                 write_line("\t.balign 8\n");
205                 bytes_written += (8 - (bytes_written % 8));
206         }
207         write_byte((v >> 56) & 0xff);
208         write_byte((v >> 48) & 0xff);
209         write_byte((v >> 40) & 0xff);
210         write_byte((v >> 32) & 0xff);
211         write_byte((v >> 24) & 0xff);
212         write_byte((v >> 16) & 0xff);
213         write_byte((v >> 8) & 0xff);
214         write_byte((v >> 0) & 0xff);
215         bytes_written += 8;
216 }
217
218 void
219 asm_writer::write_to_file(int fd)
220 {
221         // FIXME: Check return
222         write(fd, buffer.data(), buffer.size());
223 }
224
225 uint32_t
226 asm_writer::size()
227 {
228         return bytes_written;
229 }
230
231 void
232 header::write(output_writer &out)
233 {
234         out.write_label(string("dt_blob_start"));
235         out.write_label(string("dt_header"));
236         out.write_comment("magic");
237         out.write_data(magic);
238         out.write_comment("totalsize");
239         out.write_data(totalsize);
240         out.write_comment("off_dt_struct");
241         out.write_data(off_dt_struct);
242         out.write_comment("off_dt_strings");
243         out.write_data(off_dt_strings);
244         out.write_comment("off_mem_rsvmap");
245         out.write_data(off_mem_rsvmap);
246         out.write_comment("version");
247         out.write_data(version);
248         out.write_comment("last_comp_version");
249         out.write_data(last_comp_version);
250         out.write_comment("boot_cpuid_phys");
251         out.write_data(boot_cpuid_phys);
252         out.write_comment("size_dt_strings");
253         out.write_data(size_dt_strings);
254         out.write_comment("size_dt_struct");
255         out.write_data(size_dt_struct);
256 }
257
258 bool
259 header::read_dtb(input_buffer &input)
260 {
261         if (!(input.consume_binary(magic) && magic == 0xd00dfeed))
262         {
263                 fprintf(stderr, "Missing magic token in header.  Got %" PRIx32
264                                 " expected 0xd00dfeed\n", magic);
265                 return false;
266         }
267         return input.consume_binary(totalsize) &&
268                input.consume_binary(off_dt_struct) &&
269                input.consume_binary(off_dt_strings) &&
270                input.consume_binary(off_mem_rsvmap) &&
271                input.consume_binary(version) &&
272                input.consume_binary(last_comp_version) &&
273                input.consume_binary(boot_cpuid_phys) &&
274                input.consume_binary(size_dt_strings) &&
275                input.consume_binary(size_dt_struct);
276 }
277 uint32_t
278 string_table::add_string(string str)
279 {
280         std::map<string, uint32_t>::iterator old = string_offsets.find(str);
281         if (old == string_offsets.end())
282         {
283                 uint32_t start = size;
284                 // Don't forget the trailing nul
285                 size += str.size() + 1;
286                 string_offsets.insert(std::make_pair(str, start));
287                 strings.push_back(str);
288                 return start;
289         }
290         else
291         {
292                 return old->second;
293         }
294 }
295
296 void
297 string_table::write(dtb::output_writer &writer)
298 {
299         writer.write_comment(string("Strings table."));
300         writer.write_label(string("dt_strings_start"));
301         for (std::vector<string>::iterator i=strings.begin(), e=strings.end() ;
302              i!=e ; ++i)
303         {
304                 writer.write_string(*i);
305         }
306         writer.write_label(string("dt_strings_end"));
307 }
308
309 } // namespace dtb
310
311 } // namespace dtc
312