Zbudowałem obraz dla płyty Freescale iMX6 EVK (opartej na ARM), używając Buildroot. Uruchomił się dobrze z karty SD i chciałem eksperymentować z niestandardowymi poleceniami rozruchowymi w U-Boot. Chcę, aby sekwencja rozruchu była możliwie jak najbardziej szybka i szybka, więc usprawniłem niektóre kontrole i testy wykonywane przez U-Boot (np. Usunąłem test skryptu rozruchowego i rozruchu sieciowego).
Oto moja zmienna env bootcmd U-Boot env (sformatowana w celu łatwego odczytu):
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
kiedy włączam tablicę, po „Naciśnij dowolny klawisz, aby zatrzymać automatyczne uruchamianie”, otrzymuję:
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 ...
Następnie zawiesza się na etapie „Uruchamianie jądra ...”.
JEDNAK, jeśli przerwę U-Boot, naciskając klawisz Enter, wówczas (z wiersza polecenia U-Boot) uruchom jedno z poniższych poleceń:
boot
lub
run bootcmd
Pokazuje dokładnie takie same komunikaty jak powyżej, ale wtedy jądro uruchamia się OK.
Porównałem dane wyjściowe w obu przypadkach i są one identyczne jak „Uruchamianie jądra”. Dodałem również wiersz do bootcmd, aby wydrukować zmienne env ( printenv
), i potwierdziłem, że zmienne są również identyczne w obu przypadkach. Oto ostatnie bootargsy (wydrukowane przy pomocy echo ${bootargs}
) - one też są takie same w obu przypadkach:
console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait ro
Myślałem, że boot
polecenie właśnie wykonało bootcmd i że proces automatycznego uruchamiania zrobił to samo, jeśli nie został przerwany.
Dlaczego więc działa, jeśli przerywam i uruchamiam boot
ręcznie?
==== EDYCJA ====
Po komentarzach z trocin przeprowadziłem kilka eksperymentów, aby wyjaśnić problem.
1 / Dodano „earlyprintk” do kompilacji jądra (opcje hakowania jądra).
Spowodowało to, że na SUKCESOWYM rozruchu zostały wydrukowane następujące informacje:
Starting kernel ...
Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0x0
Po uruchomieniu FAILED nadal zatrzymuje się na „Uruchamianie jądra ...” (brak dodatkowych informacji z wczesnego odcisku).
2 / Dalsze hakowanie bootcmd w celu wyjaśnienia problemu.
Oto domyślna zmienna env „bootcmd”, utworzona przez świeżą kompilację (Nb: normalnie jest to wszystko w jednym wierszu, tj. „Bootcmd = ....”; sformatowane tutaj dla przejrzystości):
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
Działa to (tj. Automatyczne uruchamianie po opóźnieniu rozruchu).
Oto moja minimalna modyfikacja:
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;
Wszystko, co zrobiłem, to usunięcie zewnętrznej struktury „if” (jeśli ponowne skanowanie mmc; to ...). Nadal nazywa się „mmc rescan”, co się powiedzie.
Uwaga: zapisuje się to poprzez umieszczenie powyższego w jednym wierszu („xxxx”) i użycie:
setenv bootcmd 'xxxxx'
saveenv
Powoduje to, że płyta zawiesza się przy „Uruchamianiu jądra ...”, ale jeśli przerywam automatyczne uruchamianie, wprowadź monit u-boot, a następnie użyj „boot”, uruchamia się dobrze.
Mogę wrócić do pierwotnego bootcmd i działa poprawnie (automatyczne uruchamianie jest OK), więc myślę, że metoda zmiany zmiennej jest OK.
W pewnym momencie zobaczyłem jedną dziwną rzecz, kiedy zmieniłem ją na moją wersję:
Starting kernel ...
resetting ...
[Board Rebooted itself!]
U-Boot 2016.03 (Nov 16 2017 - 07:08:36 +1300)
[Auto-boot]
Starting kernel ...
[Hang.]
Odtąd wróciło do zawieszenia, chyba że przerwę bootowanie i wprowadzę polecenie „boot”.
Błąd podczas uruchamiania? zmienne środowiskowe u-boot jakoś są uszkodzone?
Uwaga: Nie jest to obecnie poważny problem, ale myślę, że moglibyśmy zaoszczędzić trochę ms, pozbywając się bezsensownego wyszukiwania skryptu rozruchowego, o którym wiem, że go nie ma, a w przyszłości możemy mieć powód, aby dostosować boot z innego powodu i chciałbym wiedzieć, że można to zrobić w sposób przewidywalny!
źródło
Odpowiedzi:
Po kolejnych eksperymentach odkryłem, że następujące DZIAŁANIA :
... Ale to NIE DZIAŁA :
(Sformatowane w wielu liniach dla zachowania przejrzystości). Przez „awarię” mam na myśli, że po włączeniu zasilania czeka on na limit czasu automatycznego uruchamiania, ładuje jądro i dtb, a następnie zawiesza się przy „Uruchamianiu jądra ...” i musi zostać wyłączony lub zresetowany . Jeśli jednak naciśniesz klawisz, aby przerwać automatyczne uruchamianie, a następnie wpisz „boot” lub „run bootcmd”, uruchomi się dobrze (chociaż działa dokładnie ten sam skrypt).
Z jakiegoś powodu użycie instrukcji „if” w skrypcie bootcmd (nawet trywialnym) psuje ją , chociaż nie wiem dlaczego.
To nie jest świetna odpowiedź, ale przynajmniej udało mi się to. Oryginalny projekt zawierał instrukcję if sprawdzającą wynik „mmc rescan”, ale myślę, że jeśli to się nie powiedzie, prawdopodobnie i tak zakończy się jakiś błąd.
źródło