vxKernel/scripts/core/board.py

244 lines
6.9 KiB
Python

"""
Board handling
"""
import os
import sys
import toml
__all__ = [
'board_select',
'board_command',
]
#---
# Internal functions
#---
__PROJ_PREFIX__ = f"{os.path.dirname(__file__)}/../.."
def _warning(text):
print(text, file=sys.stderr)
def _board_fetch_info_meta(board_info, board_desc, board):
""" Fetch and check board meta information
@args
> board_info (dict) - board information
> board_desc (dict) - board TOML parsed file
> board (str) - board name
@return
> 0 if success, negative value otherwise
"""
if 'meta' not in board_desc:
_warning(f"board '{board}' : missing meta section")
return -1
if 'author' not in board_desc['meta']:
_warning(f"board '{board}' : missing author names")
return -2
if 'description' not in board_desc['meta']:
_warning(f"board '{board}' : missing description")
return -3
board_info['author'] = board_desc['meta']['author']
board_info['desc'] = board_desc['meta']['description']
return 0
def _board_fetch_info_config(board_info, board_desc, board):
""" Fetch and check board configuration information
@args
> board_info (dict) - board information
> board_desc (dict) - board TOML parsed file
> board (str) - board name
@return
> 0 if success, negative value otherwise
"""
if 'config' not in board_desc:
_warning(f"board '{board}' : missing config section")
return -1
if 'modules' not in board_desc['config']:
_warning(f"board '{board}' : missing modules declaration")
return -2
if 'drivers' not in board_desc['config']:
_warning(f"board '{board}' : missing drivers declaration")
return -3
mod_prefix = f"{__PROJ_PREFIX__}/kernel/src/modules"
for mod in board_desc['config']['modules']:
if not os.path.exists(f"{mod_prefix}/{mod}"):
_warning(f"{board} : module '{mod}' does not exists, skipped")
continue
board_info['config']['modules'].append(mod)
drv_prefix = f"{__PROJ_PREFIX__}/kernel/src/drivers"
for drv in board_desc['config']['drivers']:
drv_path = drv.replace(':', '/')
if not os.path.exists(f"{drv_prefix}/{drv_path}"):
_warning(f"{board} : driver '{drv}' does not exists, skipped")
continue
board_info['config']['drivers'].append(drv_path)
return 0
def _board_fetch_info(board):
""" Generate all information about a particular board
@return
> a dictionary with all board information : {
'name' : <board name>,
'path' : <board absolute path>,
'config' : {
'drivers' : <list of driver pseudo-pathname>,
'modules' : <list of module pseudo-pathname>
},
'toolchain' : {
'file' : <toolchain file>,
'cflags' : <extra c flags>,
'libs' : <extra library needed>,
'ldflags' : <extra ld flags>
}
}
"""
board_info = {
'name' : board,
'path' : f"{__PROJ_PREFIX__}/boards/{board}",
'author' : 'unknown',
'desc' : 'unknown',
'config' : {
'drivers' : [],
'modules' : []
},
'toolchain' : {
'file' : None,
'cflags' : [],
'libs' : [],
'ldflags' : []
}
}
# Check board existance
if not os.path.exists(board_info['path']):
_warning(f"board '{board}' does not exists, skipped")
return {}
board_desc_path = f"{board_info['path']}/board.toml"
if not os.path.exists(board_desc_path):
_warning(f"board '{board}' : missing board description, skipped")
return {}
# Try to dump (and tranforms) board information
with open(board_desc_path, "r", encoding='utf8') as file:
board_desc = toml.loads(file.read())
# check meta board information
if _board_fetch_info_meta(board_info, board_desc, board) != 0:
return {}
# check board configuration
if _board_fetch_info_config(board_info, board_desc, board) != 0:
return {}
# return the board information
return board_info
def _board_fetch_available_board():
""" Fetch all available board
@return
> a list of all available board name
"""
# fetch folder information
board_prefix = f"{__PROJ_PREFIX__}/boards"
if not (available_list := list(os.walk(board_prefix))):
return []
# fetch folder content only
if not (available_list := available_list[0]):
return 0
# fetch directory only
return available_list[1]
def _board_generate_conf(kernconf, board_info):
""" generate exportable variable information
@args
> kernconf (dict) - kernel configuration
> board_info (dict) - board information
@return
> nothing
"""
kernconf['VXKERNEL_ENABLE_BOARD'] = board_info['name']
kernconf['VXKERNEL_ENABLE_MODULES'] = board_info['config']['modules']
kernconf['VXKERNEL_ENABLE_DRIVERS'] = board_info['config']['drivers']
def _board_display_list(verbose, board_target):
""" Display board information
@args
> verbose (bool) - display more information
> board_target (str) - targeted board
@return
> 0 if success, negative value othervise
"""
board_list = [board_target]
if not board_target:
board_list = _board_fetch_available_board()
print(f"\033[1m{'board':<16}{'Authors':<16}Description\033[0m")
for board in board_list:
if not (board_info := _board_fetch_info(board)):
continue
content = f"{board:<16}{board_info['author']:<16}{board_info['desc']}"
if verbose:
fake_kernconf = {}
_board_generate_conf(fake_kernconf, board_info)
content += ":\n"
for item in fake_kernconf.items():
content += f" {item[0]:<16} = {item[1]}\n"
print(content)
return 0
#---
# Public
#---
def board_select(kernconf, board):
""" Select a board and generate output information
@args
> kernconf (dict) - kernel configuration information
> board (str) - argument for the selection
@return
> Nothing, hangout if error. (return are only here for syntax sugar)
"""
if not (board_info := _board_fetch_info(board)):
sys.exit(84)
return _board_generate_conf(kernconf, board_info)
def board_command(argv):
""" Board-specific handler
@arg
> argv (list,str) - subcommand arguments
@return
> Never
"""
if not argv:
_warning('missing board argument')
sys.exit(84)
board = ''
verbose = False
for arg in argv:
if arg in ['--list', 'list']:
verbose = False
elif arg in ['--info', 'info']:
verbose = True
else:
if board:
_warning(f"{board} already selected, change for '{arg}'")
board = arg
sys.exit(_board_display_list(verbose, board))