From 1ba806ca1bdf2ce03c749d9a050d1c0bc8fe003f Mon Sep 17 00:00:00 2001 From: Giacomo Tesio Date: Fri, 25 Nov 2016 13:41:57 +0000 Subject: [PATCH] new development tools --- QA.sh | 32 +- buildtools.sh | 67 +++- cross/init.sh | 192 +++++++++ cross/patch/MakeNothing.in | 4 + .../patch/autoconf/build-aux/git-version-gen | 2 + cross/patch/binutils/bfd/config.bfd | 7 + cross/patch/binutils/gas/configure.tgt | 3 + cross/patch/binutils/ld/Makefile.am | 8 + cross/patch/binutils/ld/configure.tgt | 25 ++ .../ld/emulparams/elf_i386_jehanne.sh | 4 + .../ld/emulparams/elf_x86_64_jehanne.sh | 4 + cross/patch/gcc/config.sub | 3 + .../patch/gcc/contrib/download_prerequisites | 71 ++++ cross/patch/gcc/fixincludes/mkfixinc.sh | 1 + cross/patch/gcc/gcc/config.gcc | 31 ++ cross/patch/gcc/gcc/config/jehanne.h | 88 +++++ cross/patch/gcc/libgcc/config.host | 4 + cross/patch/gcc/libgcc/config.host.sed | 3 + cross/patch/gcc/libstdc++-v3/crossconfig.m4 | 6 + cross/src/.gitignore | 7 + cross/src/fetch.json | 62 +++ cross/tmp/.gitignore | 2 + cross/toolchain/.gitignore | 3 + devshell.sh | 4 + disk-boot-update.sh | 50 +++ disk-create.sh | 124 ++++++ disk-get.sh | 48 +++ disk-setup/configure-hjfs | 15 + disk-setup/flproto | 6 + disk-setup/syslinux.cfg | 19 + disk-setup/venti.conf | 4 + disk-update.sh | 48 +++ drawterm.sh | 7 + gdbinit | 290 ++++++++++++++ runDisk.sh | 74 ++++ runOver9P.sh | 42 +- src/jehanne/cmd/build/build.go | 150 ++++++- src/jehanne/cmd/build/codegen.go | 14 - src/jehanne/cmd/fetch/fetch.go | 197 +++++++++ src/jehanne/cmd/ksyscalls/ksyscalls.go | 374 ++++++++++++++++++ src/jehanne/cmd/mksys/mksys.go | 4 +- src/jehanne/cmd/usyscalls/usyscalls.go | 291 ++++++++++++++ 42 files changed, 2346 insertions(+), 44 deletions(-) create mode 100755 cross/init.sh create mode 100644 cross/patch/MakeNothing.in create mode 100755 cross/patch/autoconf/build-aux/git-version-gen create mode 100644 cross/patch/binutils/bfd/config.bfd create mode 100644 cross/patch/binutils/gas/configure.tgt create mode 100644 cross/patch/binutils/ld/Makefile.am create mode 100644 cross/patch/binutils/ld/configure.tgt create mode 100644 cross/patch/binutils/ld/emulparams/elf_i386_jehanne.sh create mode 100644 cross/patch/binutils/ld/emulparams/elf_x86_64_jehanne.sh create mode 100644 cross/patch/gcc/config.sub create mode 100644 cross/patch/gcc/contrib/download_prerequisites create mode 100644 cross/patch/gcc/fixincludes/mkfixinc.sh create mode 100644 cross/patch/gcc/gcc/config.gcc create mode 100644 cross/patch/gcc/gcc/config/jehanne.h create mode 100644 cross/patch/gcc/libgcc/config.host create mode 100644 cross/patch/gcc/libgcc/config.host.sed create mode 100644 cross/patch/gcc/libstdc++-v3/crossconfig.m4 create mode 100644 cross/src/.gitignore create mode 100644 cross/src/fetch.json create mode 100644 cross/tmp/.gitignore create mode 100644 cross/toolchain/.gitignore create mode 100755 disk-boot-update.sh create mode 100755 disk-create.sh create mode 100755 disk-get.sh create mode 100755 disk-setup/configure-hjfs create mode 100644 disk-setup/flproto create mode 100644 disk-setup/syslinux.cfg create mode 100644 disk-setup/venti.conf create mode 100755 disk-update.sh create mode 100755 drawterm.sh create mode 100644 gdbinit create mode 100755 runDisk.sh create mode 100644 src/jehanne/cmd/fetch/fetch.go create mode 100644 src/jehanne/cmd/ksyscalls/ksyscalls.go create mode 100644 src/jehanne/cmd/usyscalls/usyscalls.go diff --git a/QA.sh b/QA.sh index 89554eb..7be0a9d 100755 --- a/QA.sh +++ b/QA.sh @@ -1,7 +1,13 @@ #!/bin/bash + +if [ "$JEHANNE" = "" ]; then + echo ./hacking/QA.sh requires the shell started by ./hacking/devshell.sh + exit 1 +fi + trap : 2 -$JEHANNE/hacking/bin/ufs -root=$JEHANNE & +$JEHANNE/hacking/bin/ufs -d=0 -root=$JEHANNE & ufspid=$! export machineflag=pc @@ -14,23 +20,41 @@ if [ "$(uname)" = "Linux" ] && [ -e /dev/kvm ]; then fi fi -cd $JEHANNE/arch/$ARCH/kern/ +if [ "$DISK" = "" ]; then + export DISK=$JEHANNE/hacking/sample-disk.img +fi + +if [ -a $DISK ]; then + bootDisk="-device ahci,id=ahci -drive id=boot,file=$DISK,index=0,cache=writeback,if=none -device ide-drive,drive=boot,bus=ahci.0" +fi + +if [ "$KERNDIR" = "" ]; then + KERNDIR=$JEHANNE/arch/$ARCH/kern/ +fi +if [ "$KERNEL" = "" ]; then + KERNEL=jehanne.32bit +fi + +cd $KERNDIR read -r cmd < ../drawterm.build.log 2>&1 && + CONF=unix make >> ../drawterm.build.log 2>&1 && + mv drawterm $UTILITIES/bin + ) + STATUS="$?" + if [ $STATUS -eq "0" ] + then + rm $UTILITIES/third_party/src/github.com/0intro/drawterm.build.log + echo "done." + else + echo "FAIL" + cat $UTILITIES/third_party/src/github.com/0intro/drawterm.build.log + exit $STATUS + fi +fi +exit $STATUS diff --git a/cross/init.sh b/cross/init.sh new file mode 100755 index 0000000..344c3cc --- /dev/null +++ b/cross/init.sh @@ -0,0 +1,192 @@ +#!/bin/bash + +# This file is part of Jehanne. +# +# Copyright (C) 2016 Giacomo Tesio +# +# Jehanne is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 2 of the License. +# +# Jehanne is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Jehanne. If not, see . + +if [ "$JEHANNE" = "" ]; then + echo $0 requires the shell started by ./hacking/devshell.sh + exit 1 +fi + +# +# WELLCOME TO HELL ! ! ! +# + +# If you want to understand _WHY_ Jehanne exists, you should try to +# create a GCC crosscompiler in Debian without requiring root access or Tex. +# And this despite the extreme quality of Debian GNU/Linux! + +# fetch all sources +(cd src && fetch) + +# To create a Jehanne version of GCC, we need specific OUTDATED versions +# of Autotools that won't compile easily in a modern Linux distro. + +function failOnError { + # $1 -> exit status on a previous command + # $2 -> task description + if [ $1 -ne 0 ]; then + echo "ERROR $2" + exit $1 + fi +} + + +# build m4 1.4.14 +# - workaround a bug in lib/stdio.in.h, see http://lists.gnu.org/archive/html/bug-m4/2012-08/msg00008.html +# - workaround a bug in src/m4.h, see https://bugs.archlinux.org/task/19829 +# both bugs exists thanks to changes in external code +if [ ! -f tmp/bin/m4 ]; then +( + cd src/m4 && + sed -i '/_GL_WARN_ON_USE (gets/d' lib/stdio.in.h && + ( grep -q '#include ' src/m4.h || sed -i 's:.*\#include .*:&\n#include :g' src/m4.h ) && + ./configure --prefix=$JEHANNE/hacking/cross/tmp && + make && make install +) +failOnError $? "building m4" +fi +# build autoconf 2.64 +# - hack git-version-gen to avoid the -dirty flag in version on make +# - autoreconf +# - disable doc build +# - disable man build +if [ ! -f tmp/bin/autoconf ]; then +( + cd src/autoconf && + cp ../../patch/autoconf/build-aux/git-version-gen build-aux/git-version-gen && + autoreconf && + ./configure --prefix=$JEHANNE/hacking/cross/tmp && + cp ../../patch/MakeNothing.in ../autoconf/doc/Makefile.in && + cp ../../patch/MakeNothing.in ../autoconf/man/Makefile.in && + make && make install +) +failOnError $? "building autoconf" +fi +# build automake 1.11.1 +# - autoreconf to avoid conflicts with installed automake +# - automake; configure; make (that will fail) and then automake again +# to workaround this hell +# - disable doc build +# - disable disable tests build +if [ ! -f tmp/bin/automake ]; then +( + cd src/automake && + echo > doc/Makefile.am && + touch NEWS AUTHORS && autoreconf -i && + automake && + (./configure --prefix=$JEHANNE/hacking/cross/tmp && make; automake) && + ./configure --prefix=$JEHANNE/hacking/cross/tmp && + cp ../../patch/MakeNothing.in doc/Makefile.in && + cp ../../patch/MakeNothing.in tests/Makefile.in && + make && make install +) +failOnError $? "building automake" +fi +# build libtool 2.4 +if [ ! -f tmp/bin/libtool ]; then +( + cd src/libtool && + ./configure --prefix=$JEHANNE/hacking/cross/tmp && + make && make install +) +failOnError $? "building libtool" +fi + +# FINALLY! We have our OUTDATED autotools in tmp/bin +export PATH=$JEHANNE/hacking/cross/tmp/bin:$PATH +export CROSS_DIR=$JEHANNE/hacking/cross +if [ "$BUILD_DIRS_ROOT" = "" ]; then + export BUILD_DIRS_ROOT=$JEHANNE/hacking/cross/src +fi +if [ ! -d $BUILD_DIRS_ROOT ]; then + mkdir $BUILD_DIRS_ROOT +fi + +function dynpatch { + # $1 -> path from cross/src + # $2 -> string to search + ( cd $JEHANNE/hacking/cross/src && + grep -q jehanne $1 || + sed -n -i -e "/$2/r ../patch/$1" -e '1x' -e '2,${x;p}' -e '${x;p}' $1 + ) +} + +# Patch and build binutils +if [ "$BINUTILS_BUILD_DIR" = "" ]; then + export BINUTILS_BUILD_DIR=$BUILD_DIRS_ROOT/build-binutils +fi +if [ ! -d $BINUTILS_BUILD_DIR ]; then + mkdir $BINUTILS_BUILD_DIR +fi +if [ ! -f toolchain/bin/x86_64-jehanne-ar ]; then +( + sed -i '/jehanne/b; /ELF_TARGET_ID/,/elf_backend_can_gc_sections/s/0x200000/0x1000 \/\/ jehanne hack/g' src/binutils/bfd/elf64-x86-64.c && + sed -i '/jehanne/b; s/| -tirtos/| -tirtos* | -jehanne/g' src/binutils/config.sub && + dynpatch 'binutils/bfd/config.bfd' '\# END OF targmatch.h' && + dynpatch 'binutils/gas/configure.tgt' ' i860-\*-\*)' && + ( grep -q jehanne src/binutils/ld/configure.tgt || patch -p1 < patch/binutils/ld/configure.tgt ) && + cp patch/binutils/ld/emulparams/elf_x86_64_jehanne.sh src/binutils/ld/emulparams/ && + cp patch/binutils/ld/emulparams/elf_i386_jehanne.sh src/binutils/ld/emulparams/ && + dynpatch 'binutils/ld/Makefile.am' 'eelf_x86_64.c: ' && + (grep 'eelf_i386_jehanne.c \\' src/binutils/ld/Makefile.am || sed -i 's/.*ALL_EMULATION_SOURCES = \\.*/&\n\teelf_i386_jehanne.c \\/' src/binutils/ld/Makefile.am) && + (grep 'eelf_x86_64_jehanne.c \\' src/binutils/ld/Makefile.am || sed -i 's/.*ALL_64_EMULATION_SOURCES = \\.*/&\n\teelf_x86_64_jehanne.c \\/' src/binutils/ld/Makefile.am) && + cd src/binutils/ld && automake && cd ../ && + cd $BINUTILS_BUILD_DIR && + $CROSS_DIR/src/binutils/configure --disable-shared --enable-static --prefix=$JEHANNE/hacking/cross/toolchain --with-sysroot=$JEHANNE --target=x86_64-jehanne --enable-interwork --enable-multilib --disable-nls --disable-werror && + cp $CROSS_DIR/patch/MakeNothing.in $CROSS_DIR/src/binutils/bfd/doc/Makefile && + cp $CROSS_DIR/patch/MakeNothing.in $CROSS_DIR/src/binutils/bfd/po/Makefile && + cp $CROSS_DIR/patch/MakeNothing.in $CROSS_DIR/src/binutils/gas/doc/Makefile && + cp $CROSS_DIR/patch/MakeNothing.in $CROSS_DIR/src/binutils/binutils/doc/Makefile && + make MAKEINFO=true MAKEINFOHTML=true TEXI2DVI=true TEXI2PDF=true DVIPS=true && + make MAKEINFO=true MAKEINFOHTML=true TEXI2DVI=true TEXI2PDF=true DVIPS=true install +) +failOnError $? "building binutils" +fi + +# Patch and build gcc +if [ "$GCC_BUILD_DIR" = "" ]; then + export GCC_BUILD_DIR=$BUILD_DIRS_ROOT/build-gcc +fi +if [ ! -d $GCC_BUILD_DIR ]; then + mkdir $GCC_BUILD_DIR +fi +( + pwd && + ( grep -q jehanne src/gcc/gcc/config.gcc || patch -p1 < patch/gcc/gcc/config.gcc ) && + cd src && + cp ../patch/gcc/contrib/download_prerequisites gcc/contrib/download_prerequisites && + ( cd gcc && ./contrib/download_prerequisites ) && + dynpatch 'gcc/config.sub' '-none)' && + cp ../patch/gcc/gcc/config/jehanne.h gcc/gcc/config && + dynpatch 'gcc/libstdc++-v3/crossconfig.m4' ' \*)' && + cd gcc/libstdc++-v3 && autoconf -i && cd ../../ && + ( pwd && grep -q jehanne gcc/libgcc/config.host || + sed -i -f ../patch/gcc/libgcc/config.host.sed gcc/libgcc/config.host + ) && + dynpatch 'gcc/fixincludes/mkfixinc.sh' 'i\?86-\*-cygwin\*' && + cd $GCC_BUILD_DIR && + $CROSS_DIR/src/gcc/configure --disable-shared --enable-static --target=x86_64-jehanne --prefix=$JEHANNE/hacking/cross/toolchain --with-sysroot=$JEHANNE --enable-languages=c,c++ && + make MAKEINFO=true MAKEINFOHTML=true TEXI2DVI=true TEXI2PDF=true DVIPS=true all-gcc all-target-libgcc && + make MAKEINFO=true MAKEINFOHTML=true TEXI2DVI=true TEXI2PDF=true DVIPS=true install-gcc install-target-libgcc +# && +# make MAKEINFO=true MAKEINFOHTML=true TEXI2DVI=true TEXI2PDF=true DVIPS=true all-target-libstdc++-v3 && +# make MAKEINFO=true MAKEINFOHTML=true TEXI2DVI=true TEXI2PDF=true DVIPS=true install-target-libstdc++-v3 +) +failOnError $? "building gcc" + +# add sh +ln -sf /bin/bash $JEHANNE/hacking/cross/toolchain/bin/x86_64-jehanne-sh diff --git a/cross/patch/MakeNothing.in b/cross/patch/MakeNothing.in new file mode 100644 index 0000000..5f28461 --- /dev/null +++ b/cross/patch/MakeNothing.in @@ -0,0 +1,4 @@ +all: + echo "make all does nothing HERE" +install: + echo "make install does nothing HERE" diff --git a/cross/patch/autoconf/build-aux/git-version-gen b/cross/patch/autoconf/build-aux/git-version-gen new file mode 100755 index 0000000..26bab70 --- /dev/null +++ b/cross/patch/autoconf/build-aux/git-version-gen @@ -0,0 +1,2 @@ +#!/bin/sh +echo "2.64" | tr -d '\012' diff --git a/cross/patch/binutils/bfd/config.bfd b/cross/patch/binutils/bfd/config.bfd new file mode 100644 index 0000000..d707602 --- /dev/null +++ b/cross/patch/binutils/bfd/config.bfd @@ -0,0 +1,7 @@ +#ifdef BFD64 + x86_64-*-jehanne*) + targ_defvec=x86_64_elf64_vec + targ_selvecs=i386_elf32_vec + want64=true + ;; +#endif diff --git a/cross/patch/binutils/gas/configure.tgt b/cross/patch/binutils/gas/configure.tgt new file mode 100644 index 0000000..238f7e8 --- /dev/null +++ b/cross/patch/binutils/gas/configure.tgt @@ -0,0 +1,3 @@ + i386-*-jehanne*) fmt=elf em=gnu ;; + + diff --git a/cross/patch/binutils/ld/Makefile.am b/cross/patch/binutils/ld/Makefile.am new file mode 100644 index 0000000..35a321e --- /dev/null +++ b/cross/patch/binutils/ld/Makefile.am @@ -0,0 +1,8 @@ +eelf_i386_jehanne.c: $(srcdir)/emulparams/elf_i386_jehanne.sh \ + $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + ${GENSCRIPTS} elf_i386_jehanne "$(tdir_elf_i386_jehanne)" + +eelf_x86_64_jehanne.c: $(srcdir)/emulparams/elf_x86_64_jehanne.sh \ + $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + ${GENSCRIPTS} elf_x86_64_jehanne "$(tdir_elf_x86_64_jehanne)" + diff --git a/cross/patch/binutils/ld/configure.tgt b/cross/patch/binutils/ld/configure.tgt new file mode 100644 index 0000000..a87ce56 --- /dev/null +++ b/cross/patch/binutils/ld/configure.tgt @@ -0,0 +1,25 @@ +diff --git a/src/binutils/ld/configure.tgt b/src/binutils/ld/configure.tgt +index 6b6bbf2..29b5f30 100644 +--- a/src/binutils/ld/configure.tgt ++++ b/src/binutils/ld/configure.tgt +@@ -383,6 +383,9 @@ x86_64-*-nacl*) targ_emul=elf32_x86_64_nacl + targ_extra_libpath=$targ_extra_emuls + tdir_elf_i386_nacl=`echo ${targ_alias} | sed -e 's/x86_64/i386/'` + ;; ++x86_64*-jehanne*) targ_emul=elf_x86_64_jehanne ++ targ_extra_emuls="elf_i386_jehanne elf_x86_64 elf_i386" ++ ;; + i860-*-coff) targ_emul=coff_i860 ;; + i860-stardent-sysv4* | i860-stardent-elf*) + targ_emul=elf32_i860 +@@ -852,6 +855,10 @@ ia64-*-aix*) + NATIVE_LIB_DIRS='/usr/local/lib /usr/lib/ia64l64 /lib /usr/lib' + ;; + ++x86_64-*-jehanne*) ++ NATIVE_LIB_DIRS='/arch/amd64/lib' ++ ;; ++ + sparc*-*-solaris2*) + NATIVE_LIB_DIRS='/usr/local/lib /usr/ccs/lib /lib /usr/lib' + ;; diff --git a/cross/patch/binutils/ld/emulparams/elf_i386_jehanne.sh b/cross/patch/binutils/ld/emulparams/elf_i386_jehanne.sh new file mode 100644 index 0000000..54decda --- /dev/null +++ b/cross/patch/binutils/ld/emulparams/elf_i386_jehanne.sh @@ -0,0 +1,4 @@ +. ${srcdir}/emulparams/elf_i386.sh +GENERATE_SHLIB_SCRIPT= +GENERATE_PIE_SCRIPT=yes +ENTRY=_main diff --git a/cross/patch/binutils/ld/emulparams/elf_x86_64_jehanne.sh b/cross/patch/binutils/ld/emulparams/elf_x86_64_jehanne.sh new file mode 100644 index 0000000..dd2b5c7 --- /dev/null +++ b/cross/patch/binutils/ld/emulparams/elf_x86_64_jehanne.sh @@ -0,0 +1,4 @@ +. ${srcdir}/emulparams/elf_x86_64.sh +GENERATE_SHLIB_SCRIPT= +GENERATE_PIE_SCRIPT=yes +ENTRY=_main diff --git a/cross/patch/gcc/config.sub b/cross/patch/gcc/config.sub new file mode 100644 index 0000000..9555a9b --- /dev/null +++ b/cross/patch/gcc/config.sub @@ -0,0 +1,3 @@ + -jehanne*) + os=-jehanne + ;; diff --git a/cross/patch/gcc/contrib/download_prerequisites b/cross/patch/gcc/contrib/download_prerequisites new file mode 100644 index 0000000..932dc36 --- /dev/null +++ b/cross/patch/gcc/contrib/download_prerequisites @@ -0,0 +1,71 @@ +#! /bin/sh + +# Download some prerequisites needed by gcc. +# Run this from the top level of the gcc source tree and the gcc +# build will do the right thing. +# +# (C) 2010 Free Software Foundation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. + +# If you want to build GCC with the Graphite loop optimizations, +# set GRAPHITE_LOOP_OPT=yes to download optional prerequisties +# ISL Library and CLooG. +GRAPHITE_LOOP_OPT=yes + +if [ ! -e gcc/BASE-VER ] ; then + echo "You must run this script in the top level GCC source directory." + exit 1 +fi + +# Necessary to build GCC. +MPFR=mpfr-2.4.2 +GMP=gmp-4.3.2 +MPC=mpc-0.8.1 + +if [ ! -d $MPFR ]; then + wget http://ftp.mirrorservice.org/sites/sourceware.org/pub/gcc/infrastructure/$MPFR.tar.bz2 || exit 1 + tar xjf $MPFR.tar.bz2 || exit 1 + ln -sf $MPFR mpfr || exit 1 +fi + +if [ ! -d $GMP ]; then + wget http://ftp.mirrorservice.org/sites/sourceware.org/pub/gcc/infrastructure/$GMP.tar.bz2 || exit 1 + tar xjf $GMP.tar.bz2 || exit 1 + ln -sf $GMP gmp || exit 1 +fi + +if [ ! -d $MPC ]; then + wget http://ftp.mirrorservice.org/sites/sourceware.org/pub/gcc/infrastructure/$MPC.tar.gz || exit 1 + tar xzf $MPC.tar.gz || exit 1 + ln -sf $MPC mpc || exit 1 +fi + +# Necessary to build GCC with the Graphite loop optimizations. +if [ "$GRAPHITE_LOOP_OPT" = "yes" ] ; then + ISL=isl-0.12.2 + CLOOG=cloog-0.18.1 + + if [ ! -d $ISL ]; then + wget http://ftp.mirrorservice.org/sites/sourceware.org/pub/gcc/infrastructure/$ISL.tar.bz2 || exit 1 + tar xjf $ISL.tar.bz2 || exit 1 + ln -sf $ISL isl || exit 1 + fi + + if [ ! -d $CLOOG ]; then + wget http://ftp.mirrorservice.org/sites/sourceware.org/pub/gcc/infrastructure/$CLOOG.tar.gz || exit 1 + tar xzf $CLOOG.tar.gz || exit 1 + ln -sf $CLOOG cloog || exit 1 + fi +fi diff --git a/cross/patch/gcc/fixincludes/mkfixinc.sh b/cross/patch/gcc/fixincludes/mkfixinc.sh new file mode 100644 index 0000000..dc0e343 --- /dev/null +++ b/cross/patch/gcc/fixincludes/mkfixinc.sh @@ -0,0 +1 @@ + *-jehanne* | \ diff --git a/cross/patch/gcc/gcc/config.gcc b/cross/patch/gcc/gcc/config.gcc new file mode 100644 index 0000000..0ee95ab --- /dev/null +++ b/cross/patch/gcc/gcc/config.gcc @@ -0,0 +1,31 @@ +diff --git a/src/gcc/gcc/config.gcc b/src/gcc/gcc/config.gcc +index f02ddbd..e5ebfe0 100644 +--- a/src/gcc/gcc/config.gcc ++++ b/src/gcc/gcc/config.gcc +@@ -862,6 +862,16 @@ case ${target} in + tmake_file="$tmake_file vms/t-vmsnative" + fi + ;; ++*-*-jehanne*) ++ gas=yes ++ gnu_ld=yes ++ default_use_cxa_atexit=yes ++ case $target in ++ x86_64-*) ++ native_system_header_dir="/arch/amd64/include" ++ ;; ++ esac ++ ;; + *-*-vxworks*) + tmake_file=t-vxworks + xm_defines=POSIX +@@ -1347,6 +1357,9 @@ x86_64-*-darwin*) + i[34567]86-*-elf*) + tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h" + ;; ++x86_64-*-jehanne*) ++ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h glibc-stdint.h i386/i386elf.h i386/x86-64.h jehanne.h" ++ ;; + x86_64-*-elf*) + tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h" + ;; diff --git a/cross/patch/gcc/gcc/config/jehanne.h b/cross/patch/gcc/gcc/config/jehanne.h new file mode 100644 index 0000000..9dc2aac --- /dev/null +++ b/cross/patch/gcc/gcc/config/jehanne.h @@ -0,0 +1,88 @@ +/* + * This file is part of Jehanne. + * + * Copyright (C) 2016 Giacomo Tesio + * + * Jehanne is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * Jehanne is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jehanne. If not, see . + */ + +#undef TARGET_JEHANNE +#define TARGET_JEHANNE 1 + +/* Default arguments you want when running x86_64-jehanne-gcc */ +#undef LIB_SPEC +#define LIB_SPEC "-lc" + +#undef STANDARD_STARTFILE_PREFIX +#define STANDARD_STARTFILE_PREFIX "/arch/amd64/lib/" + +#undef MD_STARTFILE_PREFIX +#define MD_STARTFILE_PREFIX "/arch/amd64/lib/" + +#undef GPLUSPLUS_INCLUDE_DIR +#define GPLUSPLUS_INCLUDE_DIR "/posix/include/g++" + +#undef GCC_INCLUDE_DIR +#define GCC_INCLUDE_DIR "/posix/include/gcc" + +/* Architecture specific header (u.h) goes here (from config.gcc) */ +#define ARCH_INCLUDE_DIR NATIVE_SYSTEM_HEADER_DIR + +/* The default include dir is /sys/include but... */ +#define PORTABLE_INCLUDE_DIR "/sys/include" + +/* ...we have to wrap libc.h and stdio.h with POSIX headers */ +#define POSIX_INCLUDE_DIR "/sys/include/apw" + +#undef INCLUDE_DEFAULTS +#define INCLUDE_DEFAULTS \ + { \ + { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1, 1, 0 }, \ + { GCC_INCLUDE_DIR, 0, 0, 0, 1, 0 }, \ + { POSIX_INCLUDE_DIR, 0, 0, 0, 1, 0 }, \ + { ARCH_INCLUDE_DIR, 0, 0, 0, 1, 0 }, \ + { PORTABLE_INCLUDE_DIR, 0, 0, 0, 1, 0 }, \ + { ".", 0, 0, 0, 1, 0 }, \ + { 0, 0, 0, 0, 0, 0 } \ + } + +/* Files that are linked before user code. + The %s tells gcc to look for these files in the library directory. */ +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "crt0.o%s crti.o%s crtbegin.o%s" + +/* Files that are linked after user code. */ +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "crtend.o%s crtn.o%s" + +/* Don't automatically add extern "C" { } around header files. */ +#undef NO_IMPLICIT_EXTERN_C +#define NO_IMPLICIT_EXTERN_C 1 + +/* Fix https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67132 */ +#undef WCHAR_TYPE +#define WCHAR_TYPE "unsigned int" +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE 32 + +#undef LINK_GCC_C_SEQUENCE_SPEC +#define LINK_GCC_C_SEQUENCE_SPEC "%G %L" + +/* Additional predefined macros. */ +#undef TARGET_OS_CPP_BUILTINS +#define TARGET_OS_CPP_BUILTINS() \ + do { \ + builtin_define ("__jehanne__"); \ + builtin_assert ("system=jehanne"); \ + } while(0); + diff --git a/cross/patch/gcc/libgcc/config.host b/cross/patch/gcc/libgcc/config.host new file mode 100644 index 0000000..390276f --- /dev/null +++ b/cross/patch/gcc/libgcc/config.host @@ -0,0 +1,4 @@ +x86_64-*-jehanne*) + extra_parts="$extra_parts crtbegin.o crtend.o" + tmake_file="$tmake_file i386/t-crtstuff t-crtstuff-pic t-libgcc-pic" + ;; diff --git a/cross/patch/gcc/libgcc/config.host.sed b/cross/patch/gcc/libgcc/config.host.sed new file mode 100644 index 0000000..6854d52 --- /dev/null +++ b/cross/patch/gcc/libgcc/config.host.sed @@ -0,0 +1,3 @@ +/enable_execute_stack=enable-execute-stack-empty.c;/,/Configuration ${host} not supported/{ + /^case ${host} in$/r ../patch/gcc/libgcc/config.host +} diff --git a/cross/patch/gcc/libstdc++-v3/crossconfig.m4 b/cross/patch/gcc/libstdc++-v3/crossconfig.m4 new file mode 100644 index 0000000..a74ca37 --- /dev/null +++ b/cross/patch/gcc/libstdc++-v3/crossconfig.m4 @@ -0,0 +1,6 @@ + *-jehanne*) + GLIBCXX_CHECK_COMPILER_FEATURES + GLIBCXX_CHECK_LINKER_FEATURES + GLIBCXX_CHECK_MATH_SUPPORT + GLIBCXX_CHECK_STDLIB_SUPPORT + ;; diff --git a/cross/src/.gitignore b/cross/src/.gitignore new file mode 100644 index 0000000..e3300fa --- /dev/null +++ b/cross/src/.gitignore @@ -0,0 +1,7 @@ +gcc +binutils +autoconf +automake +libtool +m4 +build-* diff --git a/cross/src/fetch.json b/cross/src/fetch.json new file mode 100644 index 0000000..5e93a19 --- /dev/null +++ b/cross/src/fetch.json @@ -0,0 +1,62 @@ +{ + "autoconf" : { + "Upstream":"https://ftp.gnu.org/gnu/autoconf/autoconf-2.64.tar.bz2", + "Digest": { + "sha256":"872f4cadf12e7e7c8a2414e047fdff26b517c7f1a977d72433c124d0d3acaa85" + }, + "Compress":"bzip2", + "RemovePrefix": true, + "Exclude": [ + ] + }, + "m4": { + "Upstream":"https://ftp.gnu.org/gnu/m4/m4-1.4.14.tar.bz2", + "Digest": { + "sha256":"0885ffa93256353a96b1cf0bcbc4d639ed09953b687e6cc412c4048e656f4dd2" + }, + "Compress":"bzip2", + "RemovePrefix": true, + "Exclude": [ + ] + }, + "automake": { + "Upstream":"https://ftp.gnu.org/gnu/automake/automake-1.11.1.tar.bz2", + "Digest": { + "sha256":"5b159d3c0e0a1f87de71b68bcb9f1a1c49e9e71749c9b723f17e2e1e0295c7ae" + }, + "Compress":"bzip2", + "RemovePrefix": true, + "Exclude": [ + ] + }, + "libtool": { + "Upstream":"https://ftp.gnu.org/gnu/libtool/libtool-2.4.tar.gz", + "Digest": { + "sha256":"13df57ab63a94e196c5d6e95d64e53262834fe780d5e82c28f177f9f71ddf62e" + }, + "Compress":"gzip", + "RemovePrefix": true, + "Exclude": [ + ] + }, + "binutils": { + "Upstream":"https://ftp.gnu.org/gnu/binutils/binutils-2.26.tar.bz2", + "Digest": { + "sha256":"c2ace41809542f5237afc7e3b8f32bb92bc7bc53c6232a84463c423b0714ecd9" + }, + "Compress":"bzip2", + "RemovePrefix": true, + "Exclude": [ + ] + }, + "gcc": { + "Upstream":"https://ftp.gnu.org/gnu/gcc/gcc-4.9.4/gcc-4.9.4.tar.bz2", + "Digest": { + "sha256":"6c11d292cd01b294f9f84c9a59c230d80e9e4a47e5c6355f046bb36d4f358092" + }, + "Compress":"bzip2", + "RemovePrefix": true, + "Exclude": [ + ] + } +} diff --git a/cross/tmp/.gitignore b/cross/tmp/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/cross/tmp/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/cross/toolchain/.gitignore b/cross/toolchain/.gitignore new file mode 100644 index 0000000..a5baada --- /dev/null +++ b/cross/toolchain/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore + diff --git a/devshell.sh b/devshell.sh index efefefb..7351497 100755 --- a/devshell.sh +++ b/devshell.sh @@ -1,6 +1,10 @@ #!/bin/bash export JEHANNE=`git rev-parse --show-toplevel` export PATH="$JEHANNE/hacking/bin:$PATH" +export PATH="$JEHANNE/hacking/third_party/src/github.com/JehanneOS/devtools-kencc/bin:$PATH" +export PATH="$JEHANNE/hacking/cross/toolchain/bin:$PATH" export ARCH=amd64 +export TOOLPREFIX=x86_64-jehanne- + bash --rcfile <(cat ~/.bashrc; echo 'PS1="JehanneDEV $PS1"') diff --git a/disk-boot-update.sh b/disk-boot-update.sh new file mode 100755 index 0000000..b139137 --- /dev/null +++ b/disk-boot-update.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +if [ "$JEHANNE" = "" ]; then + echo $0 requires the shell started by ./hacking/devshell.sh + exit 1 +fi + +if [ "$SYSLINUXBIOS" == "" ]; then + export SYSLINUXBIOS=/usr/lib/syslinux/modules/bios/ # GNU/Linux Debian way +fi +if [ ! -d "$SYSLINUXBIOS" ]; then + echo 'Missing $SYSLINUXBIOS: install syslinux-utils or set it to the proper path.' + exit 1 +fi + +if [ -d $JEHANNE/hacking/disk-setup/bios/ ]; then + rm $JEHANNE/hacking/disk-setup/bios/* +else + mkdir $JEHANNE/hacking/disk-setup/bios/ +fi +cp $SYSLINUXBIOS/lib* $JEHANNE/hacking/disk-setup/bios/ +cp $SYSLINUXBIOS/elf.c32 $JEHANNE/hacking/disk-setup/bios/ +cp $SYSLINUXBIOS/mboot.c32 $JEHANNE/hacking/disk-setup/bios/ +cp $SYSLINUXBIOS/menu.c32 $JEHANNE/hacking/disk-setup/bios/ + +# Locate the disk +if [ "$DISK" == "" ]; then + export DISK=$JEHANNE/hacking/sample-disk.img +fi + +if [ ! -b $DISK ] && [ ! -f $DISK ]; then + echo "Cannot find DISK to update ($DISK): set the DISK variable" + exit 1 +fi + +export KERNEL=$JEHANNE/hacking/bin/workhorse.32bit +export KERNDIR=$JEHANNE/hacking/bin/ + +# install everything +cat << EOF | runqemu +disk/fdisk -p /dev/sdE0/data >> /dev/sdE0/ctl +disk/prep -p /dev/sdE0/plan9 >> /dev/sdE0/ctl +cat /dev/sdE0/ctl + +disk/format -d /dev/sdE0/dos /hacking/disk-setup/syslinux.cfg /hacking/disk-setup/bios/* /arch/amd64/kern/initrd /arch/amd64/kern/jehanne.32bit + +EOF +syslinux --offset $((2048*512)) $DISK +dd bs=440 count=1 conv=notrunc if=/usr/lib/syslinux/mbr/mbr.bin of=$DISK + diff --git a/disk-create.sh b/disk-create.sh new file mode 100755 index 0000000..4dc3a6e --- /dev/null +++ b/disk-create.sh @@ -0,0 +1,124 @@ +#!/bin/bash + +if [ "$JEHANNE" = "" ]; then + echo $0 requires the shell started by ./hacking/devshell.sh + exit 1 +fi + +if [ "$SYSLINUXBIOS" == "" ]; then + export SYSLINUXBIOS=/usr/lib/syslinux/modules/bios/ # GNU/Linux Debian way +fi +if [ ! -d "$SYSLINUXBIOS" ]; then + echo 'Missing $SYSLINUXBIOS: install syslinux-utils or set it to the proper path.' + exit 1 +fi + +if [ -d $JEHANNE/hacking/disk-setup/bios/ ]; then + rm $JEHANNE/hacking/disk-setup/bios/* +else + mkdir $JEHANNE/hacking/disk-setup/bios/ +fi +cp $SYSLINUXBIOS/lib* $JEHANNE/hacking/disk-setup/bios/ +cp $SYSLINUXBIOS/elf.c32 $JEHANNE/hacking/disk-setup/bios/ +cp $SYSLINUXBIOS/mboot.c32 $JEHANNE/hacking/disk-setup/bios/ +cp $SYSLINUXBIOS/menu.c32 $JEHANNE/hacking/disk-setup/bios/ + +# Create the data disk +if [ "$DISK" == "" ]; then + export DISK=$JEHANNE/hacking/sample-disk.img +fi + + +if [ ! -f $DISK ]; then + qemu-img create $DISK 4G + + sed -e 's/^\s*\([\+0-9a-zA-Z]*\)[ ].*/\1/' << EOF | /sbin/fdisk $DISK + o #clear partition table + n #new partition + p #primary partition + 1 #partition 1 + #start at beginning of disk + +40M #reserve 40 megabytes + t #change type + c #W95 FAT32 (LBA) + a #make it bootable + n #new partition + p #primary partition + 2 #partition 2 + #start at first free sector + #end at the end of disk + t #change type + 2 #partition 2 + 39 #Plan 9 + p #print partition table + w #write partition table + q #quit +EOF + +export KERNEL=$JEHANNE/hacking/bin/workhorse.32bit +export KERNDIR=$JEHANNE/hacking/bin/ + + # install everything + cat << EOF | runqemu +disk/fdisk -p /dev/sdE0/data >> /dev/sdE0/ctl +disk/prep -w -a nvram -a fs /dev/sdE0/plan9 +disk/prep -p /dev/sdE0/plan9 >> /dev/sdE0/ctl +cat /dev/sdE0/ctl + +disk/format -d /dev/sdE0/dos /hacking/disk-setup/syslinux.cfg /hacking/disk-setup/bios/* /arch/amd64/kern/initrd /arch/amd64/kern/jehanne.32bit + +dd -if /hacking/nvram -of /dev/sdE0/nvram + +hjfs -n hjfs -Srf /dev/sdE0/fs +/hacking/disk-setup/configure-hjfs >>/srv/hjfs.cmd +hjfs -n hjfs -Sf /dev/sdE0/fs +mount -c /srv/hjfs /n/newfs +cd /n/newfs +cd cfg +dircp /root/cfg . +cd /n/newfs +mkdir arch +cd arch +dircp /root/arch . +cd /n/newfs +mkdir lib +cd lib +dircp /root/lib . +cd /n/newfs +mkdir mnt +cd mnt +mkdir temp +mkdir term +mkdir acme +mkdir wsys +cd /n/newfs +mkdir usr +cd usr +dircp /root/usr . +cd /n/newfs +mkdir sys +cd sys +mkdir include +mkdir src +dircp /root/sys/src src/ +dircp /root/sys/include include/ +mkdir log +cd /n/newfs +mkdir qa +cd qa +dircp /root/qa . +cd /n/newfs +lc +unmount /n/newfs +echo df >> /srv/hjfs.cmd +echo sync >> /srv/hjfs.cmd +sleep 60 +echo halt >> /srv/hjfs.cmd +sleep 20 +EOF + syslinux --offset $((2048*512)) $DISK + dd bs=440 count=1 conv=notrunc if=/usr/lib/syslinux/mbr/mbr.bin of=$DISK +else + echo Root disk already exists: $DISK +fi + diff --git a/disk-get.sh b/disk-get.sh new file mode 100755 index 0000000..5549789 --- /dev/null +++ b/disk-get.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +if [ "$JEHANNE" = "" ]; then + echo $0 requires the shell started by ./hacking/devshell.sh + exit 1 +fi + +if [ "$DISK" == "" ]; then + export DISK=$JEHANNE/hacking/sample-disk.img +fi + +if [ ! -f $DISK ] && [ ! -b $DISK ]; then + echo "Cannot find DISK to update ($DISK): set the DISK variable" + exit 1 +fi + +export KERNEL=$JEHANNE/hacking/bin/workhorse.32bit +export KERNDIR=$JEHANNE/hacking/bin/ + +# install everything +cat > $JEHANNE/tmp/files.list << EOF +disk/fdisk -p /dev/sdE0/data >> /dev/sdE0/ctl +disk/prep -p /dev/sdE0/plan9 >> /dev/sdE0/ctl +cat /dev/sdE0/ctl + +hjfs -n hjfs -Sf /dev/sdE0/fs +mount -c /srv/hjfs /n/newfs + +EOF + +for var in "$@" +do + echo "cp /n/newfs/$var /tmp/$var" >> $JEHANNE/tmp/files.list +done + +cat >> $JEHANNE/tmp/files.list << EOF + +unmount /n/newfs +echo df >> /srv/hjfs.cmd +echo sync >> /srv/hjfs.cmd +sleep 60 +echo halt >> /srv/hjfs.cmd +sleep 20 + +EOF + +cat $JEHANNE/tmp/files.list | runqemu +rm $JEHANNE/tmp/files.list diff --git a/disk-setup/configure-hjfs b/disk-setup/configure-hjfs new file mode 100755 index 0000000..0d7c5e9 --- /dev/null +++ b/disk-setup/configure-hjfs @@ -0,0 +1,15 @@ +#!/cmd/rc + +echo echo on +echo create /dist sys sys 775 d +echo create /tmp sys sys 775 d +echo create /usr sys sys 775 d +echo newuser glenda +echo newuser adm +glenda +echo newuser sys +glenda +echo newuser upas +glenda +echo sync +echo echo off +echo halt +sleep 2 + diff --git a/disk-setup/flproto b/disk-setup/flproto new file mode 100644 index 0000000..fecf579 --- /dev/null +++ b/disk-setup/flproto @@ -0,0 +1,6 @@ +srv -p fscons +srv fossil +fsys main config /dev/sdE1/fossil +fsys main open -AWP +fsys main + diff --git a/disk-setup/syslinux.cfg b/disk-setup/syslinux.cfg new file mode 100644 index 0000000..c3f4a5c --- /dev/null +++ b/disk-setup/syslinux.cfg @@ -0,0 +1,19 @@ +DEFAULT menu.c32 + +# to force boot jump to a rc shell (without executing /lib/namespace, thus no command in /cmd), add +# init='/arch/amd64/cmd/rc -i' +# to the APPEND line (before ---) +# NOTE: double quotes won't work, only singe quotes are accepted + +LABEL FromUSB + KERNEL mboot.c32 + APPEND jehanne.32bit nobootprompt=local!/shr/usb/sdU67d95 maxcores=1024 auth=10.0.0.203 nvram=/shr/usb/sdU67d95/nvram nvrlen=512 nvroff=0 --- initrd + +LABEL FromAHCI + KERNEL mboot.c32 + APPEND jehanne.32bit nobootprompt=local!#S/sdE0 maxcores=1024 auth=10.0.0.1 nvram=#S/sdE0/nvram nvrlen=512 nvroff=0 --- initrd + +LABEL FromIDE + KERNEL mboot.c32 + APPEND jehanne.32bit nobootprompt=local!#S/sdC0 maxcores=1024 auth=10.0.0.1 nvram=#S/sdC0/nvram nvrlen=512 nvroff=0 --- initrd + diff --git a/disk-setup/venti.conf b/disk-setup/venti.conf new file mode 100644 index 0000000..505406a --- /dev/null +++ b/disk-setup/venti.conf @@ -0,0 +1,4 @@ +index main +isect /dev/sdE1/isect +arenas /dev/sdE1/arenas + diff --git a/disk-update.sh b/disk-update.sh new file mode 100755 index 0000000..6b463c3 --- /dev/null +++ b/disk-update.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +if [ "$JEHANNE" = "" ]; then + echo $0 requires the shell started by ./hacking/devshell.sh + exit 1 +fi + +if [ "$DISK" == "" ]; then + export DISK=$JEHANNE/hacking/sample-disk.img +fi + +if [ ! -f $DISK ] && [ ! -b $DISK ]; then + echo "Cannot find DISK to update ($DISK): set the DISK variable" + exit 1 +fi + +export KERNEL=$JEHANNE/hacking/bin/workhorse.32bit +export KERNDIR=$JEHANNE/hacking/bin/ + +# install everything +cat > $JEHANNE/tmp/files.list << EOF +disk/fdisk -p /dev/sdE0/data >> /dev/sdE0/ctl +disk/prep -p /dev/sdE0/plan9 >> /dev/sdE0/ctl +cat /dev/sdE0/ctl + +hjfs -n hjfs -Sf /dev/sdE0/fs +mount -c /srv/hjfs /n/newfs + +EOF + +for var in "$@" +do + echo "cp /$var /n/newfs/$var" >> $JEHANNE/tmp/files.list +done + +cat >> $JEHANNE/tmp/files.list << EOF + +unmount /n/newfs +echo df >> /srv/hjfs.cmd +echo sync >> /srv/hjfs.cmd +sleep 60 +echo halt >> /srv/hjfs.cmd +sleep 20 + +EOF + +cat $JEHANNE/tmp/files.list | runqemu +rm $JEHANNE/tmp/files.list diff --git a/drawterm.sh b/drawterm.sh new file mode 100755 index 0000000..2806bb2 --- /dev/null +++ b/drawterm.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +if [ "$JEHANNE" = "" ]; then + echo ./hacking/drawterm.sh requires the shell started by ./hacking/devshell.sh + exit 1 +fi +drawterm -a 127.0.0.1 -c 127.0.0.1 -u glenda diff --git a/gdbinit b/gdbinit new file mode 100644 index 0000000..9360c1f --- /dev/null +++ b/gdbinit @@ -0,0 +1,290 @@ +set pagination off +set logging file ../qemu-gdb.log +set logging overwrite on +set logging on + +define log_mach_proc + if up != 0 + printf "%s %d ", up->text, up->pid + end + if m != 0 + printf "(mach %d) ", m->machno + end +end + +define log_syscall + log_mach_proc + printf "\n" + c +end + +define log_syscalls + + # sysbind + b ../port/sysfile.c:1167 + commands + log_syscall + end + + # syschdir + b ../port/sysfile.c:1027 + commands + log_syscall + end + + # sysclose + b ../port/sysfile.c:375 + commands + log_syscall + end + + # syscreate + b ../port/sysfile.c:1263 + commands + log_syscall + end + + # sysdup + b ../port/sysfile.c:263 + commands + log_syscall + end + + # sysfd2path + b ../port/sysfile.c:191 + commands + log_syscall + end + + # sysfstat + b ../port/sysfile.c:999 + commands + log_syscall + end + + # sysfwstat + b ../port/sysfile.c:1371 + commands + log_syscall + end + + # sysmount + b ../port/sysfile.c:1192 + commands + log_syscall + end + + # sysopen + b ../port/sysfile.c:311 + commands + log_syscall + end + + # syspipe + b ../port/sysfile.c:214 + commands + log_syscall + end + + # syspread + b ../port/sysfile.c:787 + commands + log_syscall + end + + # syspwrite + b ../port/sysfile.c:857 + commands + log_syscall + end + + # sysremove + b ../port/sysfile.c:1293 + commands + log_syscall + end + + # sysseek + b ../port/sysfile.c:929 + commands + log_syscall + end + + # sysunmount + b ../port/sysfile.c:1210 + commands + log_syscall + end + + # sysfversion + b ../port/sysauth.c:50 + commands + log_syscall + end + + # sysfauth + b ../port/sysauth.c:83 + commands + log_syscall + end + + # sysrfork + b ../port/sysproc.c:36 + commands + log_syscall + end + + # sysalarm + b ../port/sysproc.c:656 + commands + log_syscall + end + + # sysawake + b ../port/sysproc.c:682 + commands + printf "sys->ticks %lld ms %lld \n", sys->ticks, ms + log_syscall + end + + # sysawait + b ../port/sysproc.c:729 + commands + log_syscall + end + + # syserrstr + b ../port/sysproc.c:791 + commands + log_syscall + end + + # sysnotify + b ../port/sysproc.c:809 + commands + log_syscall + end + + # sysexec + b ../port/sysproc.c:284 + commands + log_syscall + end + + # sysexits + b ../port/sysproc.c:702 + commands + if status != 0 + printf "status: %s", status + else + printf "status: (nil)" + end + log_syscall + end + + # sysnoted + b ../port/sysproc.c:840 + commands + log_syscall + end + + # sysrendezvous + b ../port/sysproc.c:861 + commands + printf "tag %llu rendval %llu\n", tag, rendval + printf "sys->ticks %lld lastWakeup %lld pendingWakeup %lld \n", sys->ticks, up->lastWakeup, up->pendingWakeup + log_syscall + end + + # sysnotify + b ../port/sysproc.c:820 + commands + log_syscall + end + + # sysnsec + b ../port/sysproc.c:1233 + commands + log_syscall + end + + # syssemacquire + b ../port/sysproc.c:1167 + commands + log_syscall + end + + # syssemrelease + b ../port/sysproc.c:1222 + commands + log_syscall + end + + # syssleep + b ../port/sysproc.c:640 + commands + printf "ms %lld\n", ms + log_syscall + end + + # systsemacquire + b ../port/sysproc.c:1193 + commands + log_syscall + end + +end + +define debug_awake + # awakekproc + b ../port/awake.c:139 + commands + printf "%s %d ", p->text, p->pid + printf "p->state %d p->lastWakeup %lld toAwake->time %d \n", p->state, p->lastWakeup, toAwake->time + c + end + + # sysawake + b ../port/sysproc.c:682 + commands + printf "sys->ticks %lld ms %lld \n", sys->ticks, ms + log_syscall + end + + # sysrendezvous + b ../port/sysproc.c:861 + commands + printf "ENTER: \n tag %llu rendval %llu\n", tag, rendval + printf "sys->ticks %lld lastWakeup %lld pendingWakeup %lld \n", sys->ticks, up->lastWakeup, up->pendingWakeup + log_syscall + end + + # sysrendezvous + b ../port/sysproc.c:879 + commands + printf "EXIT on match: \n tag %llu rendval %llu\n", tag, rendval + printf "sys->ticks %lld lastWakeup %lld pendingWakeup %lld \n", sys->ticks, up->lastWakeup, up->pendingWakeup + log_syscall + end + + # sysrendezvous + b ../port/sysproc.c:886 + commands + printf "EXIT on awaken: \n tag %llu rendval %llu\n", tag, rendval + printf "sys->ticks %lld lastWakeup %lld pendingWakeup %lld \n", sys->ticks, up->lastWakeup, up->pendingWakeup + log_syscall + end + + # sysrendezvous + b ../port/sysproc.c:902 + commands + printf "EXIT after wait: \n tag %llu rendval %llu\n", tag, rendval + printf "sys->ticks %lld lastWakeup %lld pendingWakeup %lld \n", sys->ticks, up->lastWakeup, up->pendingWakeup + log_syscall + end + +end + +#log_syscalls + + diff --git a/runDisk.sh b/runDisk.sh new file mode 100755 index 0000000..e5a5f0c --- /dev/null +++ b/runDisk.sh @@ -0,0 +1,74 @@ +#!/bin/sh + +export SDL_VIDEO_X11_DGAMOUSE=0 # see https://wiki.archlinux.org/index.php/QEMU#Mouse_cursor_is_jittery_or_erratic + +if [ "$JEHANNE" = "" ]; then + echo $0 requires the shell started by ./hacking/devshell.sh + exit 1 +fi + +trap : 2 + +export machineflag=pc +if [ "$(uname)" = "Linux" ] && [ -e /dev/kvm ]; then + export kvmflag='-enable-kvm' + export machineflag='pc,accel=kvm' + if [ ! -w /dev/kvm ]; then + # we don't have access as a regular user + export kvmdo=sudo + fi +fi + +if [ "$1" = "" ]; then + if [ "$DISK" = "" ]; then + if [ -f $JEHANNE/hacking/sample-disk.img ]; then + export DISK=$JEHANNE/hacking/sample-disk.img + else + echo No disk image provided: usage: $0 path/to/disk + exit 1 + fi + else + echo No disk image provided: usage: $0 path/to/disk + exit 1 + fi +else + export DISK="$1" +fi + +case "$DISK" in + *:*) + bootDisk="-usb -usbdevice host:$DISK" + ;; + *) + bootDisk="-drive if=none,id=usbstick,file=$DISK -usb -readconfig /usr/share/doc/qemu-system-x86/common/ich9-ehci-uhci.cfg -device usb-host,bus=usb-bus.0,hostbus=3,hostport=1 -device usb-host,bus=usb-bus.0,hostbus=3,hostport=1 -device usb-storage,bus=ehci.0,drive=usbstick " + ;; +esac +#bootDisk="-device ahci,id=ahci -drive id=boot,file=$DISK,index=0,cache=writeback,if=none -device ide-drive,drive=boot,bus=ahci.0" +bootDisk="-global ide-drive.physical_block_size=4096 -drive file=$DISK,if=ide,index=0,media=disk" + +cd $JEHANNE/arch/$ARCH/kern/ +read -r cmd < 0 { for _, i := range b.SourceFilesCmd { - cmd := exec.Command(tools["cc"], append(args, i)...) + largs := make([]string, 3) + largs[0] = i + largs[1] = "-o" + largs[2] = strings.Replace(filepath.Base(i), filepath.Ext(i), "", 1) + cmd := exec.Command(tools["cc"], append(largs, args...)...) run(b, *shellhack, cmd) } return } - args = append(args, b.SourceFiles...) + if !isValueInList("-c", b.Cflags) { + args = append(args, "-o", b.Program) + } cmd := exec.Command(tools["cc"], args...) run(b, *shellhack, cmd) } func link(b *build) { + if !isValueInList("-c", b.Cflags) { + return + } log.Printf("Linking %s\n", b.name) if len(b.SourceFilesCmd) > 0 { for _, n := range b.SourceFilesCmd { @@ -329,7 +436,6 @@ func link(b *build) { o := f[:len(f)] + ".o" args := []string{"-o", n, o} args = append(args, b.Oflags...) - args = append(args, "-L", fromRoot("/arch/$ARCH/lib")) args = append(args, b.Libs...) run(b, *shellhack, exec.Command(tools["ld"], args...)) } @@ -338,7 +444,6 @@ func link(b *build) { args := []string{"-o", b.Program} args = append(args, b.ObjectFiles...) args = append(args, b.Oflags...) - args = append(args, "-L", fromRoot("/arch/$ARCH/lib")) args = append(args, b.Libs...) run(b, *shellhack, exec.Command(tools["ld"], args...)) } @@ -412,12 +517,12 @@ func projects(b *build, r []*regexp.Regexp) { for _, v := range b.Projects { f, _ := findBuildfile(v) log.Printf("Doing %s\n", f) - project(f, r) + project(f, r, b) } } // assumes we are in the wd of the project. -func project(bf string, which []*regexp.Regexp) { +func project(bf string, which []*regexp.Regexp, container *build) { cwd, err := os.Getwd() failOn(err) debug("Start new project cwd is %v", cwd) @@ -430,11 +535,25 @@ func project(bf string, which []*regexp.Regexp) { debug("Processing %v: %d target", root, len(builds)) for _, b := range builds { debug("Processing %v: %v", b.name, b) + if container != nil { + b.Env = append(container.Env, b.Env...) + } projects(&b, regexpAll) for _, c := range b.Pre { // this is a hack: we just pass the command through as an exec.Cmd run(&b, true, exec.Command(c)) } + envFunc := buildEnv(&b); + b.Program = os.Expand(b.Program, envFunc) + for i, s := range b.SourceFiles { + b.SourceFiles[i] = fromRoot(os.Expand(s, envFunc)); + } + for i, s := range b.SourceFilesCmd { + b.SourceFilesCmd[i] = fromRoot(os.Expand(s, envFunc)); + } + for i, s := range b.ObjectFiles { + b.ObjectFiles[i] = fromRoot(os.Expand(s, envFunc)); + } buildkernel(&b) if len(b.SourceFiles) > 0 || len(b.SourceFilesCmd) > 0 { compile(&b) @@ -511,7 +630,7 @@ func main() { re = append(re, rx) } } - project(bf, re) + project(bf, re, nil) } func findTools(toolprefix string) { @@ -520,7 +639,10 @@ func findTools(toolprefix string) { if x := os.Getenv(strings.ToUpper(k)); x != "" { v = x } - v, err = exec.LookPath(toolprefix + v) + if v != "sh" { + v = toolprefix + v; + } + v, err = exec.LookPath(v) failOn(err) tools[k] = v } diff --git a/src/jehanne/cmd/build/codegen.go b/src/jehanne/cmd/build/codegen.go index 74a2403..1c53bba 100644 --- a/src/jehanne/cmd/build/codegen.go +++ b/src/jehanne/cmd/build/codegen.go @@ -98,20 +98,6 @@ VGAcur* vgacur[] = { nil, }; -Physseg physseg[8] = { - { - .attr = SG_SHARED, - .name = "shared", - .size = SEGMAXPG, - }, - { - .attr = SG_BSS, - .name = "memory", - .size = SEGMAXPG, - }, -}; -int nphysseg = 8; - {{ range .Config.Code }}{{ . }} {{ end }} diff --git a/src/jehanne/cmd/fetch/fetch.go b/src/jehanne/cmd/fetch/fetch.go new file mode 100644 index 0000000..c258df3 --- /dev/null +++ b/src/jehanne/cmd/fetch/fetch.go @@ -0,0 +1,197 @@ +package main + +import ( + "archive/tar" + "bytes" + "compress/bzip2" + "compress/gzip" + "crypto/sha256" + "crypto/sha512" + "encoding/hex" + "encoding/json" + "hash" + "io" + "io/ioutil" + "log" + "net/http" + "os" + "os/exec" + "path" + "strings" +) + +const ( + dirPermissions = 0755 +) + +type Fetch struct { + Upstream string + Digest map[string]string + Compress string + RemovePrefix bool + Exclude []string +} + +func main() { + + j, err := ioutil.ReadFile("fetch.json") + if err != nil { + log.Fatal(err) + } + + fetches := make(map[string]Fetch) + if err := json.Unmarshal(j, &fetches); err != nil { + log.Fatal(err) + } + + for name, f := range(fetches) { + if _, err := os.Stat(name); err == nil { + log.Printf("Fetch: skip %v (already present)", name) + } else { + log.Printf("Fetch: %v from %v", name, f.Upstream) + if err := do(&f, name); err != nil { + log.Fatal(err) + } + } + } +} + +func do(f *Fetch, name string) error { + fname := fetch(f) + s, err := os.Open(fname) + if err != nil { + return err + } + defer os.Remove(fname) + + os.MkdirAll(name, dirPermissions) + + var unZ io.Reader + switch f.Compress { + case "gzip": + unZ, err = gzip.NewReader(s) + if err != nil { + return err + } + case "bzip2": + unZ = bzip2.NewReader(s) + default: + unZ = s + } + + ar := tar.NewReader(unZ) + h, err := ar.Next() +untar: + for ; err == nil; h, err = ar.Next() { + n := h.Name + if f.RemovePrefix { + n = strings.SplitN(n, "/", 2)[1] + } + for _, ex := range f.Exclude { + if strings.HasPrefix(n, ex) { + continue untar + } + } + n = path.Join(name, n) + if h.FileInfo().IsDir() { + os.MkdirAll(n, dirPermissions) + continue + } + os.MkdirAll(path.Dir(n), dirPermissions) + out, err := os.Create(n) + if err != nil { + log.Println(err) + continue + } + + if n, err := io.Copy(out, ar); n != h.Size || err != nil { + return err + } + out.Close() + if err := os.Chmod(n, h.FileInfo().Mode()); err != nil { + return err; + } + } + if err != io.EOF { + return err + } + return nil +} + +type match struct { + hash.Hash + Good []byte + Name string +} + +func (m match) OK() bool { + return bytes.Equal(m.Good, m.Hash.Sum(nil)) +} + +func fetch(v *Fetch) string { + if len(v.Digest) == 0 { + log.Fatal("no checksums specifed") + } + + f, err := ioutil.TempFile("", "cmdVendor") + if err != nil { + log.Fatal(err) + } + defer f.Close() + + req, err := http.NewRequest("GET", v.Upstream, nil) + if err != nil { + log.Fatal(err) + } + client := &http.Client{ + Transport: &http.Transport{ + Proxy: http.ProxyFromEnvironment, + DisableCompression: true, + }, + } + res, err := client.Do(req) + if err != nil { + log.Fatal(err) + } + defer res.Body.Close() + + var digests []match + for k, v := range v.Digest { + g, err := hex.DecodeString(v) + if err != nil { + log.Fatal(err) + } + switch k { + case "sha224": + digests = append(digests, match{sha256.New224(), g, k}) + case "sha256": + digests = append(digests, match{sha256.New(), g, k}) + case "sha384": + digests = append(digests, match{sha512.New384(), g, k}) + case "sha512": + digests = append(digests, match{sha512.New(), g, k}) + } + } + ws := make([]io.Writer, len(digests)) + for i := range digests { + ws[i] = digests[i] + } + w := io.MultiWriter(ws...) + + if _, err := io.Copy(f, io.TeeReader(res.Body, w)); err != nil { + log.Fatal(err) + } + for _, h := range digests { + if !h.OK() { + log.Fatalf("mismatched %q hash\n\tWanted %x\n\tGot %x\n", h.Name, h.Good, h.Hash.Sum(nil)) + } + } + return f.Name() +} + +func run(exe string, arg ...string) error { + cmd := exec.Command(exe, arg...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() +} diff --git a/src/jehanne/cmd/ksyscalls/ksyscalls.go b/src/jehanne/cmd/ksyscalls/ksyscalls.go new file mode 100644 index 0000000..c50d0e6 --- /dev/null +++ b/src/jehanne/cmd/ksyscalls/ksyscalls.go @@ -0,0 +1,374 @@ +/* + * This file is part of Jehanne. + * + * Copyright (C) 2016 Giacomo Tesio + * + * Jehanne is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * Jehanne is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jehanne. If not, see . + */ +package main + +import ( + "encoding/json" + "flag" + "fmt" + "io/ioutil" + "log" + "os" + "text/template" +) + +type SyscallConf struct { + Ret []string + Args []string + Name string + Id uint32 +} + +type Sysconf struct { + Syscalls []SyscallConf +} + +func usage(msg string) { + fmt.Fprint(os.Stderr, msg) + fmt.Fprint(os.Stderr, "Usage: ksyscalls path/to/sysconf.json\n") + flag.PrintDefaults() + os.Exit(1) +} + +type SyscallWrapper struct { + Id uint32 + Name string + Vars []string + CommonCode string + ExecCode string + EntryPrint string + ExitPrint string + SysRetField string + DefaultRet string +} + +type KernelCode struct { + Externs []string + Wrappers []SyscallWrapper +} + +func uregArg(index int) string{ + switch(index){ + case 0: + return "di"; + case 1: + return "si"; + case 2: + return "dx"; + case 3: + return "r10"; + case 4: + return "r8"; + case 5: + return "r9"; + } + return "" +} + +func sysret(t string) string { + switch(t){ + case "int", "int32_t": + return "i" + case "long", "int64_t": + return "vl" + case "uintptr_t", "void": + return "p" + case "void*", "char*", "char**", "uint8_t*", "int32_t*", "uint64_t*", "int64_t*": + return "v" + } + return " [?? " + t + "]" +} + +func formatArg(i int, t string) string{ + switch(t){ + case "int", "int32_t": + return fmt.Sprintf("\tfmtprint(fmt, \" %%d\", a%d);\n", i) + case "unsigned int", "uint32_t": + /* unsigned int is reserved for flags */ + return fmt.Sprintf("\tfmtprint(fmt, \" %%#ux\", a%d);\n", i) + case "long", "int64_t": + return fmt.Sprintf("\tfmtprint(fmt, \" %%lld\", a%d);\n", i) + case "unsigned long", "uint64_t": + return fmt.Sprintf("\tfmtprint(fmt, \" %%#lud\", a%d);\n", i) + case "void*", "uint8_t*", "const void*", "const uint8_t*": + return fmt.Sprintf("\tfmtprint(fmt, \" %%#p\", a%d);\n", i) + case "int32_t*", "int*", "const int32_t*", "const int*": + return fmt.Sprintf("\tfmtprint(fmt, \" %%#p(%%d)\", a%d, a%d);\n", i, i) + case "const char*", "char*": + return fmt.Sprintf("\tfmtuserstring(fmt, a%d);\n", i) + case "const char**", "char**": + return fmt.Sprintf("\tfmtuserstringlist(fmt, a%d);\n", i); + } + return " [?? " + t + "]" +} + +func formatRet(t string) string{ + switch(t){ + case "int", "int32_t": + return fmt.Sprintf("\tfmtprint(fmt, \" %%d\", ret->%s);\n", sysret(t)) + case "unsigned int", "uint32_t": + /* unsigned int is reserved for flags */ + return fmt.Sprintf("\tfmtprint(fmt, \" %%#ux\", ret->%s);\n", sysret(t)) + case "long", "int64_t": + return fmt.Sprintf("\tfmtprint(fmt, \" %%lld\", ret->%s);\n", sysret(t)) + case "unsigned long", "uint64_t", "void": + return fmt.Sprintf("\tfmtprint(fmt, \" %%#llud\", ret->%s);\n", sysret(t)) + case "void*", "uintptr_t", "const void*", "const uintptr_t": + return fmt.Sprintf("\tfmtprint(fmt, \" %%#p\", ret->%s);\n", sysret(t)) + case "int32_t*", "int*", "const int32_t*", "const int*": + return fmt.Sprintf("\tfmtprint(fmt, \" %%#p(%%d)\", ret->%s, *ret->%s);\n", sysret(t), sysret(t)) + } + return " [?? " + t + "]" +} + +func generateKernelCode(calls []SyscallConf){ + code := new(KernelCode) + + for _, call := range(calls) { + /* extern definitions */ + ext := "extern " + call.Ret[0] + " sys" + call.Name + "(" + if len(call.Args) == 0 { + ext += "void"; + } else { + for i, a := range(call.Args){ + if i > 0 { + ext += ", " + } + ext += fmt.Sprintf("%s", a) + } + } + ext += ");\n" + + wcall := new(SyscallWrapper) + wcall.Id = call.Id + wcall.Name = call.Name + wcall.SysRetField = sysret(call.Ret[0]) + wcall.DefaultRet = fmt.Sprintf("ret.%s = (%s)-1;", wcall.SysRetField, call.Ret[0]) + + for i, a := range(call.Args){ + wcall.Vars = append(wcall.Vars, fmt.Sprintf("%s a%v;", a, i)) + wcall.CommonCode += fmt.Sprintf("\ta%v = (%s)ureg->%s;\n", i, a, uregArg(i)) + } + wcall.ExecCode += "\tret->" + wcall.SysRetField + " = sys" + call.Name + "(" + for i, _ := range(call.Args){ + if i > 0 { + wcall.ExecCode += ", " + } + wcall.ExecCode += fmt.Sprintf("a%v", i) + } + wcall.ExecCode += ");" + + if call.Name == "pwrite"{ + wcall.EntryPrint += formatArg(0, call.Args[0]) + wcall.EntryPrint += "\tfmtrwdata(fmt, (char*)a1, MIN(a2, 64));\n" + wcall.EntryPrint += formatArg(2, call.Args[2]) + wcall.EntryPrint += formatArg(3, call.Args[3]) + } else { + for i, a := range(call.Args){ + wcall.EntryPrint += formatArg(i, a) + } + } + + wcall.ExitPrint += formatRet(call.Ret[0]) + if call.Name == "pread"{ + wcall.ExitPrint += fmt.Sprintf("\tfmtrwdata(fmt, (char*)ureg->%s, MIN(ureg->%s, 64));\n", uregArg(1), uregArg(2)) + } + + code.Wrappers = append(code.Wrappers, *wcall) + code.Externs = append(code.Externs, ext) + } + + tmpl, err := template.New("systab.c").Parse(`/* + * This file is part of Jehanne. + * + * Copyright (C) 2016 Giacomo Tesio + * + * Jehanne is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * Jehanne is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jehanne. If not, see . + */ +/* automatically generated by ksyscalls */ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" +#include "ureg.h" + +extern void fmtrwdata(Fmt* f, char* a, int n); +extern void fmtuserstring(Fmt* f, const char* a); +extern void fmtuserstringlist(Fmt* f, const char** argv); + +{{ range .Externs }}{{.}}{{ end }} +{{ range .Wrappers }} +static void +wrap_{{ .Name }}(ScRet* ret, Ureg* ureg) +{ + {{ range .Vars }}{{.}} + {{ end }} +{{ .CommonCode }} +{{ .ExecCode }} +} +{{ end }} +int nsyscall = {{len .Wrappers}}; + +ScRet +default_syscall_ret(int syscall) +{ + static ScRet zero; + ScRet ret = zero; + switch(syscall){ + {{ range .Wrappers }}case {{ .Id }}: + {{ .DefaultRet }} + break; + {{ end }} + default: + ret.vl = -1; + break; + } + return ret; +} + +char* +syscall_name(int syscall) +{ + switch(syscall){ + {{ range .Wrappers }}case {{ .Id }}: + return "{{ .Name }}"; + {{ end }} + default: + return nil; + } +} + +void +dispatch_syscall(int syscall, Ureg* ureg, ScRet* ret) +{ + switch(syscall){ + {{ range .Wrappers }}case {{ .Id }}: + wrap_{{ .Name }}(ret, ureg); + break; + {{ end }} + default: + panic("dispatch_syscall: bad sys call number %d pc %#p\n", syscall, ureg->ip); + } +} + +{{ range .Wrappers }} +static void +enter_{{ .Name }}(Fmt* fmt, Ureg* ureg) +{ + {{ range .Vars }}{{.}} + {{ end }} +{{ .CommonCode }} + fmtprint(fmt, "{{ .Name }} %#p > ", ureg->ip); +{{ .EntryPrint }} +} +{{ end }} + +char* +syscallfmt(int syscall, Ureg* ureg) +{ + Fmt fmt; + fmtstrinit(&fmt); + fmtprint(&fmt, "%d %s ", up->pid, up->text); + + switch(syscall){ + {{ range .Wrappers }}case {{ .Id }}: + enter_{{ .Name }}(&fmt, ureg); + break; + {{ end }} + default: + panic("syscallfmt: bad sys call number %d pc %#p\n", syscall, ureg->ip); + } + + return fmtstrflush(&fmt); +} + +{{ range .Wrappers }} +static void +exit_{{ .Name }}(Fmt* fmt, Ureg* ureg, ScRet* ret) +{ + fmtprint(fmt, "{{ .Name }} %#p < ", ureg->ip); +{{ .ExitPrint }} +} +{{ end }} + +char* +sysretfmt(int syscall, Ureg* ureg, ScRet* ret, uint64_t start, uint64_t stop) +{ + Fmt fmt; + fmtstrinit(&fmt); + fmtprint(&fmt, "%d %s ", up->pid, up->text); + + switch(syscall){ + {{ range .Wrappers }}case {{ .Id }}: + exit_{{ .Name }}(&fmt, ureg, ret); + break; + {{ end }} + default: + panic("sysretfmt: bad sys call number %d pc %#p\n", syscall, ureg->ip); + } + + if(0 > ret->vl){ + fmtprint(&fmt, " %s %#llud %#llud\n", up->syserrstr, start, stop-start); + } else { + fmtprint(&fmt, " \"\" %#llud %#llud\n", start, stop-start); + } + + return fmtstrflush(&fmt); +} + +`) + err = tmpl.Execute(os.Stdout, code) + if err != nil { + log.Fatal(err) + } +} + +func main() { + + flag.Parse() + + if flag.NArg() != 1 { + usage("no path to sysconf.json") + } + + buf, err := ioutil.ReadFile(flag.Arg(0)) + if err != nil { + log.Fatal(err) + } + + var sysconf Sysconf + err = json.Unmarshal(buf, &sysconf) + if err != nil { + log.Fatal(err) + } + + generateKernelCode(sysconf.Syscalls) + +} \ No newline at end of file diff --git a/src/jehanne/cmd/mksys/mksys.go b/src/jehanne/cmd/mksys/mksys.go index 2595cec..0bc68ac 100644 --- a/src/jehanne/cmd/mksys/mksys.go +++ b/src/jehanne/cmd/mksys/mksys.go @@ -258,9 +258,9 @@ const( #include "mem.h" #include "dat.h" #include "fns.h" -#include "../../libc/9syscall/sys.h" +#include <9syscall/sys.h> -{{ range . }}extern void {{ .Sysname }}(Ar0*, ...); +{{ range . }}extern void {{ .Sysname }}(ScRet*, ScArg, ScArg, ScArg, ScArg, ScArg, ScArg); {{ end }} Systab systab[] = { {{ range . }}[{{ .Define }}] { "{{ .Name }}", {{ .Sysname }}, {{ .Fudge }} }, diff --git a/src/jehanne/cmd/usyscalls/usyscalls.go b/src/jehanne/cmd/usyscalls/usyscalls.go new file mode 100644 index 0000000..7db8d1f --- /dev/null +++ b/src/jehanne/cmd/usyscalls/usyscalls.go @@ -0,0 +1,291 @@ +/* + * This file is part of Jehanne. + * + * Copyright (C) 2016 Giacomo Tesio + * + * Jehanne is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * Jehanne is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jehanne. If not, see . + */ +package main + +import ( + "encoding/json" + "flag" + "fmt" + "io/ioutil" + "log" + "os" + "strings" + "text/template" +) + +const gplHeader string = `/* + * This file is part of Jehanne. + * + * Copyright (C) 2016 Giacomo Tesio + * + * Jehanne is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * Jehanne is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jehanne. If not, see . + */ +/* automatically generated by usyscalls */ +` + +type SyscallConf struct { + Ret []string + Args []string + Name string + Id uint32 +} + +type Sysconf struct { + Syscalls []SyscallConf +} + +type SyscallWrapper struct { + Id uint32 + Name string + FuncArgs string + MacroArgs string + VarValues []string + Vars []string + AsmArgs string + AsmClobbers string + RetType string +} + +type HeaderCode struct { + Wrappers []SyscallWrapper +} + + +func usage(msg string) { + fmt.Fprint(os.Stderr, msg) + fmt.Fprint(os.Stderr, "Usage: usyscalls header|code path/to/sysconf.json\n") + flag.PrintDefaults() + os.Exit(1) +} + +func argTypeName(t string) string{ + switch(t){ + case "int", "int32_t": + return "i" + case "unsigned int", "uint32_t": + /* unsigned int is reserved for flags */ + return "ui" + case "long", "int64_t": + return "l" + case "unsigned long", "uint64_t": + return "ul" + case "void*", "uint8_t*", "const void*", "const uint8_t*": + return "p" + case "int32_t*", "int*", "const int32_t*", "const int*": + return "p" + case "const char*", "char*": + return "p" + case "const char**", "char**": + return "p" + } + return " [?? " + t + "]" + +} + +func argRegister(index int, t string) string{ + prefix := "" + switch(t){ + case "int", "unsigned int", "uint32_t", "int32_t": + prefix = "e" + default: + prefix = "r" + } + switch(index){ + case 0: + return prefix + "di"; + case 1: + return prefix + "si"; + case 2: + return prefix + "dx"; + case 3: + return "r10"; + case 4: + return "r8"; + case 5: + return "r9"; + } + return "" +} + +func getHeaderData(calls []SyscallConf) *HeaderCode { + code := new(HeaderCode) + for _, call := range(calls) { + wcall := new(SyscallWrapper) + wcall.Id = call.Id + wcall.Name = call.Name + wcall.RetType = call.Ret[0] + + clobberMemory := false + wcall.AsmClobbers = "\"cc\", \"rcx\", \"r11\"" + wcall.AsmArgs = fmt.Sprintf("\"0\"(%d)", wcall.Id) + for i, a := range(call.Args){ + if i > 0 { + wcall.FuncArgs += ", " + wcall.MacroArgs += ", " + } + if strings.HasSuffix(a, "*") && !strings.HasPrefix(a, "const"){ + clobberMemory = true + } + wcall.FuncArgs += fmt.Sprintf("%s a%d", a, i) + wcall.MacroArgs += fmt.Sprintf("/* %s */ a%d", a, i) + wcall.VarValues = append(wcall.VarValues, fmt.Sprintf("_sysargs[%d].%s = (a%d); \\\n\t", i, argTypeName(a), i)) + wcall.Vars = append(wcall.Vars, fmt.Sprintf("register %s __r%d asm(\"%s\") = _sysargs[%d].%s; \\\n\t", a, i, argRegister(i, a), i, argTypeName(a))) + wcall.AsmArgs += fmt.Sprintf(", \"r\"(__r%d)", i) + } + if clobberMemory { + wcall.AsmClobbers += ", \"memory\"" + } + code.Wrappers = append(code.Wrappers, *wcall) + } + + return code +} + +func generateSyscallTable(calls []SyscallConf){ + code := getHeaderData(calls) + tmpl, err := template.New("tab.c").Parse(` +{{ range .Wrappers }}"{{ .Name }}", (int(*)()) {{ .Name }}, +{{ end }} +`) + err = tmpl.Execute(os.Stdout, code) + if err != nil { + log.Fatal(err) + } +} + +func generateLibcCode(calls []SyscallConf){ + code := getHeaderData(calls) + tmpl, err := template.New("syscalls.c").Parse(gplHeader + ` +#define PORTABLE_SYSCALLS +#include + +{{ range .Wrappers }} +{{ .RetType }} +{{ .Name }}({{ .FuncArgs }}) +{ + register {{ .RetType }} __ret asm ("rax"); + __asm__ __volatile__ ( + "movq %%rcx, %%r10" "\n\t" + "movq ${{ .Id }}, %%rax" "\n\t" + "syscall" + : "=r" (__ret) + : /* args are ready */ + : {{ .AsmClobbers }} + ); + return __ret; +} +{{ end }} +`) + err = tmpl.Execute(os.Stdout, code) + if err != nil { + log.Fatal(err) + } +} + +func generateSyscallHeader(calls []SyscallConf){ + funcMap := template.FuncMap{ + "title": strings.Title, + } + code := getHeaderData(calls) + tmpl, err := template.New("syscall.h").Funcs(funcMap).Parse(gplHeader + ` +typedef enum Syscalls +{ +{{ range .Wrappers }} Sys{{ .Name|title }} = {{ .Id }}, +{{ end }}} Syscalls; + +#ifndef KERNEL +{{ range .Wrappers }} +#define sys_{{ .Name }}({{ .MacroArgs }}) ({ \ + {{ range .VarValues }}{{.}}{{end}}{{ range .Vars }}{{.}}{{end}}register {{ .RetType }} __ret asm ("rax"); \ + __asm__ __volatile__ ( \ + "syscall" \ + : "=&r" (__ret) \ + : {{ .AsmArgs }} \ + : {{ .AsmClobbers }} \ + ); \ + __ret; }) +{{ end }} + +#ifdef PORTABLE_SYSCALLS + +{{ range .Wrappers }}extern {{ .RetType }} {{ .Name }}({{ .FuncArgs }}); +{{ end }} +extern int32_t read(int, void*, int32_t); +extern int32_t write(int, const void*, int32_t); + +#else + +{{ range .Wrappers }}# define {{ .Name }}(...) sys_{{ .Name }}(__VA_ARGS__) +{{ end }} +#define read(fd, buf, size) pread(fd, buf, size, -1) +#define write(fd, buf, size) pwrite(fd, buf, size, -1) + +#endif + +#endif +`) + err = tmpl.Execute(os.Stdout, code) + if err != nil { + log.Fatal(err) + } +} + +func main() { + + flag.Parse() + + if flag.NArg() != 2 { + usage("no path to sysconf.json") + } + + buf, err := ioutil.ReadFile(flag.Arg(1)) + if err != nil { + log.Fatal(err) + } + + var sysconf Sysconf + err = json.Unmarshal(buf, &sysconf) + if err != nil { + log.Fatal(err) + } + mode := flag.Arg(0) + switch(mode){ + case "header": + generateSyscallHeader(sysconf.Syscalls) + break + case "code": + generateLibcCode(sysconf.Syscalls) + break + case "tab": + generateSyscallTable(sysconf.Syscalls) + break + } + + + +} \ No newline at end of file