diff --git a/pkgs/os-specific/linux/minimal-bootstrap/default.nix b/pkgs/os-specific/linux/minimal-bootstrap/default.nix new file mode 100644 index 0000000000000..509b7fe205933 --- /dev/null +++ b/pkgs/os-specific/linux/minimal-bootstrap/default.nix @@ -0,0 +1,24 @@ +{ lib +, config +, buildPlatform +, hostPlatform +}: + +lib.makeScope + # Prevent using top-level attrs to protect against introducing dependency on + # non-bootstrap packages by mistake. Any top-level inputs must be explicitly + # declared here. + (extra: lib.callPackageWith ({ inherit lib config buildPlatform hostPlatform; } // extra)) + (self: with self; { + inherit (callPackage ./utils.nix { }) fetchurl derivationWithMeta writeTextFile writeText runCommand; + + inherit (callPackage ./stage0-posix { }) kaem m2libc mescc-tools mescc-tools-extra; + + mes = callPackage ./mes { }; + mes-libc = callPackage ./mes/libc.nix { }; + + ln-boot = callPackage ./ln-boot { }; + + tinycc-bootstrappable = callPackage ./tinycc/bootstrappable.nix { }; + tinycc-mes = callPackage ./tinycc/mes.nix { }; + }) diff --git a/pkgs/os-specific/linux/minimal-bootstrap/ln-boot/default.nix b/pkgs/os-specific/linux/minimal-bootstrap/ln-boot/default.nix new file mode 100644 index 0000000000000..23c634421cbea --- /dev/null +++ b/pkgs/os-specific/linux/minimal-bootstrap/ln-boot/default.nix @@ -0,0 +1,27 @@ +{ lib +, runCommand +, mes +}: +let + pname = "ln-boot"; + version = "unstable-2023-05-01"; + + src = ./ln.c; +in +runCommand "${pname}-${version}" { + inherit pname version; + + meta = with lib; { + description = "Basic tool for creating symbolic links"; + license = licenses.mit; + maintainers = with maintainers; [ emilytrau ]; + mainProgram = "ln"; + platforms = platforms.unix; + }; +} '' + mkdir -p ''${out}/bin + ${mes}/bin/mes --no-auto-compile -e main ${mes}/bin/mescc.scm -- \ + -lc+tcc \ + -o ''${out}/bin/ln \ + ${src} +'' diff --git a/pkgs/os-specific/linux/minimal-bootstrap/ln-boot/ln.c b/pkgs/os-specific/linux/minimal-bootstrap/ln-boot/ln.c new file mode 100644 index 0000000000000..c8dde76a93648 --- /dev/null +++ b/pkgs/os-specific/linux/minimal-bootstrap/ln-boot/ln.c @@ -0,0 +1,17 @@ +#include +#include +#include +#include + +int main(int argc, char** argv) +{ + if (argc != 4 || strcmp(argv[1], "-s")) { + fputs("Usage: ", stdout); + fputs(argv[0], stdout); + fputs("ln -s TARGET LINK_NAME\n", stdout); + exit(EXIT_FAILURE); + } + + symlink(argv[2], argv[3]); + exit(EXIT_SUCCESS); +} diff --git a/pkgs/os-specific/linux/minimal-bootstrap/mes/default.nix b/pkgs/os-specific/linux/minimal-bootstrap/mes/default.nix new file mode 100644 index 0000000000000..abf3955eb2d9a --- /dev/null +++ b/pkgs/os-specific/linux/minimal-bootstrap/mes/default.nix @@ -0,0 +1,189 @@ +{ lib +, runCommand +, fetchurl +, writeText +, callPackage +, m2libc +, mescc-tools +}: +let + pname = "mes"; + version = "0.24.2"; + + src = fetchurl { + url = "mirror://gnu/mes/mes-${version}.tar.gz"; + sha256 = "0vp8v88zszh1imm3dvdfi3m8cywshdj7xcrsq4cgmss69s2y1nkx"; + }; + + nyacc = callPackage ./nyacc.nix { inherit nyacc; }; + + config_h = builtins.toFile "config.h" '' + #undef SYSTEM_LIBC + #define MES_VERSION "${version}" + ''; + + sources = (import ./sources.nix).x86.linux.mescc; + inherit (sources) libc_mini_SOURCES libmescc_SOURCES libc_SOURCES mes_SOURCES; + + # add symlink() to libc+tcc so we can use it in ln-boot + libc_tcc_SOURCES = sources.libc_tcc_SOURCES ++ [ "lib/linux/symlink.c" ]; + + compile = sources: + lib.concatMapStringsSep + "\n" + (f: ''CC -c ''${MES_PREFIX}/${f}'') + sources; + replaceExt = ext: source: + lib.replaceStrings + [ ".c" ] + [ ext ] + (builtins.baseNameOf source); + archive = out: sources: + "catm ${out} ${lib.concatMapStringsSep " " (replaceExt ".o") sources}"; + sourceArchive = out: sources: + "catm ${out} ${lib.concatMapStringsSep " " (replaceExt ".s") sources}"; +in +runCommand "${pname}-${version}" { + inherit pname version; + + passthru = { inherit src nyacc; }; + + meta = with lib; { + description = "Scheme interpreter and C compiler for bootstrapping"; + homepage = "https://www.gnu.org/software/mes"; + license = licenses.gpl3Plus; + maintainers = with maintainers; [ emilytrau ]; + platforms = [ "i686-linux" ]; + }; +} +# Maintenance note: +# Build steps have been adapted from build-aux/bootstrap.sh.in +# as well as the live-bootstrap project +# https://github.com/fosslinux/live-bootstrap/blob/1bc4296091c51f53a5598050c8956d16e945b0f5/sysa/mes-0.24.2/mes-0.24.2.kaem +'' + # Unpack source + ungz --file ${src} --output mes.tar + mkdir ''${out} ''${out}/bin ''${out}/share + cd ''${out}/share + untar --non-strict --file ''${NIX_BUILD_TOP}/mes.tar # ignore symlinks + + MES_PREFIX=''${out}/share/mes-${version} + LIBDIR=''${MES_PREFIX}/lib + + cd ''${MES_PREFIX} + + cp ${config_h} include/mes/config.h + + mkdir include/arch + cp include/linux/x86/syscall.h include/arch/syscall.h + cp include/linux/x86/kernel-stat.h include/arch/kernel-stat.h + + # Remove pregenerated files + rm mes/module/mes/psyntax.pp mes/module/mes/psyntax.pp.header + + # These files are symlinked in the repo + cp mes/module/srfi/srfi-9-struct.mes mes/module/srfi/srfi-9.mes + cp mes/module/srfi/srfi-9/gnu-struct.mes mes/module/srfi/srfi-9/gnu.mes + + # Fixes to support newer M2-Planet + catm x86_defs.M1 ${m2libc}/x86/x86_defs.M1 lib/m2/x86/x86_defs.M1 + cp x86_defs.M1 lib/m2/x86/x86_defs.M1 + rm x86_defs.M1 + + # Remove environment impurities + __GUILE_LOAD_PATH="\"''${MES_PREFIX}/mes/module:''${MES_PREFIX}/module:${nyacc.guilePath}\"" + boot0_scm=mes/module/mes/boot-0.scm + guile_mes=mes/module/mes/guile.mes + replace --file ''${boot0_scm} --output ''${boot0_scm} --match-on "(getenv \"GUILE_LOAD_PATH\")" --replace-with ''${__GUILE_LOAD_PATH} + replace --file ''${guile_mes} --output ''${guile_mes} --match-on "(getenv \"GUILE_LOAD_PATH\")" --replace-with ''${__GUILE_LOAD_PATH} + + module_mescc_scm=module/mescc/mescc.scm + replace --file ''${module_mescc_scm} --output ''${module_mescc_scm} --match-on "(getenv \"M1\")" --replace-with "\"${mescc-tools}/bin/M1\"" + replace --file ''${module_mescc_scm} --output ''${module_mescc_scm} --match-on "(getenv \"HEX2\")" --replace-with "\"${mescc-tools}/bin/hex2\"" + replace --file ''${module_mescc_scm} --output ''${module_mescc_scm} --match-on "(getenv \"BLOOD_ELF\")" --replace-with "\"${mescc-tools}/bin/blood-elf\"" + replace --file ''${module_mescc_scm} --output ''${module_mescc_scm} --match-on "(getenv \"srcdest\")" --replace-with "\"''${MES_PREFIX}\"" + + mes_c=src/mes.c + replace --file ''${mes_c} --output ''${mes_c} --match-on "getenv (\"MES_PREFIX\")" --replace-with "\"''${MES_PREFIX}\"" + replace --file ''${mes_c} --output ''${mes_c} --match-on "getenv (\"srcdest\")" --replace-with "\"''${MES_PREFIX}\"" + + # Increase runtime resource limits + gc_c=src/gc.c + replace --file ''${gc_c} --output ''${gc_c} --match-on "getenv (\"MES_ARENA\")" --replace-with "\"100000000\"" + replace --file ''${gc_c} --output ''${gc_c} --match-on "getenv (\"MES_MAX_ARENA\")" --replace-with "\"100000000\"" + replace --file ''${gc_c} --output ''${gc_c} --match-on "getenv (\"MES_STACK\")" --replace-with "\"6000000\"" + + # Create mescc.scm + mescc_in=scripts/mescc.scm.in + replace --file ''${mescc_in} --output ''${mescc_in} --match-on "(getenv \"MES_PREFIX\")" --replace-with "\"''${MES_PREFIX}\"" + replace --file ''${mescc_in} --output ''${mescc_in} --match-on "(getenv \"includedir\")" --replace-with "\"''${MES_PREFIX}/include\"" + replace --file ''${mescc_in} --output ''${mescc_in} --match-on "(getenv \"libdir\")" --replace-with "\"''${MES_PREFIX}/lib\"" + replace --file ''${mescc_in} --output ''${mescc_in} --match-on @prefix@ --replace-with ''${MES_PREFIX} + replace --file ''${mescc_in} --output ''${mescc_in} --match-on @VERSION@ --replace-with ${version} + replace --file ''${mescc_in} --output ''${mescc_in} --match-on @mes_cpu@ --replace-with x86 + replace --file ''${mescc_in} --output ''${mescc_in} --match-on @mes_kernel@ --replace-with linux + cp ''${mescc_in} ''${out}/bin/mescc.scm + + # Build mes-m2 + mes_cpu=x86 + stage0_cpu=x86 + kaem --verbose --strict --file kaem.run + cp bin/mes-m2 ''${out}/bin/mes-m2 + chmod 555 ''${out}/bin/mes-m2 + + + # Recompile Mes and Mes C library using mes-m2 bootstrapped Mes + cd ''${NIX_BUILD_TOP} + alias CC="''${out}/bin/mes-m2 -e main ''${out}/bin/mescc.scm -- -D HAVE_CONFIG_H=1 -I ''${MES_PREFIX}/include -I ''${MES_PREFIX}/include/linux/x86" + mkdir -p ''${LIBDIR}/x86-mes + + # crt1.o + CC -c ''${MES_PREFIX}/lib/linux/x86-mes-mescc/crt1.c + cp crt1.o ''${LIBDIR}/x86-mes + cp crt1.s ''${LIBDIR}/x86-mes + + # libc-mini.a + ${compile libc_mini_SOURCES} + ${archive "libc-mini.a" libc_mini_SOURCES} + ${sourceArchive "libc-mini.s" libc_mini_SOURCES} + cp libc-mini.a ''${LIBDIR}/x86-mes + cp libc-mini.s ''${LIBDIR}/x86-mes + + # libmescc.a + ${compile libmescc_SOURCES} + ${archive "libmescc.a" libmescc_SOURCES} + ${sourceArchive "libmescc.s" libmescc_SOURCES} + cp libmescc.a ''${LIBDIR}/x86-mes + cp libmescc.s ''${LIBDIR}/x86-mes + + # libc.a + ${compile libc_SOURCES} + ${archive "libc.a" libc_SOURCES} + ${sourceArchive "libc.s" libc_SOURCES} + cp libc.a ''${LIBDIR}/x86-mes + cp libc.s ''${LIBDIR}/x86-mes + + # libc+tcc.a + # optimisation: don't recompile common libc sources + ${compile (lib.subtractLists libc_SOURCES libc_tcc_SOURCES)} + ${archive "libc+tcc.a" libc_tcc_SOURCES} + ${sourceArchive "libc+tcc.s" libc_tcc_SOURCES} + cp libc+tcc.a ''${LIBDIR}/x86-mes + cp libc+tcc.s ''${LIBDIR}/x86-mes + + # Build mes itself + ${compile mes_SOURCES} + ''${out}/bin/mes-m2 -e main ''${out}/bin/mescc.scm -- \ + --base-address 0x08048000 \ + -L ''${MES_PREFIX}/lib \ + -L . \ + -lc \ + -lmescc \ + -nostdlib \ + -o ''${out}/bin/mes \ + crt1.o \ + ${lib.concatMapStringsSep " " (replaceExt ".o") mes_SOURCES} + + # Check + ''${out}/bin/mes --version +'' diff --git a/pkgs/os-specific/linux/minimal-bootstrap/mes/gen-sources.sh b/pkgs/os-specific/linux/minimal-bootstrap/mes/gen-sources.sh new file mode 100755 index 0000000000000..3a734129c1f75 --- /dev/null +++ b/pkgs/os-specific/linux/minimal-bootstrap/mes/gen-sources.sh @@ -0,0 +1,95 @@ +#!/usr/bin/env nix-shell +#!nix-shell -i bash -p bash coreutils gnutar + +# Generate a sources.nix for a version of GNU mes. Creates lists of source files +# from build-aux/configure-lib.sh. +# +# You may point this tool at a manually downloaded tarball, but more ideal is +# using the source tarball from Nixpkgs. For example: +# +# MES_TARBALL="$(nix-build --no-link -A minimal-bootstrap.mes.src ../../../../..)" +# ./gen-sources.sh "$MES_TARBALL" > ./new-sources.nix + +set -eu + +# Supported platforms +ARCHS="x86" +KERNELS="linux" +COMPILERS="mescc gcc" + + +format() { + echo -n "[ " + # Terrible hack to convert a newline-delimited string to space-delimited + echo $* | xargs printf '"%s" ' + echo -n "]" +} + +gen_sources() { + # Configuration variables used by configure-lib.sh + export mes_libc=mes + export mes_cpu=$1 + export mes_kernel=$2 + export compiler=$3 + + # Populate source file lists + source $CONFIGURE_LIB_SH + + cat <&2 + exit 1 +fi +echo "Generating sources.nix from $MES_TARBALL" >&2 + +TMP=$(mktemp -d) +cd $TMP +echo "Workdir: $TMP" >&2 + +echo "Extracting $MES_TARBALL" >&2 +tar --strip-components 1 -xf $MES_TARBALL + +CONFIGURE_LIB_SH="$TMP/build-aux/configure-lib.sh" +if [ ! -f $CONFIGURE_LIB_SH ]; then + echo "Could not find mes's configure-lib.sh script at $CONFIGURE_LIB_SH" >&2 + exit 1 +fi + +# Create dummy config expected by configure-lib.sh +touch config.sh +chmod +x config.sh + + +echo "Configuring with $CONFIGURE_LIB_SH" >&2 + +cat < { + name = "hex0-seed-${version}"; + url = "https://github.com/oriansj/bootstrap-seeds/raw/b1263ff14a17835f4d12539226208c426ced4fba/POSIX/x86/hex0-seed"; + hash = "sha256-QU3RPGy51W7M2xnfFY1IqruKzusrSLU+L190ztN6JW8="; + executable = true; + }; + + # Packaged resources required for the first bootstrapping stage. + # Contains source code and 256-byte hex0 binary seed. + # + # We don't have access to utilities such as fetchgit and fetchzip since this + # is this is part of the bootstrap process and would introduce a circular + # dependency. The only tool we have to fetch source trees is `import ` + # with the unpack option, taking a NAR file as input. This requires source + # tarballs to be repackaged. + # + # To build see `make-bootstrap-sources.nix` + src = import { + inherit name; + url = "https://github.com/emilytrau/bootstrap-tools-nar-mirror/releases/download/2023-05-02/${name}.nar.xz"; + hash = "sha256-ZRG0k49MxL1UTZhuMTvPoEprdSpJRNVy8QhLE6k+etg="; + unpack = true; + }; +} diff --git a/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/default.nix b/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/default.nix new file mode 100644 index 0000000000000..650644f6ef029 --- /dev/null +++ b/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/default.nix @@ -0,0 +1,20 @@ +{ lib +, newScope +}: + +lib.makeScope newScope (self: with self; { + inherit (import ./bootstrap-sources.nix) version hex0-seed src; + + m2libc = src + "/M2libc"; + + hex0 = callPackage ./hex0.nix { }; + + kaem = callPackage ./kaem { }; + kaem-minimal = callPackage ./kaem/minimal.nix { }; + + inherit (callPackage ./stage0-posix-x86.nix { }) blood-elf-0 hex2 kaem-unwrapped M1 M2; + + mescc-tools = callPackage ./mescc-tools { }; + + mescc-tools-extra = callPackage ./mescc-tools-extra { }; +}) diff --git a/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/hex0.nix b/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/hex0.nix new file mode 100644 index 0000000000000..0d8c3b18b0b97 --- /dev/null +++ b/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/hex0.nix @@ -0,0 +1,28 @@ +{ lib +, derivationWithMeta +, hex0-seed +, src +, version +}: +derivationWithMeta { + inherit version; + pname = "hex0"; + builder = hex0-seed; + args = [ + "${src}/bootstrap-seeds/POSIX/x86/hex0_x86.hex0" + (placeholder "out") + ]; + + meta = with lib; { + description = "Minimal assembler for bootstrapping"; + homepage = "https://github.com/oriansj/stage0-posix"; + license = licenses.gpl3Plus; + maintainers = with maintainers; [ emilytrau ]; + platforms = [ "i686-linux" ]; + }; + + # Ensure the untrusted hex0-seed binary produces a known-good hex0 + outputHashMode = "recursive"; + outputHashAlgo = "sha256"; + outputHash = "sha256-QU3RPGy51W7M2xnfFY1IqruKzusrSLU+L190ztN6JW8="; +} diff --git a/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/kaem/default.nix b/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/kaem/default.nix new file mode 100644 index 0000000000000..2af660ad7a44d --- /dev/null +++ b/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/kaem/default.nix @@ -0,0 +1,33 @@ +{ lib +, derivationWithMeta +, kaem-unwrapped +, mescc-tools-extra +, version +}: + +# Once mescc-tools-extra is available we can install kaem at /bin/kaem +# to make it findable in environments +derivationWithMeta { + inherit version kaem-unwrapped; + pname = "kaem"; + builder = kaem-unwrapped; + args = [ + "--verbose" + "--strict" + "--file" + (builtins.toFile "kaem-wrapper.kaem" '' + mkdir -p ''${out}/bin + cp ''${kaem-unwrapped} ''${out}/bin/kaem + chmod 555 ''${out}/bin/kaem + '') + ]; + PATH = lib.makeBinPath [ mescc-tools-extra ]; + + meta = with lib; { + description = "Minimal build tool for running scripts on systems that lack any shell"; + homepage = "https://github.com/oriansj/mescc-tools"; + license = licenses.gpl3Plus; + maintainers = with maintainers; [ emilytrau ]; + platforms = [ "i686-linux" ]; + }; +} diff --git a/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/kaem/minimal.nix b/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/kaem/minimal.nix new file mode 100644 index 0000000000000..2fa1cefd7227b --- /dev/null +++ b/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/kaem/minimal.nix @@ -0,0 +1,24 @@ +{ lib +, derivationWithMeta +, src +, hex0 +, version +}: +derivationWithMeta { + inherit version; + pname = "kaem-minimal"; + builder = hex0; + args = [ + "${src}/bootstrap-seeds/POSIX/x86/kaem-minimal.hex0" + (placeholder "out") + ]; + + meta = with lib; { + description = "First stage minimal scriptable build tool for bootstrapping"; + homepage = "https://github.com/oriansj/stage0-posix"; + license = licenses.gpl3Plus; + maintainers = with maintainers; [ emilytrau ]; + platforms = [ "i686-linux" ]; + }; +} + diff --git a/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/make-bootstrap-sources.nix b/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/make-bootstrap-sources.nix new file mode 100644 index 0000000000000..fec03f370bc38 --- /dev/null +++ b/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/make-bootstrap-sources.nix @@ -0,0 +1,46 @@ +# Packaged resources required for the first bootstrapping stage. +# Contains source code and 256-byte hex0 binary seed. +# +# We don't have access to utilities such as fetchgit and fetchzip since this +# is this is part of the bootstrap process and would introduce a circular +# dependency. The only tool we have to fetch source trees is `import ` +# with the unpack option, taking a NAR file as input. This requires source +# tarballs to be repackaged. +# +# To build: +# +# nix-build pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/make-bootstrap-sources.nix +# => ./result/stage0-posix-$version-$rev-source.nar.xz +# + +{ pkgs ? import ../../../../.. {} }: +let + inherit (pkgs) callPackage runCommand fetchFromGitHub nix xz; + + inherit (import ./bootstrap-sources.nix) name rev; + + src = fetchFromGitHub { + owner = "oriansj"; + repo = "stage0-posix"; + inherit rev; + sha256 = "sha256-ZRG0k49MxL1UTZhuMTvPoEprdSpJRNVy8QhLE6k+etg="; + fetchSubmodules = true; + postFetch = '' + # Remove vendored/duplicate M2libc's + echo "Removing duplicate M2libc" + rm -rf \ + $out/M2-Mesoplanet/M2libc \ + $out/M2-Planet/M2libc \ + $out/mescc-tools/M2libc \ + $out/mescc-tools-extra/M2libc + ''; + }; +in +runCommand name { + nativeBuildInputs = [ nix xz ]; + + passthru = { inherit src; }; +} '' + mkdir $out + nix-store --dump ${src} | xz -c > "$out/${name}.nar.xz" +'' diff --git a/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/mescc-tools-extra/build.kaem b/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/mescc-tools-extra/build.kaem new file mode 100644 index 0000000000000..e50fc1c68474d --- /dev/null +++ b/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/mescc-tools-extra/build.kaem @@ -0,0 +1,39 @@ +# This is a modified version of mescc-tools-extra/mescc-tools-extra.kaem +# https://github.com/oriansj/mescc-tools-extra/blob/ec53af69d6d2119b47b369cd0ec37ac806e7ad60/mescc-tools-extra.kaem +# - Paths to build inputs have been changed for nix +# - Added additional step to create $out directory + +## Copyright (C) 2017 Jeremiah Orians +## This file is part of mescc-tools. +## +## mescc-tools 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. +## +## mescc-tools 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 mescc-tools. If not, see . + +alias CC="${mescc-tools}/bin/M2-Mesoplanet --operating-system ${OPERATING_SYSTEM} --architecture ${ARCH} -f" +cd ${src}/mescc-tools-extra + +# Create output folder +CC mkdir.c -o ${TMP}/mkdir +${TMP}/mkdir -p ${out}/bin + +CC sha256sum.c -o ${out}/bin/sha256sum +CC match.c -o ${out}/bin/match +CC mkdir.c -o ${out}/bin/mkdir +CC untar.c -o ${out}/bin/untar +CC ungz.c -o ${out}/bin/ungz +CC unbz2.c -o ${out}/bin/unbz2 +CC catm.c -o ${out}/bin/catm +CC cp.c -o ${out}/bin/cp +CC chmod.c -o ${out}/bin/chmod +CC rm.c -o ${out}/bin/rm +CC replace.c -o ${out}/bin/replace diff --git a/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/mescc-tools-extra/default.nix b/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/mescc-tools-extra/default.nix new file mode 100644 index 0000000000000..2d8c2a5334d6b --- /dev/null +++ b/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/mescc-tools-extra/default.nix @@ -0,0 +1,29 @@ +{ lib +, derivationWithMeta +, kaem-unwrapped +, mescc-tools +, src +, version +}: +derivationWithMeta { + inherit version src mescc-tools; + pname = "mescc-tools-extra"; + builder = kaem-unwrapped; + args = [ + "--verbose" + "--strict" + "--file" + ./build.kaem + ]; + + ARCH = "x86"; + OPERATING_SYSTEM = "linux"; + + meta = with lib; { + description = "Collection of tools written for use in bootstrapping"; + homepage = "https://github.com/oriansj/mescc-tools-extra"; + license = licenses.gpl3Plus; + maintainers = with maintainers; [ emilytrau ]; + platforms = [ "i686-linux" ]; + }; +} diff --git a/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/mescc-tools/build.kaem b/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/mescc-tools/build.kaem new file mode 100644 index 0000000000000..3a7ae25fbd828 --- /dev/null +++ b/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/mescc-tools/build.kaem @@ -0,0 +1,204 @@ +# This is a modified version of stage0-posix/x86/mescc-tools-full-kaem.kaem +# https://github.com/oriansj/stage0-posix-x86/blob/56e6b8df3e95f4bc04f8b420a4cd8c82c70b9efa/mescc-tools-full-kaem.kaem +# - Paths to build inputs have been changed for nix + +# Mes --- Maxwell Equations of Software +# Copyright © 2017,2019 Jan Nieuwenhuizen +# Copyright © 2017,2019 Jeremiah Orians +# +# This file is part of Mes. +# +# Mes 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. +# +# Mes 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 Mes. If not, see . + +${mkdir} -p ${out}/bin +${cp} ${M2} ${out}/bin/M2 +${chmod} 0555 ${out}/bin/M2 +${cp} ${M1} ${out}/bin/M1 +${chmod} 0555 ${out}/bin/M1 +${cp} ${hex2} ${out}/bin/hex2 +${chmod} 0555 ${out}/bin/hex2 + +# M2-Mesoplanet searches for runtime dependencies in environment variables +# We can hardcode them with the "replace" utility from mescc-tools-extra +${replace} \ + --file ${src}/M2-Mesoplanet/cc.c \ + --output ./cc_patched.c \ + --match-on "env_lookup(\"M2LIBC_PATH\")" \ + --replace-with "\"${m2libc}\"" +${replace} \ + --file ${src}/M2-Mesoplanet/cc_spawn.c \ + --output ./cc_spawn_patched.c \ + --match-on "env_lookup(\"PATH\")" \ + --replace-with "\"${out}/bin:\"" + +############################################### +# Phase-12 Build M2-Mesoplanet from M2-Planet # +############################################### + +${M2} --architecture ${ARCH} \ + -f ${m2libc}/sys/types.h \ + -f ${m2libc}/stddef.h \ + -f ${m2libc}/${ARCH}/linux/fcntl.c \ + -f ${m2libc}/fcntl.c \ + -f ${m2libc}/${ARCH}/linux/unistd.c \ + -f ${m2libc}/${ARCH}/linux/sys/stat.c \ + -f ${m2libc}/stdlib.c \ + -f ${m2libc}/stdio.h \ + -f ${m2libc}/stdio.c \ + -f ${m2libc}/string.c \ + -f ${m2libc}/bootstrappable.c \ + -f ${src}/M2-Mesoplanet/cc.h \ + -f ${src}/M2-Mesoplanet/cc_globals.c \ + -f ${src}/M2-Mesoplanet/cc_env.c \ + -f ${src}/M2-Mesoplanet/cc_reader.c \ + -f ./cc_spawn_patched.c \ + -f ${src}/M2-Mesoplanet/cc_core.c \ + -f ${src}/M2-Mesoplanet/cc_macro.c \ + -f ./cc_patched.c \ + --debug \ + -o ./M2-Mesoplanet-1.M1 + +${blood-elf-0} ${ENDIAN_FLAG} ${BLOOD_FLAG} -f ./M2-Mesoplanet-1.M1 -o ./M2-Mesoplanet-1-footer.M1 + +${M1} --architecture ${ARCH} \ + ${ENDIAN_FLAG} \ + -f ${m2libc}/${ARCH}/${ARCH}_defs.M1 \ + -f ${m2libc}/${ARCH}/libc-full.M1 \ + -f ./M2-Mesoplanet-1.M1 \ + -f ./M2-Mesoplanet-1-footer.M1 \ + -o ./M2-Mesoplanet-1.hex2 + +${hex2} --architecture ${ARCH} \ + ${ENDIAN_FLAG} \ + --base-address ${BASE_ADDRESS} \ + -f ${m2libc}/${ARCH}/ELF-${ARCH}-debug.hex2 \ + -f ./M2-Mesoplanet-1.hex2 \ + -o ${out}/bin/M2-Mesoplanet + +################################################# +# Phase-13 Build final blood-elf from C sources # +################################################# + +${M2} --architecture ${ARCH} \ + -f ${m2libc}/sys/types.h \ + -f ${m2libc}/stddef.h \ + -f ${m2libc}/${ARCH}/linux/fcntl.c \ + -f ${m2libc}/fcntl.c \ + -f ${m2libc}/${ARCH}/linux/unistd.c \ + -f ${m2libc}/stdlib.c \ + -f ${m2libc}/stdio.h \ + -f ${m2libc}/stdio.c \ + -f ${m2libc}/bootstrappable.c \ + -f ${src}/mescc-tools/stringify.c \ + -f ${src}/mescc-tools/blood-elf.c \ + --debug \ + -o ./blood-elf-1.M1 + +${blood-elf-0} ${BLOOD_FLAG} ${ENDIAN_FLAG} -f ./blood-elf-1.M1 -o ./blood-elf-1-footer.M1 +${M1} --architecture ${ARCH} \ + ${ENDIAN_FLAG} \ + -f ${m2libc}/${ARCH}/${ARCH}_defs.M1 \ + -f ${m2libc}/${ARCH}/libc-full.M1 \ + -f ./blood-elf-1.M1 \ + -f ./blood-elf-1-footer.M1 \ + -o ./blood-elf-1.hex2 + +${hex2} --architecture ${ARCH} \ + ${ENDIAN_FLAG} \ + --base-address ${BASE_ADDRESS} \ + -f ${m2libc}/${ARCH}/ELF-${ARCH}-debug.hex2 \ + -f ./blood-elf-1.hex2 \ + -o ${out}/bin/blood-elf + +# Now we have our shipping debuggable blood-elf, the rest will be down hill from +# here as we have ALL of the core pieces of compiling and assembling debuggable +# programs in a debuggable form with corresponding C source code. + +############################################# +# Phase-14 Build get_machine from C sources # +############################################# + +${M2} --architecture ${ARCH} \ + -f ${m2libc}/sys/types.h \ + -f ${m2libc}/stddef.h \ + -f ${m2libc}/${ARCH}/linux/unistd.c \ + -f ${m2libc}/${ARCH}/linux/fcntl.c \ + -f ${m2libc}/fcntl.c \ + -f ${m2libc}/stdlib.c \ + -f ${m2libc}/stdio.h \ + -f ${m2libc}/stdio.c \ + -f ${m2libc}/bootstrappable.c \ + -f ${src}/mescc-tools/get_machine.c \ + --debug \ + -o get_machine.M1 + +${out}/bin/blood-elf ${BLOOD_FLAG} ${ENDIAN_FLAG} -f ./get_machine.M1 -o ./get_machine-footer.M1 + +${M1} --architecture ${ARCH} \ + ${ENDIAN_FLAG} \ + -f ${m2libc}/${ARCH}/${ARCH}_defs.M1 \ + -f ${m2libc}/${ARCH}/libc-full.M1 \ + -f ./get_machine.M1 \ + -f ./get_machine-footer.M1 \ + -o ./get_machine.hex2 + +${hex2} --architecture ${ARCH} \ + ${ENDIAN_FLAG} \ + --base-address ${BASE_ADDRESS} \ + -f ${m2libc}/${ARCH}/ELF-${ARCH}-debug.hex2 \ + -f ./get_machine.hex2 \ + -o ${out}/bin/get_machine + +############################################ +# Phase-15 Build M2-Planet from M2-Planet # +############################################ + +${M2} --architecture ${ARCH} \ + -f ${m2libc}/sys/types.h \ + -f ${m2libc}/stddef.h \ + -f ${m2libc}/${ARCH}/linux/unistd.c \ + -f ${m2libc}/${ARCH}/linux/fcntl.c \ + -f ${m2libc}/fcntl.c \ + -f ${m2libc}/stdlib.c \ + -f ${m2libc}/stdio.h \ + -f ${m2libc}/stdio.c \ + -f ${m2libc}/bootstrappable.c \ + -f ${src}/M2-Planet/cc.h \ + -f ${src}/M2-Planet/cc_globals.c \ + -f ${src}/M2-Planet/cc_reader.c \ + -f ${src}/M2-Planet/cc_strings.c \ + -f ${src}/M2-Planet/cc_types.c \ + -f ${src}/M2-Planet/cc_core.c \ + -f ${src}/M2-Planet/cc_macro.c \ + -f ${src}/M2-Planet/cc.c \ + --debug \ + -o ./M2-1.M1 + +${out}/bin/blood-elf ${ENDIAN_FLAG} ${BLOOD_FLAG} -f ./M2-1.M1 -o ./M2-1-footer.M1 + +${M1} --architecture ${ARCH} \ + ${ENDIAN_FLAG} \ + -f ${m2libc}/${ARCH}/${ARCH}_defs.M1 \ + -f ${m2libc}/${ARCH}/libc-full.M1 \ + -f ./M2-1.M1 \ + -f ./M2-1-footer.M1 \ + -o ./M2-1.hex2 + +${hex2} --architecture ${ARCH} \ + ${ENDIAN_FLAG} \ + --base-address ${BASE_ADDRESS} \ + -f ${m2libc}/${ARCH}/ELF-${ARCH}-debug.hex2 \ + -f ./M2-1.hex2 \ + -o ${out}/bin/M2-Planet + diff --git a/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/mescc-tools/default.nix b/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/mescc-tools/default.nix new file mode 100644 index 0000000000000..a41e6bdeab412 --- /dev/null +++ b/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/mescc-tools/default.nix @@ -0,0 +1,88 @@ +{ lib +, derivationWithMeta +, kaem-unwrapped +, M1 +, M2 +, blood-elf-0 +, hex2 +, m2libc +, src +, version +}: + +let + ARCH = "x86"; + BLOOD_FLAG = " "; + BASE_ADDRESS = "0x8048000"; + ENDIAN_FLAG = "--little-endian"; + + # We need a few tools from mescc-tools-extra to assemble the output folder + buildMesccToolsExtraUtil = name: + derivationWithMeta { + pname = "mescc-tools-extra-${name}"; + builder = kaem-unwrapped; + args = [ + "--verbose" + "--strict" + "--file" + (builtins.toFile "build-${name}.kaem" '' + ''${M2} --architecture ''${ARCH} \ + -f ''${m2libc}/sys/types.h \ + -f ''${m2libc}/stddef.h \ + -f ''${m2libc}/''${ARCH}/linux/fcntl.c \ + -f ''${m2libc}/fcntl.c \ + -f ''${m2libc}/''${ARCH}/linux/unistd.c \ + -f ''${m2libc}/''${ARCH}/linux/sys/stat.c \ + -f ''${m2libc}/stdlib.c \ + -f ''${m2libc}/stdio.h \ + -f ''${m2libc}/stdio.c \ + -f ''${m2libc}/string.c \ + -f ''${m2libc}/bootstrappable.c \ + -f ''${src}/mescc-tools-extra/${name}.c \ + --debug \ + -o ${name}.M1 + + ''${blood-elf-0} ''${ENDIAN_FLAG} -f ${name}.M1 -o ${name}-footer.M1 + + ''${M1} --architecture ''${ARCH} \ + ''${ENDIAN_FLAG} \ + -f ''${m2libc}/''${ARCH}/''${ARCH}_defs.M1 \ + -f ''${m2libc}/''${ARCH}/libc-full.M1 \ + -f ${name}.M1 \ + -f ${name}-footer.M1 \ + -o ${name}.hex2 + + ''${hex2} --architecture ''${ARCH} \ + ''${ENDIAN_FLAG} \ + -f ''${m2libc}/''${ARCH}/ELF-''${ARCH}-debug.hex2 \ + -f ${name}.hex2 \ + --base-address ''${BASE_ADDRESS} \ + -o ''${out} + '') + ]; + inherit version M1 M2 blood-elf-0 hex2 m2libc src ARCH BLOOD_FLAG BASE_ADDRESS ENDIAN_FLAG; + }; + mkdir = buildMesccToolsExtraUtil "mkdir"; + cp = buildMesccToolsExtraUtil "cp"; + chmod = buildMesccToolsExtraUtil "chmod"; + replace = buildMesccToolsExtraUtil "replace"; +in +derivationWithMeta { + pname = "mescc-tools"; + builder = kaem-unwrapped; + args = [ + "--verbose" + "--strict" + "--file" + ./build.kaem + ]; + inherit version M1 M2 blood-elf-0 hex2 mkdir cp chmod replace m2libc src ARCH BLOOD_FLAG BASE_ADDRESS ENDIAN_FLAG; + + meta = with lib; { + description = "Collection of tools written for use in bootstrapping"; + homepage = "https://github.com/oriansj/mescc-tools"; + license = licenses.gpl3Plus; + maintainers = with maintainers; [ emilytrau ]; + platforms = [ "i686-linux" ]; + }; +} diff --git a/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/stage0-posix-x86.nix b/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/stage0-posix-x86.nix new file mode 100644 index 0000000000000..ae697a1caa92e --- /dev/null +++ b/pkgs/os-specific/linux/minimal-bootstrap/stage0-posix/stage0-posix-x86.nix @@ -0,0 +1,345 @@ +# This is a translation of stage0-posix/stage0-posix/x86/mescc-tools-mini-kaem.kaem to nix +# https://github.com/oriansj/stage0-posix-x86/blob/56e6b8df3e95f4bc04f8b420a4cd8c82c70b9efa/mescc-tools-mini-kaem.kaem +# +# We have access to mini-kaem at this point but it doesn't support substituting +# environment variables. Without variables there's no way of passing in store inputs, +# or the $out path, other than as command line arguments directly + +# Mes --- Maxwell Equations of Software +# Copyright © 2017,2019 Jan Nieuwenhuizen +# Copyright © 2017,2019 Jeremiah Orians +# +# This file is part of Mes. +# +# Mes 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. +# +# Mes 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 Mes. If not, see . + +# Warning all binaries prior to the use of blood-elf will not be readable by +# Objdump, you may need to use ndism or gdb to view the assembly in the binary. + +{ lib +, derivationWithMeta +, hex0 +, m2libc +, src +, version +}: +rec { + out = placeholder "out"; + + run = pname: builder: args: + derivationWithMeta { + inherit pname version builder args; + + meta = with lib; { + description = "Collection of tools written for use in bootstrapping"; + homepage = "https://github.com/oriansj/stage0-posix"; + license = licenses.gpl3Plus; + maintainers = with maintainers; [ emilytrau ]; + platforms = [ "i686-linux" ]; + }; + }; + + ################################ + # Phase-1 Build hex1 from hex0 # + ################################ + + hex1 = run "hex1" hex0 ["${src}/x86/hex1_x86.hex0" out]; + + # hex1 adds support for single character labels and is available in various forms + # in mescc-tools/x86_bootstrap to allow you various ways to verify correctness + + ################################ + # Phase-2 Build hex2 from hex1 # + ################################ + + hex2-0 = run "hex2" hex1 ["${src}/x86/hex2_x86.hex1" out]; + + # hex2 adds support for long labels and absolute addresses thus allowing it + # to function as an effective linker for later stages of the bootstrap + # This is a minimal version which will be used to bootstrap a much more advanced + # version in a later stage. + + ################################# + # Phase-2b Build catm from hex2 # + ################################# + + catm = run "catm" hex2-0 ["${src}/x86/catm_x86.hex2" out]; + + # catm removes the need for cat or shell support for redirection by providing + # equivalent functionality via catm output_file input1 input2 ... inputN + + ############################## + # Phase-3 Build M0 from hex2 # + ############################## + + M0_hex2 = run "M0.hex2" catm [out "${src}/x86/ELF-i386.hex2" "${src}/x86/M0_x86.hex2"]; + M0 = run "M0" hex2-0 [M0_hex2 out]; + + # M0 is the architecture specific version of M1 and is by design single + # architecture only and will be replaced by the C code version of M1 + + ################################ + # Phase-4 Build cc_x86 from M0 # + ################################ + + cc_x86-0_hex2 = run "cc_x86-0.hex2" M0 ["${src}/x86/cc_x86.M1" out]; + cc_x86-1_hex2 = run "cc_x86-1.hex2" catm [out "${src}/x86/ELF-i386.hex2" cc_x86-0_hex2]; + cc_x86 = run "cc_x86" hex2-0 [cc_x86-1_hex2 out]; + + ####################################### + # Phase-5 Build M2-Planet from cc_x86 # + ####################################### + + M2-0_c = run "M2-0.c" catm [ + out + "${m2libc}/x86/linux/bootstrap.c" + "${src}/M2-Planet/cc.h" + "${m2libc}/bootstrappable.c" + "${src}/M2-Planet/cc_globals.c" + "${src}/M2-Planet/cc_reader.c" + "${src}/M2-Planet/cc_strings.c" + "${src}/M2-Planet/cc_types.c" + "${src}/M2-Planet/cc_core.c" + "${src}/M2-Planet/cc_macro.c" + "${src}/M2-Planet/cc.c" + ]; + M2-0_M1 = run "M2-0.M1" cc_x86 [M2-0_c out]; + M2-0-0_M1 = run "M2-0-0.M1" catm [out "${src}/x86/x86_defs.M1" "${src}/x86/libc-core.M1" M2-0_M1]; + M2-0_hex2 = run "M2-0.hex2" M0 [M2-0-0_M1 out]; + M2-0-0_hex2 = run "M2-0-0.hex2" catm [out "${src}/x86/ELF-i386.hex2" M2-0_hex2]; + M2 = run "M2" hex2-0 [M2-0-0_hex2 out]; + + ############################################ + # Phase-6 Build blood-elf-0 from C sources # + ############################################ + + blood-elf-0_M1 = run "blood-elf-0.M1" M2 [ + "--architecture" "x86" + "-f" "${m2libc}/x86/linux/bootstrap.c" + "-f" "${m2libc}/bootstrappable.c" + "-f" "${src}/mescc-tools/stringify.c" + "-f" "${src}/mescc-tools/blood-elf.c" + "--bootstrap-mode" + "-o" out + ]; + + blood-elf-0-0_M1 = run "blood-elf-0-0.M1" catm [out "${m2libc}/x86/x86_defs.M1" "${m2libc}/x86/libc-core.M1" blood-elf-0_M1]; + blood-elf-0_hex2 = run "blood-elf-0.hex2" M0 [blood-elf-0-0_M1 out]; + blood-elf-0-0_hex2 = run "blood-elf-0-0.hex2" catm [out "${m2libc}/x86/ELF-x86.hex2" blood-elf-0_hex2]; + blood-elf-0 = run "blood-elf-0" hex2-0 [blood-elf-0-0_hex2 out]; + + # This is the last stage where the binaries will not have debug info + # and the last piece built that isn't part of the output binaries + + ##################################### + # Phase-7 Build M1-0 from C sources # + ##################################### + + M1-macro-0_M1 = run "M1-macro-0.M1" M2 [ + "--architecture" "x86" + "-f" "${m2libc}/x86/linux/bootstrap.c" + "-f" "${m2libc}/bootstrappable.c" + "-f" "${src}/mescc-tools/stringify.c" + "-f" "${src}/mescc-tools/M1-macro.c" + "--bootstrap-mode" + "--debug" + "-o" out + ]; + + M1-macro-0-footer_M1 = run "M1-macro-0-footer.M1" blood-elf-0 ["-f" M1-macro-0_M1 "--little-endian" "-o" out]; + M1-macro-0-0_M1 = run "M1-macro-0-0.M1" catm [out "${m2libc}/x86/x86_defs.M1" "${m2libc}/x86/libc-core.M1" M1-macro-0_M1 M1-macro-0-footer_M1]; + M1-macro-0_hex2 = run "M1-macro-0.hex2" M0 [M1-macro-0-0_M1 out]; + M1-macro-0-0_hex2 = run "M1-macro-0-0.hex2" catm [out "${m2libc}/x86/ELF-x86-debug.hex2" M1-macro-0_hex2]; + M1-0 = run "M1-0" hex2-0 [M1-macro-0-0_hex2 out]; + + # This is the last stage where catm will need to be used and the last stage where + # M0 is used, as we will being using it's much more powerful and cross-platform + # version with a bunch of extra goodies. + + ####################################### + # Phase-8 Build hex2-1 from C sources # + ####################################### + + hex2_linker-0_M1 = run "hex2_linker-0.M1" M2 [ + "--architecture" "x86" + "-f" "${m2libc}/sys/types.h" + "-f" "${m2libc}/stddef.h" + "-f" "${m2libc}/x86/linux/unistd.c" + "-f" "${m2libc}/x86/linux/fcntl.c" + "-f" "${m2libc}/fcntl.c" + "-f" "${m2libc}/x86/linux/sys/stat.c" + "-f" "${m2libc}/stdlib.c" + "-f" "${m2libc}/stdio.h" + "-f" "${m2libc}/stdio.c" + "-f" "${m2libc}/bootstrappable.c" + "-f" "${src}/mescc-tools/hex2.h" + "-f" "${src}/mescc-tools/hex2_linker.c" + "-f" "${src}/mescc-tools/hex2_word.c" + "-f" "${src}/mescc-tools/hex2.c" + "--debug" + "-o" out + ]; + + hex2_linker-0-footer_M1 = run "hex2_linker-0-footer.M1" blood-elf-0 ["-f" hex2_linker-0_M1 "--little-endian" "-o" out]; + + hex2_linker-0_hex2 = run "hex2_linker-0.hex2" M1-0 [ + "--architecture" "x86" + "--little-endian" + "-f" "${m2libc}/x86/x86_defs.M1" + "-f" "${m2libc}/x86/libc-full.M1" + "-f" hex2_linker-0_M1 + "-f" hex2_linker-0-footer_M1 + "-o" out + ]; + + hex2_linker-0-0_hex2 = run "hex2_linker-0-0.hex2" catm [out "${m2libc}/x86/ELF-x86-debug.hex2" hex2_linker-0_hex2]; + + hex2-1 = run "hex2-1" hex2-0 [hex2_linker-0-0_hex2 out]; + + # This is the last stage where we will be using the handwritten hex2 and instead + # be using the far more powerful, cross-platform version with a bunch more goodies + + ################################### + # Phase-9 Build M1 from C sources # + ################################### + + M1-macro-1_M1 = run "M1-macro-1.M1" M2 [ + "--architecture" "x86" + "-f" "${m2libc}/sys/types.h" + "-f" "${m2libc}/stddef.h" + "-f" "${m2libc}/x86/linux/fcntl.c" + "-f" "${m2libc}/fcntl.c" + "-f" "${m2libc}/x86/linux/unistd.c" + "-f" "${m2libc}/string.c" + "-f" "${m2libc}/stdlib.c" + "-f" "${m2libc}/stdio.h" + "-f" "${m2libc}/stdio.c" + "-f" "${m2libc}/bootstrappable.c" + "-f" "${src}/mescc-tools/stringify.c" + "-f" "${src}/mescc-tools/M1-macro.c" + "--debug" + "-o" out + ]; + + M1-macro-1-footer_M1 = run "M1-macro-1-footer.M1" blood-elf-0 ["-f" M1-macro-1_M1 "--little-endian" "-o" out]; + + M1-macro-1_hex2 = run "M1-macro-1.hex2" M1-0 [ + "--architecture" "x86" + "--little-endian" + "-f" "${m2libc}/x86/x86_defs.M1" + "-f" "${m2libc}/x86/libc-full.M1" + "-f" M1-macro-1_M1 + "-f" M1-macro-1-footer_M1 + "-o" out + ]; + + M1 = run "M1" hex2-1 [ + "--architecture" "x86" + "--little-endian" + "--base-address" "0x8048000" + "-f" "${m2libc}/x86/ELF-x86-debug.hex2" + "-f" M1-macro-1_hex2 + "-o" out + ]; + + ###################################### + # Phase-10 Build hex2 from C sources # + ###################################### + + hex2_linker-2_M1 = run "hex2_linker-2.M1" M2 [ + "--architecture" "x86" + "-f" "${m2libc}/sys/types.h" + "-f" "${m2libc}/stddef.h" + "-f" "${m2libc}/x86/linux/unistd.c" + "-f" "${m2libc}/x86/linux/fcntl.c" + "-f" "${m2libc}/fcntl.c" + "-f" "${m2libc}/x86/linux/sys/stat.c" + "-f" "${m2libc}/stdlib.c" + "-f" "${m2libc}/stdio.h" + "-f" "${m2libc}/stdio.c" + "-f" "${m2libc}/bootstrappable.c" + "-f" "${src}/mescc-tools/hex2.h" + "-f" "${src}/mescc-tools/hex2_linker.c" + "-f" "${src}/mescc-tools/hex2_word.c" + "-f" "${src}/mescc-tools/hex2.c" + "--debug" + "-o" out + ]; + + hex2_linker-2-footer_M1 = run "hex2_linker-2-footer.M1" blood-elf-0 ["-f" hex2_linker-2_M1 "--little-endian" "-o" out]; + + hex2_linker-2_hex2 = run "hex2_linker-2.hex2" M1 [ + "--architecture" "x86" + "--little-endian" + "-f" "${m2libc}/x86/x86_defs.M1" + "-f" "${m2libc}/x86/libc-full.M1" + "-f" hex2_linker-2_M1 + "-f" hex2_linker-2-footer_M1 + "-o" out + ]; + + hex2 = run "hex2" hex2-1 [ + "--architecture" "x86" + "--little-endian" + "--base-address" "0x8048000" + "-f" "${m2libc}/x86/ELF-x86-debug.hex2" + "-f" hex2_linker-2_hex2 + "-o" out + ]; + + ###################################### + # Phase-11 Build kaem from C sources # + ###################################### + + kaem_M1 = run "kaem.M1" M2 [ + "--architecture" "x86" + "-f" "${m2libc}/sys/types.h" + "-f" "${m2libc}/stddef.h" + "-f" "${m2libc}/string.c" + "-f" "${m2libc}/x86/linux/unistd.c" + "-f" "${m2libc}/x86/linux/fcntl.c" + "-f" "${m2libc}/fcntl.c" + "-f" "${m2libc}/stdlib.c" + "-f" "${m2libc}/stdio.h" + "-f" "${m2libc}/stdio.c" + "-f" "${m2libc}/bootstrappable.c" + "-f" "${src}/mescc-tools/Kaem/kaem.h" + "-f" "${src}/mescc-tools/Kaem/variable.c" + "-f" "${src}/mescc-tools/Kaem/kaem_globals.c" + "-f" "${src}/mescc-tools/Kaem/kaem.c" + "--debug" + "-o" out + ]; + + kaem-footer_M1 = run "kaem-footer.M1" blood-elf-0 ["-f" kaem_M1 "--little-endian" "-o" out]; + + kaem_hex2 = run "kaem.hex2" M1 [ + "--architecture" "x86" + "--little-endian" + "-f" "${m2libc}/x86/x86_defs.M1" + "-f" "${m2libc}/x86/libc-full.M1" + "-f" kaem_M1 + "-f" kaem-footer_M1 + "-o" out + ]; + + kaem-unwrapped = run "kaem-unwrapped" hex2 [ + "--architecture" "x86" + "--little-endian" + "-f" "${m2libc}/x86/ELF-x86-debug.hex2" + "-f" kaem_hex2 + "--base-address" "0x8048000" + "-o" out + ]; +} diff --git a/pkgs/os-specific/linux/minimal-bootstrap/tinycc/bootstrappable.nix b/pkgs/os-specific/linux/minimal-bootstrap/tinycc/bootstrappable.nix new file mode 100644 index 0000000000000..bb0e058906cb7 --- /dev/null +++ b/pkgs/os-specific/linux/minimal-bootstrap/tinycc/bootstrappable.nix @@ -0,0 +1,163 @@ +# Bootstrappable TCC is a fork from mainline TCC development +# that can be compiled by MesCC + +# Build steps adapted from https://github.com/fosslinux/live-bootstrap/blob/1bc4296091c51f53a5598050c8956d16e945b0f5/sysa/tcc-0.9.26/tcc-0.9.26.kaem +# +# SPDX-FileCopyrightText: 2021-22 fosslinux +# +# SPDX-License-Identifier: GPL-3.0-or-later + +{ lib +, runCommand +, callPackage +, fetchurl +, mes +, mes-libc +}: +let + inherit (callPackage ./common.nix { }) buildTinyccMes; + + version = "unstable-2023-04-20"; + rev = "80114c4da6b17fbaabb399cc29f427e368309bc8"; + + tarball = fetchurl { + url = "https://gitlab.com/janneke/tinycc/-/archive/${rev}/tinycc-${rev}.tar.gz"; + sha256 = "1a0cw9a62qc76qqn5sjmp3xrbbvsz2dxrw21lrnx9q0s74mwaxbq"; + }; + src = (runCommand "tinycc-bootstrappable-${version}-source" {} '' + ungz --file ${tarball} --output tinycc.tar + mkdir -p ''${out} + cd ''${out} + untar --file ''${NIX_BUILD_TOP}/tinycc.tar + '') + "/tinycc-${rev}"; + + meta = with lib; { + description = "Tiny C Compiler's bootstrappable fork"; + homepage = "https://gitlab.com/janneke/tinycc"; + license = licenses.lgpl21Only; + maintainers = with maintainers; [ emilytrau ]; + platforms = [ "i686-linux" ]; + }; + + tinycc-boot-mes = runCommand "tinycc-boot-mes-${version}" {} '' + catm config.h + ${mes}/bin/mes --no-auto-compile -e main ${mes}/bin/mescc.scm -- \ + -S \ + -o tcc.s \ + -I . \ + -D BOOTSTRAP=1 \ + -I ${src} \ + -D TCC_TARGET_I386=1 \ + -D inline= \ + -D CONFIG_TCCDIR=\"''${out}/lib\" \ + -D CONFIG_SYSROOT=\"\" \ + -D CONFIG_TCC_CRTPREFIX=\"''${out}/lib\" \ + -D CONFIG_TCC_ELFINTERP=\"/mes/loader\" \ + -D CONFIG_TCC_SYSINCLUDEPATHS=\"${mes-libc}/include\" \ + -D TCC_LIBGCC=\"${mes-libc}/lib/x86-mes/libc.a\" \ + -D CONFIG_TCC_LIBTCC1_MES=0 \ + -D CONFIG_TCCBOOT=1 \ + -D CONFIG_TCC_STATIC=1 \ + -D CONFIG_USE_LIBGCC=1 \ + -D TCC_MES_LIBC=1 \ + -D TCC_VERSION=\"${version}\" \ + -D ONE_SOURCE=1 \ + ${src}/tcc.c + mkdir -p ''${out}/bin + ${mes}/bin/mes --no-auto-compile -e main ${mes}/bin/mescc.scm -- \ + -l c+tcc \ + -o ''${out}/bin/tcc \ + tcc.s + + ''${out}/bin/tcc -version + + # Recompile libc: crt{1,n,i}, libtcc.a, libc.a, libgetopt.a + mkdir -p ''${out}/lib + ''${out}/bin/tcc ${mes-libc.CFLAGS} -c -o ''${out}/lib/crt1.o ${mes-libc}/lib/crt1.c + ''${out}/bin/tcc ${mes-libc.CFLAGS} -c -o ''${out}/lib/crtn.o ${mes-libc}/lib/crtn.c + ''${out}/bin/tcc ${mes-libc.CFLAGS} -c -o ''${out}/lib/crti.o ${mes-libc}/lib/crti.c + ''${out}/bin/tcc ${mes-libc.CFLAGS} -c -o libc.o ${mes-libc}/lib/libc.c + ''${out}/bin/tcc -ar cr ''${out}/lib/libc.a libc.o + ''${out}/bin/tcc ${mes-libc.CFLAGS} -c -o libtcc1.o ${mes-libc}/lib/libtcc1.c + ''${out}/bin/tcc -ar cr ''${out}/lib/libtcc1.a libtcc1.o + ''${out}/bin/tcc ${mes-libc.CFLAGS} -c -o libgetopt.o ${mes-libc}/lib/libgetopt.c + ''${out}/bin/tcc -ar cr ''${out}/lib/libgetopt.a libgetopt.o + ''; + + # Bootstrap stage build flags obtained from + # https://gitlab.com/janneke/tinycc/-/blob/80114c4da6b17fbaabb399cc29f427e368309bc8/boot.sh + + tinycc-boot0 = buildTinyccMes { + pname = "tinycc-boot0"; + inherit src version meta; + prev = tinycc-boot-mes; + buildOptions = [ + "-D HAVE_LONG_LONG_STUB=1" + "-D HAVE_SETJMP=1" + ]; + libtccBuildOptions = [ + "-D HAVE_LONG_LONG_STUB=1" + ]; + }; + + tinycc-boot1 = buildTinyccMes { + pname = "tinycc-boot1"; + inherit src version meta; + prev = tinycc-boot0; + buildOptions = [ + "-D HAVE_BITFIELD=1" + "-D HAVE_LONG_LONG=1" + "-D HAVE_SETJMP=1" + ]; + libtccBuildOptions = [ + "-D HAVE_LONG_LONG=1" + ]; + }; + + tinycc-boot2 = buildTinyccMes { + pname = "tinycc-boot2"; + inherit src version meta; + prev = tinycc-boot1; + buildOptions = [ + "-D HAVE_BITFIELD=1" + "-D HAVE_FLOAT_STUB=1" + "-D HAVE_LONG_LONG=1" + "-D HAVE_SETJMP=1" + ]; + libtccBuildOptions = [ + "-D HAVE_FLOAT_STUB=1" + "-D HAVE_LONG_LONG=1" + ]; + }; + + tinycc-boot3 = buildTinyccMes { + pname = "tinycc-boot3"; + inherit src version meta; + prev = tinycc-boot2; + buildOptions = [ + "-D HAVE_BITFIELD=1" + "-D HAVE_FLOAT=1" + "-D HAVE_LONG_LONG=1" + "-D HAVE_SETJMP=1" + ]; + libtccBuildOptions = [ + "-D HAVE_FLOAT=1" + "-D HAVE_LONG_LONG=1" + ]; + }; +in +buildTinyccMes { + pname = "tinycc-bootstrappable"; + inherit src version meta; + prev = tinycc-boot3; + buildOptions = [ + "-D HAVE_BITFIELD=1" + "-D HAVE_FLOAT=1" + "-D HAVE_LONG_LONG=1" + "-D HAVE_SETJMP=1" + ]; + libtccBuildOptions = [ + "-D HAVE_FLOAT=1" + "-D HAVE_LONG_LONG=1" + ]; +} diff --git a/pkgs/os-specific/linux/minimal-bootstrap/tinycc/common.nix b/pkgs/os-specific/linux/minimal-bootstrap/tinycc/common.nix new file mode 100644 index 0000000000000..84f4bcc0ed5a3 --- /dev/null +++ b/pkgs/os-specific/linux/minimal-bootstrap/tinycc/common.nix @@ -0,0 +1,69 @@ +{ lib +, runCommand +, mes-libc +, ln-boot +}: +{ + buildTinyccMes = { + pname, + version, + src, + prev, + buildOptions, + libtccBuildOptions, + meta + }: + let + options = lib.strings.concatStringsSep " " buildOptions; + libtccOptions = lib.strings.concatStringsSep " " libtccBuildOptions; + in + runCommand "${pname}-${version}" { + inherit pname version meta; + nativeBuildInputs = [ ln-boot ]; + } '' + catm config.h + mkdir -p ''${out}/bin + ${prev}/bin/tcc \ + -g \ + -v \ + -static \ + -o ''${out}/bin/tcc \ + -D BOOTSTRAP=1 \ + ${options} \ + -I . \ + -I ${src} \ + -D TCC_TARGET_I386=1 \ + -D CONFIG_TCCDIR=\"''${out}/lib\" \ + -D CONFIG_TCC_CRTPREFIX=\"''${out}/lib\" \ + -D CONFIG_TCC_ELFINTERP=\"\" \ + -D CONFIG_TCC_LIBPATHS=\"''${out}/lib\" \ + -D CONFIG_TCC_SYSINCLUDEPATHS=\"${mes-libc}/include:${src}/include\" \ + -D TCC_LIBGCC=\"libc.a\" \ + -D TCC_LIBTCC1=\"libtcc1.a\" \ + -D CONFIG_TCCBOOT=1 \ + -D CONFIG_TCC_STATIC=1 \ + -D CONFIG_USE_LIBGCC=1 \ + -D TCC_MES_LIBC=1 \ + -D TCC_VERSION=\"${version}\" \ + -D ONE_SOURCE=1 \ + -L ${prev}/lib \ + ${src}/tcc.c + + ''${out}/bin/tcc -v + + # Recompile libc: crt{1,n,i}, libtcc.a, libc.a, libgetopt.a + mkdir -p ''${out}/lib + ''${out}/bin/tcc ${mes-libc.CFLAGS} -c -o ''${out}/lib/crt1.o ${mes-libc}/lib/crt1.c + ''${out}/bin/tcc ${mes-libc.CFLAGS} -c -o ''${out}/lib/crtn.o ${mes-libc}/lib/crtn.c + ''${out}/bin/tcc ${mes-libc.CFLAGS} -c -o ''${out}/lib/crti.o ${mes-libc}/lib/crti.c + ''${out}/bin/tcc -c -D TCC_TARGET_I386=1 ${libtccOptions} -o libtcc1.o ${src}/lib/libtcc1.c + ''${out}/bin/tcc -ar cr ''${out}/lib/libtcc1.a libtcc1.o + ''${out}/bin/tcc ${mes-libc.CFLAGS} -c -o libc.o ${mes-libc}/lib/libc.c + ''${out}/bin/tcc -ar cr ''${out}/lib/libc.a libc.o + ''${out}/bin/tcc ${mes-libc.CFLAGS} -c -o libgetopt.o ${mes-libc}/lib/libgetopt.c + ''${out}/bin/tcc -ar cr ''${out}/lib/libgetopt.a libgetopt.o + + # Install headers + ln -s ${mes-libc}/include ''${out}/include + ''; +} diff --git a/pkgs/os-specific/linux/minimal-bootstrap/tinycc/mes.nix b/pkgs/os-specific/linux/minimal-bootstrap/tinycc/mes.nix new file mode 100644 index 0000000000000..81674893eada0 --- /dev/null +++ b/pkgs/os-specific/linux/minimal-bootstrap/tinycc/mes.nix @@ -0,0 +1,87 @@ +# Build steps adapted from https://github.com/fosslinux/live-bootstrap/blob/1bc4296091c51f53a5598050c8956d16e945b0f5/sysa/tcc-0.9.27/tcc-0.9.27.kaem +# +# SPDX-FileCopyrightText: 2021-22 fosslinux +# +# SPDX-License-Identifier: GPL-3.0-or-later + +{ lib +, runCommand +, fetchurl +, callPackage +, tinycc-bootstrappable +}: +let + inherit (callPackage ./common.nix { }) buildTinyccMes; + + version = "unstable-2023-04-20"; + rev = "86f3d8e33105435946383aee52487b5ddf918140"; + + tarball = fetchurl { + url = "https://repo.or.cz/tinycc.git/snapshot/${rev}.tar.gz"; + sha256 = "11idrvbwfgj1d03crv994mpbbbyg63j1k64lw1gjy7mkiifw2xap"; + }; + src = (runCommand "tinycc-${version}-source" {} '' + ungz --file ${tarball} --output tinycc.tar + mkdir -p ''${out} + cd ''${out} + untar --file ''${NIX_BUILD_TOP}/tinycc.tar + '') + "/tinycc-${builtins.substring 0 7 rev}"; + + meta = with lib; { + description = "Small, fast, and embeddable C compiler and interpreter"; + homepage = "https://repo.or.cz/w/tinycc.git"; + license = licenses.lgpl21Only; + maintainers = with maintainers; [ emilytrau ]; + platforms = [ "i686-linux" ]; + }; + + tccdefs = runCommand "tccdefs-${version}" {} '' + mkdir ''${out} + ${tinycc-bootstrappable}/bin/tcc -static -DC2STR -o c2str ${src}/conftest.c + ./c2str ${src}/include/tccdefs.h ''${out}/tccdefs_.h + ''; + + tinycc-mes-boot = buildTinyccMes { + pname = "tinycc-mes-boot"; + inherit src version meta; + prev = tinycc-bootstrappable; + buildOptions = [ + "-D HAVE_BITFIELD=1" + "-D HAVE_FLOAT=1" + "-D HAVE_LONG_LONG=1" + "-D HAVE_SETJMP=1" + "-D CONFIG_TCC_PREDEFS=1" + "-I ${tccdefs}" + "-D CONFIG_TCC_SEMLOCK=0" + ]; + libtccBuildOptions = [ + "-D HAVE_FLOAT=1" + "-D HAVE_LONG_LONG=1" + "-D CONFIG_TCC_PREDEFS=1" + "-I ${tccdefs}" + "-D CONFIG_TCC_SEMLOCK=0" + ]; + }; +in +buildTinyccMes { + pname = "tinycc-mes"; + inherit src version meta; + prev = tinycc-mes-boot; + buildOptions = [ + "-std=c99" + "-D HAVE_BITFIELD=1" + "-D HAVE_FLOAT=1" + "-D HAVE_LONG_LONG=1" + "-D HAVE_SETJMP=1" + "-D CONFIG_TCC_PREDEFS=1" + "-I ${tccdefs}" + "-D CONFIG_TCC_SEMLOCK=0" + ]; + libtccBuildOptions = [ + "-D HAVE_FLOAT=1" + "-D HAVE_LONG_LONG=1" + "-D CONFIG_TCC_PREDEFS=1" + "-I ${tccdefs}" + "-D CONFIG_TCC_SEMLOCK=0" + ]; +} diff --git a/pkgs/os-specific/linux/minimal-bootstrap/utils.nix b/pkgs/os-specific/linux/minimal-bootstrap/utils.nix new file mode 100644 index 0000000000000..1cc56654d7b0f --- /dev/null +++ b/pkgs/os-specific/linux/minimal-bootstrap/utils.nix @@ -0,0 +1,83 @@ +{ lib +, buildPlatform +, callPackage +, kaem +, mescc-tools +, mescc-tools-extra +}: + +let + checkMeta = callPackage ../../../stdenv/generic/check-meta.nix { }; +in +rec { + fetchurl = import ../../../build-support/fetchurl/boot.nix { + inherit (buildPlatform) system; + }; + + derivationWithMeta = attrs: + let + passthru = attrs.passthru or {}; + validity = checkMeta.assertValidity { inherit meta attrs; }; + meta = checkMeta.commonMeta { inherit validity attrs; }; + in + lib.extendDerivation + validity.handled + ({ inherit meta passthru; } // passthru) + (derivation ({ + inherit (buildPlatform) system; + inherit (meta) name; + } // (builtins.removeAttrs attrs [ "meta" "passthru" ]))); + + writeTextFile = + { name # the name of the derivation + , text + , executable ? false # run chmod +x ? + , destination ? "" # relative path appended to $out eg "/bin/foo" + , allowSubstitutes ? false + , preferLocalBuild ? true + }: + derivationWithMeta { + inherit name text executable allowSubstitutes preferLocalBuild; + passAsFile = [ "text" ]; + + builder = "${kaem}/bin/kaem"; + args = [ + "--verbose" + "--strict" + "--file" + (builtins.toFile "write-text-file.kaem" '' + target=''${out}''${destination} + if match x''${mkdirDestination} x1; then + mkdir -p ''${out}''${destinationDir} + fi + cp ''${textPath} ''${target} + if match x''${executable} x1; then + chmod 555 ''${target} + fi + '') + ]; + + PATH = lib.makeBinPath [ mescc-tools-extra ]; + mkdirDestination = if builtins.dirOf destination == "." then "0" else "1"; + destinationDir = builtins.dirOf destination; + inherit destination; + }; + + writeText = name: text: writeTextFile {inherit name text;}; + + runCommand = name: env: buildCommand: + derivationWithMeta ({ + inherit name; + + builder = "${kaem}/bin/kaem"; + args = [ + "--verbose" + "--strict" + "--file" + (writeText "${name}-builder" buildCommand) + ]; + + PATH = lib.makeBinPath ((env.nativeBuildInputs or []) ++ [ kaem mescc-tools mescc-tools-extra ]); + } // (builtins.removeAttrs env [ "nativeBuildInputs" ])); + +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index b71f0c6f1da8f..1e8b1b9c65775 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -26943,6 +26943,11 @@ with pkgs; metastore = callPackage ../os-specific/linux/metastore { }; + minimal-bootstrap = recurseIntoAttrs (import ../os-specific/linux/minimal-bootstrap { + inherit (stdenv) buildPlatform hostPlatform; + inherit lib config; + }); + mingetty = callPackage ../os-specific/linux/mingetty { }; miraclecast = callPackage ../os-specific/linux/miraclecast { };