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


Использование EXTERNAL-механизма для кастомизации


В предыдущей статье рассматривался простой пример добавления своей конфигурации, путем добавления defconfig’а платы и нужных файлов непосредственно в каталог Buildroot.


Но этот метод не очень удобен, особенно при обновлении buildroot. Для решения это проблемы есть механизм external tree. Суть его в том, что в отдельном каталоге можно хранить каталоги board,configs,packages и прочие( например, я использую каталог patches для наложения патчей на пакеты, подробнее в отдельном разделе) и buildroot будет сам добавлять их к имеющимися в своем каталоге.


Примечение: можно накладывать сразу несколько external tree, есть пример в руководстве buildroot


Создадим каталог my_tree, находящийся рядом с каталогом buildroot’а и перенесём туда нашу конфигурацию. На выходе должны получить следующую структуру файлов:


[alexey@alexey-pc my_tree]$ tree
.
+-- board
¦   L-- my_x86_board
¦       +-- bef_cr_fs_img.sh
¦       +-- linux.config
¦       +-- rootfs_overlay
¦       L-- users.txt
+-- Config.in
+-- configs
¦   L-- my_x86_board_defconfig
+-- external.desc
+-- external.mk
+-- package
L-- patches

6 directories, 7 files

Как видно, в целом структура повторяет структуру buildroot.


Каталог board содержит файлы, специфичные каждой плате в нашем случае:


  • bef_cr_fs_img.sh — скрипт, который будет выполняться после сборки target-файловой системы, но перед упаковыванием её в образы. В дальнейшем мы его будем использовать
  • linux.config — конфигурация ядра
  • rootfs_overlay — каталог для наложения поверх target-файловой системы
  • users.txt — файл с описанием создаваемых пользователей

Каталог configs содержит defconfig’и наших плат. У нас он всего один.


Package — каталог с нашими пакетами. Изначально buildroot содержит описания и правила сборки ограниченного числа пакетов. Позже мы добавим сюда оконный менеджер icewm и менеджер графического входа в систему Slim.
Patches — позволяет удобно хранить свои патчи для разных пакетов. Подробнее в отдельном разделе далее.
Теперь нужно добавить файлы описания нашего external-tree. За это отвечают 3 файла: external.desc, Config.in, external.mk.


external.desc содержит собственно описание:


[alexey@alexey-pc my_tree]$ cat external.desc 
name: my_tree
desc: My simple external-tree for article

Первая строка — название. В дальнейшем buildroot создать переменную $(BR2_EXTERNAL_MY_TREE_PATH), которую нужно использовать при конфигурировании сборки. Например, путь к файлу с пользователями можно задать следующим путем:


$(BR2_EXTERNAL_my_tree_PATH)/board/my_x86_board/users.txt

Вторая строка — краткое, понятное человеку описание.


Config.in, external.mk — файлы для описания добавляемых пакетов. Если свои пакеты не добавлять, то эти файлы можно оставить пустыми. Пока что мы так и поступим.
Теперь у нас готово наше external-tree, содержащее defconfig нашей платы и нужные ему файлы. Перейдем каталог buildroot, укажем использовать external-tree:


[alexey@alexey-pc buildroot]$ make BR2_EXTERNAL=../my_tree/ my_x86_board_defconfig
#
# configuration written to /home/alexey/dev/article/ramdisk/buildroot/.config
#
[alexey@alexey-pc buildroot]$ make menuconfig

В первой команде мы используем аргумент BR2_EXTERNAL=../my_tree/, указывающий использование external tree.Можно задать одновременно несколько external-tree для использования При этом достаточно сделать это один раз, после чего создается файл output/.br-external.mk, хранящий информацию об используемом external-tree:


[alexey@alexey-pc buildroot]$ cat output/.br-external.mk 
#
# Automatically generated file; DO NOT EDIT.
#

BR2_EXTERNAL ?= /home/alexey/dev/article/ramdisk/my_small_linux/my_tree
BR2_EXTERNAL_NAMES = 
BR2_EXTERNAL_DIRS = 
BR2_EXTERNAL_MKS = 

BR2_EXTERNAL_NAMES += my_tree
BR2_EXTERNAL_DIRS += /home/alexey/dev/article/ramdisk/my_small_linux/my_tree
BR2_EXTERNAL_MKS += /home/alexey/dev/article/ramdisk/my_small_linux/my_tree/external.mk
export BR2_EXTERNAL_my_tree_PATH = /home/alexey/dev/article/ramdisk/my_small_linux/my_tree
export BR2_EXTERNAL_my_tree_DESC = My simple external-tree for article

Важно! В этом файле пути будут абсолютными!


В меню появился пункт External options:



В этом подменю будут содержаться наши пакеты из нашего external-tree. Сейчас этот раздел пустой.


Сейчас нам важнее переписать нужные пути на использование external-tree.


