Andes Firmware Image layout as seen in MT76 Wifi Chipsets: C++98/STL parsing library

Firmware image found with MediaTek MT76xx wifi chipsets.

Application

Firmware Image wifi chipset

KS implementation details

License: CC0-1.0

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.

Usage

Runtime 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.

Code

Using Kaitai Struct in C++/STL usually consists of 3 steps.

  1. We need to create an STL input stream (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);
    
  2. We need to wrap our input stream into Kaitai stream:
    #include "kaitai/kaitaistream.h"
    
    kaitai::kstream ks(&is);
    
  3. And finally, we can invoke the parsing:
    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

C++98/STL source code to parse Andes Firmware Image layout as seen in MT76 Wifi Chipsets

andes_firmware.h

#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_

andes_firmware.cpp

// 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() {
}