]> rtime.felk.cvut.cz Git - novaboot.git/blobdiff - novaboot
README: Fix link
[novaboot.git] / novaboot
index 34da72f4ae1f93e00e108c081ca693392e272c4a..44d4a310daf7cb882f1eb06830ca511651ebf248 100755 (executable)
--- a/novaboot
+++ b/novaboot
@@ -1,4 +1,4 @@
-#!/usr/bin/perl -w
+#!/usr/bin/env perl
 
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -52,13 +52,14 @@ $CFG::hypervisor_params = "serial";
 $CFG::genisoimage = "genisoimage";
 $CFG::qemu = 'qemu-system-i386 -cpu coreduo -smp 2';
 $CFG::default_target = '';
 $CFG::genisoimage = "genisoimage";
 $CFG::qemu = 'qemu-system-i386 -cpu coreduo -smp 2';
 $CFG::default_target = '';
+$CFG::netif = 'eth0';
 %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',
     "novabox" => '--ssh=novabox@rtime.felk.cvut.cz',
     "localhost" => '--scriptmod=s/console=tty[A-Z0-9,]+// --server=/boot/novaboot/$NAME --grub2 --grub-prefix=/boot/novaboot/$NAME --grub2-prolog="  set root=\'(hd0,msdos1)\'"',
     "ryu" =>  '--uboot --uboot-init="mw f0000b00 \${psc_cfg}; sleep 1" --uboot-addr kernel=800000 --uboot-addr ramdisk=b00000 --uboot-addr fdt=7f0000',
 %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',
     "novabox" => '--ssh=novabox@rtime.felk.cvut.cz',
     "localhost" => '--scriptmod=s/console=tty[A-Z0-9,]+// --server=/boot/novaboot/$NAME --grub2 --grub-prefix=/boot/novaboot/$NAME --grub2-prolog="  set root=\'(hd0,msdos1)\'"',
     "ryu" =>  '--uboot --uboot-init="mw f0000b00 \${psc_cfg}; sleep 1" --uboot-addr kernel=800000 --uboot-addr ramdisk=b00000 --uboot-addr fdt=7f0000',
-    "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\""',
+    "ryuglab" => '--target ryu --ssh=ryu@pc-sojkam.felk.cvut.cz',
     "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"',
     );
 
     "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"',
     );
 
@@ -129,7 +130,7 @@ my $explicit_target = $ENV{'NOVABOOT_TARGET'};
 GetOptions ("target|t=s" => \$explicit_target);
 
 # Variables for command line options
 GetOptions ("target|t=s" => \$explicit_target);
 
 # Variables for command line options
-my ($amt, @append, $bender, @chainloaders, $concat, $config_name_opt, $dhcp_tftp, $dump_opt, $dump_config, @exiton, $exiton_timeout, @expect_raw, $final_eol, $gen_only, $grub_config, $grub_prefix, $grub_preamble, $grub2_prolog, $grub2_config, $help, $ider, $interaction, $iprelay, $iprelay_cmd, $iso_image, $interactive, $kernel_opt, $make, $man, $netif, $no_file_gen, $off_opt, $on_opt, $pulsar, $pulsar_root, $qemu, $qemu_append, $qemu_flags_cmd, @remote_cmd, $remote_expect, $remote_expect_silent, $remote_expect_timeout, $reset, @reset_cmd, $reset_send, $rom_prefix, $rsync_flags, @scriptmod, $scons, $serial, $server, $stty, $tftp, $tftp_port, $uboot, %uboot_addr, $uboot_cmd, @uboot_init);
+my ($amt, @append, $bender, @chainloaders, $concat, $config_name_opt, $dhcp_tftp, $dump_opt, $dump_config, @exiton, $exiton_timeout, @expect_raw, $final_eol, $gen_only, $grub_config, $grub_prefix, $grub_preamble, $grub2_prolog, $grub2_config, $help, $ider, $interaction, $iprelay, $iprelay_cmd, $iso_image, $interactive, $kernel_opt, $make, $man, $netif, $no_file_gen, $off_opt, $on_opt, $pulsar, $pulsar_root, $qemu, $qemu_append, $qemu_flags_cmd, @remote_cmd, $remote_expect, $remote_expect_silent, $remote_expect_timeout, $reset, @reset_cmd, $reset_send, $rom_prefix, $rsync_flags, @scriptmod, $scons, $serial, $server, $stty, $tftp, $tftp_port, $uboot, %uboot_addr, $uboot_cmd, @uboot_init, $uboot_stop_key);
 
 my ($target_reset, $target_power_on, $target_power_off);
 
 
 my ($target_reset, $target_power_on, $target_power_off);
 
