U-Bboot 无法自动启动,但手动启动可以正常进行

U-Bboot 无法自动启动,但手动启动可以正常进行

我使用 Buildroot 为 Freescale iMX6 EVK 板(基于 ARM)构建了一个映像。它从 SD 卡启动正常,我想在 U-Boot 中尝试自定义启动命令。我想使启动顺序尽可能精简和快速,因此我简化了 U-Boot 执行的一些检查和测试(例如,删除了对启动脚本和网络启动的检查)。

这是我的启动命令U-Boot 环境变量(格式化以便于阅读):

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

当我启动主板时,在“按任意键停止自动启动”之后,我得到了这个:

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

然后它挂在“启动内核...”阶段。

但是,如果我按回车键中断 U-Boot,则(从 U-Boot 提示符处)运行以下任一命令:

boot

或者

run bootcmd

它显示与上面完全相同的消息,但内核启动正常。

我比较了两种情况下的输出,发现它们在“启动内核”之前完全相同。我还添加了一行到启动命令打印出环境变量(printenv),并确认两种情况下的变量也相同。以下是最终的启动参数(印有echo ${bootargs}) - 两种情况下它们也相同:

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

我以为boot命令刚刚执行启动命令,并且如果没有被中断,自动启动过程也会执行同样的事情。

那么为什么我中断它并手动运行它还能起作用呢boot

====编辑====

根据 sawdust 的评论,我做了一些实验来澄清这个问题。

1/ 在内核构建中添加了‘earlyprintk’(内核黑客选项)。

这导致在成功启动时打印以下内容:

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

在启动失败时,它仍然停止在“启动内核......”(没有来自 earlyprintk 的其他信息)。

2/ 进一步破解 bootcmd 以澄清问题。

这是由全新构建创建的默认“bootcmd”环境变量(注意:通常这些都在一行上,即“bootcmd=....”;为清楚起见,在此格式化):

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

这有效(即启动延迟后自动启动)。

这是我的最小修改:

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;

我所做的只是删除外部的“if”结构(如果 mmc rescan;则...)。它仍然调用“mmc rescan”,并成功。

请注意,这是通过将以上内容放在一行('xxxx')并使用以下内容来保存的:

setenv bootcmd 'xxxxx'
saveenv

这会导致主板挂在“启动内核...”处,但如果我中断自动启动,进入 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 中有 Bug?u-boot 环境变量是否被破坏了?

注意:这现在不是一个主要问题,但我认为我们可以通过摆脱对我知道不存在的启动脚本的无意义搜索来节省一些时间,并且将来我们可能会因为其他原因而定制启动,我想知道它是否可以可预测地完成!

答案1

经过更多实验,我发现作品

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}

...但是这个失败

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

(为了清晰起见,格式化为多行)。“失败”是指在启动时,它会等待自动启动超时,加载内核和 dtb,然后挂在“正在启动内核...”处,并且必须关机或重置。但是,如果我按下一个键来中断自动启动,然后输入“boot”或“run bootcmd”,它就可以正常启动(尽管它运行的是完全相同的脚本)。

因此,出于某种原因,在 bootcmd 脚本中使用“if”语句(即使是一个简单的语句)也会破坏它,虽然我不知道为什么。

这不是一个很好的答案,但至少我让它工作了。最初的设计有一个 if 语句检查“mmc rescan”的结果,但我猜如果失败了,它可能会因为一些错误而停止。

相关内容