Patching custom rootfs onto existing firmware
Once you have the serial cable built as mentioned in my previous post, it is possible to patch the current firmware installation with custom rootfs, without having to upgrade/reinstall the whole firmware with custom one.
These are the high-level steps that we need to do:
- Discover the partition table and identify where the rootfs is stored in the flash storage.
- Read the rootfs of the current firmware and push it to a different machine.
- Modify the rootfs to your needs, on the other machine.
- Upload it back to WDTV and write the flash partition appropriately.
Discovering the rootfs partition
~ # mount
rootfs on / type rootfs (rw)
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
/dev/sigmblockh on / type cramfs (ro)
none on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
usb on /proc/bus/usb type usbfs (rw)
mdev on /dev type tmpfs (rw)
devpts on /dev/pts type devpts (rw)
none on /tmp type tmpfs (rw)
/dev/loop0 on /tmp/static_config type minix (rw)
Note the highlighted line. /dev/sigmblockh device is the one mounted as / partition. To confirm print the first 100 bytes on the device and you could notice the CRAMFS header.
~ # hexdump -c -n 100 /dev/sigmblockh
0000000 E = 315 ( \0 @ 021 003 003 \0 \0 \0 \0 \0 \0 \0
0000010 C o m p r e s s e d R O M F S
0000020 234 333 016 324 \0 \0 \0 \0 k & \0 \0 313 016 \0 \0
0000030 C o m p r e s s e d \0 \0 \0 \0 \0 \0
0000040 355 A 354 003 D 001 \0 d 300 004 \0 \0 355 A 354 003
0000050 354 \v \0 d 001 031 \0 \0 b i n \0 377 241 354 003
0000060 \t \0 \0 d
0000064
~ #
We still need to know the exact flash disk and the partition to which this device points to.
~ # ls /dev/sigm* -l
brw-rw---- 1 root root 254, 0 Jan 1 2000 /dev/sigmblocka
brw-rw---- 1 root root 254, 1 Jan 1 2000 /dev/sigmblockb
brw-rw---- 1 root root 254, 2 Jan 1 2000 /dev/sigmblockc
brw-rw---- 1 root root 254, 3 Jan 1 2000 /dev/sigmblockd
brw-rw---- 1 root root 254, 4 Jan 1 2000 /dev/sigmblocke
brw-rw---- 1 root root 254, 5 Jan 1 2000 /dev/sigmblockf
brw-rw---- 1 root root 254, 6 Jan 1 2000 /dev/sigmblockg
brw-rw---- 1 root root 254, 7 Jan 1 2000 /dev/sigmblockh
brw-rw---- 1 root root 254, 8 Jan 1 2000 /dev/sigmblocki
brw-rw---- 1 root root 254, 9 Jan 1 2000 /dev/sigmblockj
brw-rw---- 1 root root 254, 10 Jan 1 2000 /dev/sigmblockk
brw-rw---- 1 root root 254, 11 Jan 1 2000 /dev/sigmblockl
The highlighted line shows the major, minor numbers for this device. As you might know, the minor number is the partition number on the disk. In this case, the rootfs is stored in the 7th partition.
To understand where is the 7th partition stored in the flash disk, we need to know the partition information of the internal flash disk. This could be obtained in two different ways. Either by looking at the logs during WDTV boot (via serial port) or by issuing the following command at the terminal (via serial again).
~ # cat /proc/sigminfo
dev: size offset name CS
sigmblk0: 0ff80000 00000000 "CS0-Device" 0
sigmblk1: 00080000 00000000 "CS0-Part1" 0
sigmblk2: 00040000 00080000 "CS0-Part2" 0
sigmblk3: 00300000 000c0000 "CS0-Part3" 0
sigmblk4: 00300000 003c0000 "CS0-Part4" 0
sigmblk5: 01000000 006c0000 "CS0-Part5" 0
sigmblk6: 00800000 016c0000 "CS0-Part6" 0
sigmblk7: 05a00000 01ec0000 "CS0-Part7" 0
sigmblk8: 05a00000 078c0000 "CS0-Part8" 0
sigmblk9: 00020000 0d2c0000 "CS0-Part9" 0
sigmblk10: 00020000 0d2e0000 "CS0-Part10" 0
sigmblk11: 00020000 0d300000 "CS0-Part11" 0
We are almost there now. This shows the starting offset (0x01ec0000) and the size (0x05a00000) of the partition. That is a 90MB partition reserved for rootfs ie., the compressed cramfs partition cannot exceed 90MB.
Read rootfs and export to different machine
This is required as we need to patch the rootfs of the installed firmware. Press 0 (via the serial port) and restart WDTV Live. This will prevent loading the firmware and will stop boot at booloader YAMON.
Follow my inline comments in the script below.
[Gerald] Plugin an Ethernet cable connected to a valid network.
[Gerald] net init, initializes the interface and runs DHCP client.
YAMON> net init Ethernet driver for SMP86XX (v1.0) (MAC 00:90:xx:xx:xx:xx) em86xx_eth0 - full-duplex mode em86xx_eth0 - 100 Mbit/s em86xx_eth0 ethernet start DHCP was successfully configured. ipaddr: 192.168.8.104 subnetmask: 255.255.255.0 gateway: 192.168.8.2
[Gerald] 'nflash read' command is used to read from the flash memory. [Gerald] Based on the discovery earlier, the following command reads [Gerald] first 0x1e00000 bytes into memory at 0x8400000. [Gerald] syntax: nflash read flash_address memory_address size chip_select [Gerald] chip_select (CS) is available in the partition info at /proc/sigminfo. [Gerald] Note: Use only 0x84000000 as target. Other addresses didn't let me read [Gerald] 0x1e00000 bytes at once.Even here, I couldn't read the complete 0x5a00000 [Gerald] bytes at once. YAMON> nflash read 0x01ec0000 0x84000000 0x1e00000 0 [Gerald] Verify if this has indeed read the CRAMFS from flash. YAMON> dump 0x84000000 100 84000000: 45 3D CD 28 00 40 11 03 03 00 00 00 00 00 00 00 E=�(.@.......... 84000010: 43 6F 6D 70 72 65 73 73 65 64 20 52 4F 4D 46 53 Compressed.ROMFS 84000020: 9C DB 0E D4 00 00 00 00 6B 26 00 00 CB 0E 00 00 .�.�....k&..�... 84000030: 43 6F 6D 70 72 65 73 73 65 64 00 00 00 00 00 00 Compressed...... 84000040: ED 41 EC 03 44 01 00 64 C0 04 00 00 ED 41 EC 03 .A..D..d�....A.. 84000050: EC 0B 00 64 01 19 00 00 62 69 6E 00 FF A1 EC 03 ...d....bin..�.. 84000060: 09 00 00 64 ...d [Gerald] upload the file to a tftp server of your choice. [Gerald] syntax: fwrite tftp_path memory_address size YAMON> fwrite tftp://192.168.8.101/sigh/sigh.dump.1 0x84000000 0x1e00000 About to binary write tftp://192.168.8.101/sigh/sigh.dump.1 Successfully transferred 0x1e00000 (10'31457280) bytes [Gerald] Read the next 0x1e00000 bytes from flash and upload to TFTP YAMON> nflash read 0x03cc0000 0x84000000 0x1e00000 0 YAMON> fwrite tftp://192.168.8.101/sigh/sigh.dump.2 About to binary write tftp://192.168.8.101/sigh/sigh.dump.2 Successfully transferred 0x1e00000 (10'31457280) bytes [Gerald] Read the next 0x1e00000 bytes from flash and upload to TFTP YAMON> nflash read 0x05ac0000 0x84000000 0x1e00000 0 YAMON> fwrite tftp://192.168.8.101/sigh/sigh.dump.3 About to binary write tftp://192.168.8.101/sigh/sigh.dump.3 Successfully transferred 0x1e00000 (10'31457280) bytes YAMON>
Modify the rootfs to your needs
At this point, we have three 30MB files and concatenating them in order, should give a complete cramfs partition. You could now extract the cramfs partition (using modified cramfsck, as mentioned in my earlier post) and make the necessary modification.
I have the following section of script added to the /init script, that gets control to my USB script as root. This lets me run scripts on startup and modify them as required, without having to reflash anything. Don't forget to update the /md5sums.txt file with your updated md5sum.
# Gerald - update - start if [ -f /tmp/media/usb/wdtv/gerald_init ]; then /tmp/media/usb/wdtv/gerald_init & # Gerald - update - end
Use the modified mkcramfs (as mentioned in my earlier post) to repack the rootfs into a cramfs filesystem file. Split the file into three 30MB files (note: you may need to append zeros at the end to fill up to 30MB in the third part -- your cramfs filesystem is likely to be < 90MB).
Upload back to WDTV and write the flash partition appropriately
Boot into YAMON. Use 'fread' to read from tftp to memory at 0x84000000. Use 'nflash write' to write the parts into their correct flash locations starting at 0x01ec00000. Once all 3 partitions are written, just reboot. Your new rootfs should be active.
By now, you would no longer be worried about what to do if that doesn't boot. Good luck!