company_banner

Заводим GNU/Linux на ARM-плате с нуля (на примере Kali и iMX.6)

  • Tutorial
tl;dr: собираю образ Kali Linux для ARM-компьютера, в программе debootstrap, linux и u-boot.



Если вы покупали какой-нибудь не очень популярный одноплатник, то могли столкнуться с отсутствием для него образа любимого дистрибутива. Приблизительно то же самое случилось с планируемым Flipper One. Kali Linux под IMX6 просто нету (я готовлю), поэтому собирать приходится самостоятельно.

Процесс загрузки достаточно простой:

  1. Инициализируется железо.
  2. Из некоторой области на запоминающем устройства (SD-карта/eMMC/etc) считывается и выполняется загрузчик.
  3. Загрузчик ищет ядро операционной системы и загружает его в некоторую область памяти и выполняет.
  4. Ядро загружает всю остальную ОС.

Для моей задачи хватает такого уровня детализации, подробности можете прочесть в другой статье. Упомянутые выше «некоторые» области отличаются от платы к плате, что и создаёт некоторые сложности с установкой. Загрузку серверных ARM-платформ пытаются стандартизовать с помощью UEFI, но покуда это доступно не для всех, придётся собирать всё по отдельности.

Сборка корневой файловой системы


Для начала нужно подготовить разделы. Das U-Boot поддерживает разные ФС, я выбрал FAT32 для /boot и ext3 для корня, это стандартная разметка образов для Kali под ARM. Я воспользуюсь GNU Parted, но вы можете сделать то же самое более привычным fdisk. Также понадобятся dosfstools и e2fsprogs для создания ФС: apt install parted dosfstools e2fsprogs.

Размечаем SD-карту:

  1. Отмечаем SD-карту как использующую MBR-разметку: parted -s /dev/mmcblk0 mklabel msdos
  2. Создаём раздел под /boot на 128 мегабайт: parted -s /dev/mmcblk0 mkpart primary fat32 1MiB 128MiB. Первый пропущенный мегабайт необходимо оставить под саму разметку и под загрузчик.
  3. Создаём корневую ФС на всю оставшуюся ёмкость: parted -s /dev/mmcblk0 mkpart primary ext4 128MiB 100%
  4. Если вдруг у вас не создались или не изменились файлы разделов, надо выполнить `partprobe`, тогда таблица разделов будет перечитана.
  5. Создаём файловую систему загрузочного раздела с меткой BOOT: mkfs.vfat -n BOOT -F 32 -v /dev/mmcblk0p1
  6. Создаём корневую ФС с меткой ROOTFS: mkfs.ext3 -L ROOTFS /dev/mmcblk0p2

Отлично, теперь можно её заполнять. Для этого дополнительно потребуется debootstrap, утилита для создания корневых ФС Debian-подобных операционных систем: apt install debootstrap.

Собираем ФС:

  1. Монтируем раздел в /mnt/ (используйте более удобную для себя точку монтирования): mount /dev/mmcblk0p2 /mnt
  2. Собственно заполняем файловую систему: debootstrap --foreign --include=qemu-user-static --arch armhf kali-rolling /mnt/ http://http.kali.org/kali. Параметр --include указывает дополнительно установить некоторые пакеты, я указал статически собранный эмулятор QEMU. Он позволяет выполнять chroot в ARM-окружение. Смысл остальных опций можно посмотреть в man debootstrap. Не забудьте, что не любая ARM-плата поддерживает архитектуру armhf.
  3. Из-за разницы архитектур debootstrap выполняется в два этапа, второй выполняется так: chroot /mnt/ /debootstrap/debootstrap --second-stage
  4. Теперь нужно зачрутиться: chroot /mnt /bin/bash
  5. Заполняем /etc/hosts и /etc/hostname целевой ФС. Заполните по аналогии с содержимым на вашем локальном компьютере, не забудьте только заменить имя хоста.
  6. Можно донастроить всё остальное. В частности я доустанавливаю locales (ключи репозитория), перенастраиваю локали и часовой пояс (dpkg-reconfigure locales tzdata). Не забудьте задать пароль командой passwd.
  7. Задаём пароль для root командой passwd.
  8. Приготовления образа для меня завершаются заполнением /etc/fstab внутри /mnt/.

