Closed GoogleCodeExporter closed 9 years ago
What was the end filesize of the firmware? Did it cross a MB boundary? I would
guess that it did, causing the failure. Most firmwares are 'full', meaning if
you're going to add much to them, you're going to need to remove something. In
some cases, the simple process of extraction and rebuilding can increase the
filesize due to changes in the compression parameters and/or arrangement of
data in the filesystem.
Original comment by jeremy.collake@gmail.com
on 26 Jan 2013 at 4:48
I only changed 2 files, increasing the size by about 100 bytes only. The new
firmware was more than 200K larger:
Original: 7614608
Current: 7827600
So I added the -min option:
Remaining free bytes: 315392
So I went ahead and flashed it. The router was happy with the format and CRC,
etc. I expect it could not correctly mount the rootfs however and I can't find
any way to restore the original f/w.
Original comment by Anthony....@gmail.com
on 26 Jan 2013 at 5:49
D-Link and Trednents (often near identical at the hardware level) usually have
a router recovery mode that can accessed in one of the usual ways. Sometimes
there is some software to make this easy. Other times, you may need to manually
TFTP to the router during pre-boot initialization, or after a failed boot
(depending on how the firmware fails). Sometimes this can be invoked by holding
down the reset button during boot. In all cases, restoration should be
completely do-able, if you give it some effort, as the bootloader is still
there...
Original comment by jeremy.collake@gmail.com
on 26 Jan 2013 at 5:57
I tried holding in the reset button during power up and the router remained
unpingable on rhe previous as well as default IP. So no chance of getting to a
web f/w recovery page (assuming this model ever had one). I also tried to send
the file via tftp but no luck. I entered a static ARP entry to tell the
computer the routers MAC address on the LAN i/f. I also tried to look for any
ARP requests coming in using tcpdump but only saw the outgoing ARPs for the
computer. So I assumed this model does not support tftp, but maybe I missed
something?
Original comment by Anthony....@gmail.com
on 26 Jan 2013 at 6:16
I don't know, check the vendor's documentation. I haven't checked out that
particular device's firmware, but don't see how a failure could occur since the
boot loader is not normally touched by firmwares. The noted exception was my
old VxWorks Killer, which achieved dominance over VxWorks by using an
undocumented feature of the firmware format that allowed the bootloader to be
replaced. Anyway, the router should be recoverable from every perspective I
see. Contact D-Link's support department if you have to.
I suppose it is possible that some vendors killed the recovery mode, opting
instead for router replacement. This seems unlikely though.
As for the Firmware Mod Kit, it seems unlikely that anyone will closely
investigate the cause of the failure here, though perhaps they will. I will
leave this ticket for anyone who wants to jump in. There are so many routers
out there, most people aren't concerned with those they don't own. This creates
a highly fragmented market. Thankfully, the common use of linux, common
filesystems, and identifiable, unsigned/unencrypted firmware formats allows
existence of the firmware mod kit.
Original comment by jeremy.collake@gmail.com
on 26 Jan 2013 at 6:28
From what I've read, it seems tftp can be hardcoded to expect specific IPs for
not only the router but the computer too. This router has a default IP of
192.168.0.1. One article mentioned 192.168.1.1 and the router trying to arp
192.168.1.113 if I remember right. Another mentions using 192.168.11.1 and
192.168.11.2. I could not find a clear explanation anywhere? Do you have any
more info on this?
Original comment by Anthony....@gmail.com
on 26 Jan 2013 at 6:28
Later in the week I'll have time to give it a closer look. I will check the
exact parameters of unsquash/makesquash - this router seems to use
squashfs-4.0-lzma.
Original comment by Anthony....@gmail.com
on 26 Jan 2013 at 6:33
I checked the binwalk log and I copied the block size there into the
build-ng.sh script to force it to be the same as the original f/w. Now the
spare bytes is exactly 0 and the new f/w is the exact same size as the old one.
This seems a bit better to me, and perhaps it would be better if the script
automatically set the block size to the same value from the extract?
Original comment by Anthony....@gmail.com
on 27 Jan 2013 at 7:44
Yes, that sounds appropriate. I will dive into this when I can and automate the
process. Thanks!
Original comment by jeremy.collake@gmail.com
on 27 Jan 2013 at 9:34
Here is the noted information about this device at the OpenWrt wiki btw:
http://wiki.openwrt.org/toh/d-link/dir-645 . Should have looked this up this
before.
If you're going to play with these babies, you should order one of these and
make your life fun:
http://www.amazon.com/gp/product/B006JKNWLE/ref=oh_details_o03_s00_i00 .
Original comment by jeremy.collake@gmail.com
on 29 Jan 2013 at 3:24
I already read that. It does not really help, unless you are suggesting I use
the tools from the GPL source to build the f/w instead of firmware-mod-kit? I
can't see how it would help unless perhaps the mod kit is not correctly
handling the headers? I'm hoping the problem was simply the incorrect block
size. I'm assuming using a 1MB bs instead of the 262144 (0x40000) is what
bricked the device. I am hoping to be able to test this by copying the
rootfs.img part to the router and mounting it on ramdisk (/var/tmp). I expect
the original to work and the bad one to fail. However I must look closer at the
headers too.
I should still have a RS232C to TTL converter lying around, but to use that I
need to break the seal and open the device which would void my warranty and it
is brand new. I should receive a replacement by tomorrow.
As for tftp it really did not work - I tried it with a protocol analyser
running and could see absolutely nothing from the LAN port. Interestingly, the
WAN port still managed to acquire an IP via DHCP and I wonder if there is a
chance they moved the tftp over to the WAN side for recovery? I did not have
time to try it though as I had to drop it off at the supplier.
Original comment by Anthony....@gmail.com
on 29 Jan 2013 at 6:33
I inserted in extract-ng.sh:
FS_BLOCKSIZE=$(echo ${LINE} | sed -e 's/.*blocksize: //' | cut -d' ' -f1)
...
echo "FS_BLOCKSIZE='${FS_BLOCKSIZE}'" >> ${CONFLOG}
and to build-ng.sh:
if [ "$NEXT_PARAM" == "-min" ]
then
BS="-b $((1024*1024))"
else
BS="-b $FS_BLOCKSIZE"
fi
Original comment by Anthony....@gmail.com
on 29 Jan 2013 at 4:07
Thanks! I'll commit and test this ASAP. I am doing some embedded systems work
(first time in a couple years), so it is good timing.
Original comment by jeremy.collake@gmail.com
on 29 Jan 2013 at 7:42
I got a replacement router and I dumped the bootloader. In it I see a web page
which is the "emergency room" for reflashing the unit. I also see a menu driven
interface to enable flashing via the serial console (kermit) or by connecting
to a tftp server. However to get into this it seems the only way is via the
internal serial interface. I'm puzzled therefore as to why I could not get into
the web interface no matter what I tried. I'm wondering if on this model they
moved the recovery interface from the LAN to WAN? During boot the WAN was still
getting an IP via DHCP but I did not have a chance to try that before I had to
swap out the unit for the new one.
Original comment by Anthony....@gmail.com
on 31 Jan 2013 at 8:51
[deleted comment]
[deleted comment]
I tried that and it did not work. However I used the MAC address of the LAN i/f
and it looks like there will be absolutely no response from the router unless
it sees a packet with the correct MAC which is not necessarily the usual MAC,
but rather some fake MAC. I looked in the bootloader and see:
ethaddr="00:AA:BB:CC:DD:10"
ipaddr=10.10.10.123
serverip=10.10.10.3
which is different to what is in the article. However elsewhere in the
bootloader I see the real MAC address and:
ipaddr=192.168.0.101
serverip=1.2.3.103
This is odd as they're not even in the same subnet.
I also suspect there is a chance they might have moved recovery from the LAN to
the WAN interface, though I do see: ethact=Eth0 (10/100-M)
Last night I had the idea of trying to mount the rootfs.img on the ramdisk at
/var/tmp to confirm that it can mount OK, but I ran into a problem. There is no
loop device defined! I don't think it is enough to just mknod /dev/loop0 b 7 8.
That did not help. Any ideas here how I might mount it without flashing the
f/w? It seems the squashfs support is in the bootloader itself? So I was not
able to test it this way. Maybe I need to build squashfs and losetup and load
them? I've never tried this so not sure what is needed. I did just setup a VM
with Fedora 10 which is the environment DLink require to build their f/w.
Original comment by Anthony....@gmail.com
on 1 Feb 2013 at 5:29
Is it possible that creating the squashfs on linux 3.x (ubuntu) will give
problems when mounting it on linux 2.6 (the router)? For example the way the
IDs for block and character nodes are packed differs between different flavors
of linux.
Also, I wonder if it is better to replace sudo in your build-ng.sh with
fakeroot?
Other than the above two points, I can think of no other reason the f/w would
not work, other than using the wrong blocksize of 1MB (-min option) when the
original used 256KB.
Original comment by Anthony....@gmail.com
on 1 Feb 2013 at 5:37
In the f/w the seama hdr indicates the size of the f/w that follows, which
starts with the compressed kernal.img, which is then padded with nulls to the
next 64K boundary in the file, followed by a 32 byte header as follows:
--PaCkImGs-- (12 bytes)
00..00 (4 nulls)
size of roots.img (4 bytes)
00..00 (12 bytes)
rootfs.img
The rootfs.img is itself padded with nulls to the next 4K boundary.
build-ng.sh will append rootfs.img to the preceding data without updating any
sizes - only the 16-byte checksum (md5), and then pad the rootfs.img with FF to
the original size.
So using the -min option results in an img that is about 200K smaller, padded
with FF. I wonder if the flasher just writes the extra data to the ROM or if it
gets confused by the FFs and takes it as another file and overwrites another
partition such as nvram? Or if the bootloader gets messed up by it?
I have now successfully built the f/w from scratch using the GPL source and
will try to modify the f/w again but this time on linux 2.6 (Fedora 10) which
is the correct build environment for this f/w rather than linux 3 (Ubuntu 12).
Hopefully this will work.
The possible problems must have been one of:
Packing rootfs on linux 3 and mounting on the router running linux 2.6
Using a 1MB block size when the original uses 256K
Using sudo instead of fakeroot so perhaps a file was owned by me instead of
root.
Padding the img with FF rather than 00 and having too much padding.
Will let you know if it succeeds once I get there :)
Original comment by Anthony....@gmail.com
on 2 Feb 2013 at 11:00
NEW F/W WORKING!
I extracted the latest f/w on Fedora 10 (linux 2.6.27) (router running 2.6.33).
However I changed sudo in extract-ng.sh to fakeroot.
I changed the files under rootfs that I needed to.
However to build the new f/w, just to be sure, I first extracted the kernel.img
from header.img by stripping the first 32 bytes and also removed the null
padding at the end and made sure that lzma could successfully decompress it.
Then I reassembled using the tools in the GPL source:
First:
fakeroot mksquashfs ~/dlink/fw103/image_parts/rootfs
~/dlink/fw103/newrootfs.img -b 256k
Note the blocksize matches the original f/w.
Note also that I first did this (from their build script):
chmod 664 newrootfs.img
and also:
chmod 775 kernel.img
Then pack the two images together padding kernal to 64K boundary, adding
packimgs header with fs filesize:
tools/building/packimgs -o raw.img -i kernel.img -i newrootfs.img
Then add the seema header and md5 checksum:
tools/seama/seama -i raw.img -m dev=/dev/mtdblock/2 -m type=firmware
And add the first seama header:
tools/seama/seama -s web.img -i raw.img.seama -m signature=wrgn39_dlob.hans_645
Finally rename the file:
mv web.img DIR645A1_FW103B11.bin
I believe build-ng.sh would have created the same file if sudo was replaced
with fakeroot and the -b 256k was added. I can't check this since the
rootfs.img is different (probably due to timestamps?).
Original comment by Anthony....@gmail.com
on 2 Feb 2013 at 4:51
Congratulations ;). I will review your steps and update the FMK when I can.
Thanks for reporting those steps in detail, others may find that immediately
useful.
Original comment by jeremy.collake@gmail.com
on 2 Feb 2013 at 8:33
I finally added support to preserve the block size. I had forgot about your
patch here, and my code is actually not as pretty in the parsing of the block
size in the build script, so I will likely replace it with yours! Sorry it took
so long, I avoid thinking as long as possible.
Original comment by jeremy.collake@gmail.com
on 10 Apr 2013 at 6:37
err I mean extract script
Original comment by jeremy.collake@gmail.com
on 10 Apr 2013 at 6:38
Original issue reported on code.google.com by
Anthony....@gmail.com
on 25 Jan 2013 at 10:24