Всем доброго дня !
Как и обещал, подробно описываю процесс "раздевания/одевания" матрешки,
почему "матрешки", потому что структура фирмаря вложенная, на матрешку
похожа, пока все одежки снимешь/оденешь - употеешь.
Перед тем как начать, нам понадобятся GPL Source Codе (взять тут:
http://tsd.dlink.com.tw/),
из него нам надо:
- dcs933l/bin/addchecksum
- lzma - придется собрать из исходников: cd dcs933l/toolchain/lzma-4.32.0beta5;make
почему штатный не подходит, который есть в большинстве дистрибутивов скажу в процессе
-gen_init_cpio - тоже собираем:
cd dcs933l/RT288x_SDK/source/linux-2.6.21.x/usr
gcc -o gen_init_cpio gen_init_cpio.c
-dcs933l/RT288x_SDK/source/linux-2.6.21.x/usr/scripts/gen_initramfs_list.sh
-mkimage либо штатный, из пакета uboot-tools, либо сами соберите из SDK:
cd dc933l/RT288x_SDK/source/user/mkimage
make
Создадим каталог bin в какой-либо папке, сложим туда все это добро, для удобства.
$ ls bin
addchecksum gen_init_cpio gen_initramfs_list.sh lzma mkimage
Раздевать будем первую прошивку - dcs933l_v100_b14.bin
Приступим, внешняя одежка нашей мартешки состоит из двух половинок,
верней и нижней:
Uboot - бутлоадер, фиксированный размер UBOOT_SIZE = 0x50000
Kernel Image - собственно ядро, фиксированный размер KERNEL_SIZE = 0x7B0000
Надеюсь понятно, что эти размеры от версии к версии прошивки не меняются.
Бутлоадер нас не интересует, его мы трогать не будем, самое интересное
находится "ниже пояса", вот оттуда и начнем

Внешний осмотр, на всякий случай:
$ binwalk dcs933l_v100_b14.bin
DECIMAL HEX DESCRIPTION
-------------------------------------------------------------------------------------------------------------------
0 0x0 uImage header, header size: 64 bytes, header CRC: 0x9DBEC62, created: Wed Jan 23 10:40:42 2013, image size: 128448 bytes, Data Address: 0x80200000, Entry Point: 0x80200000, data CRC: 0x334BA6BE, OS: Linux, CPU: MIPS, image type: Standalone Program, compression type: none, image name: "SPI Flash Image"
99312 0x183F0 U-Boot boot loader reference
125639 0x1EAC7 LZMA compressed data, properties: 0x40, dictionary size: 65536 bytes, uncompressed size: 64 bytes
125663 0x1EADF LZMA compressed data, properties: 0x40, dictionary size: 65536 bytes, uncompressed size: 128 bytes
125687 0x1EAF7 LZMA compressed data, properties: 0x41, dictionary size: 65536 bytes, uncompressed size: 128 bytes
327680 0x50000 uImage header, header size: 64 bytes, header CRC: 0xC4713770, created: Wed Jan 23 10:40:37 2013, image size: 6356808 bytes, Data Address: 0x80000000, Entry Point: 0x8037E000, data CRC: 0x4ED2D8B7, OS: Linux, CPU: MIPS, image type: OS Kernel Image, compression type: lzma, image name: "Linux Kernel Image"
327744 0x50040 LZMA compressed data, properties: 0x5D, dictionary size: 33554432 bytes, uncompressed size: 8927701 bytes
binwalk не ошибся, вторая половина 327680==0x50000
достанем ее
dd if=dcs933l_v100_b14.bin iflag=skip_bytes skip=327680 of=part2
Да, забыл сказать, обе половинки записаны в формате uImage
$ file part2
part2: u-boot legacy uImage, Linux Kernel Image, Linux/MIPS, OS Kernel Image (lzma), 6356808 bytes, Wed Jan 23 10:40:37 2013, Load Address: 0x80000000, Entry Point: 0x8037E000, Header CRC: 0xC4713770, Data CRC: 0x4ED2D8B7
или
$ binwalk part2
DECIMAL HEX DESCRIPTION
-------------------------------------------------------------------------------------------------------------------
0 0x0 uImage header, header size: 64 bytes, header CRC: 0xC4713770, created: Wed Jan 23 10:40:37 2013, image size: 6356808 bytes, Data Address: 0x80000000, Entry Point: 0x8037E000, data CRC: 0x4ED2D8B7, OS: Linux, CPU: MIPS, image type: OS Kernel Image, compression type: lzma, image name: "Linux Kernel Image"
64 0x40 LZMA compressed data, properties: 0x5D, dictionary size: 33554432 bytes, uncompressed size: 8927701 bytes
$ mkimage -l part2
mkimage: ERROR: "part2" has corrupted data!
Не волнуйтесь, все в порядке, дело в том, что после uImage вторая половинка добита паддингом 0xFF,
дабы добрать фиксированный размер 0x7B0000.
Как мы видим из binwalk (или file) выше, размер блока данных uImage 6356808 байт,
плюс заголовок 64 байта, получаем полный размер uImage 6356872
Достанем его:
$ dd if=part2 bs=6356872 count=1 of=uImage
1+0 записей считано
1+0 записей написано
скопировано 6356872 байта (6,4 MB), 0,0634447 c, 100 MB/c
А теперь посмотрим:
$ file uImage
uImage: u-boot legacy uImage, Linux Kernel Image, Linux/MIPS, OS Kernel Image (lzma), 6356808 bytes, Wed Jan 23 10:40:37 2013, Load Address: 0x80000000, Entry Point: 0x8037E000, Header CRC: 0xC4713770, Data CRC: 0x4ED2D8B7
$ binwalk uImage
DECIMAL HEX DESCRIPTION
-------------------------------------------------------------------------------------------------------------------
0 0x0 uImage header, header size: 64 bytes, header CRC: 0xC4713770, created: Wed Jan 23 10:40:37 2013, image size: 6356808 bytes, Data Address: 0x80000000, Entry Point: 0x8037E000, data CRC: 0x4ED2D8B7, OS: Linux, CPU: MIPS, image type: OS Kernel Image, compression type: lzma, image name: "Linux Kernel Image"
64 0x40 LZMA compressed data, properties: 0x5D, dictionary size: 33554432 bytes, uncompressed size: 8927701 bytes
$ bin/mkimage -l uImage
Image Name: Linux Kernel Image
Created: Wed Jan 23 10:40:37 2013
Image Type: MIPS Linux Kernel Image (lzma compressed)
Data Size: 6356808 Bytes = 6207.82 kB = 6.06 MB
Load Address: 0x80000000
Entry Point: 0x8037E000
Kernel Size: 0x00000000
Ну во, все в порядке, запомните Load Address и Entry Point, нужны при "одевании".
Внутри uImage ядро то и лежит, зажатое lzma.
Снимем еще одну одежку (срезаем заголовок uImage):
$ dd if=./uImage iflag=skip_bytes skip=64 of=zImage.lzma
12415+1 записей считано
12415+1 записей написано
скопировано 6356808 байт (6,4 MB), 0,0342254 c, 186 MB/c
$ lzma -t zImage.lzma - не ругнулся, значит все OK
Еще одну одежку снимаем:
$ lzcat zImage.lzma > zImage
Ну во, теперь имеем нормальное linux ядро, к которому в конце, совершенно штатно
приклеен ramfs (он то нас и интересует).
Поехали дальше:
$ binwalk zImage
DECIMAL HEX DESCRIPTION
-------------------------------------------------------------------------------------------------------------------
3211340 0x31004C Linux kernel version "2.6.21 (
andy@ipcam-linux.alphanetworks.com) (gcc version 3.4.2)etworks.com) (gcc version 3.4.2) #1319 Wed Jan 23 14:40:30 CST "
3355636 0x3333F4 Copyright string: " (c) 2011 Alpha Networks Inc.***** free audio buffer error 1 "
3620355 0x373E03 LZMA compressed data, properties: 0x40, dictionary size: 65536 bytes, uncompressed size: 64 bytes
3620379 0x373E1B LZMA compressed data, properties: 0x40, dictionary size: 65536 bytes, uncompressed size: 128 bytes
3620403 0x373E33 LZMA compressed data, properties: 0x41, dictionary size: 65536 bytes, uncompressed size: 128 bytes
3796992 0x39F000 LZMA compressed data, properties: 0x5D, dictionary size: 1048576 bytes, uncompressed size: 16344576 bytes
в середине binwalk ошибся, конечно, а вот последняя строка правильная (по размеру понять можно).
3796992 - смещение ramfs, достанем его:
$ dd if=zImage iflag=skip_bytes skip=3796992 of=ramfs.cpio.lzma
10020+1 записей считано
10020+1 записей написано
скопировано 5130709 байт (5,1 MB), 0,0279981 c, 183 MB/c
Чуть-чуть осталось, уже нижнее белье пошло
Ramfs стандартно - это cpio архив, зажатый:
$ lzcat ramfs.cpio.lzma > ramfs.cpio
Последний шаг в раздевании придется рутом сделать, дабы сохранить UID у файлов, не знаю
насколько они важны, но на всякий случай:
$ mkdir ramfs;su root -c "cd ramfs;cpio -idmv --no-absolute-filenames < ../ramfs.cpio"
--no-absolute-filenames - без этого не запускайте, перетрет системные, т.к. в архиве все начинается с "/".
Ну вот, имеем раздетой нашу матрешку (каждый имеет в меру своей испорченности

)
Поматросили маленько, не бросать же ее в таком виде, давайте "одевать" будем

