]> rtime.felk.cvut.cz Git - novaboot.git/blobdiff - novaboot
Add --copy= as alias to --server=
[novaboot.git] / novaboot
index 11930c9858268d7245de6abcb973ef445be87ee8..15eddaa67ec7b72c4bc1017cebfc9bb595ce0525 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
@@ -52,11 +52,12 @@ $CFG::hypervisor_params = "serial";
 $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',
+    "tud" => '--copy=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)\'"',
+    "localhost" => '--scriptmod=s/console=tty[A-Z0-9,]+// --copy=/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 --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"',
@@ -141,11 +142,11 @@ my ($target_reset, $target_power_on, $target_power_off);
     );
 $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;
-$netif = 'eth0';
+$netif = $CFG::netif;
 $remote_expect_timeout = -1;
 
 my @expect_seen = ();
@@ -176,6 +177,9 @@ my %opt_spec_safe = (
     "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-stop-key=s" => \$uboot_stop_key,
@@ -219,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]); },
-    "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,
@@ -232,6 +233,7 @@ my %opt_spec = (
     "sendcont=s"     => \&handle_send,
     "serial|s:s"     => \$serial,
     "server:s"              => \$server,
+    "copy:s"        => \$server,
     "ssh:s"         => \&handle_novaboot_server,
     "strip-rom"             => sub { $rom_prefix = ''; },
     "stty=s"        => \$stty,
@@ -411,6 +413,7 @@ while (!$skip_reading && ($_ = <>)) {
            push @$generated, {filename => $1, command => $3};
            return "$1$2";
        }
+       s/\s*$//;               # Strip trailing whitespace
        return $_;
     }
     if (s/^load *//) {         # Load line
@@ -995,7 +998,7 @@ foreach my $script (@scripts) {
            $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) {
@@ -1025,11 +1028,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);
-    } 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);
+    } 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";
@@ -1171,7 +1180,7 @@ if (defined $ider) {
 ### 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) {
@@ -1246,7 +1255,7 @@ if (defined $uboot) {
        @$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");
            $exp->expect(15,
@@ -1298,7 +1307,7 @@ if ($interaction && defined $exp) {
     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;
@@ -1379,6 +1388,40 @@ having per-system, per-user or per-project configurations.
 Configuration file syntax is described in section L</"CONFIGURATION
 FILES">.
 
+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
+to 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</--copy>, 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</--copy>) 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
@@ -1409,7 +1452,7 @@ 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.
 
- ./mylinux --grub2 --server=192.168.1.1:/tftp --iprelay=192.168.1.2
+ ./mylinux --grub2 --copy=192.168.1.1:/tftp --iprelay=192.168.1.2
 
 Alternatively, you can put these switches to the configuration file
 and run:
@@ -1452,7 +1495,7 @@ I<script2> configurations.
 
 =back
 
-=head1 PHASES AND OPTIONS
+=head1 OPTIONS AND PHASES
 
 Novaboot performs its work in several phases. Command line options
 described bellow influence the execution of each phase or allow their
@@ -1561,7 +1604,7 @@ Configures novaboot to control the target via C<novaboot-shell>
 running remotely via SSH.
 
 Using this option is the same as specifying B<--remote-cmd>,
-B<--remote-expect>, B<--server> B<--rsync-flags>, B<--prefix> and
+B<--remote-expect>, B<--copy> B<--rsync-flags>, B<--prefix> and
 B<--reset-cmd> manually in a way compatible with C<novaboot-shell>.
 The server can be configured to provide other, safe bootloader-related
 options, to the client. When this happens, novaboot prints them to
@@ -1782,10 +1825,23 @@ example C<ssh server 'cu -l /dev/ttyS0'>.
 
 =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>
 
@@ -1842,10 +1898,11 @@ Port to run the TFTP server on. Implies B<--tftp>.
 
 =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]
 
@@ -1855,6 +1912,10 @@ of the novaboot script (see also B<--name>).
 
 =item --server[=[[user@]server:]path]
 
+Alias of B<--copy> (kept for backward compatibility).
+
+=item --copy[=[[user@]server:]path]
+
 Copy all files needed for booting to another location. The files will
 be copied (by B<rsync> tool) to the directory I<path>. If the I<path>
 contains string $NAME, it will be replaced with the name of the
@@ -1863,13 +1924,13 @@ novaboot script (see also B<--name>).
 =item --rsync-flags=I<flags>
 
 Specifies I<flags> to append to F<rsync> command line when
-copying files as a result of I<--server> option.
+copying files as a result of I<--copy> option.
 
 =item --concat
 
-If B<--server> is used and its value ends with $NAME, then after
+If B<--copy> is used and its value ends with $NAME, then after
 copying the files, a new bootloader configuration file (e.g. menu.lst)
-is created at I<path-wo-name>, i.e. the path specified by B<--server>
+is created at I<path-wo-name>, i.e. the path specified by B<--copy>
 with $NAME part removed. The content of the file is created by
 concatenating all files of the same name from all subdirectories of
 I<path-wo-name> found on the "server".
@@ -2095,9 +2156,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.
 
+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
-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
@@ -2305,17 +2373,22 @@ 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.
 
+=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
 key is the identifier of the target, the value is the string with
 command line options. For instance, if the configuration file contains:
 
- $targets{'mybox'} = '--server=boot:/tftproot --serial=/dev/ttyUSB0 --grub',
+ $targets{'mybox'} = '--copy=boot:/tftproot --serial=/dev/ttyUSB0 --grub',
 
 then the following two commands are equivalent:
 
- ./myos --server=boot:/tftproot --serial=/dev/ttyUSB0 --grub
+ ./myos --copy=boot:/tftproot --serial=/dev/ttyUSB0 --grub
  ./myos -t mybox
 
 =back