U-Bboot nie uruchamia się automatycznie, ale ręczne uruchamianie działa dobrze

1

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 bootpolecenie 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 bootrę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!

Jeremy
źródło
Twoje założenia dotyczące poleceń rozruchu CLI i automatycznego uruchamiania są prawidłowe. Co „usprawniłeś” i „usunąłeś” ? Czy to wszystko było w środowisku? Istnieje różnica między tymi dwoma scenariuszami, różnica w czasie. Możesz spróbować zwiększyć opóźnienie rozruchu, aby zasymulować dodatkowy czas na anulowanie automatycznego uruchamiania i wpisanie „boot” + Enter. Czy twoje jądro ma cichą lub pełną dekompresję (patrz stackoverflow.com/questions/46930346/... )?
trociny
Ustawiłem „bootdelay” na 6 sekund, ale to nie pomogło. Aby „usprawnić”, wybrałem domyślną zmienną env „bootcmd” i usunąłem bity, których nie używałem (np. Szukając skryptu rozruchowego, o którym wiem, że go nie ma). Teoretycznie powinien być funkcjonalnie taki sam jak poprzednio. Mogłem zrozumieć, jeśli wystąpił błąd podczas mojego odznaczania, ale nie mogę zrozumieć, dlaczego działa, gdy wywołuję go ręcznie za pomocą polecenia „boot”. Czy może być jakaś inna różnica oprócz opóźnienia?
Jeremy
Jądro używa cichej dekompresji, ponieważ przechodzi od „Uruchamianie jądra ...” do „Uruchamianie Linuksa na fizycznym procesorze 0x0” (kiedy ręcznie uruchamiam boot).
Jeremy,
Jeśli wczesnyprintk jest już skonfigurowany w jądrze, włącz go w wierszu poleceń jądra za pomocą zmiennej bootargs . Czy potrafisz odbudować jądro, aby uzyskać pełną dekompresję? To może pomóc określić, jak daleko posunęła się sekwencja rozruchowa (ponieważ jest to pośredni krok przed uruchomieniem jądra), jeśli nic nie dostaniesz dzięki wczesnemu drukowaniu .
trociny
Żeby było jasne, autoboot działał dobrze (z tymi samymi U-Bootami i obrazami jądra) zanim zrobiłeś „usprawnienie” ?
trociny

Odpowiedzi:

0

Po kolejnych eksperymentach odkryłem, że następujące DZIAŁANIA :

bootcmd=
setenv fdt_file imx6ull-14x14-evk.dtb; 
setenv bootargs console=${console},${baudrate} root=${mmcroot}; 
mmc dev ${mmcdev};
mmc rescan;
fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}; 
fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}; 
bootz ${loadaddr} - ${fdt_addr}

... Ale to NIE DZIAŁA :

bootcmd=
setenv fdt_file imx6ull-14x14-evk.dtb; 
setenv bootargs console=${console},${baudrate} root=${mmcroot}; 
mmc dev ${mmcdev};
if true; then 
 mmc rescan; 
 fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}; 
 fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}; 
 bootz ${loadaddr} - ${fdt_addr}; 
else 
 echo Boot FAILED: Couldnt find kernel or dtb;
fi

(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.

Jeremy
źródło