Commit | Line | Data |
---|---|---|
3527bd91 WL |
1 | /* |
2 | * Copyright (c) 2016 Wilhansen Li. All rights reserved. | |
3 | * | |
4 | * Redistribution and use in source and binary forms, with or without | |
5 | * modification, are permitted provided that the following conditions are | |
6 | * met: | |
7 | * Redistributions of source code must retain the above copyright | |
8 | notice, this list of conditions and the following disclaimer. | |
9 | * Redistributions in binary form must reproduce the above | |
10 | copyright notice, this list of conditions and the following | |
11 | disclaimer in the documentation and/or other materials provided | |
12 | with the distribution. | |
13 | * Neither the name of Wilhansen Li nor the names of its | |
14 | contributors may be used to endorse or promote products derived | |
15 | from this software without specific prior written permission. | |
16 | * | |
17 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED | |
18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT | |
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS | |
21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | |
24 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
25 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE | |
26 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN | |
27 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
28 | */ | |
29 | ||
30 | #include <iostream> | |
31 | #include <fstream> | |
32 | #include <sstream> | |
33 | #include <cstdint> | |
34 | #include <string> | |
35 | #include <cstdio> | |
36 | #include <vector> | |
b2ca13ce WL |
37 | |
38 | #include <arpa/inet.h> | |
39 | ||
3527bd91 WL |
40 | using namespace std; |
41 | ||
42 | #define AML_DT_HEADER 0x5f4c4d41 | |
43 | #define DT_HEADER_MAGIC 0xedfe0dd0 | |
44 | #define AML_DT_ID_VARI_TOTAL 3 | |
45 | ||
4a2fab8e | 46 | #pragma pack(push, 1) |
3527bd91 WL |
47 | struct DTHeader { |
48 | uint32_t magic; /* magic word of OF_DT_HEADER */ | |
49 | uint32_t totalsize; /* total size of DT block */ | |
50 | }; | |
51 | struct Header { | |
52 | uint32_t magic; | |
53 | uint32_t version; | |
54 | uint32_t entry_count; | |
55 | }; | |
56 | ||
57 | template<unsigned int ID_SIZE=4> | |
58 | struct HeaderEntry { | |
59 | char soc[ID_SIZE]; | |
60 | char plat[ID_SIZE]; | |
61 | char vari[ID_SIZE]; | |
62 | uint32_t offset; | |
63 | char padding[4]; | |
64 | }; | |
4a2fab8e | 65 | #pragma pack(pop) |
3527bd91 WL |
66 | |
67 | typedef HeaderEntry<4> HeaderEntryV1; | |
68 | typedef HeaderEntry<16> HeaderEntryV2; | |
69 | ||
70 | void trimSpace(char *b, const int len) { | |
71 | int len2 = len; | |
72 | while (len2 > 0 && isspace(b[len2 - 1])) { | |
73 | len2--; | |
74 | } | |
75 | if (len2 < len && len2 > 0) { | |
76 | b[len2] = 0; | |
77 | b[len - 1] = 0; | |
78 | } | |
79 | } | |
99c6487a WL |
80 | uint32_t swap_bytes_u32(uint32_t b) { |
81 | return ((b & 0xFF000000) >> 24) | | |
82 | ((b & 0x00FF0000) >> 8) | | |
83 | ((b & 0x0000FF00) << 8) | | |
84 | (b << 24); | |
85 | } | |
3527bd91 WL |
86 | template<unsigned int ID_SIZE> |
87 | void dumpData(const uint32_t entries, const string &dest, ifstream &dtb) { | |
88 | typedef HeaderEntry<ID_SIZE> HeaderType; | |
89 | ||
90 | vector<HeaderType> headers; | |
91 | for ( uint32_t i = 0; i < entries; ++i ) { | |
92 | HeaderType h; | |
93 | dtb.read((char*)&h, sizeof(h)); | |
94 | ||
95 | headers.push_back(h); | |
96 | } | |
97 | for ( uint32_t i = 0; i < headers.size(); ++i ) { | |
98 | auto &h = headers[i]; | |
99 | ostringstream id; | |
100 | ||
101 | auto u32soc = reinterpret_cast<uint32_t*>(h.soc); | |
102 | auto u32plat = reinterpret_cast<uint32_t*>(h.plat); | |
103 | auto u32vari = reinterpret_cast<uint32_t*>(h.vari); | |
104 | for ( uint32_t j = 0; j < ID_SIZE/sizeof(uint32_t); ++j ) { | |
99c6487a WL |
105 | *(u32soc + j) = swap_bytes_u32(*(u32soc + j)); |
106 | *(u32plat + j) = swap_bytes_u32(*(u32plat + j)); | |
107 | *(u32vari + j) = swap_bytes_u32(*(u32vari + j)); | |
3527bd91 WL |
108 | } |
109 | trimSpace(h.soc, ID_SIZE); | |
110 | trimSpace(h.plat, ID_SIZE); | |
111 | trimSpace(h.vari, ID_SIZE); | |
112 | ||
113 | if ( h.soc[ID_SIZE-1] == 0 ) { | |
114 | id << h.soc; | |
115 | } else { | |
116 | id.write(h.soc, sizeof(h.soc)); | |
117 | } | |
118 | id << '-'; | |
119 | if ( h.plat[ID_SIZE-1] == 0 ) { | |
120 | id << h.plat; | |
121 | } else { | |
122 | id.write(h.plat, sizeof(h.plat)); | |
123 | } | |
124 | id << '-'; | |
125 | if ( h.vari[ID_SIZE-1] == 0 ) { | |
126 | id << h.vari; | |
127 | } else { | |
128 | id.write(h.vari, sizeof(h.vari)); | |
129 | } | |
130 | cout << "Found header: " << id.str() << '\n'; | |
131 | ||
132 | dtb.seekg(h.offset); | |
133 | DTHeader dtheader; | |
134 | dtb.read((char*)&dtheader, sizeof(dtheader)); | |
135 | if ( dtheader.magic != DT_HEADER_MAGIC ) { | |
136 | cout.setf(ios::hex); | |
137 | cout << "\tDTB Header mismatch. Found: " << dtheader.magic; | |
138 | continue; | |
139 | } | |
140 | dtheader.totalsize = ntohl(dtheader.totalsize); | |
141 | cout.setf(ios::dec); | |
142 | cout << "\t offset: " << h.offset << " size: " << dtheader.totalsize << '\n'; | |
143 | dtb.seekg(h.offset); | |
144 | vector<char> data(dtheader.totalsize); | |
145 | dtb.read(data.data(), data.size()); | |
146 | ofstream output(dest + id.str() + ".dtb", ios::binary); | |
147 | output.write(data.data(), data.size()); | |
148 | } | |
3527bd91 WL |
149 | } |
150 | ||
151 | int main(int argc, char **argv) { | |
152 | if ( argc < 3 ) { | |
153 | cerr << "Usage: " << argv[0] << " boot.img out_prefix\n"; | |
154 | return 1; | |
155 | } | |
156 | ||
157 | ifstream dtb(argv[1], ios::binary); | |
158 | if ( !dtb ) { | |
159 | cerr << "Unable to open dtb file: " << argv[2] << endl; | |
160 | return 1; | |
161 | } | |
162 | string dest; | |
163 | if ( argc > 2 ) { | |
164 | dest = argv[2]; | |
165 | } | |
166 | Header header; | |
167 | dtb.read((char*)&header, sizeof(header)); | |
168 | ||
169 | if ( header.magic != AML_DT_HEADER ) { | |
170 | cerr << "Invalid AML DTB header." << endl; | |
171 | return 1; | |
172 | } | |
173 | cout << "DTB Version: " << header.version << " entries: " << header.entry_count << endl; | |
174 | ||
175 | if(header.version == 1) { | |
176 | dumpData<4>(header.entry_count, dest, dtb); | |
177 | } else if(header.version == 2) { | |
178 | dumpData<16>(header.entry_count, dest, dtb); | |
179 | } else { | |
180 | cerr << "Unrecognized DTB version" << endl; | |
181 | return 1; | |
182 | } | |
183 | ||
184 | return 0; | |
185 | } |