Новогоднее исследование ADSL-роутера на базе Linux — 0x3 — формат прошивки



0x0 — введение
0x1 — разбираем 🙂
0x2 — знакомимся с программной частью
0x3 — формат прошивки

Сегодня мы разберёмся, что представляет из себя файл прошивки нашего подопытного ADSL-модема!

Мы уже знаем, что на модеме крутится Linux с ядром версси 2.6 (cat /proc/version).

Так как наше исследование направлено не столько на этот модем, сколько на изучение возможностей встроенного линукса, то давайте сделаем небольшую остановку и посмотрим, как обычно загружается ОС Linux.

В нашем случае — в ADSL-модеме, — в роли загрузчика выступает CFE.

CFE ( Common Firmware Environment ) — это прошивка, разработанная фирмой Broadcom для своих 32- и 64-битных однокристальных (SOC) систем. Грубо говоря — это аналог BIOS-а у ПК.

исходный код CFE можно скачать с официального сайта Broadcom.

Файл прошивки, фактически, состоит из нескольких частей:
(Структуру можно подсмотреть в файле bcmTag.h из состава исходного кода прошивки)

1. 256-байтный заголовок, так называемый — bcmtag
2. CFE, Bootloader
3. образ корневой файловой системы (тип файловой системы: SquashFs)
4. сжатый образ ядра Linux

+---------------------------------+ 0x00000000
|                                 |
|         Broadcom Header         | фиксированный размер  bcmTag = 256 байт
|                                 |
+---------------------------------+ 0x00000100
|                                 |
|         CFE boot loader         | Размер в заголовке (cfeLen)
|                                 |
+---------------------------------+ bcmTag + cfeLen
|                                 |
|         SquashFS Root           | Размер в заголовке (rootfsLen)
|                                 |
+---------------------------------+ bcmTag +cfeLen + rootfsLen
|                                 |
|         Compressed kernel       | Размер в заголовке (kernelLen)
|                                 |
+---------------------------------+ 

Заголовок прошивки — первые 256 байт всех модемных прошивок на базе чипов Broadcom — имеют одинаковую структуру — т.н. Broadcom tag.
В них содержится информация о прошивке, адреса и размеры секций с загрузчиком, ядром и файловой системой, а также их контрольные суммы.

Дальнейшие значения приводятся на примере прошивки ZXDSL_831AIIV4.1.0a_E09_RU.

Откроем файл прошивки любым Hex-редактором, например, hiew.

Под Linux-ом можно использовать замечательную утилиту hexdump:

$ hexdump zxdsl.bin -n 256 -C
00000000  36 00 00 00 5a 58 44 53  4c 38 33 31 41 49 49 45  |6...ZXDSL831AIIE|
00000010  30 39 00 00 00 00 00 00  42 4f 54 48 00 00 00 00  |09......BOTH....|
00000020  00 00 00 00 00 00 36 33  33 38 00 00 39 36 33 33  |......6338..9633|
00000030  38 4c 2d 32 4d 2d 38 4d  00 00 00 00 31 00 31 38  |8L-2M-8M....1.18|
00000040  38 38 37 36 36 00 00 00  33 32 31 37 30 33 31 31  |88766...32170311|
00000050  36 38 00 00 36 33 33 32  34 00 00 00 00 00 33 32  |68..63324.....32|
00000060  31 37 30 39 36 39 36 30  00 00 31 32 37 33 38 35  |17096960..127385|
00000070  36 00 00 00 33 32 31 38  33 37 30 38 31 36 00 00  |6...3218370816..|
00000080  35 35 31 35 38 36 00 00  00 00 00 00 00 00 00 00  |551586..........|
00000090  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000000d0  00 00 00 00 00 00 00 00  db 8d 04 d5 22 d2 e8 4d  |............"..M|
000000e0  0b e6 b8 f4 00 00 00 00  00 00 00 00 4f ba 75 f1  |............O.u.|
000000f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................| 

структура заголовка bcmtag (256 байт):

№. название поля (описание) (длина в байтах) = значение в рассматриваемой прошивке

