Firmware image found with MediaTek MT76xx wifi chipsets.
This page hosts a formal specification of Andes Firmware Image layout as seen in MT76 Wifi Chipsets using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.
All parsing code for C++98/STL generated by Kaitai Struct depends on the C++/STL runtime library. You have to install it before you can parse data.
For C++, the easiest way is to clone the runtime library sources and build them along with your project.
Using Kaitai Struct in C++/STL usually consists of 3 steps.
std::istream
). One can open local file for that, or use existing std::string
or char*
buffer.
#include <fstream>
std::ifstream is("path/to/local/file.bin", std::ifstream::binary);
#include <sstream>
std::istringstream is(str);
#include <sstream>
const char buf[] = { ... };
std::string str(buf, sizeof buf);
std::istringstream is(str);
#include "kaitai/kaitaistream.h"
kaitai::kstream ks(&is);
andes_firmware_t data(&ks);
After that, one can get various attributes from the structure by invoking getter methods like:
data.image_header() // => get image header
#ifndef ANDES_FIRMWARE_H_
#define ANDES_FIRMWARE_H_
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
#include "kaitai/kaitaistruct.h"
#include <stdint.h>
#if KAITAI_STRUCT_VERSION < 9000L
#error "Incompatible Kaitai Struct C++/STL API: version 0.9 or later is required"
#endif
/**
* Firmware image found with MediaTek MT76xx wifi chipsets.
*/
class andes_firmware_t : public kaitai::kstruct {
public:
class image_header_t;
andes_firmware_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, andes_firmware_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~andes_firmware_t();
class image_header_t : public kaitai::kstruct {
public:
image_header_t(kaitai::kstream* p__io, andes_firmware_t* p__parent = 0, andes_firmware_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~image_header_t();
private:
uint32_t m_ilm_len;
uint32_t m_dlm_len;
uint16_t m_fw_ver;
uint16_t m_build_ver;
uint32_t m_extra;
std::string m_build_time;
andes_firmware_t* m__root;
andes_firmware_t* m__parent;
public:
uint32_t ilm_len() const { return m_ilm_len; }
uint32_t dlm_len() const { return m_dlm_len; }
uint16_t fw_ver() const { return m_fw_ver; }
uint16_t build_ver() const { return m_build_ver; }
uint32_t extra() const { return m_extra; }
std::string build_time() const { return m_build_time; }
andes_firmware_t* _root() const { return m__root; }
andes_firmware_t* _parent() const { return m__parent; }
};
private:
image_header_t* m_image_header;
std::string m_ilm;
std::string m_dlm;
andes_firmware_t* m__root;
kaitai::kstruct* m__parent;
std::string m__raw_image_header;
kaitai::kstream* m__io__raw_image_header;
public:
image_header_t* image_header() const { return m_image_header; }
std::string ilm() const { return m_ilm; }
std::string dlm() const { return m_dlm; }
andes_firmware_t* _root() const { return m__root; }
kaitai::kstruct* _parent() const { return m__parent; }
std::string _raw_image_header() const { return m__raw_image_header; }
kaitai::kstream* _io__raw_image_header() const { return m__io__raw_image_header; }
};
#endif // ANDES_FIRMWARE_H_
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
#include "andes_firmware.h"
andes_firmware_t::andes_firmware_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, andes_firmware_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = this;
m_image_header = 0;
m__io__raw_image_header = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void andes_firmware_t::_read() {
m__raw_image_header = m__io->read_bytes(32);
m__io__raw_image_header = new kaitai::kstream(m__raw_image_header);
m_image_header = new image_header_t(m__io__raw_image_header, this, m__root);
m_ilm = m__io->read_bytes(image_header()->ilm_len());
m_dlm = m__io->read_bytes(image_header()->dlm_len());
}
andes_firmware_t::~andes_firmware_t() {
_clean_up();
}
void andes_firmware_t::_clean_up() {
if (m__io__raw_image_header) {
delete m__io__raw_image_header; m__io__raw_image_header = 0;
}
if (m_image_header) {
delete m_image_header; m_image_header = 0;
}
}
andes_firmware_t::image_header_t::image_header_t(kaitai::kstream* p__io, andes_firmware_t* p__parent, andes_firmware_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void andes_firmware_t::image_header_t::_read() {
m_ilm_len = m__io->read_u4le();
m_dlm_len = m__io->read_u4le();
m_fw_ver = m__io->read_u2le();
m_build_ver = m__io->read_u2le();
m_extra = m__io->read_u4le();
m_build_time = kaitai::kstream::bytes_to_str(m__io->read_bytes(16), std::string("UTF-8"));
}
andes_firmware_t::image_header_t::~image_header_t() {
_clean_up();
}
void andes_firmware_t::image_header_t::_clean_up() {
}