]> rtime.felk.cvut.cz Git - novaboot.git/blobdiff - novaboot
Doc: Rename CONFIGURATION FILE to CONFIGURATION FILES
[novaboot.git] / novaboot
index c8576ec3dfce2dc57ebaa5f3ed673dc77c141e92..3c653c3ec0749e29563d747098675f6e9ed22e27 100755 (executable)
--- a/novaboot
+++ b/novaboot
@@ -13,6 +13,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+## Initialization
+
 use strict;
 use warnings;
 use warnings (exists $ENV{NOVABOOT_TEST} ? (FATAL => 'all') : ());
@@ -25,7 +27,7 @@ use Time::HiRes("usleep");
 use Socket;
 use FileHandle;
 use IPC::Open2;
-use POSIX qw(:errno_h);
+use POSIX qw(:errno_h sysconf);
 use Cwd qw(getcwd abs_path);
 use Expect;
 
@@ -41,7 +43,7 @@ $CFG::hypervisor = "";
 $CFG::hypervisor_params = "serial";
 $CFG::genisoimage = "genisoimage";
 $CFG::qemu = 'qemu-system-i386 -cpu coreduo -smp 2';
-$CFG::default_target = 'qemu';
+$CFG::default_target = '';
 %CFG::targets = (
     'qemu' => '--qemu',
     "tud" => '--server=erwin.inf.tu-dresden.de:~sojka/boot/novaboot --rsync-flags="--chmod=Dg+s,ug+w,o-w,+rX --rsync-path=\"umask 002 && rsync\"" --grub --grub-prefix=(nd)/tftpboot/sojka/novaboot --grub-preamble="timeout 0" --concat --iprelay=141.76.48.80:2324 --scriptmod=s/\\\\bhostserial\\\\b/hostserialpci/g',
@@ -51,9 +53,15 @@ $CFG::default_target = 'qemu';
     "ryuglab" => '--target ryu --server=pc-sojkam.felk.cvut.cz:/srv/tftp --remote-cmd="ssh -tt pc-sojkam.felk.cvut.cz \"sterm -d -s 115200 /dev/ttyUSB0\""',
     "ryulocal" => '--target ryu --dhcp-tftp --serial --reset-cmd="if which dtrrts; then dtrrts $NB_SERIAL 0 1; sleep 0.1; dtrrts $NB_SERIAL 1 1; fi"',
     );
-chomp(my $nproc = `nproc`);
-$CFG::scons = "scons -j$nproc";
-$CFG::make = "make -j$nproc";
+
+{
+    my %const;
+    $const{linux}->{_SC_NPROCESSORS_CONF} = 83;
+    my $nproc = sysconf($const{$^O}->{_SC_NPROCESSORS_CONF});
+
+    $CFG::scons = "scons -j$nproc";
+    $CFG::make = "make -j$nproc";
+}
 
 my $builddir;
 
