Новогоднее исследование ADSL-роутера на базе Linux — 0x7 — заключение



0x0 — введение
0x1 — разбираем 🙂
0x2 — знакомимся с программной частью
0x3 — формат прошивки
0x4 — модифицируем файловую систему
0x5 — пишем первую программу
0x6 — последовательный порт
0x7 — заключение

Вот и крайний день новогодних каникул… Как же быстро они пролетели! А сколько ещё нужно было сделать, исследовать, написать…
Но нельзя объять необъятное и нет сил, чтобы продлить время.
Честно признаюсь — я надолго «залип» при выборе названия этого шага. Заключение? Конец? А может всё-таки нет? Разумеется нет 🙂 Надеюсь, что это только начало. Скромный шажок в сторону настоящих встраиваемых систем и такого милого линукса 🙂 Надеюсь, впереди нас ждёт ещё масса удивительных открытий, прозрачного кода и светлого неба. Вот только когда?…

В этом заключении — я бегло опишу — что же я ещё пробовал сделать со своим подопытным ADSL-модемом ZTE ZXDSL831AII.

Завершив шаг про консольный кабель, — я ненадолго задумался — что же делать дальше. А дальше было следующее…

Я проверил возможность автозапуска своей программы:
достаточно прописать в файл
/etc/init.d/rcS
строчку вызова своего приложения 🙂

Затем, я всё-таки скачал три iso-образа Redhat Linux 9.0 (в этой ОС используется версия линуксового ядра 2.4)
ftp://archive.download.redhat.com/pub/redhat/linux/9/en/iso/i386/

установил на другую виртуальную машину (установка посложнее, чем у Ubuntu, но именно с дистрибутива Redhat Linux я начинал знакомство с ОС Linux (тогда это была 6-я версия Redhat))

затем скачал и установил набор для ADSL модема D-link 2500U:
ftp://ftp.dlink.ru/pub/ADSL/GPL_source_code/RU_DSL-2500U/RU_DSL-2500U_3-06-04-3C_GPL.tar.gz (100Mb)

установка toolchain-а прошла без ошибок:

затем так же без ошибок собрался дефолтный образ прошивки.
Для его сборки нужно в каталоге, в котором распаковались файлы RU_DSL-2500U_3-06-04-3C_consumer.tar.gz выполнить команду:

# make PROFILE=RU_DSL-2500U

в Redhat Linux 9.0 всё собирается на ура:

попытка выполнить данную команду в Ubuntu тоже запускает сборку, которая, однако, вываливается с ошибкой.
Похоже дело в версии используемого GCC и сопутствующих утилит.
В Redhat Linux 9.0 используется gcc 3.2.2-5
Но я всё же попробовал наладить сборку образа под Ubuntu:
скачал rpm-пакет gcc-3.2.2-5, преобразовал его в deb-пакет и он даже установился, но попытка сборки образа прошивки — так же сваливается с ошибками.

Далее, я начал копать в сторону управления светодиодами модема.
Сначала, начал смотреть в сторону модуля ядра и даже собрал Hello World-овский модуль 🙂

За основу я взял статью:
Введение в написание модулей ядра Linux.

и версию модуля, которая создаёт в /proc файл hello_world и возвращает соответствующую строчку при попытке чтения данного файла.

Файл в /proc — это один из простейших и наиболее популярных способов сделать связь между ядром и пользовательскими программами.
/proc — это псевдофайловая система, где операция чтения из файлов возвращает данные, синтезированные ядром, а данные, записываемые в файлы, читаются и оперируются ядром.
Т.о. /proc предоставляет простой, предопределенный путь передачи данных между ядром и пользовательским пространством с полезными инструментами и достаточной свободой действий модулей ядра.

код модуля khello.c :

//
//
// hello world via /proc
//
//

#include <linux/init.h>
#include <linux/module.h>
#include <linux/proc_fs.h> // включает поддержку работы с /proc.

static int
hello_read_proc(char *buffer, char **start, off_t offset, 
		int size, int *eof,
                void *data)
{
		char *hello_str = "Hello, world!\n";
        int len = strlen(hello_str);

        if (size < len)
            return EINVAL;

        if (offset != 0)
                return 0;

        strcpy(buffer, hello_str);
        /*
		* Signal EOF.
		*/
        *eof = 1;

        return len;

}

