scripts: utils: add board v1->v2 conversion utility
Assists on converting boards from hwmv1 to hwmv2. Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
This commit is contained in:
committed by
Jamie McCrae
parent
ef834a12d0
commit
6ae5c4e7fd
@@ -751,6 +751,7 @@ flagged.
|
||||
# toolchain Kconfig which is sourced based on
|
||||
# Zephyr toolchain variant and therefore not
|
||||
# visible to compliance.
|
||||
"BOARD_", # Used as regex in scripts/utils/board_v1_to_v2.py
|
||||
"BOOT_ENCRYPTION_KEY_FILE", # Used in sysbuild
|
||||
"BOOT_ENCRYPT_IMAGE", # Used in sysbuild
|
||||
"BINDESC_", # Used in documentation as a prefix
|
||||
|
||||
204
scripts/utils/board_v1_to_v2.py
Normal file
204
scripts/utils/board_v1_to_v2.py
Normal file
@@ -0,0 +1,204 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
Utility script to assist in the migration of a board from hardware model v1
|
||||
(HWMv1) to hardware model v2 (HWMv2).
|
||||
|
||||
.. warning::
|
||||
This script is not a complete migration tool. It is meant to assist in the
|
||||
migration process, but it does not handle all cases.
|
||||
|
||||
This script requires the following arguments:
|
||||
|
||||
- ``-b|--board``: The name of the board to migrate.
|
||||
- ``-g|--group``: The group the board belongs to. This is used to group a set of
|
||||
boards in the same folder. In HWMv2, the boards are no longer organized by
|
||||
architecture.
|
||||
- ``-v|--vendor``: The vendor name.
|
||||
- ``-s|--soc``: The SoC name.
|
||||
|
||||
In some cases, the new board name will differ from the old board name. For
|
||||
example, the old board name may have the SoC name as a suffix, while in HWMv2,
|
||||
this is no longer needed. In such cases, ``-n|--new-board`` needs to be
|
||||
provided.
|
||||
|
||||
For boards with variants, ``--variants`` needs to be provided.
|
||||
|
||||
For out-of-tree boards, provide ``--board-root`` pointing to the custom board
|
||||
root.
|
||||
|
||||
Copyright (c) 2023 Nordic Semiconductor ASA
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
"""
|
||||
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
import re
|
||||
import sys
|
||||
|
||||
import ruamel.yaml
|
||||
|
||||
|
||||
ZEPHYR_BASE = Path(__file__).parents[2]
|
||||
|
||||
|
||||
def board_v1_to_v2(board_root, board, new_board, group, vendor, soc, variants):
|
||||
try:
|
||||
board_path = next(board_root.glob(f"boards/*/{board}"))
|
||||
except StopIteration:
|
||||
sys.exit(f"Board not found: {board}")
|
||||
|
||||
new_board_path = board_root / "boards" / "v2" / group / new_board
|
||||
if new_board_path.exists():
|
||||
print("New board already exists, updating board with additional SoC")
|
||||
if not soc:
|
||||
sys.exit("No SoC provided")
|
||||
|
||||
new_board_path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
print("Moving files to the new board folder...")
|
||||
for f in board_path.iterdir():
|
||||
f_new = new_board_path / f.name
|
||||
if f_new.exists():
|
||||
print(f"Skipping existing file: {f_new}")
|
||||
continue
|
||||
f.rename(f_new)
|
||||
|
||||
print("Creating or updating board.yaml...")
|
||||
board_settings_file = new_board_path / "board.yml"
|
||||
if not board_settings_file.exists():
|
||||
board_settings = {
|
||||
"board": {
|
||||
"name": new_board,
|
||||
"vendor": vendor,
|
||||
"socs": []
|
||||
}
|
||||
}
|
||||
else:
|
||||
with open(board_settings_file) as f:
|
||||
board_settings = ruamel.yaml.safe_load(f) # pylint: disable=assignment-from-no-return
|
||||
|
||||
soc = {"name": soc}
|
||||
if variants:
|
||||
soc["variants"] = [{"name": variant} for variant in variants]
|
||||
|
||||
board_settings["board"]["socs"].append(soc)
|
||||
|
||||
yaml = ruamel.yaml.YAML()
|
||||
yaml.indent(sequence=4, offset=2)
|
||||
with open(board_settings_file, "w") as f:
|
||||
yaml.dump(board_settings, f)
|
||||
|
||||
print(f"Updating {board}_defconfig...")
|
||||
board_defconfig_file = new_board_path / f"{board}_defconfig"
|
||||
with open(board_defconfig_file) as f:
|
||||
board_soc_settings = []
|
||||
board_defconfig = ""
|
||||
|
||||
dropped_line = False
|
||||
for line in f.readlines():
|
||||
m = re.match(r"^CONFIG_BOARD_.*$", line)
|
||||
if m:
|
||||
dropped_line = True
|
||||
continue
|
||||
|
||||
m = re.match(r"^CONFIG_(SOC_[A-Z0-9_]+).*$", line)
|
||||
if m:
|
||||
board_soc_settings.append(m.group(1))
|
||||
dropped_line = True
|
||||
continue
|
||||
|
||||
if dropped_line and re.match(r"^$", line):
|
||||
continue
|
||||
|
||||
dropped_line = False
|
||||
board_defconfig += line
|
||||
|
||||
with open(board_defconfig_file, "w") as f:
|
||||
f.write(board_defconfig)
|
||||
|
||||
print("Updating Kconfig.defconfig...")
|
||||
board_kconfig_defconfig_file = new_board_path / "Kconfig.defconfig"
|
||||
with open(board_kconfig_defconfig_file) as f:
|
||||
board_kconfig_defconfig = ""
|
||||
has_kconfig_defconfig_entries = False
|
||||
|
||||
in_board = False
|
||||
for line in f.readlines():
|
||||
# drop "config BOARD" entry from Kconfig.defconfig
|
||||
m = re.match(r"^config BOARD$", line)
|
||||
if m:
|
||||
in_board = True
|
||||
continue
|
||||
|
||||
if in_board and re.match(r"^\s+.*$", line):
|
||||
continue
|
||||
|
||||
in_board = False
|
||||
|
||||
m = re.match(r"^config .*$", line)
|
||||
if m:
|
||||
has_kconfig_defconfig_entries = True
|
||||
|
||||
m = re.match(rf"^(.*)BOARD_{board.upper()}(.*)$", line)
|
||||
if m:
|
||||
board_kconfig_defconfig += (
|
||||
m.group(1) + "BOARD_" + new_board.upper() + m.group(2) + "\n"
|
||||
)
|
||||
continue
|
||||
|
||||
board_kconfig_defconfig += line
|
||||
|
||||
if has_kconfig_defconfig_entries:
|
||||
with open(board_kconfig_defconfig_file, "w") as f:
|
||||
f.write(board_kconfig_defconfig)
|
||||
else:
|
||||
print("Removing empty Kconfig.defconfig after update...")
|
||||
board_kconfig_defconfig_file.unlink()
|
||||
|
||||
print(f"Creating or updating Kconfig.{new_board}...")
|
||||
new_board_kconfig_file = new_board_path / f"Kconfig.{new_board}"
|
||||
selects = "\n\t" + "\n\t".join(["select " + setting for setting in board_soc_settings])
|
||||
if not new_board_kconfig_file.exists():
|
||||
with open(new_board_kconfig_file, "w") as f:
|
||||
f.write(
|
||||
f"config BOARD_{new_board.upper()}{selects}"
|
||||
)
|
||||
else:
|
||||
with open(new_board_kconfig_file, "a") as f:
|
||||
f.write(selects)
|
||||
|
||||
print("Removing old Kconfig.board...")
|
||||
board_kconfig_file = new_board_path / "Kconfig.board"
|
||||
board_kconfig_file.unlink()
|
||||
|
||||
print("Conversion done!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(allow_abbrev=False)
|
||||
|
||||
parser.add_argument(
|
||||
"--board-root",
|
||||
type=Path,
|
||||
default=ZEPHYR_BASE,
|
||||
help="Board root",
|
||||
)
|
||||
|
||||
parser.add_argument("-b", "--board", type=str, required=True, help="Board name")
|
||||
parser.add_argument("-n", "--new-board", type=str, help="New board name")
|
||||
parser.add_argument("-g", "--group", type=str, required=True, help="Board group")
|
||||
parser.add_argument("-v", "--vendor", type=str, required=True, help="Vendor name")
|
||||
parser.add_argument("-s", "--soc", type=str, required=True, help="Board SoC")
|
||||
parser.add_argument("--variants", nargs="+", default=[], help="Board variants")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
board_v1_to_v2(
|
||||
args.board_root,
|
||||
args.board,
|
||||
args.new_board or args.board,
|
||||
args.group,
|
||||
args.vendor,
|
||||
args.soc,
|
||||
args.variants,
|
||||
)
|
||||
Reference in New Issue
Block a user