vxGOS - v0.7.0-6 : PoC unitests interface

*add*
> [script]
  | [vxdev] add unitests interface
  | [vxdev] add bootloader unitests support
  | [vxdev] add cmake unitests generation
> [bootloader]
  | [unitests] add console open/close primitives unitests

*update*
> [script]
  | [vxdev] depreciate 'configure'
  | [vxdev] depreciate 'install'
  | [vxdev] depreciate 'uninstall'
  | [vxdev] rename build cmake abstraction
  | [vxdev] move KASLR script to build-specific module

*fix*
> [script]
  | [vxdev] fix generated build cmake template layout
> [bootloader]
  | [fxcg50] remove nonbreaking spaces
  | [console] close: proper clear console object
  | [console] open:  proper return error code
This commit is contained in:
Yann MAGNIN 2023-05-04 15:00:59 +02:00
parent 73711a76b2
commit 8acbd8bceb
26 changed files with 484 additions and 631 deletions

View File

@ -33,14 +33,10 @@ def _main(argv):
if not argv:
log.user(__HELP__)
sys.exit(84)
if argv[0] == 'configure':
sys.exit(cli.configure(argv[1:]))
if argv[0] == 'build':
sys.exit(cli.build(argv[1:]))
if argv[0] == 'install':
sys.exit(cli.install(argv[1:]))
if argv[0] == 'uninstall':
sys.exit(cli.uninstall(argv[1:]))
if argv[0] == 'unitests':
sys.exit(cli.unitests(argv[1:]))
print(f"unrecognized argument '{argv[0]}'", file=sys.stderr)
sys.exit(84)

View File

@ -1,40 +1,22 @@
"""
Expose configure script part
"""
from cli.configure import configure_entry
from cli.build import build_entry
from cli.install import install_entry
from cli.uninstall import uninstall_entry
from cli.doctor import doctor_entry
from cli.unitests import unitests_entry
__all__ = [
'configure',
'doctor',
'build',
'install',
'uninstall',
'unitests',
]
#---
# Public
#---
def doctor(argv):
""" invoke doctor script """
return doctor_entry(argv)
def configure(argv):
""" invoke configuration script """
return configure_entry(argv)
def build(argv):
""" invoke build script """
return build_entry(argv)
def install(argv):
""" invoke install script """
return install_entry(argv)
def uninstall(argv):
""" invoke uninstall script """
return uninstall_entry(argv)
def unitests(argv):
""" invoke unitests script """
return unitests_entry(argv)

View File

@ -1,95 +0,0 @@
"""
Vhex kernel configuration script
"""
import os
import sys
from core.board import board_command, board_select
from core.format import format_command, format_select
from core.config_file import config_file_generate
from core.cmake import cmake_configure
__all__ = [
'configure_entry'
]
__HELP__ = """ usage: vxdev configure [OTPIONS ...] [ACTIONS ...]
Configuration script for the Vhex unikernel.
Actions:
board: Board hadling
<board-name> select the board as compilation target
--list,list display board list information
--info,info display a particular board information
vdso: "Fake" kernel compilation like a vDSO
--info,info display all infromation that the vdso will exposes
--generate,gen generate the fake build source (debug)
Options:
-h,--help display this message
--board=<board> select the board to target
--format=<target>
select the format of the library generation. You can use two format:
<> static - generate a static library
<> vdso - generate a "fake" dynamic library (default)
"""
#---
# Public
#---
def configure_entry(argv):
""" main entry of the script """
# early check
if '-h' in argv or '--help' in argv:
print(__HELP__)
sys.exit(0)
# handle vxSDK configuration
if 'VXSDK_PKG_TARGET' in os.environ:
argv.append(f"--board={os.environ['VXSDK_PKG_TARGET']}")
# default behaviour
if not argv:
print(__HELP__)
sys.exit(84)
# configure default value
kernconf = {
'VXKERNEL_ENABLE_VERBOSE' : False,
'VXKERNEL_ENABLE_MODULES' : [],
'VXKERNEL_ENABLE_DRIVERS' : [],
'VXKERNEL_TARGET_FORMAT' : 'vdso',
}
# check subcommand
if argv[0] == 'board':
sys.exit(board_command(argv[1:]))
if argv[0] == 'format':
sys.exit(format_command(argv[1:]))
# check user arguments
for arg in argv:
if arg.find('--board=') == 0:
board_select(kernconf, arg[8:])
elif arg.find('--format=') == 0:
format_select(kernconf, arg[9:])
else:
print(f"argument '{arg}' not recognized", file=sys.stderr)
sys.exit(84)
# check vxSDK validity
try:
prefix_src = os.environ['VXSDK_CURRENT_SOURCE_DIR']
prefix_build = os.environ['VXSDK_PREFIX_BUILD']
if config_file_generate(kernconf, prefix_build) == 0:
sys.exit(cmake_configure(prefix_build, prefix_src))
except KeyError:
print(
"unable to generate the configuration file, you should use the "
"vxSDK",
file=sys.stderr
)
sys.exit(84)

