1 /* zenutils - Utilities for working with creative firmwares.
2 * Copyright 2007 (c) Rasmus Ry <rasmus.ry{at}gmail.com>
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.
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.
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
21 #include <getpot/getpot.hpp>
27 static const char VERSION
[] = "0.1";
32 << "firmware_make - Creates a Creative firmware archive." << std::endl
33 << "Version " << VERSION
<< std::endl
34 << "Copyright (c) 2007 Rasmus Ry" << std::endl
;
40 std::cout
<< std::endl
41 << "Usage: firmware_make [command] [options]" << 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
58 dword
get_tag_value(std::string tag
)
60 if (tag
[0] == '0' && tag
[1] == 'x')
63 if (sscanf(tag
.c_str(), "0x%08X", &val
) == 1)
65 if (sscanf(tag
.c_str(), "0x%08x", &val
) == 1)
70 return shared::swap(*(dword
*)&tag
[0]);
75 bool process_child(const GetPot
& mkfile
, const std::string
& root
, int index
,
76 zen::firmware_entry
& entry
)
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(), "");
87 if (file
.empty() || tag
.empty())
89 std::cerr
<< "Invalid file or tag for var: " << sstm
.str()
95 if (!shared::read_file(file
, buffer
))
97 std::cerr
<< "Failed to read the file: " << file
<< std::endl
;
101 entry
.get_bytes().clear();
102 entry
.get_header().tag
= get_tag_value(tag
);
103 size_t contoff
= entry
.get_content_offset();
106 entry
.get_bytes().resize(contoff
, 0);
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
];
114 entry
.get_bytes().insert(entry
.get_bytes().end(), buffer
.begin(),
117 entry
.get_header().size
= entry
.get_bytes().size();
122 int process_arguments(int argc
, char* argv
[])
124 //--------------------------------------------------------------------
125 // Parse input variables.
126 //--------------------------------------------------------------------
128 GetPot
cl(argc
, argv
);
129 if (cl
.size() == 1 || cl
.search(2, "-h", "--help"))
135 std::string makefile
;
136 if (cl
.search("-m") || cl
.search("--makefile"))
137 makefile
= cl
.next("");
138 if (makefile
.empty())
140 std::cerr
<< "Makefile must be specified." << std::endl
;
144 std::string firmware
;
145 if (cl
.search("-f") || cl
.search("--firmware"))
146 firmware
= cl
.next("");
147 if (firmware
.empty())
149 std::cerr
<< "Firmware must be specified." << std::endl
;
153 bool verbose
= false;
154 if (cl
.search("-V") || cl
.search("--verbose"))
157 GetPot
mkfile(makefile
.c_str());
162 std::string endian
= mkfile("endian", "little");
163 if (endian
== "little")
167 else if (endian
== "big")
173 std::cerr
<< "Invalid value of 'endian'" << std::endl
;
177 zen::firmware_archive
archive(big_endian
);
178 int childcount
= mkfile("children/count", 0);
181 std::cerr
<< "A firmware archive must have at least one child entry."
186 for (int i
= 0; i
< childcount
; i
++)
188 zen::firmware_entry
entry(big_endian
);
189 if (!process_child(mkfile
, "children", i
, entry
))
193 archive
.get_children().push_back(entry
);
196 int neighbourcount
= mkfile("neighbours/count", 0);
197 for (int i
= 0; i
< neighbourcount
; i
++)
199 zen::firmware_entry
entry(big_endian
);
200 if (!process_child(mkfile
, "neighbours", i
, entry
))
204 archive
.get_neighbours().push_back(entry
);
208 ofs
.open(firmware
.c_str(), std::ios::out
|std::ios::binary
|std::ios::trunc
);
211 std::cerr
<< "Failed to create the firmware file." << std::endl
;
215 if (!archive
.write(ofs
))
217 std::cerr
<< "Failed to save the firmware archive." << std::endl
;
222 size_t length
= archive
.calc_size();
225 std::cerr
<< "Failed to determine the size of the firmware archive."
230 int align
= length
% 4;
233 shared::bytes
padding(4 - align
, 0);
234 if (!shared::write_file(firmware
, padding
, false, length
))
236 std::cerr
<< "Failed to write padding data." << std::endl
;
244 int main(int argc
, char* argv
[])
248 return process_arguments(argc
, argv
);
250 catch (const std::exception
& xcpt
)
252 std::cerr
<< "Exception caught: " << xcpt
.what() << std::endl
;
257 std::cerr
<< "Unknown exception caught." << std::endl
;