U-Bboot не загружается автоматически, но ручная загрузка работает нормально

419
Jeremy

Я создал образ для платы Freescale iMX6 EVK (на базе ARM), используя Buildroot. Он нормально загружался с SD-карты, и я хотел поэкспериментировать с настраиваемыми командами загрузки в U-Boot. Я хочу сделать загрузочную последовательность максимально быстрой и быстрой, поэтому я упростил некоторые проверки и тесты, выполняемые U-Boot (например, удалил проверку для сценария загрузки и загрузки по сети).

Вот моя переменная bootcmd U-Boot env (отформатированная для легкого чтения):

bootcmd= echo Booting from SD...; mmc dev $; if mmc rescan; then setenv mmcroot /dev/mmcblk1p2 rootwait ro; setenv bootargs console=$,$ root=$; fatload mmc $:$ $ $; setenv fdt_file imx6ull-14x14-evk.dtb; fatload mmc $:$ $ $; bootz $ - $; 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 $) - они также одинаковы в обоих случаях:

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 $; mmc dev $; 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 $; mmc dev $; 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: Сейчас это не главная проблема, но я думаю, что мы могли бы сэкономить несколько мс, избавившись от бессмысленного поиска загрузочного скрипта, которого, как я знаю, там нет, и в будущем у нас может быть причина настроить загрузку по какой-то другой причине, и я хотел бы знать, что это можно сделать предсказуемо!

1
Ваши предположения относительно команд загрузки CLI и автоматической загрузки верны. Что вы * "упорядочили" * и * "удалили" *? Это все в окружающей среде? Существует разница между двумя сценариями, разница во времени. Вы можете попробовать увеличить ** bootdelay **, чтобы имитировать дополнительное время для отмены автозагрузки и набрав «boot» + Enter. Есть ли в вашем ядре тихая или подробная распаковка (см. Https://stackoverflow.com/questions/46930346/uncompressing-is-not-happening-with-zimage- while-booting-up-with-u-boot/47009714#47009714) ? sawdust 6 лет назад 0
Я установил «bootdelay» на 6 секунд, но это не помогло. Для «упорядочения» я выбрал стандартную переменную «bootcmd» env и удалил биты, которые я не использовал (например, поиск загрузочного скрипта, которого, как я знаю, там нет). Оно должно быть функционально таким же, как и раньше, в теории. Я мог бы понять, была ли ошибка в моем снятии, но я не могу понять, почему это работает, когда я вызываю его вручную с помощью команды «boot». Может ли быть какая-то другая разница, кроме задержки? Jeremy 6 лет назад 0
Ядро использует несжатую распаковку, поскольку оно идет прямо от «Запуск ядра ...» до «Загрузка Linux на физическом процессоре 0x0» (когда я запускаю загрузку вручную). Jeremy 6 лет назад 0
Если ** earlyprintk ** уже настроен в ядре, то включите его в командной строке ядра через переменную ** bootargs **. Можете ли вы пересобрать ядро ​​так, чтобы у вас была многословная распаковка? Это может помочь определить, как далеко продвинулась последовательность загрузки (поскольку это промежуточный этап перед запуском ядра), если вы ничего не получите с ** earlyprintk **. sawdust 6 лет назад 0
Чтобы быть понятным, autoboot раньше работал нормально (с теми же U-Boot и образами ядра) до того, как вы * упростили *? sawdust 6 лет назад 0
Да, автозагрузка работала нормально, хотя и приводила к некоторым ошибкам, таким как невозможность найти boot.scr (ожидается). Я только что подтвердил это (сбросил образ SD-карты обратно по умолчанию, протестировал загрузку, затем повторил изменения, упомянутые выше). В этой сборке ядра не включен "earlyprintk", но звучит интересно, поэтому я попробую перестроить его. Jeremy 6 лет назад 0
Давайте [продолжим это обсуждение в чате] (http://chat.stackexchange.com/rooms/68772/discussion-between-jeremy-and-sawdust). Jeremy 6 лет назад 0
Извините, я недостаточно внимательно прочитал ваш пост. Поскольку вы можете оправиться от «зависания», набрав клавишу Enter и вернуться к приглашению U-Boot, это означает, что U-Boot никогда не пытался перейти к загрузке ядра; это билет в один конец. Зависание где-то (в U-Boot) при выполнении ** bootcmd ** перед (последним) переходом к ядру. Кстати, конечная точка с запятой в вашем модифицированном ** bootcmd ** не обязательна. Точка с запятой - это разделитель команд, а не терминатор. sawdust 6 лет назад 0
Извините, я не это имел ввиду. Я не могу избежать зависания, как только это произойдет (зависание на «Запуск ядра ...»). Я имел в виду, что я могу перезагрузить компьютер, нажмите «enter», чтобы прервать автоматическую загрузку, затем запустите «boot» вручную, и все работает нормально. Если я позволю тайм-ауту автоматической загрузки завершиться, он попытается загрузиться, а затем зависнет, как описано (и не может быть исправлено, кроме как с помощью цикла сброса / включения). Я попытался удалить лишнюю точку с запятой в моей команде загрузки (хорошо заметили!), Но это не имело никакого значения. Jeremy 6 лет назад 0

1 ответ на вопрос

0
Jeremy

После дополнительных экспериментов я обнаружил, что следующие РАБОТЫ :

bootcmd= setenv fdt_file imx6ull-14x14-evk.dtb;  setenv bootargs console=$,$ root=$;  mmc dev $; mmc rescan; fatload mmc $:$ $ $;  fatload mmc $:$ $ $;  bootz $ - $ 

... Но это FAILS :

bootcmd= setenv fdt_file imx6ull-14x14-evk.dtb;  setenv bootargs console=$,$ root=$;  mmc dev $; if true; then  mmc rescan;  fatload mmc $:$ $ $;  fatload mmc $:$ $ $;  bootz $ - $;  else  echo Boot FAILED: Couldnt find kernel or dtb; fi 

(Отформатировано на несколько строк для ясности). Под «сбоями» я подразумеваю, что при включении питания он ожидает истечения времени автозагрузки, загружает ядро ​​и dtb, затем висит на «Starting Kernel ...» и должен быть выключен или сброшен . Однако, если я нажимаю клавишу для прерывания автоматической загрузки, а затем набираю «boot» или «run bootcmd», он загружается нормально (хотя он запускает точно такой же сценарий).

Поэтому по какой-то причине использование оператора if в скрипте bootcmd (даже тривиального) нарушает его, хотя я не знаю почему.

Это не очень хороший ответ, но, по крайней мере, я получил его на работу. Первоначальный проект имел оператор if, проверяющий результат «mmc rescan», но, думаю, если это не удастся, он все равно остановится с некоторой ошибкой.