Вам нужно проанализировать вывод xrandr (или написать программу или что-то еще), чтобы найти правильные имена и соответствующим образом обработать конфигурацию i3.
Порядок обнаружения устройств случайный, от него нельзя зависеть.
Несколько пунктов для изучения:
1:
## Booting kernel from Legacy Image at 81000000...
Image Name: Linux 4.1 + Devicetree
Содержит ли дерево устройств ключи ядра, которые могут конфликтовать сsetenv bootargs console=${console} root=/dev/ram0 rootfstype=ramfs initrd=0x85000000
2:
setenv bootargs console=${console} root=/dev/ram0 rootfstype=ramfs initrd=0x85000000
Нужен ли ядру адрес памяти initrd=0x850000000 или просто расположение dev/ram0.
3:
Вы используете initramfs или initrd? Вы сами собираете ядро? Образ ядра уже содержит initramfs?
Проверьте это в конфигурации ядра:
КОНФИГУРАЦИЯ _ЧЕР _РАЗРАБОТКА _ИНИТРД
КОНФИГУРАЦИЯ _INITRAMFS _ИСТОЧНИК
[ 0.131751] devtmpfs: initialized
[ 2.937980] devtmpfs: error mounting -2
Похоже, что devtmpfs монтируется дважды. Что смонтировало его в первый раз (, встроенное в initramfs )? Согласен с комментарием @sourcejedi. Нет /dev
, потому что нет rootfs.
Также ядро инициализирует оборудование. Bluetooth, USB, MMC и многое другое. Если эти модули не скомпилированы в ядро и не загружены модули, они загружаются откуда-то. (встроен в initramfs )?
4:
Если вы используете initrd вместо initramfs, а образ ядра не содержит встроенной initramfs...
Думаю, нужна конфигурация ядра:
ЧЕР _ДЕВ _ОЗУ
«Если используется, современные ядра используют /dev/ram0 для initrd».
./linux-4.x.x/Documentation/blockdev/ramdisk.txt
Разве это не initrd=/dev/ram0
, а не initrd=0x85000000
?
«Старый initrd всегда был отдельным файлом, тогда как архив initramfs связан с образом ядра linux».
./linux-4.x.x/Documentation/filesystems/ramfs-rootfs-initramfs.txtramfs-rootfs-initramfs.txt
«Программа, запущенная старым initrd (, которая называлась /initrd, а не /init ), выполнила некоторые настройки, а затем вернулась в ядро...»
./linux-4.x.x/Documentation/filesystems/ramfs-rootfs-initramfs.txtramfs-rootfs-initramfs.txt
Должен ли init быть /initrd
вместо /init
?
5:
Если вы скомпилируете собственное ядро, это сэкономит вам массу времени, поскольку процесс сборки ядра объединит initramfs в образ ядра.
КОНФИГУРАЦИЯ _ЧЕР _РАЗРАБОТКА _ИНИТРД
КОНФИГУРАЦИЯ _INITRAMFS _ИСТОЧНИК
RIM-U-Boot# bootm 0x81000000 0x85000000
## Booting kernel from Legacy Image at 81000000...
Image Name: Linux 4.1 + Devicetree
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 4024711 Bytes = 3.8 MiB
Load Address: 80008000
Entry Point: 80008000
Verifying Checksum... OK
## Loading init Ramdisk from Legacy Image at 85000000...
Image Name: uInitrd
Image Type: ARM Linux RAMDisk Image (uncompressed)
Data Size: 1410048 Bytes = 1.3 MiB
Load Address: 80008000
Entry Point: 80008000
Verifying Checksum... OK
Loading Kernel Image... OK
OK
Что-то тут не так. Адрес загрузки ядра не должен пересекаться с адресом загрузки initrd!
Для сравнения см.https://community.nxp.com/thread/305045#comment-322873
Воссоздайте uInitrd, используя адрес загрузки 0x80408000
.
Я не знаю вашего оборудования. Предлагаемые здесь распределения не должны конфликтовать друг с другом AFAICT, надеюсь, они не конфликтуют ни с чем еще:-).
Не используйте параметры загрузки ядра rootfsype=ramfs
или root=/dev/ram0
. Я не думаю, что они должны влиять на ваши проблемы, независимо от того, вы их устанавливаете. Но они ошибаются, так что давайте не будем отвлекаться. Вам не нужен ни один из них для загрузки initramfs.(Мой компьютер загружает Linux с помощью initramfs и не использует ни один из этих вариантов загрузки!)
Вам не нужно использовать initrd=...
, потому что вы передаете адрес в качестве второго параметра в bootm
. (Но, учитывая вышеизложенное, правильное значение будет initrd=0x80408000,2M
, так что не передавайте никаких других адресов! ).
Ты не хочешь rootfstype=ramfs
. Я уверен. Хотя AFAICT это не настоящая проблема.
Монтаж ramfs
игнорирует блочное устройство(root=/dev/ram0
в этом случае ). ramfs
не поддерживается никаким файлом устройства. Он изначально пустой.
Следовательно, если rootfstype=ramfs
вступит в силу, он просто смонтирует пустую fs. Следовательно, не будет init
запускаемой программы. (Это также будет генерировать ошибку 2 = ENOENT = «Нет такого файла или каталога», когда ядро пытается смонтировать devtmpfs на /dev
, как вы видите в своем журнале ).
Вы показываете, что используете новый -стиль initramfs, то есть архив cpio вместо образа файловой системы. Это хорошо. Но тогда вы должны получить сообщение типа "Распаковка initramfs...", когда ядро обнаружит новый формат стиля -и распаковывает его.
В оригинальном документе говорится, что initramfs должен быть cpio, сжатым с помощью gzip. Однако я думаю, что текущий код также доволен несжатым cpio.
Как вы сказали, у вас, похоже, проблема в том, что ядро не распознает initramfs.
По крайней мере, initrd_start
выглядит как 0
при вводе populate_rootfs()
. Если бы это было не -нулевое значение, вы бы увидели по крайней мере одно сообщение или ошибку, связанную с initrd -или initramfs -.
https://elixir.bootlin.com/linux/v4.1/source/init/initramfs.c#L608
ИЛИ, initramfs.c
даже не включается в ядро, потому что вы не включили CONFIG _BLK _DEV _INITRD. Вот что говорит мне init/Makefile .
initrd:https://www.kernel.org/doc/html/v4.18/admin-guide/initrd.html
initramfs:https://www.kernel.org/doc/Documentation/filesystems/ramfs-rootfs-initramfs.txt
Я столкнулся с такой же ситуацией. Я наконец понял, что ключ в том, что способ создания initramfs не является неправильным. Вы ДОЛЖНЫcd
перейти в папку initramfs, а затем создать архив cpio.
Лучший способ создать initramfs.gz — следовать документу ядра . в доке есть удобный скрипт.
#!/bin/sh
# Copyright 2006 Rob Landley <rob@landley.net> and TimeSys Corporation.
# Licensed under GPL version 2
if [ $# -ne 2 ]
then
echo "usage: mkinitramfs directory imagename.cpio.gz"
exit 1
fi
if [ -d "$1" ]
then
echo "creating $2 from $1"
(cd "$1"; find. | cpio -o -H newc | gzip) > "$2"
else
echo "First argument must be a directory"
exit 1
fi
Вам вообще не нужно root=/dev/ram0 initrd=0x85000000,2M
в bootargs, если вы используете initramfs.
Некоторые ключи для использования initramfs
CONFIG_BLK_DEV_INITRD=y
в конфигурации вашего ядра /init
в initramfs. Вы можете указать другой процесс инициализации через rdinit=/bin/sh
в bootargs initramfs.gz
, убедитесь, что файл initramfs.gz имеет формат uImage bootm <kernel addr> <initramfs/ramdisk addr> <dtb addr>
При использовании initrd задействованы две "инициализации":
rdinit=/init и инициализация=/sbin/инициализация (значения по умолчанию)
Первый (rdinit= )сообщает раннему пользовательскому пространству, что запускать после того, как ядро распаковало и смонтировало initrd. По умолчанию /инит.
БЕЗ initrd, второй (init= )сообщает ядру, какую инициализацию запускать (точно так же, как root= сообщает ядру, какое устройство монтировать как /)
С initrd, init= используется switchroot в конце раннего пользовательского пространства не только для монтирования нового, настоящего корня, но и для запуска реального /sbin/init -или чего угодно :init =/sbin/тест _инициализация
(Однако /init не обязательно должен вести к корневому каталогу; вы можете остаться в initrd навсегда... встроенный стиль)
Я полностью согласен с Чарльзом, единственным, кто упомянул rdinit=:
Make sure you have /init executable in your initramfs. You can specify another init process via rdinit=/bin/sh in bootargs
rdinit=/init и init=/init также должны быть возможны, это разные файлы :первый "/" означает начало вашего initrd (ваш cpio ), второй "/" означает начало из root = aka newroot.