Портирование OpenWRT на новое устройство на примере ASUS DSL N12U

Что делать если вашего роутера не оказалось в списке поддерживаемых устройств OpenWRT? Конечно же сделать свой порт. Это можно сделать довольно быстро, если поддержка данной платформы уже реализована.
В этой статье я расскажу о процессе портирования прошивки в целом и о моем опыте портирования OpenWRT на ASUS DSL N12U.

Для начала следует определить насколько вообще это будет реально сделать. Для этого нужно узнать конфигурацию своего роутера. Тут достаточно много вариантов развития событий, например мой роутер показал все необходимые параметры в логе во время загрузки и в dmesg. Здесь следует точно определить объемы RAM, ROM, адреса партиций в mtd, и конечно же, на основе какого чипа сделан сам роутер.

Пример полного лога загрузки в моем случае есть здесь.

Я же отмечу наиболее важные для нас строки:

M25P128(20 20180000) (16384 Kbytes)
mtd .name = raspi, .size = 0x01000000 (16M) .erasesize = 0x00040000 (256K) .numeraseregions = 0
Creating 5 MTD partitions on "raspi":
0x00000000-0x01000000 : "ALL"
0x00000000-0x00040000 : "Bootloader"
0x00040000-0x00080000 : "Config"
0x00080000-0x000c0000 : "Factory"
0x000c0000-0x00800000 : "Kernel"


Здесь есть адреса партиций, есть объем и тип ROM памяти. Ура.

Так же есть объем памяти и указана конкретная платформа:

ASIC 3052F (DSL-N12U) (Port5<->None)
Total memory: 32 MBytes


Теперь нужно постараться обнаружить в таблице совместимых устройств наиболее похожий на Ваш роутер (главное это платформа), если там нет ничего подобного, то эта инструкция вам уже не поможет.

Мой роутер показал всю нужную информацию в dmesg и в консоль на порт. Но возможны другие варианты и направления поиска этой и другой полезной информации. Основные это GPL релиз прошивки (если он есть) и дамп прошивки роутера.

Так же нам потребуется подключиться к UART или Serial порту роутера, вероятность успеха затеи без этого подключения стремится к нулю. В качестве USB → UART можно использовать Arduino, но нужно помнить что в Arduino уровень сигнала 5V (а у большинства подобных устройств 3.3V). И нужно принять примеры по решению этой проблемы (как минимум добавить резистор на RX роутера).

Как обнаружить Serial порт это тема отдельной статьи, но обычно он есть практически у любого роутера или устройства с Linux внутри, в моем случае хватило просто гугла.

Теперь перейдем к сборке прошивки.

В системе должны быть как минимум установлены пакеты для сборки toolchain:

sudo apt-get install subversion git build-essential


Я проводил сборку на Debian 7, но в целом проблем на этом этапе быть не должно.

Клонируем репозиторий:

svn co svn://svn.openwrt.org/openwrt/trunk wrt


Запускаем рекурсивное обновление компонентов прошивки и тулчейна:

cd ~/wrt
./scripts/feeds update -a
./scripts/feeds install -a


Собираем тулчейн:

make prereq


Далее настраиваем прошивку на наиболее похожую поддерживаемую модель роутера

make menuconfig


Здесь нас интересуют поля:

Target System (Ralink RT288x/RT3xxx)  ---> 
Subtarget (RT3x5x/RT5350 based boards)  ---> 
Target Profile (Asus RT-N13U)  --->      


Я выбрал ASUS RT-N13U как наиболее похожий на мой роутер. На самом деле этот выбор не очень важен, так как разница в конкретных профилях минимальна, и мы поправим большую часть различий, главное правильно угадать платформу.

Более в menuconfig не нужно менять ничего.

При первой сборке также нужно собрать один раз тулчейн и утилиты:

make tools/install -j9 V=-1 && make toolchain/install -j9 V=-1


Сама сборка будет проходить при помощи

make -j9 V=-1


Результат будет лежать в bin/ramips

Ramips для описания устройства использует DTS которые лежат в target/linux/ramips/dts. Оригинальный DTS для ASUS DSL RT-N13U лежит тут.

Здесь мы заменим полностью блок cfi@1f000000 на наш, новый. Очевидно что это не то, что подходит для нашего ROM чипа. Быстрый поиск по соседним dts позволил обнаружить, что пример конфигурации должен выглядеть как-то так (это опять же блок для DTS):

