328 lines
9.9 KiB
Python
Executable File
328 lines
9.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
# Copyright (C) 2023-2024 ArtInChip
|
|
|
|
import os
|
|
import sys
|
|
import argparse
|
|
import subprocess
|
|
|
|
UBOOT_DIR = 'source/uboot-2021.10/'
|
|
LINUX_DIR = ''
|
|
|
|
|
|
def GetLinuxDir(args):
|
|
global LINUX_DIR
|
|
dirs = os.listdir(args.topdir + '/source')
|
|
|
|
for sub_dir in dirs:
|
|
if 'linux' in sub_dir:
|
|
LINUX_DIR = 'source/' + sub_dir + '/'
|
|
|
|
|
|
def RunCommand(cmd, dumpmsg=False, verbose=False):
|
|
"""Execute command
|
|
Args:
|
|
cmd: cmd line content
|
|
dumpmsg: display message during cmd execute
|
|
Return:
|
|
0 if success, -1 if failure.
|
|
"""
|
|
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=-1)
|
|
ret = p.wait()
|
|
if ret != 0:
|
|
print('Run commmand error:')
|
|
print(' ' + cmd)
|
|
print('stdout: {}\nstderr: {}'.format(p.stdout.read(), p.stderr.read()))
|
|
return -1
|
|
if verbose:
|
|
print(cmd)
|
|
if dumpmsg or verbose:
|
|
print(p.stdout.read())
|
|
if verbose:
|
|
print(p.stderr.read())
|
|
|
|
return 0
|
|
|
|
|
|
def RunShellCommand(cmd):
|
|
ret = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
if ret.returncode:
|
|
print(indent_str('Failed to run shell command:' + cmd, 1))
|
|
sys.exit(1)
|
|
return str(ret.stdout, encoding='utf-8')
|
|
|
|
|
|
def indent_str(text, indent):
|
|
itext = text
|
|
while indent > 0:
|
|
itext = '\t' + itext
|
|
indent -= 1
|
|
return itext
|
|
|
|
|
|
def GetReferenceBoardDefconfig(targetcfg):
|
|
cmd = 'find {} -maxdepth 1 -type f -name "*_defconfig"'.format(targetcfg)
|
|
defconfigs = RunShellCommand(cmd)
|
|
return defconfigs.split()
|
|
|
|
|
|
def GetChipNameOfDefconfig(dotcfg):
|
|
f = open(dotcfg, 'r')
|
|
lines = f.readlines()
|
|
f.close()
|
|
|
|
name = None
|
|
for ln in lines:
|
|
if 'LUBAN_CHIP_NAME' in ln:
|
|
name = ln.replace('LUBAN_CHIP_NAME=', '').replace('"', '').strip()
|
|
break
|
|
return name
|
|
|
|
|
|
def GetChipOptionOfDefconfig(dotcfg, chip):
|
|
f = open(dotcfg, 'r')
|
|
lines = f.readlines()
|
|
f.close()
|
|
|
|
name = None
|
|
for ln in lines:
|
|
if 'LUBAN_CHIP_{}'.format(chip.upper()) in ln and '=y' in ln:
|
|
name = ln.replace('=y', '').strip()
|
|
break
|
|
return name
|
|
|
|
|
|
def GetBoardNameOfDefconfig(dotcfg):
|
|
f = open(dotcfg, 'r')
|
|
lines = f.readlines()
|
|
f.close()
|
|
name = None
|
|
for ln in lines:
|
|
if 'LUBAN_BOARD_NAME' in ln:
|
|
name = ln.replace('LUBAN_BOARD_NAME=', '').replace('"', '').strip()
|
|
break
|
|
return name
|
|
|
|
|
|
def GetBoardOptionNameOfDefconfig(dotcfg, board_name):
|
|
f = open(dotcfg, 'r')
|
|
lines = f.readlines()
|
|
f.close()
|
|
opt_name = None
|
|
for ln in lines:
|
|
if 'LUBAN_BOARD_' in ln and board_name.upper() in ln and '=y' in ln:
|
|
opt_name = ln.replace('=y', '').strip()
|
|
break
|
|
return opt_name
|
|
|
|
|
|
def GetArchOfRefDefconfig(dotcfg):
|
|
f = open(dotcfg, 'r')
|
|
lines = f.readlines()
|
|
f.close()
|
|
name = None
|
|
for ln in lines:
|
|
if 'BR2_ARCH=' in ln:
|
|
name = ln.replace('BR2_ARCH=', '').replace('"', '').strip()
|
|
break
|
|
return name
|
|
|
|
|
|
def SelectReferenceDefconfig(defconfigs, dotconfigs):
|
|
reflist = []
|
|
for cfg in defconfigs:
|
|
for dotcfg in dotconfigs:
|
|
if os.path.basename(cfg) in dotcfg:
|
|
break
|
|
reflist.append(os.path.basename(cfg))
|
|
if len(reflist) == 0:
|
|
print(indent_str('Error, cannot find reference defconfig', 1))
|
|
sys.exit(1)
|
|
print(indent_str('Reference defconfig:(Delete one board base on selected defconfig)', 1))
|
|
num = 1
|
|
for ref in reflist:
|
|
print(indent_str('{}: {}'.format(num, ref), 2))
|
|
num += 1
|
|
inputstr = input(indent_str('Select reference defconfig for detele board(number): ', 1)).strip()
|
|
if inputstr.isdigit() == False:
|
|
print(indent_str('Error, please input number'), 1)
|
|
sys.exit(1)
|
|
num = int(inputstr)
|
|
if num not in range(1, len(reflist) + 1):
|
|
print(indent_str('Error, input number not in list', 1))
|
|
sys.exit(1)
|
|
|
|
selected = reflist[num - 1]
|
|
print(indent_str(selected + '\n', 2))
|
|
return selected
|
|
|
|
|
|
def GetBoardNameForConfig(name):
|
|
return name.replace('\t', '_').replace(' ', '_')
|
|
|
|
|
|
def GenDotConfig(args, cfg_list):
|
|
root_cfg = args.topdir + 'package/Config.in'
|
|
dotconfigs = []
|
|
tmpdir = os.path.dirname(args.conf) + '/tmp/'
|
|
cmd = 'rm -rf {} && mkdir -p {}'.format(tmpdir, tmpdir)
|
|
RunShellCommand(cmd)
|
|
for cfg in cfg_list:
|
|
dotcfg = tmpdir + os.path.basename(cfg) + '.config'
|
|
dotconfigs.append(dotcfg)
|
|
cmd = 'HOSTARCH={} BR2_CONFIG={} BASE_DIR={} BR2_DEFCONFIG={} {} --defconfig={} {}'.format(args.arch, dotcfg, args.outdir, cfg, args.conf, cfg, root_cfg)
|
|
RunShellCommand(cmd)
|
|
return dotconfigs
|
|
|
|
|
|
def DeleteOneBoardDirectory(topdir, refcfg, dotconfigs):
|
|
|
|
for ref_dotcfg in dotconfigs:
|
|
if refcfg in ref_dotcfg:
|
|
break
|
|
|
|
refboardname = GetBoardNameOfDefconfig(ref_dotcfg)
|
|
refchipname = GetChipNameOfDefconfig(ref_dotcfg)
|
|
refboard_dir = topdir + 'target/{}/{}'.format(refchipname, refboardname)
|
|
|
|
# copy new board directory
|
|
cmd = 'rm -rdf {}'.format(refboard_dir)
|
|
RunShellCommand(cmd)
|
|
print(indent_str('Deleted: ' + refboard_dir.replace(topdir, ''), 1))
|
|
|
|
|
|
def DeleteOneDefconfig(topdir, refcfg, dotconfigs):
|
|
global UBOOT_DIR
|
|
global LINUX_DIR
|
|
|
|
for ref_dotcfg in dotconfigs:
|
|
if refcfg in ref_dotcfg:
|
|
break
|
|
|
|
arch = GetArchOfRefDefconfig(ref_dotcfg)
|
|
refboardname = GetBoardNameOfDefconfig(ref_dotcfg)
|
|
refboard_opt = GetBoardOptionNameOfDefconfig(ref_dotcfg, refboardname)
|
|
refchipname = GetChipNameOfDefconfig(ref_dotcfg)
|
|
|
|
target_cfgdir = topdir + 'target/configs/'
|
|
f = open(target_cfgdir + refcfg, 'r')
|
|
lines = f.readlines()
|
|
f.close()
|
|
# Create U-Boot/Kernel/Busybox defconfig for new board
|
|
ref_uboot_cfg = ''
|
|
ref_linux_cfg = ''
|
|
ref_busybox_cfg = ''
|
|
for ln in lines:
|
|
if 'BR2_TARGET_UBOOT_BOARD_DEFCONFIG' in ln:
|
|
ref_uboot_cfg = ln.replace('BR2_TARGET_UBOOT_BOARD_DEFCONFIG', '').replace('=', '').replace('"', '').strip() + '_defconfig'
|
|
if 'BR2_LINUX_KERNEL_DEFCONFIG' in ln:
|
|
ref_linux_cfg = ln.replace('BR2_LINUX_KERNEL_DEFCONFIG', '').replace('=', '').replace('"', '').strip() + '_defconfig'
|
|
if 'BR2_PACKAGE_BUSYBOX_CONFIG' in ln:
|
|
ref_busybox_cfg = ln.replace('BR2_PACKAGE_BUSYBOX_CONFIG', '').replace('=', '').replace('"', '').strip()
|
|
|
|
# Delete defconfig for u-boot
|
|
refcfg_path = '{}{}configs/{}'.format(topdir, UBOOT_DIR, ref_uboot_cfg)
|
|
cmd = 'rm {}'.format(refcfg_path)
|
|
RunShellCommand(cmd)
|
|
print(indent_str('deleted: ' + refcfg_path.replace(topdir, ''), 1))
|
|
|
|
# Delete defconfig for linux kernel
|
|
if arch == 'riscv64':
|
|
arch = 'riscv'
|
|
refcfg_path = '{}{}arch/{}/configs/{}'.format(topdir, LINUX_DIR, arch, ref_linux_cfg)
|
|
cmd = 'rm {}'.format(refcfg_path)
|
|
RunShellCommand(cmd)
|
|
print(indent_str('Deleted: ' + refcfg_path.replace(topdir, ''), 1))
|
|
|
|
# Delete config for busybox
|
|
refcfg_path = '{}{}'.format(topdir, ref_busybox_cfg)
|
|
cmd = 'rm {}'.format(refcfg_path)
|
|
RunShellCommand(cmd)
|
|
print(indent_str('Deleted: ' + refcfg_path.replace(topdir, ''), 1))
|
|
|
|
# Delete SDK defconfig
|
|
refcfg_path = '{}{}'.format(target_cfgdir, refcfg)
|
|
cmd = 'rm {}'.format(refcfg_path)
|
|
RunShellCommand(cmd)
|
|
print(indent_str('Deleted: ' + refcfg_path.replace(topdir, ''), 1))
|
|
|
|
# Add new board to Config.in
|
|
cfg_in = '{}target/{}/Config.in'.format(topdir, refchipname)
|
|
f = open(cfg_in, 'r')
|
|
lines = f.readlines()
|
|
f.close()
|
|
|
|
board_option = 'LUBAN_BOARD_{}_{}'.format(refchipname.upper(), refboardname.upper())
|
|
f = open(cfg_in, 'w')
|
|
|
|
chip_option = GetChipOptionOfDefconfig(ref_dotcfg, refchipname)
|
|
delete_depends = False
|
|
for ln in lines:
|
|
if 'config' in ln and board_option in ln:
|
|
delete_depends = True
|
|
continue
|
|
if 'bool' in ln and refboardname in ln:
|
|
continue
|
|
if delete_depends and 'depends on' in ln and chip_option in ln:
|
|
delete_depends = False
|
|
continue
|
|
if 'default' in ln and board_option in ln:
|
|
continue
|
|
f.write(ln)
|
|
f.close()
|
|
print(indent_str('Updated: ' + cfg_in.replace(topdir, ''), 1))
|
|
|
|
|
|
def DeleteOneBoard(args):
|
|
GetLinuxDir(args)
|
|
target_cfgdir = args.topdir + 'target/configs/'
|
|
defconfigs = GetReferenceBoardDefconfig(target_cfgdir)
|
|
|
|
defconfigs.sort()
|
|
if len(defconfigs) == 0:
|
|
print(indent_str("Error: no defconfig is found.", 1));
|
|
sys.exit(1)
|
|
dotconfigs = GenDotConfig(args, defconfigs)
|
|
|
|
refcfg = SelectReferenceDefconfig(defconfigs, dotconfigs)
|
|
|
|
DeleteOneBoardDirectory(args.topdir, refcfg, dotconfigs)
|
|
DeleteOneDefconfig(args.topdir, refcfg, dotconfigs)
|
|
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("-c", "--conf", type=str, help="conf executable")
|
|
parser.add_argument("-t", "--topdir", type=str, help="Top root directory")
|
|
parser.add_argument("-o", "--outdir", type=str, help="Output root directory")
|
|
args = parser.parse_args()
|
|
|
|
if args.conf == None:
|
|
print(indent_str('Error, please provide path of application "conf"', 1))
|
|
sys.exit(1)
|
|
if os.path.exists(args.conf) == False:
|
|
print(indent_str('Error, "conf" is not exist', 1))
|
|
sys.exit(1)
|
|
|
|
if args.topdir == None:
|
|
print(indent_str('Error, please provide path of top directory', 1))
|
|
sys.exit(1)
|
|
|
|
args.topdir = os.path.abspath(args.topdir)
|
|
if args.topdir.endswith('/') == False:
|
|
args.topdir = args.topdir + '/'
|
|
if args.outdir == None:
|
|
args.outdir = args.topdir
|
|
else:
|
|
args.outdir = os.path.abspath(args.outdir)
|
|
if args.outdir.endswith('/') == False:
|
|
args.outdir = args.outdir + '/'
|
|
cmd = 'arch'
|
|
args.arch = RunShellCommand(cmd)
|
|
DeleteOneBoard(args)
|
|
|