Unpacking and Modification
First let's build the tool :
gcc -o splitnslu splitnslu.c
This tool has two capabilities: unpacking a Flash and packing a Flash. In order to get to the RAM disk, unpack the Flash:
./splitnslu unpack NSLU2_V23R25.bin
This should give you a series of messages as it unpacks the Flash into its component parts. The output file that we are interested in is the ramdisk.gz file. As the file extension indicates, the file is gzipped. We'll have to unzip it in order to work with it:
gzip -d ramdisk.gz
Now we have a file that can be directly mounted as a loop-back filesystem by Linux for manipulation. Create a mount point in your work directory like so:
Then mount the RAM disk with the following command which will likely require root privilege:
mount -o loop ramdisk nslu2
Now what we have is a copy of the NSLU2 RAM disk mounted on the nslu2 directory. You can explore the disk by cd'ing into the directory, but be very careful. Any modifications that you purposely or inadvertently make will be permanent when we are finished. If you mess something up, you may destroy your box.
Our approach will be to make as few changes as possible in order to minimize the chances of doing something wrong. We just want to add a little hook and do the real work in a script that will live on the hard drive. First we need to determine where to place our hook.
The path of execution inside the RAM disk is fairly standard for a Linux system and can be easily traced. Almost always on a UNIX-like system the first process to run is called "init" and it is the same for the NSLU2. In our case, some sleuthing shows that init calls etc/rc which calls etc/rc.sysinit which calls etc/rc.d/rc.1. In the rc.1 file we can see where all of the various daemons such as the web server are started. This looks like a reasonable place to add our hook since our new processes are similar to the others being started in this script.
So, take a deep breath, steady your hand, cd into the directory and edit the rc.1 file with a simple text editor. I added the hook just before the web server was started. Here's what my new line looks like followed by the web server line:
/bin/echo "Starting Local Hook:"; . /etc/rc.d/rc.hook;check_status /bin/echo "Starting WEB Server:"; . /etc/rc.d/rc.thttpd;check_status
Double check and then triple check your new line. I made the change by duplicating the web server line and modifying the "echo" portion and the rc.hook reference. Everything else should be the same.
Now we'll need to create the new script that we referenced in the rc.1 file. The script will live in the rc.d directory and will be called rc.hook. The idea of our new script will be to look for a hard-drive based script and if it exists, execute it. If it doesn't exist, we'll do nothing. No harm, no foul. The system will boot as it always did. Here's the script as I wrote it:
#!/bin/sh if [ -x /share/hdd/conf/rc.d/rc.custom ] then /share/hdd/conf/rc.d/rc.custom fi
The first line of the file is superfluous since we are "dotting" the file from rc.1, not executing it. I added the line to keep it consistent with the rest of the scripts in this directory. The next line checks for an executable script called rc.custom in our conf/rc.d directory on the hard drive. If this file exists, it is executed.
We'll have to be careful that actions we take in the rc.custom script do not block causing the rest of the boot sequence to hang. Once again, double check rc.hook very, very carefully. As a sanity check, execute the script on your development system just like the rc.1 script will, to verify that it contains no errors:
In the case of our development system it should not find the rc.custom script and will exit silently. When you are satisfied with the script and your change to rc.1 unmount the RAM disk like so:
cd ../../../ umount nslu2
We are done with our firmware modifications. If you want to do a complete double-check, you can mount the RAM disk file again, verify your changes are in it and then unmount it.