View File

@ -1,32 +0,0 @@
"""
cli.doctor - used to check vxOS feature and process
"""
import sys
from core.logger import log
__all__ = [
'doctor_entry',
]
#----
# Internals
#----
__HELP__ = """ usage: vxdev doctor [OPTIONS] ...
Inspect vxOS source code a fetch information
Options
-h, --help display this help
"""
#---
# Public
#----
def doctor_entry(argv):
""" doctor CLI entry """
if '-h' in argv or '--help' in argv:
log.user(__HELP__)
sys.exit(0)

View File

@ -1,51 +0,0 @@
"""
Vhex kernel install script
"""
import os
import sys
#from core.cmake import cmake_install
__all__ = [
'install_entry'
]
__HELP__ = """ usage: vxdev install [OPTIONS] ...
Install script for the Vhex kernel
Options:
-h, --help display this message
-v, --verbose display more information during the building process
"""
#---
# Public
#---
def install_entry(argv):
""" Install entry """
if '-h' in argv or '--help' in argv:
print(__HELP__)
sys.exit(0)
enable_verbose = False
for arg in argv:
if arg in ['-v', '--verbose']:
enable_verbose = True
continue
print(f"unrecognized argument '{arg}'", file=sys.stderr)
sys.exit(84)
try:
_ = os.environ['VXSDK_PREFIX_BUILD']
__ = os.environ['VXSDK_PREFIX_INSTALL']
except KeyError:
print(
"unable to generate the configuration file, you should use the "
"vxSDK",
file=sys.stderr
)
sys.exit(84)
#return cmake_install(os.environ['VXSDK_PREFIX_BUILD'], enable_verbose)
return enable_verbose

View File

@ -1,51 +0,0 @@
"""
Vhex kernel uninstall script
"""
import os
import sys
#from core.cmake import cmake_uninstall
__all__ = [
'uninstall_entry'
]
__HELP__ = """ usage: vxdev uninstall [OPTIONS] ...
uninstall script for the Vhex kernel
Options:
-h, --help display this message
-v, --verbose display more information during the building process
"""
#---
# Public
#---
def uninstall_entry(argv):
""" uninstall entry """
if '-h' in argv or '--help' in argv:
print(__HELP__)
sys.exit(0)
enable_verbose = False
for arg in argv:
if arg in ['-v', '--verbose']:
enable_verbose = True
continue
print(f"unrecognized argument '{arg}'", file=sys.stderr)
sys.exit(84)
try:
_ = os.environ['VXSDK_PREFIX_BUILD']
__ = os.environ['VXSDK_PREFIX_INSTALL']
except KeyError:
print(
"unable to generate the configuration file, you should use the "
"vxSDK",
file=sys.stderr
)
sys.exit(84)
#return cmake_uninstall(os.environ['VXSDK_PREFIX_BUILD'], enable_verbose)
return enable_verbose

View File

@ -0,0 +1,46 @@
"""
cli.unitests - unit tests interface
"""
import sys
from core.logger import log
from core.unitests import VxOSUnitest
__all__ = [
'unitests_entry'
]
#---
# Internal
#---
__HELP__ = """ usage: vxdev unitest [OPTIONS] ...
Build script for the Vhex kernel
Options:
-h, --help display this message
-v, --verbose display more information during the building process
"""
#---
# Public
#---
def unitests_entry(argv):
""" Build entry """
if '-h' in argv or '--help' in argv:
log.user(__HELP__)
sys.exit(0)
enable_verbose = False
for arg in argv:
if arg in ['-v', '--verbose']:
enable_verbose = True
continue
log.error(f"unrecognized argument '{arg}'")
unitest = VxOSUnitest(enable_verbose)
unitest.configure()
unitest.execute()
return 0

