Add bootloader extension

This commit is contained in:
Thomas Stoddard
2026-10-21 19:22:50 -04:00
committed by Kyle Schwarz
parent 4db27aa187
commit 6ac041cadc
61 changed files with 13816 additions and 68 deletions
@@ -0,0 +1,74 @@
#ifndef __BOOTLOADER_FWBIN_H_
#define __BOOTLOADER_FWBIN_H_
#ifdef __cplusplus
#include "icsneo/device/extensions/bootloader/parser/fwrepo.h"
#include <cstdint>
#include <fstream>
#include <map>
#include <optional>
#include <string>
#include <vector>
namespace icsneo {
namespace Bootloader {
class FWBin : public FWRepo {
public:
FWBin() = default;
bool load(const std::string& path);
const FirmwareSourceVersion& getVersion() const override { return version; }
bool getFW(const std::string& iefName, std::vector<uint8_t>& fw) const override;
std::optional<icsneo::DeviceAppVersion> getChipVersion(const std::string& iefName) const override;
static uint32_t HashDjb2(const std::string& str);
private:
static constexpr const uint32_t SignatureHash = 0;
struct VersionTags {
const char* majorTag = nullptr;
const char* minorTag = nullptr;
operator bool() const {
return majorTag && minorTag;
}
};
static VersionTags GetVersionTags(const std::string& iefName);
struct TagData {
enum class Type : uint8_t {
DataBytes = 0,
DataLength = 1,
IEFVersion = 2,
Signature = 3,
Unknown = 0xFF
};
Type type = Type::Unknown;
std::streampos arrayPosition = 0;
uint32_t arrayLength = 0;
bool read(std::ifstream& stream, std::vector<uint8_t>& out) const;
};
bool readTag(const std::string& tag, std::vector<uint8_t>& out) const;
mutable std::ifstream file;
FirmwareSourceVersion version;
std::map<uint32_t, TagData> tags;
};
} // namespace Bootloader
} // namespace icsneo
#endif // __cplusplus
#endif // __BOOTLOADER_FWBIN_H_
@@ -0,0 +1,45 @@
#ifndef __BOOTLOADER_FWBUNDLE_H_
#define __BOOTLOADER_FWBUNDLE_H_
#ifdef __cplusplus
#include "icsneo/device/extensions/bootloader/parser/fwrepo.h"
#include <cstdint>
#include <optional>
#include <string>
#include <unordered_map>
#include <vector>
namespace icsneo {
namespace Bootloader {
class FWBundle : public FWRepo {
public:
FWBundle() = default;
bool load(const std::string& path);
static bool IsFWBundle(const std::string& path);
const FirmwareSourceVersion& getVersion() const override { return version; }
bool getFW(const std::string& iefName, std::vector<uint8_t>& fw) const override;
std::optional<icsneo::DeviceAppVersion> getChipVersion(const std::string& iefName) const override;
private:
struct ChipBinary {
std::vector<uint8_t> data;
FirmwareSourceVersion version;
};
FirmwareSourceVersion version;
std::unordered_map<uint32_t, ChipBinary> binaries;
};
} // namespace Bootloader
} // namespace icsneo
#endif // __cplusplus
#endif // __BOOTLOADER_FWBUNDLE_H_
@@ -0,0 +1,27 @@
#ifndef __BOOTLOADER_FWLOADER_H_
#define __BOOTLOADER_FWLOADER_H_
#ifdef __cplusplus
#include "icsneo/device/extensions/bootloader/parser/fwrepo.h"
#include <memory>
#include <string>
namespace icsneo {
namespace Bootloader {
class FWLoader {
public:
// Detects whether the file is a firmware bundle or a fw.bin and loads it, returns nullptr on failure
static std::unique_ptr<FWRepo> Load(const std::string& path);
};
} // namespace Bootloader
} // namespace icsneo
#endif // __cplusplus
#endif // __BOOTLOADER_FWLOADER_H_
@@ -0,0 +1,34 @@
#ifndef __BOOTLOADER_FWREPO_H_
#define __BOOTLOADER_FWREPO_H_
#ifdef __cplusplus
#include "icsneo/device/extensions/bootloader/version.h"
#include "icsneo/device/deviceversion.h"
#include <cstdint>
#include <optional>
#include <string>
#include <vector>
namespace icsneo {
namespace Bootloader {
class FWRepo {
public:
FWRepo() = default;
virtual ~FWRepo() = default;
virtual bool getFW(const std::string& iefName, std::vector<uint8_t>& fw) const = 0;
virtual std::optional<icsneo::DeviceAppVersion> getChipVersion(const std::string& iefName) const = 0;
virtual const FirmwareSourceVersion& getVersion() const = 0;
};
} // namespace Bootloader
} // namespace icsneo
#endif // __cplusplus
#endif // __BOOTLOADER_FWREPO_H_
@@ -0,0 +1,37 @@
#ifndef __BOOTLOADER_FWZIP_H_
#define __BOOTLOADER_FWZIP_H_
#ifdef __cplusplus
#include <cstdint>
#include <memory>
#include <optional>
#include <vector>
namespace icsneo {
namespace Bootloader {
class ZipHandle;
class FWZip {
private:
std::unique_ptr<ZipHandle> handle;
std::vector<uint8_t> zipData;
std::optional<size_t> uncompressedSize = std::nullopt;
public:
FWZip(std::vector<uint8_t>&& tagData);
~FWZip();
std::optional<size_t> size() const { return uncompressedSize; }
bool readAll(uint8_t* out);
bool readAll(std::vector<uint8_t>& out);
};
} // namespace Bootloader
} // namespace icsneo
#endif // __cplusplus
#endif // __BOOTLOADER_FWZIP_H_
@@ -0,0 +1,47 @@
#ifndef __BOOTLOADER_IEF_H_
#define __BOOTLOADER_IEF_H_
#ifdef __cplusplus
#include "icsneo/device/extensions/bootloader/bytesview.h"
#include <cstdint>
#include <utility>
#include <vector>
namespace icsneo {
namespace Bootloader {
class IEF {
public:
struct Version {
uint8_t appMajor;
uint8_t appMinor;
uint8_t prodId;
uint8_t chipId;
};
using Sector = std::pair<uint32_t, BytesView>;
IEF() = default;
bool load(std::vector<uint8_t>&& bytes);
const Version& getVersion() const { return version; }
const std::vector<Sector>& getSectors() const { return sectors; }
// IEFs are comprised of equally sized blocks of data - take the size of the first
uint32_t getBlockSize() const { return sectors.empty() ? 0 : static_cast<uint32_t>(sectors.front().second.size()); }
private:
std::vector<uint8_t> data;
Version version = {};
std::vector<Sector> sectors;
};
} // namespace Bootloader
} // namespace icsneo
#endif // __cplusplus
#endif // __BOOTLOADER_IEF_H_