@@ -90,6 +98,10 @@ my @cfgs;
        $dir = File::Spec->catdir(@dirs[0..$#dirs-1]);
     }
     @cfgs = reverse @cfgs;
+
+    my $xdg_config_home = $ENV{'XDG_CONFIG_HOME'} || $ENV{'HOME'}.'/.config';
+    unshift(@cfgs, "$xdg_config_home/novaboot") if -r "$xdg_config_home/novaboot";
+
     $dir = $ENV{'NOVABOOT_CONFIG_DIR'} || '/etc/novaboot.d';
     if (opendir(my $dh, $dir)) {
        my @etccfg = map { "$dir/$_" } grep { /^[-_a-zA-Z0-9]+$/ && -f "$dir/$_" } readdir($dh);
@@ -105,15 +117,22 @@ read_config($_) foreach $cfg or @cfgs;
 
 ## Command line handling
 
-my $explicit_target;
+my $explicit_target = $ENV{'NOVABOOT_TARGET'};
 GetOptions ("target|t=s" => \$explicit_target);
 
-my ($amt, @append, $bender, @chainloaders, $concat, $config_name_opt, $dhcp_tftp, $dump_opt, $dump_config, @exiton, $exiton_timeout, @expect_raw, $gen_only, $grub_config, $grub_prefix, $grub_preamble, $grub2_prolog, $grub2_config, $help, $ider, $iprelay, $iso_image, $interactive, $kernel_opt, $make, $man, $no_file_gen, $off_opt, $on_opt, $pulsar, $pulsar_root, $qemu, $qemu_append, $qemu_flags_cmd, $remote_cmd, $remote_expect, $reset, $reset_cmd, $rom_prefix, $rsync_flags, @scriptmod, $scons, $serial, $server, $stty, $tftp, $tftp_port, $uboot, %uboot_addr, @uboot_init);
+my ($amt, @append, $bender, @chainloaders, $concat, $config_name_opt, $dhcp_tftp, $dump_opt, $dump_config, @exiton, $exiton_timeout, @expect_raw, $gen_only, $grub_config, $grub_prefix, $grub_preamble, $grub2_prolog, $grub2_config, $help, $ider, $interaction, $iprelay, $iso_image, $interactive, $kernel_opt, $make, $man, $no_file_gen, $off_opt, $on_opt, $pulsar, $pulsar_root, $qemu, $qemu_append, $qemu_flags_cmd, $remote_cmd, $remote_expect, $remote_expect_silent, $reset, $reset_cmd, $rom_prefix, $rsync_flags, @scriptmod, $scons, $serial, $server, $stty, $tftp, $tftp_port, $uboot, %uboot_addr, $uboot_cmd, @uboot_init);
+
+%uboot_addr = (
+    'kernel'  => '${kernel_addr_r}',
+    'ramdisk' => '${ramdisk_addr_r}',
+    'fdt'     => '${fdt_addr_r}',
+    );
 
 $rsync_flags = '';
 $rom_prefix = 'rom://';
 $stty = 'raw -crtscts -onlcr 115200';
 $reset = 1;                    # Reset target by default
+$interaction = 1;              # Perform target interaction by default
 
 my @expect_seen = ();
 sub handle_expect
@@ -157,6 +176,7 @@ my %opt_spec;
     "grub2:s"       => \$grub2_config,
     "grub2-prolog=s" => \$grub2_prolog,
     "ider"           => \$ider,
+    "interaction!"   => \$interaction,
     "iprelay=s"             => \$iprelay,
     "iso:s"         => \$iso_image,
     "kernel|k=s"     => \$kernel_opt,
@@ -173,6 +193,7 @@ my %opt_spec;
     "qemu-flags|q=s" => \$qemu_flags_cmd,
     "remote-cmd=s"   => \$remote_cmd,
     "remote-expect=s"=> \$remote_expect,
+    "remote-expect-silent=s"=> sub { $remote_expect=$_[1]; $remote_expect_silent=1; },
     "reset!"         => \$reset,
     "reset-cmd=s"    => \$reset_cmd,
     "rsync-flags=s"  => \$rsync_flags,
@@ -187,7 +208,9 @@ my %opt_spec;
     "tftp"          => \$tftp,
     "tftp-port=i"    => \$tftp_port,
     "uboot:s"       => \$uboot,
+    "no-uboot"      => sub { undef $uboot; },
     "uboot-addr=s"   => \%uboot_addr,
+    "uboot-cmd=s"    => \$uboot_cmd,
     "uboot-init=s"   => \@uboot_init,
     "h"             => \$help,
     "help"          => \$man,
@@ -245,6 +268,16 @@ if ($ider) {
     if (!defined $amt) { die "Error: --ider requires --amt"; }
 }
 
+{
+    my %input_opts = ('--iprelay'    => \$iprelay,
+                     '--serial'     => \$serial,
+                     '--remote-cmd' => \$remote_cmd,
+                     '--amt'        => \$amt);
+    my @opts = grep(defined(${$input_opts{$_}}) , keys %input_opts);
+
+    die("novaboot: More than one target connection option: ".join(', ', @opts)) if scalar @opts > 1;
+}
+
 # Default options
 if (defined $serial) {
     $serial ||= "/dev/ttyUSB0";
@@ -381,7 +414,7 @@ sub generate_configs($$$) {
        open(my $f, '>', $fn) || die("$fn: $!");
        map { s|\brom://([^ ]*)|$rom_prefix$base$1|g; print $f "$_"; } @{$config};
        close($f);
-       print "novaboot: Created $fn\n";
+       print STDERR "novaboot: Created $fn\n";
       } elsif (exists $$g{command} && ! $no_file_gen) {
        $ENV{SRCDIR} = dirname(File::Spec->rel2abs( $filename, $invocation_dir ));
        if (exists $$g{filename}) {
@@ -513,7 +546,7 @@ sub shell_cmd_string(@)
 
 sub exec_verbose(@)
 {
-    print "novaboot: Running: ".shell_cmd_string(@_)."\n";
+    print STDERR "novaboot: Running: ".shell_cmd_string(@_)."\n";
     exec(@_);
     exit(1); # should not be reached
 }
@@ -521,19 +554,25 @@ sub exec_verbose(@)
 sub system_verbose($)
 {
     my $cmd = shift;
-    print "novaboot: Running: $cmd\n";
+    print STDERR "novaboot: Running: $cmd\n";
     my $ret = system($cmd);
     if ($ret & 0x007f) { die("Command terminated by a signal"); }
     if ($ret & 0xff00) {die("Command exit with non-zero exit code"); }
     if ($ret) { die("Command failure $ret"); }
 }
 
+sub trim($) {
+    my ($str) = @_;
+    $str =~ s/^\s+|\s+$//g;
+    return $str
+}
+
 ## WvTest headline
 
 if (exists $variables->{WVDESC}) {
-    print "Testing \"$variables->{WVDESC}\" in $last_fn:\n";
+    print STDERR "Testing \"$variables->{WVDESC}\" in $last_fn:\n";
 } elsif ($last_fn =~ /\.wv$/) {
-    print "Testing \"all\" in $last_fn:\n";
+    print STDERR "Testing \"all\" in $last_fn:\n";
 }
 
 ## Connect to the target and check whether it is not occupied
@@ -557,9 +596,9 @@ if (defined $iprelay) {
     my $paddr   = sockaddr_in($port, inet_aton($addr));
     my $proto   = getprotobyname('tcp');
     socket($IPRELAY, PF_INET, SOCK_STREAM, $proto)  || die "socket: $!";
-    print "novaboot: Connecting to IP relay... ";
+    print STDERR "novaboot: Connecting to IP relay... ";
     connect($IPRELAY, $paddr)    || die "connect: $!";
-    print "done\n";
+    print STDERR "done\n";
     $exp = Expect->init(\*$IPRELAY);
     $exp->log_stdout(1);
 
@@ -628,7 +667,7 @@ elsif ($serial) {
     $exp = Expect->init(\*$CONN);
 }
 elsif ($remote_cmd) {
-    print "novaboot: Running: $remote_cmd\n";
+    print STDERR "novaboot: Running: $remote_cmd\n";
     $exp = Expect->spawn($remote_cmd);
 }
 elsif (defined $amt) {
@@ -726,7 +765,7 @@ END
     };
 
     my $cmd = "amtterm -u $amt_user -p $amt_password $amt_host $amt_port";
-    print "novaboot: Running: $cmd\n" =~ s/\Q$amt_password\E/???/r;
+    print STDERR "novaboot: Running: $cmd\n" =~ s/\Q$amt_password\E/???/r;
     $exp = Expect->spawn($cmd);
     $exp->expect(10, "RUN_SOL") || die "Expect for 'RUN_SOL' timed out";
 
@@ -735,7 +774,15 @@ END
 
 if ($remote_expect) {
     $exp || die("No serial line connection");
+    my $log = $exp->log_stdout;
+    if (defined $remote_expect_silent) {
+       $exp->log_stdout(0);
+    }
     $exp->expect(180, $remote_expect) || die "Expect for '$remote_expect' timed out";
+    if (defined $remote_expect_silent) {
+       $exp->log_stdout($log);
+       print $exp->after() if $log;
+    }
 }
 
 if (defined $reset_cmd) {
@@ -749,7 +796,7 @@ if (defined $on_opt && defined $target_power_on) {
     exit;
 }
 if (defined $off_opt && defined $target_power_off) {
-    print "novaboot: Switching the target off...\n";
+    print STDERR "novaboot: Switching the target off...\n";
     &$target_power_off();
     exit;
 }
@@ -757,7 +804,7 @@ if (defined $off_opt && defined $target_power_off) {
 $builddir ||= dirname(File::Spec->rel2abs( ${$scripts[0]}{filename})) if scalar @scripts;
 if (defined $builddir) {
     chdir($builddir) or die "Can't change directory to $builddir: $!";
-    print "novaboot: Entering directory `$builddir'\n";
+    print STDERR "novaboot: Entering directory `$builddir'\n";
 } else {
     $builddir = $invocation_dir;
 }
@@ -779,7 +826,7 @@ foreach my $script (@scripts) {
     if (exists $variables->{BUILDDIR}) {
        $builddir = File::Spec->rel2abs($variables->{BUILDDIR});
        chdir($builddir) or die "Can't change directory to $builddir: $!";
-       print "novaboot: Entering directory `$builddir'\n";
+       print STDERR "novaboot: Entering directory `$builddir'\n";
     }
 
     if ($grub_prefix) {
@@ -879,13 +926,7 @@ if (scalar(@scripts) > 1 && ( defined $dhcp_tftp || defined $serial || defined $
 }
 
 if ($variables->{WVTEST_TIMEOUT}) {
-    print "wvtest: timeout ", $variables->{WVTEST_TIMEOUT}, "\n";
-}
-
-sub trim($) {
-    my ($str) = @_;
-    $str =~ s/^\s+|\s+$//g;
-    return $str
+    print STDERR "wvtest: timeout ", $variables->{WVTEST_TIMEOUT}, "\n";
 }
 
 ### Start in Qemu
@@ -924,7 +965,7 @@ if (defined $qemu) {
     }
     push(@qemu_flags,  qw(-serial stdio)); # Redirect serial output (for collecting test restuls)
     unshift(@qemu_flags, ('-name', $config_name));
-    print "novaboot: Running: ".shell_cmd_string($qemu, @qemu_flags)."\n";
+    print STDERR "novaboot: Running: ".shell_cmd_string($qemu, @qemu_flags)."\n";
     $exp = Expect->spawn(($qemu, @qemu_flags)) || die("exec() failed: $!");
 }
 
@@ -980,7 +1021,7 @@ if (defined $dhcp_tftp || defined $tftp) {
 ### AMT IDE-R
 if (defined $ider) {
     my $ider_cmd= "amtider -c $iso_image -u $amt_user -p $amt_password $amt_host $amt_port"  ;
-    print "novaboot: Running: $ider_cmd\n" =~ s/\Q$amt_password\E/???/r;
+    print STDERR "novaboot: Running: $ider_cmd\n" =~ s/\Q$amt_password\E/???/r;
     my $ider_pid = fork();
     if ($ider_pid == 0) {
        exec($ider_cmd);
@@ -994,15 +1035,29 @@ if (defined $ider) {
 ### Reset target (IP relay, AMT, ...)
 
 if (defined $target_reset && $reset) {
-    print "novaboot: Reseting the test box... ";
+    print STDERR "novaboot: Reseting the test box... ";
     &$target_reset();
-    print "done\n";
+    print STDERR "done\n";
+    if (defined $exp) {
+       # We don't want to output anything printed by the target
+       # before reset so we clear the buffers now. This is, however,
+       # not ideal because we may loose some data that were sent
+       # after the reset. If this is a problem, one should reset and
+       # connect to serial line in atomic manner. For example, if
+       # supported by hardware, use --remote-cmd 'sterm -d ...' and
+       # do not use separate --reset-cmd.
+       my $log = $exp->log_stdout;
+       $exp->log_stdout(0);
+       $exp->expect(0); # Read data from target
+       $exp->clear_accum();    # Clear the read data
+       $exp->log_stdout($log);
+    }
 }
 
 ### U-boot conversation
 if (defined $uboot) {
     my $uboot_prompt = $uboot || '=> ';
-    print "novaboot: Waiting for U-Boot prompt...\n";
+    print STDERR "novaboot: Waiting for U-Boot prompt...\n";
     $exp || die("No serial line connection");
     $exp->log_stdout(1);
     #$exp->exp_internal(1);
@@ -1034,17 +1089,20 @@ if (defined $uboot) {
     }
 
     # Boot the system if there are some load lines in the script
-    if (scalar(@$modules) > 0 && !$variables->{NO_BOOT}) {
+    if ((scalar(@$modules) > 0 && !$variables->{NO_BOOT}) ||
+       defined $uboot_cmd) {
        my ($kbin, $kcmd) = split(' ', shift(@$modules), 2);
        my $dtb;
        @$modules = map { if (/\.dtb$/) { $dtb=$_; (); } else { $_ } } @$modules;
        my $initrd = shift @$modules;
 
-       die "No '--uboot-addr kernel' given" unless $uboot_addr{kernel};
-       $exp->send("tftpboot $uboot_addr{kernel} $prefix$kbin\n");
-       $exp->expect(10,
-                    [qr/##/, sub { exp_continue; }],
-                    $uboot_prompt) || die "Kernel load timeout";
+       if (defined $kbin) {
+           die "No '--uboot-addr kernel' given" unless $uboot_addr{kernel};
+           $exp->send("tftpboot $uboot_addr{kernel} $prefix$kbin\n");
+           $exp->expect(10,
+                        [qr/##/, sub { exp_continue; }],
+                        $uboot_prompt) || die "Kernel load timeout";
+       }
        if (defined $dtb) {
            die "No '--uboot-addr fdt' given" unless $uboot_addr{fdt};
            $exp->send("tftpboot $uboot_addr{fdt} $prefix$dtb\n");
@@ -1056,53 +1114,51 @@ if (defined $uboot) {
            die "No '--uboot-addr ramdisk' given" unless $uboot_addr{ramdisk};
            $exp->send("tftpboot $uboot_addr{ramdisk} $prefix$initrd\n");
            $exp->expect(10,
-                        [qr/#/, sub { exp_continue; }],
+                        [qr/##/, sub { exp_continue; }],
                         $uboot_prompt) || die "Initrd load timeout";
        } else {
            $uboot_addr{ramdisk} = '-';
        }
-       $exp->send("echo $kcmd\n");
-       $exp->expect(1, '-re', qr{echo .*\n(.*)\n$uboot_prompt})  || die "Command line test timeout";
-       my $args = ($exp->matchlist)[0];
-       if ($args =~ /^setenv\s+bootargs/) {
-           $exp->send("$args\n");
-       } else {
-           $exp->send("setenv bootargs $kcmd\n");
-       }
+
+       $kcmd //= '';
+       $exp->send("setenv bootargs $kcmd\n");
        $exp->expect(5, $uboot_prompt)  || die "U-Boot prompt timeout";
-       $exp->send("bootm $uboot_addr{kernel} $uboot_addr{ramdisk} $uboot_addr{fdt}\n");
+
+       $uboot_cmd //= $variables->{UBOOT_CMD} // 'bootm $kernel_addr $ramdisk_addr $fdt_addr';
+       $uboot_cmd =~ s/\$kernel_addr/$uboot_addr{kernel}/g;
+       $uboot_cmd =~ s/\$ramdisk_addr/$uboot_addr{ramdisk}/g;
+       $uboot_cmd =~ s/\$fdt_addr/$uboot_addr{fdt}/g;
+
+       $exp->send($uboot_cmd . "\n");
        $exp->expect(5, "\n")  || die "U-Boot command timeout";
     }
 }
 
 ### Serial line interaction
-if (defined $exp) {
+if ($interaction && defined $exp) {
     # Serial line of the target is available
     my $interrupt = 'Ctrl-C';
     if ($interactive && !@exiton) {
        $interrupt = '"~~."';
     }
-    my $note = (-t STDIN) ? '' : '- only target->host ';
-    print "novaboot: Serial line interaction $note(press $interrupt to interrupt)...\n";
+    print STDERR "novaboot: Serial line interaction (press $interrupt to interrupt)...\n";
     $exp->log_stdout(1);
     if (@exiton) {
        $exp->expect($exiton_timeout, @expect_raw, @exiton) || die("exiton timeout");
     } else {
        my @inputs = ($exp);
-       if (-t STDIN) { # Set up bi-directional communication if we run on terminal
-           my $infile = new IO::File;
-           $infile->IO::File::fdopen(*STDIN,'r');
-           my $in_object = Expect->exp_init($infile);
-           $in_object->set_group($exp);
-
-           if ($interactive) {
-               $in_object->set_seq('~~\.', sub { print "novaboot: Escape sequence detected\r\n"; undef; });
-               $in_object->manual_stty(0);       # Use raw terminal mode
-           } else {
-               $in_object->manual_stty(1);       # Do not modify terminal settings
-           }
-           push(@inputs, $in_object);
+       my $infile = new IO::File;
+       $infile->IO::File::fdopen(*STDIN,'r');
+       my $in_object = Expect->exp_init($infile);
+       $in_object->set_group($exp);
+
+       if ($interactive) {
+           $in_object->set_seq('~~\.', sub { print STDERR "novaboot: Escape sequence detected\r\n"; undef; });
+           $in_object->manual_stty(0);   # Use raw terminal mode
+       } else {
+           $in_object->manual_stty(1);   # Do not modify terminal settings
        }
+       push(@inputs, $in_object);
        #use Data::Dumper;
        #print Dumper(\@expect_raw);
        $exp->expect(undef, @expect_raw) if @expect_raw;
@@ -1115,6 +1171,9 @@ if (defined $dhcp_tftp || defined $tftp) {
     die("novaboot: This should kill servers on background\n");
 }
 
+# Always finish novaboot output with newline
+print "\n";
+
 ## Documentation
 
 =head1 NAME
@@ -1154,7 +1213,7 @@ only the B<-t>/B<--target> command line option to select the target.
 Internally, this option expands to the pre-configured options.
 Configuration files are searched at multiple places, which allows to
 have per-system, per-user or per-project configurations. Configuration
-file syntax is described in section L</"CONFIGURATION FILE">.
+file syntax is described in section L</"CONFIGURATION FILES">.
 
 Simple examples of using C<novaboot>:
 
@@ -1162,10 +1221,10 @@ Simple examples of using C<novaboot>:
 
 =item 1.
 
-Run an OS in Qemu. This is the default action when no other action is
-specified by command line switches. Thus running C<novaboot myos> (or
-C<./myos> as described above) will run Qemu and make it boot the
-configuration specified in the F<myos> script.
+Run an OS in Qemu. This is can be specified with the B<--qemu> option.
+Thus running C<novaboot --qemu myos> (or C<./myos --qemu> as described
+above) will run Qemu and make it boot the configuration specified in
+the F<myos> script.
 
 =item 2.
 
@@ -1203,31 +1262,65 @@ I<script2> configurations.
 
 Novaboot performs its work in several phases. Each phase can be
 influenced by several command line options, certain phases can be
-skipped. The list of phases (in the execution order) and the
-corresponding options follows.
+skipped. The list of phases (in the execution order) is as follows.
+
+=over
+
+=item 1. L<Configuration reading|/Configuration reading phase>
+
+=item 2. L<Command line processing|/Command line processing phase>
+
+=item 3. L<Script preprocessing|/Script preprocessing phase>
+
+=item 4. L<File generation|/File generation phase>
+
+=item 5. L<Target connection|/Target connection check>
+
+=item 6. L<File deployment|/File deployment phase>
+
+=item 7. L<Target power-on and reset|/Target power-on and reset phase>
+
+=item 8. L<Interaction with the bootloader|/Interaction with the bootloader on the target>
+
+=item 9. L<Target interaction|/Target interaction phase>
+
+=back
+
+Each phase is described in the following sections together with the
+command line options that control it.
 
 =head2 Configuration reading phase
 
 After starting, novaboot reads configuration files. Their content is
-described in section L</"CONFIGURATION FILE">. By default,
-configuration is read from two locations. First from the configuration
-directory and second from F<.novaboot> files along the path to the
-current directory. The latter read files override settings from the
-former ones.
-
-Configuration directory is determined by the content of
+described in section L</"CONFIGURATION FILES">. By default,
+configuration is read from multiple locations. First from the system
+configuration directory (F</etc/novaboot.d/>), second from the user
+configuration file (F<~/.config/novaboot>) and third from F<.novaboot>
+files along the path to the current directory. Alternatively, a single
+configuration file specified with the B<-c> switch or with the
+C<NOVABOOT_CONFIG> environment variable is read. The latter read files
+override settings from the former ones.
+
+The system configuration directory is determined by the content of
 NOVABOOT_CONFIG_DIR environment variable and defaults to
 F</etc/novaboot.d>. Files in this directory with names consisting
 solely of English letters, numbers, dashes '-' and underscores '_'
 (note that dot '.' is not included) are read in alphabetical order.
 
-Then novaboot searches for files named F<.novaboot> starting from the
+Then, the user configuration file is read from
+F<$XDG_CONFIG_HOME/novaboot>. If C<$XDG_CONFIG_HOME> environemnt
+variable is not set F<~/.config/novaboot> is read instead.
+
+Finally, novaboot searches for files named F<.novaboot> starting from the
 directory of the novaboot script (or working directory, see bellow)
 and continuing upwards up to the root directory. The found
 configuration files are then read in the opposite order (i.e. from the
-root directory downwards). This allows to have, for example, user
-specific configuration in F<~/.novaboot> and project specific one in
-F<~/project/.novaboot>.
+root directory downwards). This allows to have, for example, a project
+specific configuration in F<~/project/.novaboot>.
+
+Note the difference between F<~/.config/novaboot> and F<~/.novaboot>.
+The former one is read always, whereas the latter only when novaboot
+script or working directory is under the C<$HOME> directory.
 
 In certain cases, the location of the novaboot script cannot be
 determined in this early phase. This happens either when the script is
@@ -1260,9 +1353,13 @@ Print short (B<-h>) or long (B<--help>) help.
 =item -t, --target=I<target>
 
 This option serves as a user configurable shortcut for other novaboot
-options. The effect of this option is the same as the options stored
-in the C<%targets> configuration variable under key I<target>. See
-also L</"CONFIGURATION FILE">.
+options. The effect of this option is the same as specifying the
+options stored in the C<%targets> configuration variable under key
+I<target>. See also L</"CONFIGURATION FILES">.
+
+When this option is not given, novaboot tries to determine the target
+to use from either B<NOVABOOT_TARGET> environment variable or from
+B<$default_target> configuration file variable.
 
 =back
 
@@ -1470,9 +1567,15 @@ example C<ssh server 'cu -l /dev/ttyS0'>.
 
 =item --remote-expect=I<string>
 
-Wait for reception of I<string> after establishing the the remote
-connection before continuing.
+Wait for reception of I<string> after establishing the remote
+connection.
 
+=item --remote-expect-silent=I<string>
+
+The same as B<--remote-expect> except that the remote output is not
+echoed to stdout while waiting for the I<string>. Everything after the
+matched string is printed to stdout, so you may want to include line
+end characters in the I<string> as well.
 
 =back
 
@@ -1587,7 +1690,7 @@ Command that resets the target.
 
 =item --no-reset, --reset
 
-Disable/enable reseting of the target.
+Disable/enable resetting of the target.
 
 =back
 
@@ -1603,6 +1706,10 @@ novaboot script. I<prompt> specifies the U-Boot's prompt (default is
 Implementation of this option is currently tied to a particular board
 that we use. It may be subject to changes in the future!
 
+=item --no-uboot
+
+Disable U-Boot interaction previously enabled with B<--uboot>.
+
 =item --uboot-init
 
 Command(s) to send the U-Boot bootloader before loading the images and
@@ -1621,6 +1728,21 @@ Load address of U-Boot's C<tftpboot> command for loading I<name>,
 where name is one of I<kernel>, I<ramdisk> or I<fdt> (flattened device
 tree).
 
+The default addresses are ${I<name>_addr_r}, i.e. U-Boot environment
+variables used by convention for this purpose.
+
+=item --uboot-cmd=I<command>
+
+Specifies U-Boot command used to execute the OS. If the command
+contains strings C<$kernel_addr>, C<$ramdisk_addr>, C<$fdt_addr>,
+these are replaced with the addresses configured with B<--uboot-addr>.
+
+The default value is
+
+    bootm $kernel_addr $ramdisk_addr $fdt_addr
+
+or the C<UBOOT_CMD> variable if defined in the novaboot script.
+
 =back
 
 =head2 Target interaction phase
@@ -1661,6 +1783,11 @@ special characters). This, among others, means that Ctrl-C is passed
 to the target and does no longer interrupt novaboot. Use "~~."
 sequence to exit novaboot.
 
+=item --no-interaction, --interaction
+
+Skip resp. force target interaction phase. When skipped, novaboot exits
+immediately when boot is initiated.
+
 =item --expect=I<string>
 
 When I<string> is received from the target, send the string specified
@@ -1811,6 +1938,10 @@ QEMU_FLAGS.
 
 Use specific qemu flags (can be overridden with B<-q>).
 
+=item UBOOT_CMD
+
+See L</--uboot-cmd>.
+
 =item WVDESC
 
 Description of the WvTest-compliant program.
@@ -1824,18 +1955,19 @@ intermediate output.
 
 =back
 
-=head1 CONFIGURATION FILE
+=head1 CONFIGURATION FILES
 
 Novaboot can read its configuration from one or more files. By
-default, novaboot looks for files in F</etc/novaboot.d> and files
-named F<.novaboot> as described in L</Configuration reading phase>.
-Alternatively, configuration file location can be specified with the
-B<-c> switch or with the NOVABOOT_CONFIG environment variable. The
-configuration file has Perl syntax (i.e. it is better to put C<1;> as
-a last line) and should set values of certain Perl variables. The
-current configuration can be dumped with the B<--dump-config> switch.
-Some configuration variables can be overridden by environment
-variables (see below) or by command line switches.
+default, novaboot looks for files in F</etc/novaboot.d>, file
+F<~/.config/novaboot> and files named F<.novaboot> as described in
+L</Configuration reading phase>. Alternatively, configuration file
+location can be specified with the B<-c> switch or with the
+NOVABOOT_CONFIG environment variable. The configuration file has Perl
+syntax (i.e. it is better to put C<1;> as the last line) and should set
+values of certain Perl variables. The current configuration can be
+dumped with the B<--dump-config> switch. Some configuration variables
+can be overridden by environment variables (see below) or by command
+line switches.
 
 Supported configuration variables include:
 
@@ -1849,7 +1981,8 @@ file.
 =item $default_target
 
 Default target (see below) to use when no target is explicitly
-specified on command line with the B<--target> option.
+specified with the B<--target> command line option or
+B<NOVABOOT_TARGET> environment variable.
 
 =item %targets
 
@@ -1885,6 +2018,12 @@ one(s).
 Name of the novaboot configuration directory. When not specified
 F</etc/novaboot.d> is used.
 
+=item NOVABOOT_TARGET
+
+Name of the novaboot target to use. This overrides the value of
+B<$default_target> from the configuration file and can be overriden
+with the B<--target> command line option.
+
 =item NOVABOOT_BENDER
 
 Defining this variable has the same meaning as B<--bender> option.