View File

@ -1,242 +0,0 @@
"""
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
board_conf = board_desc['config']
if 'modules' not in board_conf:
_warning(f"board '{board}' : missing modules declaration")
return -2
if 'drivers' not in board_conf:
_warning(f"board '{board}' : missing drivers declaration")
return -3
mod_prefix = f"{__PROJ_PREFIX__}/kernel/src/modules"
for mod in board_conf['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_conf['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)
if 'install_files' in board_conf:
for file in board_conf['install_files']:
file_pathname = f"{__PROJ_PREFIX__}/boards/{board}/{file}"
if not os.path.exists(file_pathname):
_warning("{board}: unable to find the file '{file}', skipped")
continue
board_info['config']['install_files'].append(file_pathname)
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>
},
}
"""
board_info = {
'name' : board,
'path' : f"{__PROJ_PREFIX__}/boards/{board}",
'author' : 'unknown',
'desc' : 'unknown',
'config' : {
'drivers' : [],
'modules' : [],
'install_files' : []
}
}
# 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
"""
bconf = board_info['config']
kernconf['VXKERNEL_ENABLE_BOARD'] = board_info['name']
kernconf['VXKERNEL_ENABLE_MODULES'] = bconf['modules']
kernconf['VXKERNEL_ENABLE_DRIVERS'] = bconf['drivers']
kernconf['VXKERNEL_INSTALL_EXTRA_FILES'] = bconf['install_files']
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))

View File

@ -7,8 +7,8 @@ import sys
from core.logger import log
from core.build.bootloader import bootloader_configure
from core.build.kernel import kernel_configure
from core.cmake import cmake_build
from core.kaslr import kaslr_generate
from core.build.cmake import cmake_build_compile
from core.build.kaslr import kaslr_generate
from version import (
# VXGOS_OS_VERSION,
@ -119,7 +119,7 @@ class VxOSBuild():
log.user("[+] compiling each OS part...")
for partname in self._binlist:
log.user(f"- {partname}...")
binpathlist[partname] = cmake_build(
binpathlist[partname] = cmake_build_compile(
partname,
f"{self.prefix['build']}/{partname}/",
self.verbose

View File

@ -6,9 +6,9 @@ import subprocess
import glob
from core.logger import log
from core.cmake import (
cmake_generate_template,
cmake_configure,
from core.build.cmake import (
cmake_build_generate_template,
cmake_build_configure,
)
__all__ = [
@ -68,5 +68,5 @@ def bootloader_configure(build, version):
'src' : '\n '.join(assets_src + common_src + board_src),
'libs' : '\n '.join(os.environ['VXSDK_BUILD_LIBS'].split(';'))
}
cmake_generate_template(proj, prefix)
cmake_configure(proj['name'], prefix)
cmake_build_generate_template(proj, prefix)
cmake_build_configure(proj['name'], prefix)

View File

@ -8,9 +8,9 @@ import re
from core.logger import log
__all__ = [
'cmake_generate_template',
'cmake_configure',
'cmake_build',
'cmake_build_generate_template',
'cmake_build_configure',
'cmake_build_compile',
]
#---
@ -26,9 +26,15 @@ cmake_minimum_required(VERSION 3.15)
project({VXDEV_PROJ_NAME} VERSION {VXDEV_PROJ_VERSION} LANGUAGES C ASM)
include_directories({VXDEV_BUILD_INCLUDES})
add_compile_options({VXDEV_BUILD_CFLAGS})
add_link_options({VXDEV_BUILD_LDFLAGS})
include_directories(
{VXDEV_BUILD_INCLUDES}
)
add_compile_options(
{VXDEV_BUILD_CFLAGS}
)
add_link_options(
{VXDEV_BUILD_LDFLAGS}
)
set(
CMAKE_EXE_LINKER_FLAGS
"${CMAKE_EXE_LINKER_FLAGS} -T {VXDEV_BUILD_LINKER}"
@ -38,7 +44,8 @@ set(
# source files listing
#---
set(VXDEV_PROJ_SOURCES
set(
VXDEV_PROJ_SOURCES
{VXDEV_SOURCE_FILES}
)
@ -54,7 +61,7 @@ target_link_libraries({VXDEV_PROJ_NAME} {VXDEV_BUILD_LIBS})
# Pulbic
#---
def cmake_generate_template(proj, prefix):
def cmake_build_generate_template(proj, prefix):
""" Generate a common CMake file
@args
@ -77,7 +84,7 @@ def cmake_generate_template(proj, prefix):
with open(f"{prefix}/CMakeLists.txt", 'x', encoding='ascii') as cmk:
cmk.write(cmakefile)
def cmake_configure(name, prefix):
def cmake_build_configure(name, prefix):
""" Abstract cmake configuration
@args
@ -91,7 +98,7 @@ def cmake_configure(name, prefix):
if subprocess.run(shell_cmd.split(), check=False).returncode != 0:
log.emergency(f"{name}: unable to configure the projet, abord")
def cmake_build(name, prefix, verbose):
def cmake_build_compile(name, prefix, verbose):
""" Abstract cmake configuration
@args
@ -108,36 +115,3 @@ def cmake_build(name, prefix, verbose):
if subprocess.run(shell_cmd.split(), check=False).returncode != 0:
log.emergency(f"{name}: unable to configure the projet, abord")
return f"{prefix}/{name}"
#def cmake_install(prefix_build, verbose):
# """ Abstract cmake installation """
# shell_cmd = f"cmake --install {prefix_build}"
# if verbose:
# shell_cmd += ' --verbose'
# return subprocess.run(shell_cmd.split(), check=False).returncode
#
#def cmake_uninstall(prefix_build, verbose):
# """ Abstract cmake uninstall
#
# Note that CMake does not offert a easy way to uninstall project, but it
# generate a file which contains all installed pathname
# """
# manifile = f"{prefix_build}/install_manifest.txt"
# if not os.path.exists(manifile):
# print('project not installed')
# return -1
#
# retcode = 0
# with open(manifile, 'r', encoding='utf8') as manifest:
# for pathname in manifest.readlines():
# pathname = pathname.strip()
# if not os.path.exists(pathname):
# continue
# if verbose:
# print("-- Removing {pathname}")
# ret = subprocess.run(f"rm {pathname}".split(), check=False)
# if ret.returncode == 0:
# continue
# print("warning : error during removing file", file=sys.stderr)
# retcode -= 1
# return retcode

View File

@ -6,9 +6,9 @@ import glob
import toml
from core.logger import log
from core.cmake import (
cmake_generate_template,
cmake_configure,
from core.build.cmake import (
cmake_build_generate_template,
cmake_build_configure,
)
__all__ = [
@ -127,5 +127,5 @@ def kernel_configure(build, version):
'src' : '\n '.join(sources),
'libs' : '\n '.join(os.environ['VXSDK_BUILD_LIBS'].split(';'))
}
cmake_generate_template(proj, prefix)
cmake_configure(proj['name'], prefix)
cmake_build_generate_template(proj, prefix)
cmake_build_configure(proj['name'], prefix)

View File

@ -1,38 +0,0 @@
"""
Configuration file handling
"""
import os
__all__ = [
'config_file_generate'
]
#---
# Public
#---
def config_file_generate(kernconf, confile_prefix):
""" Generate the kernel configuration file for CMake build system
@args
> kernconf (dict) - kernel configuration information
> confile_prefix (str) - build prefix
@return
> 0 on success, negative value otherwise
"""
if not os.path.exists(confile_prefix):
os.makedirs(confile_prefix)
content = "# file generated by the vxSDK\n\n"
for item in kernconf.items():
if not (data := item[1]):
continue
if isinstance(item[1], list):
data = ' '.join(item[1])
content += f"set({item[0]} {data})\n"
confile_path = f"{confile_prefix}/vxkernel_config.cmake"
with open(confile_path, 'w+', encoding='utf8') as file:
file.write(content)
return 0

View File

@ -1,34 +0,0 @@
"""
Format handling
"""
__all__ = [
'format_select',
'format_command',
]
#---
# Public
#---
def format_select(_, __):
""" Select a kernel format and generate output information
@args
> kernconf (dict) - kernel configuration information
> format (str) - targeted format
@return
> Nothing, hangout if error. (return are only here for syntax sugar)
"""
def format_command(_):
""" format-specific handler
@arg
> argv (list,str) - subcommand arguments
@return
> Never
"""

View File

@ -0,0 +1,79 @@
"""
core.unitests - unit tests abstraction
"""
import os
import subprocess
from core.logger import log
from core.unitests.bootloader import bootloader_unitest_config
from core.unitests.cmake import cmake_unitest_compile
__all__ = [
'VxOSUnitest'
]
#---
# Public
#---
class VxOSUnitest():
""" Unit tests abstraction
"""
def __init__(self, verbose):
self._verbose = verbose
prefix_base = f"{os.path.dirname(__file__)}/../../../../"
prefix_base = os.path.normpath(prefix_base)
self._prefix = {
'base' : prefix_base,
'build' : f"{prefix_base}/.vxsdk/unitests",
'src' : f"{prefix_base}/vxgos",
}
self._unitpath = {
'bootloader' : [],
'kernel' : [],
'os' : [],
}
#---
# Properties
#---
@property
def prefix(self):
""" return the prefix dictionary """
return self._prefix
#---
# Methods
#---
def configure(self):
""" generate all unitests env """
self._unitpath['bootloader'] = bootloader_unitest_config(self)
def execute(self):
""" execute all unitests
"""
bininfo_list = []
log.user('- compile unitests...')
for item in self._unitpath.items():
for unitest in item[1]:
log.user(f" > {item[0]}:{unitest['name']}...")
bininfo_list.append((
f"{item[0]}:{unitest['name']}",
cmake_unitest_compile(
unitest['name'],
unitest['prefix'],
self._verbose
)
))
log.user('- execute unitests...')
for bininfo in bininfo_list:
log.user(f" > {bininfo[0]}...")
if subprocess.run([bininfo[1]], check=False).returncode != 0:
log.error("{bininfo[0]}: unitest error, skipped code coverage")
continue
cmd = f"gcovr {os.path.dirname(bininfo[1])}"
if subprocess.run(cmd.split(), check=False).returncode != 0:
log.error(f"{bininfo[0]}: code coverage error, skipped")
continue

View File

@ -0,0 +1,75 @@
"""
core.unitests.bootloader - bootloader unit tests abstraction
"""
import os
import glob
from core.logger import log
from core.unitests.cmake import (
cmake_unitest_generate_template,
cmake_unitest_configure
)
__all__ = [
'bootloader_unitest_config'
]
#---
# Internals
#---
def _bootloader_unitest_new(unitest, prefix, test):
""" add a new bootloader unitest
"""
log.debug(f"- new unitest '{test}'...")
dependencies = f"{prefix}/unitests/{test}/dependencies.txt"
if not os.path.exists(dependencies):
log.warn(f"bootloader:{test}: missing dependencies.txt, skipped")
return ''
deplist = []
with open(dependencies, 'r', encoding='ascii') as depfile:
while True:
if not (rela_filename := depfile.readline()):
break
real_filename = f"{prefix}/{rela_filename.strip()}"
if not os.path.exists(real_filename):
log.error(
f"bootloader:{test}: dependency '{real_filename}'"
"not exists"
)
return ''
deplist.append(real_filename)
log.user(f"> deplist = {deplist}")
srclist = f"{prefix}/unitests/{test}/**/*.[csS]"
srclist = glob.glob(srclist, recursive=True)
log.debug(f"> srclist = {srclist}")
include_list = [
f"{prefix}/include/",
f"{prefix}/unitests/{test}/"
]
proj = {
'name' : test,
'src' : '\n '.join(deplist + srclist),
'include' : '\n '.join(include_list)
}
prefix_build = f"{unitest.prefix['build']}/bootloader/{test}"
cmake_unitest_generate_template(proj, prefix_build)
cmake_unitest_configure(proj['name'], prefix_build)
return {'name' : test, 'prefix' : prefix_build}
#---
# Public
#---
def bootloader_unitest_config(unitest):
""" bootloader unitests abstraction entry
"""
unitpath = []
prefix = f"{unitest.prefix['src']}/bootloader"
for test in os.listdir(f"{prefix}/unitests/"):
unitpath.append(_bootloader_unitest_new(unitest, prefix, test))
return unitpath

View File

@ -0,0 +1,112 @@
"""
core.unitests.cmake - CMake abstraction for unitests
"""
import os
import subprocess
import re
from core.logger import log
__all__ = [
'cmake_unitest_generate_template',
'cmake_unitest_configure',
'cmake_unitest_compile',
]
#---
# Internals
#---
_CMAKE_TEMPLATE = """
cmake_minimum_required(VERSION 3.15)
#---
# project-specific information
#---
project({VXDEV_PROJ_NAME} VERSION 0.1.0 LANGUAGES C ASM)
include_directories(
{VXDEV_BUILD_INCLUDES}
)
add_compile_options(
-Wall
-Wextra
-std=c2x
-g3
--coverage
-fsanitize=address
)
add_link_options(
--coverage
-lasan
-lcriterion
)
#---
# source files listing
#---
set(
VXDEV_PROJ_SOURCES
{VXDEV_SOURCE_FILES}
)
#---
# commit projet
#---
add_executable({VXDEV_PROJ_NAME} ${VXDEV_PROJ_SOURCES})
target_link_libraries({VXDEV_PROJ_NAME})
""".strip()
#---
# Pulbic
#---
def cmake_unitest_generate_template(proj, prefix):
""" Generate a common CMake file
@args
> proj (dict) - project information
> prefix (str) - build prefix
"""
if os.path.exists(f"{prefix}/CMakeLists.txt"):
return
cmakefile = _CMAKE_TEMPLATE
cmakefile = re.sub('{VXDEV_PROJ_NAME}', proj['name'], cmakefile)
cmakefile = re.sub('{VXDEV_SOURCE_FILES}', proj['src'], cmakefile)
cmakefile = re.sub('{VXDEV_BUILD_INCLUDES}', proj['include'], cmakefile)
if not os.path.exists(prefix):
os.makedirs(prefix)
with open(f"{prefix}/CMakeLists.txt", 'x', encoding='ascii') as cmk:
cmk.write(cmakefile)
def cmake_unitest_configure(name, prefix):
""" Abstract cmake configuration
@args
> name (str) - project name
> prefix (str) - build prefix
"""
shell_cmd = f"cmake -B {prefix} -S {prefix}"
if subprocess.run(shell_cmd.split(), check=False).returncode != 0:
log.emergency(f"{name}: unable to configure the projet, abord")
def cmake_unitest_compile(name, prefix, verbose):
""" Abstract cmake configuration
@args
> name (str) - project name
> prefix (str) - build prefix
> verbose (bool) - build verbose
@return
> the generated binary pathname
"""
shell_cmd = f"cmake --build {prefix}"
if verbose:
shell_cmd += ' --verbose'
if subprocess.run(shell_cmd.split(), check=False).returncode != 0:
log.emergency(f"{name}: unable to configure the projet, abord")
return f"{prefix}/{name}"

View File

@ -40,7 +40,7 @@ translation_entry:
! We don't need to setup the stack because we are loaded from CasioABS
! (Casio OS) as a simple program (addin) with a given stack, which we will
! not use even if we use "special" registers such as r8, r9, ... as we will
! be careful to never return from here.
! be careful to never return from here.
!
! @note
! - r0 is reused
@ -91,7 +91,7 @@ translation_entry:
! The SH7305 has a special register for that called Cache Control Register
! (CCR), and it seems tobe the same as SH7724 (except that no official POC
! or information can invalidate the instruction Cache (IC) without causing
! the machine to crash):
! the machine to crash):
!
! - Indicate that P1 area use the "Write-back" method
! - Indicate that P0/P3 areas use the "Write-through" method

