U-Bboot won't autoboot but manual boot works fine

1

I've built an image for a Freescale iMX6 EVK board (ARM based), using Buildroot. It booted fine off an SD card, and I wanted to experiment with customized boot commands in U-Boot. I want to make the boot sequence as lean and fast as possible, so I streamlined some of the checks and tests done by U-Boot (e.g. removed the check for a boot script and network boot).

Here's my bootcmd U-Boot env variable (formatted for easy reading):

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

when I power up the board, after the "Hit any key to stop autoboot", I get this:

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

It then hangs at the "Starting kernel ..." stage.

HOWEVER, if I interrupt U-Boot by pressing enter, then (from the U-Boot prompt) run either of these commands:

boot

or

run bootcmd

It shows the exact same messages as above, but then the kernel starts OK.

I've compared the outputs in both cases and they are identical up to "Starting kernel". I also added a line to bootcmd to print out the env variables (printenv), and confirmed that the variables are also identical in both cases. Here are the final bootargs (printed with echo ${bootargs}) - these too are the same in both cases:

console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait ro 

I thought the boot command just executed bootcmd, and that the autoboot process did the same thing if not interrupted.

So why does it work if I interrupt it and run boot manually?

==== EDIT ====

Following comments from sawdust, I did some more experiments to clarify the problem.

1/ Added 'earlyprintk' to kernel build (Kernel hacking options).

This caused the following to be printed on a SUCCESSFUL boot:

Starting kernel ...
Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0x0

On a FAILED boot, it still stops at "Starting kernel ..." (no additional information from earlyprintk).

2/ Further hacking of bootcmd to clarify the problem.

Here's the default "bootcmd" env variable, created by a fresh build (Nb: Normally this is all on one line, i.e. "bootcmd=...."; formatted here for clarity):

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

This works (i.e. auto boots after the boot delay).

Here's my minimal modification:

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;

All I did was remove the outer 'if' structure (if mmc rescan; then...). It still calls "mmc rescan", which succeeds.

Note this is saved by putting the above on one line ('xxxx'), and using:

setenv bootcmd 'xxxxx'
saveenv

This causes the board to hang at "Starting kernel ...", but if I interrupt the auto boot, enter the u-boot prompt then use "boot", it boots fine.

I can change back to the original bootcmd and it works correctly (autoboot is OK) so I think the method for changing the variable is OK.

I saw one weird thing at one point when I changed it over to my version:

Starting kernel ...
resetting ...

[Board Rebooted itself!]

U-Boot 2016.03 (Nov 16 2017 - 07:08:36 +1300)

[Auto-boot]

Starting kernel ...    
[Hang.]

From then on, it was back to hanging unless I interrupt the boot and enter "boot" command.

Bug in u-boot? u-boot environment variables somehow being corrupted?

Nb: This is not a major issue right now, but I think we could save some ms by getting rid of the pointless search for a boot script that I know isn't there, and in the future we might have reason to customize the boot for some other reason and I'd like to know that it it could be done predictably!

Jeremy

Posted 2017-11-14T19:24:45.350

Reputation: 393

Your assumptions about the CLI boot commands and autoboot are correct. What did you "streamline" and "remove"? Was this all in the environment? There is a difference between the two scenarios, a difference in time. You could try increasing the bootdelay to simulate the additional time to cancel autoboot & typing "boot"+Enter. Does your kernel have silent or verbose uncompression (see https://stackoverflow.com/questions/46930346/uncompressing-is-not-happening-with-zimage-while-booting-up-with-u-boot/47009714#47009714)?

– sawdust – 2017-11-14T20:38:29.307

I set the "bootdelay" to 6 seconds, but this didn't help. For "streamlining", what I did was unpick the default "bootcmd" env variable and removed bits I wasn't using (e.g. searching for a boot script which I know isn't there). It should be functionally the same as before, in theory. I could understand if there was an error in my unpicking, but what I can't figure out is why it works when I call it manually with "boot" command. Could there be any other difference other than the delay? – Jeremy – 2017-11-14T21:51:41.450

Kernel is using silent uncompression, as it goes straight from "Starting kernel ..." to "Booting Linux on physical CPU 0x0" (when I manually run the boot). – Jeremy – 2017-11-14T21:53:01.323

If earlyprintk is already configured in the kernel, then enable it in the kernel command line via the bootargs variable. Can you rebuild the kernel so that you have verbose uncompression? That could help tell how far the boot sequence has progressed (since it's an intermediate step before the kernel starts) if you get nothing with earlyprintk. – sawdust – 2017-11-14T22:15:12.897

To be clear, autoboot used to work just fine (with the same U-Boot and kernel images) before you did the "streamlining"? – sawdust – 2017-11-14T22:40:48.653

Yes, autoboot was working fine - although it gave some errors such as not being able to find boot.scr (expected). I just confirmed this (reset the SD card image back the default, tested booting, then repeated the changes mentioned above). I don't have "earlyprintk" turned on in this kernel build, but it sounds interesting so I will try rebuilding with it on. – Jeremy – 2017-11-15T02:01:42.230

Let us continue this discussion in chat.

– Jeremy – 2017-11-15T17:44:22.300

Sorry, I didn't read your post carefully enough. Since you can recover from the "hang" by typing the Enter key and get back to the U-Boot prompt, then that means that U-Boot never tried to jump to boot the kernel; that's a one-way ticket. The hang is somewhere (in U-Boot) while executing bootcmd, before the (final) jump to the kernel. BTW the trailing semicolon in your modifed bootcmd is not necessary. The semicolon is a command separator, and not a terminator. – sawdust – 2017-11-16T00:39:05.013

Sorry, that wasn't what I meant. I CANNOT escape the hang once it happens (hung at "Starting Kernel..."). I meant that I can reboot, press "enter" to interrupt the auto boot, then run "boot" manually, and it works fine. If I let the auto boot timeout finish, it tries to boot then hangs as described (and can't be fixed except with a reset / power cycle). I tried removing the extra semi-colon in my boot command (well spotted!) but that made no difference. – Jeremy – 2017-11-19T21:59:38.133

Answers

0

After more experiments, I have discovered that the following WORKS:

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}

...But this FAILS:

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

(Formatted onto multiple lines for clarity). By "fails", I mean that on power up, it waits for the auto-boot timeout, loads the kernel and dtb, then hangs at "Starting Kernel..." and must be powered off or reset. However, if I press a key to interrupt the auto-boot, then type "boot" or "run bootcmd", it boots fine (although it's running exactly the same script).

So, for some reason, using an "if" statement in the bootcmd script (even a trivial one) breaks it, although I don't know why.

This is not a great answer, but at least I got it to work. The original design had the if statement checking the result of "mmc rescan", but I guess if that fails, it will probably stop with some error anyway.

Jeremy

Posted 2017-11-14T19:24:45.350

Reputation: 393