#!/usr/bin/expect # # \brief Implementation of the 'tool/run' interface # \author Martin Stein # \date 2011-12-16 # ############### ## Utilities ## ############### # # Ensure that the next Genode build includes no target specific boot modules # proc clean_boot_modules { } { exec rm -rf boot_modules.s var/libcache/boot_modules/boot_modules.o } # # Get target argument # proc target { } { return [get_cmd_arg --target "qemu"] } ########################## ## 'tool/run' interface ## ########################## proc build {targets} { # skip targets that shall not be build if {[get_cmd_switch --skip-build]} return # handle false remnants of previous builds clean_boot_modules # # Build all remaining targets. # Core is build with a dummy boot-modules file first. # regsub -all {\s\s+} $targets " " targets set timeout 10000 set pid [eval "spawn make $targets"] expect { eof { } } if {[lindex [wait $pid] end] != 0} { puts stderr "Error: Genode build failed" exit -1 } } proc create_boot_directory { } { exec rm -rf [run_dir] exec mkdir -p [run_dir]/genode } proc build_boot_image {binaries} { # strip binaries copy_and_strip_genode_binaries_to_run_dir $binaries # append init config if {[file exists "[run_dir]/genode/config"] == 1} { append binaries " config" } # # 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}] } { 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 # 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" # offer ELF image set elf_img "[run_dir]/image.elf" exec cp -L bin/core $elf_img exec [cross_dev_prefix]strip $elf_img # 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} {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 } # # Try to use one of the supported backends for running the scripts # # if {[is_amt_available]} { # spawn_amt $wait_for_re $timeout_value # return # } # if {[is_qemu_available]} { # spawn_qemu $wait_for_re $timeout_value # return # } if {[target] == "qemu"} { spawn_qemu $wait_for_re $timeout_value } else { puts stderr "Error: Can't execute automatically on target '[target]'" puts stderr " Target might be: 'qemu'" exit -1 } }