Python 3 执行 MIUI 线刷包内 flash_gen_crc_list.py 文件

一些小技巧分享给大家,关于小米刷机的

  1. EDL 模式,即高通 9008 模式下,可以刷入更多内容,可参考:小米 Note 3 进 EDL (9008) 模式方法。可修复传感器、相机启动贼慢问题
  2. 线刷包解压后,在使用 MiFlash 刷机前,可以用「蘑菇 ROM 助手」进行 IMG 镜像 编辑:下载地址
  3. 第 2 点提到的软件,建议修改 cust.imguserdata.imgsystem.img 修改后有一定概率打包失败,不建议修改他,因为即便是修改了,系统 OTA 更新时也会覆盖掉
  4. 编辑 partition.xmlrawprogram0.xml 可以刷入更多的分区,例如在 9008 下通过修改这两个文件,加入 persist.img 可以修复传感器、陀螺仪等失效问题
  5. 编辑后需要执行 flash_gen_crc_list.pyflash_gen_md5_list.py 两个文件进行校验值的生成。而 flash_gen_crc_list.py 需要手动编辑并加入需要额外刷入的镜像及修正代码

flash_gen_crc_list.py 这个文件因为依赖了 flash_gen_resparsecount 这个程序,导致我们没法在 Windows 以及 Mac 上直接运行。

如果是 Windows 10 的用户可以打开 Ubuntu Linux For Windows 10,切换到 bash Ubuntu 命令行上,是可以正常的通过 python3 运行这个程序的。

否则,只能依靠虚拟机或者实体安装的 Linux 系统才能运行。

以下是修正的代码:

#!/usr/bin/env python
from __future__ import print_function

import binascii
import os
import struct

# sparse_file_list 及 unsparse_file_list 自行根据各自的线刷包调整
sparse_file_list = {
    "cache": "cache.img",
    "system": "system.img",
    "cust": "cust.img",
    "userdata": "userdata.img",
    "persist": "persist.img"
}

unsparse_file_list = {
    "xbl": "xbl.elf",
    "xblbak": "xbl.elf",
    "abl": "abl.elf",
    "ablbak": "abl.elf",
    "tz": "tz.mbn",
    "tzbak": "tz.mbn",
    "hyp": "hyp.mbn",
    "hypbak": "hyp.mbn",
    "rpm": "rpm.mbn",
    "rpmbak": "rpm.mbn",
    "pmic": "pmic.elf",
    "pmicbak": "pmic.elf",
    "devcfg": "devcfg.mbn",
    "devcfgbak": "devcfg.mbn",
    "storsec": "storsec.mbn",
    "storsecbak": "storsec.mbn",
    "bluetooth": "BTFM.bin",
    "cmnlib": "cmnlib.mbn",
    "cmnlibbak": "cmnlib.mbn",
    "cmnlib64": "cmnlib64.mbn",
    "cmnlib64bak": "cmnlib64.mbn",
    "modem": "NON-HLOS.bin",
    "dsp": "dspso.bin",
    "keymaster": "keymaster.mbn",
    "keymasterbak": "keymaster.mbn",
    "logo": "logo.img",
    "misc": "misc.img",
    "recovery": "recovery.img",
    "boot": "boot.img"
}

file_list = dict(unsparse_file_list, **sparse_file_list)


