python实现qboot打包功能

发布于 2023-04-25  553 次阅读


下面是一个完整的示例,展示了如何使用 zlib.crc32 函数和 quicklz 压缩算法来实现 qboot 文件的打包功能:

import os
import sys
import struct
import zlib
import time
import quicklz
 


def pack_qboot(bin_file, qboot_file, type_string, algo, algo2, part_name, fw_ver, prod_code):
    with open(bin_file, 'rb') as f:
        bin_data = f.read()
    # 对文件进行4字节对齐,不足补零
    align_value = 0
    bin_data = bin_data + align_value.to_bytes(4-len(bin_data)%4,byteorder='big')
    # 计算对齐后固件大小和固件 CRC32
    firmware_size = len(bin_data)
    firmware_crc32 = zlib.crc32(bin_data)
    #print(firmware_size)
    #print(firmware_crc32)
    # 使用 quicklz 压缩数据
    compressed_full_data = bytes()
    bin_data_parts = [bin_data[i:i+4096] for i in range(0, len(bin_data), 4096)]
    for part in bin_data_parts:
        compressed_data = quicklz.compress(part)
        compressedSize = len(compressed_data)
        compressed_full_data = compressed_full_data + compressedSize.to_bytes(4, byteorder='big') + compressed_data
    #print(compressed_data)
    # 计算打包大小和打包 CRC32
    pack_size = len(compressed_full_data)
    pack_crc32 = zlib.crc32(compressed_full_data)
    # 获取当前时间戳
    timestamp = int(time.time())
    # 计算 qboot 文件长度
    qboot_len = pack_size + 120
    # 准备包头数据
    header_data = struct.pack('<4sHHI16s24s24sIIII', type_string.encode(), algo, algo2, timestamp, part_name.encode(), fw_ver.encode(), prod_code.encode(), pack_crc32, firmware_crc32, firmware_size, pack_size)
    # 计算包头 CRC32
    header_crc32 = zlib.crc32(header_data)
    # 更新包头 CRC32
    header_data = struct.pack('<4sHHI16s24s24sIIIII', type_string.encode(), algo, algo2, timestamp, part_name.encode(), fw_ver.encode(), prod_code.encode(), pack_crc32, firmware_crc32, firmware_size, pack_size, header_crc32)
    
    #print(pack_crc32)
    #print(header_data)
    with open(qboot_file, 'wb') as f:
        f.write(header_data)
        f.write(compressed_full_data)
    print(firmware_size)
    print(pack_size)
    print(prod_code)
    print(fw_ver)
 
if __name__ == '__main__':
    if len(sys.argv) != 9:
        print('Usage: python qboot_pack.py input.bin output.qbt type_string algo algo2 part_name fw_ver prod_code')
        sys.exit(1)
    bin_file = sys.argv[1]
    qboot_file = sys.argv[2]
    type_string = sys.argv[3]
    algo = int(sys.argv[4])
    algo2 = int(sys.argv[5])
    part_name = sys.argv[6]
    fw_ver = sys.argv[7]
    prod_code = sys.argv[8]
    pack_qboot(bin_file, qboot_file, type_string, algo, algo2, part_name, fw_ver, prod_code)
 

上面的代码定义了一个名为 pack_qboot 的函数,用于将一个二进制文件打包成一个 qboot 文件。它接受多个参数,包括输入的二进制文件、输出的 qboot 文件、类型字符串、算法编号、分区名称、固件版本和产品代码等。

这个脚本还包含了一个主程序,用于在命令行中运行这个脚本。你可以使用以下命令来运行这个脚本:

python qboot_pack.py input.bin output.qbt RBL 1 2 my_part_name v1.0.0 my_product

其中 input.bin 是你要打包的二进制文件,output.qbt 是输出的 qboot 文件,其他参数分别表示类型字符串、算法编号、分区名称、固件版本和产品代码等。

你可以根据自己的需求修改这些代码,以实现更多的功能。

是的,在 Python 中,zlib.crc32 函数使用的是固定的初始多项式。这个多项式的值为 0xEDB88320,它是一个常用的 CRC32 多项式。

如果你想要使用不同的初始多项式来计算 CRC32,你可以使用其他库来实现这个功能。例如,你可以使用 crcmod 库来自定义 CRC32 多项式。你可以使用以下命令来安装这个库:

pip install crcmod

安装完成后,你可以在 pack_qboot 函数中使用 crcmod 库来计算 CRC32。下面是一个简单的示例,展示了如何使用自定义的初始多项式来计算 CRC32:

import crcmod

def pack_qboot(bin_file, qboot_file):
    with open(bin_file, 'rb') as f:
        bin_data = f.read()
    # 使用 quicklz 压缩数据
    compressed_data = quicklz.compress(bin_data)
    # 计算打包大小和打包 CRC32
    pack_size = len(compressed_data)
    # 使用自定义的初始多项式计算 CRC32
    crc32_func = crcmod.mkCrcFun(0x104C11DB7, initCrc=0, xorOut=0xFFFFFFFF)
    pack_crc32 = crc32_func(compressed_data)
    # 获取当前时间戳
    timestamp = int(time.time())
    # 计算 qboot 文件长度
    qboot_len = pack_size + 28
    # 准备包头数据
    header_data = struct.pack('<IIIIIII', qboot_len, 0x00000000, firmware_size, pack_size, firmware_crc32, pack_crc32, timestamp)
    # 计算包头 CRC32
    header_crc32 = crc32_func(header_data)
    with open(qboot_file, 'wb') as f:
        f.write(header_data)
        f.write(struct.pack('<I', header_crc32))
        f.write(compressed_data)

上面的代码使用 crcmod.mkCrcFun 函数创建了一个自定义的 CRC32 函数。它传递了三个参数:初始多项式、初始 CRC 值和最终异或值。然后,它使用这个自定义的 CRC32 函数来计算压缩数据和包头数据的 CRC32 值。

你可以根据自己的需求修改这些代码,以实现更多的功能。

要在上述代码的基础上使用 quicklz 算法实现压缩功能,你需要安装 pyquicklz 库。你可以使用以下命令来安装这个库:

pip install pyquicklz

安装完成后,你可以在 pack_qboot 函数中使用 quicklz 库来实现压缩功能。下面是一个简单的示例,展示了如何在 pack_qboot 函数中使用 quicklz 压缩:

import quicklz

def pack_qboot(bin_file, qboot_file):
    with open(bin_file, 'rb') as f:
        bin_data = f.read()
    # 使用 quicklz 压缩数据
    compressed_data = quicklz.compress(bin_data)
    # 计算 CRC32 校验值
    crc32_value = zlib.crc32(compressed_data)
    compressed_len = len(compressed_data)
    qboot_len = compressed_len + 12
    with open(qboot_file, 'wb') as f:
        f.write(struct.pack('<III', qboot_len, 0x00000000, crc32_value))
        f.write(compressed_data)

上面的代码使用 quicklz.compress 函数来实现 quicklz 压缩。它将二进制数据作为参数传递给 quicklz.compress 函数,然后获取压缩后的数据。

你可以根据自己的需求修改这些代码,以实现更多的功能。


一沙一世界,一花一天堂。君掌盛无边,刹那成永恒。