#!/usr/bin/perl # $Id: serial-autoboot,v 1.1 2001/01/29 16:33:10 stewart Exp $ my $device; my $done; while (1) { # reset the tty device (ttyS0) system ("stty_reset"); $device = get_serial_device ("/dev/ttyS0", 9600); get_firmUI_prompt ($device); print "\nHave FirmUI prompt\n"; flush_ttys ($device); boot_diskless ($device); print "\nKernel is booting\n"; $done = 0; while ($done == 0) { #sysread ($device, $line, 20); $line = <$device>; print $line; if ($line =~ /^The system is halted/ || $line =~ /^Power down/) { close ($device); $done = 1; } } } ############# sub upload_binary; sub get_tty; sub flush_ttys; sub get_serial_device; sub boot_diskless; sub get_firmUI_prompt; # # Uploads a file over serial # params: device (/dev/ttyS0) # file name (with absolute path) # start address in the memory space to upload the file to # sub upload_binary { use FileHandle; autoflush TTY; my $device = $_[0]; my $upload_file = $_[1]; my $start_addr = $_[2]; my $file_size = (stat ($upload_file))[7]; my $file_blksize = (stat ($upload_file))[11]; my $file_blocks = (stat ($upload_file))[12]; my $file_size_hex = sprintf "%lx", $file_size; close (TTY); sysopen(TTY, $device, O_RDWR | O_SYNC | O_NOCTTY) or die "Cannot open device $device: $!"; # open (SND_FILE, $upload_file) || \ # die "Cannot open file $upload_file: $!" ; # $i = 0; # print TTY "z $start_addr $file_size_hex\n"; print TTY "x $start_addr\n"; # while (read (SND_FILE, $buff, $file_blksize)) { # print (TTY $buff) || die "Problem writting loop time: $i : $!"; # $i++; # } system ("sx -b --xmodem $upload_file < /dev/ttyS0 >/dev/ttyS0"); print "Finished uploading file \n"; # close (SND_FILE); close (TTY); sleep 2; } # # returns a tty ready to write to -- waits for IO # params: device (/dev/ttyS0) # sub get_tty { my $device = $_[0]; close (TTY); sysopen(TTY, $device, O_RDWR | O_SYNC | O_NOCTTY) or die "Cannot open device $device: $!"; return (TTY); } # # flush any data which may be waiting at the tty # params: tty file pointer to an opened TTY # sub flush_ttys { my $tty = $_[0]; my $end = 1; while ($end == 1) { eval { local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required alarm 1; $line = <$tty>; alarm 0; }; if ($@) { die unless $@ eq "alarm\n"; # propagate unexpected errors $end = 0; print "\nBuffer is clear\n"; # timed out } } } # # params: device (/dev/ttyS0) # sub get_serial_device { my $device = $_[0]; system ("stty_reset"); close (TTY); use FileHandle; autoflush TTY; my $device = $_[0]; #sysopen(TTY, $device, O_RDWR | O_NODELAY | O_NOCTTY) sysopen(TTY, $device, O_RDWR | O_SYNC | O_NOCTTY) or die "Cannot open device $device: $!"; use FileHandle; autoflush TTY; flush_ttys (TTY); return (TTY); } sub boot_diskless { my $tty = $_[0]; print $tty "boot production\n"; # There is a pause, then it ask a question, simply send a newline # to not answer the question sleep 2; print $tty "\n"; sleep 2; print $tty "\n"; print "Starting boot\n"; } # # read the boot up messages during boot of the NetWinder on the # serail console. # interupt the boot sequence and enter the debug menu # sub get_firmUI_prompt{ my $tty = $_[0]; my $end = 1; my $ok; my $start_time = time (); print "\nin reading init\n"; $end = 1; while ($end == 1) { eval { # NB: \n required local $SIG{ALRM} = sub { die "alarm\n" }; alarm 4; # We have to use sysread(), else we cannot reliably # get a correct reading. As well it will read a max # buffer size of 20, but in reality will normly only # read about 4-8 characters. sysread ($tty, $line, 20); alarm 0; }; if ($@) { # propagate unexpected errors die unless $@ eq "alarm\n"; $tmp = time() - $start_time; print "alarm timed out in loop for: $tmp seconds\n"; # timed out } print "@$line+"; print $tty "\n"; if ($line =~ /^Rebel/) { $end = 0; print "\t\tHAVE control\n"; next; } } print "Out of loop.\n"; if ($end == 0) { $ok = 1; } else { $ok = -1; } return ($ok); } # /* get_firmUI_prompt() */