def gen_sparse_crc(path):
    global crc
    FH = open(path, 'rb')
    header_bin = FH.read(28)
    header = struct.unpack("<I4H4I", header_bin)

    magic = header[0]
    major_version = header[1]
    minor_version = header[2]
    file_hdr_sz = header[3]
    chunk_hdr_sz = header[4]
    blk_sz = header[5]
    total_blks = header[6]
    total_chunks = header[7]
    image_checksum = header[8]
    sparsecrc = 0

    if magic != 0xED26FF3A:
        print("%s: Magic should be 0xED26FF3A but is 0x%08X"
              % (path, magic))
        return 0
    if major_version != 1 or minor_version != 0:
        print("%s: I only know about version 1.0, but this is version %u.%u"
              % (path, major_version, minor_version))
        return 0
    if file_hdr_sz != 28:
        print("%s: The file header size was expected to be 28, but is %u."
              % (path, file_hdr_sz))
        return 0
    if chunk_hdr_sz != 12:
        print("%s: The chunk header size was expected to be 12, but is %u."
              % (path, chunk_hdr_sz))
        return 0

    print("%s: Total of %u %u-byte output blocks in %u input chunks."
          % (path, total_blks, blk_sz, total_chunks))

    if image_checksum != 0:
        print("checksum=0x%08X" % image_checksum)

    offset = 0
    for i in range(1, total_chunks + 1):
        header_bin = FH.read(12)
        header = struct.unpack("<2H2I", header_bin)
        chunk_type = header[0]
        reserved1 = header[1]
        chunk_sz = header[2]
        total_sz = header[3]
        data_sz = total_sz - 12

        if chunk_type == 0xCAC1:
            if data_sz != (chunk_sz * blk_sz):
                print("Raw chunk input size (%u) does not match output size (%u)"
                      % (data_sz, chunk_sz * blk_sz))
                break
            else:
                sparsecrc = binascii.crc32(FH.read(data_sz), sparsecrc)
        elif chunk_type == 0xCAC2:
            if data_sz != 4:
                print("Fill chunk should have 4 bytes of fill, but this has %u"
                      % (data_sz), end="")
                break
            else:
                fill_bin = FH.read(4)
                fill = struct.unpack("<I", fill_bin)
                print("Fill with 0x%08X" % (fill))
                fill_buf = [fill] * (blk_sz / data_sz)
                # Python 3 没有 xrange,用 range 代替
                for j in range(1, chunk_sz + 1):
                    sparsecrc = binascii.crc32(fill_buf, sparsecrc)
        elif chunk_type == 0xCAC3:
            if data_sz != 0:
                print("Don't care chunk input size is non-zero (%u)" % (data_sz))
                break
        elif chunk_type == 0xCAC4:
            if data_sz != 4:
                print("CRC32 chunk should have 4 bytes of CRC, but this has %u"
                      % (data_sz), end="")
                break
            else:
                crc_bin = FH.read(4)
                crc = struct.unpack("<I", crc)
                print("Unverified CRC32 0x%08X" % crc)
        else:
            print("Unknown chunk type 0x%04X" % chunk_type, end="")
            break

        offset += chunk_sz
    return sparsecrc


def gen_crc(file_path):
    f = open(file_path, "rb")
    crc = binascii.crc32(f.read())

    return crc


def get_sparse_count(cmd):
    line = os.popen(cmd, 'r').readline()
    if line[0] == 'I' or line[0] == 'i':
        return -1
    return int(line)


# ------------------------------------------------------------------------------
if __name__ == "__main__":
    thispath = os.path.dirname(__file__)
    path = os.path.join(thispath, 'images')
    crclist = os.path.join(path, 'crclist.txt')
    sparsecrclist = os.path.join(path, 'sparsecrclist.txt')
    max_download_size = 512 * 1024 * 1024
    crc = 0
    try:
        fs = open(sparsecrclist, 'w')
        f = open(crclist, 'w')
        fs.write("SPARSECRC-LIST\n")
        f.write("CRC-LIST\n")
        for ptn in file_list:
            filepath = os.path.join(path, file_list[ptn])
            print(filepath)
            if not os.path.isfile(filepath):
                print(filepath + ' doesn\'t exist, skip it')
                continue
            # has_key 废弃,用 in 代替
            if ptn in unsparse_file_list:
                crc = gen_crc(filepath)
                if crc:
                    f.write(ptn + ' ' + hex(crc & (2 ** 32 - 1)) + '\n')
            else:
                size = os.path.getsize(filepath)
                if size < max_download_size:
                    crc = gen_crc(filepath)
                    if crc:
                        f.write(ptn + ' ' + hex(crc & (2 ** 32 - 1)) + '\n')
                else:
                    # need get the sparsecount
                    cmdarg = './flash_gen_resparsecount' + ' -S ' + str(max_download_size) + ' ' + filepath
                    cmd = os.path.join(thispath, cmdarg)
                    count = get_sparse_count(cmd)
                    if count > 0:
                        countstr = str(count)
                        crc = gen_sparse_crc(filepath)
                        if crc:
                            fs.write(ptn + ' ' + hex(crc & (2 ** 32 - 1)) + ' ' + countstr + '\n')
    # except Exception, e,逗号修改为 as
    except Exception as e:
        os.remove(crclist)
        os.remove(sparsecrclist)
        raise
发布了188 篇原创文章 · 获赞 198 · 访问量 211万+

猜你喜欢

转载自blog.csdn.net/maxsky/article/details/86748910