660 lines
18 KiB
Python
Executable File
660 lines
18 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# PYTHON_ARGCOMPLETE_OK
|
|
|
|
import logging
|
|
import os
|
|
import re
|
|
import glob
|
|
import argparse
|
|
import itertools
|
|
import collections
|
|
import json
|
|
import os.path
|
|
from datetime import datetime
|
|
|
|
import build_helper
|
|
import kconfiglib
|
|
|
|
try:
|
|
import argcomplete
|
|
except ImportError:
|
|
argcomplete = None
|
|
|
|
|
|
build_helper.check_python_min_version()
|
|
|
|
Board = collections.namedtuple("Board", "chip, board, ddr_cfg, info")
|
|
Arch = collections.namedtuple("Arch", "chip, board")
|
|
|
|
ENVS_FROM_CONFIG = [
|
|
"CHIP",
|
|
"ARCH",
|
|
"BOARD",
|
|
"DDR_CFG",
|
|
"ATF_SRC",
|
|
"ATF_KEY_SEL",
|
|
"KERNEL_SRC",
|
|
"UBOOT_SRC",
|
|
"USE_CCACHE",
|
|
"MULTI_FIP",
|
|
"STORAGE_TYPE",
|
|
"NANDFLASH_PAGESIZE",
|
|
"MW_VER",
|
|
"SDK_VER",
|
|
"SENSOR_TUNING_PARAM",
|
|
"BUILD_TURNKEY_ACCESSGUARD",
|
|
"BUILD_TURNKEY_IPC",
|
|
"FLASH_SIZE_SHRINK",
|
|
"BUILD_FOR_DEBUG",
|
|
"DDR_64MB_SIZE",
|
|
"PANEL_TUNING_PARAM",
|
|
"PANEL_LANE_NUM_TUNING_PARAM",
|
|
"PANEL_LANE_SWAP_TUNING_PARAM",
|
|
"MTRACE",
|
|
]
|
|
|
|
|
|
def parse_args():
|
|
parser = argparse.ArgumentParser(
|
|
description="Scan boards to generate env and configs"
|
|
)
|
|
parser.add_argument(
|
|
"-v",
|
|
"--verbose",
|
|
default="INFO",
|
|
choices=["CRITICAL", "DEBUG", "ERROR", "INFO", "NOTSET", "WARNING"],
|
|
)
|
|
parser.add_argument("--logfile", type=str)
|
|
parser.add_argument("--gen-build-kconfig", action="store_true")
|
|
parser.add_argument("--scan-boards-config", action="store_true")
|
|
parser.add_argument("--gen-board-env", type=str)
|
|
parser.add_argument("--print-usage", action="store_true")
|
|
parser.add_argument("--list-chip-arch", action="store_true")
|
|
parser.add_argument("--get-chip-arch", action="store_true")
|
|
parser.add_argument("--list-boards", type=str)
|
|
parser.add_argument("--gen-board-its", dest="arch")
|
|
parser.add_argument("--gen_single_board_its", action="store_true")
|
|
parser.add_argument("--chip_name", dest="chip_name", type=str)
|
|
parser.add_argument("--board_name", dest="board_name", type=str)
|
|
parser.add_argument("--skip_ramdisk", action="store_true")
|
|
|
|
if argcomplete:
|
|
argcomplete.autocomplete(parser)
|
|
|
|
return parser.parse_args()
|
|
|
|
|
|
def load_board_config(path):
|
|
logging.debug("load %s", path)
|
|
|
|
kconf = kconfiglib.Kconfig(
|
|
build_helper.KCONFIG_PATH, suppress_traceback=True, warn=True
|
|
)
|
|
kconf.load_config(path)
|
|
|
|
return kconf
|
|
|
|
|
|
def check_board_path(board_dir, chip, board):
|
|
full_board_name = os.path.basename(board_dir)
|
|
full_board_name2 = "%s_%s" % (chip, board)
|
|
logging.debug("full_board_name=%s %s", full_board_name, full_board_name2)
|
|
if full_board_name != full_board_name2:
|
|
raise Exception(
|
|
"The CHIP(%s)/BOARD(%s) in .config are not same as %s"
|
|
% (chip, board, full_board_name)
|
|
)
|
|
|
|
|
|
def scan_boards_config():
|
|
configs_saved = sorted(glob.glob(build_helper.BOARD_KCONFIG_SAVED_GLOB))
|
|
|
|
boards = {}
|
|
|
|
for n, path in enumerate(configs_saved):
|
|
*_, arch, board, conf = path.split("/")
|
|
if arch == "default":
|
|
continue
|
|
|
|
kconf = load_board_config(path)
|
|
|
|
check_board_path(
|
|
os.path.dirname(path),
|
|
kconf.syms["CHIP"].str_value,
|
|
kconf.syms["BOARD"].str_value,
|
|
)
|
|
|
|
br = Board(
|
|
kconf.syms["CHIP"].str_value,
|
|
kconf.syms["BOARD"].str_value,
|
|
kconf.syms["DDR_CFG"].str_value,
|
|
"",
|
|
)
|
|
|
|
logging.debug("%d: %s", n, br)
|
|
boards.setdefault(br.chip, []).append(br)
|
|
|
|
return boards
|
|
|
|
|
|
kconfig_tmpl = """
|
|
#
|
|
# Automatically generated by boards_scan.py; DO NOT EDIT.
|
|
#
|
|
|
|
choice
|
|
prompt "Chip selection"
|
|
{chip_choice}
|
|
endchoice
|
|
|
|
{chip_arch_config}
|
|
|
|
config CHIP
|
|
string
|
|
{chip_config}
|
|
|
|
choice
|
|
prompt "Board selection"
|
|
{board_choice}
|
|
endchoice
|
|
|
|
config BOARD
|
|
string
|
|
{board_config}
|
|
|
|
choice
|
|
prompt "DDR configuration selection"
|
|
{ddr_cfg_choice}
|
|
endchoice
|
|
|
|
config DDR_CFG
|
|
string
|
|
{ddr_cfg_config}
|
|
|
|
"""
|
|
|
|
|
|
def board_dir_to_name(board_dir):
|
|
chips = build_helper.get_chip_list()
|
|
chip_list = list(itertools.chain(*chips.values()))
|
|
|
|
m = re.search(
|
|
r"^([0-9a-z]+)_(.+)$", os.path.basename(board_dir), flags=re.IGNORECASE
|
|
)
|
|
chip, br_name = m.groups()
|
|
if chip not in chip_list:
|
|
raise Exception(
|
|
"%r of %r is unknown (missing in chip_list.json?)" % (chip, board_dir)
|
|
)
|
|
|
|
for chip_arch, xlist in chips.items():
|
|
if chip in xlist:
|
|
break
|
|
else:
|
|
raise Exception("Can't find CHIP_ARCH for %r" % chip)
|
|
|
|
return chip_arch, chip, br_name
|
|
|
|
|
|
def gen_build_kconfig():
|
|
board_list = collections.OrderedDict()
|
|
config_str = {
|
|
"chip_choice": "",
|
|
"chip_arch_config": "",
|
|
"chip_config": "",
|
|
"board_choice": "",
|
|
"board_config": "",
|
|
"ddr_cfg_choice": "",
|
|
}
|
|
|
|
board_list.setdefault("none", []).append(Board("none", "none", "none", "none"))
|
|
|
|
os.makedirs(build_helper.BUILD_OUTPUT_DIR, exist_ok=True)
|
|
|
|
kconfig_path = os.path.join(build_helper.BUILD_OUTPUT_DIR, "Kconfig")
|
|
|
|
for chip_arch in build_helper.get_chip_list():
|
|
_dir = os.path.join(build_helper.BOARD_DIR, chip_arch)
|
|
|
|
for board_dir in sorted(os.listdir(_dir)):
|
|
if board_dir.strip() == "default":
|
|
continue
|
|
board_dir = os.path.join(build_helper.BOARD_DIR, chip_arch, board_dir)
|
|
if not os.path.isdir(board_dir):
|
|
continue
|
|
|
|
logging.debug("board_dir=%r", board_dir)
|
|
_, chip, br_name = board_dir_to_name(board_dir)
|
|
|
|
cj_path = os.path.join(board_dir, "config.json")
|
|
with open(cj_path, "r", encoding="utf-8") as fp:
|
|
cj = json.load(fp)
|
|
|
|
br = Board(chip, br_name, cj["ddr_cfg_list"], cj["board_information"])
|
|
board_list.setdefault(chip, []).append(br)
|
|
|
|
chip_list = build_helper.get_chip_list()
|
|
chip_list["none"] = ["none"]
|
|
chip_list_r = {c: k for k, v in chip_list.items() for c in v}
|
|
|
|
config_str["chip_choice"] = "\n ".join(
|
|
(
|
|
'config CHIP_{chip}\n bool "{chip}"\n select CHIP_ARCH_{chip_arch}'.format(
|
|
chip=chip, chip_arch=chip_list_r[chip]
|
|
).strip()
|
|
for chip in board_list.keys()
|
|
)
|
|
)
|
|
|
|
config_str["chip_config"] = "\n ".join(
|
|
[
|
|
'default "{chip}" if CHIP_{chip}'.format(chip=chip).strip()
|
|
for chip in board_list.keys()
|
|
]
|
|
)
|
|
|
|
config_str["chip_arch_config"] = "\n".join(
|
|
(
|
|
"config CHIP_ARCH_{chip_arch}\n def_bool n".format(
|
|
chip_arch=chip_arch
|
|
).strip()
|
|
for chip_arch in chip_list
|
|
)
|
|
)
|
|
|
|
config_str["board_choice"] = "\n ".join(
|
|
[
|
|
'config BOARD_{br}\n bool "{br} ({br_info})"\n depends on CHIP_{chip}'.format(
|
|
chip=chip, br=br.board, br_info=br.info if br.info else "none"
|
|
).strip()
|
|
for chip, br_list in board_list.items()
|
|
for br in br_list
|
|
]
|
|
)
|
|
|
|
config_str["board_config"] = "\n ".join(
|
|
[
|
|
'default "{br}" if BOARD_{br}'.format(br=br.board).strip()
|
|
for _, br_list in board_list.items()
|
|
for br in br_list
|
|
]
|
|
)
|
|
|
|
config_str["ddr_cfg_choice"] = "\n ".join(
|
|
[
|
|
'config DDR_CFG_{ddf_cfg}\n bool "{ddf_cfg}"\n depends on CHIP_{chip} && BOARD_{br}'.format(
|
|
chip=chip, br=br.board, ddf_cfg=ddr_cfg if ddr_cfg else "none"
|
|
).strip()
|
|
for chip, br_list in board_list.items()
|
|
for br in br_list
|
|
for ddr_cfg in br.ddr_cfg
|
|
]
|
|
)
|
|
|
|
config_str["ddr_cfg_config"] = "\n ".join(
|
|
[
|
|
'default "{ddf_cfg}" if DDR_CFG_{ddf_cfg}'.format(
|
|
ddf_cfg=ddr_cfg if ddr_cfg else "none"
|
|
).strip()
|
|
for chip, br_list in board_list.items()
|
|
for br in br_list
|
|
for ddr_cfg in br.ddr_cfg
|
|
]
|
|
)
|
|
|
|
kconfig = kconfig_tmpl.format(**config_str)
|
|
with open(kconfig_path, "w") as fp:
|
|
fp.write(kconfig)
|
|
|
|
|
|
def gen_build_env(boards):
|
|
chips = build_helper.get_chip_list()
|
|
|
|
# Chip definition
|
|
for chip_arch, chip_list in sorted(chips.items()):
|
|
chip_list = " ".join(sorted(chip_list))
|
|
print("chip_%s=(%s)" % (chip_arch, chip_list))
|
|
|
|
chip_cv_str = " ".join(sorted(itertools.chain(*chips.values())))
|
|
print("chip_cv=(%s)" % chip_cv_str)
|
|
# compatible with the original shell script
|
|
print("chip_sel=(%s)" % chip_cv_str)
|
|
|
|
# Platform definition
|
|
print("subtype_sel=(palladium fpga asic)")
|
|
|
|
# Board definition and information
|
|
for chip, br_list in boards.items():
|
|
n = 0
|
|
br_list = [
|
|
i for i in br_list if all(j not in i.board for j in ["palladium", "fpga"])
|
|
]
|
|
br_list.sort()
|
|
for n, br in enumerate(br_list):
|
|
print('%s_board_sel[%d]="%s"' % (chip, n, br.board))
|
|
print('%s_board_info[%d]="%s"' % (chip, n, br.info))
|
|
print('%s_board_ddr_cfg[%d]="%s"' % (chip, n, br.ddr_cfg))
|
|
|
|
|
|
def gen_board_env(full_board_name):
|
|
logging.debug("full_board_name=%s", full_board_name)
|
|
|
|
config_path = os.path.join(build_helper.BUILD_REPO_DIR, ".config")
|
|
with open(config_path, "r"):
|
|
pass
|
|
kconf = load_board_config(config_path)
|
|
|
|
chips = build_helper.get_chip_list()
|
|
chip = kconf.syms["CHIP"].str_value
|
|
|
|
for chip_arch, chip_list in chips.items():
|
|
if chip in chip_list:
|
|
print('export CHIP_ARCH="%s"' % chip_arch.upper())
|
|
break
|
|
else:
|
|
raise Exception("Can't find CHIP_ARCH for %r" % chip)
|
|
|
|
print('export CHIP_SEGMENT="%s"' % build_helper.get_segment_from_chip(chip))
|
|
|
|
for name in ENVS_FROM_CONFIG:
|
|
print('export %s="%s"' % (name, kconf.syms[name].str_value))
|
|
|
|
board = kconf.syms["BOARD"].str_value
|
|
subtype = [i for i in ["palladium", "fpga"] if i in board]
|
|
if subtype:
|
|
subtype = subtype[0]
|
|
else:
|
|
subtype = "asic"
|
|
print('export SUBTYPE="%s"' % subtype)
|
|
|
|
|
|
def get_chip_arch(board):
|
|
if not board:
|
|
return
|
|
board_split, *_ = board.split("_")
|
|
if board == board_split:
|
|
return
|
|
for arch, chips in build_helper.get_chip_list().items():
|
|
if board_split in chips:
|
|
print(arch)
|
|
return
|
|
|
|
|
|
def list_chip_arch():
|
|
for arch, chips in build_helper.get_chip_list().items():
|
|
print(" ** %6s ** -> %s" % (arch, chips))
|
|
|
|
|
|
def list_boards_by_chip_arch(chip_arch):
|
|
boards = {}
|
|
if chip_arch not in build_helper.get_chip_list():
|
|
print(" \033[1;31;47m Input chip arch '", chip_arch, "' is ERROR\033[0m")
|
|
return
|
|
for arch in build_helper.get_chip_list()[chip_arch]:
|
|
boards[arch] = []
|
|
board_dir = os.path.join(build_helper.BOARD_DIR, chip_arch)
|
|
for board in sorted(os.listdir(board_dir)):
|
|
m = re.search(r"^([0-9a-z]+)_(.+)$", board, flags=re.IGNORECASE)
|
|
chip, _ = m.groups()
|
|
|
|
conf_path = os.path.join(board_dir, board, "config.json")
|
|
with open(conf_path, "r", encoding="utf-8") as fp:
|
|
conf = json.load(fp)
|
|
boards[chip].append({"board": board, "info": conf["board_information"]})
|
|
|
|
print("\033[93m*", chip_arch, "* the avaliable cvitek EVB boards\033[0m")
|
|
for chip, board_list in boards.items():
|
|
if not board_list:
|
|
continue
|
|
|
|
jump = 0
|
|
print("%8s - " % chip, end="")
|
|
for board in board_list:
|
|
jump = jump + 1
|
|
if jump > 1:
|
|
print(
|
|
" ",
|
|
board["board"],
|
|
" [",
|
|
board["info"],
|
|
"]",
|
|
end="\n",
|
|
sep="",
|
|
)
|
|
else:
|
|
print(board["board"], " [", board["info"], "]", end="\n", sep="")
|
|
|
|
|
|
def print_usage():
|
|
chips = build_helper.get_chip_list()
|
|
chip_list = list(itertools.chain(*chips.values()))
|
|
|
|
# Initialize the dictionary
|
|
map_name = dict()
|
|
map_info = dict()
|
|
for what in chip_list:
|
|
map_name[what] = []
|
|
|
|
for board_dir in sorted(os.listdir(build_helper.BOARD_DIR)):
|
|
if board_dir.strip() == "default":
|
|
continue
|
|
board_dir = os.path.join(build_helper.BOARD_DIR, board_dir)
|
|
if not os.path.isdir(board_dir):
|
|
continue
|
|
m = re.search(
|
|
r"^([0-9a-z]+)_(.+)$", os.path.basename(board_dir), flags=re.IGNORECASE
|
|
)
|
|
chip, br_name = m.groups()
|
|
map_name[chip].append(br_name)
|
|
cj_path = os.path.join(board_dir, "config.json")
|
|
with open(cj_path, "r", encoding="utf-8") as fp:
|
|
cj = json.load(fp)
|
|
map_info[chip + br_name] = cj["board_information"]
|
|
|
|
print("\033[93m- The avaliable cvitek EVB boards\033[0m")
|
|
for chip in sorted(map_name):
|
|
jump = 0
|
|
print("%8s - " % chip, end="")
|
|
for boards in sorted(map_name[chip]):
|
|
jump = jump + 1
|
|
if jump > 1:
|
|
print(
|
|
" ",
|
|
chip,
|
|
"_",
|
|
boards,
|
|
" [",
|
|
map_info[chip + boards],
|
|
"]",
|
|
end="\n",
|
|
sep="",
|
|
)
|
|
else:
|
|
print(
|
|
chip,
|
|
"_",
|
|
boards,
|
|
" [",
|
|
map_info[chip + boards],
|
|
"]",
|
|
end="\n",
|
|
sep="",
|
|
)
|
|
|
|
|
|
config_list_tmpl = """
|
|
configurations {{
|
|
{config}
|
|
}};
|
|
"""
|
|
|
|
|
|
fdt_list_tmpl = """
|
|
{fdt}
|
|
"""
|
|
|
|
|
|
fdt_tmpl = """
|
|
fdt-{chip}_{board} {{
|
|
description = "cvitek device tree - {chip}_{board}";
|
|
data = /incbin/("./{chip}_{board}.dtb");
|
|
type = "flat_dt";
|
|
arch = "arm64";
|
|
compression = "none";
|
|
hash-1 {{
|
|
algo = "{hash_algo}";
|
|
}};
|
|
}};
|
|
"""
|
|
|
|
|
|
config_tmpl = """
|
|
config-{chip}_{board} {{
|
|
description = "boot cvitek system with board {chip}_{board}";
|
|
kernel = "kernel-1";
|
|
ramdisk = "ramdisk-1";
|
|
fdt = "fdt-{chip}_{board}";
|
|
}};
|
|
"""
|
|
|
|
|
|
config_noramdisk_tmpl = """
|
|
config-{chip}_{board} {{
|
|
description = "boot cvitek system with board {chip}_{board}";
|
|
kernel = "kernel-1";
|
|
fdt = "fdt-{chip}_{board}";
|
|
}};
|
|
"""
|
|
|
|
|
|
def insertAfter(string, keyword, replacement):
|
|
i = string.find(keyword)
|
|
return string[: i + len(keyword)] + replacement + string[i + len(keyword) :]
|
|
|
|
|
|
def gen_single_board_its(chip, board, skip_ramdisk=False):
|
|
its_str = {
|
|
"fdt": "",
|
|
"config": "",
|
|
}
|
|
|
|
os.makedirs(build_helper.BUILD_OUTPUT_DIR, exist_ok=True)
|
|
its_path = os.path.join(build_helper.BUILD_OUTPUT_DIR, "multi.its.tmp")
|
|
|
|
cfg_tmpl = config_noramdisk_tmpl if skip_ramdisk else config_tmpl
|
|
its_str["fdt"] = fdt_tmpl.format(
|
|
chip=chip, board=board, hash_algo=get_hash_algo(board)
|
|
)
|
|
its_str["config"] = cfg_tmpl.format(chip=chip, board=board)
|
|
|
|
config_list = config_list_tmpl.format(**its_str)
|
|
fdt_list = fdt_list_tmpl.format(**its_str)
|
|
|
|
with open(its_path, "r") as fp:
|
|
FileString = fp.read()
|
|
replaceTmp = insertAfter(FileString, "/*FDT*/", fdt_list)
|
|
replaceDone = insertAfter(replaceTmp, "/*CFG*/", config_list)
|
|
|
|
with open(its_path, "w") as fp:
|
|
fp.write(replaceDone)
|
|
|
|
|
|
def get_hash_algo(br_name):
|
|
if "fpga" in br_name:
|
|
return "crc32"
|
|
elif "palladium" in br_name:
|
|
return "crc32"
|
|
return "sha256"
|
|
|
|
|
|
def gen_board_its(input_arch, skip_ramdisk=False):
|
|
its_str = {
|
|
"fdt": "",
|
|
"config": "",
|
|
}
|
|
os.makedirs(build_helper.BUILD_OUTPUT_DIR, exist_ok=True)
|
|
its_path = os.path.join(build_helper.BUILD_OUTPUT_DIR, "multi.its.tmp")
|
|
|
|
board_list = []
|
|
|
|
for _arch in build_helper.get_chip_list():
|
|
_dir = os.path.join(build_helper.BOARD_DIR, _arch)
|
|
|
|
for board_dir in sorted(os.listdir(_dir)):
|
|
if board_dir.strip() == "default":
|
|
continue
|
|
board_dir = os.path.join(build_helper.BOARD_DIR, _arch, board_dir)
|
|
if not os.path.isdir(board_dir):
|
|
continue
|
|
|
|
chip_arch, chip, br_name = board_dir_to_name(board_dir)
|
|
if chip_arch == input_arch:
|
|
board_list.append(Arch(chip, br_name))
|
|
|
|
cfg_tmpl = config_noramdisk_tmpl if skip_ramdisk else config_tmpl
|
|
its_str["fdt"] = "\n".join(
|
|
fdt_tmpl.format(chip=chip, board=board, hash_algo=get_hash_algo(board))
|
|
for chip, board in board_list
|
|
)
|
|
its_str["config"] = "\n".join(
|
|
cfg_tmpl.format(chip=chip, board=board) for chip, board in board_list
|
|
)
|
|
|
|
config_list = config_list_tmpl.format(**its_str)
|
|
fdt_list = fdt_list_tmpl.format(**its_str)
|
|
|
|
with open(its_path, "r") as fp:
|
|
FileString = fp.read()
|
|
replaceTmp = insertAfter(FileString, "/*FDT*/", fdt_list)
|
|
replaceDone = insertAfter(replaceTmp, "/*CFG*/", config_list)
|
|
|
|
with open(its_path, "w") as fp:
|
|
fp.write(replaceDone)
|
|
|
|
|
|
def main():
|
|
args = parse_args()
|
|
|
|
# build_helper.init_logging(args.logfile, stdout_level=args.verbose)
|
|
# build_helper.dump_debug_info()
|
|
logging.debug("[%s] start", datetime.now().isoformat())
|
|
|
|
# The location of the top Kconfig
|
|
os.environ["srctree"] = build_helper.BUILD_REPO_DIR
|
|
|
|
if args.gen_build_kconfig:
|
|
gen_build_kconfig()
|
|
|
|
if args.scan_boards_config:
|
|
boards = scan_boards_config()
|
|
gen_build_env(boards)
|
|
|
|
if args.gen_board_env:
|
|
gen_board_env(args.gen_board_env)
|
|
|
|
if args.print_usage:
|
|
print_usage()
|
|
|
|
if args.list_chip_arch:
|
|
list_chip_arch()
|
|
|
|
if args.list_boards:
|
|
list_boards_by_chip_arch(args.list_boards)
|
|
|
|
if args.arch:
|
|
gen_board_its(args.arch.lower(), args.skip_ramdisk)
|
|
|
|
if args.get_chip_arch:
|
|
get_chip_arch(args.board_name)
|
|
|
|
if args.gen_single_board_its:
|
|
gen_single_board_its(
|
|
args.chip_name.lower(), args.board_name.lower(), args.skip_ramdisk
|
|
)
|
|
|
|
logging.debug("[%s] finished", datetime.now().isoformat())
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|