genode/tool/run/run

1099 lines
26 KiB
Plaintext
Raw Normal View History

2015-01-08 21:08:48 +00:00
#!/usr/bin/expect
#
# \brief Framework for running automated tests
# \author Norman Feske
# \date 2010-03-16
#
# Usage: run --name <run_name> --include <run_script> ...
#
# The '--name' argument is used for as name for the boot-image and
# temporary directories. The files includes via the '--include'
# argument provide platform-specific additions/refinements to the
# test framework as well as the actual test steps.
#
##
# Remove leading and trailing whitespace from string
#
proc strip_whitespace {string} {
regsub -all {^\s+} $string "" string
regsub -all {\s+$} $string "" string
return $string
}
##
# Check if the specified spec requirement is satisfied
#
proc assert_spec {spec} {
global specs
if {[lsearch $specs $spec] == -1} {
puts stderr "Test requires '$spec'"
exit 0
}
}
##
# Build genode targets specified as space-separated strings
#
# If the build process fails, this procedure will exit the program with
# the error code -4.
#
proc build {targets} {
if {[get_cmd_switch --skip-build]} return
regsub -all {\s\s+} $targets " " targets
puts "building targets: $targets"
set timeout 10000
set pid [eval "spawn make $targets"]
expect { eof { } }
if {[lindex [wait $pid] end] != 0} {
puts "Error: Genode build failed"
exit -4
}
puts "genode build completed"
}
##
# Create a fresh boot directory
#
proc create_boot_directory { } {
exec rm -rf [run_dir]
exec mkdir -p [run_dir]
exec mkdir -p [run_dir]/genode
}
##
# Append string to variable only if 'condition' is satisfied
#
proc append_if {condition var args} {
2015-01-08 21:08:48 +00:00
upvar $var up_var
if {$condition} { append up_var [join $args ""] }
2015-01-08 21:08:48 +00:00
}
##
# Append element to list only if 'condition' is satisfied
#
proc lappend_if {condition var string} {
upvar $var up_var
if {$condition} { lappend up_var $string }
}
##
# Check syntax of specified XML file using xmllint
#
proc check_xml_syntax {xml_file} {
if {![have_installed xmllint]} {
puts "Warning: Cannot validate config syntax (please install xmllint)"
return;
}
if {[catch {exec xmllint --noout $xml_file} result]} {
puts stderr $result
puts stderr "Error: Invalid XML syntax in $xml_file"
exit 1
}
}
##
# Validate configuration file to match an XML schema using xmllint
#
# \param bin binary name of the component behind the config
# \param xml_file configuration file
# \param xsd_file configuration schema file
# \param avail_xsd_files list of xsd files that might be used for
# configurations of children of the component
# \param nesting_level level of recursive calls of this procedure
#
proc check_config {bin xml_file xsd_file label avail_xsd_files xsd_inc nesting_level} {
# check prerequisites if this is not a recursive call
if {$nesting_level == 0} {
if {![have_installed xmllint]} {
puts ""
puts "Warning: cannot validate config syntax\
(please install xmllint)"
puts ""
exit 1
}
}
# check the given component configuration itself
puts " CHECK $label"
if {[catch {exec xmllint --noout --path $xsd_inc -schema $xsd_file $xml_file} result]} {
if {$result != "$xml_file validates"} {
puts stderr "$result"
puts stderr "Error: Invalid XML syntax"
exit 1
}
}
#
# If this is no instance of Genodes Init component, we can skip checking
# for potential child configurations.
#
if {$bin != "init"} {
return
}
#
# The names of the available XSD files tell us for which binaries we
# can do a check. So iterate through the XSD files and try to find
# corresponding child instances.
#
foreach child_xsd_file $avail_xsd_files {
set child_bin [file tail [file rootname $child_xsd_file]]
for {set child_instance 1} {1} {incr child_instance} {
#
# Try to find a child instance that uses this binary. We start
# with selecting the first matching start node, than the
# second, and so on. As soon as xmlscarlet returns an empty
# string, we know that there is no further matching start node.
#
set xpath_start_cond "child::binary\[@name=\'$child_bin\'\] or \
not(child::binary) and @name=\'$child_bin\'"
set xpath "string(/config/start\[$xpath_start_cond\]\[$child_instance\]/@name)"
set select_xpath "xmllint --xpath \"$xpath\" $xml_file"
if {[catch {exec {*}$select_xpath} child_name]} {
#
# No further child instance that uses this binary.
# Proceed with next binary.
#
break
}
#
# If the child has a config, check it with a recursive
# call to this procedure.
#
set xpath "/config/start\[$xpath_start_cond\]\[$child_instance\]/config"
set select_xpath "xmllint --xpath \"$xpath\" $xml_file"
if {[catch {exec {*}$select_xpath} child_xml]} {
# the child has no config
break
}
# write child config to temporary file
set child_xml_file ".config_$nesting_level.xml.tmp"
set child_xml_fd [open $child_xml_file w]
puts $child_xml_fd $child_xml
close $child_xml_fd
# call this procedure again on the child config file
set child_label "$label -> $child_name"
check_config $child_bin $child_xml_file $child_xsd_file \
$child_label $avail_xsd_files $xsd_inc \
[expr $nesting_level+1]
# clean up
exec rm -f $child_xml_file
}
}
}
##
# Install content of specified variable as init config file
2015-01-08 21:08:48 +00:00
#
proc install_config { args } {
2015-01-08 21:08:48 +00:00
set fh [open "[run_dir]/genode/config" "WRONLY CREAT TRUNC"]
puts $fh [join $args {}]
2015-01-08 21:08:48 +00:00
close $fh
}
##
# Integrate specified binaries into boot image
#
# \param binaries space-separated list of file names located within the
# '<build-dir>/bin/' directory
#
proc build_boot_image {binaries} {
check_for_missing_depot_archives
# lookup XSD files in the run-script-specific folder
set xsd_files ""
if {[catch {exec find [run_dir]/genode -name *.xsd} find_stdout] == 0} {
set xsd_files [split "$find_stdout" "\n"]
}
# lookup XSD files in the binaries folder
foreach binary $binaries {
if {[file exists "bin/$binary.xsd"]} {
lappend xsd_files "bin/$binary.xsd"
}
}
# determine which XSD file to use for the init config
set init_xsd_file ""
foreach xsd_file $xsd_files {
set filename [file tail $xsd_file]
if {$filename == "init.xsd"} {
set init_xsd_file $xsd_file
}
}
# determine include directories that can be used by the XSD files
global repositories;
set xsd_inc ""
foreach repo $repositories {
if {[file exists $repo/xsd]} {
append xsd_inc "$repo/xsd " }
}
# check configurations of init and its children
puts "checking configuration syntax"
check_config init [run_dir]/genode/config $init_xsd_file init $xsd_files $xsd_inc 0
2015-01-08 21:08:48 +00:00
run_boot_dir $binaries
}
2021-01-21 12:57:56 +00:00
# set expect match-buffer size
match_max -d 40000
2015-01-08 21:08:48 +00:00
2021-01-21 12:57:56 +00:00
2015-01-08 21:08:48 +00:00
##
# Execute Genode
#
# \param wait_for_re regular expression that matches the test completion
# \param timeout_value timeout in seconds
# \param spawn_id spawn_id of a already running and spawned process
# spawn_id may be a list of spawned processes if needed
# \global output contains the core output (modified)
#
# If the function is called without any argument, Genode is executed in
# interactive mode.
#
# If the test execution times out, this procedure will exit the program with
# the error code -2.
#
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;
}
set retry 3
while { $retry != 0 } {
#
# Depending an the used run module, a reset can include
# shutting the power off and turning it on again.
#
if (![run_power_cycle]) {
puts "Power cycle step failed, retry."
sleep 3
incr retry -1;
continue
}
2015-01-08 21:08:48 +00:00
if {![run_load]} {
puts "Load step failed, retry."
# kill the spawned load process if there is one
if {[load_spawn_id] != -1} {
kill_spawned [load_spawn_id]
2015-01-08 21:08:48 +00:00
}
incr retry -1;
continue;
}
if {![run_log $wait_for_re $timeout_value]} {
puts "Log step failed, retry."
incr retry -1;
continue;
}
return;
}
puts stderr "Boot process failed 3 times in series. I give up!";
exit -1;
}
##
# "Safely" kill spawned process
#
proc kill_spawned {spawn_id} {
set pid [exp_pid -i $spawn_id]
close -i $spawn_id
exec kill -9 $pid
wait -i $spawn_id
}
2015-01-08 21:08:48 +00:00
##
# Remove color information from output
#
proc filter_out_color_escape_sequences { } {
global output
regsub -all {\e\[.*?m} $output "" output
}
##
# Remove superfluous empty lines and unify line endings from output
#
proc trim_lines { } {
global output
regsub -all {[\r\n]+} $output "\n" output
}
##
# Filter output based on the specified pattern
#
# Only those lines that match the pattern are preserved.
#
proc grep_output {pattern} {
global output
filter_out_color_escape_sequences
trim_lines
set output_list [split $output "\n"]
set filtered ""
foreach line $output_list {
if {[regexp $pattern $line]} {
append filtered "$line\n"
}
}
set output $filtered
}
##
# Unify known variations that appear in the test output
#
# \global output test output (modified)
#
proc unify_output {pattern replacement} {
global output
regsub -all $pattern $output $replacement output
}
##
# Compare output against expected output line by line
#
# \param good expected test output
# \global output test output
#
# This procedure will exit the program with the error code -1 if the
# comparison fails.
#
proc compare_output_to { good } {
global output
set output_list [split [strip_whitespace $output] "\n"]
set good_list [split [strip_whitespace $good] "\n"]
set i 0
set mismatch_cnt 0
foreach good_line $good_list {
set output_line [strip_whitespace [lindex $output_list $i]]
set good_line [strip_whitespace $good_line]
if {$output_line != $good_line} {
puts ""
puts stderr "Line $i of output is unexpected"
puts stderr " expected: '$good_line'"
puts stderr " got: '$output_line'"
incr mismatch_cnt
}
incr i
}
#
# if $good is empty the foreach-loop isn't entered
# so we've to check for it separately
#
if {![llength $good_list] && [llength $output_list]} {
foreach output_line $output_list {
set output_line [strip_whitespace $output_line]
puts ""
puts stderr "Line $i of output is unexpected"
puts stderr " got: '$output_line'"
incr mismatch_cnt
incr i
}
}
if {$mismatch_cnt > 0} {
puts "Error: Test failed, $mismatch_cnt unexpected lines of output"
exit -1
}
}
##
# Return true if command-line switch was specified
#
proc get_cmd_switch { arg_name } {
global argv
return [expr [lsearch $argv $arg_name] >= 0]
}
##
# Return command-line argument value
#
# If a argument name is specified multiple times, a
# list of argument values is returned.
#
proc get_cmd_arg { arg_name default_value } {
global argv
# find argument name in argv list
set arg_idx_list [lsearch -all $argv $arg_name]
if {[llength $arg_idx_list] == 0} { return $default_value }
set result {}
foreach arg_idx $arg_idx_list {
set next_idx [expr $arg_idx + 1]
# stop if argv ends with the argument name
if {$next_idx >= [llength $argv]} continue
# return list element following the argument name
lappend result [lindex $argv $next_idx]
}
# if argument occurred only once, return its value
if {[llength $result] == 1} { return [lindex $result 0] }
# if argument occurred multiple times, contain list of arguments
return $result
}
2021-01-21 12:57:56 +00:00
2015-01-08 21:08:48 +00:00
##
# Return command-line argument value
#
# If a argument name is specified multiple times, return only the
# first match.
#
proc get_cmd_arg_first { arg_name default_value } {
global argv
set arg_idx [lsearch $argv $arg_name]
if {$arg_idx == -1} { return $default_value }
return [lindex $argv [expr $arg_idx + 1]]
}
#
# Read command-line arguments
#
set run_name [get_cmd_arg --name "noname"]
set genode_dir [get_cmd_arg --genode-dir ""]
set cross_dev_prefix [get_cmd_arg --cross-dev-prefix ""]
set specs [get_cmd_arg --specs ""]
set board_var [get_cmd_arg --board ""]
2015-01-08 21:08:48 +00:00
set repositories [get_cmd_arg --repositories ""]
# accessor functions for command-line arguments
proc run_name { } { global run_name; return $run_name }
proc run_dir { } { global run_name; return var/run/$run_name }
proc genode_dir { } { global genode_dir; return $genode_dir }
proc cross_dev_prefix { } { global cross_dev_prefix; return $cross_dev_prefix }
##
# Return true if spec value is set for the build
#
proc have_spec {spec} { global specs; return [expr [lsearch $specs $spec] != -1] }
##
# Return true if specified program is installed
#
proc have_installed {program} {
if {[catch { exec which $program }] == 0} { return true; }
if {[catch { exec which "/sbin/$program" }] == 0} { return true; }
if {[catch { exec which "/usr/sbin/$program" }] == 0} { return true; }
if {[catch { exec which "/usr/local/bin/$program" }] == 0} { return true; }
return false;
2015-01-08 21:08:48 +00:00
}
##
# Check if a shell command is installed
#
# \param command name of the command to search
2015-01-08 21:08:48 +00:00
#
# \return absolute path of command if found, or exists if not
#
proc installed_command {command} {
if { [catch {set path [exec which $command]}] == 0} {
return $path
}
set dir { /sbin /usr/sbin /usr/local/bin }
foreach location $dir {
append location / $command
if { [file exists $location] == 1} {
return $location
}
2015-01-08 21:08:48 +00:00
}
puts stderr "Error: '$command' command could be not found. Please make sure to install the"
puts stderr " packet containing '$command', or make it available in your PATH variable.\n"
exit 1
2015-01-08 21:08:48 +00:00
}
##
# Return first repository containing the given path
#
proc repository_contains {path} {
global repositories;
foreach i $repositories {
if {[file exists $i/$path]} { return $i }
}
}
##
## Utilities for performing steps that are the same on several platforms
##
##
# Read kernel location from build-directory configuration
#
# If config file does not exist or if there is no 'KERNEL' declaration in the
# config file, the function returns 'default_location'. If the config file
# points to a non-existing kernel image, the function aborts with the exit
# value -6.
#
proc kernel_location_from_config_file { config_file default_location } {
global _kernel
if {![info exists _kernel]} {
if {[file exists $config_file]} {
set _kernel [exec sed -n "/^KERNEL/s/^.*=\\s*//p" $config_file]
# check if the regular expression matched
if {$_kernel != ""} {
if {[file exists $_kernel]} {
return $_kernel
} else {
puts stderr "Error: kernel specified in '$config_file' does not exist"
exit -6
}
}
}
# try to fall back to version hosted with the Genode build directory
set _kernel $default_location
}
return $_kernel
}
##
# Return name of kernel-specific binary for a given generic name
#
# The boot_dir plugin may provide functions named 'binary_name_<binary>'
# where '<binary>' stands for a generic name like "timer" or "nic". The
# function returns the name of the binary to integrate into the boot
# directory under the name '<binary>'.
#
# If no such function exists, it returns the argument as is. This is the
# case for regular binaries that appear in the boot directory under their
# original name.
#
proc kernel_specific_binary { binary {silent ""} } {
regsub -all {\.} $binary "_" function_suffix
set function_name "binary_name_$function_suffix"
if {[info procs $function_name] == $function_name} {
set binary_name [$function_name]
if {$silent != "silent"} {
puts "using '$binary_name' as '$binary'"
}
return [$function_name]
}
return $binary
}
proc copy_file {src dst} {
file copy -force $src $dst
}
proc copy_genode_binaries_to_run_dir { binaries } {
2015-01-08 21:08:48 +00:00
foreach binary $binaries {
copy_file bin/[kernel_specific_binary $binary] [run_dir]/genode/$binary
2015-01-08 21:08:48 +00:00
}
}
##
# 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
}
2015-10-26 14:02:14 +00:00
set platform_msg [run_boot_string]
if {$platform_msg eq ""} {
set platform_msg "undefined platform command startup string sequence"
}
2015-01-08 21:08:48 +00:00
expect {
2015-10-26 14:02:14 +00:00
-i $running_spawn_id $platform_msg { puts stderr "Error: platform rebooted unexpectedly"; exit -4 }
2015-01-08 21:08:48 +00:00
-i $running_spawn_id -re $wait_for_re { }
eof { puts stderr "Error: Spawned process died unexpectedly"; exit -3 }
timeout { puts stderr "Error: Test execution timed out"; exit -2 }
}
append output $expect_out(buffer)
2015-01-08 21:08:48 +00:00
}
##
# Remove 'genode' directory in 'run_dir' unless --preserve-genode-dir is present
# in RUN_OPT
#
proc remove_genode_dir { } {
global env
if {![get_cmd_switch --preserve-genode-dir]} {
exec rm -rf [run_dir]/genode
}
}
2015-01-08 21:08:48 +00:00
##
## Fall-back implementations of all run module procedures
##
##
# Dummy boot_string procedure
#
proc run_boot_string { } { return ""; }
2015-01-08 21:08:48 +00:00
##
# Fall-back boot_dir module
#
# If this function is called someone forgot to include an appropriate boot_dir
# module. So, we exit with an error.
#
proc run_boot_dir { binaries } {
puts stderr "Error: boot_dir module missing, e.g., '--include boot_dir/hw'"
exit 1
}
2015-01-08 21:08:48 +00:00
##
# Dummy image build module
#
proc run_image { {image "" } } { return true; }
##
# Dummy load module
#
proc run_load { } { return true; }
##
# Dummy output module
#
# XXX explain why exit 0 is appropiate
#
proc run_log { wait_for_re timeout_value } { exit 0 }
##
# Dummy power_on module
#
proc run_power_on { } { return true; }
##
# Dummy power_off module
#
proc run_power_off { } { return true; }
##
# Default power cycle fallback procedure
#
proc run_power_cycle { } {
#
# On targets that are directly connected to a socket,
# turn the socket off and on again. On targets that
# use a module were that is not required, e.g. softreset,
# power_off is a NOP. Note, we give the target some time
# to effectively drain energy before switching it on again.
#
run_power_off
sleep 1
return [run_power_on]
}
##
# Default core linker options
#
proc core_ld_opts { } {
set ret { -Wl,-T }
lappend ret "-Wl,[genode_dir]/repos/base/src/ld/genode.ld"
return $ret
}
2021-01-21 12:57:56 +00:00
##
# Default core link address
#
proc core_link_address { } { return "0x01000000" }
2021-01-21 12:57:56 +00:00
2015-01-08 21:08:48 +00:00
##
# Check if a specific file is included
#
proc have_include { name } {
global include_list
foreach element $include_list {
if {[string equal $element $name]} {
return true
}
}
return false
}
##
# Override the exit procedure
#
# We have to override the exit procedure to make sure that a loaded
# run_power_off procedure is in any case execute when stopping the
# execution of the run tool.
#
rename exit real_exit
proc exit {{status 0}} {
run_power_off
real_exit $status
}
##
# Determine terminal program
#
proc terminal { } {
global env
return x-terminal-emulator
2015-01-08 21:08:48 +00:00
}
##
# Return the board to build for
#
proc board { } {
global board_var
if {$board_var eq ""} {
puts "Unknown platform no BOARD variable set"
exit 1
}
return $board_var
}
##
# Return whether the board equals to the given string
#
proc have_board {board} { global board_var; return [expr {$board_var} eq {$board}] }
2021-01-21 12:57:56 +00:00
2015-01-08 21:08:48 +00:00
##
# Determine GDB executable installed at the host
#
proc gdb { } {
if {[have_installed "[cross_dev_prefix]gdb"]} {
return "[cross_dev_prefix]gdb" }
return [installed_command gdb]
2015-01-08 21:08:48 +00:00
}
##
# Generate assembly code aggregating boot-module data from specified files.
#
proc generate_boot_modules_asm {path modules} {
# architecture dependent definitions
if {[have_spec "64bit"]} { set address_type ".quad"
} else { set address_type ".long" }
# 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 \"${path}/${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
}
##
# Link core image containing given modules
#
proc build_core {lib modules target link_address} {
# generate assembly code aggregating the modules data
set asm_src [generate_boot_modules_asm [run_dir]/genode $modules]
# architecture dependent definitions
set arch {}
if {[have_spec "x86_64"]} { set arch { -m64 -mcmodel=large } }
if {[have_spec "x86_32"]} { set arch -m32 }
# determine the libgcc
set libgcc [exec [cross_dev_prefix]gcc -print-libgcc-file-name {*}$arch]
# compile the boot modules into one object file
exec [cross_dev_prefix]gcc {*}$arch -c -x assembler -o [run_dir].boot_modules.o - << $asm_src
# link final image
exec [cross_dev_prefix]g++ {*}$arch -nostdlib {*}[core_ld_opts] \
-Wl,-z -Wl,max-page-size=0x1000 \
-Wl,-Ttext=$link_address -Wl,-gc-sections \
-Wl,-nostdlib -Wl,--whole-archive -Wl,--start-group \
$lib [run_dir].boot_modules.o -Wl,--no-whole-archive \
-Wl,--end-group $libgcc -o $target
}
##
# Return kernel-specific files to be excluded from the core image
#
proc kernel_files { } { return { } }
##
# Generate bootable core image containing all boot-modules
#
proc build_core_image { modules } {
set core_obj [kernel_specific_binary core.a]
# replace 'core' with actual core-object name in 'modules' list
if {[lsearch $modules "core"] != -1} {
set idx [lsearch $modules "core"]
set modules [lreplace $modules $idx $idx]
lappend modules $core_obj
}
copy_genode_binaries_to_run_dir $modules
Disambiguate kernel-specific file names This patch removes possible ambiguities with respect to the naming of kernel-dependent binaries and libraries. It also removes the use of kernel-specific global side effects from the build system. The reach of kernel-specific peculiarities has thereby become limited to the actual users of the respective 'syscall-<kernel>' libraries. Kernel-specific build artifacts are no longer generated at magic places within the build directory (like okl4's includes, or the L4 build directories of L4/Fiasco and Fiasco.OC, or the build directories of various kernels). Instead, such artifacts have been largely moved to the libcache. E.g., the former '<build-dir>/l4/' build directory for the L4 build system resides at '<build-dir>/var/libcache/syscall-foc/build/'. This way, the location is unique to the kernel. Note that various tools are still generated somewhat arbitrarily under '<build-dir>/tool/' as there is no proper formalism for building host tools yet. As the result of this work, it has become possible to use a joint Genode build directory that is usable with all kernels of a given hardware platform. E.g., on x86_32, one can now seamlessly switch between linux, nova, sel4, okl4, fiasco, foc, and pistachio without rebuilding any components except for core, the kernel, the dynamic linker, and the timer driver. At the current stage, such a build directory must still be created manually. A change of the 'create_builddir' tool will follow to make this feature easily available. This patch also simplifies various 'run/boot_dir' plugins by removing the option for an externally hosted kernel. This option remained unused for many years now. Issue #2190
2016-12-10 00:30:38 +00:00
# create core binary without modules for debugging
if {[file exists debug/$core_obj]} {
build_core debug/$core_obj {} [run_dir].core [core_link_address]
}
# determine modules to be incorporated into the core image
set modules [glob -nocomplain -tails -directory [run_dir]/genode/ *]
set excluded_modules [kernel_files]
lappend excluded_modules $core_obj
foreach excluded $excluded_modules {
set modules [lsearch -inline -not -all $modules $excluded] }
# check syntax of all boot modules named *.config
foreach file [glob -nocomplain [run_dir]/genode/*.config] {
check_xml_syntax $file }
# create core binary containing the boot modules
build_core [run_dir]/genode/$core_obj $modules [run_dir]/image.elf [core_link_address]
exec [cross_dev_prefix]strip [run_dir]/image.elf
# Save config part of the image.elf for easy inspection
exec cp -f [run_dir]/genode/config [run_dir].config
}
2021-01-21 12:57:56 +00:00
proc build_initrd { modules } {
2021-01-21 12:57:56 +00:00
copy_genode_binaries_to_run_dir $modules
2021-01-21 12:57:56 +00:00
set modules [glob -nocomplain -tails -directory [run_dir]/genode/ *]
set excluded_modules [kernel_files]
2021-01-21 12:57:56 +00:00
foreach file [glob -nocomplain [run_dir]/genode/*.config] {
check_xml_syntax $file }
2021-01-21 12:57:56 +00:00
exec cp -f [run_dir]/genode/config [run_dir].config
set here [pwd]
cd [run_dir]
puts "generating initrd"
exec cp genode/initramfs init
exec mkdir tmp
exec mkdir dev
set files "init\ntmp\ndev\ngenode\n"
append files [exec find genode -type f,l -printf "genode/%f\n"]
exec -ignorestderr echo $files | [installed_command cpio] -o -L -H newc > initrd
#workaround because cpio fails to compress broken links sometimes
exec touch dev/platform_info
cd genode
exec ln -s ../dev/platform_info platform_info
cd ..
exec -ignorestderr echo "genode/platform_info" | [installed_command cpio] -o -A -H newc -O initrd
cd ${here}
}
source [genode_dir]/tool/run/depot.inc
source [genode_dir]/tool/run/qemu.inc
2015-01-08 21:08:48 +00:00
##
## Execution of run scripts
##
set include_list { }
##
# Read and execute files specified as '--include' arguments
#
# Out of convenience run modules may be included by using a relative path.
#
foreach include_name [get_cmd_arg --include ""] {
# first check if the include name is absolute
if {[string first "/" $include_name] == 0} {
puts "including $include_name"
lappend include_list $include_name
source $include_name
continue
}
# if it is relative, check repositories and tool directory for run modules
set search_dirs {}
foreach rep_dir $repositories {
lappend search_dirs [file join $rep_dir tool run] }
lappend search_dirs [genode_dir]/tool/run
2015-01-08 21:08:48 +00:00
set found 0
foreach dir $search_dirs {
set include_file $dir/$include_name
2015-01-08 21:08:48 +00:00
if {[file exists $include_file] == 1} {
puts "including $include_file"
lappend include_list $include_name
source $include_file
set found 1
break
}
}
if {!$found} {
puts stderr "Aborting, could not load '$include_file'"
exit -1;
}
}
puts "\nRun script execution successful."
exit 0