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


    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 which I don't understand how to decode, but seems related to the sercomm signature that I have hard coded).

    # 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
    #   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
    #   <>
    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);
            # 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);
            # 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);
            # 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 = $@;
        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 = $@;
        die "$err\n" if ($err);
    my $err = $@;
    if ($err) {
        die "$err\n";

    Attached Files:

  2. jac_goudsmit

    jac_goudsmit Super Moderator Staff Member Member


    I think the 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.

  3. alejandro_liu

    alejandro_liu Addicted to LI Member


    I did a "strace" on the "bind" utility that comes from Linksys. According to that the Sercom header is written right after the file is read. So my guess is that somehow the two are related.
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice