hotfix for the vxSDK

This commit is contained in:
Yann MAGNIN 2022-08-02 14:59:03 +02:00
parent 674d4b382c
commit 585254cb2e
5 changed files with 839 additions and 1 deletions

373
Makefile Normal file
View File

@ -0,0 +1,373 @@
#!/usr/bin/make -f
# ---
# Project: vxKernek - Vhex project kernel
# Author: yann.magnin@protonmail.com
#
# TODO:
# <> proper clean rule
# ---
#---
# environment check
#---
ifeq ($(VXSDK_PREFIX_BUILD),)
$(error "The vxKernel sould be build using the vxSDK")
endif
#---
# Build rules
#---
# Make selects the first rule set when you type "make" but, in our case, we are
# going to generate most of the rules. So, we set a placeholder to force the
# "all" rule to be the "first" rule
first: all
# display the library version
version:
@echo "$(VXSDK_PKG_VERSION)"
# Display helper
help:
@ echo 'Rules listing:'
@ echo '... all the default, if no target is provided'
@ echo '... clean remove build object'
@ echo '... fclean remove all generated object'
@ echo '... re same as `make fclean all`'
@ echo '... version display version'
@ echo '... install install the library'
@ echo '... uninstall uninstall the library'
.PHONY: help version first
#---
# Check build validity
#---
CONFIG := $(VXSDK_PREFIX_BUILD)/kernel.cfg
ifeq "$(wildcard $(CONFIG))" ""
$(error "config file $(CONFIG) does not exist (you should use `../configure`")
endif
include $(CONFIG)
#---
# Variables definition
#---
# Many variables will be provided by the "kernel.cfg" file (generated during
# the configuration part). It will defines:
# <> BOARD - indicate the target board list
# <> {BOARD}-SRC-MODULE-PATH - list of all sources path for a specific board
# <> {BOARD}-TOOLCHAIN-PREFIX - toolchain prefix for a board (sh-elf, ...)
# <> FORMAT - format for the kernel (static, dynamic)
# color definition, for swagg :D
red := \033[1;31m
green := \033[1;32m
blue := \033[1;34m
white := \033[1;37m
nocolor := \033[1;0m
#---
# Rules definition
#
# The objectif is to generate a building this build tree:
#
# <VXSDK_BUILD_PREFIX>/:
# |-- kernel.cfg
# |-- <board_name>/:
# | |-- <format>/:
# | | |-- obj/:
# | | | |-- main.o
# ...
# | | | `-- initialize.o
# | | `-- map
# | |-- <board_name>.ld
# | `-- libvxkernel-<format>.[so/a]
# `-- Makefile
#---
# Function that will generate a rule for one object file
# @param
# *1 - GCC name (with specific prefix if needed)
# *2 - CFLAGS list
# *3 - source file path
# *4 - build root directory path
# *5 - object file compilation rule list
# *6 - dependencies file compilation rule list
# *7 - unique id (used to generate unique variable name (workaround))
define generate-compile-file-rule
# generate the object file path
# @note
# <> This is alse the generated rule name
# <> step:
# 1) ../board/path/file.c -> ../board/path/file
# 2) .._board_path_file -> board_path_file
# 3) board_path_file.o -> {build path}/board_path_file.o
tname := $(strip $7)
obj-$(tname)-name := $$(basename $3)
obj-$(tname)-name := $$(subst /,_,$$(obj-$(tname)-name))
obj-$(tname)-name := $$(patsubst %,$4/%.o,$$(obj-$(tname)-name))
# generate the building rule
$$(obj-$(tname)-name): $3
@ mkdir -p $$(dir $$@)
ifeq ($(CONFIG.VERBOSE),false)
@ printf "$(green)>$(nocolor) $(white)$$@$(nocolor)\n"
@ $1 $2 -o $$@ -c $$< -MMD -MT $$@ -MF $$@.d -MP
else
$1 $2 -o $$@ -c $$< -MMD -MT $$@ -MF $$@.d -MP
endif
# register the build rules and dependencies file name
$5 += $$(obj-$(tname)-name)
$6 += $$(obj-$(tname)-name).d
endef
# Function that will generate all rules for a specific board and format
# @params
# *1 - board name
# *2 - format name (static or dynamic)
# *3 - rules list variable name
define generate-target-lib
# generate common information
# @note:
# Because we generate rule "on-the-fly" we need to create unique variable
# definition because make is not a "scoped" language. (therefore, when a
# variable is created, it will never be destroyed until the end of the script)
t-$1-$2-build := $(VXSDK_PREFIX_BUILD)/$1/$2
# generate compilation flags
t-$1-$2-ar := $$(CONFIG.$1.TOOLCHAIN.PREFIX)ar
t-$1-$2-ld := $$(CONFIG.$1.TOOLCHAIN.PREFIX)ld
t-$1-$2-gcc := $$(CONFIG.$1.TOOLCHAIN.PREFIX)gcc
t-$1-$2-ldflags := $$(CONFIG.$1.TOOLCHAIN.LDFLAGS)
t-$1-$2-cflags := $$(CONFIG.$1.TOOLCHAIN.CFLAGS)
t-$1-$2-cflags += -fpic -ffreestanding -nostdlib -fstrict-volatile-bitfields -O1
t-$1-$2-cflags += -Wa,--dsp
# generate compiler information (used to find some library like libgcc.a)
t-$1-$2-gcc-base := $$(shell $$(CONFIG.$1.TOOLCHAIN.PREFIX)gcc --print-search-dirs | grep install | sed 's/install: //')
t-$1-$2-gcc-header := -I$$(t-$1-$2-gcc-base)/include -I$$(t-$1-$2-gcc-base)/include/openlibm
t-$1-$2-cflags += -Iinclude -I. -Isrc $$(t-$1-$2-gcc-header)
t-$1-$2-cflags += -Llib -L. -L$$(t-$1-$2-gcc-base)
# generate file's sources list, based on the configuration step
t-$1-$2-src := $$(foreach path,$$(CONFIG.$1.SRC-MODULE-PATH),\
$$(wildcard $$(path)/*.c) \
$$(wildcard $$(path)/*.S) \
$$(wildcard $$(path)/*.s))
# generate format-specific flags
t-$1-$2-exec :=
ifeq ($2,static)
t-$1-$2-exec := $(VXSDK_PREFIX_BUILD)/libvhex-$1.a
endif
ifeq ($2,dynamic)
t-$1-$2-ldflags += -shared
t-$1-$2-ldflags += -soname=libvhex-$1-$(VXSDK_PKG_VERSION).so
t-$1-$2-ldflags += -Map=$$(t-$1-$2-build)/map
t-$1-$2-exec := $(VXSDK_PREFIX_BUILD)/libvhex-$1.so
t-$1-$2-src := $(wildcard fake/*.c)
endif
# generate file's compilation rules and all object filename into an object
# list variable, this will be used by the `main` rule
t-$1-$2-obj :=
t-$1-$2-dep :=
$$(foreach source,$$(t-$1-$2-src),$$(eval \
$$(call generate-compile-file-rule,\
$$(t-$1-$2-gcc),\
$$(t-$1-$2-cflags),\
$$(source),\
$$(t-$1-$2-build),\
t-$1-$2-obj,\
t-$1-$2-dep,\
$1-$2\
))\
)
# asset generation
t-$1-$2-asset := $(patsubst \
$(VXSDK_ASSETS_SRC)/%,\
$(VXSDK_ASSETS_BUILD)/$1/$2/%.o,\
$(wildcard $(VXSDK_ASSETS_SRC)/*.c) \
)
$(VXSDK_ASSETS_BUILD)/$1/$2/%.o: $(VXSDK_ASSETS_SRC)/%
ifeq ($(CONFIG.VERBOSE),true)
@ mkdir -p $$(dir $$@)
sh-elf-vhex-gcc $$(t-$1-$2-cflags) -o $$@ -c $$<
else
@ mkdir -p $$(dir $$@)
@ printf "$(green)>$(nocolor) $(white)$@$(nocolor)\n"
@ sh-elf-vhex-gcc $$(t-$1-$2-cflags) -o $$@ -c $$<
endif
# generate the "main" rule for this lib
$$(t-$1-$2-exec): $$(t-$1-$2-obj) $$(t-$1-$2-asset)
@ mkdir -p $$(dir $$@)
@ echo "dep : $$(t-$1-$2-dep)"
@ printf "$(blue)Create the library $(red)$$@$(nocolor)\n"
ifeq ($2,dynamic)
$$(t-$1-$2-gcc) -shared $$(t-$1-$2-cflags) $$(t-$1-$2-gcc-libs) -o $$@ $$^
else
$$(t-$1-$2-ar) crs $$@ $$^
endif
# register the "main" building rule for the lib
$3 += $$(t-$1-$2-exec)
# import dependencies rules
-include $$(t-$1-$2-dep)
$$(t-$1-$2-dep): ;
.PRECIOUS: $$(t-$1-$2-dep)
endef
# Generate the "main" rules list
target-lib-list :=
$(foreach board,$(CONFIG.BOARD-LIST),\
$(foreach format,$(CONFIG.FORMAT-LIST),$(eval\
$(call generate-target-lib,$(board),$(format),target-lib-list)\
))\
)
#---
# Build rules
#---
all: $(target-lib-list)
.PHONY: all
#---
# Generate installation rules
#---
# Common rules generated for the installation of each libraries.
# Basically, it will generate <libname>-install and <libname>-uninstall rules
# @note:
# *1 - library pathname
# *2 - variable name (installation rules list)
# *3 - variable name (uninstallation rules list)
define generate-install-rule
# Generate the installation rule
$(basename $(notdir $1))-install:
install -d $(VXSDK_PREFIX_LIB)
install $1 -m 644 $(VXSDK_PREFIX_LIB)
# Generate the uninstallation rule
$(basename $(notdir $1))-uninstall:
rm -f $(VXSDK_PREFIX_LIB)/$(notdir $1)
# Register generated rules into their appropriate list
$2 += $(basename $(notdir $1))-install
$3 += $(basename $(notdir $1))-uninstall
endef
# Common rules generated for the installation of board-specific linker script
# @note:
# $1 - board name
# $2 - variable name (installation rules list)
# $3 - variable name (uninstallation rules list)
define generate-board-install-rule
$1-install:
install -d $(VXSDK_PREFIX_LIB)
install board/$(strip $1)/*.ld -m 644 $(VXSDK_PREFIX_LIB)
$1-uninstall:
rm -f $(VXSDK_PREFIX_LIB)/$(strip $1).ld
rm -f $(VXSDK_PREFIX_LIB)/$(strip $1)-dynamic.ld
$2 += $1-install
$3 += $1-uninstall
endef
# Generate all installation/uninstallation rules
target-install-rules :=
target-uninstall-rules :=
$(foreach target,$(target-lib-list),$(eval \
$(call generate-install-rule, \
$(target), \
target-install-rules, \
target-uninstall-rules \
) \
))
$(foreach board,$(CONFIG.BOARD-LIST),$(eval \
$(call generate-board-install-rule, \
$(board), \
target-install-rules, \
target-uninstall-rules \
) \
))
# Generate the path where include directory will be installed.
target-install-hdr-dir := $(VXSDK_PREFIX_LIB)/include/
ifeq ($(wildcard $(target-install-header-dir)vhex/.*),)
target-install-hdr-dir := $(target-install-hdr-dir)vhex
endif
#---
# Installation rules
#---
install: $(target-install-rules)
mkdir -p $(dir $(target-install-hdr-dir))
cp -r include/vhex $(target-install-hdr-dir)
unsintall: $(target-uninstall_rules)
rm -rf $(VXSDK_PREFIX_LIB)/include/vhex
.PHONY: install uninstall
#---
# cleaning rules
#---
#clean: TODO: generate clean rule list
fclean: clean
rm -rf $(target-lib-list)
re: fclean all
.PHONY: clean fclean re all

290
configure vendored Executable file
View File

@ -0,0 +1,290 @@
#! /usr/bin/python3
import sys
import os.path
import os
import shutil
import toml
help_string = f"""
usage: config [options...]
Configuration script for the Vhex unikernel. You should build out-of-tree by
creating a build directory and configuring from there.
Options:
-h,--help
display this message
--verbose
display more information during the compilation step
--<format>
select the format of the library generation. You can use two format:
<> static - generate a static library
<> dynamic - generate a dynamic library
By default, only "dynamic" is used.
--board[=BOARD,board[,...]]
select boards. If no board name is given, a list of all available board
will be printed.
--prefix=PATH
installation path for all generated libraries
""".strip()
#---
# Internal functions
#---
def __list_dir(path):
ldir = []
for dirent in os.listdir(path):
dpath = f'{path}/{dirent}'
if os.path.isdir(dpath):
ldir.append(dpath)
ldir += __list_dir(dpath)
return ldir
def error(string, exitcode=84):
print(string, file=sys.stderr)
exit(exitcode)
def warn(string):
print(string, file=sys.stderr)
#---
# part handlers
#---
def _board_check(file, board_list):
r"""Check board and architecture.
This function will try to load the <prefix>/board/<board>/board.toml file
which describe the required module to be build for the kernel image
generation.
TODO: board.toml documentation
TODO: function documentation
Args:
> [out] file (stream) - the 'kernel.cfg' files stream
> [in] board_list (list of str) - list of all board to support
"""
# list available board and architecture
try:
boards = list(os.walk('board'))[0][1]
archs = list(os.walk('src/driver/mpu'))[0][1]
except Exception:
error(f"{prefix}: project not found, fix VXSDK_PREFIX_BUILD")
# list all available board if no board target is provided
if not board_list:
print('board available:')
for board in boards:
path = f'board/{board}/board.toml'
if not os.path.exists(path):
warn(f'missing \'{board}\' board description')
continue
conf = None
with open(path) as f:
conf = toml.loads(f.read())
if not ('meta' in conf) or not ('description' in conf['meta']):
print(f'<> {board}'.ljust(16) + 'No description available')
continue
print(f'<> {board}'.ljust(16) + f"{conf['meta']['description']}")
exit(0)
# generate board list information
valid_board_list = []
for board in board_list:
# try to read the board description
if not (board in boards):
warn(f"board '{board}' does not exist")
continue
path = f'board/{board}/board.toml'
if not os.path.exists(path):
warn(f"board '{board}' does not have descriptor file")
continue
conf = None
with open(path) as f:
conf = toml.loads(f.read())
# check fundamental information
if not ('drivers' in conf) or not ('mpu' in conf['drivers']):
warn(f"board '{board}': missing MPU information")
continue
# gues the architecture
arch = None
mpu = conf['drivers']['mpu']
for _arch in archs:
if not os.path.exists(f'src/driver/mpu/{_arch}/{mpu}'):
continue
arch = _arch
break
if not arch:
warn(f"board '{board}': unreconized MPU '{mpu}'")
continue
# Now generate the complete directory list that will be used by the
# Makefile as <pathlib[i]/*.[c/s/S]> to find all source files
pathlist = [
f'src',
f'board/{board}',
f'src/driver/mpu/{_arch}/{mpu}'
]
pathlist += __list_dir(f'board/{board}')
pathlist += __list_dir(f'src/driver/mpu/{_arch}/{mpu}')
# generate driver path list
for driver in conf['drivers']:
if driver == 'mpu':
continue
dpath = f'src/driver/{driver}'
if not os.path.exists(dpath):
warn(f"board '{board}': unreconized driver \'{driver}\', skipped")
continue
for t in conf['drivers'][driver].split(','):
tpath = dpath + '/' + t
if not os.path.exists(tpath):
warn(f"board '{board}': unreconized driver '{t}'")
continue
pathlist.append(tpath)
pathlist += __list_dir(tpath)
# generate module path list
modules = []
if ('config' in conf) and ('modules' in conf['config']):
modules = conf['config']['modules']
for dirent in os.listdir(f'src'):
if (dirent in ['driver']):
continue
if modules and not (dirent in modules):
continue
pathlist.append(f'src/{dirent}')
pathlist += __list_dir(f'src/{dirent}')
# fetch toolchain information
# TODO: polymorphisme
ldflags,cflags,prefix,libs = [],[],[],[]
if 'toolchain' in conf:
if 'prefix' in conf['toolchain']:
prefix = conf['toolchain']['prefix']
if 'cflags' in conf['toolchain']:
cflags = conf['toolchain']['cflags']
if 'libs' in conf['toolchain']:
libs = conf['toolchain']['libs']
# add board information in the make configuration file
confstr = 'CONFIG.' + board
file.write(
confstr + '.SRC-MODULE-PATH := ' + ' '.join(map(str, pathlist)) + '\n'
+ confstr + '.TOOLCHAIN.LDFLAGS := ' + ' '.join(map(str, ldflags)) + '\n'
+ confstr + '.TOOLCHAIN.CFLAGS := ' + ' '.join(map(str, cflags)) + '\n'
+ confstr + '.TOOLCHAIN.PREFIX := ' + prefix + '\n'
+ confstr + '.LIBS :=' + ' '.join(map(str, libs)) + '\n'
)
# append board list
valid_board_list.append(board)
# write board list
file.write('CONFIG.BOARD-LIST := ' + ' '.join(valid_board_list) + '\n')
def _format_check(file, format_list):
file.write('CONFIG.FORMAT-LIST :=')
for _format in format_list:
if not (_format in ["static", "dynamic", "all"]):
print("%s: unreconized format '%s'" % (sys.argv[0], _format))
exit(84)
if _format == 'all':
file.write(' dynamic static\n')
return
file.write(' ' + _format)
if not format_list:
file.write(' dynamic')
file.write('\n')
def _prefix_check(file, prefix):
file.write('CONFIG.INSTALL-PREFIX :=' + prefix + '\n')
def _verbose_check(file, verbose):
file.write(f"CONFIG.VERBOSE := {'true' if verbose else 'false'}\n")
#---
# Public part
#---
def parse_arguments():
"""
The objectif of this function is to generate the "arguments object" with
all arguments passed throuth this script correctly isolated.
"""
args = {
'board' : [],
'format' : set(),
'verbose': False,
'prefix': ''
}
arg_name = [
"-h",
"--help",
"--static",
"--dynamic",
"--verbose",
"--board",
"--prefix"
]
for arg in sys.argv[1:]:
info = arg.split("=")
if (info[0] in arg_name) == False:
print("%s: unreconized option '%s'" % (sys.argv[0],info[0]))
print("Try '%s --help' for more information" % sys.argv[0])
exit(84)
if info[0] == "--verbose":
args["verbose"] = True
continue
if info[0] == "--prefix":
args["prefix"] = info[1]
continue
if info[0] in ['--static', '--dynamic']:
args['format'].add(info[0][2:])
continue
if len(info) > 1:
args[info[0][2:]] = info[1].split(",")
return args
def main():
""" main entry of the script """
# early check
if ('-h' in sys.argv[1:]) or ('--help' in sys.argv[1:]):
print(help_string)
exit(0)
# check if we are used by the vxSDK or not
try:
bprefix = os.environ['VXSDK_PREFIX_BUILD']
except Exception:
error('The vxKernel cannot be built without using the vxSDK.')
# check user arguments
args = parse_arguments()
# creare the configuration file
file = open(f'{bprefix}/kernel.cfg', 'w')
# handle all part of the configuration steps
_board_check(file, args['board'])
_format_check(file, args['format'])
_prefix_check(file, args['prefix'])
_verbose_check(file, args['verbose'])
main()

140
fake/display.c Normal file
View File

@ -0,0 +1,140 @@
/* dpixel(): Change a pixel's color */
void dpixel(int x, int y, int color)
{
(void)x;
(void)y;
(void)color;
}
/* dupdate(): Push the video RAM to the display driver */
void dupdate(void)
{
;
}
/* dclear(): Fill the screen with a single color */
void dclear(int color)
{
(void)color;
}
/* dascii() : display one ASCII character */
extern void dascii(int x, int y, int fg, int bg, int n)
{
(void)x;
(void)y;
(void)fg;
(void)bg;
(void)n;
}
/* dline(): Render a straight line */
void dline(int x1, int y1, int x2, int y2, int color)
{
(void)x1;
(void)y1;
(void)x2;
(void)y2;
(void)color;
}
/* dtext() : display raw text */
void dtext(int x, int y, int fg, char const * restrict const text)
{
(void)x;
(void)y;
(void)fg;
(void)text;
}
/* dprint() : display formated text */
void dprint(int x, int y, int fg, char const * const text, ...)
{
(void)x;
(void)y;
(void)fg;
(void)text;
}
/* dsize(): Get the width and height of rendered text */
void dsize(char const *str, int *w, int *h)
{
(void)str;
(void)w;
(void)h;
}
/* dnsize(): Get the width and height of rendered text for the n first char */
void dnsize(char const *str, int n, int *w, int *h)
{
(void)str;
(void)n;
(void)w;
(void)h;
}
/* drect(): Fill a rectangle of the screen */
void drect(int x1, int y1, int x2, int y2, int color)
{
(void)x1;
(void)y1;
(void)x2;
(void)y2;
(void)color;
}
/* dhline(): Draw horizontal line */
void dhline(int x1, int x2, int y, int color)
{
(void)x1;
(void)x2;
(void)y;
(void)color;
}
/* dvline(): Draw vertical line */
void dvline(int y1, int y2, int x, int color)
{
(void)y1;
(void)y2;
(void)x;
(void)color;
}
void dsubimage(int x, int y, void *image, int left, int top,
int width, int height, int flags)
{
(void)x;
(void)y;
(void)image;
(void)left;
(void)top;
(void)width;
(void)height;
(void)flags;
}
void *dfont(void const *font)
{
(void)font;
}
void dimage(int x, int y, void const *image)
{
(void)x;
(void)y;
(void)image;
}
void dprint_opt(int x, int y, int fg, int bg, int halign, int valign,
char const *format, ...)
{
(void)x;
(void)y;
(void)fg;
(void)bg;
(void)halign;
(void)valign;
(void)format;
}

35
fake/kmalloc.c Normal file
View File

@ -0,0 +1,35 @@
#include <stddef.h>
/* kmalloc(): Allocate memory in one of the available arenas
This function acts like malloc(). The second parameter specifies which arena
to allocate from; when NULL, all default arenas are considered.
@size Size of requested block
@arena_name Name of arena to allocate in (can be NULL)
Returns address of allocated block, NULL on error. */
void *kmalloc(size_t size, char const *arena_name)
{
(void)size;
(void)arena_name;
}
/* krealloc(): Reallocate memory
This function acts like realloc(). It only tries to reallocate the block in
the arena where it was previously allocated. Note that if NULL is returned,
the user needs to have a copy of the original address or the memory will
become unreachable.
@ptr Existing allocated block
@size New requested size for the block
Returns address of reallocated block, NULL on error. */
void *krealloc(void *ptr, size_t size)
{
(void)ptr;
(void)size;
}
/* kfree(): Free memory allocated with kalloc() */
void kfree(void *ptr)
{
(void)ptr;
}

View File

@ -1,6 +1,6 @@
[project]
name = 'vxkernel'
version = '0.5.0'
type = 'lib'
[build]
configure = 'python3 ./configure --board=fxcg50'