Я создал образ для платы Freescale iMX6 EVK (на базе ARM), используя Buildroot. Он нормально загружался с SD-карты, и я хотел поэкспериментировать с настраиваемыми командами загрузки в U-Boot. Я хочу сделать загрузочную последовательность максимально быстрой и быстрой, поэтому я упростил некоторые проверки и тесты, выполняемые U-Boot (например, удалил проверку для сценария загрузки и загрузки по сети).
Вот моя переменная bootcmd U-Boot env (отформатированная для легкого чтения):
bootcmd=
echo Booting from SD...;
mmc dev ${mmcdev};
if mmc rescan; then
setenv mmcroot /dev/mmcblk1p2 rootwait ro;
setenv bootargs console=${console},${baudrate} root=${mmcroot};
fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image};
setenv fdt_file imx6ull-14x14-evk.dtb;
fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file};
bootz ${loadaddr} - ${fdt_addr};
else
echo Boot FAILED: Couldnt find kernel or dtb;
fi
когда я включаю плату, после нажатия любой клавиши, чтобы остановить автозагрузку, я получаю это:
Hit any key to stop autoboot: 0
Booting from SD...
switch to partitions #0, OK
mmc1 is current device
reading zImage
4652504 bytes read in 369 ms (12 MiB/s)
reading imx6ull-14x14-evk.dtb
33755 bytes read in 30 ms (1.1 MiB/s)
Kernel image @ 0x80800000 [ 0x000000 - 0x46fdd8 ]
## Flattened Device Tree blob at 83000000
Booting using the fdt blob at 0x83000000
Using Device Tree in place at 83000000, end 8300b3da
Starting kernel ...
Затем он зависает на этапе «Starting kernel ...».
ОДНАКО, если я прерву U-Boot нажатием Enter, то (из приглашения U-Boot) запустите одну из следующих команд:
boot
или же
run bootcmd
Он показывает те же сообщения, что и выше, но затем ядро запускается в порядке.
Я сравнил результаты в обоих случаях, и они идентичны до "Стартовое ядро". Я также добавил строку в bootcmd для вывода переменных env (printenv
) и подтвердил, что переменные также идентичны в обоих случаях. Вот последние ботарги (напечатанные с помощью echo ${bootargs}
) - они также одинаковы в обоих случаях:
console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait ro
Я думал, что команда boot
только что выполнила bootcmd, и что процесс автоматической загрузки сделал то же самое, если не был прерван.
Так почему же это работает, если я прерываю его и запускаю boot
вручную?
==== РЕДАКТИРОВАТЬ ====
После комментариев от опилок я провел еще несколько экспериментов, чтобы прояснить проблему.
1/ Добавлен 'earlyprintk' в сборку ядра (опции взлома ядра).
Это привело к тому, что при успешной загрузке было напечатано следующее:
Starting kernel ...
Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0x0
При неудачной загрузке он по-прежнему останавливается на «Запуск ядра ...» (никакой дополнительной информации от earlyprintk).
2/ Дальнейший взлом bootcmd для выяснения проблемы.
Вот переменная env "bootcmd" по умолчанию, созданная новой сборкой (Примечание: обычно это все в одной строке, то есть «bootcmd = ....»; отформатировано здесь для ясности):
run findfdt;
mmc dev ${mmcdev};
mmc dev ${mmcdev};
if mmc rescan; then
if run loadbootscript; then
run bootscript;
else
if run loadimage; then
run mmcboot;
else
run netboot;
fi;
fi;
else
run netboot;
fi
Это работает (то есть автоматическая загрузка после задержки загрузки).
Вот моя минимальная модификация:
run findfdt;
mmc dev ${mmcdev};
mmc dev ${mmcdev};
mmc rescan;
if run loadbootscript; then
run bootscript;
else
if run loadimage; then
run mmcboot;
else
run netboot;
fi;
fi;
Все, что я сделал, это удалил внешнюю структуру if (если mmc повторно сканирует; затем ...). Это все еще называет "mmc rescan", который преуспевает.
Обратите внимание, что это сохраняется, поместив вышеуказанное в одну строку ('xxxx') и используя:
setenv bootcmd 'xxxxx'
saveenv
Это приводит к зависанию платы на «Starting kernel ...», но если я прерву автоматическую загрузку, введите приглашение u-boot, а затем используйте "boot", она загрузится нормально.
Я могу вернуться к исходному bootcmd, и он работает правильно (с автоматической загрузкой все в порядке), поэтому я думаю, что метод изменения переменной - это нормально.
Однажды я увидел одну странную вещь, когда изменил ее на свою версию:
Starting kernel ...
resetting ...
[Board Rebooted itself!]
U-Boot 2016.03 (Nov 16 2017 - 07:08:36 +1300)
[Auto-boot]
Starting kernel ...
[Hang.]
С тех пор все вернулось к зависанию, если я не прерву загрузку и не введу команду "boot".
Ошибка в U-Boot? переменные среды u-boot как-то повреждены?
Nb: Сейчас это не главная проблема, но я думаю, что мы могли бы сэкономить несколько мс, избавившись от бессмысленного поиска загрузочного скрипта, которого, как я знаю, там нет, и в будущем у нас может быть причина настроить загрузку по какой-то другой причине, и я хотел бы знать, что это можно сделать предсказуемо!