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