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