Flipper Zero Unleashed 固件 Heatshrink 压缩 Tar 格式(HSDS)详解

发布时间:2026/9/13 8:51:54
Flipper Zero Unleashed 固件 Heatshrink 压缩 Tar 格式(HSDS)详解 Flipper Zero Unleashed 固件 Heatshrink 压缩 Tar 格式HSDS详解【免费下载链接】unleashed-firmwareFlipper Zero Unleashed Firmware项目地址: https://gitcode.com/GitHub_Trending/un/unleashed-firmware本指南以 documentation/file_formats/TarHeatshrinkFormat.md 为骨架结合仓库中固件端解析实现lib/toolbox/tar/tar_archive.c、lib/toolbox/compress.c与主机端生成工具scripts/hs.py、scripts/flipper/assets/tarball.py的源码佐证完整讲解 Heatshrink 压缩.tar归档的容器格式、7 字节文件头字段语义、压缩参数含义以及从生成.ths文件到固件解包读取的完整链路。读完你将能够独立解析、生成或校验 Flipper 固件使用的 Heatshrink 压缩 tar 数据流.ths文件。为什么需要自定义容器格式Heatshrink 是一种面向嵌入式系统的 LZSS 变体有损针对小内存场景设计压缩库Flipper Zero 固件使用它压缩.tar归档以获得更小的文件体积与更快的 OTA 更新体验。但 Heatshrink 压缩算法本身只定义比特流格式并不定义如何记录压缩参数。解码器在解压前必须知道压缩时使用的滑动窗口大小window size与前瞻缓冲区大小lookahead size否则无法正确解码。为此Flipper 固件在压缩数据流前附加了一个 7 字节的二进制文件头将压缩参数随数据一起存储形成自描述的 HSDSHeatShrink DataStream格式。本文档即是对这一容器格式的正式规范。文件整体布局一个 Heatshrink 压缩 tar 文件通常扩展名为.ths由两部分组成| 7 字节文件头 (Header) | Heatshrink 压缩数据流 (Compressed data) |文件头描述压缩参数其后紧跟 Heatshrink 编码器输出的原始压缩比特流不再有额外包装。文件头Header字段详解文件头共7 字节依次包含魔数、版本号与两个压缩参数字节偏移长度字段取值说明04Magic0x48 0x53 0x44 0x53ASCII 字符串 HSDS即 HeatShrink DataStream41Version0x01版本号当前固定为 151Window size压缩参数滑动窗口大小对应 Heatshrink CLI 的-w参数61Lookahead size压缩参数前瞻缓冲区大小对应 Heatshrink CLI 的-l参数1. Magic魔数魔数为 4 字节0x48 0x53 0x44 0x53即 ASCII HSDSHeatShrink DataStream。固件端读取文件头后首先校验该魔数不匹配即判定为非法文件并拒绝打开。源码中该魔数以小端 32 位整数常量定义于 lib/toolbox/tar/tar_archive.c#L77-L78/* HSDS heatshrink data stream header magic */ static const uint32_t HEATSHRINK_MAGIC 0x53445348;0x53445348按小端序写入文件后字节序列恰好为48 53 44 53与规范一致。主机端 Python 实现scripts/flipper/assets/heatshrink_stream.py使用struct.pack(IBBB, 0x53445348, ...)同样以小端打包双方字节序严格对齐。2. Version版本号版本号为 1 字节当前固定为0x01。Python 端HeatshrinkDataStreamHeader.VERSION 1unpack()时若魔数或版本不匹配会抛出ValueError用于防止不同代格式之间误解析。3. Window size滑动窗口大小1 字节记录压缩器使用的滑动窗口大小对应 Heatshrink CLI 的-w参数。从 API 命名window_sz2与 heatshrink 库约定可以推断该值是以 2 为底的对数形式例如值13表示窗口大小为2^13 8192字节。窗口越大算法可在越长的历史数据中寻找匹配压缩率通常越高但解码端所需内存与计算量也随之增大。4. Lookahead size前瞻缓冲区大小1 字节记录压缩器使用的前瞻缓冲区大小对应 Heatshrink CLI 的-l参数。同样为对数形式例如值6表示缓冲区大小为2^6 64字节。它决定了一次最多可匹配多少个字节的向前搜索范围是压缩率与资源开销的另一个权衡点。固件端结构体与校验固件端用打包结构体表示该文件头并静态断言其大小必须为 7 字节防止 ABI 漂移lib/toolbox/tar/tar_archive.c#L80-L86typedef struct { uint32_t magic; uint8_t version; uint8_t window_sz2; uint8_t lookahead_sz2; } FURI_PACKED HeatshrinkStreamHeader; _Static_assert(sizeof(HeatshrinkStreamHeader) 7, Invalid HeatshrinkStreamHeader size);打开归档时固件依次完成读头 → 校验魔数 → 按头中参数构造解码器三步lib/toolbox/tar/tar_archive.c#L174-L191读取 7 字节头若长度不足或header.magic ! HEATSHRINK_MAGIC则关闭文件并返回失败从头部提取window_sz2与lookahead_sz2写入CompressConfigHeatshrink配置结构将input_buffer_sz设为FILE_BLOCK_SIZE512 字节见 lib/toolbox/tar/tar_archive.c#L12调用compress_stream_decoder_alloc(CompressTypeHeatshrink, ...)创建流式解码器再以 Heatshrink 后端初始化 microtar 库。CompressConfigHeatshrink结构定义于 lib/toolbox/compress.h#L57-L62包含window_sz2、lookahead_sz2、input_buffer_sz三个字段流式解码器在 lib/toolbox/compress.c#L419-L439 中按heatshrink_decoder_alloc(input_buffer_sz, window_sz2, lookahead_sz2)实例化底层 heatshrink 解码器并维护解压缓冲与流位置。注意 Heatshrink 压缩 tar 是只读模式heatshrink_ops的write回调为NULLlib/toolbox/tar/tar_archive.c#L118-L123固件只能解包、不能回写压缩归档。文件扩展名与自动识别压缩 tar 使用.ths扩展名Tar HeatShrink固件通过扩展名自动选择解包模式。tar_archive_get_mode_for_path()lib/toolbox/tar/tar_archive.c#L17-L29提取路径扩展名若为.ths则返回TarOpenModeReadHeatshrink定义于 lib/toolbox/tar/tar_archive.h#L21否则走普通未压缩 tar 读取路径。主机端同样约定TAR_HEATSRINK_EXTENSION .thsscripts/flipper/assets/tarball.py#L9。压缩参数默认值与生成工具主机端生成命令scripts/hs.py仓库提供命令行工具 scripts/hs.py基于heatshrink2Python 库支持compress、decompress、info、tar四个子命令。其默认参数为默认窗口window13即2^13 8192字节默认前瞻lookahead6即2^6 64字节压缩单个文件python3 scripts/hs.py compress -w 13 -l 6 input.bin -o output.hs python3 scripts/hs.py decompress output.hs -o restored.bin python3 scripts/hs.py info output.hs其中compress子命令将压缩参数写入 7 字节 HSDS 头后拼接压缩流scripts/hs.py#L69-L88decompress先读 7 字节头取得 window/lookahead 再解压scripts/hs.py#L90-L111info仅解析并打印头部参数可用于快速验证文件合法性scripts/hs.py#L113-L127。直接生成压缩 tarpython3 scripts/hs.py tar some_dir -o bundle.ths -w 13 -l 6tar子命令在 scripts/hs.py#L129-L141 中调用compress_tree_tarball()完成先打 tar、再压缩、最后写 7 字节头的整条链路并输出原始大小、压缩后大小与压缩比日志。打包实现scripts/flipper/assets/tarball.pyscripts/flipper/assets/tarball.py 的compress_tree_tarball()是核心实现将目录以USTAR 格式tarfile.USTAR_FORMAT兼容 microtar打包进内存缓冲区并经tar_sanitizer_filter()清洗元数据uid/gid 置 0、mtime 置 0、uname/gname 统一为 furippa保证可复现构建用heatshrink2.compress(data, window_sz2hs_window, lookahead_sz2hs_lookahead)压缩整个 tar 数据先写入HeatshrinkDataStreamHeader(hs_window, hs_lookahead).pack()7 字节头再写入压缩流。头部打包/解析类HeatshrinkDataStreamHeader位于 scripts/flipper/assets/heatshrink_stream.pypack()使用IBBB打包 4 字节魔数 3 字节参数unpack()校验长度必须 7 字节、魔数与版本三者任一不符即抛ValueError。端到端工作流从 .ths 到固件解包一个完整的.ths文件处理流程为主机端将资源目录打包为 USTAR tar → heatshrink 压缩 → 前置 7 字节 HSDS 头 → 输出bundle.ths固件端tar_archive_get_mode_for_path()依据.ths扩展名选择TarOpenModeReadHeatshrinktar_archive_open()读取并校验 7 字节头按头部参数创建 Heatshrink 流式解码器再以此作为 microtar 的 I/O 后端heatshrink_ops完成 tar 结构的迭代、读取与解包解包时mtar_read_data()经由mtar_heatshrink_file_read()调用compress_stream_decoder_read()按需解压出原始字节流lib/toolbox/tar/tar_archive.c#L100-L104支持seek只能向前见 lib/toolbox/compress.h#L196-L198 的警告与rewind。实际应用OTA 更新与资源包HSDS 格式在固件中最重要的应用是 OTA 更新资源包。更新脚本将资源包命名为resources.thsscripts/update.py#L25固件更新任务在恢复资源阶段以TarOpenModeReadHeatshrink打开该文件并解包到 SD 卡根目录applications/system/updater/util/update_task_worker_backup.c#L166-L173同时通过文件回调上报解包进度。这正是文档开头所述更小的文件体积与更快的 OTA 更新的落点。单元测试验证仓库内置单元测试直接验证了 HSDS tar 的固件端兼容性applications/debug/unit_tests/tests/compress/compress_test.c#L265-L293断言tar_archive_get_mode_for_path(...test.ths) TarOpenModeReadHeatshrink验证.ths扩展名识别以TarOpenModeReadHeatshrink打开测试文件test.ths并解包断言条目数为 9测试文件内附各解包文件的 MD5 校验和用于比对解包结果一致性compress_test.c#L253-L263。此外 compress_test.c#L18-L94 的参考编解码测试以默认配置见 lib/toolbox/compress.c#L18-L22进行压解对比验证 heatshrink 编解码结果与参考文件完全一致。与图标等资源压缩格式的区别需注意 HSDS 头与固件内另一套 heatshrink 容器图标/内存资源压缩lib/toolbox/compress.c#L33-L39 的CompressHeader并不相同后者是4 字节头1 字节压缩标志 1 字节保留 2 字节压缩数据长度带is_compressed标志位压缩不划算时直接存储原始数据而本文档描述的 HSDS 是7 字节头、无压缩标志、专为流式解压 tar 设计且只读。两者不能混用解析时务必按各自规范区分。兼容性与实现要点小结文件头固定 7 字节字段顺序为 Magic(4) Version(1) Window(1) Lookahead(1)全程小端魔数校验是文件合法性的第一道门槛固件与主机端工具均强制执行Window 与 Lookahead 以 2 的对数存储生产环境默认窗口 13、前瞻 6对应 CLI 的-w 13 -l 6压缩参数随数据自描述任何符合本规范的实现固件 C 代码、Python 工具、自定义脚本均可互操作地解压.ths文件如需手工构造文件最稳妥的方式是直接复用 scripts/hs.py 的tar子命令避免字节序或参数语义出错。【免费下载链接】unleashed-firmwareFlipper Zero Unleashed Firmware项目地址: https://gitcode.com/GitHub_Trending/un/unleashed-firmware创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询