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