В обратном порядке.
Cобираем cpio.В штатном cpio не на нашел как из относительного пути
сделать абсолютный при сборке архива, а в исходном архиве они все с "/" начинаются, не знаю насколько
это важно, по документации вроде как не возбраняется, но ломать это правило не стал, с chroot тоже возиться лень было,
поэтому взял тулзы из SDK.
сначала список архива:
$ su root -c "bin/gen_initramfs_list.sh ramfs > file.list"
теперь сам архив:
$ su root -c "bin/gen_init_cpio file.list > my_ramfs.cpio"
$ su root -c "chown XXX:XXX my_ramfs.cpio "
Заглядываем внутрь - все пути с "/" начинаются, UID и права на месте
Далее:
$ bin/lzma -z -k -f -9 my_ramfs.cpio
В начале я упоминал, почему не штатный lzma, потому, что штатный более свежей
версии, он пишет сигнатуру, которую binwalk потом распознать не может,
а вдруг нам снова раздевать захочется

$ file my_ramfs.cpio.lzma
my_ramfs.cpio.lzma: data
Это нормально, а вот если штатным зажать, то file скажет, что это архив.
Теперь давайте приклеем сей ramfs к ядру, как и было:
Смотрим в исходный:
$ binwalk zImage
DECIMAL HEX DESCRIPTION
-------------------------------------------------------------------------------------------------------------------
3211340 0x31004C Linux kernel version "2.6.21 (
andy@ipcam-linux.alphanetworks.com) (gcc version 3.4.2)etworks.com) (gcc version 3.4.2) #1319 Wed Jan 23 14:40:30 CST "
3355636 0x3333F4 Copyright string: " (c) 2011 Alpha Networks Inc.***** free audio buffer error 1 "
3620355 0x373E03 LZMA compressed data, properties: 0x40, dictionary size: 65536 bytes, uncompressed size: 64 bytes
3620379 0x373E1B LZMA compressed data, properties: 0x40, dictionary size: 65536 bytes, uncompressed size: 128 bytes
3620403 0x373E33 LZMA compressed data, properties: 0x41, dictionary size: 65536 bytes, uncompressed size: 128 bytes
3796992 0x39F000 LZMA compressed data, properties: 0x5D, dictionary size: 1048576 bytes, uncompressed size: 16344576 bytes
3796992 - смещение куда его положить надо
Откусываем kernel образ:
$ dd if=zImage bs=3796992 count=1 of=my_zImage
1+0 записей считано
1+0 записей написано
скопировано 3796992 байта (3,8 MB), 0,00848172 c, 448 MB/c
Приклеиваем ramfs:
$ cat my_ramfs.cpio.lzma >> my_zImage
Проверочка:
$ binwalk my_zImage
DECIMAL HEX DESCRIPTION
-------------------------------------------------------------------------------------------------------------------
3211340 0x31004C Linux kernel version "2.6.21 (
andy@ipcam-linux.alphanetworks.com) (gcc version 3.4.2)etworks.com) (gcc version 3.4.2) #1319 Wed Jan 23 14:40:30 CST "
3355636 0x3333F4 Copyright string: " (c) 2011 Alpha Networks Inc.***** free audio buffer error 1 "
3620355 0x373E03 LZMA compressed data, properties: 0x40, dictionary size: 65536 bytes, uncompressed size: 64 bytes
3620379 0x373E1B LZMA compressed data, properties: 0x40, dictionary size: 65536 bytes, uncompressed size: 128 bytes
3620403 0x373E33 LZMA compressed data, properties: 0x41, dictionary size: 65536 bytes, uncompressed size: 128 bytes
3796992 0x39F000 LZMA compressed data, properties: 0x5D, dictionary size: 33554432 bytes, uncompressed size: 16344576 bytes
16344576 - Это cpio image size
$ ls -ln my_ramfs.cpio
-rw-rw-r-- 1 1000 1000 16344576 янв. 14 22:18 my_ramfs.cpio
Все четко, совпадает.
Одеваем дальше:
$ bin/lzma -z -k -f -9 my_zImage
Теперь сей образ надо вложить в структуру uImage. Вспоминаем цифири Load Address и Entry Point, который запомнили
в начале, даем команду:
$ bin/mkimage -A mips -O linux -T kernel -C lzma -a 80000000 -e 8037E000 -n "Linux Kernel Image" -d my_zImage.lzma my_uImage
Image Name: Linux Kernel Image
Created: Tue Jan 14 22:35:29 2014
Image Type: MIPS Linux Kernel Image (lzma compressed)
Data Size: 6157708 Bytes = 6013.39 kB = 5.87 MB
Load Address: 0x80000000
Entry Point: 0x8037E000
Kernel Size: 0x00000000
Смотрим что получилось:
$ file my_uImage
my_uImage: u-boot legacy uImage, Linux Kernel Image, Linux/MIPS, OS Kernel Image (lzma), 6157708 bytes, Tue Jan 14 22:35:29 2014, Load Address: 0x80000000, Entry Point: 0x8037E000, Header CRC: 0xAFA99227, Data CRC: 0xFBE8FA4E
[dennis@htpc my-1.00b14]$ binwalk my_uImage
DECIMAL HEX DESCRIPTION
-------------------------------------------------------------------------------------------------------------------
0 0x0 uImage header, header size: 64 bytes, header CRC: 0xAFA99227, created: Tue Jan 14 22:35:29 2014, image size: 6157708 bytes, Data Address: 0x80000000, Entry Point: 0x8037E000, data CRC: 0xFBE8FA4E, OS: Linux, CPU: MIPS, image type: OS Kernel Image, compression type: lzma, image name: "Linux Kernel Image"
64 0x40 LZMA compressed data, properties: 0x5D, dictionary size: 33554432 bytes, uncompressed size: 8731174 bytes
Уххх ..., осталось только образ фирмваря склеить ...
Как я говорил, он из двух половинок состоит:
UBOOT_SIZE = 0x50000
KERNEL_SIZE = 0x7B0000
Верхнюю мы не трогаем, это бутлоадер (327680 == 0x50000)
$ dd if=dcs933l_v100_b14.bin bs=327680 count=1 of=my_firmware.bin
1+0 записей считано
1+0 записей написано
скопировано 327680 байт (328 kB), 0,000830688 c, 394 MB/c
А теперь добавляем наш uImage (0x7B0000 == 8060928)
$ cat my_uImage >> my_firmware.bin
Немного арифметики, фирмварь надо добить до размера 8388608 (327680+8060928)
паттерном 0xFF
$ ls -ln my_uImage
-rw-rw-r-- 1 1000 1000 6157772 янв. 14 22:35 my_uImage
$ echo "8060928-6157772"|bc
1903156 - это размер padding-а
$ dd if=/dev/zero count=1 bs=1903156 2>/dev/null |tr \\000 \\377 >> my_firmware.bin
И последний шаг - контрольная сумма:
$ bin/addchecksum my_firmware.bin
Смотрим что получилось:
$ ls -ln dcs933l_v100_b14.bin my_firmware.bin
-rw-r--r-- 1 1000 1000 8388608 янв. 23 2013 dcs933l_v100_b14.bin
-rw-rw-r-- 1 1000 1000 8388608 янв. 14 22:51 my_firmware.bin
$ binwalk my_firmware.bin
DECIMAL HEX DESCRIPTION
-------------------------------------------------------------------------------------------------------------------
0 0x0 uImage header, header size: 64 bytes, header CRC: 0x9DBEC62, created: Wed Jan 23 10:40:42 2013, image size: 128448 bytes, Data Address: 0x80200000, Entry Point: 0x80200000, data CRC: 0x334BA6BE, OS: Linux, CPU: MIPS, image type: Standalone Program, compression type: none, image name: "SPI Flash Image"
99312 0x183F0 U-Boot boot loader reference
125639 0x1EAC7 LZMA compressed data, properties: 0x40, dictionary size: 65536 bytes, uncompressed size: 64 bytes
125663 0x1EADF LZMA compressed data, properties: 0x40, dictionary size: 65536 bytes, uncompressed size: 128 bytes
125687 0x1EAF7 LZMA compressed data, properties: 0x41, dictionary size: 65536 bytes, uncompressed size: 128 bytes
327680 0x50000 uImage header, header size: 64 bytes, header CRC: 0xAFA99227, created: Tue Jan 14 22:35:29 2014, image size: 6157708 bytes, Data Address: 0x80000000, Entry Point: 0x8037E000, data CRC: 0xFBE8FA4E, OS: Linux, CPU: MIPS, image type: OS Kernel Image, compression type: lzma, image name: "Linux Kernel Image"
327744 0x50040 LZMA compressed data, properties: 0x5D, dictionary size: 33554432 bytes, uncompressed size: 8731174 bytes
Все.
А дальше - сами знаете что делать !
