Передача параметров ядра из U-Boot в ARM Linux при использовании дерева устройств - PullRequest
0 голосов
/ 02 ноября 2018

Я изучал изменение некоторых встроенных программ, поскольку мы хотим, чтобы U-Boot мог передавать ядру определенные параметры командной строки, которые не обязательно известны заранее.

Это сделано для того, чтобы ядро ​​могло сказать , с какого раздела U-Boot он был запущен (у нас есть две копии, одна в /dev/mmc3boot0 и /dev/mmc3boot1, и обе они совместно используют одну (избыточную) ) пространство среды, поэтому мы не можем использовать это одно для уникальной идентификации экземпляра).

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

Вот почему мы решили использовать параметр ядра - поскольку экземпляры U-Boot более старого стиля никогда не предоставляют идентификатор, мы знаем, что он работает в boot0. Более новый стиль предоставил бы их фактический идентификатор, чтобы мы могли затем выполнить поиск по двум boot разделам, чтобы выяснить, в каком из них он находится.

Для этого я изменил U-Boot, чтобы он настраивал ATAG для прохождения через необходимый дополнительный параметр. В частности:

  • Я определил CONFIG_SYS_BOOT_GET_CMDLINE в arch\arm\include\asm\config.h, поэтому вызывается boot_get_cmdline().
  • Я изменил эту функцию boot_get_cmdline(), чтобы она настраивала определенный параметр до добавления нормальных параметров. Другими словами, вместо plugh=xyzzy мы теперь получаем uboot_instance=42 plugh=xyzzy.

Все это прекрасно компилируется, и U-Boot успешно запускает ядро, но дополнительная информация не отражается в ядре Linux, для которого его параметры ядра установлены на обычные plugh=xyzzy.

При дальнейших исследованиях выясняется, что мы сталкиваемся с двумя возможными способами вызова ядра. Один из них - с ATAG, а другой - со сплющенным деревом устройств (FDT), и они кажутся взаимоисключающими (код запуска ядра выбирает одну или другую на основе сигнатур, передаваемых указателем, ссылающимся либо на ATAG, либо на структуру FDT). ).

Так что мой вопрос такой. Учитывая, что дерево устройств должно быть структурой fixed для устройства, которое вы описываете, как вы передаете произвольные параметры командной строки ядра (рассчитанные во время выполнения), когда загрузчик вызывая ядро?

1 Ответ

0 голосов
/ 02 ноября 2018

Вы можете использовать фиктивную переменную среды для вашей платформы в include/configs/<board>.h.

Например, предположим, что у вас есть следующие (упрощенные) переменные среды UBoot для загрузки:

bootcmd=run mmcargs
        run loadimage loadfdt
        bootz ${loadaddr} - ${fdt_addr}
mmcargs=setenv bootargs blah=blah

Используется mmcargs для настройки используемой командной строки ядра. Что нам нужно сделать, это вставить эту фиктивную переменную среды так, чтобы текущие экземпляры UBoot ничего не предоставляли, а новые - фактический идентификатор. Это делается просто со следующим изменением:

mmcargs=setenv bootargs ${uboot_id_stanza} blah=blah

Затем, во время инициализации платы, вы можете установить эту переменную, используя env_set API, в частности, написав свой собственный board_late_init кода инициализации платы в board/<vendor>/<init_code>.c.

Следующая строка должна находиться в конце функции board_late_init:

setenv("uboot_id_stanza", "uboot_id=<uniqueId>");

Таким образом, переменная uboot_id добавляется в командную строку ядра, но, поскольку вы не сделали saveenv, она не станет постоянной. Каждый экземпляр UBoot будет устанавливать правильный идентификатор (включая старые, которые не устанавливают идентификатор).

...