radio_tool 0.2.1
Loading...
Searching...
No Matches
cs_fw.cpp
1
21#include <radio_tool/fw/cs_fw.hpp>
22#include <radio_tool/fw/cipher/cs800.hpp>
23#include <radio_tool/fw/cipher/dr5xx0.hpp>
24#include <radio_tool/util.hpp>
25
26#include <fstream>
27#include <sstream>
28#include <iomanip>
29#include <iterator>
30
31using namespace radio_tool::fw;
32
33auto CSFW::Read(const std::string& fw) -> void
34{
35 std::ifstream in_file(fw, std::ios_base::binary);
36 if (in_file.is_open())
37 {
38 in_file.seekg(0, std::fstream::end);
39 auto len = in_file.tellg();
40 in_file.seekg(0, std::fstream::beg);
41
42 in_file.read((char*)&header, sizeof(CS800D_header));
43
44 //test file size is correct
45 if (header.imagesize == 0)
46 {
47 throw std::runtime_error("Invalid firmware file");
48 }
49 if (header.imagesize + header.imageHeaderSize + sizeof(uint16_t) != len)
50 {
51 throw std::runtime_error("Invalid firmware header");
52 }
53
54 data.resize(header.imagesize);
55 in_file.read((char*)data.data(), header.imagesize);
56 in_file.read((char*)&checksum, sizeof(uint16_t));
57 in_file.close();
58
59 //xor checksum
60 ((uint8_t*)&checksum)[0] = ((uint8_t*)&checksum)[0] ^ cipher::cs800_0[header.imagesize % cipher::cs800_length];
61 ((uint8_t*)&checksum)[1] = ((uint8_t*)&checksum)[1] ^ cipher::cs800_0[(header.imagesize + 1) % cipher::cs800_length];
62
63 memory_ranges.push_back({ header.baseaddr_offset, header.imagesize });
64
65 //test checksum
66 auto cs_check = MakeChecksum();
67 if (cs_check != checksum)
68 {
69 //checksum not working right now
70 throw std::runtime_error("Invalid checksum");
71 }
72 }
73 else
74 {
75 throw std::runtime_error("Cant open file");
76 }
77}
78
79auto CSFW::UpdateHeader() -> void
80{
81 if (memory_ranges.size() != 1)
82 {
83 throw std::runtime_error("CS Firmware can only contain one segment!");
84 }
85 header.imagesize = data.size();
86 header.imageHeaderSize = sizeof(CS800D_header);
87 header.version = 1;
88 if (memory_ranges.size())
89 {
90 header.baseaddr_offset = memory_ranges[0].first;
91 }
92}
93
94auto CSFW::Write(const std::string& fw) -> void
95{
96 std::ofstream of(fw, std::ios_base::binary);
97 if (of.is_open())
98 {
99 UpdateHeader();
100 auto data = MakeFiledata();
101 of.write((char*)data.data(), data.size());
102
103 //Apply XOR to make checksum
104 ApplyXOR(data.begin() + header.imageHeaderSize, data.end(), cipher::cs800_0, cipher::cs800_length);
105 auto cs = CSChecksum(data.begin(), data.end());
106
107 //XOR the checksum before writing
108 ((uint8_t*)&cs)[0] = ((uint8_t*)&cs)[0] ^ cipher::cs800_0[header.imagesize % cipher::cs800_length];
109 ((uint8_t*)&cs)[1] = ((uint8_t*)&cs)[1] ^ cipher::cs800_0[(header.imagesize + 1) % cipher::cs800_length];
110
111 of.write((char*)&cs, sizeof(cs));
112
113 of.close();
114 }
115}
116
117auto CSFW::ToString() const -> std::string
118{
119 std::stringstream out;
120
121 out << "== Connect Systems Firmware ==" << std::endl
122 << "Image Size: " << FormatBytes(header.imagesize) << std::endl
123 << "Version: " << header.version << std::endl
124 << "Checksum: 0x" << std::setw(4) << std::setfill('0') << std::hex << checksum << std::endl
125 << "Data Segments: " << std::endl;
126
127 auto n = 0u;
128 for (const auto& m : memory_ranges)
129 {
130 out << " " << n++ << ": Start=0x" << std::setfill('0') << std::setw(8) << std::hex << m.first
131 << ", Length=0x" << std::setfill('0') << std::setw(8) << std::hex << m.second
132 << std::endl;
133 }
134
135 return out.str();
136}
137
138auto CSFW::GetRadioModel() const -> const std::string
139{
140 //TODO: find a way to detect firmware radio model
141 return "CS800";
142}
143
144auto CSFW::SetRadioModel(const std::string&) -> void
145{
146 //dont do anything (yet)
147}
148
149auto CSFW::Decrypt() -> void
150{
151 //dont know how to detect dr5xx0 so just use cs800 cipher always
152 ApplyXOR(data, cipher::cs800_0, cipher::cs800_length);
153}
154
155auto CSFW::Encrypt() -> void
156{
157 //dont know how to detect dr5xx0 so just use cs800 cipher always
158 ApplyXOR(data, cipher::cs800_0, cipher::cs800_length);
159}
160
161auto CSFW::SupportsFirmwareFile(const std::string& file) -> bool
162{
163 std::ifstream in_file(file, std::ios_base::binary);
164 if (in_file.is_open())
165 {
166 CS800D_header header = {};
167 in_file.read((char*)&header, sizeof(CS800D_header));
168 in_file.seekg(0, std::ios_base::end);
169 auto len = in_file.tellg();
170 in_file.close();
171
172 //test is not resource file
173 if (header.imagesize == 0)
174 {
175 return false;
176 }
177
178 //test image size matches
179 if (header.imagesize + header.imageHeaderSize + sizeof(uint16_t) != len)
180 {
181 return false;
182 }
183
184 return true;
185 }
186 return false;
187}
188
189auto CSFW::SupportsRadioModel(const std::string& model) -> bool
190{
191 //TODO: Make this better
192 if (model == "CS800")
193 {
194 return true;
195 }
196 return false;
197}
198
199auto CSFW::MakeChecksum() const -> uint16_t
200{
201 //Make a copy of the firmware data because we will apply XOR
202 auto to_check = MakeFiledata();
203
204 //XOR firmware data
205 ApplyXOR(to_check.begin() + header.imageHeaderSize, to_check.end(), cipher::cs800_0, cipher::cs800_length);
206
207 return CSChecksum(to_check.begin(), to_check.end());
208}
209
210auto CSFW::MakeFiledata() const -> std::vector<uint8_t>
211{
212 auto h_ptr = (uint8_t*)&header;
213 std::vector<uint8_t> ret;
214 ret.reserve(header.imageHeaderSize + header.imagesize);
215
216 std::copy(h_ptr, h_ptr + sizeof(CS800D_header), std::back_inserter(ret));
217 std::copy(data.begin(), data.end(), std::back_inserter(ret));
218
219 return ret;
220}
221
222auto CSFW::IsCompatible(const FirmwareSupport* Other) const -> bool
223{
224 if (typeid(Other) != typeid(this)) {
225 return false;
226 }
227
228 auto afw = dynamic_cast<const CSFW*>(Other);
229 return true;
230}
auto Read(const std::string &fw) -> void override
Definition: cs_fw.cpp:33
auto Encrypt() -> void override
Definition: cs_fw.cpp:155
auto IsCompatible(const FirmwareSupport *Other) const -> bool override
Definition: cs_fw.cpp:222
auto Write(const std::string &fw) -> void override
Definition: cs_fw.cpp:94
auto GetRadioModel() const -> const std::string override
Definition: cs_fw.cpp:138
static auto SupportsFirmwareFile(const std::string &file) -> bool
Definition: cs_fw.cpp:161
auto SetRadioModel(const std::string &) -> void override
Definition: cs_fw.cpp:144
auto ToString() const -> std::string override
Definition: cs_fw.cpp:117
auto Decrypt() -> void override
Definition: cs_fw.cpp:149
std::vector< uint8_t > data
Definition: fw.hpp:166
std::vector< std::pair< uint32_t, uint32_t > > memory_ranges
Definition: fw.hpp:172
const unsigned char cs800_0[cs800_length]
Definition: cs800.hpp:31