1. tagVersion (Header version) (4) = 6
2. signature_1 (Company info) (20) = ZXDSL831AIIE09
3. signature_2 (Version number) (14) = BOTH
4. chipId (Chip ID) (6) = 6338
5. boardId (Board ID) (16) = 96338L-2M-8M
6. bigEndian (1-big, 0 -little) (2) = 1
7. totalImageLen (Firmware image = CFE+Root FS+Kernel) (10) = 1888766 // должно совпасть с размер_файла_прошивки-256: 1889022-256 = 1888766
8. cfeAddress (CFE starting address, dec) (12) = 3217031168
9. cfeLen (CFE (Boot loader) size) (10) = 63324
10. rootfsAddress (Root filesystem address, dec)(12) = 3217096960
11. rootfsLen (Root filesystem (SquashFS) size) (10) = 1273856
12. kernelAddress (Kernel starting address, dec) (12) = 3218370816
13. kernelLen (Kernel (LZMA-compressed) size) (10) = 551586
14. dualImage (Dual image flag: 1-dual, 0-none) (2) = 0
15. inactiveLen (Image active flag: 1-inactive, 0-active) (2) = 0
16. reserved (Reserved for later use) (74) = 0
17. imageValidationToken (Image validation token (4 unsigned char CRC)) (20) = DB8D04D522D2E84D0BE6B8F40000000000000000
18. tagValidationToken (Validation token for tag (from signature_1 to end)) (20) = 4FBA75F100000000000000000000000000000000

примечание по рассчёту CRC:
17. первые 4 байта — это CRC образа cfe+sqsh+kernel (DB8D04D5)
(у D-linkов = cfe+sqsh+kernel+name)
следующие 4 байта — это CRC образа sqsh (22D2E84D)
следующие 4 байта — это CRC образа kernel (0BE6B8F4)

18. 4 байта CRC — это CRC заголовка без последних 20 байт (т.е. без поля самой контрольной суммы) (4FBA75F1)

если сложить все длины то, разумеется, должно получиться: 256 🙂

итого — файл прошивки — ZXDSL_831AIIV4.1.0a_E09_RU.bin (1889022 bytes):
1. bcm_tag (256 bytes)
2. cfe.img (63324 bytes)
3. sqsh.img (1273856 bytes)
4. kernel.img (551586 bytes)
(что в сумме даёт длину всей прошивки = 1889022)

у D-link-ов в самом конце ещё идёт поле названия модели
5. model_name (32 bytes)

код структуры для хранения BCMTAG и функция для рассчёта контрольной суммы (CRC):

#define TAG_LEN         256
#define TAG_VER_LEN     4
#define SIG_LEN         20
#define SIG_LEN_2       14   // Original second SIG = 20 is now devided into 14 for SIG_LEN_2 and 6 for CHIP_ID
#define CHIP_ID_LEN		6	
#define IMAGE_LEN       10
#define ADDRESS_LEN     12
#define FLAG_LEN        2
#define TOKEN_LEN       20
#define BOARD_ID_LEN    16
#define RESERVED_LEN    (TAG_LEN - TAG_VER_LEN - SIG_LEN - SIG_LEN_2 - CHIP_ID_LEN - BOARD_ID_LEN - \
                        (4*IMAGE_LEN) - (3*ADDRESS_LEN) - (3*FLAG_LEN) - (2*TOKEN_LEN))

typedef struct _FILE_TAG
{
    unsigned char tagVersion[TAG_VER_LEN];       // tag version.  Will be 2 here.
    unsigned char signiture_1[SIG_LEN];          // text line for company info
    unsigned char signiture_2[SIG_LEN_2];        // additional info (can be version number)
    unsigned char chipId[CHIP_ID_LEN];           // chip id 
    unsigned char boardId[BOARD_ID_LEN];         // board id
    unsigned char bigEndian[FLAG_LEN];           // if = 1 - big, = 0 - little endia of the host
    unsigned char totalImageLen[IMAGE_LEN];      // the sum of all the following length
    unsigned char cfeAddress[ADDRESS_LEN];       // if non zero, cfe starting address
    unsigned char cfeLen[IMAGE_LEN];             // if non zero, cfe size in clear ASCII text.
    unsigned char rootfsAddress[ADDRESS_LEN];    // if non zero, filesystem starting address
    unsigned char rootfsLen[IMAGE_LEN];          // if non zero, filesystem size in clear ASCII text.
    unsigned char kernelAddress[ADDRESS_LEN];    // if non zero, kernel starting address
    unsigned char kernelLen[IMAGE_LEN];          // if non zero, kernel size in clear ASCII text.
    unsigned char imageSequence[FLAG_LEN * 2];   // increments everytime an image is flashed
    unsigned char reserved[RESERVED_LEN];        // reserved for later use
    unsigned char imageValidationToken[TOKEN_LEN];// image validation token - can be crc, md5, sha;  for
                                                 // now will be 4 unsigned char crc
    unsigned char tagValidationToken[TOKEN_LEN]; // validation token for tag(from signiture_1 to end of // mageValidationToken)
} FILE_TAG, *PFILE_TAG;


