压缩数据以标志字节开头,其标志位(从LSB开始)指示哪个接下来的字节将被复制(位设置),哪些字节是查找信息(位未设置)。查找信息由2字节/ 16位组成,我正在寻求帮助以解码其确切格式。
我已经知道:
MSB将
index
包含到查找缓冲区中LSB包含查找的
length
,即从给定索引处的查找缓冲区中复制的字节数length
至少为3位实际查找长度为
length + 3
(因为3是有意义的最小长度,例如2的位指示长度等于5字节的实际查找长度)我怀疑:
查找长度为3或4位(在我可以手动解码的数据中,虽然没有发现需要4位的长度)
查找为3位或4位,索引应为13位或12位。 12位使查找缓冲区的大小为4096字节,13位使缓冲区的大小为8192,它对应于顶部的未压缩数据块,并且可能是缓冲区的初始数据。
从
00675CCE
开始:00675CC0 65 0D 0A 0D FD 0A 33 C0 3C 68 74 6D 6C 3E FF 3C e...ý.3À<html>ÿ<
00675CD0 68 65 61 64 3E 3C 74 BF 69 74 6C 65 3E 34 40 C0 head><t¿itle>4@À
00675CE0 42 FF 61 64 20 52 65 71 75 65 6F 73 74 3C 2F 5F Bÿad Requeost</_
00675CF0 C3 3C 2F 59 C3 6F 62 6F 64 79 57 C0 31 3E 69 CA Ã</YÃobodyWÀ1>iÊ
00675D00 FE 8A C0 3C 70 3E 59 6F 75 72 FF 20 62 72 6F 77 þŠÀ<p>Yourÿ brow
解码序列:
00675CCE FF: read 8 bytes ("<head><t")
00675CD7 BF: read 6 bytes ("itle>4")
lookup 40C0 -> read 3 bytes @ ? index ("00 ")
read 1 byte ("B")
00675CE0 FF: read 8 bytes ("ad Reque")
00675CEA 6F: read 4 bytes ("st</")
lookup 5FC3 -> read 6 bytes @ ? index ("title>")
read 2 bytes ("</")
lookup 59C3 -> read 6 bytes @ ? index ("head><")
00675CF5 6F: read 4 bytes ("body")
...
解码结果:
00000000 3C 68 65 61 64 3E 3C 74 69 74 6C 65 3E 34 30 30 <head><title>400
00000010 20 42 61 64 20 52 65 71 75 65 73 74 3C 2F 74 69 Bad Request</ti
00000020 74 6C 65 3E 3C 2F 68 65 61 64 3E 3C 62 6F 64 79 tle></head><body
现在让我们看一下最后两个查找及其可能的解码:
0x5FC3 = 0101111111000011b
0101111111000 011 -> index 3064, length 6 (3 + 3 per above rule)
010111111100 0011 -> index 1532, length 6
0x59C3 = 0101100111000011b
0101100111000 011 -> index 2872, length 6
010110011100 0011 -> index 1436, length 6
我专门选择了此示例,因为这两个查询仅返回了几个字节。在解码后的输出/查找缓冲区中,
0x5FC3
回溯23个字节,0x59C3
回溯38个字节。长度绝对正确,但是索引编号对我来说没有意义。无论我采用哪种缓冲区大小,或者无论索引是从缓冲区的前面还是后面开始,或者甚至是区分字节序,数字都不合适。我假设由于仅回溯了几个字节,查找索引应该位于缓冲区的上边缘或下边缘。同样,由于它们在压缩数据和查找数据中都相邻,因此它们的索引应该非常接近。所以问题是,如何正确解释查找索引,或者假设它们正确,查找缓冲区如何工作,因为在这种情况下它不能成为标准的循环缓冲区。
ps:如果有人感兴趣,YI M1和Fujifilm X-A10相机将使用有问题的固件格式。固件解压缩程序的当前状态可在GitHub上找到。
更新2:
找到证据表明查找长度至少需要4位。还弄清楚了查找字节是以大端顺序存储的(好像上次尝试时我犯了一个错误)。在链接代码存储库中进行设置后,我注意到许多查找都偏离了709字节,因此我添加了初始查找缓冲区写偏移709,现在我可以正确解码大部分数据,包括上面的示例。其他部分似乎还需要另一个偏移量,因此仍然可以解决。
更新3:
通过分析查找偏移量的变化位置,我注意到较长的0x00字节序列,如果将数据压缩,显然不会出现。仔细观察它们,结果发现它们是2048字节对齐的填充,而压缩数据段又由几个子段组成。一旦将它们拆分并分别解压缩,就解决了更改缓冲区查找偏移量的问题。因此,最后似乎LZSS算法的工作原理与我上面已发布的链接完全相同。谜题不是压缩本身,而是文件结构。与此相关的问题还有很多,一旦完成,我将发布更详细的答案。
#1 楼
正如我对问题的更新中已经描述的那样,事实证明压缩算法是具有12位查找索引和4位查找长度的标准LZSS算法。它们只是以意外的方式存储(翻转的字节)。从以下示例中进行询问:以下内容:
0x5FC3 = 0 1 0 1 1 1 1 1 1 1 0 0 0 0 1 1 b
<-------------> <-----> <----->
7 0 11 8 3 0 (bit indices)
index index length
因此,在缓冲区位置3167处查找是6个字节。缓冲区位置是绝对的,并且始终从“物理”缓冲区索引0开始,不是
观察到怪异且变化的查找索引偏移的原因是
数据包含多个独立的压缩段,拆分后,给出了恒定的缓冲区偏移量
我仍然必须应用缓冲区偏移量才能正确解压缩,这可能是由于某些我尚未确定的数据头或初始化数据所致,但这超出了此范围问题
评论
仅检查解压缩代码在做什么可能会更容易。找到了吗?我假定代码也是压缩数据的一部分,因为其他固件部分仅包含资源,booboo和分区表。但是它可能在前8192个未压缩字节中,因此谢谢您的提示!我也尚未确定体系结构……您听说过“ EV9x”(“ / XC_ODM / sdk / SDK_selfcheck / src / EV9x_DevEnv”)吗?
固件包含“ ARM926”字符串,指向armv5te体系结构。相对较新的可处理4K H.264视频的相机是否可以基于使用了十年的处理器?
ARM926实际上具有用于加速类似DSP的代码的特殊指令(即armv5te中的e),但大多数处理可能是在专用硬件模块中完成的,而CPU仅处理UI和任务管理。