вторник, 15 января 2008 г.

arm-linux toolchain (рецепт)

Вот наконец оно заработало.

binutils-2.18 не требует патчей

gcc-4.2.2 требует gcc-arm-softfloat.patch. В отличии от остальных - этот патч известный, выдернул из buildroot наверное, не помню точно, хотя и в интернете можно найти. Лечит отсутствие -lfloat.

uClibc-0.9.29 требует uClibc-msync-redeclaration.patch.

linux kernel headers я взял свои текущие (2.6.11.8-hsc0-ea). Не знаю точно, насколько сильно конфигурация ядра влияет на устанавливаемые заголовки, но предпочел взять и ядро и конфигурацию свою. так вернее.

elf2flt-src-20060506.tar.bz2. --disable-got-check не помог elf2flt генерировать файлы правильно, поэтому прищлось вырезать все лишнее. После наложения патча elf2flt-nogot.patch elf2flt будет генерировать исключительно Load-to-ram бинари.

На всякий случай приложу sha1sum исходных архивов.
fdec92e9dfc6c32155869f3910f47041c78e2277 binutils-2.18.tar.bz2
b7046a127b91fd58b5680e1c8fcdab2bd6d9cc5a elf2flt-nogot.patch
61b2133609e44e470d07ee66eb4d7ccfcf33e96e elf2flt-src-20060506.tar.bz2
dcf2139e0f318850d475a6af3dcd5f176f1acb0e gcc-4.2.2.tar.bz2
f2df77f26528fd18466538d0cb2cf5e93d0527f3 gcc-arm-softfloat.patch
1c5a36dc2cfa58b41db413190e45675c44ca4691 uClibc-0.9.29.tar.bz2
7508ee533004dec56070fbe221ccfea1be60389b uClibc-msync-redeclaration.patch


Порядок сборки следующий:
  1. binutils:
    ./configure --prefix=$(PREFIX) --with-sysroot=${PREFIX} --target=arm-linux --disable-nls
    make
    make install

    После сборки исходники не удалять, они еще понадобяться для elf2flt.

  2. gcc (стадия первая):
    ./configure --prefix=$(PREFIX) --target=arm-linux --with-sysroot=${PREFIX} --with-float=soft --with-arch=armv4t --with-tune=arm7tdmi --with-newlib --enable-languages=c --enable-threads=no --disable-shared --disable-nls --disable-multilib --disable-tls --disable-mudflap
    make
    make install

    После сборки и установки binutils в пути (PATH) необходимо добавить $(PREFIX)/bin.

  3. заголовки ядра:
    • Если у вас ядро свежее 2.6.18, то можно сделать так:
      make ARCH=arm CROSS_COMPILE=arm-linux- headers_install INSTALL_HDR_PATH=$(PREFIX)/usr

    • В противном случае (более старое ядро) придется мучаться:
      make ARCH=arm CROSS_COMPILE=arm-linux- prepare
      mkdir -p $(PREFIX)/usr/include
      cp -a ./include/linux $(PREFIX)/usr/include/linux
      cp -a ./include/asm-arm $(PREFIX)/usr/include/asm
      cp -a ./include/asm-generic $(PREFIX)/usr/include/asm-generic


  4. uClibc:
    make CROSS=arm-linux- menuconfig
    make CROSS=arm-linux- KERNEL_HEADERS=$(PREFIX)/usr/include
    make CROSS=arm-linux- install PREFIX=$(PREFIX)/ RUNTIME_PREFIX= DEVEL_PREFIX=usr/ KERNEL_HEADERS=$(PREFIX)/usr/include


  5. gcc (финальная стадия):
    ./configure --prefix=$(PREFIX) --target=arm-linux --with-sysroot=${PREFIX} --with-float=soft --with-arch=armv4t --with-tune=arm7tdmi --enable-languages=c --enable-threads=posix --disable-shared --disable-nls --disable-multilib --disable-mudflap
    make
    make install


  6. elf2flt:
    ./configure --prefix=$(PREFIX) --target=arm-linux --with-binutils-include-dir=../binutils/include/ --with-bfd-include-dir=../binutils/bfd/ --with-libbfd=../binutils/bfd/libbfd.a --disable-got-check
    make
    make install


И на последок самое главное - привожу Makefile, которым все собирается. Я думаю никому не составит труда заточить его под свои нужды или переработать в шелл скрипт. Мне Makefile удобнее.

PS: Я еще не разобрался как заставить работать init из busybox, но это уже вопрос времени. Шеллы всякие в качестве инитов или скрипты у меня прекрасно запускаются. Можно жить.

О, майн GOT...

Мне удалось собрать Hello world... и даже simpleinit из uClinux...

А вот Busybox пока не удалось, и я даже знаю почему.
$ ~/arm-linux/bin/arm-linux-flthdr busybox
busybox
Magic: bFLT
Rev: 4
Build Date: Tue Jan 15 13:48:30 2008
Entry: 0x6c0
Data Start: 0x3f5a0
Data End: 0x46540
BSS End: 0x590c0
Stack Size: 0x4e20
Reloc Start: 0x46540
Reloc Count: 0x12a
Flags: 0x2 ( Has-PIC-GOT )


В то время, как
$ ~/arm-linux/bin/arm-linux-flthdr init
init
Magic: bFLT
Rev: 4
Build Date: Mon Jan 14 17:42:41 2008
Entry: 0x50
Data Start: 0x6980
Data End: 0x7620
BSS End: 0x19070
Stack Size: 0x1000
Reloc Start: 0x7620
Reloc Count: 0xe5
Flags: 0x1 ( Load-to-Ram )


Насколько удалось выяснить, PIC-GOT это такой позиционно независимый бинарник, который может запускаться с любого места памяти. Это как-то связано с ключевым словом XIP (eXecute In Place), которое используется в ядре. У этого бинарника тоже есть релоки, но они какие-то особенные.

Кроме того удалось выяснить, что такой бинарник можно получить генерируя позиционно независимый код (-fpic). Странно только то, что я нигде в бусибоксе не указывал такой ерунды, да и нет там такой опции.

Но если гора не идет к Магомету, значит надо отучить elf2flt генерировать PIC_GOT. После долгих поисков в интернете обнаружил опцию configure у elf2flt, которую сначала не приметил, наверное потому что не знал что такое got.
elf2flt $ ./configure --help
...
Optional Features:
...
--disable-got-check - disable check for GOT (needed on H8)
...

Ага, это нужно не только H8, но и мне! Посмотрим что из этого выйдет. Но как приятно было увидеть это:
## Starting application at 0xA0008000 ...
Linux version 2.6.11.8-hsc0 (dron@mdf2007) (gcc version 4.2.2) #2 Tue Jan 15 10:14:59 MSK 2008
CPU: Philips-lpc24xx [24000000] (ARMv3)
...
Freeing init memory: 80K
Hello ARM!

понедельник, 14 января 2008 г.

И снова toolchain...

Снапшот от buildroot, как оказалось, кривой. elf2flt, входящая в его состав ругается на отсутствие секции .text, и я не знаю че с этим поделать. Взял elf2flt из состава devkitPro, с ним тулчейн генерирует правильные флэтовые бинари. Но несмотря на успешную сборку тулчейна (в состав которого вошли gcc-4.2.2, binutils-2.18 и uClibc-9.29), и вполне работающее ядро, дальнейших успехов что-то не наблюдается.

## Starting application at 0xA0008000 ...
Linux version 2.6.11.8-hsc0 (dron@mdf2007) (gcc version 4.2.2) #2 Mon Jan 14 17:53:46 MSK 2008

То ли слишком старое ядро имеет несоответствующую текущему положению дел поддержку flat, то ли компилятор генерирует не совсем корректные бинари (хотя я вроде бы указываю arm7tdmi). Обновлять ядро я пока не хочу, это не слишком просто, учитывая тот факт, что на это ядро наложены архитектуры от EmbeddedArtists. Хочу сперва добиться работоспособности.

Но моя проблема еще в том, что даже оригинальный uСlinux (от EmbeddedArtists) на собранном мною тулчейне не работает...

Freeing init memory: 80K
BINFMT_FLAT: reloc outside program 0x14690000 (0 - 0x19034/0x6940), killing init!
BINFMT_FLAT: reloc outside program 0x14690000 (0 - 0x19034/0x6940), killing init!
BINFMT_FLAT: reloc outside program 0xffffffff (0 - 0x4b864/0x2c660), killing sh!

