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

Что-то великоватый Image...

Собираю новое ядро (2.6.23) для своего LPC2468, и что-то странное происходит с Image...

В то время, как vmlinux вполне корректен на первый взгляд...
$ file vmlinux
vmlinux: ELF 32-bit LSB executable, ARM, version 1, statically linked, not stripped
$ ls -la vmlinux
-rwxr-xr-x 1 dron dron 1919833 Янв 21 10:08 vmlinux


Этого совершенно нельзя сказать про полученный, стандартными средствами, надо сказать, Image.
$ ls -la arch/arm/boot/Image
-rw-r--r-- 1 dron dron 2685758032 Янв 21 10:08 arch/arm/boot/Image
$ file arch/arm/boot/Image
arch/arm/boot/Image: X11 SNF font data, LSB first


Надо сказать что в старом ядре linux.bin собирался кастомной рулей:
linux.bin: vmlinux FORCE
    @$(OBJCOPY) $(OBJCOPYFLAGS) vmlinux $@
    @echo ' Kernel: $@ is ready'


Но лично я не вижу никаких принципиальных отличий от стандартной рули для Image:
$(obj)/Image: vmlinux FORCE
    $(call if_changed,objcopy)
    @echo ' Kernel: $@ is ready'


Которые собственно разворачиваются в
arm-linux-objcopy -O binary -R .note -R .comment -S vmlinux linux.bin
arm-linux-objcopy -O binary -R .note -R .comment -S vmlinux arch/arm/boot/Image

соответственно. Пока даже мыслей нету - почему возникает такая ерунда.

Буду думать.

PS: Ну все ясно. Как говорится - нечего на objcopy пинять, коли vmlinux кривой. в него затесалась секция .note.gnu.build-id, замапленная на 0, в то время как основной код замаплен на 0xa0008000. вот и получается бинарь в 3 гига. Прибил секцию - пришло счастье...

$ ~/arm-linux/bin/arm-linux-objdump -h vmlinux
Sections:
Idx Name Size VMA LMA File off Algn
0 .note.gnu.build-id 00000024 00000000 00000000 00008000 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA, LINK_ONCE_DISCARD
1 .text.head 00000184 a0008000 a0008000 00010000 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE

четверг, 17 января 2008 г.

Массивные изменения с контролем версий.

Обычно изменения исходников достаточно немногочисленны и разобраться с ними вручную не составляет труда. Но иногда возникают сложности...

Я сейчас строю небольшой дистрибутивчик, встраиваемое решение. Состоит он из ядра linux, busybox и одной программочки из util-linux. Минимум. В оригинале система была построена на базе uClinux, но сделать с ним что-то было весьма не просто, старый, ничего не собирается. Поэтому я его распотрошил, выдернул ядро 2.6.11.8 со всякими патчами как было, взял свежий busybox, свежий util-linux, написал Makefile который все быстро билдит почти с учетом всех зависимостей.

Busybox конечно глючная штука. никак с ним не поборюсь, но основные утилиты работают. Самое страшное для меня - это ядро. Надо отметить, что погружал я его в систему контроля версий почастям... сперва ядро 2.6.11.8, потом hsc0 патч, потом погрузил имеющуюся версию и теперь могу отделить патч от разработчика платы в чистом виде. Кроме того на него уже наложен мой патч на шифрование, но там все просто.

От проекта требуется в первую очередь работать с USB, причем не только как хост, но и как девайс. Вот с этим какраз возникают проблемы, которые заключаются в том, что не все флешки одинаково качественны. И не всякое чтение дойдет до середины флешки.

Это была присказка.. или как говорят - преамбула... теперь наступила амбула.

Поскольку в текущем состоянии все работает, имеет смысл перейти на всежее ядро, предполагаю, что в последних ядрах USB стек сильно отличается от ядра 2.6.11.8, которое выпущено в 2005 году. Если мне не изменяет память USB 2.0 тогда только зародилось.

Делаем бранч, но чтобы не раздувать БД не просто меняем одно ядро на другое, а аккуратно патчим с текущего до последнего. При этом необходимые патчи на архитектуру и на шифрование конечно исчезают, но я их потом аккууратненько наложу. С архитектурой всеравно без напильника не обойтись.

Вот после этого и наступила засада... svn status показывает список изменений, необъятного размера, где часть файлов исчезла, часть файлов появилась, и еще много просто модифицировалось. Надо думать как аккуратно зафиксировать все это. Может быть, пришедшее ко мне в голову решение весьма тривиально, но тем не менее оно достойно того, чтобы взять его на вооружение.

$ svn status | grep \! | sed -e 's/\!//g' | xargs svn rm
$ svn status | grep ? | sed -e 's/\?//g' | xargs svn add
$ svn commit

Первая команда удаляет все исчезнувшие файлы, вторая добавляет все новые. И фиксируем.
Такой вот узелок на память.

вторник, 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, ибо на своем опыте убедился насколько востребована эта тема.