static int __init
hello_init(void)
{

        if (create_proc_read_entry("hello_world", 0, 
				NULL, hello_read_proc,
                                    NULL) == 0) {
                printk(KERN_ERR
				"Unable to register \"Hello, world!\" proc file\n");
                return -ENOMEM;
        }

        return 0;
}

module_init(hello_init);

static void __exit
hello_exit(void)
{
        remove_proc_entry("hello_world", NULL);
}

module_exit(hello_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Valerie Henson ");
MODULE_DESCRIPTION("\"Hello, world!\" minimal module");
MODULE_VERSION("proc");

Makefile:

obj-m := khello.o

all:
	$(MAKE) -C /lib/modules/`uname -r`/build/ M=`pwd` modules
insmod: all rmmod
	sudo insmod khello.ko
rmmod: 
	sudo rmmod khello|true
clean:
	$(MAKE) -C /lib/modules/`uname -r`/build/ M=`pwd` clean

Обратите внимание, на используемую команду uname -r - она возвращает текущую версию используемого ядра ОС.
В моём случае - Ubuntu 10.10 пишет:

2.6.35-22-generic

Соответсвенно, по пути /lib/modules/версия_ядра должны находиться исходные коды вашего ядра, чтобы компилятор мог подключить требуемые заголовочные файлы.

И ещё момент - данный модуль успешно компилируется и работает под ядрами версии 2.6, но под версиями ядра 2.4 оформление модуля должно быть другим (т.е. под той же Redhat Linux 9.0 - этот модуль не скомпилируется).

Выполнив команду make мы получим в папке с кодом массу файлов, самый важный из которых - это khello.ko
Попробуйте загрузить модуль:

# insmod khello.ko

и выполните чтение /proc/hello_world
работает? 🙂

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

# rmmod khello

Итак, модуль работает. Остаётся скомпилировать его для нашего модема.
Для этого достаточно всего-лишь изменить Makefile:

obj-m := khello.o

all:
	$(MAKE) -C /home/noonv/adsl/ M=`pwd` modules  

,где путь /home/noonv/adsl/ ,у меня ведёт к директории, в которой распакованы файлы для сборки образа прошивки.

Остаётся выполнить команду make

Однако, во время попытки компиляции (под Ubuntu) вывалилось три ошибки - не удавалось найти 3 файла
по пути
/usr/crossdev/mips/bin/

сначала, выполним команду создания нужных директорий с параметром -p ,чтобы создать все требуемые родительские каталоги:

# mkdir -p /usr/crossdev/mips/bin/

а далее нужно создать символьные ссылки на требуемые исполнительные файлы нашего кросс-компилятора командой ln -s:

ln -s /opt/toolchains/uclibc-crosstools_gcc-3.4.2_uclibc-20050502/bin/mips-linux-uclibc-gcc /usr/crossdev/mips/bin/mips-linux-gcc 

у меня потребовались:
mips-linux-gcc
mips-linux-ld
mips-linux-sstrip

# ls -asl /usr/crossdev/mips/bin/
total 20
4 drwxr-xr-x 2 root root 4096 2011-01-08 21:38 .
4 drwxr-xr-x 3 root root 4096 2011-01-08 21:33 ..
4 lrwxrwxrwx 1 root root   85 2011-01-08 21:36 mips-linux-gcc -> /opt/toolchains/uclibc-crosstools_gcc-3.4.2_uclibc-20050502/bin/mips-linux-uclibc-gcc
4 lrwxrwxrwx 1 root root   84 2011-01-08 21:36 mips-linux-ld -> /opt/toolchains/uclibc-crosstools_gcc-3.4.2_uclibc-20050502/bin/mips-linux-uclibc-ld
4 lrwxrwxrwx 1 root root   88 2011-01-08 21:38 mips-linux-sstrip -> /opt/toolchains/uclibc-crosstools_gcc-3.4.2_uclibc-20050502/bin/mips-linux-uclibc-sstrip

пробуем выполнить make

в итоге - в Ubuntu, make всё равно заканчивается с ошибкой, но модуль всё же создайтся.
(в RedHat - компиляция модуля происходит безо всяких проблем)

исходный код и файл модуля - khello.tar.gz

ну что же проверяем 🙂
сбросим файл модуля в наш традиционный user/bin и соберём корневую файловую систему -
sq6.zip

прошивка с модулем khello:
result-sq6-khello.zip

подключаемся

# cd /usr/bin
# ls -asl
   1 lrwxrwxrwx    1 0        0              17 tftp -> ../../bin/busybox
   1 lrwxrwxrwx    1 0        0              17 test -> ../../bin/busybox
   1 lrwxrwxrwx    1 0        0              17 tty -> ../../bin/busybox
   0 -rwxrwxrwx    1 0        0              37 mytest
   1 lrwxrwxrwx    1 0        0              17 expr -> ../../bin/busybox
   1 lrwxrwxrwx    1 0        0              17 logger -> ../../bin/busybox
   1 lrwxrwxrwx    1 0        0              17 [ -> ../../bin/busybox
   1 lrwxrwxrwx    1 0        0              17 ftpget -> ../../bin/busybox
   4 -rw-r--r--    1 0        0            3716 khello.ko

модуль есть - попробуем его загрузить

# insmod khello.ko
# cat /proc/modules
khello 992 0 - Live 0xc00c8000
ipt_multiport 672 0 - Live 0xc00c6000
ipt_REDIRECT 768 0 - Live 0xc00c4000
ip_nat_rtsp 4816 0 - Live 0xc009a000
ipt_state 544 1 - Live 0xc00c0000
ipt_MARK 704 0 - Live 0xc00be000
ipt_TCPMSS 2304 0 - Live 0xc00bc000
ip_conntrack_irc 68896 0 - Live 0xc00aa000
ipt_limit 896 0 - Live 0xc00a8000
ipt_connlimit 1696 0 - Live 0xc00a6000
ip_nat_ftp 2976 0 - Live 0xc00a4000
ipt_MASQUERADE 3280 0 - Live 0xc005d000
ip_conntrack_ftp 20608 1 ip_nat_ftp, Live 0xc009d000
ipt_mark 416 0 - Live 0xc0081000
ipt_FTOS 992 0 - Live 0xc007f000
ipt_RDNS 1152 1 - Live 0xc007d000
ipt_dns 640 1 - Live 0xc005f000
ip_nat_ipsec 46720 0 - Live 0xc008d000
ip_conntrack_ipsec 30640 0 - Live 0xc0074000
ip_nat_h323 5056 0 - Live 0xc0044000
ip_conntrack_h323 35280 1 ip_nat_h323, Live 0xc0083000
ip_conntrack_rtsp 73024 1 ip_nat_rtsp, Live 0xc0061000
ip_nat_pptp 2048 0 - Live 0xc005b000
ip_conntrack_pptp 3312 0 - Live 0xc0059000
ip_nat_gre 1280 0 - Live 0xc0057000
ip_conntrack_gre 2064 2 ip_nat_pptp,ip_conntrack_pptp, Live 0xc0055000
iptable_mangle 960 1 - Live 0xc0042000
iptable_nat 15632 9 ipt_REDIRECT,ip_nat_rtsp,ip_nat_ftp,ipt_MASQUERADE,ip_nat_ip
sec,ip_nat_h323,ip_nat_pptp,ip_nat_gre, Live 0xc0050000
ip_conntrack 29984 17 ipt_REDIRECT,ip_nat_rtsp,ipt_state,ip_conntrack_irc,ipt_co
nnlimit,ip_nat_ftp,ipt_MASQUERADE,ip_conntrack_ftp,ip_nat_ipsec,ip_conntrack_ips
ec,ip_nat_h323,ip_conntrack_h323,ip_conntrack_rtsp,ip_nat_pptp,ip_conntrack_pptp
,ip_conntrack_gre,iptable_nat, Live 0xc0047000
iptable_filter 928 1 - Live 0xc0037000
ip_tables 14144 15 ipt_multiport,ipt_REDIRECT,ipt_state,ipt_MARK,ipt_TCPMSS,ipt_
limit,ipt_connlimit,ipt_MASQUERADE,ipt_mark,ipt_FTOS,ipt_RDNS,ipt_dns,iptable_ma
ngle,iptable_nat,iptable_filter, Live 0xc0026000
bcm_usb 15984 0 - Live 0xc0008000
bcm_enet 25312 0 - Live 0xc002c000
br2684 66016 0 - Live 0xc000e000

# ls /proc
802          8            uptime       cpuinfo      net          iomem
676          7            meminfo      partitions   sysvipc      mtd
675          6            version      stat         sys          nvram
674          5            devices      interrupts   fs           var
481          4            filesystems  slabinfo     driver       hello_world
202          3            cmdline      buddyinfo    tty
44           2            locks        vmstat       bus
18           1            execdomains  diskstats    irq
10           self         mounts       modules      misc
9            loadavg      kmsg         kcore        ioports

модуль загрузился!
проверим его работу:

# cat /proc/hello_world
Hello, world!

нууууууууу! сууууууууууууупер! Вы как хотите, но это решительно здорово! 🙂

Зачем нам нужен модуль ядра?
А затем, что Linux не позволяет обратиться напрямую к регистрам. Либо через ядро, либо через драйвер. Поэтому, для общения с железом модема нам и нужен собственный драйвер, который предоставляет пользовательским приложениям стандартный интерфейс взаимодействия (каждый девайс - есть файл).

Итак, кажется что остаётся теперь наполнить модуль для работы с GPIO светодиодов.

GPIO (General Purpose Input/Output) - вывод (пин) чипа, чьим состоянием можно программно управлять.
Выводы GPIO не имеют специального назначения и по-умолчанию не используются.

GPIO, по сути, является портом ввода\вывода, который нужен для реализации различных функций.
В частности, для:
* включения/выключения индикаторов (например, светодиодов)
* управления некоторыми сигналами выбора внешнего чипа (сигналы chip_select, сокращенно CS)
* обслуживания прерываний с внешних устройств

документация gpio в ядре Linux: gpio.txt
Для работы с GPIO в модуль нужно подключить одноименный заголовочный файл:

#include <linux/gpio.h>

И тут я обнаружил, что в исходниках ядра, который идёт в RU_DSL-2500U_3-06-04-3C_GPL.tar.gz
его просто нет 🙁
Ну и ладно, решил я, - придётся пока отложить разбирательство с GPIO, к тому же я нашёл другой - более "простой" способ поработать со светодиодами 🙂

Я спросил себя - а как же прошивка работает со светодиодами - если не через gpio.h?
Полез смотреть исходники. Не знаю, всё ли правильно я понял в структуре исходников, но я нашёл вот такие интересные файлы:
bcmdrivers\opensource\include\bcm963xx\bcm_map_part.h

#ifndef __BCM_MAP_PART_H
#define __BCM_MAP_PART_H

#if defined(CONFIG_BCM96338)
#include <6338_map_part.h>
#endif
#if defined(CONFIG_BCM96348)
#include <6348_map_part.h>
#endif
#if defined(CONFIG_BCM96358)
#include <6358_map_part.h>
#endif

#endif

- т.е. в зависимости от заданного типа процессора - он подключает соответствующий заголовочный файл, в нашем случае 6338_map_part.h, который нашёлся здесь:
shared\opensource\include\bcm963xx\6338_map_part.h

и в котором есть вот такие интересные строчки:

#define PERF_BASE           0xfffe0000
#define TIMR_BASE           0xfffe0200 
#define UART_BASE           0xfffe0300
#define GPIO_BASE           0xfffe0400
#define SPI_BASE            0xfffe0c00 

...

typedef struct GpioControl {
  uint32        unused0;
  uint32        GPIODir;      /* bits 7:0 */
  uint32        unused1;
  uint32        GPIOio;       /* bits 7:0 */
  uint32        LEDCtrl;
#define         LED3_STROBE             0x08000000
#define         LED2_STROBE             0x04000000
#define         LED1_STROBE             0x02000000
#define         LED0_STROBE             0x01000000
#define         LED_TEST                0x00010000
#define         LED3_DISABLE_LINK_ACT   0x00008000
#define         LED2_DISABLE_LINK_ACT   0x00004000
#define         LED1_DISABLE_LINK_ACT   0x00002000
#define         LED0_DISABLE_LINK_ACT   0x00001000
#define         LED_INTERVAL_SET_MASK   0x00000f00
#define         LED_INTERVAL_SET_320MS  0x00000500
#define         LED_INTERVAL_SET_160MS  0x00000400
#define         LED_INTERVAL_SET_80MS   0x00000300
#define         LED_INTERVAL_SET_40MS   0x00000200
#define         LED_INTERVAL_SET_20MS   0x00000100
#define         LED3_ON                 0x00000080
#define         LED2_ON                 0x00000040
#define         LED1_ON                 0x00000020
#define         LED0_ON                 0x00000010
#define         LED3_ENABLE             0x00000008
#define         LED2_ENABLE             0x00000004
#define         LED1_ENABLE             0x00000002
#define         LED0_ENABLE             0x00000001
  uint32        SpiSlaveCfg;
#define         SPI_SLAVE_RESET         0x00010000
#define         SPI_RESTRICT            0x00000400
#define         SPI_DELAY_DISABLE       0x00000200
#define         SPI_PROBE_MUX_SEL_MASK  0x000001e0
#define         SPI_SER_ADDR_CFG_MASK   0x0000000c
#define         SPI_MODE                0x00000001
  uint32        vRegConfig;
} GpioControl;

#define GPIO ((volatile GpioControl * const) GPIO_BASE)

/* Number to mask conversion macro used for GPIODir and GPIOio */
#define GPIO_NUM_MAX_BITS_MASK          0x0f
#define GPIO_NUM_TO_MASK(X)             (1 << ((X) & GPIO_NUM_MAX_BITS_MASK)) 

а пример работы со светодиодами реализован в:
bcmdrivers\opensource\char\board\bcm963xx\impl1\bcm63xx_led.c
вот код одной из функций:

// turn led on and set the ledState
void ledOn(PLED_INFO pLed)
{
    if( pLed->ledMask )
    {
        if (pLed->ledSerial) {
#if defined(CONFIG_BCM96358)
            while (GPIO->SerialLedCtrl & SER_LED_BUSY);
            if( pLed->ledActiveLow )
                GPIO->SerialLed  &= ~pLed->ledMask;    // turn on the led
            else
                GPIO->SerialLed  |= pLed->ledMask;     // turn on the led
#endif
        }
        else {
            GPIO->GPIODir |= pLed->ledMask;         // turn on the direction bit in case was turned off by some one
            if( pLed->ledActiveLow )
                GPIO->GPIOio  &= ~pLed->ledMask;    // turn on the led
            else
                GPIO->GPIOio  |= pLed->ledMask;     // turn on the led
        }
        pLed->ledState = pLed->savedLedState = kLedStateOn;
    }
}

Выходит, что GPIO_BASE задаёт адрес памяти по которому доступны регистры GPIO.

Далее, я прочитал, что доступ просто получить через memory mapping (/dev/mem), причём - для этого не нужен специальный драйвер ядра!

Таким образом, через /dev/mem можно читать-писать любые адреса памяти или устройств (т.к. все устройства отображены на память).
Для работы используется функция mmap()

mmap - системный вызов Unix, позволяющий выполнить отображение файла или устройства на память. Является методом ввода/вывода через отображение файла на память

документация mmap

#include <sys/mman.h>

void *mmap(void *addr, size_t length, int prot, int flags,
                  int fd, off_t offset);

Для дальнейших исследований воспользуемся утилиткой memwrite - если программе передать один параметр, то она покажет данные по данному адресу, а если задать и второй параметр, то она запишет эти данные по адресу в первом параметре.

соберём утилиту и сбросим в наш usr/bin/
сразу утилита не запустилась - ругнулась, что функция atoll() не поддерживается (программа собирается, но на модеме запускаться отказывается)
заменим atoll() на atol() 🙂

исходник и программа - memwrite-blank.tar.gz

# cd usr/bin
# ls
tftp      memwrite  mytest    logger    ftpget
test      tty       expr      [
# ls -asl
   1 lrwxrwxrwx    1 0        0              17 tftp -> ../../bin/busybox
   0 lrwxrwxrwx    1 0        0              17 test -> ../../bin/busybox
   7 -rwxr-xr-x    1 0        0            7602 memwrite
   1 lrwxrwxrwx    1 0        0              17 tty -> ../../bin/busybox
   0 -rwxrwxrwx    1 0        0              37 mytest
   0 lrwxrwxrwx    1 0        0              17 expr -> ../../bin/busybox
   1 lrwxrwxrwx    1 0        0              17 logger -> ../../bin/busybox
   0 lrwxrwxrwx    1 0        0              17 [ -> ../../bin/busybox
   0 lrwxrwxrwx    1 0        0              17 ftpget -> ../../bin/busybox
# memwrite
pagesize = 4096
do_page_fault() #2: sending SIGSEGV to memwrite for invalid read access from
00000000 (epc == 2ab07a70, ra == 0040082c)
SIGSEGV

# memwrite 4096
pagesize = 4096
basepage=00001000, baseoff = 00000000, destaddr = 00001000
Old value:
addr[00001000]=0xFFFFFFF7 0xFFFFFFFA 0xFFFFFFED 0xFFFFFFFE

но до нужного адреса я что-то никак не мог добраться, пока не модифицировал memwrite так, что отсчёт нуля теперь начинался от

#define PERF_BASE           0xfffe0000

т.е. просто добавляю это значение к первому параметру:

base = PERF_BASE + atol(argv[1]);

модифицированный memwrite - исходник и программа специально для bcm6338 - memwrite-bcm6338.tar.gz

корневая файловая система - sq7.zip

файл прошивки - result-sq7-memwrite.zip

чтож, теперь посмотрим, что покажет модифицированная версия memwrite для bcm6338

# memwrite 1024
pagesize = 4096
basepage=FFFE0000, baseoff = 00000400, destaddr = FFFE0400
Old value:
addr[FFFE0400]=0x00 0x00 0x00 0x00

# memwrite 1032
pagesize = 4096
basepage=FFFE0000, baseoff = 00000408, destaddr = FFFE0408
Old value:
addr[FFFE0408]=0x00 0x00 0x00 0x00

# memwrite 1036
pagesize = 4096
basepage=FFFE0000, baseoff = 0000040C, destaddr = FFFE040C
Old value:
addr[FFFE040C]=0x00 0x00 0x00 0x7A

# memwrite 1040
pagesize = 4096
basepage=FFFE0000, baseoff = 00000410, destaddr = FFFE0410
Old value:
addr[FFFE0410]=0x00 0x00 0x03 0x00

# memwrite 1044
pagesize = 4096
basepage=FFFE0000, baseoff = 00000414, destaddr = FFFE0414
Old value:
addr[FFFE0414]=0x00 0x00 0x08 0x09

в общем, стал я разбираться и сумел поуправлять двумя светодиодами - Ethernet и USB:

USB led off, Ethernet led off (биты: 0000 0000) - светодиоды выключены

# memwrite 1024 0
pagesize = 4096
basepage=FFFE0000, baseoff = 00000400, destaddr = FFFE0400
Old value:
addr[FFFE0400]=0x00 0x00 0x00 0x00
New value:
addr[FFFE0420]=0x00 0x00 0x00 0x00

USB led on (биты: 0001 0000) - светодиод USB - горит

# memwrite 1024 16
pagesize = 4096
basepage=FFFE0000, baseoff = 00000400, destaddr = FFFE0400
Old value:
addr[FFFE0400]=0x00 0x00 0x00 0x00
New value:
addr[FFFE0420]=0x00 0x00 0x00 0x00

Ethernet led on (USB led off) (биты: 0010 0000) - светодид Ethernet горит, USB - выключен

# memwrite 1024 32
pagesize = 4096
basepage=FFFE0000, baseoff = 00000400, destaddr = FFFE0400
Old value:
addr[FFFE0400]=0x00 0x00 0x00 0x00
New value:
addr[FFFE0420]=0x00 0x00 0x00 0x00

Ethernet led on, USB led on (биты: 0011 0000) светодиоды Ethernet и USB - горят

# memwrite 1024 48
pagesize = 4096
basepage=FFFE0000, baseoff = 00000400, destaddr = FFFE0400
Old value:
addr[FFFE0400]=0x00 0x00 0x00 0x00
New value:
addr[FFFE0420]=0x00 0x00 0x00 0x00

Воооот. Другие светодиоды я пока не победил, но думаю принцип уже понятен 🙂
(кстати, если кто справится с остальными светодиодами - дайте знать 🙂

UPD по подсказке neitrino:
утилита управления светодиодами ledctrl отыскалась в исходниках:
RU_DSL-2500U_3-06-04-3C_consumer\userapps\opensource\busybox\miscutils\ledctrl.c
работает, общаясь с /dev/brcmboard через ioctl.

Кажется - пока всё 🙂
Вот стоит себе тихонько эта маленькая коробочка модема, но сколько нового, увлекательно-интересного она позволила узнать! Получилось настоящее погружение в мир встроенных систем и более близкое знакомство с линуксом.
Разумеется, отладочные платы в этом плане намного удобнее, но если модем/роутер уже есть или приобрести его проще (и дешевле), то и он вполне поддаётся настойчивости исследователя 🙂

Далее: Превращаем ADSL-модем в Ethernet-шилд
Исследование Wi-Fi-роутера TP-LINK TL-MR3020

Ссылки
Введение в написание модулей ядра Linux.
Writing device drivers in Linux: A brief tutorial
The Kernel Newbie Corner: Your First Loadable Kernel Module
mini2440 Работа с GPIO из Linux

Программы:
khello.tar.gz
memwrite-blank.tar.gz
memwrite-bcm6338.tar.gz

Автор: Vladimir (noonv), 2011

Эксклюзивно для robocraft.ru
копирование на другие ресурсы и публикация
без разрешения автора запрещены.


13 комментариев на «“Новогоднее исследование ADSL-роутера на базе Linux — 0x7 — заключение”»

    • Он пишет мол не найдено программы для запуска

    • если внимательнее присмотреться к примеру вызова в статье, то можно увидеть, что перед названием программы символы

      ./

      , которые указывают, что для запуска используется программа в текущей директории. Если Вы запускаете программу, которая находится где-то в другом месте, то нужно просто прописать абсолютный или относительный путь до неё:
      абсолютный путь: /usr/bin/mytest
      относительный путь: ../mytest — запустит программу из родительской директории.

      (это основы ОС Linux и если Вам это внове, то рекомендую сначала почитать соответствующие статьи)

    • Захожу в папку где лижит unsquashfs запускаю терминал и выполняю

      ./unsquashfs sqsh.bin

      пишет нет доступа, тогда запускаю из под рута

      sudo ./unsquashfs sqsh.bin

      и снова ошибка

      sudo: ./unsquashfs: command not found
      

    • Ну все вроде разобрался надо было

      /media/74ACA603ACA5BFCA/unsquashfs sqsh.bin
    • И еще один вопрос, когда я запаковываю прошивку и пишу

      ./mksquashfs squashfs-root/ sq3.bin -be  -no-fragments -noI -all-root -noappend -lzma -b 65536

      выскакивает ошибка

      libstdc++.so.5: cannot open shared object file: No such file or directory

      хотя у меня судя по всему установлен libstdc++ 6

    • советую очень внимательно перечитать статью. там содержатся ответы на все ваши вопросы.

    • Если вы про это

      sudo apt-get install libstdc++5

      то при установки пишет ошибку

      E: Не удалось найти пакет libstdc++5
      
    • проблема гуглится на счёт раз 😉 например так:

      Ubuntu 10.04 libstdc++5

      и, о чудо! мы узнаём, что в репозиториях Ubuntu 10.04 (и Ubuntu 9.10) этой библиотеки нет.
      А решить эту проблему можно просто сходив на packages.ubuntu.com и скачав требуемый deb-пакет вручную.

  1. нашел несколько модемов ZXDSL 831 II в них используется Flash с параллельным доступом и судя по даташиту на чип BOARDCOM bcm6338 вывод SPI остается свободным (незадействованным).
    Так как я в линуксе еще не силен настолько;
    1. как можно задействовать данный интерфейс.
    2. Можно ли реализовать USB host на данном модеме, т.е. конечно это реализуется программно, но как? Подключить к нему bluetooth или USB flash накопитель?

  2. У меня модем DLink 2500U H/W Ver:A1
    В папке бин есть программа ledctrl

    # ledctrl
    
    Usage: ledctrl led_name led_state
    
    Supported led names:
    Adsl
    Wireless
    Usb
    Hpna
    WanData
    PPP
    Voip
    Alarm
    
    Supported led states:
    Off
    On
    Fail
    BlinkOnce
    SlowBlinkContinues
    FastBlinkContinues
    #

    принимает два параметра, имя индикатора и какой режим установить.

    • о! спасибо! эта утилита отыскалась в исходниках:
      RU_DSL-2500U_3-06-04-3C_consumer\userapps\opensource\busybox\miscutils\ledctrl.c
      работает, общаясь с /dev/brcmboard через ioctl.

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

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
Робототехника
Будущее за бионическими роботами?
Нейронная сеть - введение