On Mon, 2009-09-14 at 22:01 -0500, Larry Finger wrote:
> I tried it on the file above and got the following:
> 
> fin...@larrylap:~/WAG54GX2> ~/sprom/b43_fwcutter.py
> src.GPL/driver/2.6.8.1/extra/wl.ko
> Firmware md5sum is 4f1218df93c23b4e27c83cb208031a1d...
> Extracting a0g0bsinitvals2 of length 0x10 from offset 0x52A4C...
> Traceback (most recent call last):
>   File "/home/finger/sprom/b43_fwcutter.py", line 267, in <module>
>     extract_firmware(fd, extract, options.endian, outfn)
>   File "/home/finger/sprom/b43_fwcutter.py", line 197, in extract_firmware
>     buf, n = build_ivs(buf, endian)
>   File "/home/finger/sprom/b43_fwcutter.py", line 169, in build_ivs
>     assert biv.size in (2,4)
> AssertionError
> 

Oh, sorry... run it with the -b option to indicate that the binary is
big-endian.

You can see the command-line options with --help.  Also, I've attached
my script to downloads and inspect /all/ the firmware from the Linksys
site.  (Warning: ugly, hackish code to handle ugly, ridiculously
organized archives.)

Dan
#!/usr/bin/python
#
# (C) 2009 by Dan Lenski
# 
# Uses b43_finder.py to seek out all the firmware from Linksys's GPL
# code site.
#
#   Redistribution and use in source and binary forms, with or without
#   modification, are permitted provided that the following conditions
#   are met:
#
#     1. Redistributions of source code must retain the above copyright
#        notice, this list of conditions and the following disclaimer.
#     2. Redistributions in binary form must reproduce the above
#        copyright notice, this list of conditions and the following
#        disclaimer in the documentation and/or other materials provided
#        with the distribution.
#
#   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
#   WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
#   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
#   DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
#   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
#   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
#   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
#   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
#   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
#   OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
#   EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


import sys, os, re, tempfile, urllib, hashlib
import tarfile, zipfile
import b43_fwcutter

outdir = sys.argv[1]

def reporthook(blocks, blocksize, totalsize):
    sofar = blocks*blocksize
    if sofar>1.01e9: amount="%.2f GB"%(sofar/1e9)
    elif sofar>1.01e6: amount="%.2f MB"%(sofar/1e6)
    elif sofar>1.01e3: amount="%.2f kB"%(sofar/1e3)
    else: amount="%.2f B"%sofar
    if totalsize: percent = 100.0*sofar/totalsize
    else: percent = 100
    print "%2d%% - Downloaded %s      \r" % (percent, amount),
    if percent>=100: print

def search_archive(fn, name):
    # open the archive
    try:
        if name.endswith('.zip'):
            print "Opening zipfile..."
            archive = zipfile.ZipFile(fn)
            getnames = archive.namelist
            getfile = archive.open
        elif any(x in name for x in ('.tar','.tgz','.gz','.tbz','.bz')):
            print "Opening tarball..."
            archive = tarfile.open(fn)
            getnames = archive.getnames
            getfile = archive.extractfile
        else:
            print "Don't know what to do with archive named '%s'..." % name
            print "Skipping..."
            return

        # get contents
        print "Getting contents..."
        names = getnames()
    except:
        print "Couldn't open/list archive named '%s'..." % name
        print "Skipping..."
        return

    # find nested archives and potential firmware-containing binaries
    print "Finding files potentially containing firmware..."
    nested = [ n for n in names if any(x in n.lower() for x in ('.zip','.tar','.tgz','.gz','.tbz','.bz')) ]
    potential = [ n for n in names if re.match('wl(?:\w*)\.k?o', os.path.basename(n)) ]

    # stupid archive-inside-archives... RRRGH!
    if not potential:
        for fn in nested:
            tmp = "/tmp/"+hashlib.md5(fn).hexdigest()
            if not os.access(tmp, os.F_OK):
                print "Extracting nested archive %s..." % fn
                try:
                    open(tmp,"w").write( getfile(fn).read() )
                except:
                    print "Couldn't extract nested archive!!!"
                    continue
            print "Checking nested archive %s..." % fn
            search_archive( tmp, fn ) # RECURSE!

    # extract potential firmware-containing binaries
    for fn in potential:
        print "Extracting %s..." % fn
        tmp = tempfile.NamedTemporaryFile()
        contents = getfile(fn).read()
        md5sum = hashlib.md5(contents).hexdigest()
        tmp.write( contents )

        print "Guessing endian..."
        endian = '<'
        headers = os.popen("readelf -h %s" % tmp.name).readlines()
        for h in headers:
            if 'little endian' in h:
                endian = '<'
                break
            elif 'big endian' in h:
                endian = '>'
                break

        print "Cataloging %s..." % fn
        extracts = b43_fwcutter.mklist(tmp.name)

        if extracts:
            print " Found firmware!"
            print " MD5SUM of file is %s" % md5sum
            print " Saving firmware to %s/%s..." % (outdir, md5sum)
            if not os.access("%s/%s" % (outdir, md5sum), os.F_OK):
                os.mkdir("%s/%s" % (outdir, md5sum))

            open("%s/%s/info.txt" % (outdir, md5sum), "w").write("Archive: %s\nFile: %s\n" % (name, fn))
            open(os.path.join(outdir, md5sum, os.path.basename(fn)), "w").write(contents)

            for extract in extracts:
                print " Extracting %s of length 0x%X from offset 0x%X..." % (
                    extract.name, extract.length, extract.offset)
                outfn = os.path.join(outdir, md5sum, extract.name+".fw")
                b43_fwcutter.extract_firmware(tmp, extract, endian, outfn)

######################################################################

# get list of GPL code archives from Linksys
page = urllib.urlopen("http://www.linksysbycisco.com/gpl";).read()
archives = re.findall('''href=['"](http://downloads.linksysbycisco.com/.+)['"]''', page)
archives.insert(0, archives.pop(archives.index('http://downloads.linksysbycisco.com/downloads/wrt610n_v1.00.02.10_us.tar,0.gz')))

# go through 'em one-by-one
for archive in archives:
    tmp = "/tmp/"+hashlib.md5(archive).hexdigest()
    if not os.access(tmp, os.F_OK):
        print "Downloading %s..." % archive
        tmp, headers = urllib.urlretrieve(archive, tmp, reporthook=reporthook)
    print "Checking archive from %s for firmware..." % archive
    search_archive(tmp, archive)
    print "Done with %s..." % archive
    print "=================================================="
    print
_______________________________________________
Bcm43xx-dev mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/bcm43xx-dev

Reply via email to