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

ТЛ; ін: збираю образ Kali Linux для ARM-комп'ютера, у програмі debootstrap, linux и u-boot.

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

Якщо ви купували який-небудь не дуже популярний одноплатник, могли зіткнутися з відсутністю для нього образу улюбленого дистрибутива. Приблизно те саме сталося з запланованим 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 для первинного завантаження. Повноцінна підтримка зазвичай забезпечується у власному форці, але й апстрім контриб'ютити не забувають. У моєму випадку плата підтримується в мейнлайн, Тому вилка я проігнорував.

Збираємо сам завантажувач:

  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 байти? Так пропонують зробити в документації. Для інших плат процес складання образу та запису може трохи відрізнятися.

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

Замість висновку

А ви знали, що лоб у дельфіна не костистий? Це буквально третє око, жирова лінза для ехолокації!

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

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

Джерело: habr.com