А мои бинари и того хуже...

Freeing init memory: 80K
Unhandled fault: alignment exception (0x5000101) at 0x0000012c
Unhandled fault: alignment exception (0x5000101) at 0x0000012c
Unhandled fault: alignment exception (0x5000101) at 0x0000012c

Когда я разберусь со всеми этими глюками - я обязательно опишу сценарий сборки тулчейна для ARM, ибо на своем опыте убедился насколько востребована эта тема.

пятница, 11 января 2008 г.

arm toolchain

Не так то просто собрать свой тулчейн.

Поскольку стандартная прошивка LPC писалась под старый uclinux, то мне просто необходимо было иметь binutils с elf2flt, потому что там основной формат flat. К тому же мне абсолютно не нужен был glibc.

Долго я с этим возился, и как вижу - я не одинок в этом...
чего мне пока с последними версиями gcc проделать на удалось - под ARM собираться не хочет, binutils собираются, bootstrap compiler тоже, а сборка libc - сваливается... или это сборка полноценного компилера? не помню уже... после десятка безуспешных попыток я это дело отложил на неопределенное время.

Начнем с того, что стандартные средства gentoo (crossdev) хоть и предполагают, но не могут собрать toolchain с uClibc. А поддержка elf2flt видимо когда-то и была, но ныне включается только ковырянием в ебилдах.

Стандартные средства uClinux имеют волосатую дату 14 марта 2003 и включают в себя старый binutils который не в состоянии собрать нынешнее ядро. С неофициальным тулчейном ситуация не намного лучше, ибо он базируется на gcc-3.4.0, в то время как <gcc-3.4.1 имел баг с компиляцией на arm, что также дает полную неюзабельность данных пакетов. А еще я убил бы того, кто придумал закатывать архивы в .sh! Моя система имеет локаль по умолчанию - UTF8. Похоже, что именно это не дает скрипту нормально отрабатывать ибо UTF8 пребразование превращает архив непонятно во что. Пришлось выцеплять архив из .sh файла при помощи dd, после чего их стало возможным раскрутить, но всеравно бестолку.

Есть предположение, что разработчики uClinux забросили эти инструменты в пользу buildroot, который, в отличи от OpenEmbedded, заточен на uClinux. И если повезет, то можно найти снапшот (стабильного релиза так и не нашел), который, после небольшой доработки напильником сможет собрать корректный тулчейн. Так я и поступил, ибо то, что пытаюсь собрать я сам, упорно не хочет работать ругаясь то на отсутствие либ, то на некорректность бинарей.

Вообще я наверное что-то не понимаю, но мне кажется что с кросскомпиляцией GNU'шники что-то намудрили.

PS: А еще почему-то когда я делаю выравнивание вправо у меня сразу меняется межстрочный интервал. глюка какая-то.

суббота, 5 января 2008 г.

mencoder bug???

С сентября меня мучает одна проблема. Мой mencoder почему-то разучился корректно кодировать видео в два прохода. Что я только не делал, пересобирал mplayer с различными USE-флагами (пытался отключать оптимизации всякие), различные опции кодирования менял. Однопроходное кодирование работает корректно, а после второго прохода видео корректно отображает кажется только сам mplayer.

Многочисленные дальнейшие эксперименты показали что кодирование через ffmpeg дает точно такой-же некорректный результат. Вместо 23 минут видео почти все плейеры показывают около 4 часов. Формат звуковой дорожки абсолютно не при чем, менял форматы, но даже один видеопоток отображается некорректно. Так же пытался менять и контейнер (вдруг это проблема avi?), но mpeg точно так же врет.

В порыве отчаяния я пересобрал все до mplayer (emerge -e mplayer), но и это абсолютно ничего не дало. Я что-то не понимаю, неужели никто под gentoo не кодирует видео? Не кодирует в два прохода? Или эта проблема только у меня (руки?). Ведь не может быть такого чтобы за три месяца никто не озадачился проблемой корректности двухпроходного кодирования, ежели она всетаки присутствует.

Где я только не искал отгадку, но пока ее не обнаруживаю. Так и сижу, как дурак, без mencoder'а.