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!
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.
User contributions licensed under CC BY-SA 3.0