1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

NAS200 image bind utility

Discussion in 'Cisco/Linksys Network Storage Devices' started by alejandro_liu, Aug 28, 2008.

  1. alejandro_liu

    alejandro_liu Addicted to LI Member

    Hi,

    I am starting to play around the NAS200 firmware using the GPL code from Linksys (V32R62).

    Unfortunately this code is not fully open. A bunch of stuff is closed source. With an eye to make NAS200 firmware projects open source, I wrote a perl script replacement to the "bind" executable that can be found in the linksys GPL kit under the images directory.

    This is a quick hack, and seems to work. It you give it a bzImage, romdisk and redboot.bin it will create a new linux.bin file that should be identical to the output from "bind". (note, it does not need the nd51.pid which I don't understand how to decode, but seems related to the sercomm signature that I have hard coded).

    Code:
    #!/usr/bin/perl
    #
    # Replacement of the "bind" utility for the NAS200 GPL kit
    #
    #   nascc-bind
    #   Copyright (C) 2008 Alejandro Liu Ly
    #
    #   nascc-bind is free software; you can redistribute it and/or modify
    #   it under the terms of the GNU General Public License as
    #   published by the Free Software Foundation; either version 2 of
    #   the License, or (at your option) any later version.
    #
    #   nascc-bind is distributed in the hope that it will be useful,
    #   but WITHOUT ANY WARRANTY; without even the implied warranty of
    #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    #   GNU General Public License for more details.
    #
    #   You should have received a copy of the GNU General Public
    #   License along with this program.  If not, see
    #   <http://www.gnu.org/licenses/>
    #
    #
    
    use strict;
    use warnings;
    use Fcntl qw(:DEFAULT :seek);
    
    my $bzimage = 'bzImage';
    my $romdisk = 'romdisk';
    my $redboot = 'redboot.bin';
    my $output = 'linux.bin';
    
    my $bzimage_off = 0;
    my $bzimage_sz = 1792 * 1024;
    my $romdisk_off = $bzimage_off + $bzimage_sz;
    my $romdisk_sz = 6144 * 1024;
    my $config_off = $romdisk_off + $romdisk_sz;
    my $config_sz = 128 * 1024;
    my $redboot_off = $config_off + $config_sz;
    my $redboot_sz = 128 * 1024;
    my $image_end = $redboot_off + $redboot_sz;
    
    my $md5sig_sz = 32;
    
    my $magic_off = 1632;
    
    my $sercomm = "sErCoMm\0\1\0\0\4p1\225X\20\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\22\0\0\0\0\0\0\0\3\0\0004b\0\0\0 sErCoMm";
    
    while (scalar(@ARGV)) {
        my $opt = shift;
    
        if ($opt =~ /^--([A-Za-z]+)=(.+)$/) {
            $opt = $1;
            unshift @ARGV,$2;
        }
    
        if ($opt eq '--bzImage') {
            $bzimage =shift;
            $bzimage || die "Missing bzimage argument\n";
        } elsif ($opt eq '--romdisk') {
            $romdisk = shift;
            $romdisk || die "Missing romdisk argument\n";
        } elsif ($opt eq '--redboot') {
            $redboot = shift;
            $redboot || die "Missing redboot argument\n";
        } elsif ($opt eq '--output' || $opt eq '-o') {
            $output = shift;
            $output || die "Missing output argument\n";
        } else {
            die "Unknown option $opt\n";
        }
    }
    
    die "$output: already exists\n" if (-f $output);
    
    eval {
        # Create image...
        open(my $outh,">",$output) || die "$output: $!\n";
        eval {
            # Make sure file is the right size..
            seek($outh,$image_end-1,SEEK_SET) || die "seek(end): $!\n";
            print $outh "\0";
    
            # Write linux kernel image...
            seek($outh,$bzimage_off,SEEK_SET) || die "$output: seek $!\n";
            open(my $bzi,"<",$bzimage) || die "$bzimage: $!\n";
            while (<$bzi>) {
                print $outh $_;
            }
            die "$bzimage: Linunx kernel is too big (> $bzimage_sz)\n"
                if (tell($bzi) > $bzimage_sz);
            close($bzi);
    
            # Write rom disk...
            seek($outh,$romdisk_off, SEEK_SET) || die "$output: seek $!\n";
            open(my $fs,"<",$romdisk) || die "$romdisk: $!\n";
            while (<$fs>) {
                print $outh $_;
            }
            die "$romdisk: Image is too big (> $romdisk_sz)\n"
                if (tell($fs) > $romdisk_sz);
            close($fs);
    
            # Redboot bios
            seek($outh, $redboot_off, SEEK_SET) || die "$redboot: seek $!\n";
            open(my $rb,"<",$redboot) || die "$redboot: $!\n";
            while (<$rb>) {
                print $outh $_;
            }
            die "$redboot: Redboot is too big (> $redboot_sz)\n"
                if (tell($rb) > $redboot_sz);
            close($rb);
    
            # Write sercomm signatures...
            seek($outh, $romdisk_off + $romdisk_sz - length($sercomm), SEEK_SET)
                || die "sercomm(1): seek $!\n";
            print $outh $sercomm;
    
            seek($outh, $redboot_off + $redboot_sz - $magic_off, SEEK_SET)
                || die "sercomm(2): seek $!\n";
            print $outh $sercomm;
    
            seek($outh,$config_off + $config_sz - $md5sig_sz,SEEK_SET)
                || die "md5sum(1): seek $!\n";
            for (my $i = 0 ; $i < $md5sig_sz; ++$i) {
                print $outh "\0";
            }
        };
        my $err = $@;
        close($outh);
        die "$err\n" if ($err);
    
        # Calculate checksum...
        my $cksum = `md5sum "$output"`;
        $cksum || die "$output: Unable to do md5sum\n";
        ($cksum)  = split(/\s+/,$cksum);
        die "$output: Invalid md5sum data\n"
            if (!$cksum || length($cksum) != 32);
    
        open(my $ckh,"+<",$output) || die "$output: $!\n";
        eval {
            seek($ckh,$config_off + $config_sz - $md5sig_sz,SEEK_SET)
                || die "md5sum(2): seek $!\n";
            print $ckh $cksum;
        };
        $err = $@;
        close($ckh);
        die "$err\n" if ($err);
    };
    my $err = $@;
    if ($err) {
        unlink($output);
        die "$err\n";
    }
    
    
     

    Attached Files:

  2. jac_goudsmit

    jac_goudsmit Super Moderator Staff Member Member

    Thanks!

    I think the nd51.pid file is an identification string that contains the version of the image. The "sErCoMm" signature comes in handy if you want to use e.g. Upslug to download the image to the NAS200 but I believe it's not strictly necessary.

    ===Jac
     
  3. alejandro_liu

    alejandro_liu Addicted to LI Member

    Hi,

    I did a "strace" on the "bind" utility that comes from Linksys. According to that the Sercom header is written right after the nd51.pid file is read. So my guess is that somehow the two are related.
     

Share This Page