11 changed files with 426 additions and 2 deletions
@ -0,0 +1,191 @@
|
||||
# SPDX-FileCopyrightText: Emery Hemingway |
||||
# |
||||
# SPDX-License-Identifier: LicenseRef-Hippocratic-1.1 |
||||
|
||||
{ testPkgs, hostPkgs, lib }: |
||||
|
||||
let |
||||
testDriver = with hostPkgs; |
||||
stdenv.mkDerivation { |
||||
name = "nova-genode-test-driver"; |
||||
|
||||
buildInputs = [ makeWrapper expect ]; |
||||
|
||||
dontUnpack = true; |
||||
|
||||
preferLocalBuild = true; |
||||
|
||||
installPhase = '' |
||||
install -Dm555 ${./nova-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 = "test-run-${driver.testName}"; |
||||
|
||||
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 |
||||
''; |
||||
}; |
||||
|
||||
makeTest = { testScript, testConfig, name ? "unamed", ... }@t: |
||||
let |
||||
|
||||
baseSetup = with testPkgs; |
||||
|
||||
'' |
||||
global modules |
||||
set HOSTLD ${buildPackages.binutils}/bin/x86_64-unknown-genode-elf-ld |
||||
|
||||
file link -s timer ${genode.base-nova}/bin/nova_timer_drv |
||||
file link -s ld.lib.so ${depot.base-nova}/lib/ld.lib.so |
||||
file link -s core-nova.o ${depot.base-nova}/lib/core-nova.o |
||||
file link -s init ${genode.os}/bin/init |
||||
file link -s config ${./driver-config.xml} |
||||
file link -s test.config $env(testConfig) |
||||
|
||||
set modules { |
||||
timer |
||||
ld.lib.so |
||||
init |
||||
config |
||||
test.config |
||||
} |
||||
|
||||
set qemu_mem 64 |
||||
|
||||
## |
||||
# Link core image containing given modules |
||||
# |
||||
proc build_core {lib modules target} { |
||||
global env |
||||
|
||||
# generate assembly code aggregating the modules data |
||||
set asm_src [generate_boot_modules_asm $modules] |
||||
|
||||
# compile the boot modules into one object file |
||||
exec $env(CC) -c -x assembler -o boot_modules.o - << $asm_src |
||||
|
||||
# link final image |
||||
global HOSTLD |
||||
exec $HOSTLD -nostdlib \ |
||||
-T${./genode.ld} \ |
||||
-T${./nova-bss.ld} \ |
||||
-z max-page-size=0x1000 \ |
||||
-Ttext=0x100000 -gc-sections \ |
||||
--whole-archive \ |
||||
$lib boot_modules.o --no-whole-archive \ |
||||
-o $target |
||||
} |
||||
|
||||
proc build_iso {target} { |
||||
# TODO: take our own build of NOVA |
||||
file mkdir boot/syslinux |
||||
file copy ${nova}/hypervisor-x86_64 boot/hypervisor |
||||
file copy ${./nova-isolinux.cfg} boot/syslinux/isolinux.cfg |
||||
file copy ${hostPkgs.syslinux}/share/syslinux/isolinux.bin boot/syslinux/isolinux.bin |
||||
file copy ${hostPkgs.syslinux}/share/syslinux/ldlinux.c32 boot/syslinux/ldlinux.c32 |
||||
file copy ${hostPkgs.syslinux}/share/syslinux/libcom32.c32 boot/syslinux/libcom32.c32 |
||||
file copy ${hostPkgs.syslinux}/share/syslinux/mboot.c32 boot/syslinux/mboot.c32 |
||||
|
||||
exec chmod +w boot/syslinux/isolinux.bin |
||||
catch { exec ${hostPkgs.cdrkit}/bin/mkisofs -o $target \ |
||||
-b syslinux/isolinux.bin -c syslinux/boot.cat \ |
||||
-no-emul-boot -boot-load-size 4 -boot-info-table \ |
||||
-iso-level 2 \ |
||||
boot |
||||
} |
||||
puts "built ISO?" |
||||
} |
||||
|
||||
## |
||||
# Wait for a specific output of a already running spawned process |
||||
# |
||||
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 env modules qemu_mem |
||||
file mkdir boot |
||||
build_core core-nova.o $modules boot/image.elf |
||||
|
||||
set out $env(out) |
||||
build_iso $out/test.iso |
||||
|
||||
global spawn_id |
||||
spawn ${hostPkgs.qemu_test}/bin/qemu-system-x86_64 -cdrom $out/test.iso -nographic -m $qemu_mem |
||||
wait_for_output $wait_for_re $timeout_value $spawn_id |
||||
} |
||||
''; |
||||
|
||||
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 "$testConfig" > $out/test.config |
||||
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 testConfig=\"$testConfig\"" \ |
||||
--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 test; }; |
||||
|
||||
in { |
||||
callTest = path: args: |
||||
makeTest (import path ({ |
||||
pkgs = testPkgs; |
||||
inherit lib; |
||||
} // args)); |
||||
} |
@ -0,0 +1,137 @@
|
||||
/* |
||||
* \brief Linker script for Genode programs |
||||
* \author Christian Helmuth |
||||
* \date 2006-04-12 |
||||
*/ |
||||
|
||||
/* |
||||
* Copyright (C) 2006-2017 Genode Labs GmbH |
||||
* |
||||
* This file is part of the Genode OS framework, which is distributed |
||||
* under the terms of the GNU Affero General Public License version 3. |
||||
*/ |
||||
|
||||
ENTRY(_start) |
||||
|
||||
PHDRS |
||||
{ |
||||
ro PT_LOAD; |
||||
rw PT_LOAD; |
||||
boot PT_LOAD FLAGS(4); |
||||
} |
||||
|
||||
SECTIONS |
||||
{ |
||||
.text : { |
||||
/* begin of program image (link address) */ |
||||
_prog_img_beg = .; |
||||
|
||||
/* put entry code at the start of the text segment / raw binary */ |
||||
KEEP (*(.text.crt0)) |
||||
|
||||
*(.init) |
||||
*(.text .text.* .gnu.linkonce.t.*) |
||||
*(.fini) |
||||
*(.rodata .rodata.* .gnu.linkonce.r.*) |
||||
|
||||
. = ALIGN(0x08); |
||||
|
||||
_ctors_start = .; |
||||
KEEP (*(.ctors)) |
||||
KEEP (*(SORT(.ctors.*))) |
||||
KEEP (*(.init_array)) /* list of constructors specific for ARM eabi */ |
||||
_ctors_end = .; |
||||
_dtors_start = .; |
||||
KEEP (*(SORT(.dtors.*))) |
||||
KEEP (*(.dtors)) |
||||
_dtors_end = .; |
||||
} : ro = 0x0 |
||||
|
||||
/* Linux: exception section for uaccess mechanism */ |
||||
__ex_table : { *(__ex_table) } |
||||
|
||||
.eh_frame_hdr : { *(.eh_frame_hdr) } |
||||
__eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0; |
||||
__eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0; |
||||
|
||||
. = ALIGN(0x1000); |
||||
|
||||
.data : { |
||||
/* |
||||
* Leave space for parent capability parameters at start of data |
||||
* section. The protection domain creator is reponsible for storing |
||||
* sane values here. |
||||
*/ |
||||
_parent_cap = .; |
||||
_parent_cap_thread_id = .; |
||||
LONG(0xffffffff); |
||||
_parent_cap_local_name = .; |
||||
LONG(0xffffffff); |
||||
LONG(0xffffffff); |
||||
LONG(0xffffffff); |
||||
LONG(0xffffffff); |
||||
LONG(0xffffffff); |
||||
LONG(0xffffffff); |
||||
LONG(0xffffffff); |
||||
|
||||
/* |
||||
* Platform-specific entry for Fiasco.OC. |
||||
* |
||||
* PIC-code compiled for Fiasco.OC, needs some PIC-compatible |
||||
* way to enter the kernel, the fixed address of the kernel |
||||
* entry code address needs to be found here. |
||||
*/ |
||||
__l4sys_invoke_indirect = .; |
||||
LONG(0xeacff000); |
||||
|
||||
*(.data .gnu.linkonce.d.*) |
||||
|
||||
/* include all data subsections except those of the boot modules */ |
||||
*(EXCLUDE_FILE (*boot_modules.o) .data.*) |
||||
} : rw |
||||
|
||||
/* exception frames for C++ */ |
||||
.eh_frame : { |
||||
__eh_frame_start__ = .; |
||||
__eh_frame_start = .; |
||||
KEEP (*(.eh_frame)) |
||||
__eh_frame_end = .; |
||||
LONG(0) |
||||
} : rw |
||||
|
||||
.gcc_except_table : { |
||||
KEEP(*(.gcc_except_table)) |
||||
KEEP(*(.gcc_except_table.*)) |
||||
} |
||||
|
||||
.dynamic : { *(.dynamic) } |
||||
|
||||
/* .ARM.exidx is sorted, so has to go in its own output section */ |
||||
__exidx_start = .; |
||||
.ARM.exidx : { |
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*) |
||||
} |
||||
__exidx_end = .; |
||||
|
||||
.ARM.extab : { |
||||
*(.ARM.extab*) |
||||
} : rw |
||||
|
||||
.bss : { |
||||
_bss_start = ALIGN(4); |
||||
*(.bss .bss.* .gnu.linkonce.b.* COMMON) |
||||
} |
||||
_bss_end = ALIGN(4); |
||||
|
||||
/* separate location for the binaries of the boot modules */ |
||||
.data.boot_modules_binaries : { *(.data.boot_modules_binaries) } : boot |
||||
|
||||
/* end of program image -- must be after last section */ |
||||
_prog_img_end = .; |
||||
|
||||
/DISCARD/ : { |
||||
*(.note) |
||||
*(.note.ABI-tag) |
||||
*(.comment) |
||||
} |
||||
} |
@ -0,0 +1,6 @@
|
||||
SECTIONS |
||||
{ |
||||
.data : { |
||||
*(.bss .bss.* .gnu.linkonce.b.* COMMON) |
||||
} : rw |
||||
} |
@ -0,0 +1,5 @@
|
||||
SERIAL |
||||
DEFAULT 0 |
||||
LABEL 0 |
||||
KERNEL mboot.c32 |
||||
APPEND /hypervisor iommu novpid serial --- /image.elf |
@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env expect |
||||
|
||||
## |
||||
# Generate assembly code aggregating boot-module data from specified files. |
||||
# |
||||
proc generate_boot_modules_asm {modules} { |
||||
|
||||
# architecture dependent definitions |
||||
set address_type ".quad" |
||||
|
||||
# header |
||||
set asm_src {} |
||||
append asm_src ".set MIN_PAGE_SIZE_LOG2, 12\n" |
||||
append asm_src ".set DATA_ACCESS_ALIGNM_LOG2, 3\n" |
||||
append asm_src "\n" |
||||
append asm_src ".section .data\n" |
||||
append asm_src "\n" |
||||
append asm_src ".p2align DATA_ACCESS_ALIGNM_LOG2\n" |
||||
append asm_src ".global _boot_modules_headers_begin\n" |
||||
append asm_src "_boot_modules_headers_begin:\n" |
||||
append asm_src "\n" |
||||
|
||||
# module list |
||||
set i 0 |
||||
foreach module $modules { |
||||
incr i |
||||
append asm_src "${address_type} _boot_module_${i}_name\n" |
||||
append asm_src "${address_type} _boot_module_${i}_begin\n" |
||||
append asm_src "${address_type} _boot_module_${i}_end -" |
||||
append asm_src " _boot_module_${i}_begin\n" |
||||
append asm_src "\n" |
||||
} |
||||
append asm_src ".global _boot_modules_headers_end\n" |
||||
append asm_src "_boot_modules_headers_end:\n" |
||||
append asm_src "\n" |
||||
|
||||
# module names |
||||
set i 0 |
||||
foreach module $modules { |
||||
incr i |
||||
append asm_src ".p2align DATA_ACCESS_ALIGNM_LOG2\n" |
||||
append asm_src "_boot_module_${i}_name:\n" |
||||
append asm_src ".string \"${module}\"\n" |
||||
append asm_src ".byte 0\n" |
||||
append asm_src "\n" |
||||
} |
||||
|
||||
# header end |
||||
append asm_src ".section .data.boot_modules_binaries\n" |
||||
append asm_src "\n" |
||||
append asm_src ".global _boot_modules_binaries_begin\n" |
||||
append asm_src "_boot_modules_binaries_begin:\n" |
||||
append asm_src "\n" |
||||
|
||||
# module data |
||||
set i 0 |
||||
foreach module $modules { |
||||
incr i |
||||
append asm_src ".p2align MIN_PAGE_SIZE_LOG2\n" |
||||
append asm_src "_boot_module_${i}_begin:\n" |
||||
append asm_src ".incbin \"${module}\"\n" |
||||
append asm_src "_boot_module_${i}_end:\n" |
||||
append asm_src "\n" |
||||
} |
||||
|
||||
append asm_src ".p2align MIN_PAGE_SIZE_LOG2\n" |
||||
append asm_src ".global _boot_modules_binaries_end\n" |
||||
append asm_src "_boot_modules_binaries_end:\n" |
||||
|
||||
return $asm_src |
||||
} |
||||
|
||||
eval $env(baseSetup) |
||||
|
||||
eval $env(testScript) |
Loading…
Reference in new issue