# 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') : ());
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;
$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',
"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;
## 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_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, $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, $reset, $reset_cmd, $reset_send, $rom_prefix, $rsync_flags, @scriptmod, $scons, $serial, $server, $stty, $tftp, $tftp_port, $uboot, %uboot_addr, $uboot_cmd, @uboot_init);
+# Default values of certain command line options
%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
+$final_eol = 1;
+$netif = 'eth0';
my @expect_seen = ();
sub handle_expect
"expect=s" => \&handle_expect,
"expect-re=s" => \&handle_expect,
"expect-raw=s" => sub { my ($n, $v) = @_; unshift(@expect_raw, eval($v)); },
+ "final-eol!" => \$final_eol,
"gen-only" => \$gen_only,
"grub|g:s" => \$grub_config,
"grub-preamble=s"=> \$grub_preamble,
"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,
"interactive|i" => \$interactive,
"name=s" => \$config_name_opt,
"make|m:s" => \$make,
+ "netif=s" => \$netif,
"no-file-gen" => \$no_file_gen,
"off" => \$off_opt,
"on" => \$on_opt,
"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,
+ "reset-send=s" => \$reset_send,
"rsync-flags=s" => \$rsync_flags,
"scons:s" => \$scons,
"scriptmod=s" => \@scriptmod,
"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,
'--amt' => \$amt);
my @opts = grep(defined(${$input_opts{$_}}) , keys %input_opts);
- print STDERR "novaboot: Warning: More than one target connection option: ".join(', ', @opts) if scalar @opts > 1;
+ die("novaboot: More than one target connection option: ".join(', ', @opts)) if scalar @opts > 1;
}
# Default options
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}) {
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
}
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
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);
$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) {
};
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";
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) {
};
}
+if (defined $reset_send) {
+ $target_reset = sub {
+ $reset_send =~ s/\\n/\n/g;
+ $exp->send($reset_send);
+ };
+}
+
if (defined $on_opt && defined $target_power_on) {
&$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;
}
$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;
}
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) {
map({ my $file = (split)[0]; die "$file: $!" if ! -f $file; } @$modules);
my $istty = -t STDOUT && ($ENV{'TERM'} || 'dumb') ne 'dumb';
my $progress = $istty ? "--progress" : "";
- system_verbose("rsync $progress -RLp $rsync_flags $files $real_server");
- if ($server =~ m|/\$NAME$| && $concat) {
- my $cmd = join("; ", map { "( cd $path/.. && cat */$_ > $_ )" } @bootloader_configs);
- system_verbose($hostname ? "ssh $hostname '$cmd'" : $cmd);
+ if ($files) {
+ system_verbose("rsync $progress -RLp $rsync_flags $files $real_server");
+ if ($server =~ m|/\$NAME$| && $concat) {
+ my $cmd = join("; ", map { "( cd $path/.. && cat */$_ > $_ )" } @bootloader_configs);
+ system_verbose($hostname ? "ssh $hostname '$cmd'" : $cmd);
+ }
}
}
}
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
}
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: $!");
}
system_verbose('mkdir -p tftpboot');
generate_grub_config("tftpboot/os-menu.lst", $config_name, "(nd)", \@$modules, "timeout 0");
open(my $fh, '>', 'dhcpd.conf');
- my $mac = `cat /sys/class/net/eth0/address`;
+ my $mac = `cat /sys/class/net/$netif/address`;
chomp $mac;
print $fh "subnet 10.23.23.0 netmask 255.255.255.0 {
range 10.23.23.10 10.23.23.100;
fixed-address 10.23.23.1;
}";
close($fh);
- system_verbose("sudo ip a add 10.23.23.1/24 dev eth0;
- sudo ip l set dev eth0 up;
+ system_verbose("sudo ip a add 10.23.23.1/24 dev $netif;
+ sudo ip l set dev $netif up;
sudo touch dhcpd.leases");
# We run servers by forking ourselves, because the servers end up
### 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);
### 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);
$timeout = 10;
}
if ($cmd =~ /\$NB_MYIP/) {
- my $ip = (grep /inet /, `ip addr show eth0`)[0] || die "Problem determining our IP address";
+ my $ip = (grep /inet /, `ip addr show $netif`)[0] || die "Problem determining our IP address";
$ip =~ s/\s*inet ([0-9.]*).*/$1/;
$cmd =~ s/\$NB_MYIP/$ip/g;
}
}
chomp($cmd);
$exp->send("$cmd\n");
- $exp->expect($timeout, $uboot_prompt) || die "U-Boot prompt timeout";
+
+ my ($matched_pattern_position, $error,
+ $successfully_matching_string,
+ $before_match, $after_match) =
+ $exp->expect($timeout, $uboot_prompt);
+ die "No U-Boot prompt: $error" if $error;
+ #print "\n>>>>$before_match<<<<\n";
}
- # Boot the system if there are some load lines in the script
- if (scalar(@$modules) > 0 && !$variables->{NO_BOOT}) {
+ # Load files if there are some load lines in the script
+ if (scalar(@$modules) > 0 && !$variables->{NO_BOOT}) {
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");
$exp->send("setenv bootargs $kcmd\n");
$exp->expect(5, $uboot_prompt) || die "U-Boot prompt timeout";
- $uboot_cmd //= $variables->{UBOOT_CMD} // 'bootm $kernel_addr $ramdisk_addr $fdt_addr';
+ }
+ $uboot_cmd //= $variables->{UBOOT_CMD} // 'bootm $kernel_addr $ramdisk_addr $fdt_addr';
+ if (!$variables->{NO_BOOT} && $uboot_cmd ne '') {
$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;
}
### 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");
- print "\n";
} 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;
die("novaboot: This should kill servers on background\n");
}
+# Always finish novaboot output with newline
+print "\n" if $final_eol;
+
## Documentation
+=encoding utf8
=head1 NAME
novaboot - Boots a locally compiled operating system on a remote
=head1 DESCRIPTION
-This program makes booting of a locally compiled operating system (OS)
+Novaboot makes booting of a locally compiled operating system (OS)
(e.g. NOVA or Linux) on remote targets as simple as running a program
locally. It automates things like copying OS images to a TFTP server,
generation of bootloader configuration files, resetting of target
hardware or redirection of target's serial line to stdin/out. Novaboot
-is highly configurable and it makes it easy to boot a single image on
+is highly configurable and makes it easy to boot a single image on
different targets or different images on a single target.
-Novaboot operation is controlled by command line options and by a so
-called novaboot script, which can be thought as a generalization of
-bootloader configuration files (see L</"NOVABOOT SCRIPT SYNTAX">).
-Typical way of using novaboot is to make the novaboot script
-executable and set its first line to I<#!/usr/bin/env novaboot>. Then,
-booting a particular OS configuration becomes the same as executing a
-local program - the novaboot script.
+Novaboot operation is controlled by configuration files, command line
+options and by a so called novaboot script, which can be thought as a
+generalization of bootloader configuration files (see L</"NOVABOOT
+SCRIPT SYNTAX">). Typical way of using novaboot is to make the
+novaboot script executable and set its first line to I<#!/usr/bin/env
+novaboot>. Then, booting a particular OS configuration becomes the
+same as executing a local program – the novaboot script.
Novaboot uses configuration files to, among other things, define
command line options needed for different targets. Users typically use
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>:
=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 can be specified with the B<--qemu> option.
+Thus running
+
+ 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.
./myos --grub2 --server=192.168.1.1:/tftp --iprelay=192.168.1.2
+Alternatively, you can put these switches to the configuration file
+and run:
+
+ ./myos --target mytarget
+
=item 3.
Run DHCP and TFTP server on developer's machine to boot the target
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,
+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>
=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
=item -b, --bender
-Use F<bender> chainloader. Bender scans the PCI bus for PCI serial
-ports and stores the information about them in the BIOS data area for
-use by the kernel.
+Use L<bender|https://github.com/TUD-OS/morbo/blob/master/standalone/bender.c>
+chainloader. Bender scans the PCI bus for PCI serial ports and stores
+the information about them in the BIOS data area for use by the
+kernel.
=item --chainloader=I<chainloader>
=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
Port to run the TFTP server on. Implies B<--tftp>.
+=item --netif=I<network interface>
+
+Network interface used to deploy files to the target. Default value is
+I<eth0>. This influences the configuration of the DHCP server started
+by B<--dhcp-tftp> and the value that B<$NB_MYIP> get replaced with in
+U-Boot conversation.
+
=item --iso[=filename]
Generates the ISO image that boots NOVA system via GRUB. If no filename
At this point, the target is reset (or switched on/off). There is
several ways how this can be accomplished. Resetting a physical target
can currently be accomplished by the following options: B<--amt>,
-B<--iprelay>, B<--reset-cmd>.
+B<--iprelay>, B<--reset-cmd> and B<--reset-send>.
=over 8
Command that resets the target.
+=item --reset-send=I<string>
+
+Reset the target by sending the given I<string> to the remote serial
+line. "\n" sequences are replaced with newline character.
+
=item --no-reset, --reset
Disable/enable resetting of the target.
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
commands from each option novaboot waits for U-Boot I<prompt>.
If the command contains string I<$NB_MYIP> then this string is
-replaced by IPv4 address of eth0 interface. Similarly I<$NB_PREFIX> is
-replaced with prefix given by B<--prefix>.
+replaced by IPv4 address of eth0 interface (see also B<--netif>).
+Similarly I<$NB_PREFIX> is replaced with prefix given by B<--prefix>.
See also C<uboot> keyword in L</"NOVABOOT SCRIPT SYNTAX">).
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
Example: C<--expect='Continue?' --sendcont='yes\n'>
+=item --final-eol, --no-final-eol
+
+By default, B<novaboot> always prints an end-of-line character at the
+end of its execution in order to ensure that the output of programs
+started after novaboot appears at the beginning of the line. When this
+is not desired B<--no-final-eol> option can be used to override this
+behavior.
+
=back
=head1 NOVABOOT SCRIPT SYNTAX
=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>, 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
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.
+Defining this variable has the same effect as using B<--bender>
+option.
=back
Michal Sojka <sojka@os.inf.tu-dresden.de>
+Latest novaboot version can be found at
+L<https://github.com/wentasah/novaboot>.
+
=cut
# LocalWords: novaboot Novaboot NOVABOOT TFTP PXE DHCP filename stty