mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-25 08:21:08 +00:00
42db1e112b
* introduces central memory map for core/kernel * on 32-bit platforms the kernel/core starts at 0x80000000 * on 64-bit platforms the kernel/core starts at 0xffffffc000000000 * mark kernel/core mappings as global ones (tagged TLB) * move the exception vector to begin of core's binary, thereby bootstrap knows from where to map it appropriately * do not map boot modules into core anymore * constrain core's virtual heap memory area * differentiate in between user's and core's main thread's UTCB, which now resides inside the kernel segment Ref #2091
889 lines
20 KiB
Plaintext
Executable File
889 lines
20 KiB
Plaintext
Executable File
#!/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} {
|
|
upvar $var up_var
|
|
if {$condition} { append up_var [join $args ""] }
|
|
}
|
|
|
|
|
|
##
|
|
# 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 file to match Genode's XML schema using xmllint
|
|
#
|
|
proc check_xml_with_schema {xml_file} {
|
|
|
|
if {![have_installed xmllint]} {
|
|
puts "Warning: Cannot validate config syntax (please install xmllint)"
|
|
return;
|
|
}
|
|
|
|
if {[catch {exec xmllint --noout -schema [genode_dir]/tool/run/genode.xsd $xml_file} result]} {
|
|
if {$result != "$xml_file validates"} {
|
|
puts stderr "$result"
|
|
puts stderr "Error: Invalid XML syntax in $xml_file"
|
|
exit 1
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
##
|
|
# Install content of specified variable as init config file
|
|
#
|
|
proc install_config { args } {
|
|
set fh [open "[run_dir]/genode/config" "WRONLY CREAT TRUNC"]
|
|
puts $fh [join $args {}]
|
|
close $fh
|
|
|
|
check_xml_with_schema [run_dir]/genode/config
|
|
}
|
|
|
|
|
|
##
|
|
# 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
|
|
run_boot_dir $binaries
|
|
}
|
|
|
|
# set expect match-buffer size
|
|
match_max -d 40000
|
|
|
|
##
|
|
# 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 } {
|
|
|
|
if {[expr [run_power_on] == false]} {
|
|
puts "Power on step failed, retry."
|
|
sleep 3
|
|
incr retry -1;
|
|
continue
|
|
}
|
|
|
|
if {![run_load]} {
|
|
puts "Load step failed, retry."
|
|
|
|
# kill the spawned load process if there is one
|
|
if {[load_spawn_id] != -1} {
|
|
set pid [exp_pid -i [load_spawn_id]]
|
|
exec kill -9 $pid
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
##
|
|
# 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
|
|
}
|
|
|
|
##
|
|
# 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 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 }]} { return false; }
|
|
return true
|
|
}
|
|
|
|
|
|
##
|
|
# Return true if specified program is installed on the host platform
|
|
#
|
|
proc requires_installation_of {program} {
|
|
if {![have_installed $program]} {
|
|
puts "Run script aborted because $program is not installed"; exit
|
|
}
|
|
}
|
|
|
|
|
|
##
|
|
# 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_genode_binaries_to_run_dir { binaries } {
|
|
|
|
foreach binary $binaries {
|
|
file copy -force bin/[kernel_specific_binary $binary] [run_dir]/genode/$binary
|
|
}
|
|
}
|
|
|
|
|
|
##
|
|
# 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
|
|
}
|
|
|
|
set platform_msg [run_boot_string]
|
|
if {$platform_msg eq ""} {
|
|
set platform_msg "undefined platform command startup string sequence"
|
|
}
|
|
|
|
expect {
|
|
-i $running_spawn_id $platform_msg { puts stderr "Error: platform rebooted unexpectedly"; exit -4 }
|
|
-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)
|
|
}
|
|
|
|
|
|
##
|
|
## Fall-back implementations of all run module procedures
|
|
##
|
|
|
|
##
|
|
# Dummy boot_string procedure
|
|
#
|
|
proc run_boot_string { } { return ""; }
|
|
|
|
|
|
##
|
|
# 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
|
|
}
|
|
|
|
|
|
##
|
|
# 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 core linker options
|
|
#
|
|
proc core_ld_opts { } {
|
|
set ret { -Wl,-T }
|
|
lappend ret "-Wl,[genode_dir]/repos/base/src/ld/genode.ld"
|
|
return $ret
|
|
}
|
|
|
|
##
|
|
# Default core link address
|
|
#
|
|
proc core_link_address { } { return "0x01000000" }
|
|
|
|
##
|
|
# 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
|
|
if {[info exists env(COLORTERM)]} {
|
|
return $env(COLORTERM)
|
|
}
|
|
return $env(TERM)
|
|
}
|
|
|
|
|
|
##
|
|
# Determine GDB executable installed at the host
|
|
#
|
|
proc gdb { } {
|
|
if {[have_installed "[cross_dev_prefix]gdb"]} {
|
|
return "[cross_dev_prefix]gdb" }
|
|
|
|
if {[have_installed gdb]} {
|
|
return "gdb" }
|
|
|
|
requires_installation_of gdb
|
|
}
|
|
|
|
|
|
##
|
|
# Check if a shell command is installed
|
|
#
|
|
# \param command name of the command to search
|
|
#
|
|
# \return absolute path of command if found, or exists if not
|
|
#
|
|
proc check_installed {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
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
|
|
##
|
|
# 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.o]
|
|
|
|
# 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
|
|
|
|
# create core binary without modules for debugging
|
|
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
|
|
}
|
|
|
|
source [genode_dir]/tool/run/depot.inc
|
|
|
|
|
|
##
|
|
## 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 run modules
|
|
set run_path [genode_dir]/tool/run
|
|
set dir { etc }
|
|
lappend dir $run_path
|
|
|
|
set found 0
|
|
foreach location $dir {
|
|
set include_file $location/$include_name
|
|
if {[file exists $include_file] == 1} {
|
|
puts "including $include_file"
|
|
lappend include_list $include_name
|
|
source $include_file
|
|
|
|
set found 1
|
|
break
|
|
} else {
|
|
}
|
|
}
|
|
|
|
if {!$found} {
|
|
puts stderr "Aborting, could not load '$include_file'"
|
|
exit -1;
|
|
}
|
|
}
|
|
|
|
puts "\nRun script execution successful."
|
|
exit 0
|