View File

@ -1,4 +1,5 @@
#include <stdlib.h>
#include <string.h>
#include "bootloader/console.h"
@ -13,5 +14,6 @@ int console_close(struct console *console)
return -1;
if (console->output.buffer.data != NULL)
free(console->output.buffer.data);
memset(console, 0x00, sizeof(struct console));
return 0;
}

View File

@ -17,6 +17,8 @@ int console_open(struct console *console)
return -1;
if (dfont_get(&font) != 0)
return -2;
if (font == NULL)
return -3;
memset(console, 0x00, sizeof(struct console));
dinfo(
@ -41,7 +43,7 @@ int console_open(struct console *console)
);
if (console->output.buffer.data == NULL) {
console_close(console);
return -2;
return -4;
}
console->_private.color.bg = C_BLACK;

View File

@ -0,0 +1,2 @@
src/console/open.c
src/console/close.c

View File

@ -0,0 +1,65 @@
#include <criterion/criterion.h>
#include "bootloader/console.h"
#include "bootloader/display.h"
//---
// Internals
//---
static bool enable_font = false;
//---
// Provided primitives
//---
/* dinfo() : get display information */
void dinfo(size_t *width, size_t *height)
{
if (width != NULL)
*width = 396;
if (height != NULL)
*height = 224;
}
/* dfont_get() : get font information */
int dfont_get(struct font **font)
{
extern struct font font8x9;
if (font == NULL)
return -1;
*font = NULL;
if (enable_font == true)
*font = &font8x9;
return 0;
}
#define _creq(callable, val, msg) \
do { \
__auto_type _a = callable; \
cr_assert_eq(_a, val, "(%d != %d) "msg, _a, val); \
} while (0)
//---
// Public
//---
/* console:open_close - check open and close primitives
* @todo
* - malloc fails
* - console content */
Test(console, open_close)
{
struct console console;
enable_font = false;
_creq(console_open(NULL), -1, "open console with no console");
_creq(console_open(&console), -3, "open console with no font");
enable_font = true;
_creq(console_open(&console), 0, "open console");
_creq(console_close(NULL), -1, "close with no console");
_creq(console_close(&console), 0, "close console");
}

