Andes Firmware Image layout as seen in MT76 Wifi Chipsets: C++/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

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 a stream for reading from a local file:
      #include <fstream>
      
      std::ifstream is("path/to/local/file.andes_firmware", std::ifstream::binary);
    • Or one can prepare a stream for reading from existing std::string str:
      #include <sstream>
      
      std::istringstream is(str);
    • Or one can parse arbitrary char* buffer in memory, given that we know its size:
      #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++/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 < 7000L
#error "Incompatible Kaitai Struct C++/STL API: version 0.7 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();

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();

    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;
    _read();
}

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() {
    delete m__io__raw_image_header;
    delete m_image_header;
}

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;
    _read();
}

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