From cefccb8bb1b5c79230fb9f8dd1da1c1e2e06cd00 Mon Sep 17 00:00:00 2001 From: Yann MAGNIN Date: Fri, 2 Jun 2023 12:51:39 +0200 Subject: [PATCH] vxGOS - v0.7.0-10 : add raspi3b support (WIP) *add* > [vxgos] | [raspi3b] add vxsdk build entry | [raspi3b] add bzImage generation | [raspi3b] add ASLR support (WIP) | [raspi3b] add fake bios primitives support (WIP) > [bootloader] | [linker] add `.bootloader.header` section for image that need header *update* > [scripts] | [vxdev] isolate compiler flags from "vxsdk.toml" to "compiles.toml" | [vxdev] generate toolchain file for CMake (remove obscure env hook used by the vxSDK) *fix* > [bootloader] | [linker] disable got section size assert | [linker] ignore `.note.*` section --- .nvimrc | 8 - scripts/vxdev/core/build/aslr.py | 2 +- scripts/vxdev/core/build/bootloader.py | 18 ++- scripts/vxdev/core/build/cmake.py | 50 ++++++- scripts/vxdev/core/build/compiles.py | 50 +++++++ scripts/vxdev/core/build/kernel.py | 16 +- vxgos/boards/fxcg50/generate.py | 16 +- vxgos/boards/raspi3b/generate.py | 124 ++++++++++++++++ vxgos/bootloader/boards/fxcg50/compiles.toml | 23 +++ .../src/console/{handle.c => key_handle.c} | 0 vxgos/bootloader/boards/fxcg50/src/primary.S | 6 +- vxgos/bootloader/boards/fxcg50/src/start.S | 16 +- vxgos/bootloader/boards/raspi3b/compiles.toml | 18 +++ .../boards/raspi3b/src/bios/dinfo.c | 14 ++ .../boards/raspi3b/src/bios/dpixel.c | 13 ++ .../boards/raspi3b/src/bios/dupdate.c | 11 ++ .../bootloader/boards/raspi3b/src/bios/free.c | 11 ++ .../boards/raspi3b/src/bios/malloc.c | 12 ++ .../boards/raspi3b/src/console/key_handle.c | 16 ++ .../boards/raspi3b/src/console/keysc.c | 10 ++ vxgos/bootloader/boards/raspi3b/src/image.S | 46 ++++++ vxgos/bootloader/boards/raspi3b/src/start.S | 140 ++++++++++++++++++ vxgos/bootloader/bootloader.ld | 16 +- vxsdk.toml | 74 +-------- 24 files changed, 599 insertions(+), 111 deletions(-) create mode 100644 scripts/vxdev/core/build/compiles.py create mode 100644 vxgos/boards/raspi3b/generate.py create mode 100644 vxgos/bootloader/boards/fxcg50/compiles.toml rename vxgos/bootloader/boards/fxcg50/src/console/{handle.c => key_handle.c} (100%) create mode 100644 vxgos/bootloader/boards/raspi3b/compiles.toml create mode 100644 vxgos/bootloader/boards/raspi3b/src/bios/dinfo.c create mode 100644 vxgos/bootloader/boards/raspi3b/src/bios/dpixel.c create mode 100644 vxgos/bootloader/boards/raspi3b/src/bios/dupdate.c create mode 100644 vxgos/bootloader/boards/raspi3b/src/bios/free.c create mode 100644 vxgos/bootloader/boards/raspi3b/src/bios/malloc.c create mode 100644 vxgos/bootloader/boards/raspi3b/src/console/key_handle.c create mode 100644 vxgos/bootloader/boards/raspi3b/src/console/keysc.c create mode 100644 vxgos/bootloader/boards/raspi3b/src/image.S create mode 100644 vxgos/bootloader/boards/raspi3b/src/start.S diff --git a/.nvimrc b/.nvimrc index d7b91db..c34f360 100644 --- a/.nvimrc +++ b/.nvimrc @@ -1,11 +1,3 @@ -" Force-display trailing whitespaces -highlight ExtraWhitespace ctermbg=red guibg=red -match ExtraWhitespace /\s\+$/ -autocmd BufWinEnter * match ExtraWhitespace /\s\+$/ -autocmd InsertEnter * match ExtraWhitespace /\s\+\%#\@ prefix = {prefix}") + log.debug('- fetching compiles informations...') + compiles = compiles_fetch(f"{prefix}/boards/{build.target}/compiles.toml") + if not compiles: + log.emergency( + "unable to find bootloader's compilation information " + "(compiles.toml)" + ) + log.debug('- generate assets sources files...') cmd = '/usr/bin/env python3 ' cmd += f"{prefix}/../../sdk/converter conv-assets " @@ -61,10 +69,12 @@ def bootloader_configure(build, version): 'name' : 'bootloader', 'version' : version, 'linker' : f"{build.prefix['bootloader']}/bootloader.ld", - 'ldflags' : os.environ['VXSDK_BUILD_LDFLAGS'].split(';'), - 'cflags' : os.environ['VXSDK_BUILD_CFLAGS'].split(';'), + 'ldflags' : compiles.ldflags, + 'cflags' : compiles.cflags, 'include' : include_list, 'src' : assets_src + common_src + board_src, - 'libs' : os.environ['VXSDK_BUILD_LIBS'].split(';'), + 'libs' : compiles.libs, + 'toolchain_prefix' : compiles.toolchain_prefix, + 'toolchain_proc' : compiles.toolchain_processor, } ) diff --git a/scripts/vxdev/core/build/cmake.py b/scripts/vxdev/core/build/cmake.py index 885c355..a731d17 100644 --- a/scripts/vxdev/core/build/cmake.py +++ b/scripts/vxdev/core/build/cmake.py @@ -16,6 +16,27 @@ __all__ = [ # Internals #--- +_CMAKE_TOOLCHAIN_TEMPLATE = """ +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_VERSION 1) +set(CMAKE_SYSTEM_PROCESSOR {VXDEV_TOOLCHAIN_PROCESSOR}) + +set(CMAKE_C_COMPILER {VXDEV_TOOLCHAIN_PREFIX}gcc) +set(CMAKE_CXX_COMPILER {VXDEV_TOOLCHAIN_PREFIX}g++) + +set(CMAKE_C_FLAGS_INIT "") +set(CMAKE_CXX_FLAGS_INIT "") + +# required to avoid CMake compiler check fails +add_compile_options(-nostdlib) +add_link_options(-nostdlib) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) +""".strip() + _CMAKE_TEMPLATE = """ cmake_minimum_required(VERSION 3.15) @@ -103,7 +124,26 @@ def _cmake_build_generate_template(prefix, proj): cmakefile.write(content) return True +def _cmake_build_generate_toolchain(prefix, proj): + """ generate the toolchain file + """ + toolchain_proc = proj['toolchain_proc'] + toolchain_prefix = proj['toolchain_prefix'] + cmakefile_pathname = f"{prefix}/toolchain.cmake" + content = _CMAKE_TOOLCHAIN_TEMPLATE + content = re.sub('{VXDEV_TOOLCHAIN_PROCESSOR}', toolchain_proc, content) + content = re.sub('{VXDEV_TOOLCHAIN_PREFIX}', toolchain_prefix, content) + + if not _cmakefile_need_update(cmakefile_pathname, content): + return False + if not os.path.exists(prefix): + os.makedirs(prefix) + + log.debug(f"generate cmakefile at '{prefix}'...") + with open(cmakefile_pathname, 'x', encoding='ascii') as cmakefile: + cmakefile.write(content) + return True #--- # Pulbic @@ -116,11 +156,13 @@ def cmake_build_configure(prefix, proj): > name (str) - project name > prefix (str) - build prefix """ - if not _cmake_build_generate_template(prefix, proj): - return toolchain_flag = '' - if toolchain_path := os.environ.get('VXSDK_HOOK_CMAKE_TOOLCHAIN'): - toolchain_flag = f"-DCMAKE_TOOLCHAIN_FILE={toolchain_path}" + check = _cmake_build_generate_toolchain(prefix, proj) + if proj['toolchain_prefix']: + check += _cmake_build_generate_template(prefix, proj) + toolchain_flag = f"-DCMAKE_TOOLCHAIN_FILE={prefix}/toolchain.cmake" + if check == 0: + return shell_cmd = f"cmake {toolchain_flag} -B {prefix} -S {prefix}" if subprocess.run(shell_cmd.split(), check=False).returncode != 0: log.emergency(f"{proj['name']}: unable to configure the projet, abord") diff --git a/scripts/vxdev/core/build/compiles.py b/scripts/vxdev/core/build/compiles.py new file mode 100644 index 0000000..bf40374 --- /dev/null +++ b/scripts/vxdev/core/build/compiles.py @@ -0,0 +1,50 @@ +""" +core.build.compiles - handle "compiles.toml" files +""" +import dataclasses +import toml + +from core.logger import log + +__all__ = [ + 'compiles_fetch', +] + +#--- +# Internals +#--- + +@dataclasses.dataclass +class CompilesInfo(): + """ board compilation information """ + toolchain_prefix = '' + toolchain_processor = '' + cflags = [] + ldflags = [] + libs = [] + +#--- +# Public +#--- + +def compiles_fetch(filename): + """ try to load the compiles.toml file + """ + board_info = toml.load(filename) + info = CompilesInfo() + + check = 'VXDEV_TOOLCHAIN_PREFIX' in board_info + check += 'VXDEV_TOOLCHAIN_PROCESSOR' in board_info + if check == 1: + log.emergency(f"{filename}: missing toolchaine information, abord") + if check == 2: + info.toolchain_prefix = board_info['VXDEV_TOOLCHAIN_PREFIX'] + info.toolchain_processor = board_info['VXDEV_TOOLCHAIN_PROCESSOR'] + if 'VXDEV_CFLAGS' in board_info: + info.cflags = board_info['VXDEV_CFLAGS'] + if 'VXDEV_LDFLAGS' in board_info: + info.ldflags = board_info['VXDEV_LDFLAGS'] + if 'VXDEV_LIBS' in board_info: + info.libs = board_info['VXDEV_LIBS'] + + return info diff --git a/scripts/vxdev/core/build/kernel.py b/scripts/vxdev/core/build/kernel.py index 5175e28..6e87a4b 100644 --- a/scripts/vxdev/core/build/kernel.py +++ b/scripts/vxdev/core/build/kernel.py @@ -7,6 +7,7 @@ import toml from core.logger import log from core.build.cmake import cmake_build_configure +from core.build.compiles import compiles_fetch __all__ = [ 'kernel_configure', @@ -99,6 +100,13 @@ def kernel_configure(build, version): log.debug('fetching kernel files...') log.debug(f"> prefix = {prefix}") + log.debug('- fetching compiles informations...') + compiles = compiles_fetch(f"{prefix}/boards/{build.target}/compiles.toml") + if not compiles: + log.emergency( + "unable to find kernel's compilation information (compiles.toml)" + ) + board_cfg = _fetch_board_config( build, f"{prefix}/boards/{build.target}/board.toml" @@ -120,10 +128,12 @@ def kernel_configure(build, version): 'name' : 'kernel', 'version' : version, 'linker' : f"{build.prefix['kernel']}/kernel.ld", - 'ldflags' : os.environ['VXSDK_BUILD_LDFLAGS'].split(';'), - 'cflags' : os.environ['VXSDK_BUILD_CFLAGS'].split(';'), + 'ldflags' : compiles.ldflags, + 'cflags' : compiles.cflags, 'include' : include_list, 'src' : sources, - 'libs' : os.environ['VXSDK_BUILD_LIBS'].split(';'), + 'libs' : compiles.libs, + 'toolchain_prefix' : compiles.toolchain_prefix, + 'toolchain_proc' : compiles.toolchain_processor, } ) diff --git a/vxgos/boards/fxcg50/generate.py b/vxgos/boards/fxcg50/generate.py index be33400..cd19dcf 100644 --- a/vxgos/boards/fxcg50/generate.py +++ b/vxgos/boards/fxcg50/generate.py @@ -1,5 +1,5 @@ """ -generate - post-build script used to generate bootlaoder blob with KASLR +generate - post-build script used to generate bootlaoder blob with ASLR """ import os import sys @@ -31,13 +31,13 @@ def _patch_got_section(symfile, section): #--- def generate_aslr_blob(binpath, symtab, sectab): - """ generate bootloader final blob with KASLR + """ generate bootloader final blob with ASLR The objectif of this script is to generate the final bootloader blob with - KASLR. To performs this, we will performs 3 steps: + ASLR. To performs this, we will performs 3 steps: * generate the raw binary file of the bootloader (objcpy) - * generate the raw KALSR symbols table + * generate the raw ALSR symbols table * generate the complet blootloader image @args @@ -109,10 +109,10 @@ def generate_image(prefix_build, bootloader_path, _): image_size = len(image) # patch first two instruction of the image (see ) - image[0] = 0b00000000 # (MSB) nop - image[1] = 0b00001001 # (LSB) nop - image[2] = 0b11010000 # (MSB) mov.l @(1*, PC), r0 - image[3] = 0b00000001 # (LSB) mov.l @(1*, PC), r0 + image[0] = 0b00000000 # (MSB) nop + image[1] = 0b00001001 # (LSB) nop + image[2] = 0b11010000 # (MSB) mov.l @(1*, PC), r0 + image[3] = 0b00000001 # (LSB) mov.l @(1*, PC), r0 image[8] = (image_size & 0xff000000) >> 24 image[9] = (image_size & 0x00ff0000) >> 16 image[10] = (image_size & 0x0000ff00) >> 8 diff --git a/vxgos/boards/raspi3b/generate.py b/vxgos/boards/raspi3b/generate.py new file mode 100644 index 0000000..e816188 --- /dev/null +++ b/vxgos/boards/raspi3b/generate.py @@ -0,0 +1,124 @@ +""" +generate - post-build script used to generate bootlaoder blob with ASLR +""" +import os +import sys +import subprocess + +__all__ = [ + 'generate_aslr_blob', + 'generate_image' +] + +#--- +# Public +#--- + +def generate_aslr_blob(binpath, symtab, _): + """ generate bootloader final blob with ASLR + + The objectif of this script is to generate the final bootloader blob with + ASLR. To performs this, we will performs 3 steps: + + * generate the raw binary file of the bootloader (objcpy) + * generate the raw ALSR symbols table + * generate the complet blootloader image + + @args + > binpath (str) - binary file + > symtab (list) - list of all reloc information (readelf -r binpath) + > sectab (list) - list of all sections information (readelf -S binpath) + + @return + > Nothings + """ + print('- generate raw binary...') + if os.path.exists(f"{binpath}.raw"): + os.remove(f"{binpath}.raw") + cmd = f"aarch64-linux-gnu-objcopy -O binary -R .bss {binpath} {binpath}.raw" + subprocess.run( + cmd.split(), + capture_output=False, + check=False + ) + + print('- generate raw symtab...') + if os.path.exists(f"{binpath}.symtab"): + os.remove(f"{binpath}.symtab") + #need_patch_got = False + with open(f"{binpath}.symtab", 'xb') as symfile: + for i, sym in enumerate(symtab): + # direct 32bits address + #if sym[2] == 'R_SH_DIR32': + # print(f" > reloc 'R_SH_DIR32' sym at {sym[0]}") + # symfile.write(int(sym[0], base=16).to_bytes(4, 'big')) + # continue + # GOT related jump + if sym[2] == 'R_AARCH64_ABS64': + print(f" > [{i}] reloc {sym[2]} not implemented o(x_x)o") + need_patch_got = True + continue + if sym[2] in [ + 'R_AARCH64_ADR_PRE', + 'R_AARCH64_ADD_ABS', + 'R_AARCH64_ADR_GOT', + 'R_AARCH64_LD64_GO', + ]: + print(f" > [{i}] reloc {sym[2]} not tested yet o(x_x)o") + continue + if sym[2] not in [ + 'R_AARCH64_JUMP26', + 'R_AARCH64_CALL26', + 'R_AARCH64_ADR_PRE', + 'R_AARCH64_ADD_ABS', + 'R_AARCH64_ABS64', + 'R_AARCH64_ADR_GOT', + 'R_AARCH64_LD64_GO', + ]: + print(f" > [{i}] reloc {sym[2]} not supported") + sys.exit(84) + #if need_patch_got: + # _patch_got_section(symfile, sectab) + symfile.write(int('00000000', base=16).to_bytes(8, 'big')) + + print('- generate the full bootloader...') + if os.path.exists(f"{binpath}.bzImage"): + os.remove(f"{binpath}.bzImage") + with open(f"{binpath}.bzImage", 'xb') as bzimgfile: + with open(f"{binpath}.raw", 'rb') as rawbinfile: + bzimgfile.write(rawbinfile.read()) + with open(f"{binpath}.symtab", 'rb') as symtabfile: + bzimgfile.write(symtabfile.read()) + return f"{binpath}.bzImage" + + +def generate_image(prefix_build, bootloader_path, _): + """ generate complet image file + """ + # mov x0, #0x0000 = 0xd2800000 - 0xd29fffe0 + # mov x0, #0x0000, lsl 16 = 0xf2a00000 - 0xf2bfffe0 + # mov x0, #0x0000, lsl 32 = 0xf2c00000 - 0xf2dfffe0 + # mov x0, #0x0000, lsl 48 = 0xf2e00000 - 0xf2ffffe0 + + image = bytearray(0) + with open(bootloader_path, 'rb') as bootloaderfile: + image += bootloaderfile.read() + # (todo) os/kernel + image_size = len(image) + + print(image_size) + mov0 = 0xd2800000 | (((image_size & 0x000000000000ffff) >> 0) << 5) + mov1 = 0xf2a00000 | (((image_size & 0x00000000ffff0000) >> 16) << 5) + mov2 = 0xf2c00000 | (((image_size & 0x0000ffff00000000) >> 32) << 5) + mov3 = 0xf2e00000 | (((image_size & 0xffff000000000000) >> 48) << 5) + + image[0x40:0x44] = mov0.to_bytes(4, 'little') + image[0x44:0x48] = mov1.to_bytes(4, 'little') + image[0x48:0x4c] = mov2.to_bytes(4, 'little') + image[0x4c:0x50] = mov3.to_bytes(4, 'little') + + bzimage = f"{prefix_build}/vxgos.bzImage" + if os.path.exists(bzimage): + os.remove(bzimage) + with open(bzimage, 'xb') as bzimage: + bzimage.write(image) diff --git a/vxgos/bootloader/boards/fxcg50/compiles.toml b/vxgos/bootloader/boards/fxcg50/compiles.toml new file mode 100644 index 0000000..71cf473 --- /dev/null +++ b/vxgos/bootloader/boards/fxcg50/compiles.toml @@ -0,0 +1,23 @@ +VXDEV_TOOLCHAIN_PREFIX = 'sh-elf-vhex-' +VXDEV_TOOLCHAIN_PROCESSOR = 'sh' +VXDEV_CFLAGS = [ + '-Wall', + '-Wextra', + '-D__SUPPORT_FXCG50__', + '-ffreestanding', + '-nostdlib', + '-fPIE', + '-O1', + '-mb', + '-m4-nofpu', + '-fstrict-volatile-bitfields', +] +VXDEV_LDFLAGS = [ + '-static', + '-Wl,-Map=map', + '-Wl,--build-id=none', + '-Wl,--emit-relocs', +] +VXDEV_LIBS = [ + '-lgcc', +] diff --git a/vxgos/bootloader/boards/fxcg50/src/console/handle.c b/vxgos/bootloader/boards/fxcg50/src/console/key_handle.c similarity index 100% rename from vxgos/bootloader/boards/fxcg50/src/console/handle.c rename to vxgos/bootloader/boards/fxcg50/src/console/key_handle.c diff --git a/vxgos/bootloader/boards/fxcg50/src/primary.S b/vxgos/bootloader/boards/fxcg50/src/primary.S index 45d5014..80bf422 100644 --- a/vxgos/bootloader/boards/fxcg50/src/primary.S +++ b/vxgos/bootloader/boards/fxcg50/src/primary.S @@ -6,11 +6,11 @@ We are currently virtualized as a common program (addin) at 0x00300000, but the code currently executed is physically fragmented through the ROM. So, we cannot -perform KASLR self-relocation here. +perform ASLR self-relocation here. The first thing we need to do is find the "user" RAM allocated by Casio (by analyzing the TLB) and then performs a "self-translation" into this place. -After that, we will be able to perform KASLR self-relocation and classic +After that, we will be able to perform ASLR self-relocation and classic "kernel" bootstrapping.. */ function(__fxcg50_primary_bootloader): @@ -19,7 +19,7 @@ function(__fxcg50_primary_bootloader): ! *CRITICAL* ! ! The next two instructions will be patched *DURING COMPILE TIME* with the - ! complete image size (bootloader, KASLR, kernel, OS,...) as follows: + ! complete image size (bootloader, ASLR, kernel, OS,...) as follows: ! > mov.l complet_image_size, r0 ! > nop ! If not patched, the code will just return and indicate to Casio not to diff --git a/vxgos/bootloader/boards/fxcg50/src/start.S b/vxgos/bootloader/boards/fxcg50/src/start.S index 61a0e35..16569f8 100644 --- a/vxgos/bootloader/boards/fxcg50/src/start.S +++ b/vxgos/bootloader/boards/fxcg50/src/start.S @@ -4,7 +4,7 @@ /* ___fxcg50_bootloader_start() : real bootstrap entry -Now we are in the URAM we can performs KASLR patching, setup stack and involve +Now we are in the URAM we can performs ASLR patching, setup stack and involve the first high-level C code which will perform kernel setup. The primary (fake) bootloader (previous operations) have setup some arg: @@ -23,9 +23,9 @@ function(__fxcg50_bootloader_start): #define image_size r6 ! --- - ! KASLR application + ! ASLR application ! - ! perform KASLR patch by using the symbols table information injected + ! perform ASLR patch by using the symbols table information injected ! during bootloader build steps at the end of the bootloader code marked ! with ___bootloader_code_end. ! @@ -46,21 +46,21 @@ function(__fxcg50_bootloader_start): ! - we MUST perform patching using P2 (uncachable) area to avoid ! inconsistancy behaviour with the cache. ! - symbols are relocalize through P1 (cachable) area -kaslr_symbol_patch_loop: +aslr_symbol_patch_loop: mov.l @r0, r8 tst r8, r8 - bt kaslr_commit + bt aslr_commit add r2, r8 mov.l @r8, r9 add r1, r9 mov.l r9, @r8 mov.l r8, @r0 add #4, r0 - bra kaslr_symbol_patch_loop + bra aslr_symbol_patch_loop nop -kaslr_commit: - ! Now that KASLR symbols has been updated using uncachable area (P2), we +aslr_commit: + ! Now that ASLR symbols has been updated using uncachable area (P2), we ! need to invalitate all Operands Cache entry that the MPU have possibly ! setup to avoid inconsistant `mov.x` behaviour ! @note diff --git a/vxgos/bootloader/boards/raspi3b/compiles.toml b/vxgos/bootloader/boards/raspi3b/compiles.toml new file mode 100644 index 0000000..236eaed --- /dev/null +++ b/vxgos/bootloader/boards/raspi3b/compiles.toml @@ -0,0 +1,18 @@ +VXDEV_TOOLCHAIN_PREFIX = 'aarch64-linux-gnu-' +VXDEV_TOOLCHAIN_PROCESSOR = 'aarch64' +VXDEV_CFLAGS = [ + '-Wall', + '-Wextra', + '-D__SUPPORT_RASPI3B__', + '-ffreestanding', + '-nostdlib', + '-fPIE', + '-O1', + '-fstrict-volatile-bitfields', +] +VXDEV_LDFLAGS = [ + '-static', + '-Wl,-Map=map', + '-Wl,--build-id=none', + '-Wl,--emit-relocs', +] diff --git a/vxgos/bootloader/boards/raspi3b/src/bios/dinfo.c b/vxgos/bootloader/boards/raspi3b/src/bios/dinfo.c new file mode 100644 index 0000000..5b1dbf2 --- /dev/null +++ b/vxgos/bootloader/boards/raspi3b/src/bios/dinfo.c @@ -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 = 0; + if (height != NULL) + *height = 0; +} diff --git a/vxgos/bootloader/boards/raspi3b/src/bios/dpixel.c b/vxgos/bootloader/boards/raspi3b/src/bios/dpixel.c new file mode 100644 index 0000000..f0a5151 --- /dev/null +++ b/vxgos/bootloader/boards/raspi3b/src/bios/dpixel.c @@ -0,0 +1,13 @@ +#include "bootloader/bios.h" + +//--- +// Public +//--- + +/* _bios_dpixel() : dpixel wrapper */ +void _bios_dpixel(int x, int y, int color) +{ + (void)x; + (void)y; + (void)color; +} diff --git a/vxgos/bootloader/boards/raspi3b/src/bios/dupdate.c b/vxgos/bootloader/boards/raspi3b/src/bios/dupdate.c new file mode 100644 index 0000000..be1c065 --- /dev/null +++ b/vxgos/bootloader/boards/raspi3b/src/bios/dupdate.c @@ -0,0 +1,11 @@ +#include "bootloader/bios.h" + +//--- +// Public +//--- + +/* _bios_dupdate() : small R61524 driver */ +void _bios_dupdate(void) +{ + ; +} diff --git a/vxgos/bootloader/boards/raspi3b/src/bios/free.c b/vxgos/bootloader/boards/raspi3b/src/bios/free.c new file mode 100644 index 0000000..089ba56 --- /dev/null +++ b/vxgos/bootloader/boards/raspi3b/src/bios/free.c @@ -0,0 +1,11 @@ +#include "bootloader/bios.h" + +//--- +// Public +//--- + +/* _bios_free() : free allocated memory */ +void _bios_free(void *ptr) +{ + (void)ptr; +} diff --git a/vxgos/bootloader/boards/raspi3b/src/bios/malloc.c b/vxgos/bootloader/boards/raspi3b/src/bios/malloc.c new file mode 100644 index 0000000..b7ebb16 --- /dev/null +++ b/vxgos/bootloader/boards/raspi3b/src/bios/malloc.c @@ -0,0 +1,12 @@ +#include "bootloader/bios.h" + +//--- +// Public +//--- + +/* _bios_malloc() : memory allocator */ +void *_bios_malloc(size_t size) +{ + (void)size; + return NULL; +} diff --git a/vxgos/bootloader/boards/raspi3b/src/console/key_handle.c b/vxgos/bootloader/boards/raspi3b/src/console/key_handle.c new file mode 100644 index 0000000..6e8956b --- /dev/null +++ b/vxgos/bootloader/boards/raspi3b/src/console/key_handle.c @@ -0,0 +1,16 @@ + +//--- +// Public +//--- + +/* console_key_handle_special() : handle special key handling */ +int console_key_handle_special(void) +{ + return -1; +} + +/* console_key_handle(): Update the internal buffer with the given key code */ +int console_key_handle(void) +{ + return -1; +} diff --git a/vxgos/bootloader/boards/raspi3b/src/console/keysc.c b/vxgos/bootloader/boards/raspi3b/src/console/keysc.c new file mode 100644 index 0000000..991fadc --- /dev/null +++ b/vxgos/bootloader/boards/raspi3b/src/console/keysc.c @@ -0,0 +1,10 @@ + +//--- +// Public +//--- + +/* console_key_get() : small one-shot key waiter */ +int console_key_get(void) +{ + return -1; +} diff --git a/vxgos/bootloader/boards/raspi3b/src/image.S b/vxgos/bootloader/boards/raspi3b/src/image.S new file mode 100644 index 0000000..df6ae2b --- /dev/null +++ b/vxgos/bootloader/boards/raspi3b/src/image.S @@ -0,0 +1,46 @@ +.section .bootloader.header, "ax" +.global __aarch64_image_hdr + +/* __aarch64_image_hdr - fake linux boot header + + This structure is placed at the first start of the final image binary have + can have multiple role depending on the host which the project is executed, + but generaly it's used to indicate how the image must be loaded in physical + memory + + Also note that is the raspi find this header, will be loaded a 0x20000000 + instead of the classical 0x80000 which will allows us to performs the self + translation as we want */ +__aarch64_image_hdr: + + // This is a harmless instruction that also happens to have "MZ" as its + // first two (little-endian) bytes, which is the EFI (PE-COFF) magic + // number. Some boot loaders and file utility look for this, apparently. + // @note + // * instruction = if (!N) { x18 -= 0 } else { N:Z:C:V = 0x0d } + // * pl = Conditional Code = Plus, Positive or zero = !N + ccmp x18, #0x0, #0xd, pl + + // branch to the bootloader bootstrap entry + b __raspi3b_bootloader_start + + // Image load offset + .quad 0x0000000000000000 + + // Image size. + // This information is patched *DURING COMPILE TIME* + .quad 0x0000000000000000 + + // Loading Flags. + // @note + // * [0b***0] select little-endian + // * [0b*01*] select kernel page size of 4ko + // * [0b1***] select only 2Mio-aligned loading address but random position + .quad 0b1010 + + // Reserved and magic information + .quad 0x0000000000000000 + .quad 0x0000000000000000 + .quad 0x0000000000000000 + .ascii "ARM\x64" + .int 0x00000000 diff --git a/vxgos/bootloader/boards/raspi3b/src/start.S b/vxgos/bootloader/boards/raspi3b/src/start.S new file mode 100644 index 0000000..8bb234d --- /dev/null +++ b/vxgos/bootloader/boards/raspi3b/src/start.S @@ -0,0 +1,140 @@ +.section .bootloader.pre_text, "ax" +.global __raspi3b_bootloader_start + +.extern __aarch64_image_hdr + +__raspi3b_bootloader_start: + + // --- + // *CRITICAL* + // + // The next four instructions will be patched *DURING COMPILE TIME* with + // the complete image size (bootloader, ASLR, kernel, OS,...) as follows: + // > mov x0, # + // > mov x0, #, lsl 16 + // > mov x0, #, lsl 32 + // > mov x0, #, lsl 48 + // If not patched, the code will just wait a manual reset + // --- + +_patch_trap: + wfe + b _patch_trap + nop + nop + +translation_entry: + + // --- + // prepare alias + // --- + #define image_size x0 + #define ram_base_addr x1 + #define rom_base_addr x2 + + // --- + // handle secondary CPUs + // + // For now, each secondary CPUs will hang in a infinite wait loop. This + // will be changed as soon as the bootloader is stable + // --- + + mrs x3, mpidr_el1 + and x3, x3, #3 + cbz x3, _primary_continue +_secondary_wait_loop: + wfe + b _secondary_wait_loop +_primary_continue: + + // --- + // Translate the image in RAM + // + // For now, no check is performed for the RAM size and all this part relies + // on material assumption + // + // @note + // - 64 = the size of the image.S file + // - ram_base_addr is hardcoded here + // + // @todo + // - check if we are already in RAM + // - detect RAM geometry (size, start and end) + // - ramdom translation offset + // --- + + adr x3, patch_aslr_symbols + add x3, x3, #(__raspi3b_bootloader_start - patch_aslr_symbols - 64) + mov rom_base_addr, x3 + mov ram_base_addr, 0x00000000 + + // for now, assume that we will always be loaded in RAM + mov ram_base_addr, rom_base_addr + +#if 0 + mov x4, image_size + mov x5, rom_base_addr + mov x6, ram_base_addr +_ram_translation_loop: + cbz x4, _ram_translation_validate + ldr x7, [x5], #16 + str x7, [x6], #16 + sub x4, x4, #16 + cbnz x4, _ram_translation_loop + +_ram_translation_validate: + wfe + b _ram_translation_validate +#endif + + // --- + // Patch ASLR + // + // perform ASLR patch by using the symbols table information injected + // during bootloader build steps at the end of the bootloader code marked + // with ___bootloader_code_end. + // + // The content of the table has been generated during post-compiling script + // --- + +patch_aslr_symbols: + + // The table symbol is not aready resolved (its our job), we must manually + // calculate the real address of the symbols table + adr x4, __bootloader_code_end + add x4, ram_base_address +_aslr_symbol_patch_loop: + ldr x5, [x4], #8 + cbz x5, _bootloader_panik + ldr x6, [x5] + add x6, ram_base_address + str x6, [x5] + b patch_aslr_symbols + // TODO + + // --- + // RAM translation + // --- + + // TODO : invalidate cache + // TODO : jump to the relocalized RAM + + // --- + // Setup stack + // --- + + // TODO + + // --- + // High-level bootloader invokation + // --- + + // TODO + + // --- + // Bootloader panik if returned + // --- + +_bootloader_panik: + wfe + b _bootloader_panik diff --git a/vxgos/bootloader/bootloader.ld b/vxgos/bootloader/bootloader.ld index cc1eabd..33a15ec 100644 --- a/vxgos/bootloader/bootloader.ld +++ b/vxgos/bootloader/bootloader.ld @@ -15,6 +15,7 @@ SECTIONS /* explicitly isolate the "pre text" code which should be executed first */ .bootloader : { + KEEP(*(.bootloader.header)) KEEP(*(.bootloader.pre_text)) KEEP(*(.bootloader.text)) } : vxgos_load @@ -36,7 +37,13 @@ SECTIONS .bss ALIGN(16) (NOLOAD) : { *(.bss) *(.bss.*) + . = ALIGN(16) ; + + __bootloader_stack = . ; + . = . + (16 * 1024) ; + + . = ALIGN(16); } /* readable / writable data (must be 16-aligned) */ @@ -68,13 +75,13 @@ SECTIONS * ("_DYNAMIC") into '.got', as required by ABI, and three empty entry on * some architecture. */ .got : { *(.got.plt) *(.got) } - ASSERT( - SIZEOF(.got) <= 4 * 8, + /*ASSERT( + SIZEOF(.got) <= (4 * 8), "'.got' should contain only ABI-required entries" - ) + )*/ /* indicate the end of the bootloader - * this symbols will be used to resolve KASLR patching during runtime */ + * this symbols will be used to resolve ASLR patching during runtime */ ___bootloader_code_end = . ; /* unwanted sections */ @@ -93,5 +100,6 @@ SECTIONS *(.eh_frame) *(.comment) *(.interp) + *(.note.*) } } diff --git a/vxsdk.toml b/vxsdk.toml index 1fd8237..6f97087 100644 --- a/vxsdk.toml +++ b/vxsdk.toml @@ -1,75 +1,13 @@ [project] -name = 'vxkernel' +name = 'vxkernel' version = '0.7.0' -type = 'lib' -target = [ +target = [ 'fxcg50', - 'sdl2' + 'raspi3b', ] [build] -#configure = './vxdev configure' -build = '/usr/bin/env python3 ./scripts/vxdev build' -#install = '/usr/bin/env python3 ./scripts/vxdev install' -#uninstall = '/usr/bin/env python3 ./scripts/vxdev uninstall' +build = '/usr/bin/env python3 ./scripts/vxdev build --verbose' -[converter] -assets_prefix = [ - 'kernel/assets' -] - -[fxcg50] - [fxcg50.dependencies] - sh-elf-vhex = 'master@superh' - [fxcg50.env] - VXSDK_COMMON_BUILD_CFLAGS = [ - '-Wall', - '-Wextra', - '-D__SUPPORT_FXCG50__', - '-ffreestanding', - '-nostdlib', - '-fPIE', - '-O1', - '-mb', - '-m4-nofpu', - '-fstrict-volatile-bitfields', -# '-Wa,--dsp', -# '-fstack-protector-all', - ] - VXSDK_PRIVATE_BUILD_LDFLAGS = [ - '-static', - '-Wl,-Map=map', - '-Wl,--build-id=none', - '-Wl,--emit-relocs', - ] - VXSDK_PRIVATE_BUILD_LIBS = [ - '@COMMON@', - '@sh-elf-vhex@', -# '-lc', - '-lgcc', - ] -# VXSDK_PUBLIC_BUILD_LDFLAGS = [ -# '-T {VXSDK_CURRENT_SOURCE_DIR}/boards/fxcg50/fxcg50.ld', -# '-static', -# '-Wl,-q' -# ] - -[sdl2] - [sdl2.env] - VXSDK_COMMON_BUILD_CFLAGS = [ - '@COMMON@', - '-D_GNU_SOURCE', - '-D__VXKERNEL_SUPPORT_SDL2__', - '-g3', - ] - VXSDK_PUBLIC_BUILD_LIBS = [ - '@COMMON@', - '-Wl,--whole-archive', - '-lvxkernel', - '-Wl,--no-whole-archive', - '-lSDL2', - '-lm' - ] - VXSDK_PUBLIC_BUILD_LDFLAGS = [ - '-T {VXSDK_CURRENT_SOURCE_DIR}/boards/sdl2/sdl2.ld', - ] +[fxcg50.dependencies] +sh-elf-vhex = 'master@superh'