Загружать буду в соответствии с созданными ранее метками, поэтому содержимое будет таким:
LABEL=ROOTFS / auto errors=remount-ro 0 1
LABEL=BOOT /boot auto defaults 0 0

Наконец, можно примонтировать загрузочный раздел, он нам понадобится для ядра: `mount /dev/mmcblk0p1 /mnt/boot/`

Сборка Linux


Для сборки ядра (и загрузчика потом) на Debian Testing надо установить стандартный набор из GCC, GNU Make и заголовочных файлов GNU C Library для целевой архитектуры (у меня armhf), а также заголовки OpenSSL, консольный калькулятор bc, bison и flex: apt install crossbuild-essential-armhf bison flex libssl-dev bc. Так как загрузчик по умолчанию ищет файл zImage на файловой системе загрузочного раздела, пора разбивать флешку.

  1. Клонировать ядро слишком долго, поэтому просто скачаю: wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.9.1.tar.xz. Распакуем и перейдём в директорию с исходниками: tar -xf linux-5.9.1.tar.xz && cd linux-5.9.1
  2. Конфигурируем перед компиляцией: make ARCH=arm KBUILD_DEFCONFIG=imx_v6_v7_defconfig defconfig. Конфиг находится в директории arch/arm/configs/. Если такового нет, вы можете попробовать найти и скачать готовый и передать название файла в этой директории в параметр KBUILD_DEFCONFIG. В крайнем случае сразу переходите к следующему пункту.
  3. Опционально можно докрутить настройки: make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
  4. И кроскомпилируем образ: make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
  5. Теперь можно скопировать файлик с ядром: cp arch/arm/boot/zImage /mnt/boot/
  6. И файлы с DeviceTree (описание имеющегося на плате железа): cp arch/arm/boot/dts/*.dtb /mnt/boot/
  7. И доустановить собранные в виде отдельных файлов модули: make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- INSTALL_MOD_PATH=/mnt/ modules_install

Ядро готово. Можно всё отмонтировать: umount /mnt/boot/ /mnt/

Das U-Boot


Так как загрузчик интерактивный, для проверки его работы достаточно самой платы, запоминающего устройства и опционально устройства USB-to-UART. То есть, можно ядро и ОС отложить на потом.

Абсолютное большинство производителей предлагают использовать Das U-Boot для первичной загрузки. Полноценная поддержка обычно обеспечивается в собственном форке, но и в апстрим контрибьютить не забывают. В моём случае плата поддерживается в мейнлайне, поэтому форк я проигнорировал.

Cобираем сам загрузчик:

  1. Клонируем стабильную ветку репозитория: git clone https://gitlab.denx.de/u-boot/u-boot.git -b v2020.10
  2. Переходим в саму директорию: cd u-boot
  3. Готовим конфигурацию сборки: make mx6ull_14x14_evk_defconfig. Это работает только если конфигурация есть в самом Das U-Boot, в ином случае вам потребуется найти конфиг производителя и положить его в корень репозитория в файл .config, или собрать иным рекомендованным производителем образом.
  4. Собираем сам образ загрузчика кросс-компилятором armhf: make CROSS_COMPILE=arm-linux-gnueabihf- u-boot.imx

В результате мы получаем файл u-boot.imx, это готовый образ, который можно записывать на флешку. Записываем на SD-карту, пропустив первые 1024 байта. Почему я выбрал таргет u-boot.imx? Почему пропустил именно 1024 байта? Так предлагают сделать в документации. Для других плат процесс сборки образа и записи может немного отличаться.

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

Вместо заключения


А вы знали, что лоб у дельфина не костистый? Это буквально третий глаз, жировая линза для эхолокации!



RUVDS.com
VDS/VPS-хостинг. Скидка 10% по коду HABR

Комментарии 15

    +5
    Угу. Плата настолько непопулярная, что даже конфиги править не пришлось ни у u-boot ни у linux.
      +1

      В крайнем случае можно просто взять ядро и конфиг у вендора, тоже не придётся править ничего. Мне нужно было завести дистрибутив, а не разработать под него системный софт.

        +4
        Так тогда и нужно было назвать статью «запускаем», а не «портируем». Портируем — это когда к примеру вы взяли стандартное ядро linux, а его нет под такую архитектуру(сейчас сложно конечно представить) или оно не запускается и нужно что-то допилить.
          +1

          Не вполне согласен, но неоднозначность действительно есть. Меньше всего я думаю над заголовком, поправил.

      +1
      1. Почему выбор пал именно на Kali? Это из-за особенностей платформы Flipper One?
      Насколько я понимаю, под IMX6 есть другие (готовые) варианты Linux.
      2. «Kali Linux под IMX6 просто нету (я готовлю)» — было бы очень интересно потом увидеть от Вас статью на эту тему и ссылочку на образ. Потестировал бы на Андроид TVbox.
      3. Написано интересно, аж руки зачесались попробовать по инструкции из статьи развернуть на чём-нибудь. Сижу теперь, думаю на чём =)

      з.ы спасибо автору за интересный материал.
        +1
        1. Под Kali собирают огромное количество самого разного ПО требуемого для пентеста, скорее всего, это будет использоваться в следующем Флиппере. оно находится в более актуальном состоянии и требования для его сопровождения у Kali существенно ниже чем, например, у Debian. Думаю, сравнивать имеет смысл только с другими дистрибутивами для пентеста.
        2. Всё в мерж-реквесте. Собираются образы shell-скриптом, функциональную часть я в этой статье и расписал. Есть, конечно, некоторые best practices, но они слишком специфичны для конкретно этой команды, просто сложившийся набор правил.
          +2
          Я глупую вещь спрошу, но чем Kali принципиально отличается от Ubuntu? Если есть rootfs для ARM платформы, то там портирование с готовым ядром не должно составить проблем, тем более что вы используете конфиги по умолчанию.
            0

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


            Для добавления пакета в Ubuntu придётся либо выполнять довольно строгие требования проекта Debian, либо выполнять всё то же самое для Ubuntu и, возможно, объяснять, почему это не было добавлено сразу в Debian. А потом ещё ждать релиза перед использованием.


            Альтернатива — собственный репозиторий, который придётся частично синхронизировать с Kali, возможно, следить за версиями и зависимостями.


            В общем, простота поддержки является очень серьёзным критерием выбора, так как отнимает уйму времени. Но всё ещё может поменяться.

              0
              Просто я много развлекался портированием для процессоров im6ull различных сборок для различных задач. И в общем-то, если вы используете конфиг по умолчанию mx6ull_14x14_evk даже компиляцией заниматься не нужно.

              Накатывай rootfs, да и делов.

              Паша рассказывал, что у вас критична скорость загрузки, если это важно, то ещё можно использовать buldroot. Обрезанная сборка грузится за секунды, в отличии от убунты, которая грузится минуту.
        +2
        Разве нет Yocto слоя для Kali Linux? Неужели его никто еще на ARM не собирал? Странно…
        Как по мне, с Yocto все попроще получается. Да и поддерживать потом удобнее.
          0

          До вашего комментария не знал о такой фиче. Попробую разобраться, спасибо!

            0
            Я писал свой make для автоматической сборки.
          0

          я очень далёк от линукса и у меня вопрос — а есть такое для банана пи м3? На форуме чего-то мудрили с 19 версией http://forum.banana-pi.org/c/bpi-m3/M2image http://forum.banana-pi.org/c/bpi-m3/Projects, но оно нерабочее.

            0

            Не очень понятен вопрос. Если речь о Kali под Banana Pi, то я предлагаю сделать всё то же самое, заменив только сборку ядра и U-Boot. Все инструкции по сборке этих двух компонентов должны быть в наличии.

              0

              речь об убунте 19 с новым на тот момент ядром. Нерабочая и заброшенная. Риторический вопрос на зачем выпускать такое и забрасывать? И вопрос по теме "а что делать далёким от линукса, если есть банан м3 и ему нужна нормальная ось?". Пока присматриваюсь к армбиану, но там свои недоделки, выдаваемые за фичи.
              Необходим авторазгон CPU с установкой верхней границы по частоте и возможность задать частоту для GPU. По раздельности это есть в сборках убунты (в 16 точно) и армбиана, а вот вместе не встречал.

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

          Самое читаемое