@@ -141,12 +142,12 @@ my ($target_reset, $target_power_on, $target_power_off);
     );
 $rsync_flags = '';
 $rom_prefix = 'rom://';
     );
 $rsync_flags = '';
 $rom_prefix = 'rom://';
-$stty = 'raw -crtscts -onlcr 115200';
+$stty = 'raw -crtscts -onlcr -echo 115200';
 $reset = 1;                    # Reset target by default
 $interaction = 1;              # Perform target interaction by default
 $final_eol = 1;
 $reset = 1;                    # Reset target by default
 $interaction = 1;              # Perform target interaction by default
 $final_eol = 1;
-$netif = 'eth0';
-$remote_expect_timeout = 180;
+$netif = $CFG::netif;
+$remote_expect_timeout = -1;
 
 my @expect_seen = ();
 sub handle_expect
 
 my @expect_seen = ();
 sub handle_expect
@@ -176,8 +177,12 @@ my %opt_spec_safe = (
     "prefix|grub-prefix=s" => \$grub_prefix,
     "pulsar-root=s"  => \$pulsar_root,
     "pulsar|p:s"     => \$pulsar,
     "prefix|grub-prefix=s" => \$grub_prefix,
     "pulsar-root=s"  => \$pulsar_root,
     "pulsar|p:s"     => \$pulsar,
+    "remote-expect=s"=> \$remote_expect,
+    "remote-expect-silent=s"=> sub { $remote_expect=$_[1]; $remote_expect_silent=1; },
+    "remote-expect-timeout=i"=> \$remote_expect_timeout,
     "uboot-addr=s"   => \%uboot_addr,
     "uboot-cmd=s"    => \$uboot_cmd,
     "uboot-addr=s"   => \%uboot_addr,
     "uboot-cmd=s"    => \$uboot_cmd,
+    "uboot-stop-key=s" => \$uboot_stop_key,
     "uboot-init=s"   => sub { push @uboot_init, { command => $_[1] }; },
     "uboot:s"       => \$uboot,
     );
     "uboot-init=s"   => sub { push @uboot_init, { command => $_[1] }; },
     "uboot:s"       => \$uboot,
     );
@@ -218,9 +223,6 @@ my %opt_spec = (
     "qemu-append=s"  => \$qemu_append,
     "qemu-flags|q=s" => \$qemu_flags_cmd,
     "remote-cmd=s"   => sub { @remote_cmd = ($_[1]); },
     "qemu-append=s"  => \$qemu_append,
     "qemu-flags|q=s" => \$qemu_flags_cmd,
     "remote-cmd=s"   => sub { @remote_cmd = ($_[1]); },
-    "remote-expect=s"=> \$remote_expect,
-    "remote-expect-silent=s"=> sub { $remote_expect=$_[1]; $remote_expect_silent=1; },
-    "remote-expect-timeout=i"=> \$remote_expect_timeout,
     "reset!"         => \$reset,
     "reset-cmd=s"    => sub { @reset_cmd = ($_[1]); },
     "reset-send=s"   => \$reset_send,
     "reset!"         => \$reset,
     "reset-cmd=s"    => sub { @reset_cmd = ($_[1]); },
     "reset-send=s"   => \$reset_send,
@@ -994,7 +996,7 @@ foreach my $script (@scripts) {
            $hostname = "";
        }
        my $files = join(" ", map({ ($file) = m/([^ ]*)/; $file; } ( @$modules, @bootloader_configs, @$copy)));
            $hostname = "";
        }
        my $files = join(" ", map({ ($file) = m/([^ ]*)/; $file; } ( @$modules, @bootloader_configs, @$copy)));
