summaryrefslogtreecommitdiff
path: root/utils/zenutils/source/firmware_make/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/zenutils/source/firmware_make/main.cpp')
-rwxr-xr-xutils/zenutils/source/firmware_make/main.cpp261
1 files changed, 261 insertions, 0 deletions
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
27static const char VERSION[] = "0.1";
28
29void 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
37void 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
58dword 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
75bool 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
122int 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
244int 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}