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
|
|
|
|
#
|
2017-03-09 10:54:05 +00:00
|
|
|
proc append_if {condition var args} {
|
2015-01-08 21:08:48 +00:00
|
|
|
upvar $var up_var
|
2017-03-09 10:54:05 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
##
|
2017-12-03 17:48:40 +00:00
|
|
|
# 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
|
|
|
|
#
|
2018-07-04 12:08:16 +00:00
|
|
|
proc check_config {bin xml_file xsd_file label avail_xsd_files xsd_inc nesting_level} {
|
2017-12-03 17:48:40 +00:00
|
|
|
|
|
|
|
# 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
|
|
|
|
}
|
2017-09-05 21:05:43 +00:00
|
|
|
}
|
|
|
|
|
2017-12-03 17:48:40 +00:00
|
|
|
# check the given component configuration itself
|
|
|
|
puts " CHECK $label"
|
2018-07-04 12:08:16 +00:00
|
|
|
if {[catch {exec xmllint --noout --path $xsd_inc -schema $xsd_file $xml_file} result]} {
|
2017-12-03 17:48:40 +00:00
|
|
|
|
2017-09-05 21:05:43 +00:00
|
|
|
if {$result != "$xml_file validates"} {
|
2017-12-03 17:48:40 +00:00
|
|
|
|
2017-09-05 21:05:43 +00:00
|
|
|
puts stderr "$result"
|
2017-12-03 17:48:40 +00:00
|
|
|
puts stderr "Error: Invalid XML syntax"
|
2017-09-05 21:05:43 +00:00
|
|
|
exit 1
|
|
|
|
}
|
|
|
|
}
|
2017-12-03 17:48:40 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# 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 \
|
2018-07-04 12:08:16 +00:00
|
|
|
$child_label $avail_xsd_files $xsd_inc \
|
|
|
|
[expr $nesting_level+1]
|
2017-12-03 17:48:40 +00:00
|
|
|
|
|
|
|
# clean up
|
|
|
|
exec rm -f $child_xml_file
|
|
|
|
}
|
|
|
|
}
|
2017-09-05 21:05:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
##
|
|
|
|
# Install content of specified variable as init config file
|
2015-01-08 21:08:48 +00:00
|
|
|
#
|
2017-07-05 14:36:27 +00:00
|
|
|
proc install_config { args } {
|
2015-01-08 21:08:48 +00:00
|
|
|
set fh [open "[run_dir]/genode/config" "WRONLY CREAT TRUNC"]
|
2017-07-05 14:36:27 +00:00
|
|
|
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} {
|
2017-12-03 17:48:40 +00:00
|
|
|
|
2017-12-17 21:04:33 +00:00
|
|
|
check_for_missing_depot_archives
|
|
|
|
|
|
|
|
# lookup XSD files in the run-script-specific folder
|
2017-12-03 17:48:40 +00:00
|
|
|
set xsd_files ""
|
2017-12-17 21:04:33 +00:00
|
|
|
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
|
2017-12-03 17:48:40 +00:00
|
|
|
foreach binary $binaries {
|
|
|
|
if {[file exists "bin/$binary.xsd"]} {
|
|
|
|
lappend xsd_files "bin/$binary.xsd"
|
|
|
|
}
|
|
|
|
}
|
2017-12-17 21:04:33 +00:00
|
|
|
# determine which XSD file to use for the init config
|
2021-04-14 08:08:57 +00:00
|
|
|
set init_xsd_file ""
|
2017-12-17 21:04:33 +00:00
|
|
|
foreach xsd_file $xsd_files {
|
|
|
|
set filename [file tail $xsd_file]
|
|
|
|
if {$filename == "init.xsd"} {
|
|
|
|
set init_xsd_file $xsd_file
|
|
|
|
}
|
|
|
|
}
|
2018-07-04 12:08:16 +00:00
|
|
|
# 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 " }
|
|
|
|
}
|
2017-12-17 21:04:33 +00:00
|
|
|
# check configurations of init and its children
|
2017-12-03 17:48:40 +00:00
|
|
|
puts "checking configuration syntax"
|
2018-07-04 12:08:16 +00:00
|
|
|
check_config init [run_dir]/genode/config $init_xsd_file init $xsd_files $xsd_inc 0
|
2017-12-03 17:48:40 +00:00
|
|
|
|
2015-01-08 21:08:48 +00:00
|
|
|
run_boot_dir $binaries
|
|
|
|
}
|
|
|
|
|
2021-01-21 12:57:56 +00:00
|
|
|
|
2015-02-12 12:13:21 +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 } {
|
|
|
|
|
2019-02-01 10:50:08 +00:00
|
|
|
#
|
|
|
|
# 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."
|
2017-08-07 14:30:38 +00:00
|
|
|
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} {
|
2019-09-26 12:51:39 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-09-26 12:51:39 +00:00
|
|
|
##
|
|
|
|
# "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 ""]
|
2019-05-09 12:04:03 +00:00
|
|
|
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} {
|
2018-06-19 17:55:04 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
##
|
2018-06-19 17:55:04 +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
|
|
|
#
|
2018-06-19 17:55:04 +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
|
|
|
}
|
2018-06-19 17:55:04 +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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-12-09 22:09:17 +00:00
|
|
|
##
|
|
|
|
# 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.
|
|
|
|
#
|
2017-05-17 10:57:14 +00:00
|
|
|
proc kernel_specific_binary { binary {silent ""} } {
|
2016-12-09 22:09:17 +00:00
|
|
|
|
|
|
|
regsub -all {\.} $binary "_" function_suffix
|
|
|
|
set function_name "binary_name_$function_suffix"
|
|
|
|
|
|
|
|
if {[info procs $function_name] == $function_name} {
|
|
|
|
set binary_name [$function_name]
|
2017-05-17 10:57:14 +00:00
|
|
|
if {$silent != "silent"} {
|
|
|
|
puts "using '$binary_name' as '$binary'"
|
|
|
|
}
|
2016-12-09 22:09:17 +00:00
|
|
|
return [$function_name]
|
|
|
|
}
|
|
|
|
|
|
|
|
return $binary
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-04-14 08:10:25 +00:00
|
|
|
proc copy_file {src dst} {
|
|
|
|
file copy -force $src $dst
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-04-03 13:39:36 +00:00
|
|
|
proc copy_genode_binaries_to_run_dir { binaries } {
|
2015-01-08 21:08:48 +00:00
|
|
|
|
|
|
|
foreach binary $binaries {
|
2021-04-14 08:10:25 +00:00
|
|
|
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 }
|
|
|
|
}
|
2015-03-24 10:02:56 +00:00
|
|
|
append output $expect_out(buffer)
|
2015-01-08 21:08:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-05-16 09:03:59 +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
|
|
|
|
##
|
|
|
|
|
2015-02-06 17:02:55 +00:00
|
|
|
##
|
|
|
|
# Dummy boot_string procedure
|
2017-04-03 13:39:36 +00:00
|
|
|
#
|
2015-02-06 17:02:55 +00:00
|
|
|
proc run_boot_string { } { return ""; }
|
|
|
|
|
2017-04-03 13:39:36 +00:00
|
|
|
|
2015-01-08 21:08:48 +00:00
|
|
|
##
|
2015-04-28 16:34:15 +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.
|
2017-04-03 13:39:36 +00:00
|
|
|
#
|
2015-04-28 16:34:15 +00:00
|
|
|
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; }
|
|
|
|
|
|
|
|
|
2019-02-01 10:50:08 +00:00
|
|
|
##
|
|
|
|
# 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]
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-15 14:08:33 +00:00
|
|
|
##
|
|
|
|
# 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
|
|
|
|
2016-09-15 14:08:33 +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
|
2020-04-06 13:17:50 +00:00
|
|
|
return x-terminal-emulator
|
2015-01-08 21:08:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-05-09 12:04:03 +00:00
|
|
|
##
|
|
|
|
# Return the board to build for
|
|
|
|
#
|
|
|
|
proc board { } {
|
|
|
|
global board_var
|
|
|
|
if {$board_var eq ""} {
|
|
|
|
puts "Unknown platform no BOARD variable set"
|
2019-06-13 15:06:57 +00:00
|
|
|
exit 1
|
2019-05-09 12:04:03 +00:00
|
|
|
}
|
|
|
|
return $board_var
|
|
|
|
}
|
|
|
|
|
2021-01-07 18:15:55 +00:00
|
|
|
##
|
|
|
|
# Return whether the board equals to the given string
|
|
|
|
#
|
|
|
|
proc have_board {board} { global board_var; return [expr {$board_var} eq {$board}] }
|
2019-05-09 12:04:03 +00:00
|
|
|
|
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" }
|
|
|
|
|
2018-06-19 17:55:04 +00:00
|
|
|
return [installed_command gdb]
|
2015-01-08 21:08:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-15 14:08:33 +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"
|
|
|
|
}
|
|
|
|
|
2017-09-22 12:15:26 +00:00
|
|
|
append asm_src ".p2align MIN_PAGE_SIZE_LOG2\n"
|
2016-09-15 14:08:33 +00:00
|
|
|
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
|
|
|
|
#
|
2016-10-20 08:28:11 +00:00
|
|
|
proc build_core {lib modules target link_address} {
|
2016-09-15 14:08:33 +00:00
|
|
|
|
|
|
|
# generate assembly code aggregating the modules data
|
|
|
|
set asm_src [generate_boot_modules_asm [run_dir]/genode $modules]
|
|
|
|
|
|
|
|
# architecture dependent definitions
|
|
|
|
set arch {}
|
2017-06-20 13:25:04 +00:00
|
|
|
if {[have_spec "x86_64"]} { set arch { -m64 -mcmodel=large } }
|
2016-09-15 14:08:33 +00:00
|
|
|
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 \
|
2016-10-20 08:28:11 +00:00
|
|
|
-Wl,-Ttext=$link_address -Wl,-gc-sections \
|
2016-09-15 14:08:33 +00:00
|
|
|
-Wl,-nostdlib -Wl,--whole-archive -Wl,--start-group \
|
|
|
|
$lib [run_dir].boot_modules.o -Wl,--no-whole-archive \
|
|
|
|
-Wl,--end-group $libgcc -o $target
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-04-03 13:39:36 +00:00
|
|
|
##
|
|
|
|
# Return kernel-specific files to be excluded from the core image
|
|
|
|
#
|
|
|
|
proc kernel_files { } { return { } }
|
|
|
|
|
|
|
|
|
2016-09-15 14:08:33 +00:00
|
|
|
##
|
|
|
|
# Generate bootable core image containing all boot-modules
|
|
|
|
#
|
2017-04-03 13:39:36 +00:00
|
|
|
proc build_core_image { modules } {
|
2016-12-08 11:25:00 +00:00
|
|
|
|
2021-02-19 14:23:49 +00:00
|
|
|
set core_obj [kernel_specific_binary core.a]
|
2016-09-15 14:08:33 +00:00
|
|
|
|
2017-04-03 13:39:36 +00:00
|
|
|
# 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
|
|
|
|
}
|
2016-09-15 14:08:33 +00:00
|
|
|
|
2017-04-03 13:39:36 +00:00
|
|
|
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
|
|
|
|
2016-09-15 14:08:33 +00:00
|
|
|
# create core binary without modules for debugging
|
2017-10-20 09:49:26 +00:00
|
|
|
if {[file exists debug/$core_obj]} {
|
|
|
|
build_core debug/$core_obj {} [run_dir].core [core_link_address]
|
|
|
|
}
|
2017-04-03 13:39:36 +00:00
|
|
|
|
|
|
|
# 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 }
|
2016-09-15 14:08:33 +00:00
|
|
|
|
|
|
|
# create core binary containing the boot modules
|
2017-04-03 13:39:36 +00:00
|
|
|
build_core [run_dir]/genode/$core_obj $modules [run_dir]/image.elf [core_link_address]
|
2016-09-15 14:08:33 +00:00
|
|
|
exec [cross_dev_prefix]strip [run_dir]/image.elf
|
2016-12-08 11:25:00 +00:00
|
|
|
|
2017-02-09 13:04:04 +00:00
|
|
|
# Save config part of the image.elf for easy inspection
|
2017-04-03 13:39:36 +00:00
|
|
|
exec cp -f [run_dir]/genode/config [run_dir].config
|
2016-09-15 14:08:33 +00:00
|
|
|
}
|
|
|
|
|
2021-01-21 12:57:56 +00:00
|
|
|
|
2017-10-20 12:11:44 +00:00
|
|
|
proc build_initrd { modules } {
|
|
|
|
|
2021-01-21 12:57:56 +00:00
|
|
|
copy_genode_binaries_to_run_dir $modules
|
2017-10-20 12:11:44 +00:00
|
|
|
|
2021-01-21 12:57:56 +00:00
|
|
|
set modules [glob -nocomplain -tails -directory [run_dir]/genode/ *]
|
|
|
|
set excluded_modules [kernel_files]
|
2017-10-20 12:11:44 +00:00
|
|
|
|
2021-01-21 12:57:56 +00:00
|
|
|
foreach file [glob -nocomplain [run_dir]/genode/*.config] {
|
2017-10-20 12:11:44 +00:00
|
|
|
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}
|
2017-10-20 12:11:44 +00:00
|
|
|
}
|
|
|
|
|
2017-03-29 14:04:07 +00:00
|
|
|
source [genode_dir]/tool/run/depot.inc
|
2020-04-02 19:20:50 +00:00
|
|
|
source [genode_dir]/tool/run/qemu.inc
|
2017-03-29 14:04:07 +00:00
|
|
|
|
2016-09-15 14:08:33 +00:00
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2021-01-19 13:17:26 +00:00
|
|
|
# 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
|
2021-01-19 13:17:26 +00:00
|
|
|
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
|