parent
64a34814dd
commit
7d5d2a3c5e
@ -0,0 +1,46 @@
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
{ stdenv, nixpkgs, dhallApps, packages }:
|
||||
|
||||
let inherit (packages) base-hw-pc;
|
||||
in nixpkgs.writeScriptBin "hw-image" (with nixpkgs.buildPackages;
|
||||
let inherit (stdenv) cc;
|
||||
|
||||
in ''
|
||||
#!${runtimeShell}
|
||||
set -eu
|
||||
|
||||
CC="${cc}/bin/${cc.targetPrefix}cc"
|
||||
LD="${buildPackages.binutils}/bin/${buildPackages.binutils.targetPrefix}ld"
|
||||
|
||||
TMPDIR="$(${coreutils}/bin/mktemp -d)"
|
||||
trap "rm -rf $TMPDIR" err exit
|
||||
|
||||
export DHALL_PRELUDE=${packages.dhallPrelude}/package.dhall
|
||||
export DHALL_GENODE=${packages.dhallGenode}/package.dhall
|
||||
|
||||
build_core() {
|
||||
local lib="$1"
|
||||
local modules="$2"
|
||||
local link_address="$3"
|
||||
${dhallApps.dhall.program} text <<< \
|
||||
"(${../modules.as.dhall}).to64bitImage ($modules)" \
|
||||
> "$TMPDIR/modules.as"
|
||||
|
||||
# compile the boot modules into one object file
|
||||
$CC -c -x assembler -o "$TMPDIR/boot_modules.o" "$TMPDIR/modules.as"
|
||||
|
||||
# link final image
|
||||
$LD \
|
||||
--strip-all \
|
||||
-T${base-hw-pc.src}/repos/base/src/ld/genode.ld \
|
||||
-z max-page-size=0x1000 \
|
||||
-Ttext=$link_address -gc-sections \
|
||||
"$lib" "$TMPDIR/boot_modules.o"
|
||||
cat a.out
|
||||
}
|
||||
set -v
|
||||
${dhallApps.dhall.program} <<< "${../render-rom.dhall} ($@)" > "$TMPDIR/modules.dhall"
|
||||
build_core "''${CORE_OBJ:-${base-hw-pc}/lib/core-hw-pc.o}" "$TMPDIR/modules.dhall" 0xffffffc000000000 > core.elf
|
||||
build_core "''${BOOTSTRAP_OBJ:-${base-hw-pc}/lib/bootstrap-hw-pc.o}" "${../to-rom.dhall} \"core.elf\" \"./core.elf\"" 0x00200000
|
||||
'')
|
@ -0,0 +1,43 @@
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
{ stdenv, nixpkgs, packages, hw-image }:
|
||||
|
||||
nixpkgs.writeScriptBin "hw-iso" (with nixpkgs.buildPackages;
|
||||
let inherit (stdenv) cc;
|
||||
|
||||
in ''
|
||||
#!${runtimeShell}
|
||||
set -eu
|
||||
|
||||
SYSLINUX="${syslinux}/share/syslinux"
|
||||
|
||||
TMPDIR="$(${coreutils}/bin/mktemp -d)"
|
||||
trap "rm -rf $TMPDIR" err exit
|
||||
|
||||
mkdir -p "$TMPDIR/boot/syslinux"
|
||||
${hw-image.program} $@ > "$TMPDIR/boot/image.elf"
|
||||
|
||||
pushd "$TMPDIR" > /dev/null
|
||||
out="hw.iso"
|
||||
|
||||
# build ISO layout
|
||||
cp ${packages.NOVA}/hypervisor* boot/hypervisor
|
||||
cp ${./isolinux.cfg} boot/syslinux/isolinux.cfg
|
||||
cp \
|
||||
$SYSLINUX/isolinux.bin \
|
||||
$SYSLINUX/ldlinux.c32 \
|
||||
$SYSLINUX/libcom32.c32 \
|
||||
$SYSLINUX/mboot.c32 \
|
||||
boot/syslinux
|
||||
chmod +w boot/syslinux/isolinux.bin
|
||||
|
||||
# create ISO image
|
||||
${cdrkit}/bin/mkisofs -o "$out" \
|
||||
-b syslinux/isolinux.bin -c syslinux/boot.cat \
|
||||
-no-emul-boot -boot-load-size 4 -boot-info-table \
|
||||
-iso-level 2 \
|
||||
boot
|
||||
|
||||
${syslinux}/bin/isohybrid "$out"
|
||||
cat "$out"
|
||||
'')
|
@ -0,0 +1,5 @@
|
||||
SERIAL
|
||||
DEFAULT 0
|
||||
LABEL 0
|
||||
KERNEL mboot.c32
|
||||
APPEND /image.elf
|
@ -0,0 +1,17 @@
|
||||
-- SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
let Genode = env:DHALL_GENODE
|
||||
|
||||
let render =
|
||||
λ(boot : Genode.Boot.Type)
|
||||
→ let rom =
|
||||
[ { mapKey = "config"
|
||||
, mapValue =
|
||||
Genode.Boot.Rom.RomText (Genode.Init.render boot.config)
|
||||
}
|
||||
]
|
||||
# boot.rom
|
||||
|
||||
in rom
|
||||
|
||||
in render
|
@ -0,0 +1,10 @@
|
||||
-- SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
let Genode = env:DHALL_GENODE
|
||||
|
||||
let toRom =
|
||||
λ(mapKey : Text)
|
||||
→ λ(path : Text)
|
||||
→ [ { mapKey = mapKey, mapValue = Genode.Boot.Rom.RomPath path } ]
|
||||
|
||||
in toRom
|
@ -0,0 +1,65 @@
|
||||
{ nixpkgs, apps }:
|
||||
|
||||
{ name, targets, libTargets ? [ ], arch ? "x86_64", kernel ? "linux"
|
||||
, board ? "pc", ... }@extraAttrs:
|
||||
let
|
||||
sourceForgeToolchain =
|
||||
nixpkgs.buildPackages.callPackage ./../genode/toolchain.nix { };
|
||||
|
||||
stdenvGcc = let
|
||||
env = nixpkgs.stdenvAdapters.overrideCC nixpkgs.stdenv sourceForgeToolchain;
|
||||
in assert env.cc.isGNU; env;
|
||||
version = "19.11";
|
||||
toolPrefix = if arch == "x86_64" then
|
||||
"genode-x86-"
|
||||
else
|
||||
throw "unknown tool prefix for Genode arch ${arch}";
|
||||
in stdenvGcc.mkDerivation ({
|
||||
outputs = [ "out" "manifest" ];
|
||||
pname = name;
|
||||
inherit version targets libTargets;
|
||||
src = nixpkgs.fetchFromGitHub {
|
||||
owner = "genodelabs";
|
||||
repo = "genode";
|
||||
rev = version;
|
||||
sha256 = "0j0wfwqmv8mivfkpra1pb02a8dy1nnsakr3v6l5y964dfkq3737i";
|
||||
};
|
||||
|
||||
nativeBuildInputs = with nixpkgs.buildPackages; [ binutils tcl which ];
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
configurePhase = ''
|
||||
patchShebangs ./tool/check_abi
|
||||
patchShebangs ./tool/create_builddir
|
||||
substituteInPlace repos/base/etc/tools.conf \
|
||||
--replace "/usr/local/genode/tool/19.05/bin/" ""
|
||||
substituteInPlace tool/check_abi \
|
||||
--replace "exec nm" "exec ${toolPrefix}nm"
|
||||
./tool/create_builddir ${arch} BUILD_DIR=build
|
||||
'';
|
||||
|
||||
makeFlags = [ "-C build" "KERNEL=${kernel}" "BOARD=${board}" ];
|
||||
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
local flagsArray=(
|
||||
''${enableParallelBuilding:+-j''${NIX_BUILD_CORES} -l''${NIX_BUILD_CORES}}
|
||||
SHELL=$SHELL
|
||||
$makeFlags ''${makeFlagsArray+"''${makeFlagsArray[@]}"}
|
||||
$buildFlags ''${buildFlagsArray+"''${buildFlagsArray[@]}"}
|
||||
)
|
||||
for LIB in $libTargets; do
|
||||
make "''${flagsArray[@]}" LIB=$LIB
|
||||
done
|
||||
make "''${flagsArray[@]}" $targets
|
||||
runHook postBuild
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
find build/bin -execdir install -Dt $out/bin '{}' \;
|
||||
runHook postInstall
|
||||
${apps.generate-manifest.program} $out > $manifest
|
||||
'';
|
||||
} // extraAttrs)
|
@ -0,0 +1,95 @@
|
||||
-- SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
let Genode = env:DHALL_GENODE
|
||||
|
||||
let Prelude = Genode.Prelude
|
||||
|
||||
let ChildEntry = Prelude.Map.Entry Text Genode.Init.Start.Type
|
||||
|
||||
let toChildEntry =
|
||||
λ(init : Genode.Init.Type)
|
||||
→ let childCount = Prelude.List.length ChildEntry init.children
|
||||
|
||||
let onlyChild = Prelude.Natural.lessThan childCount 2
|
||||
|
||||
let child =
|
||||
if onlyChild
|
||||
|
||||
then Prelude.Optional.fold
|
||||
ChildEntry
|
||||
(Prelude.List.head ChildEntry init.children)
|
||||
ChildEntry
|
||||
(λ(child : ChildEntry) → child)
|
||||
{ mapKey = ""
|
||||
, mapValue = Genode.Init.Start::{ binary = "" }
|
||||
}
|
||||
|
||||
else { mapKey = "init", mapValue = Genode.Init.toStart init }
|
||||
|
||||
in child
|
||||
|
||||
in λ(boot : Genode.Boot.Type)
|
||||
→ let child = toChildEntry boot.config
|
||||
|
||||
in { config =
|
||||
Genode.Init::{
|
||||
, defaultRoutes =
|
||||
Genode.Init.default.defaultRoutes
|
||||
# [ Genode.ServiceRoute.parent "IO_MEM"
|
||||
, Genode.ServiceRoute.parent "IO_PORT"
|
||||
, Genode.ServiceRoute.parent "IRQ"
|
||||
, Genode.ServiceRoute.child "Timer" "timer"
|
||||
]
|
||||
, children =
|
||||
[ { mapKey = "timer"
|
||||
, mapValue =
|
||||
Genode.Init.Start::{
|
||||
, binary = "hw_timer_drv"
|
||||
, resources = { caps = 96, ram = Genode.units.MiB 1 }
|
||||
, provides = [ "Timer" ]
|
||||
}
|
||||
}
|
||||
, { mapKey = "harness"
|
||||
, mapValue =
|
||||
Genode.Init.Start::{
|
||||
, binary = "sotest-harness"
|
||||
, exitPropagate = True
|
||||
, resources =
|
||||
{ caps = child.mapValue.resources.caps + 128
|
||||
, ram =
|
||||
child.mapValue.resources.ram
|
||||
+ Genode.units.MiB 1
|
||||
}
|
||||
, config =
|
||||
Some
|
||||
( Prelude.XML.element
|
||||
{ name = "config"
|
||||
, attributes = Prelude.XML.emptyAttributes
|
||||
, content =
|
||||
[ Genode.Init.Start.toXML
|
||||
child.mapKey
|
||||
child.mapValue
|
||||
]
|
||||
}
|
||||
)
|
||||
, routes =
|
||||
[ Genode.ServiceRoute.parentLabel
|
||||
"LOG"
|
||||
(Some "SOTEST")
|
||||
(Some "unlabeled")
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
, rom =
|
||||
let manifest = env:MANIFEST
|
||||
|
||||
in Genode.Boot.toRomPaths
|
||||
[ manifest.base-hw-pc.lib.ld
|
||||
, manifest.base-hw-pc.bin.hw_timer_drv
|
||||
, manifest.os.bin.init
|
||||
, manifest.sotest-producer.bin.sotest-harness
|
||||
]
|
||||
# boot.rom
|
||||
}
|
@ -0,0 +1,171 @@
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
{ system, apps, testPkgs, hostPkgs, lib, depot }:
|
||||
|
||||
let
|
||||
testDriver = with hostPkgs;
|
||||
stdenv.mkDerivation {
|
||||
name = "hw-genode-test-driver";
|
||||
preferLocalBuild = true;
|
||||
|
||||
buildInputs = [ makeWrapper expect ];
|
||||
|
||||
dontUnpack = true;
|
||||
|
||||
installPhase = ''
|
||||
install -Dm555 ${./hw-test-driver.exp} $out/bin/genode-test-driver
|
||||
wrapProgram $out/bin/genode-test-driver \
|
||||
--prefix PATH : "${lib.makeBinPath [ expect coreutils ]}"
|
||||
'';
|
||||
};
|
||||
|
||||
runTests = driver:
|
||||
hostPkgs.stdenv.mkDerivation {
|
||||
name = "hw-" + driver.testName;
|
||||
preferLocalBuild = true;
|
||||
|
||||
buildCommand = ''
|
||||
mkdir -p $out/nix-support
|
||||
|
||||
${driver}/bin/genode-test-driver | tee $out/log
|
||||
|
||||
touch $out/nix-support
|
||||
echo "report testlog $out log" >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
};
|
||||
|
||||
defaultScript = ''run_genode_until {child "init" exited with exit value 0} 60'';
|
||||
|
||||
mkTest = { name ? "unamed", testScript ? defaultScript, testConfig, testInputs ? [ ]
|
||||
, env ? { }, qemuMem ? 32, ... # TODO: remove ...
|
||||
}@t:
|
||||
let
|
||||
manifest = lib.mergeManifests (with testPkgs;
|
||||
[ base-hw-pc genode.os sotest-producer ]
|
||||
++ testInputs);
|
||||
env' = {
|
||||
DHALL_PRELUDE = "${testPkgs.dhallPrelude}/package.dhall";
|
||||
DHALL_GENODE = "${testPkgs.dhallGenode}/package.dhall";
|
||||
MANIFEST = manifest;
|
||||
} // env;
|
||||
|
||||
image = apps.hw-image.function env'
|
||||
"${./driver-hw-config.dhall} ${testConfig}";
|
||||
|
||||
baseSetup = ''
|
||||
##
|
||||
# Wait for a specific output of a already running spawned proce
|
||||
#
|
||||
proc wait_for_output { wait_for_re timeout_value running_spawn_id } {
|
||||
global output
|
||||
|
||||
if {$wait_for_re == "forever"} {
|
||||
set timeout -1
|
||||
interact {
|
||||
\003 {
|
||||
send_user "Expect: 'interact' received 'strg+c' and was cancelled\n";
|
||||
exit
|
||||
}
|
||||
-i $running_spawn_id
|
||||
}
|
||||
} else {
|
||||
set timeout $timeout_value
|
||||
}
|
||||
|
||||
expect {
|
||||
-i $running_spawn_id -re $wait_for_re { }
|
||||
eof { puts stderr "Error: Spawned process died unexpectedly"; exit -1 }
|
||||
timeout { puts stderr "Error: Test execution timed out"; exit -1 }
|
||||
}
|
||||
set output $expect_out(buffer)
|
||||
}
|
||||
|
||||
proc run_genode_until {{wait_for_re forever} {timeout_value 0} {running_spawn_id -1}} {
|
||||
#
|
||||
# If a running_spawn_id is specified, wait for the expected output
|
||||
#
|
||||
if {$running_spawn_id != -1} {
|
||||
wait_for_output $wait_for_re $timeout_value $running_spawn_id
|
||||
return
|
||||
}
|
||||
|
||||
global spawn_id
|
||||
spawn ${hostPkgs.qemu_test}/bin/qemu-system-x86_64 \
|
||||
-machine q35 -serial mon:stdio -nographic \
|
||||
-m size=${toString qemuMem} \
|
||||
-kernel "${testPkgs.bender}" \
|
||||
-initrd "${image}"
|
||||
wait_for_output $wait_for_re $timeout_value $spawn_id
|
||||
}
|
||||
|
||||
# TODO: not in TCL
|
||||
global env
|
||||
set out $env(out)
|
||||
'';
|
||||
|
||||
driver = with hostPkgs;
|
||||
buildPackages.runCommand "genode-test-driver-${name}" {
|
||||
buildInputs = [ makeWrapper expect ];
|
||||
inherit baseSetup testConfig testScript;
|
||||
preferLocalBuild = true;
|
||||
testName = name;
|
||||
} ''
|
||||
mkdir -p $out/bin
|
||||
echo "$testScript" > $out/test-script
|
||||
echo "$baseSetup" > $out/base-setup
|
||||
ln -s ${testDriver}/bin/genode-test-driver $out/bin/
|
||||
wrapProgram $out/bin/genode-test-driver \
|
||||
--run "export testScript=\"\$(cat $out/test-script)\"" \
|
||||
--run "export baseSetup=\"\$(cat $out/base-setup)\"" \
|
||||
'';
|
||||
|
||||
passMeta = drv:
|
||||
drv
|
||||
// lib.optionalAttrs (t ? meta) { meta = (drv.meta or { }) // t.meta; };
|
||||
|
||||
test = passMeta (runTests driver);
|
||||
|
||||
in test // {
|
||||
inherit driver image test manifest;
|
||||
|
||||
config = hostPkgs.runCommand (name + ".dhall") env' ''
|
||||
export XDG_CACHE_HOME=''${TMPDIR:-/tmp}
|
||||
${apps.dhall.program} <<< \
|
||||
"(${./driver-hw-config.dhall} ${testConfig})" > $out
|
||||
'';
|
||||
|
||||
iso = apps.hw-iso.function env'
|
||||
"(${./driver-hw-config.dhall} ${testConfig})";
|
||||
|
||||
xml = hostPkgs.runCommand (name + ".config") env' ''
|
||||
export XDG_CACHE_HOME=''${TMPDIR:-/tmp}
|
||||
${apps.render-init.program} \
|
||||
"(${./driver-hw-config.dhall} ${testConfig}).config" > $out'';
|
||||
|
||||
sotest = hostPkgs.runCommand "hw-${name}-sotest" env' ''
|
||||
cp "${testPkgs.bender}" bender
|
||||
cp ${image} image.elf
|
||||
mkdir -p $out/nix-support
|
||||
${hostPkgs.zip}/bin/zip "$out/binaries.zip" \
|
||||
bender image.elf
|
||||
${apps.dhall-to-yaml.program} < ${
|
||||
./sotest_hw_config.dhall
|
||||
} > "$out/sotest_config.yaml"
|
||||
echo file zip $out/binaries.zip >> "$out/nix-support/hydra-build-products"
|
||||
echo file config $out/sotest_config.yaml >> "$out/nix-support/hydra-build-products"
|
||||
'';
|
||||
|
||||
};
|
||||
|
||||
in {
|
||||
callTest = path: args:
|
||||
(import path ({
|
||||
testEnv = {
|
||||
inherit mkTest lib;
|
||||
isLinux = false;
|
||||
isNova = true;
|
||||
};
|
||||
pkgs = testPkgs;
|
||||
inherit depot hostPkgs;
|
||||
} // args));
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env expect
|
||||
|
||||
eval $env(baseSetup)
|
||||
|
||||
eval $env(testScript)
|
@ -0,0 +1,4 @@
|
||||
{ boot_items =
|
||||
[ { exec = "bender", load = [ "image.elf" ], name = "Genode base-hw" } ]
|
||||
, boot_panic_patterns = [ "Error: init", "PAGE-FAULT IN CORE" ]
|
||||
}
|
Loading…
Reference in New Issue