radio_tool 0.2.1
Loading...
Searching...
No Matches
tyt_fw.cpp
1
18#include <radio_tool/fw/tyt_fw.hpp>
19#include <radio_tool/util.hpp>
20
21using namespace radio_tool::fw;
22
23auto TYTFW::Read(const std::string& file) -> void
24{
25 const auto HeaderSize = 0x100;
26
27 auto i = std::ifstream(file, std::ios_base::binary);
28 if (i.is_open())
29 {
30 auto header = ReadHeader(i);
31 CheckHeader(header);
32
33 firmware_model = std::string(header.radio, header.radio + strlen((const char*)header.radio));
34 counterMagic = std::vector<uint8_t>(header.counter_magic, header.counter_magic + 1 + header.counter_magic[0]);
35 radio_model = GetRadioFromMagic(counterMagic);
36
37 auto binarySize = 0;
38 for (uint32_t nMem = 0; nMem < header.n_regions; nMem++)
39 {
40 uint32_t rStart = 0, rLength = 0;
41 i.read((char*)&rStart, 4);
42 i.read((char*)&rLength, 4);
43 memory_ranges.push_back(std::make_pair(rStart, rLength));
44 binarySize += rLength;
45 }
46
47 //skip to binary
48 i.seekg(HeaderSize);
49
50 data.resize(binarySize);
51 i.read((char*)data.data(), data.size());
52
53 //meh ignore footer
54 }
55 i.close();
56}
57
58auto TYTFW::Write(const std::string& file) -> void
59{
60 std::ofstream fout(file, std::ios_base::binary);
61 if (fout.is_open())
62 {
63 //make header
64 TYTFirmwareHeader h = {};
65 h.n1 = 0x30000230;
66 h.n2 = 0x47004000;
67 std::copy(tyt::magic::begin.begin(), tyt::magic::begin.end(), h.magic);
68 std::copy(firmware_model.begin(), firmware_model.end(), h.radio);
69 for (auto cx = 0; cx < 76; cx++)
70 {
71 if (cx > 0x20)
72 {
73 h.counter_magic[cx] = 0xff;
74 }
75 else
76 {
77 h.counter_magic[cx] = cx;
78 }
79 }
80 std::copy(counterMagic.begin(), counterMagic.end(), h.counter_magic);
81 h.n_regions = memory_ranges.size();
82
83 //write the header
84 fout.write((char*)&h, sizeof(TYTFirmwareHeader));
85
86 //write region info
87 for (const auto& rx : memory_ranges)
88 {
89 fout.write((char*)&rx.first, sizeof(uint32_t));
90 fout.write((char*)&rx.second, sizeof(uint32_t));
91 }
92
93 //add padding
94 for (uint32_t pad_x = 0; pad_x < 0x80 - (sizeof(uint32_t) * memory_ranges.size() * 2); pad_x++)
95 {
96 fout.put(0xff);
97 }
98
99 //write firmware data
100 fout.write((char*)data.data(), data.size());
101
102 //add footer padding
103 for (auto pad_end = 0; pad_end < 0x100 - 16; pad_end++)
104 {
105 fout.put(0xff);
106 }
107
108 //add end magic
109 fout.write((char*)tyt::magic::end.data(), tyt::magic::end.size());
110
111 fout.close();
112 }
113}
114
115auto TYTFW::ToString() const -> std::string
116{
117 std::stringstream out;
118 out << "== TYT Firmware == " << std::endl
119 << "Radio: " << firmware_model << " (" << radio_model << ")" << std::endl
120 << "Size: " << FormatBytes(data.size()) << std::endl
121 << "Data Segments: " << std::endl;
122 auto n = 0;
123 for (const auto& m : memory_ranges)
124 {
125 out << " " << n++ << ": Start=0x" << std::setfill('0') << std::setw(8) << std::hex << m.first
126 << ", Length=0x" << std::setfill('0') << std::setw(8) << std::hex << m.second
127 << std::endl;
128 }
129 return out.str();
130}
131
132auto TYTFW::ReadHeader(std::ifstream& i) -> TYTFirmwareHeader
133{
134 TYTFirmwareHeader ret = {};
135 i.seekg(0, i.beg);
136 i.read((char*)&ret, sizeof(TYTFirmwareHeader));
137
138 if (ret.n_regions == std::numeric_limits<uint32_t>::max())
139 {
140 ret.n_regions = 1; //if 0xFFFFFFFF then assume 1
141 }
142
143 return ret;
144}
145
146auto TYTFW::CheckHeader(const TYTFirmwareHeader& header) -> void
147{
148 if (!std::equal(tyt::magic::begin.begin(), tyt::magic::begin.end(), header.magic))
149 {
150 throw std::runtime_error("Invalid start magic");
151 }
152
153 if (header.counter_magic[0] > 3)
154 {
155 throw std::runtime_error("Invalid counter magic length");
156 }
157
158 auto magic_match = false;
159 for (const auto& r : tyt::config::All)
160 {
161 //header.counter_magic should always be longer than r.second
162 if (std::equal(r.counter_magic.begin(), r.counter_magic.end(), header.counter_magic))
163 {
164 magic_match = true;
165 break;
166 }
167 }
168 if (!magic_match)
169 {
170 throw std::runtime_error("Counter magic is invalid, or not supported");
171 }
172
173 if ((header.n_regions * 8) > 0x80)
174 {
175 throw std::runtime_error("Memory region count out of bounds");
176 }
177}
178
179auto TYTFW::SupportsFirmwareFile(const std::string& file) -> bool
180{
181 std::ifstream i;
182 i.open(file, i.binary);
183 if (i.is_open())
184 {
185 auto header = ReadHeader(i);
186 i.close();
187
188 try
189 {
190 CheckHeader(header);
191 }
192 catch (std::exception&)
193 {
194 return false;
195 }
196
197 return true;
198 }
199 else
200 {
201 throw std::runtime_error("Can't open firmware file");
202 }
203}
204
205auto TYTFW::SupportsRadioModel(const std::string& model) -> bool
206{
207 for (const auto& mx : tyt::config::All)
208 {
209 if (mx.radio_model == model)
210 {
211 return true;
212 }
213 }
214 return false;
215}
216
217auto TYTFW::GetRadioModel() const -> const std::string
218{
219 return GetRadioFromMagic(counterMagic);
220}
221
222
223auto TYTFW::SetRadioModel(const std::string& model) -> void
224{
225 for (const auto& rg : tyt::config::All)
226 {
227 if (rg.radio_model == model)
228 {
229 counterMagic = rg.counter_magic;
230 radio_model = rg.radio_model;
231 firmware_model = rg.firmware_model;
232 break;
233 }
234 }
235}
236
237auto TYTFW::Decrypt() -> void
238{
239 ApplyXOR();
240}
241
242auto TYTFW::Encrypt() -> void
243{
244 ApplyXOR();
245}
246
247auto TYTFW::ApplyXOR() -> void
248{
249 const uint8_t* xor_model = nullptr;
250 uint32_t xor_len = 1024;
251
252 for (const auto& r : tyt::config::All)
253 {
254 if (std::equal(r.counter_magic.begin(), r.counter_magic.end(), counterMagic.begin(), counterMagic.end()))
255 {
256 xor_model = r.cipher;
257 xor_len = r.cipher_len;
258 break;
259 }
260 }
261
262 if (xor_model == nullptr)
263 {
264 throw std::runtime_error("No cipher found");
265 }
266
267 radio_tool::ApplyXOR(data, xor_model, xor_len);
268}
269
270auto TYTFW::IsCompatible(const FirmwareSupport* Other) const -> bool
271{
272 if (typeid(Other) != typeid(this)) {
273 return false;
274 }
275
276 auto afw = dynamic_cast<const TYTFW*>(Other);
277 return afw->radio_model == radio_model
278 && afw->firmware_model == firmware_model;
279}
std::vector< uint8_t > data
Definition: fw.hpp:166
std::vector< std::pair< uint32_t, uint32_t > > memory_ranges
Definition: fw.hpp:172
auto Write(const std::string &file) -> void override
Definition: tyt_fw.cpp:58
auto Read(const std::string &file) -> void override
Definition: tyt_fw.cpp:23
static auto GetRadioFromMagic(const std::vector< uint8_t > &cm) -> const std::string
Definition: tyt_fw.hpp:173
auto IsCompatible(const FirmwareSupport *Other) const -> bool override
Definition: tyt_fw.cpp:270
static auto SupportsRadioModel(const std::string &model) -> bool
Definition: tyt_fw.cpp:205
auto SetRadioModel(const std::string &) -> void override
Definition: tyt_fw.cpp:223
auto GetRadioModel() const -> const std::string override
Definition: tyt_fw.cpp:217
auto Decrypt() -> void override
Definition: tyt_fw.cpp:237
auto Encrypt() -> void override
Definition: tyt_fw.cpp:242
auto ToString() const -> std::string override
Definition: tyt_fw.cpp:115
static auto SupportsFirmwareFile(const std::string &file) -> bool
Definition: tyt_fw.cpp:179