palmbus@10000000 {
    spi@b00 {
        status = "okay";
        m25p80@0 {
            #address-cells = <1>;
            #size-cells = <1>;
            compatible = "m25p128";
            reg = <0 0>;
            linux,modalias = "m25p80", "m25p128";
            spi-max-frequency = <10000000>;

            partition@0 {
                label = "u-boot";
                reg = <0x0 0x30000>;
                read-only;
            };

            partition@30000 {
                label = "u-boot-env";
                reg = <0x30000 0x10000>;
                read-only;
            };

            factory: partition@40000 {
                label = "factory";
                reg = <0x40000 0x10000>;
                read-only;
            };

            partition@50000 {
                label = "firmware";
                reg = <0x50000 0xfb0000>;
            };
        };
    };
};


Надеясь на благополучный исход с минимумом работы я собрал прошивку для ASUS RT-N13U c внесенными изменениями и попытался её залить через recovery режим, но роутер отказался ее принимать с ошибкой
wrong product id.

На данный момент я не смог обнаружить, какой именно id он проверяет, поэтому установка прошивки без доступа к Serial порту невозможна.

Но роутер без проблем прошился во 2 режиме uboot

2: System Load Linux Kernel then write to Flash via TFTP.
 Warning!! Erase Linux in Flash then burn new one. Are you sure?(Y/N)
 Please Input new ones /or Ctrl-C to discard
        Input device IP (192.168.1.1) ==:192.168.0.2
        Input server IP (192.168.1.20) ==:192.168.0.20
        Input Linux Kernel filename () ==:fw.bin


В нем используется не TFTP сервер, как в recovery от ASUS, а роутер сам идет на указанный сервер и качает указанный файл.
С первой попытки роутер не запустился из-за невозможности примонтировать /, но лог загрузки показал что проблемы с ROM’ом

[    0.550000] m25p80 spi32766.0: found mr25h256, expected w25q128
[    0.560000] m25p80 spi32766.0: mr25h256 (32 Kbytes)
[    0.570000] 4 ofpart partitions found on MTD device spi32766.0
[    0.580000] Creating 4 MTD partitions on "spi32766.0":
[    0.590000] 0x000000000000-0x000000030000 : "u-boot"
[    0.600000] mtd: partition "u-boot" extends beyond the end of device "spi32766.0" -- size truncated to 0x8000
[    0.620000] 0x000000030000-0x000000040000 : "u-boot-env"
[    0.640000] mtd: partition "u-boot-env" is out of reach -- disabled
[    0.650000] 0x000000040000-0x000000050000 : "factory"
[    0.660000] mtd: partition "factory" is out of reach -- disabled
[    0.670000] 0x000000050000-0x000001000000 : "firmware"
[    0.680000] mtd: partition "firmware" is out of reach -- disabled


Быстрый взгляд в драйвер m25p80 в сочетании с подозрительной ошибкой

[    0.470000] rt2880-pinmux pinctrl: pin io3 already requested by pinctrl; cannot claim for 10000b00.spi
[    0.490000] rt2880-pinmux pinctrl: pin-3 (10000b00.spi) status -22
[    0.500000] rt2880-pinmux pinctrl: could not request pin 3 (io3) from group spi  on device rt2880-pinmux


позволил понять что проблема в некоем pinctr и похоже, что драйвер не может получить доступ к чипу (он определил его как самый примитивный с id 0). Как оказалось достаточно было стереть в DTS из секции pinctrl строчку с spi, именно она мешала драйверу m25p80 получить доступ к spi.

При следующей попытке загрузить устройство стало ясно, что ROM определился корректно, и дело осталось только за выставлением правильных адресов mtd партиций.

В итоге получилось так:

palmbus@10000000 {
    spi@b00 {
        status = "okay";
        m25p80@0 {
            #address-cells = <1>;
            #size-cells = <1>;
            compatible = "m25p128";
            reg = <0 0>;
            linux,modalias = "m25p80", "m25p128";
            spi-max-frequency = <10000000>;

            partition@0 {
                label = "u-boot";
                reg = <0x0 0x40000>;
                read-only;
            };

            partition@40000 {
                label = "u-boot-env";
                reg = <0x40000 0x40000>;
                read-only;
            };

            factory: partition@80000 {
                label = "factory";
                reg = <0x80000 0x40000>;
                read-only;
            };

            partition@c0000 {
                label = "firmware";
                reg = <0xc0000 0x740000>;
            };
        };
    };
};


Прошиваем, и внезапно все грузится, УРА!

Лог успешной загрузки устройства.

В итоге на этом все: роутер заработал на OpenWRT без каких либо проблем и сбоев. Естественно DSL не работает, но все остальное работает лучше чем на оригинальной прошивке. Даже индикация на корпусе заработала корректно.

Эта статья написана для того чтобы показать, что запуск OpenWRT на новом устройстве (при условии что платформа поддерживается) — это очень просто, надеюсь она поможет кому-нибудь сделать порт OpenWRT и на свое устройство.

© Habrahabr.ru