vxGOS - v0.7.0-3 : refacto bios and board-specific sources architecture
*add* > [vxdev] | [kernel] add sources handling > [bootloader] | [ulib] add small as possible libc routines | [ulib] add calloc, memset, memcpy, free, malloc, vsnprintf *update* > [.nvimrc] | proper handle compilation flags declaration > [scripts] | [checkers] add pylint checker (WIP) | [vxdev] | [cli] diable installation an uninstallation steps | [core] prepare kernel build support | [core] centralize KASLR generation | [bootloader] proper support libs link | [bootloader] proper support new board-specific architecture | [cmake] proper support libs | [cmake] disable install and uninstall steps | [kaslr] automatically invoke board-specific KASLR generating routine > [bootloader] | [fxcg50] fragmentation BIOS primitives | [console] first implementation of the writing primitive | [console] prepare reading routine | [display] add some drawing primitive (dinfo, dline, dpixel) > [vxsdk] | [toml] remove libc request *fix* > [bootloader] | [fxcg50] proper send argument high-level routine
This commit is contained in:
parent
74571c7882
commit
ac38d420f7
39
.nvimrc
39
.nvimrc
|
@ -8,18 +8,45 @@ autocmd BufWinLeave * call clearmatches()
|
|||
|
||||
" indicate the compiler to use
|
||||
let g:ale_asm_gcc_executable = 'sh-elf-vhex-gcc'
|
||||
let g:ale_c_gcc_executable = 'sh-elf-vhex-gcc'
|
||||
let g:ale_c_cc_executable = 'sh-elf-vhex-gcc'
|
||||
let g:ale_c_gcc_executable = 'sh-elf-vhex-gcc'
|
||||
let g:ale_c_cc_executable = 'sh-elf-vhex-gcc'
|
||||
let g:ale_cpp_gcc_executable = 'sh-elf-vhex-gcc'
|
||||
|
||||
" Find GiteaPC include directory information
|
||||
let s:_hdrflags = [
|
||||
\ '-I./vxgos/bootloader/include',
|
||||
\ '-I./vxgos/bootloader/boards/fxcg50/include/',
|
||||
\ ]
|
||||
let s:_cflags = [
|
||||
\ '-DFXCG50',
|
||||
\ '-std=c11',
|
||||
\ '-Wall',
|
||||
\ '-Wextra',
|
||||
\ ]
|
||||
let s:_asmflags = [
|
||||
\ '-DFXCG50',
|
||||
\ '-x assembler-with-cpp',
|
||||
\ '-Wall',
|
||||
\ '-Wextra',
|
||||
\ '-m4-nofpu',
|
||||
\ '-mb',
|
||||
\ '-Wa,--dsp',
|
||||
\ ]
|
||||
|
||||
" convert table into string
|
||||
let s:_hdrflags = join(s:_hdrflags)
|
||||
let s:_asmflags = join(s:_asmflags)
|
||||
let s:_cflags = join(s:_cflags)
|
||||
|
||||
" Patch option
|
||||
" @note
|
||||
" - we setup cpp because header file is considered ad C++ file
|
||||
" - we force sh-elf-vhex for assembly file only
|
||||
let g:ale_asm_gcc_options = '-x assembler-with-cpp -Wall -m4-nofpu -mb -Wa,--dsp -I./vxgos/bootloader/boards/fxcg50/'
|
||||
let g:ale_c_gcc_options = '-std=c11 -Wall -I./vxgos/bootloader/include/'
|
||||
let g:ale_c_cc_options = '-std=c11 -Wall -I./vxgos/bootloader/include/'
|
||||
let g:ale_cpp_gcc_options = '-std=c11 -Wall -I./vxgos/bootloader/include/'
|
||||
let g:ale_asm_gcc_options = s:_asmflags.' '.s:_hdrflags
|
||||
let g:ale_c_gcc_options = s:_cflags.' '.s:_hdrflags
|
||||
let g:ale_c_cc_options = s:_cflags.' '.s:_hdrflags
|
||||
let g:ale_cpp_cc_options = s:_cflags.' '.s:_hdrflags
|
||||
let g:ale_cpp_gcc_options = s:_cflags.' '.s:_hdrflags
|
||||
|
||||
" Enable completion
|
||||
let g:ale_completion_enabled = 1
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
"""
|
||||
pylint - checker for vxnorm
|
||||
|
||||
This file does not expose an explicite VxChecker object declaration to avoid
|
||||
dependencies handling, you just need to provide:
|
||||
======================= ===============================================
|
||||
parse_file() Parse the source file
|
||||
======================= ===============================================
|
||||
"""
|
||||
import subprocess
|
||||
|
||||
#---
|
||||
# Public
|
||||
#---
|
||||
|
||||
def parse_file(checker, _, pathinfo):
|
||||
""" parse the mapped file
|
||||
|
||||
The file is mapped using mmap() and seeked through offset 0 to avoid too
|
||||
many I/O operations with classical file primitive.
|
||||
|
||||
@args
|
||||
> checker (VxChecker) - current checker instance for this file
|
||||
> mfile (mmap) - mmap instance of the file, seeked at 0
|
||||
> pathname (str) - file pathname
|
||||
|
||||
@return
|
||||
> Nothing
|
||||
"""
|
||||
status = subprocess.run(
|
||||
['pylint', pathinfo['filepath']], capture_output=True, check=False
|
||||
)
|
||||
if status.returncode == 0:
|
||||
return
|
||||
|
||||
for line in status.stdout.decode('utf8').split('\n'):
|
||||
if not line:
|
||||
continue
|
||||
if line[0] == '*':
|
||||
continue
|
||||
if line[0] == '-':
|
||||
break
|
||||
if not (line := line.split(' ', 2)):
|
||||
continue
|
||||
checker.notify(
|
||||
line[0].split(':', 1)[1][:-1],
|
||||
f"[{line[1][:-1]}] {line[2]}",
|
||||
'pylint'
|
||||
)
|
|
@ -4,7 +4,7 @@ Vhex kernel install script
|
|||
import os
|
||||
import sys
|
||||
|
||||
from core.cmake import cmake_install
|
||||
#from core.cmake import cmake_install
|
||||
|
||||
__all__ = [
|
||||
'install_entry'
|
||||
|
@ -47,4 +47,5 @@ def install_entry(argv):
|
|||
file=sys.stderr
|
||||
)
|
||||
sys.exit(84)
|
||||
return cmake_install(os.environ['VXSDK_PREFIX_BUILD'], enable_verbose)
|
||||
#return cmake_install(os.environ['VXSDK_PREFIX_BUILD'], enable_verbose)
|
||||
return enable_verbose
|
||||
|
|
|
@ -4,7 +4,7 @@ Vhex kernel uninstall script
|
|||
import os
|
||||
import sys
|
||||
|
||||
from core.cmake import cmake_uninstall
|
||||
#from core.cmake import cmake_uninstall
|
||||
|
||||
__all__ = [
|
||||
'uninstall_entry'
|
||||
|
@ -47,4 +47,5 @@ def uninstall_entry(argv):
|
|||
file=sys.stderr
|
||||
)
|
||||
sys.exit(84)
|
||||
return cmake_uninstall(os.environ['VXSDK_PREFIX_BUILD'], enable_verbose)
|
||||
#return cmake_uninstall(os.environ['VXSDK_PREFIX_BUILD'], enable_verbose)
|
||||
return enable_verbose
|
||||
|
|
|
@ -5,11 +5,14 @@ import os
|
|||
import sys
|
||||
|
||||
from core.logger import log
|
||||
from core.build.bootloader import bootloader_configure, bootloader_build
|
||||
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 version import (
|
||||
# VXGOS_OS_VERSION,
|
||||
# VXGOS_KERNEL_VERSION,
|
||||
VXGOS_KERNEL_VERSION,
|
||||
VXGOS_BOOTLOADER_VERSION,
|
||||
)
|
||||
|
||||
|
@ -63,7 +66,12 @@ class VxOSBuild():
|
|||
self._prefix = {
|
||||
'build' : os.environ['VXSDK_PREFIX_BUILD'],
|
||||
'bootloader' : f"{self._prefix_base}/bootloader",
|
||||
'kernel' : f"{self._prefix_base}/kernel",
|
||||
#'kernel' : f"{self._prefix_base}/kernel",
|
||||
}
|
||||
self._binlist = {
|
||||
'bootloader' : '',
|
||||
#'kernel' : '',
|
||||
#'os' : ''
|
||||
}
|
||||
|
||||
#---
|
||||
|
@ -96,13 +104,37 @@ class VxOSBuild():
|
|||
|
||||
def configure(self):
|
||||
""" compile OS/kernel, bootloader and perform post-build scripts """
|
||||
bootloader_configure(self, VXGOS_BOOTLOADER_VERSION)
|
||||
self._binlist = {
|
||||
'bootloader': bootloader_configure(self, VXGOS_BOOTLOADER_VERSION),
|
||||
#'kernel' : kernel_configure(self, VXGOS_KERNEL_VERSION),
|
||||
#'os' : '',
|
||||
}
|
||||
|
||||
def build(self):
|
||||
""" compile OS/kernel, bootloader and perform post-build scripts """
|
||||
bootloader_path = bootloader_build(self)
|
||||
""" compile OS/kernel, bootloader and perform post-build scripts
|
||||
|
||||
TODO
|
||||
"""
|
||||
binpathlist = {}
|
||||
log.user("[+] compiling each OS part...")
|
||||
for partname in self._binlist:
|
||||
log.user(f"- {partname}...")
|
||||
binpathlist[partname] = cmake_build(
|
||||
partname,
|
||||
f"{self.prefix['build']}/{partname}/",
|
||||
self.verbose
|
||||
)
|
||||
|
||||
blobpathlist = {}
|
||||
log.user("[+] generate KASLR information...")
|
||||
for bininfo in binpathlist.items():
|
||||
log.user(f"- {bininfo[0]}...")
|
||||
blobpathlist[bininfo[0]] = kaslr_generate(self, bininfo[1])
|
||||
|
||||
return self.postscript['image'](
|
||||
self.prefix['build'],
|
||||
bootloader_path,
|
||||
blobpathlist['bootloader'],
|
||||
'',
|
||||
#blobpathlist['kernel'],
|
||||
#blobpathlist['os']
|
||||
)
|
||||
|
|
|
@ -2,20 +2,16 @@
|
|||
core.build.bootloader - bootloader build abstraction
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import glob
|
||||
|
||||
from core.logger import log
|
||||
from core.kaslr import kaslr_generate
|
||||
from core.cmake import (
|
||||
cmake_generate_template,
|
||||
cmake_configure,
|
||||
cmake_build,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
'bootloader_configure',
|
||||
'bootloader_build'
|
||||
]
|
||||
|
||||
#---
|
||||
|
@ -40,7 +36,7 @@ def bootloader_configure(build, version):
|
|||
common_src = glob.glob(common_src, recursive=True)
|
||||
log.debug(f"> common src = {common_src}")
|
||||
|
||||
board_src = f"{prefix}/boards/{build.target}/**/*.[csS]"
|
||||
board_src = f"{prefix}/boards/{build.target}/src/**/*.[csS]"
|
||||
board_src = glob.glob(board_src, recursive=True)
|
||||
log.debug(f"> board src = {board_src}")
|
||||
|
||||
|
@ -56,25 +52,8 @@ def bootloader_configure(build, version):
|
|||
'ldflags' : '\n '.join(os.environ['VXSDK_BUILD_LDFLAGS'].split(';')),
|
||||
'cflags' : '\n '.join(os.environ['VXSDK_BUILD_CFLAGS'].split(';')),
|
||||
'include' : '\n '.join(include_list),
|
||||
'src' : '\n '.join(common_src + board_src)
|
||||
'src' : '\n '.join(common_src + board_src),
|
||||
'libs' : '\n '.join(os.environ['VXSDK_BUILD_LIBS'].split(';'))
|
||||
}
|
||||
cmake_generate_template(prefix, proj)
|
||||
cmake_configure(prefix)
|
||||
|
||||
def bootloader_build(build):
|
||||
""" build the bootloader
|
||||
|
||||
@return
|
||||
> final bootloader blob (complet) path
|
||||
"""
|
||||
log.debug('bootloader compilation...')
|
||||
binpath = f"{build.prefix['build']}/bootloader/bootloader"
|
||||
|
||||
log.debug('> cmake build...')
|
||||
cmake_build(f"{build.prefix['build']}/bootloader/", build.verbose)
|
||||
|
||||
log.debug('> generate KSALR table information...')
|
||||
symtab = kaslr_generate(binpath)
|
||||
|
||||
log.debug('> generate architecture-specific blobs...')
|
||||
return build.postscript['kalsr'](binpath, symtab)
|
||||
cmake_generate_template(proj, prefix)
|
||||
cmake_configure(proj['name'], prefix)
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
"""
|
||||
vxdev.core.build.kernel - kernel build abstraction
|
||||
"""
|
||||
import os
|
||||
import glob
|
||||
import toml
|
||||
|
||||
from core.logger import log
|
||||
from core.cmake import (
|
||||
cmake_generate_template,
|
||||
cmake_configure,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
'kernel_configure',
|
||||
]
|
||||
|
||||
#---
|
||||
# Internals
|
||||
#---
|
||||
|
||||
def _fetch_board_config(build, board_cfg_path):
|
||||
""" try to find and load the board configuratio file
|
||||
|
||||
This routine will check the TOML boards configuration validity and return
|
||||
only the 'config' section which contain most of the information needed to
|
||||
fetch all kernel source files
|
||||
|
||||
@return
|
||||
> a dictionary with all configuration information
|
||||
> give up if an error is detected
|
||||
"""
|
||||
if not os.path.exists(board_cfg_path):
|
||||
log.emergency("unable to find the kernel '{build.target}' board file")
|
||||
log.debug(f"> board config = {board_cfg_path}")
|
||||
board_cfg = toml.load(board_cfg_path)
|
||||
if 'meta' not in board_cfg:
|
||||
log.emergency(f"{build.target}: missing board 'meta' information")
|
||||
if 'config' not in board_cfg:
|
||||
log.emergency(f"{build.target}: missing board 'config' information")
|
||||
if 'modules' not in board_cfg['config']:
|
||||
log.emergency(f"{build.target}: missing board 'modules' information")
|
||||
if 'drivers' not in board_cfg['config']:
|
||||
log.emergency(f"{build.target}: missing board 'drivers' information")
|
||||
return board_cfg['config']
|
||||
|
||||
def _fetch_board_sources(build, prefix):
|
||||
""" fetch board specific sources files
|
||||
|
||||
Scan the target board source directory (<prefix>/src/) and fetch all C
|
||||
and assembly file.
|
||||
|
||||
@return
|
||||
> a list of all source file found
|
||||
"""
|
||||
prefix = f"{prefix}/boards/{build.target}/src"
|
||||
if not os.path.exists(prefix):
|
||||
return glob.glob(f"{prefix}/**/*.[csS]", recursive=True)
|
||||
return []
|
||||
|
||||
def _fetch_common_sources(_, prefix):
|
||||
""" fetch common source file
|
||||
"""
|
||||
return glob.glob(f"{prefix}/src/*.[csS]", recursive=False)
|
||||
|
||||
def _fetch_drivers_sources(build, prefix, drvlist):
|
||||
""" fetch selected drivers
|
||||
"""
|
||||
sources = []
|
||||
for drv in drvlist:
|
||||
if not os.path.exists(f"{prefix}/src/drivers/{drv}"):
|
||||
log.emergency(f"{build.target}: unable to find driver '{drv}'")
|
||||
sources += glob.glob(
|
||||
f"{prefix}/src/drivers/{drv}/**/*.[csS]",
|
||||
recursive=True
|
||||
)
|
||||
return sources
|
||||
|
||||
def _fetch_modules_sources(build, prefix, modlist):
|
||||
""" fetch selected kernel module
|
||||
"""
|
||||
sources = []
|
||||
for mod in modlist:
|
||||
if not os.path.exists(f"{prefix}/src/modules/{mod}"):
|
||||
log.emergency(f"{build.target}: unable to find module '{mod}'")
|
||||
sources += glob.glob(
|
||||
f"{prefix}/src/modules/{mod}/**/*.[csS]",
|
||||
recursive=True
|
||||
)
|
||||
return sources
|
||||
|
||||
#---
|
||||
# Public
|
||||
#---
|
||||
|
||||
def kernel_configure(build, version):
|
||||
""" configure the kernel
|
||||
|
||||
TODO
|
||||
"""
|
||||
prefix = build.prefix['kernel']
|
||||
log.debug('fetching kernel files...')
|
||||
log.debug(f"> prefix = {prefix}")
|
||||
|
||||
board_cfg = _fetch_board_config(
|
||||
build,
|
||||
f"{prefix}/boards/{build.target}/board.toml"
|
||||
)
|
||||
sources = _fetch_board_sources(build, prefix)
|
||||
sources += _fetch_common_sources(build, prefix)
|
||||
sources += _fetch_drivers_sources(build, prefix, board_cfg['drivers'])
|
||||
sources += _fetch_modules_sources(build, prefix, board_cfg['modules'])
|
||||
log.debug("> fetched sources = {sources}")
|
||||
|
||||
prefix = f"{build.prefix['build']}/kernel/"
|
||||
include_list = [
|
||||
f"{build.prefix['kernel']}/include/",
|
||||
f"{build.prefix['kernel']}/boards/{build.target}/include/"
|
||||
]
|
||||
proj = {
|
||||
'name' : 'kernel',
|
||||
'version' : version,
|
||||
'linker' : f"{build.prefix['kernel']}/kernel.ld",
|
||||
'ldflags' : '\n '.join(os.environ['VXSDK_BUILD_LDFLAGS'].split(';')),
|
||||
'cflags' : '\n '.join(os.environ['VXSDK_BUILD_CFLAGS'].split(';')),
|
||||
'include' : '\n '.join(include_list),
|
||||
'src' : '\n '.join(sources),
|
||||
'libs' : '\n '.join(os.environ['VXSDK_BUILD_LIBS'].split(';'))
|
||||
}
|
||||
cmake_generate_template(proj, prefix)
|
||||
cmake_configure(proj['name'], prefix)
|
|
@ -2,16 +2,15 @@
|
|||
CMake abstraction
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import re
|
||||
|
||||
from core.logger import log
|
||||
|
||||
__all__ = [
|
||||
'cmake_generate_template',
|
||||
'cmake_configure',
|
||||
'cmake_build',
|
||||
'cmake_install',
|
||||
'cmake_uninstall',
|
||||
]
|
||||
|
||||
#---
|
||||
|
@ -48,15 +47,21 @@ set(VXDEV_PROJ_SOURCES
|
|||
#---
|
||||
|
||||
add_executable({VXDEV_PROJ_NAME} ${VXDEV_PROJ_SOURCES})
|
||||
target_link_libraries({VXDEV_PROJ_NAME} {VXDEV_BUILD_LIBS})
|
||||
""".strip()
|
||||
|
||||
#---
|
||||
# Pulbic
|
||||
#---
|
||||
|
||||
def cmake_generate_template(prefix_build, proj):
|
||||
""" Generate a common CMake file """
|
||||
if os.path.exists(f"{prefix_build}/CMakeLists.txt"):
|
||||
def cmake_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)
|
||||
|
@ -66,63 +71,73 @@ def cmake_generate_template(prefix_build, proj):
|
|||
cmakefile = re.sub('{VXDEV_BUILD_LINKER}', proj['linker'], 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_build):
|
||||
os.makedirs(prefix_build)
|
||||
with open(f"{prefix_build}/CMakeLists.txt", 'x', encoding='ascii') as cmk:
|
||||
cmakefile = re.sub('{VXDEV_BUILD_LIBS}', proj['libs'], 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_configure(prefix_build):
|
||||
""" Abstract cmake configuration """
|
||||
def cmake_configure(name, prefix):
|
||||
""" Abstract cmake configuration
|
||||
|
||||
@args
|
||||
> name (str) - project name
|
||||
> prefix (str) - build prefix
|
||||
"""
|
||||
toolchain_flag = ''
|
||||
if toolchain_path := os.environ.get('VXSDK_HOOK_CMAKE_TOOLCHAIN'):
|
||||
toolchain_flag = f"-DCMAKE_TOOLCHAIN_FILE={toolchain_path}"
|
||||
shell_cmd = f"cmake {toolchain_flag} -B {prefix_build} -S {prefix_build}"
|
||||
return subprocess.run(shell_cmd.split(), check=False).returncode
|
||||
shell_cmd = f"cmake {toolchain_flag} -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_configure(prefix_build, prefix_src):
|
||||
# """ Abstract cmake configuration """
|
||||
# toolchain_flag = ''
|
||||
# if toolchain_path := os.environ.get('VXSDK_HOOK_CMAKE_TOOLCHAIN'):
|
||||
# toolchain_flag = f"-DCMAKE_TOOLCHAIN_FILE={toolchain_path}"
|
||||
# shell_cmd = f"cmake {toolchain_flag} -B {prefix_build} -S {prefix_src}"
|
||||
# return subprocess.run(shell_cmd.split(), check=False).returncode
|
||||
def cmake_build(name, prefix, verbose):
|
||||
""" Abstract cmake configuration
|
||||
|
||||
def cmake_build(prefix_build, verbose):
|
||||
""" Abstract cmake configuration """
|
||||
shell_cmd = f"cmake --build {prefix_build}"
|
||||
if verbose:
|
||||
shell_cmd += ' --verbose'
|
||||
return subprocess.run(shell_cmd.split(), check=False).returncode
|
||||
@args
|
||||
> name (str) - project name
|
||||
> prefix (str) - build prefix
|
||||
> verbose (bool) - build verbose
|
||||
|
||||
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
|
||||
@return
|
||||
> the generated binary pathname
|
||||
"""
|
||||
manifile = f"{prefix_build}/install_manifest.txt"
|
||||
if not os.path.exists(manifile):
|
||||
print('project not installed')
|
||||
return -1
|
||||
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}"
|
||||
|
||||
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
|
||||
#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
|
||||
|
|
|
@ -13,8 +13,11 @@ __all__ = [
|
|||
# Public
|
||||
#---
|
||||
|
||||
def kaslr_generate(binpath):
|
||||
""" generate KASLR symbols table """
|
||||
def kaslr_generate(build, binpath):
|
||||
""" generate KASLR symbols table
|
||||
|
||||
TODO
|
||||
"""
|
||||
ret = subprocess.run(
|
||||
f"readelf -r {binpath}".split(),
|
||||
capture_output=True,
|
||||
|
@ -30,4 +33,4 @@ def kaslr_generate(binpath):
|
|||
continue
|
||||
log.debug(f"[{i}] {sinfo}")
|
||||
symbol_table.append(sinfo)
|
||||
return symbol_table
|
||||
return build.postscript['kalsr'](binpath, symbol_table)
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
#include "fxcg50/asm_utils.h"
|
||||
|
||||
.text
|
||||
|
||||
!---
|
||||
! Public
|
||||
!---
|
||||
|
||||
/* _bios_dclear() (Bdisp_Fill_VRAM) : clear VRAM */
|
||||
function(_bios_dclear):
|
||||
mov #3, r5
|
||||
syscall(0x0275)
|
|
@ -0,0 +1,14 @@
|
|||
#include "bootloader/bios.h"
|
||||
|
||||
//---
|
||||
// Public
|
||||
//---
|
||||
|
||||
/* _bios_dinfo() : get display information */
|
||||
void _bios_dinfo(size_t *width, size_t *height)
|
||||
{
|
||||
if (width != NULL)
|
||||
*width = 396;
|
||||
if (height != NULL)
|
||||
*height = 224;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bootloader/bios.h"
|
||||
|
||||
//---
|
||||
// Public
|
||||
//---
|
||||
|
||||
/* _bios_dpixel() : dpixel wrapper */
|
||||
void _bios_dpixel(int x, int y, int color)
|
||||
{
|
||||
uint16_t *vram;
|
||||
|
||||
__asm__ volatile (
|
||||
"mov %1, r0;"
|
||||
"mov %2, r1;"
|
||||
"jsr @r1;"
|
||||
"nop;"
|
||||
"mov r0, %0"
|
||||
: "=r"(vram)
|
||||
: "r"(0x01e6), "r"(0x80020070)
|
||||
: "pr"
|
||||
);
|
||||
vram[(y * 384) + x] = color;
|
||||
}
|
|
@ -1,19 +1,10 @@
|
|||
#include "fxcg50_asm_utils.h"
|
||||
#include "fxcg50/asm_utils.h"
|
||||
|
||||
.text
|
||||
|
||||
!--
|
||||
!---
|
||||
! Public
|
||||
!--
|
||||
|
||||
/* _bios_dclear() (Bdisp_Fill_VRAM) : clear VRAM */
|
||||
function(_bios_dclear):
|
||||
mov #3, r5
|
||||
syscall(0x0275)
|
||||
|
||||
/* _bios_udpate() (Bdisp_PutDisp_DD) : display VRAM to screen using DMA */
|
||||
function(_bios_dupdate):
|
||||
syscall(0x025f)
|
||||
!---
|
||||
|
||||
/* _bios_dtext() (Bdisp_PrintMiniMini): display string */
|
||||
function(_bios_dtext):
|
|
@ -0,0 +1,11 @@
|
|||
#include "fxcg50/asm_utils.h"
|
||||
|
||||
.text
|
||||
|
||||
!---
|
||||
! Public
|
||||
!---
|
||||
|
||||
/* _bios_udpate() (Bdisp_PutDisp_DD) : display VRAM to screen using DMA */
|
||||
function(_bios_dupdate):
|
||||
syscall(0x025f)
|
|
@ -0,0 +1,11 @@
|
|||
#include "fxcg50/asm_utils.h"
|
||||
|
||||
.text
|
||||
|
||||
!---
|
||||
! Public
|
||||
!---
|
||||
|
||||
/* _bios_free() (free) : free allocated memory */
|
||||
function(_bios_free):
|
||||
syscall(0x1f42)
|
|
@ -0,0 +1,11 @@
|
|||
#include "fxcg50/asm_utils.h"
|
||||
|
||||
.text
|
||||
|
||||
!---
|
||||
! Public
|
||||
!---
|
||||
|
||||
/* _bios_malloc() (malloc) : allocate memory */
|
||||
function(_bios_malloc):
|
||||
syscall(0x1f44)
|
|
@ -1,4 +1,4 @@
|
|||
#include "fxcg50_asm_utils.h"
|
||||
#include "fxcg50/asm_utils.h"
|
||||
|
||||
.section .bootloader.pre_text, "ax"
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#include "fxcg50_asm_utils.h"
|
||||
#include "fxcg50/asm_utils.h"
|
||||
|
||||
.section .bootloader.text, "ax"
|
||||
|
||||
|
@ -77,9 +77,12 @@ setup_stack:
|
|||
! TODO : stack canary
|
||||
|
||||
bootloader_c_invokation:
|
||||
mov.l p2_addr_base, r2
|
||||
mov ram_reloc_base, r4
|
||||
mov image_size, r5
|
||||
mov.l bootloader_main, r0
|
||||
jsr @r0
|
||||
nop
|
||||
or r2, r4
|
||||
|
||||
! ---
|
||||
! bootloader panic
|
|
@ -1,13 +1,28 @@
|
|||
#ifndef BOOTLOADER_BIOS_H
|
||||
#define BOOTLOADER_BIOS_H 1
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* _bios_dinfo() : get display information */
|
||||
extern void _bios_dinfo(size_t *width, size_t *height);
|
||||
|
||||
/* _bios_dclear() : clear VRAM */
|
||||
extern void _bios_dclear(int color);
|
||||
|
||||
/* _bios_dtext() : draw raw text */
|
||||
extern void _bios_dtext(int x, int y, int color, char *text);
|
||||
|
||||
/* _bios_dpixel() : draw pixel */
|
||||
extern void _bios_dpixel(int x, int y, int color);
|
||||
|
||||
/* _bios_dudpate() : display VRAM to screen */
|
||||
extern void _bios_dupdate(void);
|
||||
|
||||
/* _bios_free() : free allocated memory */
|
||||
extern void _bios_free(void *ptr);
|
||||
|
||||
/* _bios_malloc() : memory allocator */
|
||||
extern void *_bios_malloc(size_t size);
|
||||
|
||||
#endif /* BOOTLOADER_BIOS_H */
|
||||
|
|
|
@ -1,19 +1,82 @@
|
|||
#ifndef BOOTLOADER_CONSOLE_H
|
||||
#define BOOTLOADER_CONSOLE_H 1
|
||||
|
||||
/* struct console : */
|
||||
struct console {
|
||||
int a;
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
//---
|
||||
// macros
|
||||
//---
|
||||
|
||||
/* internal terminal hardcoded information */
|
||||
#define TERM_BUFFER_NB_FRAME (2)
|
||||
|
||||
//---
|
||||
// Types
|
||||
//---
|
||||
|
||||
/* define console structure */
|
||||
struct console
|
||||
{
|
||||
/* windows information */
|
||||
struct {
|
||||
unsigned short ws_col;
|
||||
unsigned short ws_row;
|
||||
unsigned short ws_xpixel;
|
||||
unsigned short ws_ypixel;
|
||||
unsigned short ft_xpixel;
|
||||
unsigned short ft_ypixel;
|
||||
} winsize;
|
||||
|
||||
/* cursor information */
|
||||
struct {
|
||||
unsigned short x;
|
||||
unsigned short y;
|
||||
} cursor;
|
||||
|
||||
/* buffer information */
|
||||
struct {
|
||||
uint8_t *data;
|
||||
off_t cursor;
|
||||
size_t size;
|
||||
} buffer;
|
||||
|
||||
/* private information */
|
||||
struct {
|
||||
uint32_t watermark;
|
||||
struct {
|
||||
int fg;
|
||||
int bg;
|
||||
} color;
|
||||
} _private;
|
||||
};
|
||||
|
||||
//---
|
||||
// Public API
|
||||
//---
|
||||
|
||||
/* console_clear() : clear the console information */
|
||||
extern void console_init(struct console *console);
|
||||
/* console_open() : open console */
|
||||
extern int console_open(struct console *console);
|
||||
|
||||
/* console_write() : printf-like write primitive (support line discipline) */
|
||||
extern void console_write(struct console *console, char *format, ...);
|
||||
extern int console_write(struct console *console, char const *format, ...);
|
||||
|
||||
/* console_vwrite() : printf wrapper for the terminal device with va_list */
|
||||
extern int console_vwrite(struct console *console, const char *f, va_list ap);
|
||||
|
||||
/* console_close() : close console */
|
||||
extern int console_close(struct console *console);
|
||||
|
||||
//---
|
||||
// Low-level API
|
||||
//---
|
||||
|
||||
/* console_buffer_insert() : insert string anywhere in the output buffer */
|
||||
extern int console_buffer_insert(struct console *console, char *b, size_t nb);
|
||||
|
||||
/* console_buffer_write() : display the buffer on screen */
|
||||
extern int console_buffer_display(struct console *console);
|
||||
|
||||
#endif /* BOOTLOADER_CONSOLE_H */
|
||||
|
|
|
@ -1,7 +1,31 @@
|
|||
#ifndef BOOTLOADER_DISPLAY_H
|
||||
#define BOOTLOADER_DISPLAY_H 1
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* color alias */
|
||||
#define C_WHITE 0x0000
|
||||
#define C_BLACK 0xffff
|
||||
|
||||
/* hardcoded font size (TODO: dynamic !) */
|
||||
//#ifdef FXCG50
|
||||
#define FWIDTH 10
|
||||
#define FHEIGHT 11
|
||||
#define DWIDTH 396
|
||||
#define DHEIGHT 224
|
||||
//#endif
|
||||
//#ifdef FX9860G
|
||||
//#define FWIDTH 3
|
||||
//#define FHEIGHT 5
|
||||
//#endif
|
||||
|
||||
//---
|
||||
// Public API
|
||||
//---
|
||||
|
||||
/* dinfo() : get display information */
|
||||
extern void dinfo(size_t *width, size_t *height);
|
||||
|
||||
/* dclear() : clear VRAM with unified color */
|
||||
extern void dclear(int color);
|
||||
|
@ -12,6 +36,12 @@ extern void dtext(int x, int y, int color, char *text);
|
|||
/* dprint() : printf-like dtext() */
|
||||
extern void dprint(int x, int y, int color, char *format, ...);
|
||||
|
||||
/* dline() : display line */
|
||||
extern void dline(int x0, int y0, int x1, int y1, int color);
|
||||
|
||||
/* dpixel() : draw pixel */
|
||||
extern void dpixel(int x, int y, int color);
|
||||
|
||||
/* dupdate() : update VRAM to screen */
|
||||
extern void dupdate(void);
|
||||
|
||||
|
|
|
@ -0,0 +1,186 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "bootloader/console.h"
|
||||
#include "bootloader/display.h"
|
||||
|
||||
//---
|
||||
// Update the internal buffer
|
||||
//---
|
||||
|
||||
/* console_buffer_insert() : insert string anywhere in the output buffer */
|
||||
int console_buffer_insert(struct console *console, char *buffer, size_t nb)
|
||||
{
|
||||
size_t dump;
|
||||
void *start;
|
||||
|
||||
/* check error */
|
||||
if (console == NULL)
|
||||
return -1;
|
||||
|
||||
/* calculate the "real" number of byte to dump into the buffer */
|
||||
dump = nb;
|
||||
start = &buffer[0];
|
||||
if (dump > console->buffer.size) {
|
||||
dump -= console->buffer.size;
|
||||
start = &buffer[nb - dump];
|
||||
}
|
||||
|
||||
/* dump the buffer (be careful with the circular effect) */
|
||||
if (console->buffer.cursor + dump > console->buffer.size)
|
||||
{
|
||||
memcpy(
|
||||
&console->buffer.data[console->buffer.cursor],
|
||||
start,
|
||||
console->buffer.size - console->buffer.cursor
|
||||
);
|
||||
dump -= console->buffer.size - console->buffer.cursor;
|
||||
console->buffer.cursor = 0;
|
||||
}
|
||||
memcpy(&console->buffer.data[console->buffer.cursor], start, dump);
|
||||
console->buffer.cursor += dump;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//---
|
||||
// Display the internal buffer
|
||||
//---
|
||||
|
||||
/* console_vertical_update() - Update vertical cursor */
|
||||
static void console_vertical_update(struct console *console)
|
||||
{
|
||||
if (console->cursor.y + 1 < console->winsize.ws_col) {
|
||||
console->cursor.y = console->cursor.y + 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* console_horizontal_update() - Update horizotal cursor */
|
||||
static int console_horizontal_update(struct console *console)
|
||||
{
|
||||
console->cursor.x = console->cursor.x + 1;
|
||||
if (console->cursor.x >= console->winsize.ws_col)
|
||||
{
|
||||
console_vertical_update(console);
|
||||
console->cursor.x = 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* console_line_discipline() - Check "special" char */
|
||||
static int console_line_discipline(struct console *console, char n)
|
||||
{
|
||||
int offset;
|
||||
|
||||
switch (n)
|
||||
{
|
||||
case '\0':
|
||||
return 1;
|
||||
case '\n':
|
||||
console->cursor.x = 0;
|
||||
console_vertical_update(console);
|
||||
return 1;
|
||||
case '\b':
|
||||
if (console->cursor.x > 0)
|
||||
console->cursor.x = console->cursor.x - 1;
|
||||
return 1;
|
||||
case '\v':
|
||||
console_vertical_update(console);
|
||||
return 1;
|
||||
case '\r':
|
||||
console->cursor.x = 0;
|
||||
return 1;
|
||||
case '\t':
|
||||
/* Check if we need a new line or not. */
|
||||
offset = console->cursor.x - ((console->cursor.x / 5) * 5);
|
||||
offset = 5 - offset;
|
||||
while (--offset >= 0)
|
||||
console_horizontal_update(console);
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* console_buffer_write() : display the buffer on screen */
|
||||
int console_buffer_display(struct console *console)
|
||||
{
|
||||
uint8_t *buffer;
|
||||
char tmp[2];
|
||||
int cursor;
|
||||
int x;
|
||||
int y;
|
||||
int i;
|
||||
|
||||
/* check obvious error */
|
||||
if (console == NULL)
|
||||
return -1;
|
||||
|
||||
/* Due to potential special char, we sould find the "real" starting
|
||||
index for the internal buffer */
|
||||
console->cursor.x = 0;
|
||||
console->cursor.y = 0;
|
||||
i = console->buffer.cursor - 1;
|
||||
if (i < 0)
|
||||
i = console->buffer.size - 1;
|
||||
buffer = &console->buffer.data[0];
|
||||
while (1)
|
||||
{
|
||||
/* decrease the cursor and avoid circular effect */
|
||||
if (--i < 0)
|
||||
i = console->buffer.size - 1;
|
||||
|
||||
/* check loop condition */
|
||||
if (i == (int)console->buffer.cursor)
|
||||
break;
|
||||
if (buffer[i] == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
/* handle the character (only to force update cursors) */
|
||||
if (console_line_discipline(console, buffer[i] & 0x7f) == 0)
|
||||
console_horizontal_update(console);
|
||||
if (console->cursor.y >= console->winsize.ws_row)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Display character per character because we need to check special
|
||||
behaviour (like cariege return, line feed, ...) */
|
||||
tmp[1] = '\0';
|
||||
console->cursor.x = 0;
|
||||
console->cursor.y = 0;
|
||||
while (1)
|
||||
{
|
||||
/* update the index */
|
||||
if (++i >= (int)console->buffer.size)
|
||||
i = 0;
|
||||
if (i == (int)console->buffer.cursor)
|
||||
break;
|
||||
|
||||
/* get the cursor and remove the potential cursor marker */
|
||||
cursor = ((buffer[i] & 0x80) != 0);
|
||||
buffer[i] &= 0x7f;
|
||||
|
||||
/* display part (character + cursor if needed) */
|
||||
x = console->cursor.x * console->winsize.ft_xpixel;
|
||||
y = console->cursor.y * console->winsize.ft_ypixel;
|
||||
if (console_line_discipline(console, buffer[i]) == 0)
|
||||
{
|
||||
tmp[0] = buffer[i];
|
||||
dtext(x, y, console->_private.color.fg, tmp);
|
||||
console_horizontal_update(console);
|
||||
}
|
||||
if (cursor != 0)
|
||||
{
|
||||
dline(
|
||||
x,
|
||||
y + console->winsize.ft_ypixel,
|
||||
x + console->winsize.ft_xpixel - 2,
|
||||
y + console->winsize.ft_ypixel,
|
||||
console->_private.color.fg
|
||||
);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include "bootloader/console.h"
|
||||
|
||||
//---
|
||||
// Public
|
||||
//---
|
||||
|
||||
/* console_close(): Uninitialize the terminal */
|
||||
int console_close(struct console *console)
|
||||
{
|
||||
if (console == NULL)
|
||||
return -1;
|
||||
if (console->buffer.data != NULL)
|
||||
free(console->buffer.data);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "bootloader/console.h"
|
||||
#include "bootloader/display.h"
|
||||
|
||||
//---
|
||||
// Public
|
||||
//---
|
||||
|
||||
/* console_open(): Initialize and open the terminal */
|
||||
int console_open(struct console *console)
|
||||
{
|
||||
if (console == NULL)
|
||||
return -1;
|
||||
|
||||
memset(console, 0x00, sizeof(struct console));
|
||||
console->winsize.ws_xpixel = DWIDTH;
|
||||
console->winsize.ws_ypixel = DHEIGHT;
|
||||
console->winsize.ft_xpixel = FWIDTH + 1;
|
||||
console->winsize.ft_ypixel = FHEIGHT + 1;
|
||||
console->winsize.ws_col = DWIDTH / console->winsize.ft_xpixel;
|
||||
console->winsize.ws_row = DHEIGHT / console->winsize.ft_ypixel;
|
||||
|
||||
console->buffer.size = console->winsize.ws_row;
|
||||
console->buffer.size *= console->winsize.ws_col;
|
||||
console->buffer.size *= TERM_BUFFER_NB_FRAME;
|
||||
console->buffer.size *= sizeof(uint8_t);
|
||||
|
||||
console->buffer.data = calloc(sizeof(char), console->buffer.size);
|
||||
if (console->buffer.data == NULL) {
|
||||
console_close(console);
|
||||
return -2;
|
||||
}
|
||||
|
||||
console->_private.color.bg = C_BLACK;
|
||||
console->_private.color.fg = C_WHITE;
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,235 @@
|
|||
#if 0
|
||||
#include <string.h>
|
||||
|
||||
#include "bootloader/console.h"
|
||||
|
||||
//---
|
||||
// Internals
|
||||
//---
|
||||
|
||||
/* internal structure used to store many information */
|
||||
struct {
|
||||
struct {
|
||||
unsigned short x;
|
||||
unsigned short y;
|
||||
int visible;
|
||||
off_t saved;
|
||||
} cursor;
|
||||
struct {
|
||||
uint8_t alpha: 1;
|
||||
uint8_t shift: 1;
|
||||
uint8_t ctrl: 1;
|
||||
uint8_t exit: 1;
|
||||
uint8_t const: 4;
|
||||
} mode;
|
||||
struct {
|
||||
size_t max;
|
||||
size_t size;
|
||||
off_t cursor;
|
||||
char *data;
|
||||
} buffer;
|
||||
} term_rdinfo;
|
||||
|
||||
//---
|
||||
// Display
|
||||
//---
|
||||
|
||||
/* term_display_all() : display all*/
|
||||
void term_display_all(void)
|
||||
{
|
||||
/* mark special characte that the cursor is here */
|
||||
if (term_rdinfo.cursor.visible == 1)
|
||||
term_rdinfo.buffer.data[term_rdinfo.buffer.cursor] |= 0x80;
|
||||
|
||||
/* restore terminal context */
|
||||
terminal.cursor.x = term_rdinfo.cursor.x;
|
||||
terminal.cursor.y = term_rdinfo.cursor.y;
|
||||
terminal.buffer.cursor = term_rdinfo.cursor.saved;
|
||||
terminal_buffer_insert(
|
||||
term_rdinfo.buffer.data,
|
||||
term_rdinfo.buffer.size
|
||||
);
|
||||
|
||||
/* display management */
|
||||
dclear(terminal.private.color.bg);
|
||||
terminal_buffer_display();
|
||||
dupdate();
|
||||
|
||||
/* remove cursor mark */
|
||||
term_rdinfo.buffer.data[term_rdinfo.buffer.cursor] &= ~0x80;
|
||||
}
|
||||
|
||||
//---
|
||||
// buffer functions
|
||||
//---
|
||||
|
||||
/* term_buffer_remove(): Remove character based on current cursor position */
|
||||
static void term_buffer_remove(void)
|
||||
{
|
||||
/* check if this action is possible */
|
||||
if (term_rdinfo.buffer.cursor == 0)
|
||||
return;
|
||||
/* move data if needed */
|
||||
if (term_rdinfo.buffer.cursor < (int)term_rdinfo.buffer.size - 1) {
|
||||
memcpy(
|
||||
&term_rdinfo.buffer.data[term_rdinfo.buffer.cursor - 1],
|
||||
&term_rdinfo.buffer.data[term_rdinfo.buffer.cursor],
|
||||
term_rdinfo.buffer.size - term_rdinfo.buffer.cursor
|
||||
);
|
||||
}
|
||||
/* force NULL-char and update cursor/size */
|
||||
term_rdinfo.buffer.cursor = term_rdinfo.buffer.cursor - 1;
|
||||
term_rdinfo.buffer.data[--term_rdinfo.buffer.size - 1] = '\0';
|
||||
}
|
||||
|
||||
/* term_buffer_insert() - Insert character based on current cursor position */
|
||||
static int term_buffer_insert(char n)
|
||||
{
|
||||
/* save space for the "\n\0" (EOL) */
|
||||
if (term_rdinfo.buffer.size + 1 >= term_rdinfo.buffer.max)
|
||||
return -1;
|
||||
/* move data if needed */
|
||||
if (term_rdinfo.buffer.cursor < (int)term_rdinfo.buffer.size - 1) {
|
||||
off_t i = term_rdinfo.buffer.size + 1;
|
||||
while (--i >= term_rdinfo.buffer.cursor) {
|
||||
term_rdinfo.buffer.data[i] = term_rdinfo.buffer.data[i - 1];
|
||||
}
|
||||
}
|
||||
/* insert the character and force NULL-char */
|
||||
term_rdinfo.buffer.data[term_rdinfo.buffer.cursor++] = n;
|
||||
term_rdinfo.buffer.data[++term_rdinfo.buffer.size] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---
|
||||
// key handling
|
||||
//---
|
||||
|
||||
// TODO
|
||||
// - F_UP -> history
|
||||
// - F_DOWN -> history
|
||||
static int term_key_handle_special(key_event_t key_event)
|
||||
{
|
||||
switch (key_event.key)
|
||||
{
|
||||
case KEY_SHIFT:
|
||||
term_rdinfo.mode.shift ^= 1;
|
||||
return 1;
|
||||
case KEY_ALPHA:
|
||||
term_rdinfo.mode.alpha ^= 1;
|
||||
return 1;
|
||||
case KEY_OPTN:
|
||||
term_rdinfo.mode.ctrl ^= 1;
|
||||
return 1;
|
||||
case KEY_DOT:
|
||||
term_buffer_insert(' ');
|
||||
return 1;
|
||||
case KEY_DEL:
|
||||
term_buffer_remove();
|
||||
return 1;
|
||||
case KEY_EXE:
|
||||
/* Add End Of Line character */
|
||||
term_rdinfo.buffer.data[term_rdinfo.buffer.size - 1] = '\n';
|
||||
term_rdinfo.buffer.data[term_rdinfo.buffer.size] = '\0';
|
||||
/* indicate that the EXE key has been pressed. */
|
||||
term_rdinfo.mode.exit = 1;
|
||||
return 1;
|
||||
case KEY_LEFT:
|
||||
if (term_rdinfo.buffer.cursor > 0)
|
||||
term_rdinfo.buffer.cursor -= 1;
|
||||
return 1;
|
||||
case KEY_RIGHT:
|
||||
if (term_rdinfo.buffer.cursor < (int)term_rdinfo.buffer.size - 1)
|
||||
term_rdinfo.buffer.cursor += 1;
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* term_buffer_update(): Update the internal buffer with the given key code */
|
||||
static int term_key_buffer_update(key_event_t key_event)
|
||||
{
|
||||
static const uint8_t keylist_alpha[] = {
|
||||
KEY_XOT, KEY_LOG, KEY_LN, KEY_SIN, KEY_COS, KEY_TAN,
|
||||
KEY_FRAC, KEY_FD, KEY_LEFTP, KEY_RIGHTP, KEY_COMMA, KEY_ARROW,
|
||||
KEY_7, KEY_8, KEY_9,
|
||||
KEY_4, KEY_5, KEY_6, KEY_MUL, KEY_DIV,
|
||||
KEY_1, KEY_2, KEY_3, KEY_PLUS, KEY_MINUS,
|
||||
KEY_0, 0xff
|
||||
};
|
||||
static const uint8_t keylist_num[] = {
|
||||
KEY_0, KEY_1, KEY_2, KEY_3, KEY_4,
|
||||
KEY_5, KEY_6, KEY_7, KEY_8, KEY_9,
|
||||
KEY_PLUS, KEY_MINUS, KEY_MUL, KEY_DIV,
|
||||
KEY_LEFTP, KEY_RIGHTP, KEY_COMMA, KEY_POWER,
|
||||
KEY_DOT, KEY_FD, KEY_ARROW, 0xff
|
||||
};
|
||||
static const char keylist_num_char[] = "0123456789+-x/(),^.|_";
|
||||
const uint8_t *keycode_list;
|
||||
char character;
|
||||
int i;
|
||||
|
||||
/* Get the appropriate key list. */
|
||||
keycode_list = keylist_alpha;
|
||||
if (term_rdinfo.mode.shift == 1)
|
||||
keycode_list = keylist_num;
|
||||
|
||||
/* Try to find the pressed key. */
|
||||
i = -1;
|
||||
while (keycode_list[++i] != 0xff && keycode_list[i] != key_event.key);
|
||||
if (keycode_list[i] != key_event.key)
|
||||
return 0;
|
||||
|
||||
/* handle mode then update the buffer */
|
||||
if (term_rdinfo.mode.shift == 0) {
|
||||
character = 'a' + i;
|
||||
if (term_rdinfo.mode.alpha == 1)
|
||||
character = 'A' + i;;
|
||||
} else {
|
||||
character = keylist_num_char[i];
|
||||
}
|
||||
term_buffer_insert(character);
|
||||
return 1;
|
||||
}
|
||||
|
||||
//---
|
||||
// primitive
|
||||
//---
|
||||
|
||||
/* */
|
||||
int console_read(struct console *console, void *buffer, size_t nb)
|
||||
{
|
||||
key_event_t key;
|
||||
|
||||
/* check obvious error */
|
||||
if (buffer == NULL || nb == 0)
|
||||
return 0;
|
||||
|
||||
/* initialize internal data */
|
||||
memset(&term_rdinfo, 0x00, sizeof(term_rdinfo));
|
||||
memset(buffer, 0x00, nb);
|
||||
|
||||
/* save terminal information */
|
||||
term_rdinfo.cursor.visible = 1;
|
||||
term_rdinfo.cursor.saved = terminal.buffer.cursor;
|
||||
term_rdinfo.cursor.x = terminal.cursor.x;
|
||||
term_rdinfo.cursor.y = terminal.cursor.y;
|
||||
term_rdinfo.buffer.data = buffer;
|
||||
term_rdinfo.buffer.size = 1;
|
||||
term_rdinfo.buffer.max = nb;
|
||||
|
||||
/* keyboard handling */
|
||||
while (term_rdinfo.mode.exit == 0)
|
||||
{
|
||||
/* handle pressed keys */
|
||||
key = getkey_opt(GETKEY_REP_ALL | GETKEY_MENU, NULL);
|
||||
if (term_key_handle_special(key) == 0)
|
||||
term_key_buffer_update(key);
|
||||
/* display */
|
||||
term_display_all();
|
||||
}
|
||||
|
||||
return term_rdinfo.buffer.size;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,41 @@
|
|||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "bootloader/console.h"
|
||||
#include "bootloader/display.h"
|
||||
|
||||
//---
|
||||
// Public
|
||||
//---
|
||||
|
||||
/* console_vwrite() : printf wrapper for the terminal device with va_list */
|
||||
int console_vwrite(struct console *console, const char *format, va_list ap)
|
||||
{
|
||||
char buffer[1024];
|
||||
int nb;
|
||||
|
||||
/* process the format */
|
||||
nb = vsnprintf(buffer, 1024, format, ap);
|
||||
|
||||
/* update the internal buffer */
|
||||
console_buffer_insert(console, buffer, nb);
|
||||
|
||||
/* display the internal buffer */
|
||||
dclear(console->_private.color.bg);
|
||||
console_buffer_display(console);
|
||||
dupdate();
|
||||
return nb;
|
||||
}
|
||||
|
||||
/* console_write() - printf wrapper for the terminal device */
|
||||
int console_write(struct console *console, char const *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int nb;
|
||||
|
||||
va_start(ap, format);
|
||||
nb = console_vwrite(console, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
return nb;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
#include "bootloader/display.h"
|
||||
#include "bootloader/bios.h"
|
||||
|
||||
//---
|
||||
// Public
|
||||
//---
|
||||
|
||||
/* dclear() : clear VRAM with unified color */
|
||||
void dclear(int color)
|
||||
{
|
||||
_bios_dclear(color);
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "bootloader/display.h"
|
||||
#include "bootloader/bios.h"
|
||||
|
||||
//---
|
||||
// Public
|
||||
//---
|
||||
|
||||
/* dinfo() : get display information */
|
||||
void dinfo(size_t *width, size_t *height)
|
||||
{
|
||||
_bios_dinfo(width, height);
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
#include <bootloader/display.h>
|
||||
#include <bootloader/bios.h>
|
||||
|
||||
/* sgn() (without double evaluation) */
|
||||
#define sgn(s) ({ \
|
||||
__auto_type _s = (s); \
|
||||
_s < 0 ? -1 : \
|
||||
_s > 0 ? +1 : \
|
||||
0; \
|
||||
})
|
||||
|
||||
//---
|
||||
// Public
|
||||
//---
|
||||
|
||||
/* dline() : draw line */
|
||||
void dline(int x1, int y1, int x2, int y2, int color)
|
||||
{
|
||||
int i;
|
||||
int cumul;
|
||||
int x = x1;
|
||||
int y = y1;
|
||||
int dx = x2 - x1;
|
||||
int dy = y2 - y1;
|
||||
int sx = sgn(dx);
|
||||
int sy = sgn(dy);
|
||||
|
||||
dx = (dx >= 0 ? dx : -dx);
|
||||
dy = (dy >= 0 ? dy : -dy);
|
||||
|
||||
dpixel(x1, y1, color);
|
||||
|
||||
if(dx >= dy)
|
||||
{
|
||||
/* Start with a non-zero cumul to even the overdue between the
|
||||
two ends of the line (for more regularity) */
|
||||
cumul = dx >> 1;
|
||||
for(i = 1; i < dx; i++)
|
||||
{
|
||||
x += sx;
|
||||
cumul += dy;
|
||||
if(cumul > dx) {
|
||||
cumul -= dx;
|
||||
y += sy;
|
||||
}
|
||||
dpixel(x, y, color);
|
||||
}
|
||||
} else {
|
||||
cumul = dy >> 1;
|
||||
for(i = 1; i < dy; i++)
|
||||
{
|
||||
y += sy;
|
||||
cumul += dx;
|
||||
if(cumul > dy) {
|
||||
cumul -= dy;
|
||||
x += sx;
|
||||
}
|
||||
dpixel(x, y, color);
|
||||
}
|
||||
}
|
||||
dpixel(x2, y2, color);
|
||||
}
|
||||
|
||||
#undef sgn
|
|
@ -0,0 +1,12 @@
|
|||
#include "bootloader/display.h"
|
||||
#include "bootloader/bios.h"
|
||||
|
||||
//---
|
||||
// Public
|
||||
//---
|
||||
|
||||
/* dpixel() : draw pixel */
|
||||
void dpixel(int x, int y, int color)
|
||||
{
|
||||
_bios_dpixel(x, y, color);
|
||||
}
|
|
@ -1,25 +1,14 @@
|
|||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <alloca.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <bootloader/display.h>
|
||||
#include <bootloader/bios.h>
|
||||
#include "bootloader/display.h"
|
||||
#include "bootloader/bios.h"
|
||||
|
||||
//---
|
||||
// Public
|
||||
//---
|
||||
|
||||
/* dclear() : clear VRAM with unified color */
|
||||
void dclear(int color)
|
||||
{
|
||||
_bios_dclear(color);
|
||||
}
|
||||
|
||||
/*dtext() : display raw text to VRAM */
|
||||
void dtext(int x, int y, int color, char *text)
|
||||
{
|
||||
_bios_dtext(x, y, color, text);
|
||||
}
|
||||
|
||||
/* dprint() : printf-like dtext() */
|
||||
void dprint(int x, int y, int color, char *format, ...)
|
||||
{
|
||||
|
@ -37,8 +26,4 @@ void dprint(int x, int y, int color, char *format, ...)
|
|||
_bios_dtext(x, y, color, buffer);
|
||||
}
|
||||
|
||||
/* dupdate() : update VRAM to screen */
|
||||
void dupdate(void)
|
||||
{
|
||||
_bios_dupdate();
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#include "bootloader/display.h"
|
||||
#include "bootloader/bios.h"
|
||||
|
||||
//---
|
||||
// Public
|
||||
//---
|
||||
|
||||
/*dtext() : display raw text to VRAM */
|
||||
void dtext(int x, int y, int color, char *text)
|
||||
{
|
||||
_bios_dtext(x, y, color, text);
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
#include "bootloader/display.h"
|
||||
#include "bootloader/bios.h"
|
||||
|
||||
//---
|
||||
// Public
|
||||
//---
|
||||
|
||||
/* dupdate() : update VRAM to screen */
|
||||
void dupdate(void)
|
||||
{
|
||||
_bios_dupdate();
|
||||
}
|
|
@ -14,7 +14,7 @@ int bootloader_main(uintptr_t image_base_addr, size_t image_size)
|
|||
|
||||
//TODO : check special key pressed, if not simply boot the kernel
|
||||
|
||||
console_init(&console);
|
||||
console_open(&console);
|
||||
console_write(
|
||||
&console,
|
||||
"vxGOS bootloader entry\n"
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
|
||||
|
||||
int bootloader_c_test(void)
|
||||
{
|
||||
while (1);
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
//---
|
||||
// Public
|
||||
//---
|
||||
|
||||
/* calloc() : malloc + memset */
|
||||
void *calloc(size_t nmemb, size_t size)
|
||||
{
|
||||
unsigned int total_size;
|
||||
void *mem;
|
||||
|
||||
if(__builtin_umul_overflow(nmemb, size, &total_size))
|
||||
return NULL;
|
||||
|
||||
mem = malloc(total_size);
|
||||
if(mem != NULL)
|
||||
memset(mem, 0, total_size);
|
||||
return mem;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#include "bootloader/bios.h"
|
||||
|
||||
//---
|
||||
// Public
|
||||
//---
|
||||
|
||||
/* free() : free allocated memory */
|
||||
void free(void *ptr)
|
||||
{
|
||||
return _bios_free(ptr);
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include "bootloader/bios.h"
|
||||
|
||||
//---
|
||||
// Public
|
||||
//---
|
||||
|
||||
/* malloc() : memory allocator */
|
||||
void *malloc(size_t size)
|
||||
{
|
||||
return _bios_malloc(size);
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
//---
|
||||
// Public
|
||||
//---
|
||||
|
||||
/* memcpy() : copy memory arena */
|
||||
void *memcpy(void *dest, const void *src, size_t count)
|
||||
{
|
||||
for (size_t i = 0; i < count; i = i + 1)
|
||||
((uint8_t *) dest)[i] = ((uint8_t *) src)[i];
|
||||
return dest;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
//---
|
||||
// Public
|
||||
//---
|
||||
|
||||
/* memset() : wipe arena */
|
||||
void *memset(void *s, int c, size_t n)
|
||||
{
|
||||
while ((int)--n >= 0)
|
||||
((uint8_t *) s)[n] = c;
|
||||
return s;
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
//---
|
||||
// Internals
|
||||
//---
|
||||
|
||||
struct __snprintf_core
|
||||
{
|
||||
uintptr_t buffer;
|
||||
uintptr_t buffer_saved;
|
||||
size_t buffer_size;
|
||||
};
|
||||
|
||||
/* __buffer_update() : inject one char if possible */
|
||||
static int __buffer_inj_char(struct __snprintf_core *core, char c)
|
||||
{
|
||||
((char*)core->buffer)[0] = c;
|
||||
core->buffer += 1;
|
||||
((char*)core->buffer)[0] = '\0';
|
||||
if ((core->buffer - core->buffer_saved) < core->buffer_size - 1)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* __buffer_inj_ptr() : inject ptr */
|
||||
static int __buffer_inj_ptr(struct __snprintf_core *core, uintptr_t ptr)
|
||||
{
|
||||
static char const * const table = "0123456789abcdef";
|
||||
|
||||
if (
|
||||
__buffer_inj_char(core, '0') != 0
|
||||
|| __buffer_inj_char(core, 'x') != 0
|
||||
|| __buffer_inj_char(core, table[(ptr & 0xf0000000) >> 28]) != 0
|
||||
|| __buffer_inj_char(core, table[(ptr & 0x0f000000) >> 24]) != 0
|
||||
|| __buffer_inj_char(core, table[(ptr & 0x00f00000) >> 20]) != 0
|
||||
|| __buffer_inj_char(core, table[(ptr & 0x000f0000) >> 16]) != 0
|
||||
|| __buffer_inj_char(core, table[(ptr & 0x0000f000) >> 12]) != 0
|
||||
|| __buffer_inj_char(core, table[(ptr & 0x00000f00) >> 8]) != 0
|
||||
|| __buffer_inj_char(core, table[(ptr & 0x000000f0) >> 4]) != 0
|
||||
|| __buffer_inj_char(core, table[(ptr & 0x0000000f) >> 0]) != 0
|
||||
) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* __buffer_inj_digit() : inject number */
|
||||
static int __buffer_inj_digit(struct __snprintf_core *core, int nb, bool patch)
|
||||
{
|
||||
if (patch && nb == 0)
|
||||
return 0;
|
||||
if (__buffer_inj_digit(core, nb / 10, true) != 0)
|
||||
return -1;
|
||||
return __buffer_inj_char(core, (nb % 10) + '0');
|
||||
}
|
||||
|
||||
//---
|
||||
// Public
|
||||
//---
|
||||
|
||||
/* vsnprintf() : snprintf-like function */
|
||||
int vsnprintf(char *buffer, size_t sz, char const *format, va_list ap)
|
||||
{
|
||||
struct __snprintf_core core;
|
||||
int exit;
|
||||
|
||||
core.buffer = (uintptr_t)buffer;
|
||||
core.buffer_saved = (uintptr_t)buffer;
|
||||
core.buffer_size = sz;
|
||||
|
||||
exit = 0;
|
||||
while (format[0] != '\0' && exit == 0)
|
||||
{
|
||||
if (format[0] != '%') {
|
||||
exit = __buffer_inj_char(&core, format[0]);
|
||||
format = &format[1];
|
||||
continue;
|
||||
}
|
||||
switch (format[1])
|
||||
{
|
||||
case '\0':
|
||||
exit = __buffer_inj_char(&core, '%') - 10;
|
||||
break;
|
||||
case '%':
|
||||
exit = __buffer_inj_char(&core, '%');
|
||||
break;
|
||||
case 'p':
|
||||
exit = __buffer_inj_ptr(&core, va_arg(ap, uintptr_t));
|
||||
break;
|
||||
case 'd':
|
||||
exit = __buffer_inj_digit(&core, va_arg(ap, int), false);
|
||||
break;
|
||||
|
||||
}
|
||||
format = &format[2];
|
||||
}
|
||||
return (core.buffer - core.buffer_saved);
|
||||
}
|
||||
|
||||
/* snprintf() : snprintf-like function */
|
||||
int snprintf(char *buffer, size_t sz, char const *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int n;
|
||||
|
||||
va_start(ap, format);
|
||||
n = vsnprintf(buffer, sz, format, ap);
|
||||
va_end(ap);
|
||||
return n;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
#define ASM_SOURCE
|
||||
#include <vhex/hardware.h>
|
||||
#include "boards/fxcg50/include/hardware.h"
|
||||
#include "fxcg50/hardware.h"
|
||||
.text
|
||||
|
||||
.global _sh7305_inth_callback
|
||||
|
@ -97,5 +97,3 @@ _sh7305_inth_callback:
|
|||
.long (0xf << 4)
|
||||
.vhex:
|
||||
.long _vhex
|
||||
|
||||
|
||||
|
|
21
vxsdk.toml
21
vxsdk.toml
|
@ -9,7 +9,7 @@ target = [
|
|||
|
||||
[build]
|
||||
#configure = './vxdev configure'
|
||||
build = '/usr/bin/env python3 ./scripts/vxdev build --verbose'
|
||||
build = '/usr/bin/env python3 ./scripts/vxdev build'
|
||||
#install = '/usr/bin/env python3 ./scripts/vxdev install'
|
||||
#uninstall = '/usr/bin/env python3 ./scripts/vxdev uninstall'
|
||||
|
||||
|
@ -37,25 +37,22 @@ assets_prefix = [
|
|||
# '-fstack-protector-all',
|
||||
]
|
||||
VXSDK_PRIVATE_BUILD_LDFLAGS = [
|
||||
'-static',
|
||||
'-Wl,-Map=map',
|
||||
'-Wl,--build-id=none',
|
||||
'-Wl,--emit-relocs',
|
||||
]
|
||||
VXSDK_PUBLIC_BUILD_LIBS = [
|
||||
VXSDK_PRIVATE_BUILD_LIBS = [
|
||||
'@COMMON@',
|
||||
'-Wl,--whole-archive',
|
||||
'-lvxkernel',
|
||||
'-Wl,--no-whole-archive',
|
||||
'@sh-elf-vhex@',
|
||||
'-lc',
|
||||
# '-lc',
|
||||
'-lgcc',
|
||||
'-lssp_nonshared',
|
||||
]
|
||||
VXSDK_PUBLIC_BUILD_LDFLAGS = [
|
||||
'-T {VXSDK_CURRENT_SOURCE_DIR}/boards/fxcg50/fxcg50.ld',
|
||||
'-static',
|
||||
'-Wl,-q'
|
||||
]
|
||||
# VXSDK_PUBLIC_BUILD_LDFLAGS = [
|
||||
# '-T {VXSDK_CURRENT_SOURCE_DIR}/boards/fxcg50/fxcg50.ld',
|
||||
# '-static',
|
||||
# '-Wl,-q'
|
||||
# ]
|
||||
|
||||
[sdl2]
|
||||
[sdl2.env]
|
||||
|
|
Loading…
Reference in New Issue