Обратите внимание, что в разделе Build options > Location to save buildroot config, будет абсолютный путь к сохраняемому defconfig'у. Формируется он в момент указания импользования extgernal_tree.


Также в разделе System configuration поправим пути. Для таблицы с создаваемыми пользователями:


$(BR2_EXTERNAL_my_tree_PATH)/board/my_x86_board/users.txt

В разделе Kernel поменяем путь к конфигурации ядра:


$(BR2_EXTERNAL_my_tree_PATH)/board/my_x86_board/linux.config

Теперь при сборке будут использоваться наши файлы из нашего external-tree. При переносе в другой каталог, обновлении buildroot у нас будет минимум проблем.


Добавление root fs overlay:


Данный механизм позволяет легко добавлять/заменять файлы в target-файловой системе.
Если файл есть в root fs overlay, но нет в target, то он будет добавлен
Если файл есть в root fs overlay и в target, то он будет заменён.
Сначала зададим путь к root fs overlay dir. Это делается в разделе System configuration > Root filesystem overlay directories:


$(BR2_EXTERNAL_my_tree_PATH)/board/my_x86_board/rootfs_overlay/

Теперь проведем создадим два файла.


[alexey@alexey-pc my_small_linux]$ cat my_tree/board/my_x86_board/rootfs_overlay/etc/hosts 
127.0.0.1   localhost
127.0.1.1   my_small_linux
8.8.8.8     google-public-dns-a.google.com.
[alexey@alexey-pc my_small_linux]$ cat my_tree/board/my_x86_board/rootfs_overlay/new_file.txt 
This is new file from overlay

Первый файл (my_tree/board/my_x86_board/rootfs_overlay/etc/hosts) заменит файл /etc/hosts в готовой системе. Второй файл (cat my_tree/board/my_x86_board/rootfs_overlay/new_file.txt) добавится.


Собираем и проверяем:



Выполнение скриптов кастомизации на разных этапах сборки системы


Часто нужно выполнить некоторые действия внутри target-файловой системы до того, как как она будет упакована в образы.


Это можно сделать в разделе System configuration:



Первые два скрипта выполняются после сборки target-файловой системы, но до упаковки её в образы. Разница в том, что fakeroot-скрипт выполняется в контексте fakeroot, те имитируется работа от пользователя root.


Последний скрипт выполняется уже после создания образов системы. В нем можно выполнять дополнительные действия, например, скопировать нужные файлы на nfs-сервер или создать образ своей прошивки устройства.


В качестве примера я создам скрипт, который будет писать версию и дату сборки в /etc/.
Сначала укажу путь к этому файлу в моем external-tree:



А теперь сам скрипт:


[alexey@alexey-pc buildroot]$ cat ../my_tree/board/my_x86_board/bef_cr_fs_img.sh 
#!/bin/sh
echo "my small linux 1.0 pre alpha" > output/target/etc/mysmalllinux-release
date >> output/target/etc/mysmalllinux-release

После сборки можно увидеть этот файл в системе.


На практике, скрипт может стать большим. Поэтому в реальном проекте я пошел более продвинутым путем:


  1. Создал каталог (my_tree/board_my_x86_board/inside_fakeroot_scripts), в котором лежат скрипты для выполнения, с порядковыми номерами. Например, 0001-add-my_small_linux-version.sh, 0002-clear-apache-root-dir.sh
  2. Написал скрипт(my_tree/board_my_x86_board/run_inside_fakeroot.sh), который проходит по этому каталогу и последовательно выполняет скрипты, лежашие в нем
  3. Указал этот скрипт в настройках платы в разеле System configuration -> Custom scripts to run inside the fakeroot environment ($(BR2_EXTERNAL_my_tree_PATH)/board/my_x86_board/run_inside_fakeroot.sh)