View File

@ -0,0 +1,61 @@
#include "bootloader/display.h"
/* font8x9 - Vhex asset
This object has been converted by using the vxSDK converter */
struct font const font8x9 = {
.data = (uint32_t[]){
0x00000000, 0x00000000, 0x00000000, 0x00181818, 0x18181800, 0x18180000,
0x00666666, 0x44000000, 0x00000000, 0x006c6cfe, 0x6c6c6cfe, 0x6c6c0000,
0x00187edb, 0xd87e1bdb, 0x7e180000, 0x00006066, 0x0c183066, 0x06000000,
0x0078cccc, 0x6870dbce, 0xce7b0000, 0x00383818, 0x30000000, 0x00000000,
0x000c1830, 0x30303030, 0x180c0000, 0x0030180c, 0x0c0c0c0c, 0x18300000,
0x000018db, 0x7e3c7edb, 0x18000000, 0x00001818, 0x18ff1818, 0x18000000,
0x00000000, 0x00000000, 0x38381830, 0x00000000, 0x00fe0000, 0x00000000,
0x00000000, 0x00000000, 0x18180000, 0x000c0c18, 0x18383030, 0x60600000,
0x007cc6c6, 0xc6c6c6c6, 0xc67c0000, 0x00183878, 0x58181818, 0x187e0000,
0x003c6606, 0x060c1830, 0x607e0000, 0x007cc606, 0x063c0606, 0xc67c0000,
0x000c1c3c, 0x6cccccfe, 0x0c0c0000, 0x00fcc0c0, 0xfc060606, 0xc67c0000,
0x007cc6c0, 0xfcc6c6c6, 0xc67c0000, 0x00fec606, 0x0c0c1818, 0x18180000,
0x007cc6c6, 0xc67cc6c6, 0xc67c0000, 0x007cc6c6, 0xc6c67e06, 0x067c0000,
0x00000018, 0x18000018, 0x18000000, 0x00000018, 0x18000038, 0x18180000,
0x0000040c, 0x1830180c, 0x04000000, 0x00000000, 0xfe00fe00, 0x00000000,
0x00006030, 0x180c1830, 0x60000000, 0x003c6606, 0x0c181800, 0x18180000,
0x007cc603, 0x7bdbdbdb, 0xde7c0000, 0x00103838, 0x6c6c6cfe, 0xc6c60000,
0x00fcc6c6, 0xc6fcc6c6, 0xc6fc0000, 0x003c66c0, 0xc0c0c0c0, 0x663c0000,
0x00f8ccc6, 0xc6c6c6c6, 0xccf80000, 0x00fec0c0, 0xc0f8c0c0, 0xc0fe0000,
0x00fec0c0, 0xc0f8c0c0, 0xc0c00000, 0x003c66c0, 0xc0cec6c6, 0x663e0000,
0x00c6c6c6, 0xc6fec6c6, 0xc6c60000, 0x007e1818, 0x18181818, 0x187e0000,
0x001e0606, 0x06060606, 0xc67c0000, 0x00c6ccd8, 0xf0e0f0d8, 0xccc60000,
0x00c0c0c0, 0xc0c0c0c0, 0xc0fe0000, 0x00c3c3e7, 0xffdbc3c3, 0xc3c30000,
0x00c6c6e6, 0xf6decec6, 0xc6c60000, 0x003c66c3, 0xc3c3c3c3, 0x663c0000,
0x00f8ccc6, 0xc6ccf8c0, 0xc0c00000, 0x003c66c3, 0xc3c3c3db, 0x6e370000,
0x00fcc6c6, 0xc6c6fccc, 0xc6c60000, 0x007cc6c0, 0xc07c0606, 0xc67c0000,
0x00ff1818, 0x18181818, 0x18180000, 0x00c6c6c6, 0xc6c6c6c6, 0xc67c0000,
0x00c3c3c3, 0x6666663c, 0x3c180000, 0x00c3c3c3, 0xdbdb7e7e, 0x66660000,
0x00c3c366, 0x3c183c66, 0xc3c30000, 0x00c3c366, 0x663c1818, 0x18180000,
0x007e0606, 0x0c183060, 0x607e0000, 0x003c3030, 0x30303030, 0x303c0000,
0x00606030, 0x30381818, 0x0c0c0000, 0x003c0c0c, 0x0c0c0c0c, 0x0c3c0000,
0x00386cc6, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00fe0000,
0x00703018, 0x08000000, 0x00000000, 0x0000003c, 0x66067ec6, 0xce760000,
0x00c0c0dc, 0xe6c6c6c6, 0xe6dc0000, 0x0000003c, 0x66c0c0c0, 0x663c0000,
0x0003033b, 0x67c3c3c3, 0x673b0000, 0x0000003c, 0x66c3ffc0, 0x663c0000,
0x001e3330, 0x307c3030, 0x30300000, 0x00000076, 0xcec6c6c6, 0xce76067c,
0x00c0c0dc, 0xe6c6c6c6, 0xc6c60000, 0x00180038, 0x18181818, 0x183c0000,
0x0006000e, 0x06060606, 0x06663c00, 0x00c0c0c6, 0xccd8f0d8, 0xccc60000,
0x00381818, 0x18181818, 0x183c0000, 0x000000f6, 0xdbdbdbdb, 0xdbdb0000,
0x000000dc, 0xe6c6c6c6, 0xc6c60000, 0x0000003c, 0x66c3c3c3, 0x663c0000,
0x000000dc, 0xe6c6c6c6, 0xe6dcc0c0, 0x00000076, 0xcec6c6c6, 0xce760606,
0x000000de, 0xf3e0c0c0, 0xc0c00000, 0x0000007c, 0xc6c07c06, 0xc67c0000,
0x003030fc, 0x30303030, 0x331e0000, 0x000000c6, 0xc6c6c6c6, 0xce760000,
0x000000c3, 0xc366663c, 0x3c180000, 0x000000c3, 0xc3dbdb7e, 0x66660000,
0x000000c6, 0xc66c386c, 0xc6c60000, 0x000000c6, 0xc6c66c6c, 0x38183060,
0x0000007e, 0x060c1830, 0x607e0000, 0x000c1818, 0x18301818, 0x180c0000,
0x00181818, 0x18181818, 0x18180000, 0x00301818, 0x180c1818, 0x18300000,
0x00000000, 0x76dc0000, 0x00000000, 0x007e4242, 0x42424242, 0x427e0000,
},
.count = 96,
.height = 12,
.width = 8,
.line_height = 9,
.char_block_size = 96,
};