The Flash memory is partitioned into 4 "/dev/mtdblock" devices:
Depending on the type of data in an mtdblock, it may/may not have a header. "mtdblock0" is what the IXP42x boots from - there's no header (there's no code running yet that could interpret a header - headers make sense on 'data' partitions).
As Jim Buzbee has pointed out, "mtdblock1" starts with a 4-byte length, with the data immediately following that (offset 4 into the partition). The 4-byte length value reflects the length of the following data (doesn't include size of 4-byte length)
"mtdblock2" and "mtdblock3" appear to have 16-byte headers. They start with a 4-byte length, followed by 12 zeros. The length is the number of data bytes in the block excluding the 16 byte header - the data starts immediately after the header.
It's clear to me that the 4-byte length on "mtdblock3" represents the size of the upcoming data (after the 16-byte header). If you look at offset "length + 16" into "mtdblock3", you'll start to see zeros (and, there's a non-zero value just before that)
But, it's less clear on "mtdblock2". If you look at offset "length + 4", you start to see zeros (and there's a non-zero value just before that). It's possible that the image data in "mtdblock2" ends with zeros, and the definition of "length" here is the same as in "mtdblock3".
So, if we assume that the raw data stored in "mtdblock2" actually ends with some zeros, then we can interpret the "length" at the start to mean the length of the data immediately following the 16-byte header (just like "mtdblock3").
This can be confirmed by changing the bytes at the end and examining what RedBoot copies into memory at boot.
But, why would "mtdblock1" be different (4-byte length immediately followed by data - no 12-byte 'header pad')? One reason could be that LinkSys's own code is probably what reads/writes to "mtdblock1", whereas the (non-LinkSys) code in RedBoot is reading/writing "mtdblock2/3". I don't know - it's just speculation.
I believe that some of the 'header/trailer' stuff in 'splitnslu' is a little incorrect. The code update image from LinkSys is an exact 8MByte image of the entire flash (the 4 partitions concatenated together).
So, I think the "HEADER_OFFSET/HEADER_LENGTH" stuff is incorrect. "splitnslu" should do the following, I think:
- write first 262144 (0x40000) bytes to "Redboot"
- Grab 4-byte value @ offset 0x40000, use that as length of "SysConf" image. Write that many bytes from offset 0x40004 to "SysConf"
- Grab 4-byte value @ offset 0x60000 (262144+131072), use that as length of "vmlinuz" image. Write that many bytes from offset 0x60010 to "vmlinuz"
- Grab 4-byte value @ offset 0x160000 (262144+131072+1048576), use that as length of "ramdisk.gz" image. Write that many bytes from offset 0x160010 to "ramdisk.gz"
- Write 16 bytes from offset 0x7ffff0 to "SercommFlashTrailer"
To re-assemble (pack):
- allocate 8MByte image, memset to zero to be safe
- copy "Redboot" to offset 0 of allocated array
- copy "SysConf" to offset 0x40004 of allocated array, and store 4-byte length of "SysConf" @ offset 0x40000
- copy "vmlinuz" to offset 0x60010 of allocated array, and store 4-byte length of "vmlinuz" @ offset 0x60000
- copy "ramdisk.gz" to offset 0x160010 of allocated array, and store 4-byte length of "ramdisk.gz" @ offset 0x160000
- copy "SercommFlashTrailer" to offset 0x7ffff0 of allocated array
- write allocated array (8MBytes) to an output .bin file
NOTE: Because of the mis-interpretation of 'headers' in splitnslu, it's possible that things could be patched/put back together and actually work (unlike what author Brian Lantz found). For example, if the resulting modified "ramdisk.gz" image had a different (larger) byte size than the original (stored the 4-byte header just before it) then it wouldn't decompress correctly (truncated input to gunzip)