diff options
author | Maurus Cuelenaere <mcuelenaere@gmail.com> | 2008-07-11 15:50:46 +0000 |
---|---|---|
committer | Maurus Cuelenaere <mcuelenaere@gmail.com> | 2008-07-11 15:50:46 +0000 |
commit | 14c7f45cdae826f88dc539c8c38dd95caf305731 (patch) | |
tree | 832da054b7cfb2dc6fd63339af736625f31d21aa /utils/zenutils/source/firmware_make | |
parent | 7c84ede3781c27db73403bd6302f320c76a58c8c (diff) | |
download | rockbox-14c7f45cdae826f88dc539c8c38dd95caf305731.tar.gz rockbox-14c7f45cdae826f88dc539c8c38dd95caf305731.zip |
Add zook's ZenUtils to SVN
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18010 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'utils/zenutils/source/firmware_make')
-rwxr-xr-x | utils/zenutils/source/firmware_make/CMakeLists.txt | 3 | ||||
-rwxr-xr-x | utils/zenutils/source/firmware_make/main.cpp | 261 |
2 files changed, 264 insertions, 0 deletions
diff --git a/utils/zenutils/source/firmware_make/CMakeLists.txt b/utils/zenutils/source/firmware_make/CMakeLists.txt new file mode 100755 index 0000000000..518a008730 --- /dev/null +++ b/utils/zenutils/source/firmware_make/CMakeLists.txt | |||
@@ -0,0 +1,3 @@ | |||
1 | ADD_EXECUTABLE(firmware_make main.cpp) | ||
2 | |||
3 | TARGET_LINK_LIBRARIES (firmware_make shared) | ||
diff --git a/utils/zenutils/source/firmware_make/main.cpp b/utils/zenutils/source/firmware_make/main.cpp new file mode 100755 index 0000000000..b0602b6ffe --- /dev/null +++ b/utils/zenutils/source/firmware_make/main.cpp | |||
@@ -0,0 +1,261 @@ | |||
1 | /* zenutils - Utilities for working with creative firmwares. | ||
2 | * Copyright 2007 (c) Rasmus Ry <rasmus.ry{at}gmail.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | |||
19 | #include <iostream> | ||
20 | #include <sstream> | ||
21 | #include <getpot/getpot.hpp> | ||
22 | #include <file.h> | ||
23 | #include <firmware.h> | ||
24 | #include <utils.h> | ||
25 | |||
26 | |||
27 | static const char VERSION[] = "0.1"; | ||
28 | |||
29 | void print_version() | ||
30 | { | ||
31 | std::cout | ||
32 | << "firmware_make - Creates a Creative firmware archive." << std::endl | ||
33 | << "Version " << VERSION << std::endl | ||
34 | << "Copyright (c) 2007 Rasmus Ry" << std::endl; | ||
35 | } | ||
36 | |||
37 | void print_help() | ||
38 | { | ||
39 | print_version(); | ||
40 | std::cout << std::endl | ||
41 | << "Usage: firmware_make [command] [options]" << std::endl | ||
42 | << std::endl | ||
43 | << " Commands:" << std::endl | ||
44 | << " -h,--help" << std::endl | ||
45 | << " prints this message." << std::endl | ||
46 | << " -m,--makefile [file]" << std::endl | ||
47 | << " specifies the .mk file to build the firmware archive from." | ||
48 | << std::endl << std::endl | ||
49 | << " Options:" << std::endl | ||
50 | << " -V,--verbose" << std::endl | ||
51 | << " prints verbose messages." << std::endl | ||
52 | << " -f,--firmware [file]" << std::endl | ||
53 | << " specifies the output firmware file name" << std::endl | ||
54 | << std::endl | ||
55 | ; | ||
56 | } | ||
57 | |||
58 | dword get_tag_value(std::string tag) | ||
59 | { | ||
60 | if (tag[0] == '0' && tag[1] == 'x') | ||
61 | { | ||
62 | dword val = 0; | ||
63 | if (sscanf(tag.c_str(), "0x%08X", &val) == 1) | ||
64 | return val; | ||
65 | if (sscanf(tag.c_str(), "0x%08x", &val) == 1) | ||
66 | return val; | ||
67 | } | ||
68 | else | ||
69 | { | ||
70 | return shared::swap(*(dword*)&tag[0]); | ||
71 | } | ||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | bool process_child(const GetPot& mkfile, const std::string& root, int index, | ||
76 | zen::firmware_entry& entry) | ||
77 | { | ||
78 | std::stringstream sstm; | ||
79 | sstm << root << "/" << index; | ||
80 | std::string var = sstm.str() + "/tag"; | ||
81 | std::string tag = mkfile(var.c_str(), ""); | ||
82 | var = sstm.str() + "/name"; | ||
83 | std::string name = mkfile(var.c_str(), ""); | ||
84 | var = sstm.str() + "/file"; | ||
85 | std::string file = mkfile(var.c_str(), ""); | ||
86 | |||
87 | if (file.empty() || tag.empty()) | ||
88 | { | ||
89 | std::cerr << "Invalid file or tag for var: " << sstm.str() | ||
90 | << std::endl; | ||
91 | return false; | ||
92 | } | ||
93 | |||
94 | shared::bytes buffer; | ||
95 | if (!shared::read_file(file, buffer)) | ||
96 | { | ||
97 | std::cerr << "Failed to read the file: " << file << std::endl; | ||
98 | return false; | ||
99 | } | ||
100 | |||
101 | entry.get_bytes().clear(); | ||
102 | entry.get_header().tag = get_tag_value(tag); | ||
103 | size_t contoff = entry.get_content_offset(); | ||
104 | if (contoff) | ||
105 | { | ||
106 | entry.get_bytes().resize(contoff, 0); | ||
107 | if (!name.empty()) | ||
108 | { | ||
109 | size_t endoff = entry.is_big_endian() ? 1 : 0; | ||
110 | for (int i = 0; i < name.size(); ++i) | ||
111 | entry.get_bytes()[i * 2 + endoff] = name[i]; | ||
112 | } | ||
113 | } | ||
114 | entry.get_bytes().insert(entry.get_bytes().end(), buffer.begin(), | ||
115 | buffer.end()); | ||
116 | |||
117 | entry.get_header().size = entry.get_bytes().size(); | ||
118 | |||
119 | return true; | ||
120 | } | ||
121 | |||
122 | int process_arguments(int argc, char* argv[]) | ||
123 | { | ||
124 | //-------------------------------------------------------------------- | ||
125 | // Parse input variables. | ||
126 | //-------------------------------------------------------------------- | ||
127 | |||
128 | GetPot cl(argc, argv); | ||
129 | if (cl.size() == 1 || cl.search(2, "-h", "--help")) | ||
130 | { | ||
131 | print_help(); | ||
132 | return 1; | ||
133 | } | ||
134 | |||
135 | std::string makefile; | ||
136 | if (cl.search("-m") || cl.search("--makefile")) | ||
137 | makefile = cl.next(""); | ||
138 | if (makefile.empty()) | ||
139 | { | ||
140 | std::cerr << "Makefile must be specified." << std::endl; | ||
141 | return 2; | ||
142 | } | ||
143 | |||
144 | std::string firmware; | ||
145 | if (cl.search("-f") || cl.search("--firmware")) | ||
146 | firmware = cl.next(""); | ||
147 | if (firmware.empty()) | ||
148 | { | ||
149 | std::cerr << "Firmware must be specified." << std::endl; | ||
150 | return 3; | ||
151 | } | ||
152 | |||
153 | bool verbose = false; | ||
154 | if (cl.search("-V") || cl.search("--verbose")) | ||
155 | verbose = true; | ||
156 | |||
157 | GetPot mkfile(makefile.c_str()); | ||
158 | if (verbose) | ||
159 | mkfile.print(); | ||
160 | |||
161 | bool big_endian; | ||
162 | std::string endian = mkfile("endian", "little"); | ||
163 | if (endian == "little") | ||
164 | { | ||
165 | big_endian = false; | ||
166 | } | ||
167 | else if (endian == "big") | ||
168 | { | ||
169 | big_endian = true; | ||
170 | } | ||
171 | else | ||
172 | { | ||
173 | std::cerr << "Invalid value of 'endian'" << std::endl; | ||
174 | return 4; | ||
175 | } | ||
176 | |||
177 | zen::firmware_archive archive(big_endian); | ||
178 | int childcount = mkfile("children/count", 0); | ||
179 | if (!childcount) | ||
180 | { | ||
181 | std::cerr << "A firmware archive must have at least one child entry." | ||
182 | << std::endl; | ||
183 | return 5; | ||
184 | } | ||
185 | |||
186 | for (int i = 0; i < childcount; i++) | ||
187 | { | ||
188 | zen::firmware_entry entry(big_endian); | ||
189 | if (!process_child(mkfile, "children", i, entry)) | ||
190 | { | ||
191 | return 6; | ||
192 | } | ||
193 | archive.get_children().push_back(entry); | ||
194 | } | ||
195 | |||
196 | int neighbourcount = mkfile("neighbours/count", 0); | ||
197 | for (int i = 0; i < neighbourcount; i++) | ||
198 | { | ||
199 | zen::firmware_entry entry(big_endian); | ||
200 | if (!process_child(mkfile, "neighbours", i, entry)) | ||
201 | { | ||
202 | return 7; | ||
203 | } | ||
204 | archive.get_neighbours().push_back(entry); | ||
205 | } | ||
206 | |||
207 | std::ofstream ofs; | ||
208 | ofs.open(firmware.c_str(), std::ios::out|std::ios::binary|std::ios::trunc); | ||
209 | if (!ofs) | ||
210 | { | ||
211 | std::cerr << "Failed to create the firmware file." << std::endl; | ||
212 | return 8; | ||
213 | } | ||
214 | |||
215 | if (!archive.write(ofs)) | ||
216 | { | ||
217 | std::cerr << "Failed to save the firmware archive." << std::endl; | ||
218 | return 9; | ||
219 | } | ||
220 | ofs.close(); | ||
221 | |||
222 | size_t length = archive.calc_size(); | ||
223 | if (!length) | ||
224 | { | ||
225 | std::cerr << "Failed to determine the size of the firmware archive." | ||
226 | << std::endl; | ||
227 | return 10; | ||
228 | } | ||
229 | |||
230 | int align = length % 4; | ||
231 | if (align) | ||
232 | { | ||
233 | shared::bytes padding(4 - align, 0); | ||
234 | if (!shared::write_file(firmware, padding, false, length)) | ||
235 | { | ||
236 | std::cerr << "Failed to write padding data." << std::endl; | ||
237 | return 11; | ||
238 | } | ||
239 | } | ||
240 | |||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | int main(int argc, char* argv[]) | ||
245 | { | ||
246 | try | ||
247 | { | ||
248 | return process_arguments(argc, argv); | ||
249 | } | ||
250 | catch (const std::exception& xcpt) | ||
251 | { | ||
252 | std::cerr << "Exception caught: " << xcpt.what() << std::endl; | ||
253 | return -1; | ||
254 | } | ||
255 | catch (...) | ||
256 | { | ||
257 | std::cerr << "Unknown exception caught." << std::endl; | ||
258 | return -2; | ||
259 | } | ||
260 | return -3; | ||
261 | } | ||