diff --git a/base-hw/run/env b/base-hw/run/env index 0ac36188eb..821cf42f77 100644 --- a/base-hw/run/env +++ b/base-hw/run/env @@ -1,146 +1,32 @@ #!/usr/bin/expect # -# \brief Implementation of the interface provided by 'tool/run' +# \brief Implementation of the 'tool/run' interface # \author Martin Stein # \date 2011-12-16 # -###################### -## Utility routines ## -###################### - -# -# Build an assembly file that enables the creation of a single boot image -# -# \param file targeted file -# \parem binaries targeted boot modules, must reside in '[run_dir]/genode/' -# -# This file rawly includes all binaries given in -# 'binaries', minus 'core' if given, plus 'config' if available. It also -# provides a simple file system that enables Genode to access these BLOBs. -# -proc boot_modules_arm {{file} {binaries}} { - - set load_store_align_l2 2 - set min_page_align_l2 12 - - # introduce boot module headers - exec echo -e \ - "/**" \ - "\n * This file was automatically generated by the procedure" \ - "\n * 'boot_modules_arm' in 'run/env'." \ - "\n */" \ - "\n" \ - "\n.section .data" \ - "\n" \ - "\n.p2align ${load_store_align_l2}" \ - "\n.global _boot_modules_begin" \ - "\n_boot_modules_begin:" \ - "\n.string \"GROM\"" \ - "\n" \ - "\n.p2align ${load_store_align_l2}" \ - "\n.global _boot_module_headers_begin" \ - "\n_boot_module_headers_begin:" > $file - - # generate header for each boot module except core - set i 1 - foreach binary $binaries { - if {$binary == "core"} { continue } - exec echo -e \ - "\n.long mod${i}_name" \ - "\n.long mod${i}_start" \ - "\n.long mod${i}_end - mod${i}_start" >> $file - incr i - } - - # end boot module headers - exec echo -e \ - "\n.global _boot_module_headers_end" \ - "\n_boot_module_headers_end:" \ - "\n" >> $file - - # generate name string for each module except core - set i 1 - foreach binary $binaries { - if {$binary == "core"} { continue } - exec echo -e \ - ".p2align ${load_store_align_l2}" \ - "\nmod${i}_name:" \ - "\n.string \"${binary}\"" \ - "\n.byte 0" \ - "\n" >> $file - incr i - } - - # include raw data of modules consecutively but page aligned - set i 1 - foreach binary $binaries { - if {$binary == "core"} { continue } - exec echo -e \ - ".p2align ${min_page_align_l2}" \ - "\nmod${i}_start:" \ - "\n.incbin \"[run_dir]/genode/${binary}\"" \ - "\nmod${i}_end:" \ - "\n" >> $file - incr i - } - - # end boot-modules file - exec echo -e \ - ".global _boot_modules_end" \ - "\n_boot_modules_end:" >> $file -} - +############### +## Utilities ## +############### # # Ensure that the next Genode build includes no target specific boot modules # -proc disable_specific_boot_modules { } { - - exec rm -rf boot_modules.s - exec rm -rf var/libcache/boot_modules/boot_modules.o -} +proc clean_boot_modules { } { + exec rm -rf boot_modules.s var/libcache/boot_modules/boot_modules.o } # -# Ensure that the next Genode build includes target specific boot modules +# Get target argument # -proc enable_specific_boot_modules {file} { - - exec rm -rf boot_modules.s - exec ln -s $file boot_modules.s - exec rm -rf var/libcache/boot_modules/boot_modules.o - exec find . -type f -name "core" -delete -} +proc target { } { return [get_cmd_arg --target "qemu"] } -# -# Apply the boot modules file 'file' to the core image -# -proc apply_boot_modules_to_core {file} { - - # recompile 'core', with specific boot modules - puts "Building single boot image" - set timeout 10000 - enable_specific_boot_modules $file - set pid [eval "spawn make core"] - expect { eof { } } - if {[lindex [wait $pid] end] != 0} { - puts "Error: Genode build failed" - exit -4 - } - - # clean up for subsequent builds - disable_specific_boot_modules - puts "Single boot image built" -} - - -###################################### -## Interface supplied by 'tool/run' ## -###################################### +########################## +## 'tool/run' interface ## +########################## proc build {targets} { @@ -148,22 +34,20 @@ proc build {targets} { if {[get_cmd_switch --skip-build]} return # handle false remnants of previous builds - disable_specific_boot_modules + clean_boot_modules # # Build all remaining targets. # Core is build with a dummy boot-modules file first. # 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 stderr "Error: Genode build failed" + exit -1 } - puts "genode build completed" } @@ -176,49 +60,157 @@ proc create_boot_directory { } { proc build_boot_image {binaries} { - # create additional stripped version of any binary + # strip binaries copy_and_strip_genode_binaries_to_run_dir $binaries - # append init configuration if existent to the binaries + # append init config if {[file exists "[run_dir]/genode/config"] == 1} { append binaries " config" } - # create scenario-specific 'boot_modules.s' of all given binaries + # + # Compose a platform specific assembly file 'boot_modules.s', that + # enables the creation of a single boot image. The file rawly includes + # all binaries given in 'binaries', minus 'core', if given, plus 'config', + # if available. It also provides a simple file system, that enables Genode + # to access these BLOBs. To build a single image this file is simply + # linked against core. To build core stand-alone this file is substituted + # by a dummy version. 'boot_modules.s' must be composed on demand, because + # it depends on the individual run scenario. + # set boot_modules "[run_dir]/boot_modules.s" if { [have_spec {arm}] } { - boot_modules_arm $boot_modules $binaries - puts "Boot_modules: ${boot_modules}" - exec cp ${boot_modules} /tmp/ + + set load_store_align_l2 2 + set min_page_align_l2 12 + + # introduce boot module headers + exec echo -e \ + "/**" \ + "\n * This file was automatically generated by the procedure" \ + "\n * 'build_boot_image' in 'base-hw/run/env'." \ + "\n */" \ + "\n" \ + "\n.section .data" \ + "\n" \ + "\n.p2align ${load_store_align_l2}" \ + "\n.global _boot_modules_begin" \ + "\n_boot_modules_begin:" \ + "\n.string \"GROM\"" \ + "\n" \ + "\n.p2align ${load_store_align_l2}" \ + "\n.global _boot_module_headers_begin" \ + "\n_boot_module_headers_begin:" > $boot_modules + + # generate header for each boot module except core + set i 1 + foreach binary $binaries { + if {$binary == "core"} { continue } + exec echo -e \ + "\n.long mod${i}_name" \ + "\n.long mod${i}_start" \ + "\n.long mod${i}_end - mod${i}_start" >> $boot_modules + incr i + } + + # end boot module headers + exec echo -e \ + "\n.global _boot_module_headers_end" \ + "\n_boot_module_headers_end:" \ + "\n" >> $boot_modules + + # generate name string for each module except core + set i 1 + foreach binary $binaries { + if {$binary == "core"} { continue } + exec echo -e \ + ".p2align ${load_store_align_l2}" \ + "\nmod${i}_name:" \ + "\n.string \"${binary}\"" \ + "\n.byte 0" \ + "\n" >> $boot_modules + incr i + } + + # include raw data of modules consecutively but page aligned + set i 1 + foreach binary $binaries { + if {$binary == "core"} { continue } + exec echo -e \ + ".p2align ${min_page_align_l2}" \ + "\nmod${i}_start:" \ + "\n.incbin \"[run_dir]/genode/${binary}\"" \ + "\nmod${i}_end:" \ + "\n" >> $boot_modules + incr i + } + + # end boot-modules file + exec echo -e \ + ".global _boot_modules_end" \ + "\n_boot_modules_end:" >> $boot_modules + + } else { + puts stderr "Error: Unknown architecture" + puts stderr " SPEC must contain one of: 'arm'" + exit -1 } + clean_boot_modules + exec ln -s $boot_modules boot_modules.s - # preserve stand-alone core for debugging + # recompile core with boot modules exec cp -L bin/core core/core.standalone + exec find . -type f -name "core" -delete + set timeout 10000 + set pid [eval "spawn make core"] + expect { eof { } } + if {[lindex [wait $pid] end] != 0} { + clean_boot_modules + puts stderr "Error: Genode build failed" + exit -1 + } + clean_boot_modules + exec rm -rf "[run_dir]/genode" - # apply the new 'boot_modules.s' to 'core' to create single boot image - apply_boot_modules_to_core $boot_modules - exec cp -L bin/core [run_dir]/image.elf - exec [cross_dev_prefix]strip [run_dir]/image.elf + # offer ELF image + set elf_img "[run_dir]/image.elf" + exec cp -L bin/core $elf_img + exec [cross_dev_prefix]strip $elf_img - # remove stripped binaries and retrieve stand-alone core - exec cp core/core.standalone bin/core - exec rm core/core.standalone - exec rm -r [run_dir]/genode + # target specific ops + if {[target] == "uboot"} { + + # parse ELF entrypoint and load address + set entrypoint [exec [cross_dev_prefix]readelf -h $elf_img | \ + grep "Entry point address: " | \ + sed -e "s/.*Entry point address: *//"] + set load_addr [exec [cross_dev_prefix]readelf -l $elf_img | \ + grep -m 1 "LOAD"] + set load_addr [lindex [regexp -inline -all -- {\S+} $load_addr] 3] + + # compress ELF + set bin_img "[run_dir]/image.bin" + exec [cross_dev_prefix]objcopy -O binary $elf_img $bin_img + exec gzip --best --force $bin_img + + # create compressed uImage + set uboot_img [run_dir]/uImage + exec mkimage -A arm -O linux -T kernel -C gzip -a $load_addr \ + -e $entrypoint -d $bin_img.gz $uboot_img + exec rm -rf $bin_img.gz + } + # retrieve stand-alone core + exec mv core/core.standalone bin/core } proc run_genode_until {{wait_for_re forever} {timeout_value 0}} { - # get the targeted method of execution, the default is 'qemu' - set image [run_dir]/image.elf - set target [get_cmd_arg --target "qemu"] - - # try to execute image according to the targeted method of execution - if { $target == "qemu" } { - spawn_qemu $wait_for_re $timeout_value + if {[target] == "qemu"} { spawn_qemu $wait_for_re $timeout_value } else { - puts stderr "Error: Target '${target}' is not supported" - puts stderr " Supported targets are: 'qemu'"; exit -3 + puts stderr "Error: Can't execute automatically on target '$target'" + puts stderr " Target might be: 'qemu'" + exit -1 } }