Комментарии (20)


  1. DigitalSmile
    26.04.2019 10:45

    Спасибо за серию статей!
    Еще бы кто-нибудь сделал серию по формированию файла Device Tree с глубоким погружением, цены бы такому человеку не было бы…


    1. maquefel
      26.04.2019 11:25

      А что конкретно в Device Tree вас интересует? Что именно непонятно?


      1. DigitalSmile
        26.04.2019 14:51

        Ну вот мы разрабатываем свою плату. Берем в правую руку даташит на процессор и периферию, в левую руку клавиатуру и файл с Device Tree. Что дальше? С чего начать описание? Как правильно мапить адреса, прерывания, регистры...? Если я чего-то не замапил — ядро этого не увидит? Или увидит но будет криво работать? В чем отличие Device Tree для ядра от Device Tree в моем флеше (почему-то по гайду от производителя их надо 2 — один для bootloader второй для ядра)?

        Короче говоря, хотелось бы ликбез какой-то с чего начинаем, какие параметры вписываем, как оно взаимодействует с ядром. Есть несколько источников в сети на elinux где кое-что описано, но общего понимания всего равно нет…

        Добавлю: сейчас наш процесс создания такого файла — это метод проб и ошибок, бессистемный.


        1. maquefel
          26.04.2019 15:54

          Я вас понял. Да такую статью я бы и сам почитал :-D.


          1. DigitalSmile
            26.04.2019 16:52

            Ну вот… Я уж губу раскатал думал нашел такого человека, который все расскажет :D


        1. gosha-z
          27.04.2019 08:52

          А это сильно зависит от процессора. Для начала можно поизучать уже имеющиеся. dtsi и. dts от других плат. И может понадобиться также и схема самой платы (например, для правильного описания gpio, pinctrl и led'ов)


          1. DigitalSmile
            29.04.2019 11:44

            Ну вот мы так и идем, даже демо плату купили… Только это как-то кустарно выглядит как способ разработки…


            1. maquefel
              29.04.2019 11:53

              Так большинство, по-моему, идет. На самом деле если глянуть, то все SoM, SoC в большинстве своем калька с Evaluation Board.
              Не так уж много делают новых плат — да и зачем.


              1. DigitalSmile
                29.04.2019 12:00

                Ответ на вопрос «зачем?» может занять много места :) Есть куча факторов, почему не стоит ИМХО делать кальку с Demo Board (начиная от выбора компонентов, заканчивая ошибками в разведении и недоступностью фич на камне). Поэтому для заказчика часто приходится делать что-то свое, иногда нестандартное.

                Взять к примеру HDMI — его щас лепят на все демо платы. Проблема с ним в том, что начиная с определенного времени надо заносить денюжку организации, которая владеет стандартом (неслабую надо отметить). Без лицензии тебе не продадут мост LVDS-HDMI. Есть запасы старых чипов, которые не требуют лицензии, но на серьезном серийном производстве полагаться на запасы нельзя (они имеют свойство заканчиваться). При этом на наш чип «православных» Display Port выходов никто не делал. Вот и приходится заниматься этой разработкой вслепую, методом проб и ошибок…


                1. maquefel
                  29.04.2019 12:05

                  Ну вот тогда вам и флаг в руки :-D со статьёй. В моей практике не так часто приходится, что-то принципиально новое разводить.


                  1. DigitalSmile
                    29.04.2019 12:06

                    Да, я вот и чувствую по формату беседы, что к этому и идет :D


                    1. maquefel
                      29.04.2019 12:09

                      Но вообще говоря сильно зависит от производителя камня. У texas отличные инструменты для pinmux, NXP тоже догоняет. А вот если плохо с документацией на камень, тогда все очень печально.


                      1. DigitalSmile
                        29.04.2019 12:14

                        Мы стараемся брать компоненты у проверенных компаний с хорошей документацией, только проблема возникает на стыке софта и харда. У нас отличные инженеры, которые все хорошо разведут и классные программисты, которые пишут хороший код. Только вот соединить их навыки из-за отсутствия теоретического материала и практического опыта сейчас крайне тяжело. Много времени уходит просто на анализ существующих драйверов, чтобы «сделать по аналогии» ну и тут же вносятся изменения в схему и консультации с инженерами. Иногда бывают тупики и приходится возвращаться назад.
                        В общем, жалко что никакого готового материала нет, надо и правда подумать о создании своего…


                1. Boozlachu Автор
                  29.04.2019 12:08

                  maquefel подал не плохую мысль.
                  Действительно, если Вы начнёте писать статью по этой теме, то это даст хороший рост. Объяснить кому-то всегда сложнее, чем взять и сделать.
                  Я поэтому и начал писать про buildroot. Хорошая систематизация знаний и мозный стимул начать разбираться как следует


                  1. maquefel
                    29.04.2019 12:10

                    Ну вообще да. Просим статью.


                  1. DigitalSmile
                    29.04.2019 12:15

                    Взял эту мысль на вооружение.


            1. gosha-z
              29.04.2019 13:57

              Почему кустарно? Пользование текстовым редактором и чтение документации — это уже кустарщина?


              1. DigitalSmile
                29.04.2019 14:05

                Метод проб и ошибок, бессистемный анализ и глупое копирование без понимания сути — это кустарщина.


                1. gosha-z
                  29.04.2019 14:08

                  Почему бессистемный. Выкатывайте вашу плату, на вашей плате сделаем пример создания DT. Практика всегда лучше теории. Только давайте что-нибудь приличное и документированное, типа TI/NXP/Xilinx, от китайцев лучше держаться подальше, у них с документацией традиционно швах.


                  1. DigitalSmile
                    29.04.2019 14:24

                    Спасибо за предложение помощи! :)
                    Я думаю это уже не в рамках комментариев к хабру надо общаться. Чип у нас Atmel SAMA5D44 на первой итерации, после пробы пера хотим поменять на TI Cortex A-9 (пока еще не выбрали какой конкретно).