-       map({ my $file = (split)[0]; die "$file: $!" if ! -f $file; } @$modules);
+       map({ my $file = (split)[0]; die "Not a file: $file: $!" if ! -e $file || -d $file; } @$modules);
        my $istty = -t STDOUT && ($ENV{'TERM'} || 'dumb') ne 'dumb';
        my $progress = $istty ? "--progress" : "";
        if ($files) {
        my $istty = -t STDOUT && ($ENV{'TERM'} || 'dumb') ne 'dumb';
        my $progress = $istty ? "--progress" : "";
        if ($files) {
@@ -1024,11 +1026,17 @@ if (defined $iso_image) {
     if (-f '/usr/lib/ISOLINUX/isolinux.bin') {
        # Newer ISOLINUX version
        @files = qw(/usr/lib/ISOLINUX/isolinux.bin /usr/lib/syslinux/modules/bios/mboot.c32 /usr/lib/syslinux/modules/bios/libcom32.c32 /usr/lib/syslinux/modules/bios/menu.c32 /usr/lib/syslinux/modules/bios/ldlinux.c32);
     if (-f '/usr/lib/ISOLINUX/isolinux.bin') {
        # Newer ISOLINUX version
        @files = qw(/usr/lib/ISOLINUX/isolinux.bin /usr/lib/syslinux/modules/bios/mboot.c32 /usr/lib/syslinux/modules/bios/libcom32.c32 /usr/lib/syslinux/modules/bios/menu.c32 /usr/lib/syslinux/modules/bios/ldlinux.c32);
-    } else {
+    } elsif (-f '/usr/lib/syslinux/isolinux.bin') {
        # Older ISOLINUX version
        @files = qw(/usr/lib/syslinux/isolinux.bin /usr/lib/syslinux/mboot.c32 /usr/lib/syslinux/menu.c32);
        # Older ISOLINUX version
        @files = qw(/usr/lib/syslinux/isolinux.bin /usr/lib/syslinux/mboot.c32 /usr/lib/syslinux/menu.c32);
+    } else {
+       # NixOS and maybe others
+       my $syslinux = `which syslinux` || die "Cannot find syslinux";
+       chomp $syslinux;
+       $syslinux =~ s,/bin/syslinux$,,;
+       @files = ("$syslinux/share/syslinux/isolinux.bin", "$syslinux/share/syslinux/mboot.c32", "$syslinux/share/syslinux/libcom32.c32", "$syslinux/share/syslinux/menu.c32", "$syslinux/share/syslinux/ldlinux.c32");
     }
     }
-    system_verbose("cp @files isolinux");
+    system_verbose("cp @files isolinux && chmod +w isolinux/*");
     open(my $fh, ">isolinux/isolinux.cfg");
     if ($#scripts) {
        print $fh "TIMEOUT 50\n";
     open(my $fh, ">isolinux/isolinux.cfg");
     if ($#scripts) {
        print $fh "TIMEOUT 50\n";
@@ -1170,7 +1178,7 @@ if (defined $ider) {
 ### Reset target (IP relay, AMT, ...)
 
 if (defined $target_reset && $reset) {
 ### Reset target (IP relay, AMT, ...)
 
 if (defined $target_reset && $reset) {
-    print STDERR "novaboot: Reseting the test box... ";
+    print STDERR "novaboot: Resetting the test box... ";
     &$target_reset();
     print STDERR "done\n";
     if (defined $exp) {
     &$target_reset();
     print STDERR "done\n";
     if (defined $exp) {
@@ -1197,7 +1205,9 @@ if (defined $uboot) {
     $exp->log_stdout(1);
     #$exp->exp_internal(1);
     $exp->expect(20,
     $exp->log_stdout(1);
     #$exp->exp_internal(1);
     $exp->expect(20,
-                [qr/Hit any key to stop autoboot:/, sub { $exp->send("\n"); exp_continue; }],
+                [qr/Hit any key to stop autoboot:/, sub {
+                    $exp->send($uboot_stop_key // "\n");
+                    exp_continue; }],
                 $uboot_prompt) || die "No U-Boot prompt deteceted";
     foreach my $cmdspec (@uboot_init) {
        my ($cmd, $timeout);
                 $uboot_prompt) || die "No U-Boot prompt deteceted";
     foreach my $cmdspec (@uboot_init) {
        my ($cmd, $timeout);
@@ -1243,17 +1253,17 @@ if (defined $uboot) {
        @$modules = map { if (/\.dtb$/) { $dtb=$_; (); } else { $_ } } @$modules;
        my $initrd = shift @$modules;
 
        @$modules = map { if (/\.dtb$/) { $dtb=$_; (); } else { $_ } } @$modules;
        my $initrd = shift @$modules;
 
-       if (defined $kbin) {
+       if (defined $kbin && $kbin ne '/dev/null') {
            die "No '--uboot-addr kernel' given" unless $uboot_addr{kernel};
            $exp->send("tftpboot $uboot_addr{kernel} $prefix$kbin\n");
            die "No '--uboot-addr kernel' given" unless $uboot_addr{kernel};
            $exp->send("tftpboot $uboot_addr{kernel} $prefix$kbin\n");
-           $exp->expect(10,
+           $exp->expect(15,
                         [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");
                         [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");
-           $exp->expect(10,
+           $exp->expect(15,
                         [qr/##/, sub { exp_continue; }],
                         $uboot_prompt) || die "Device tree load: " . ($! || "timeout");
        } else  {
                         [qr/##/, sub { exp_continue; }],
                         $uboot_prompt) || die "Device tree load: " . ($! || "timeout");
        } else  {
@@ -1262,7 +1272,7 @@ if (defined $uboot) {
        if (defined $initrd) {
            die "No '--uboot-addr ramdisk' given" unless $uboot_addr{ramdisk};
            $exp->send("tftpboot $uboot_addr{ramdisk} $prefix$initrd\n");
        if (defined $initrd) {
            die "No '--uboot-addr ramdisk' given" unless $uboot_addr{ramdisk};
            $exp->send("tftpboot $uboot_addr{ramdisk} $prefix$initrd\n");
-           $exp->expect(10,
+           $exp->expect(15,
                         [qr/##/, sub { exp_continue; }],
                         $uboot_prompt) || die "Initrd load: " . ($! || "timeout");
        } else {
                         [qr/##/, sub { exp_continue; }],
                         $uboot_prompt) || die "Initrd load: " . ($! || "timeout");
        } else {
@@ -1295,7 +1305,7 @@ if ($interaction && defined $exp) {
     print STDERR "novaboot: Serial line interaction (press $interrupt to interrupt)...\n";
     $exp->log_stdout(1);
     if (@exiton) {
     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"));
+       $exp->expect($exiton_timeout, @exiton, @expect_raw) || die("exiton: " . ($! || "timeout"));
     } else {
        my @inputs = ($exp);
        my $infile = new IO::File;
     } else {
        my @inputs = ($exp);
        my $infile = new IO::File;
@@ -1335,6 +1345,7 @@ print "\n" if $final_eol;
 ## Documentation
 
 =encoding utf8
 ## Documentation
 
 =encoding utf8
+
 =head1 NAME
 
 novaboot - Boots a locally compiled operating system on a remote
 =head1 NAME
 
 novaboot - Boots a locally compiled operating system on a remote
@@ -1375,46 +1386,102 @@ having per-system, per-user or per-project configurations.
 Configuration file syntax is described in section L</"CONFIGURATION
 FILES">.
 
 Configuration file syntax is described in section L</"CONFIGURATION
 FILES">.
 
-Simple examples of using C<novaboot>:
+Novaboot newcomers may be confused by a large number of configuration
+options. Understanding all these options is not always needed,
+depending on the used setup. The L<figure from the doc directory
+|https://github.com/wentasah/novaboot/blob/master/doc/typical-setups.svg>
+shows different setups that vary in how much effort is needed
+configure novaboot for them. The setups are:
+
+=over 3
+
+=item A: Laptop and target device only
+
+This requires to configure everything on the laptop side, including a
+serial line connection (L</--serial>, L</--remote-cmd>, ...), power
+on/off/reset commands (L</--reset-cmd>, ...), TFTP server
+(L</--server>, L</--prefix>...), device IP addresses, etc.
+
+=item B: Laptop, target device and external TFTP server
+
+Like the previous setup, but the TFTP (and maybe DHCP) configuration
+is handled by a server. Novaboot users need to understand where to
+copy their files to the TFTP server (L</--server>) and which IP
+addresses their target will get, but do not need to configure the
+servers themselves.
+
+=item C: Novaboot server running novaboot-shell
+
+With this setup, the configuration is done on the server. Users only
+need to know the SSH account (L</--ssh>) used to communicate between
+novaboot and novaboot server. The server is implemented as a
+restricted shell (L<novaboot-shell(1)>) on the server. No need to give
+full shell access to novaboot users on the server.
+
+=back
+
+=head2 Simple examples of using C<novaboot>:
+
+To boot Linux (files F<bzImage> and F<rootfs.cpio> in current
+directory), create F<mylinux> file with this content:
+
+    #!/usr/bin/env novaboot
+    load bzImage console=ttyS0,115200
+    load rootfs.cpio
 
 =over 3
 
 =item 1.
 
 
 =over 3
 
 =item 1.
 
-Running an OS in Qemu can be accomplished by giving the B<--qemu> option.
+Booting an OS in Qemu can be accomplished by giving the B<--qemu> option.
 Thus running
 
 Thus running
 
- novaboot --qemu myos
+ novaboot --qemu mylinux
 
 
-(or C<./myos --qemu> as described above) will run Qemu and make it
-boot the configuration specified in the F<myos> script.
+(or C<./mylinux --qemu> as described above) will run Qemu and make it
+boot the configuration specified in the F<mylinux> script. How is qemu
+started can be configured in various ways (see below).
 
 =item 2.
 
 Create a bootloader configuration file (currently supported
 bootloaders are GRUB, GRUB2, ISOLINUX, Pulsar, and U-Boot) and copy it
 
 =item 2.
 
 Create a bootloader configuration file (currently supported
 bootloaders are GRUB, GRUB2, ISOLINUX, Pulsar, and U-Boot) and copy it
-with all other files needed for booting to a remote boot server. Then
+with all other files needed for booting to a remote TFTP server. Then
 use a TCP/IP-controlled relay/serial-to-TCP converter to reset the
 target and receive its serial output.
 
 use a TCP/IP-controlled relay/serial-to-TCP converter to reset the
 target and receive its serial output.
 
- ./myos --grub2 --server=192.168.1.1:/tftp --iprelay=192.168.1.2
+ ./mylinux --grub2 --server=192.168.1.1:/tftp --iprelay=192.168.1.2
 
 Alternatively, you can put these switches to the configuration file
 and run:
 
 
 Alternatively, you can put these switches to the configuration file
 and run:
 
- ./myos --target mytarget
+ ./mylinux --target mytarget
 
 =item 3.
 
 
 =item 3.
 
+Specifying all the options needed by novaboot to successfully control
+the target, either on command line or in configuration files, can be
+difficult for users. Novaboot supports configuring the target
+centrally via L<novaboot-shell(1)> on a server. With such a
+configuration, users only need to use the B<--ssh> option to specify
+where to boot their OS:
+
+ ./mylinux --ssh myboard@example.com
+
+Typically, the server is the computer connected to and controlling the
+target board and running the TFTP server.
+
+=item 4.
+
 Run DHCP and TFTP server on developer's machine to boot the target
 from it.
 
 Run DHCP and TFTP server on developer's machine to boot the target
 from it.
 
- ./myos --dhcp-tftp
+ ./mylinux --dhcp-tftp
 
 This usage is useful when no network infrastructure is in place, and
 the target is connected directly to developer's box.
 
 
 This usage is useful when no network infrastructure is in place, and
 the target is connected directly to developer's box.
 
-=item 4.
+=item 5.
 
 Create bootable ISO image.
 
 
 Create bootable ISO image.
 
@@ -1426,9 +1493,9 @@ I<script2> configurations.
 
 =back
 
 
 =back
 
-=head1 PHASES AND OPTIONS
+=head1 OPTIONS AND PHASES
 
 
-Novaboot performs its work in several phases. Command like options
+Novaboot performs its work in several phases. Command line options
 described bellow influence the execution of each phase or allow their
 skipping. The list of phases (in the execution order) is as follows.
 
 described bellow influence the execution of each phase or allow their
 skipping. The list of phases (in the execution order) is as follows.
 
@@ -1756,10 +1823,23 @@ example C<ssh server 'cu -l /dev/ttyS0'>.
 
 =item --remote-expect=I<string>
 
 
 =item --remote-expect=I<string>
 
-Wait for reception of I<string> after establishing the remote
-connection. This option is needed when novaboot should wait for
-confirmation before deploying files to the target, e.g. to not
-overwrite other user's files when they are using the target.
+Wait for reception of I<string> after establishing the remote serial
+line connection. Novaboot assumes that after establishing the serial
+line connection, the user running novaboot has exclusive access to the
+target. If establishing of the serial line connection happens
+asynchronously (e.g. running a command remotely via SSH), we need this
+option to wait until the exclusive access is confirmed by the remote
+side.
+
+Depending on target configuration, this option can solve two practical
+problems: 1) Overwriting of files deployed by another user currently
+using the target. 2) Resetting the target board before serial line
+connection is established and thus missing bootloader interaction.
+
+Example of usage with the L<sterm
+tool|https://rtime.felk.cvut.cz/gitweb/sojka/sterm.git>:
+
+  --remote-cmd='ssh -tt example.com sterm -v /dev/ttyUSB0' --remote-expect='sterm: Connected'
 
 =item --remote-expect-silent=I<string>
 
 
 =item --remote-expect-silent=I<string>
 
@@ -1772,7 +1852,7 @@ end characters in the I<string> as well.
 
 Timeout in seconds for B<--remote-expect> or
 B<--remote-expect-seconds>. When negative, waits forever. The default
 
 Timeout in seconds for B<--remote-expect> or
 B<--remote-expect-seconds>. When negative, waits forever. The default
-is 180 seconds.
+is -1 seconds.
 
 =back
 
 
 =back
 
@@ -1816,10 +1896,11 @@ Port to run the TFTP server on. Implies B<--tftp>.
 
 =item --netif=I<network interface>
 
 
 =item --netif=I<network interface>
 
-Network interface used to deploy files to the target. The default value is
-I<eth0>. This option influences the configuration of the DHCP server started
-by B<--dhcp-tftp> and the value that B<$NB_MYIP> get replaced with during
-U-Boot conversation.
+Network interface used to deploy files to the target. This option
+influences the configuration of the DHCP server started by
+B<--dhcp-tftp> and the value that B<$NB_MYIP> get replaced with during
+U-Boot conversation. The default value is C<$netif> variable from
+configuration files, which defaults to I<eth0>.
 
 =item --iso[=filename]
 
 
 =item --iso[=filename]
 
@@ -1917,6 +1998,12 @@ novaboot script. I<prompt> specifies the U-Boot's prompt (default is
 
 Disable U-Boot interaction previously enabled with B<--uboot>.
 
 
 Disable U-Boot interaction previously enabled with B<--uboot>.
 
+=item --uboot-stop-key=I<key>
+
+Character, which is sent as a response to U-Boot's "Hit any key to
+stop autoboot" message. The default value is newline, but some devices
+(e.g. TP-Link TD-W8970) require a specific key to be pressed.
+
 =item --uboot-init
 
 Command(s) to send the U-Boot bootloader before loading the images and
 =item --uboot-init
 
 Command(s) to send the U-Boot bootloader before loading the images and
@@ -1978,7 +2065,7 @@ The same as --exiton -re --exiton I<regex>.
 =item --exiton-timeout=I<seconds>
 
 By default B<--exiton> waits for the string match forever. When this
 =item --exiton-timeout=I<seconds>
 
 By default B<--exiton> waits for the string match forever. When this
-option is specified, "exiton" timeouts after the specifies the number of
+option is specified, "exiton" timeouts after the specified number of
 seconds and novaboot returns non-zero exit code.
 
 =item -i, --interactive
 seconds and novaboot returns non-zero exit code.
 
 =item -i, --interactive
@@ -2063,9 +2150,16 @@ word after C<load> is a file name (relative to the build directory
 (see B<--build-dir>) of the module to load and the remaining words are
 passed to it as the command line parameters.
 
 (see B<--build-dir>) of the module to load and the remaining words are
 passed to it as the command line parameters.
 
+When booting Linux, the first C<load> line usually refers to the
+kernel image and its command line parameters (unless you use some
+special pre-loader). Other C<load> lines may refer to an initramfs
+image and/or a device tree blob. Their order is not important, as the
+device tree is recognized as the file name ending with C<.dtb>.
+
 When the C<load> line ends with "<<WORD" then the subsequent lines
 until the line containing solely WORD are copied literally to the file
 When the C<load> line ends with "<<WORD" then the subsequent lines
 until the line containing solely WORD are copied literally to the file
-named on that line. This is similar to shell's heredoc feature.
+named on that line. This is similar to the heredoc feature of UNIX
+shells.
 
 When the C<load> line ends with "< CMD" then command CMD is executed
 with F</bin/sh> and its standard output is stored in the file named on
 
 When the C<load> line ends with "< CMD" then command CMD is executed
 with F</bin/sh> and its standard output is stored in the file named on
@@ -2273,6 +2367,11 @@ Default target (see below) to use when no target is explicitly
 specified with the B<--target> command line option or
 B<NOVABOOT_TARGET> environment variable.
 
 specified with the B<--target> command line option or
 B<NOVABOOT_TARGET> environment variable.
 
+=item $netif
+
+Default value for the B<--netif> option. If not specified, it defaults
+to I<eth0>.
+
 =item %targets
 
 Hash of target definitions to be used with the B<--target> option. The
 =item %targets
 
 Hash of target definitions to be used with the B<--target> option. The