[build] add cvitek build scripts
Change-Id: If63ce4a669e5d4d72b8e3b9253336dd99bf74c30
This commit is contained in:
281
build/tools/common/spinand_tool/mkubiimg.py
Executable file
281
build/tools/common/spinand_tool/mkubiimg.py
Executable file
@ -0,0 +1,281 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
import argparse
|
||||
import logging
|
||||
from os import path, getcwd
|
||||
from XmlParser import XmlParser
|
||||
from tempfile import mkdtemp
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
FORMAT = "%(levelname)s: %(message)s"
|
||||
logging.basicConfig(level=logging.INFO, format=FORMAT)
|
||||
|
||||
|
||||
def resource_path(relative_path):
|
||||
""" Get absolute path to resource, works for dev and for PyInstaller """
|
||||
try:
|
||||
# PyInstaller creates a temp folder and stores path in _MEIPASS
|
||||
base_path = sys._MEIPASS
|
||||
except Exception:
|
||||
base_path = path.dirname(path.realpath(__file__))
|
||||
return path.join(base_path, relative_path)
|
||||
|
||||
|
||||
def parse_Args():
|
||||
parser = argparse.ArgumentParser(description="Create UBI image")
|
||||
parser.add_argument("xml", help="path to partition xml")
|
||||
parser.add_argument("label", help="label of the partition")
|
||||
parser.add_argument(
|
||||
"input_path", metavar="input", type=str, help="input file or folder for packing"
|
||||
)
|
||||
parser.add_argument(
|
||||
"output_path",
|
||||
metavar="output_file_path",
|
||||
type=str,
|
||||
help="the folder path to install dir inclued fip,rootfs and kernel",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"-v", "--verbose", help="increase output verbosity", action="store_true"
|
||||
)
|
||||
parser.add_argument(
|
||||
"-p",
|
||||
"--pagesize",
|
||||
help="page size of nand, default is 2Kib",
|
||||
type=str,
|
||||
default="2K",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-b",
|
||||
"--blocksize",
|
||||
help="block size of nand, default is 128Kib",
|
||||
type=str,
|
||||
default="128K",
|
||||
)
|
||||
|
||||
parser.add_argument("--ubinize", help="path to ubinize", type=str)
|
||||
parser.add_argument("--mkfs", help="path to mkfs.ubifs", type=str)
|
||||
parser.add_argument(
|
||||
"--ubionly",
|
||||
help="create ubi image only",
|
||||
action="store_true",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--maxsize",
|
||||
help="Set max size for the partition"
|
||||
"(For the partition without size assigned) ",
|
||||
type=int,
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--reserved",
|
||||
help="Set reserved blocks percentage for the partition,"
|
||||
"For example: --reserved 10 means 10%% reserved blocks."
|
||||
"(For the partition without size assigned) ",
|
||||
type=int,
|
||||
)
|
||||
args = parser.parse_args()
|
||||
if args.verbose:
|
||||
logging.debug("Enable more verbose output")
|
||||
logging.getLogger().setLevel(level=logging.DEBUG)
|
||||
|
||||
if args.ubinize is None:
|
||||
args.ubinize = resource_path("ubinize")
|
||||
|
||||
if args.mkfs is None:
|
||||
args.mkfs = resource_path("mkfs.ubifs")
|
||||
return args
|
||||
|
||||
|
||||
def log_subprocess_output(pipe):
|
||||
for line in iter(pipe.readline, b""): # b'\n'-separated lines
|
||||
logging.debug("got line from subprocess: %r", line)
|
||||
|
||||
|
||||
def create_ubicfg(img_path, part_size, label, output, ubionly=False):
|
||||
with open(output, "w") as f:
|
||||
f.write("[ubifs]\n")
|
||||
f.write("mode=ubi\n")
|
||||
f.write("image=%s\n" % img_path)
|
||||
f.write("vol_id=0\n")
|
||||
if not ubionly:
|
||||
f.write("vol_size=%d\n" % part_size)
|
||||
f.write("vol_type=dynamic\n")
|
||||
f.write("vol_name=%s\n" % label)
|
||||
f.write("vol_flags=autoresize\n")
|
||||
|
||||
# Debug message
|
||||
logging.debug("[ubifs]")
|
||||
logging.debug("[mode]=ubi")
|
||||
logging.debug("image=%s" % img_path)
|
||||
logging.debug("vol_id=0")
|
||||
logging.debug("vol_size=%d" % part_size)
|
||||
logging.debug("vol_type=dynamic")
|
||||
logging.debug("vol_name=%s" % label)
|
||||
logging.debug("vol_flags=autoresize")
|
||||
|
||||
|
||||
def create_ubifs(
|
||||
input_dir, output_dir, internal_part_size, pagesize, pebsize, mkfs, verbose=False
|
||||
):
|
||||
|
||||
lebsize = pebsize - 2 * pagesize
|
||||
part_lebcnt = internal_part_size / lebsize
|
||||
ubifs_args = "-r %s -m %d -e %d -c %d -F" % (
|
||||
input_dir,
|
||||
pagesize,
|
||||
lebsize,
|
||||
part_lebcnt,
|
||||
)
|
||||
logging.debug("ubifs args %s", ubifs_args)
|
||||
tmp_ubifs = path.join(output_dir, "tmp.ubifs")
|
||||
mkfs_cmd = "%s %s -o %s" % (mkfs, ubifs_args, tmp_ubifs)
|
||||
logging.debug("mkfs_cmd:%s", mkfs_cmd)
|
||||
try:
|
||||
process = subprocess.Popen(
|
||||
mkfs_cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
cwd=getcwd(),
|
||||
shell=True,
|
||||
)
|
||||
except Exception:
|
||||
return -1
|
||||
if verbose:
|
||||
with process.stdout:
|
||||
log_subprocess_output(process.stdout)
|
||||
ret = process.wait()
|
||||
return [ret, tmp_ubifs]
|
||||
|
||||
|
||||
def create_ubi(img_path, cfg_path, output, pagesize, pebsize, ubinize, verbose=False):
|
||||
ubi_args = "-p %d -m %d" % (pebsize, pagesize)
|
||||
logging.debug("ubi args %s", ubi_args)
|
||||
ubinize_cmd = "%s -o %s %s %s" % (ubinize, output, ubi_args, cfg_path)
|
||||
logging.debug("ubinize_cmd:%s", ubinize_cmd)
|
||||
try:
|
||||
process = subprocess.Popen(
|
||||
ubinize_cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
cwd=getcwd(),
|
||||
shell=True,
|
||||
)
|
||||
except Exception:
|
||||
return -1
|
||||
if verbose:
|
||||
with process.stdout:
|
||||
log_subprocess_output(process.stdout)
|
||||
ret = process.wait()
|
||||
return ret
|
||||
|
||||
|
||||
def main():
|
||||
args = parse_Args()
|
||||
parser = XmlParser(args.xml)
|
||||
parts = parser.parse()
|
||||
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 args.label == p["label"]:
|
||||
part = p
|
||||
|
||||
break
|
||||
try:
|
||||
part_size = part["part_size"]
|
||||
label = part["label"]
|
||||
except Exception:
|
||||
logging.error("label is not found in partition.xml, please check!")
|
||||
return -1
|
||||
logging.debug("get partition as below:")
|
||||
logging.debug(p)
|
||||
pagesize = XmlParser.parse_size(args.pagesize)
|
||||
pebsize = XmlParser.parse_size(args.blocksize)
|
||||
lebsize = pebsize - 2 * pagesize
|
||||
|
||||
if part_size == sys.maxsize:
|
||||
if args.maxsize:
|
||||
part_size = args.maxsize
|
||||
else:
|
||||
logging.error("please use --maxsize size to assign size")
|
||||
return 1
|
||||
# 1.
|
||||
# 2 PEBs are used to store the volume table;
|
||||
# 1 PEB is reserved for wear-leveling purposes;
|
||||
# 1 PEB is reserved for the atomic LEB change operation;
|
||||
# 2.
|
||||
# some amount of PEBs are reserved for bad PEB handling;
|
||||
# this is applicable for NAND flash but not for NOR flash
|
||||
# the amount of reserved PEBs is configurable and is equal to
|
||||
# 20 blocks per 1024 blocks by default.
|
||||
# 3.
|
||||
# UBI stores the EC and VID headers at the beginning of each PEB;
|
||||
# the number of bytes used for these purposes depends on
|
||||
# the flash type and is explained below.
|
||||
# 4.
|
||||
# According to above design, set at lease 5 blocks reserved
|
||||
# Set extra reserved for bad blocks, at least 1 block or 1% of partition
|
||||
# size for r/w partition
|
||||
# 5.
|
||||
# SP: PEB
|
||||
# SL: LEB
|
||||
# P: Total number of PEBs on the MTD device
|
||||
# O: The overhead related to storing EC and VID headers in bytes, i.e. O = SP - SL
|
||||
# B: Number of bad block handling
|
||||
# UBI Overhead = (B + 4) * SP + O * (P - B - 4)
|
||||
SP = pebsize
|
||||
SL = lebsize
|
||||
P = int(part_size / pebsize)
|
||||
Ox = SP - SL
|
||||
try:
|
||||
B = max(1, int((args.reserved / 100) * P), int(0.01 * P))
|
||||
except Exception:
|
||||
B = max(int(0.01 * P), 1)
|
||||
ubi_overhead = (B + 4) * SP + Ox * (P - B - 4)
|
||||
lebcnt = int((part_size - ubi_overhead) / pebsize)
|
||||
|
||||
internal_part_size = lebcnt * lebsize
|
||||
tmpdir = mkdtemp()
|
||||
if not args.ubionly:
|
||||
logging.info("Creating ubifs")
|
||||
ret, fs_path = create_ubifs(
|
||||
args.input_path,
|
||||
tmpdir,
|
||||
internal_part_size,
|
||||
pagesize,
|
||||
pebsize,
|
||||
args.mkfs,
|
||||
args.verbose,
|
||||
)
|
||||
if ret:
|
||||
logging.error("create ubifs error, please enable verbose!")
|
||||
return -1
|
||||
else:
|
||||
fs_path = args.input_path
|
||||
tmp_cfg_path = path.join(tmpdir, "tmp.cfg")
|
||||
create_ubicfg(
|
||||
fs_path,
|
||||
internal_part_size,
|
||||
label,
|
||||
tmp_cfg_path,
|
||||
(args.ubionly or part_size == sys.maxsize),
|
||||
)
|
||||
|
||||
ret = create_ubi(
|
||||
fs_path,
|
||||
tmp_cfg_path,
|
||||
args.output_path,
|
||||
pagesize,
|
||||
pebsize,
|
||||
args.ubinize,
|
||||
args.verbose,
|
||||
)
|
||||
if ret:
|
||||
logging.error("create ubi image error, please enable verbose!")
|
||||
return -1
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user