]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/dtc/dtb.cc
stand: TARGET_ARCH is spelled MACHINE_ARCH in Makefiles
[FreeBSD/FreeBSD.git] / usr.bin / dtc / dtb.cc
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2013 David Chisnall
5  * All rights reserved.
6  *
7  * This software was developed by SRI International and the University of
8  * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
9  * ("CTSRD"), as part of the DARPA CRASH research programme.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * $FreeBSD$
33  */
34
35 #include "dtb.hh"
36 #include <sys/types.h>
37 #include <inttypes.h>
38 #include <stdio.h>
39 #include <unistd.h>
40 #include <errno.h>
41
42 using std::string;
43
44 namespace {
45
46 void write(dtc::byte_buffer &buffer, int fd)
47 {
48         size_t size = buffer.size();
49         uint8_t *data = buffer.data();
50         while (size > 0)
51         {
52                 ssize_t r = ::write(fd, data, size);
53                 if (r >= 0)
54                 {
55                         data += r;
56                         size -= r;
57                 }
58                 else if (errno != EAGAIN)
59                 {
60                         fprintf(stderr, "Writing to file failed\n");
61                         exit(-1);
62                 }
63         }
64 }
65 }
66
67 namespace dtc
68 {
69 namespace dtb
70 {
71
72 void output_writer::write_data(byte_buffer b)
73 {
74         for (auto i : b)
75         {
76                 write_data(i);
77         }
78 }
79
80 void
81 binary_writer::write_string(const string &name)
82 {
83         push_string(buffer, name);
84         // Trailing nul
85         buffer.push_back(0);
86 }
87
88 void
89 binary_writer::write_data(uint8_t v)
90 {
91         buffer.push_back(v);
92 }
93
94 void
95 binary_writer::write_data(uint32_t v)
96 {
97         while (buffer.size() % 4 != 0)
98         {
99                 buffer.push_back(0);
100         }
101         push_big_endian(buffer, v);
102 }
103
104 void
105 binary_writer::write_data(uint64_t v)
106 {
107         while (buffer.size() % 8 != 0)
108         {
109                 buffer.push_back(0);
110         }
111         push_big_endian(buffer, v);
112 }
113
114 void
115 binary_writer::write_to_file(int fd)
116 {
117         write(buffer, fd);
118 }
119
120 uint32_t
121 binary_writer::size()
122 {
123         return buffer.size();
124 }
125
126 void
127 asm_writer::write_line(const char *c)
128 {
129         if (byte_count != 0)
130         {
131                 byte_count = 0;
132                 buffer.push_back('\n');
133         }
134         write_string(c);
135 }
136
137 void
138 asm_writer::write_byte(uint8_t b)
139 {
140         char out[3] = {0};
141         if (byte_count++ == 0)
142         {
143                 buffer.push_back('\t');
144         }
145         write_string(".byte 0x");
146         snprintf(out, 3, "%.2hhx", b);
147         buffer.push_back(out[0]);
148         buffer.push_back(out[1]);
149         if (byte_count == 4)
150         {
151                 buffer.push_back('\n');
152                 byte_count = 0;
153         }
154         else
155         {
156                 buffer.push_back(';');
157                 buffer.push_back(' ');
158         }
159 }
160
161 void
162 asm_writer::write_label(const string &name)
163 {
164         write_line("\t.globl ");
165         push_string(buffer, name);
166         buffer.push_back('\n');
167         push_string(buffer, name);
168         buffer.push_back(':');
169         buffer.push_back('\n');
170         buffer.push_back('_');
171         push_string(buffer, name);
172         buffer.push_back(':');
173         buffer.push_back('\n');
174         
175 }
176
177 void
178 asm_writer::write_comment(const string &name)
179 {
180         write_line("\t/* ");
181         push_string(buffer, name);
182         write_string(" */\n");
183 }
184
185 void
186 asm_writer::write_string(const char *c)
187 {
188         while (*c)
189         {
190                 buffer.push_back((uint8_t)*(c++));
191         }
192 }
193
194
195 void
196 asm_writer::write_string(const string &name)
197 {
198         write_line("\t.string \"");
199         push_string(buffer, name);
200         write_line("\"\n");
201         bytes_written += name.size() + 1;
202 }
203
204 void
205 asm_writer::write_data(uint8_t v)
206 {
207         write_byte(v);
208         bytes_written++;
209 }
210
211 void
212 asm_writer::write_data(uint32_t v)
213 {
214         if (bytes_written % 4 != 0)
215         {
216                 write_line("\t.balign 4\n");
217                 bytes_written += (4 - (bytes_written % 4));
218         }
219         write_byte((v >> 24) & 0xff);
220         write_byte((v >> 16) & 0xff);
221         write_byte((v >> 8) & 0xff);
222         write_byte((v >> 0) & 0xff);
223         bytes_written += 4;
224 }
225
226 void
227 asm_writer::write_data(uint64_t v)
228 {
229         if (bytes_written % 8 != 0)
230         {
231                 write_line("\t.balign 8\n");
232                 bytes_written += (8 - (bytes_written % 8));
233         }
234         write_byte((v >> 56) & 0xff);
235         write_byte((v >> 48) & 0xff);
236         write_byte((v >> 40) & 0xff);
237         write_byte((v >> 32) & 0xff);
238         write_byte((v >> 24) & 0xff);
239         write_byte((v >> 16) & 0xff);
240         write_byte((v >> 8) & 0xff);
241         write_byte((v >> 0) & 0xff);
242         bytes_written += 8;
243 }
244
245 void
246 asm_writer::write_to_file(int fd)
247 {
248         write(buffer, fd);
249 }
250
251 uint32_t
252 asm_writer::size()
253 {
254         return bytes_written;
255 }
256
257 void
258 header::write(output_writer &out)
259 {
260         out.write_label("dt_blob_start");
261         out.write_label("dt_header");
262         out.write_comment("magic");
263         out.write_data(magic);
264         out.write_comment("totalsize");
265         out.write_data(totalsize);
266         out.write_comment("off_dt_struct");
267         out.write_data(off_dt_struct);
268         out.write_comment("off_dt_strings");
269         out.write_data(off_dt_strings);
270         out.write_comment("off_mem_rsvmap");
271         out.write_data(off_mem_rsvmap);
272         out.write_comment("version");
273         out.write_data(version);
274         out.write_comment("last_comp_version");
275         out.write_data(last_comp_version);
276         out.write_comment("boot_cpuid_phys");
277         out.write_data(boot_cpuid_phys);
278         out.write_comment("size_dt_strings");
279         out.write_data(size_dt_strings);
280         out.write_comment("size_dt_struct");
281         out.write_data(size_dt_struct);
282 }
283
284 bool
285 header::read_dtb(input_buffer &input)
286 {
287         if (!input.consume_binary(magic))
288         {
289                 fprintf(stderr, "Missing magic token in header.");
290                 return false;
291         }
292         if (magic != 0xd00dfeed)
293         {
294                 fprintf(stderr, "Bad magic token in header.  Got %" PRIx32
295                                 " expected 0xd00dfeed\n", magic);
296                 return false;
297         }
298         return input.consume_binary(totalsize) &&
299                input.consume_binary(off_dt_struct) &&
300                input.consume_binary(off_dt_strings) &&
301                input.consume_binary(off_mem_rsvmap) &&
302                input.consume_binary(version) &&
303                input.consume_binary(last_comp_version) &&
304                input.consume_binary(boot_cpuid_phys) &&
305                input.consume_binary(size_dt_strings) &&
306                input.consume_binary(size_dt_struct);
307 }
308 uint32_t
309 string_table::add_string(const string &str)
310 {
311         auto old = string_offsets.find(str);
312         if (old == string_offsets.end())
313         {
314                 uint32_t start = size;
315                 // Don't forget the trailing nul
316                 size += str.size() + 1;
317                 string_offsets.insert(std::make_pair(str, start));
318                 strings.push_back(str);
319                 return start;
320         }
321         else
322         {
323                 return old->second;
324         }
325 }
326
327 void
328 string_table::write(dtb::output_writer &writer)
329 {
330         writer.write_comment("Strings table.");
331         writer.write_label("dt_strings_start");
332         for (auto &i : strings)
333         {
334                 writer.write_string(i);
335         }
336         writer.write_label("dt_strings_end");
337 }
338
339 } // namespace dtb
340
341 } // namespace dtc
342