[build] add cvitek build scripts
Change-Id: If63ce4a669e5d4d72b8e3b9253336dd99bf74c30
This commit is contained in:
170
build/tools/common/image_tool/raw2cimg.py
Executable file
170
build/tools/common/image_tool/raw2cimg.py
Executable file
@ -0,0 +1,170 @@
|
||||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
import logging
|
||||
import argparse
|
||||
import os
|
||||
from array import array
|
||||
import binascii
|
||||
from XmlParser import XmlParser
|
||||
from tempfile import TemporaryDirectory
|
||||
import shutil
|
||||
|
||||
MAX_LOAD_SIZE = 16 * 1024 * 1024
|
||||
CHUNK_TYPE_DONT_CARE = 0
|
||||
CHUNK_TYPE_CRC_CHECK = 1
|
||||
FORMAT = "%(levelname)s: %(message)s"
|
||||
logging.basicConfig(level=logging.INFO, format=FORMAT)
|
||||
|
||||
|
||||
def parse_Args():
|
||||
parser = argparse.ArgumentParser(description="Create CVITEK device image")
|
||||
|
||||
parser.add_argument(
|
||||
"file_path",
|
||||
metavar="file_path",
|
||||
type=str,
|
||||
help="the file you want to pack with cvitek image header",
|
||||
)
|
||||
parser.add_argument(
|
||||
"output_dir",
|
||||
metavar="output_folder_path",
|
||||
type=str,
|
||||
help="the folder path to install dir inclued fip,rootfs and kernel",
|
||||
)
|
||||
parser.add_argument("xml", help="path to partition xml")
|
||||
parser.add_argument(
|
||||
"-v", "--verbose", help="increase output verbosity", action="store_true"
|
||||
)
|
||||
args = parser.parse_args()
|
||||
if args.verbose:
|
||||
logging.debug("Enable more verbose output")
|
||||
logging.getLogger().setLevel(level=logging.DEBUG)
|
||||
|
||||
return args
|
||||
|
||||
|
||||
class ImagerBuilder(object):
|
||||
def __init__(self, storage: int, output_path):
|
||||
self.storage = storage
|
||||
self.output_path = output_path
|
||||
|
||||
def packHeader(self, part):
|
||||
"""
|
||||
Header format total 64 bytes
|
||||
4 Bytes: Magic
|
||||
4 Bytes: Version
|
||||
4 Bytes: Chunk header size
|
||||
4 Bytes: Total chunks
|
||||
4 Bytes: File size
|
||||
32 Bytes: Extra Flags
|
||||
12 Bytes: Reserved
|
||||
"""
|
||||
with open(part["file_path"], "rb") as fd:
|
||||
magic = fd.read(4)
|
||||
if magic == b"CIMG":
|
||||
logging.debug("%s has been packed, skip it!" % part["file_name"])
|
||||
return
|
||||
fd.seek(0)
|
||||
Magic = array("b", [ord(c) for c in "CIMG"])
|
||||
Version = array("I", [1])
|
||||
chunk_header_sz = 64
|
||||
Chunk_sz = array("I", [chunk_header_sz])
|
||||
chunk_counts = part["file_size"] // MAX_LOAD_SIZE
|
||||
remain = part["file_size"] - MAX_LOAD_SIZE * chunk_counts
|
||||
if (remain != 0):
|
||||
chunk_counts = chunk_counts + 1
|
||||
Totak_chunk = array("I", [chunk_counts])
|
||||
File_sz = array("I", [part["file_size"] + (chunk_counts * chunk_header_sz)])
|
||||
try:
|
||||
label = part["label"]
|
||||
except KeyError:
|
||||
label = "gpt"
|
||||
Extra_flags = array("B", [ord(c) for c in label])
|
||||
for _ in range(len(label), 32):
|
||||
Extra_flags.append(ord("\0"))
|
||||
|
||||
img = open(os.path.join(self.output_path, part["file_name"]), "wb")
|
||||
# Write Header
|
||||
for h in [Magic, Version, Chunk_sz, Totak_chunk, File_sz, Extra_flags]:
|
||||
h.tofile(img)
|
||||
img.seek(64)
|
||||
total_size = part["file_size"]
|
||||
offset = part["offset"]
|
||||
part_sz = part["part_size"]
|
||||
while total_size:
|
||||
chunk_sz = min(MAX_LOAD_SIZE, total_size)
|
||||
chunk = fd.read(chunk_sz)
|
||||
crc = binascii.crc32(chunk) & 0xFFFFFFFF
|
||||
chunk_header = self._getChunkHeader(chunk_sz, offset, part_sz, crc)
|
||||
img.write(chunk_header)
|
||||
img.write(chunk)
|
||||
total_size -= chunk_sz
|
||||
offset += chunk_sz
|
||||
img.close()
|
||||
|
||||
def _getChunkHeader(self, size: int, offset: int, part_sz: int, crc32: int):
|
||||
"""
|
||||
Header format total 64 bytes
|
||||
4 Bytes: Chunk Type
|
||||
4 Bytes: Chunk data size
|
||||
4 Bytes: Program part offset
|
||||
4 Bytes: Program part size
|
||||
4 Bytes: Crc32 checksum
|
||||
"""
|
||||
logging.info("size:%x, offset:%x, part_sz:%x, crc:%x" % (size, offset, part_sz, crc32))
|
||||
Chunk = array(
|
||||
"I",
|
||||
[
|
||||
CHUNK_TYPE_CRC_CHECK,
|
||||
size,
|
||||
offset,
|
||||
part_sz,
|
||||
crc32,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
],
|
||||
)
|
||||
return Chunk
|
||||
|
||||
|
||||
def main():
|
||||
args = parse_Args()
|
||||
xmlParser = XmlParser(args.xml)
|
||||
install_dir = os.path.dirname(args.file_path)
|
||||
parts = xmlParser.parse(install_dir)
|
||||
storage = xmlParser.getStorage()
|
||||
tmp = TemporaryDirectory()
|
||||
imgBuilder = ImagerBuilder(storage, tmp.name)
|
||||
for p in parts:
|
||||
# Since xml parser will parse with abspath and the user input path can
|
||||
# be relative path, use file name to check.
|
||||
if os.path.basename(args.file_path) == p["file_name"]:
|
||||
if (
|
||||
storage != "emmc" and storage != "spinor"
|
||||
and p["file_size"] > p["part_size"] - 128 * 1024
|
||||
and p["mountpoint"]
|
||||
and p["mountpoint"] != ""
|
||||
):
|
||||
logging.error(
|
||||
"Imaege is too big, it will cause mount partition failed!!"
|
||||
)
|
||||
raise ValueError
|
||||
imgBuilder.packHeader(p)
|
||||
tmp_path = os.path.join(tmp.name, p["file_name"])
|
||||
out_path = os.path.join(args.output_dir, p["file_name"])
|
||||
logging.debug("Moving %s -> %s" % (tmp_path, out_path))
|
||||
shutil.move(tmp_path, out_path)
|
||||
logging.info("Packing %s done!" % (p["file_name"]))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user