#define CRC32_INIT_VALUE 0xffffffff /* Initial CRC32 checksum value */
#define CRC_LEN 4

static unsigned long Crc32_table[256] = {
    0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
    0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
    0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
    0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
    0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
    0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
    0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
    0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
    0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
    0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
    0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
    0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
    0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
    0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
    0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
    0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
    0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
    0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
    0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
    0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
    0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
    0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
    0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
    0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
    0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
    0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
    0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
    0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
    0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
    0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
    0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
    0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
    0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
    0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
    0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
    0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
    0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
    0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
    0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
    0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
    0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
    0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
    0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
    0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
    0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
    0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
    0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
    0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
    0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
    0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
    0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
    0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
    0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
    0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
    0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
    0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
    0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
    0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
    0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
    0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
    0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
    0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
    0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
    0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};


// Function Name: getCrc32
// Description  : caculate the CRC 32 of the given data.
// Parameters   : pdata - array of data.
//                size - number of input data bytes.
//                crc - either CRC32_INIT_VALUE or previous return value.
// Returns      : crc.
****************************************************************************/
uint32_t getCrc32(uint8_t *pdata, uint32_t size, uint32_t crc)
{
    while (size-- > 0)
    {
        crc = (crc >> 8) ^ Crc32_table[(crc ^ *pdata++) & 0xff];
    }

    return crc;
}

далее: 0x4 — модифицируем файловую систему

Ссылки
http://www.hiew.ru
http://wiki.openwrt.org/doc/techref/brcm63xx.imagetag

CFE:
http://en.wikipedia.org/wiki/Common_Firmware_Environment
http://www.linux-mips.org/wiki/Common_Firmware_Environment
http://oldwiki.openwrt.org/OpenWrtDocs(2f)Customizing(2f)Firmware(2f)CFE.html
http://www.melbournewireless.org.au/files/wrt54/cfe.pdf


0 комментариев на «“Новогоднее исследование ADSL-роутера на базе Linux — 0x3 — формат прошивки”»

  1. Доброго дня, уважаемый NOONV!
    Вы не поможите разобраться где в прошивках broadcom хранится дефолтные IP и MAC (если таковой вообще имеет место быть) адреса? а так же текущий и дефолтный конфиг?

    З.Ы. ваши статьи очень познавательны и актуальны, они мне очень помогли в понимании процесса перехода с прошивки HG520 на Dynalink для платформы RTA1025w.
    stream-tst.ru/component/option,com_fireboard/Itemid,29/func,view/id,26062/catid,9/limit,6/limitstart,72/

    • Добрый 🙂
      не встречал такого — возможно в конфигурационных файлах.

    • у openWrt все классно — они имаджи выкладывают) И все прямо вот отлично…
      Кстати вы только изучали ZTE роутеры?

    • только он у меня и был 🙂
      подумываю — может Wi-Fi-роутер прикупить 🙂

    • У меня вон завалялся DSL-2600U — думаю поиграться с ним да превратить в своеобразный «шилд» для Arduino 😀

  2. О прошивках на D-Link (DSL-2500U/DRU/D, RU_1.58):
    Входе экспериментов выяснилось, что model name необязательно 32 байта, у меня 24 байта. Выяснил обычным подсчетом: размер самой прошивки — (CFE + RootFS + Kernel + bcm).
    При расчете CRC не учитывается model name.
    ParseImage с внесенными изменениями

Добавить комментарий

Arduino

Что такое Arduino?
Зачем мне Arduino?
Начало работы с Arduino
Для начинающих ардуинщиков
Радиодетали (точка входа для начинающих ардуинщиков)
Первые шаги с Arduino

Разделы

  1. Преимуществ нет, за исключением читабельности: тип bool обычно имеет размер 1 байт, как и uint8_t. Думаю, компилятор в обоих случаях…

  2. Добрый день! Я недавно начал изучать программирование под STM32 и ваши уроки просто бесценны! Хотел узнать зачем использовать переменную типа…

3D-печать AI Android Arduino Bluetooth CraftDuino DIY IDE iRobot Kinect LEGO OpenCV Open Source Python Raspberry Pi RoboCraft ROS swarm ИК автоматизация андроид балансировать бионика версия видео военный датчик дрон интерфейс камера кибервесна конкурс манипулятор машинное обучение наше нейронная сеть подводный пылесос работа распознавание робот робототехника светодиод сервомашинка собака управление ходить шаг за шагом шаговый двигатель шилд

OpenCV
Робототехника
Будущее за бионическими роботами?
Нейронная сеть - введение