iMX6 获取 U-Boot 以临时启动另一个 U-Boot
iMX6 get U-Boot to temporarily boot another U-Boot
首先是一些背景:
我们在基于 iMX6 的嵌入式系统中有以下设置。有两个 U-Boot 分区和两个系统 (Linux) 分区。目前我们只使用第一个 U-Boot 分区,它使用标准方法来选择、运行宁和(如果需要)回滚系统分区。
我们现在正在研究升级 U-Boot 本身的类似方案(这种情况很少发生,但我们确实希望能够做到这一点而不必 return 将设备设置为基础)。
然而,这更充满危险,因为一旦您告诉 iMX6 设备从备用 U-Boot 分区启动,就是这样 - 没有 U-Boot/watchdog 组合会恢复到前一个,如果启动失败,所以一个错误的更新 运行 会导致设备变砖的严重风险,直到我们可以 return 将其修复(这是一个昂贵的选择,这就是我们试图尽可能减轻它的原因).
选择的方法是两步U-Boot安装程序,包括'write'和'activate'。它依赖于我们成功确定如果设备重新启动(所选分区)哪个 U-Boot 分区将 运行 以及当前 运行(启动分区)的能力。我们已经解决了这个问题。
但我们缺少的一点是 UBoot 在某些情况下将控制转移到 other UBoot 分区的能力。我们得到它仅基于 UBoot 环境执行不同的操作,如下所示:
首先,mmcboot
添加了一个前缀,以便它检查控制权转移,特别是它被设置为 run ub_xfer_chk ; <original content of mmcboot>
。
其次,我们有一个变量 ub_xfer_flag
通常设置为 0
。
第三,我们有校验函数ub_xfer_chk
,定义为:
if test ${ub_xfer_flag} -eq 1 ; then
echo Soft-booting other UBoot...
setenv ub_xfer_flag 0
saveenv
weave_magic
fi
weave_magic
代码是我们遇到麻烦的地方 :-) 这个想法是,这会将另一个 UBoot 分区加载到内存中(在 0x1780000
的 CONFIS_SYS_TEXT_BASE
处)并且执行它就像实际设备已经完成一样。
我们已经通过使用 reset
代替 weave_magic
测试了此解决方案的主要内容,它成功地重启了设备一次,因此我们确信我们可以保证它的安全。
那么我的具体问题是:我如何说服 U-Boot 从另一个分区加载第二个副本并 运行 它?
两个 UBoot 分区位于可从系统分区访问的 /dev/mmcblk3boot0
和 /dev/mmcblk3boot1
设备中,并且是 2M 文件,包括 1K 导入头和末尾的一些填充.
更新:
我们实际上取得了一些的成功,并设法使用以下命令从引导分区加载 IMX 映像:
ext4load mmc ${mmcdev}:${mmcpart} 0x17800000 ${bootdir}/u-boot.imx
但是,当尝试执行它时:
go 0x17800000
我们收到非法指令并立即重启:
pc : [<17800070>] lr : [<4ff83c64>]
sp : 4f579ac0 ip : 00000030 fp : 4f57be58
r10: 00000002 r9 : 4f579efc r8 : 4ffbe2b0
r7 : 4f57be68 r6 : 17800000 r5 : fffff200 r4 : 000002cc
r3 : 17800000 r2 : 4f57be6c r1 : 4f57be6c r0 : 00000000
Flags: nZCv IRQs off FIQs off Mode SVC_32
Resetting CPU ...
所以我猜那不是该文件开头的可执行代码。关于从这里去哪里有什么想法吗?
IMX文件中的实际代码不在开头。你可以通过使用 excellent on-line disassembler 和 armv5 big-endian no-thumb
架构来发现这个事实,找出开头的字节经常给你无效的 and/or not-very-sensible 代码:
ldtdmi a1, [a1], -a2 ; <UNPREDICTABLE>
strne a1, [a1, a1]
andeq a1, a1, a1
ldrbne pc, [pc, -ip, lsr #8]! ; <UNPREDICTABLE>
在任何情况下,IMX 文件开头的数据已知是 header 信息(开头的 d1
是一个 "magic" 标记,表示 IVT header 之后还应该有一个 DCD 块。然而,即使 超出 IVT 和 DCD 块(基于它们在 header 字段中声称的长度),代码不合理。
但是,在一大块 0x00
字节之后的偏移量 0xc00
处有可行的信息:
00000be0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000bf0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000c00: 0f00 00ea 14f0 9fe5 14f0 9fe5 14f0 9fe5 ................
00000c10: 14f0 9fe5 14f0 9fe5 14f0 9fe5 14f0 9fe5 ................
将偏移量 0xc00
处的十六进制字节放入反汇编程序,并调整分支跳过的区域,显示有效的 和 合理的 ARM 代码。
而且,事实上,通过以下方式剥离 IMX 文件:
dd if=u-boot.imx bs=1 skip=3072 of=ub-at-c00.imx
应该给你一个可以启动的文件:
ext4load mmc ${mmcdev}:${mmcpart} 0x17800000 ${bootdir}/ub-at-c00.imx
go 0x17800000
当我们这样做时,它输出:
U-Boot 2014.04 (Nov 07 2018 - 19:05:32)
CPU: Freescale i.MX6Q rev1.5 at 792 MHz
CPU: Temperature 32 C, calibration data: 0x5764e169
Reset cause: unknown reset
Board: DTI BRD0208 (Spitfire I) 05/01/2017
I2C: ready
DRAM: 1 GiB
我们知道这是较新的 UBoot,因为我们使用的普通 UBoot 输出日期是 10 月而不是 11 月。
不幸的是,它在那一刻挂起,看门狗定时器最终启动并重新启动回到原来的 UBoot,但我怀疑这与 UBoot 不喜欢设备的当前状态有关(即,它不我不喜欢将它初始化两次)。
所以我们必须弄清楚如何说服它这样做,但至少我们已经让它启动了自己的另一个副本,这就是问题所在。
首先是一些背景:
我们在基于 iMX6 的嵌入式系统中有以下设置。有两个 U-Boot 分区和两个系统 (Linux) 分区。目前我们只使用第一个 U-Boot 分区,它使用标准方法来选择、运行宁和(如果需要)回滚系统分区。
我们现在正在研究升级 U-Boot 本身的类似方案(这种情况很少发生,但我们确实希望能够做到这一点而不必 return 将设备设置为基础)。
然而,这更充满危险,因为一旦您告诉 iMX6 设备从备用 U-Boot 分区启动,就是这样 - 没有 U-Boot/watchdog 组合会恢复到前一个,如果启动失败,所以一个错误的更新 运行 会导致设备变砖的严重风险,直到我们可以 return 将其修复(这是一个昂贵的选择,这就是我们试图尽可能减轻它的原因).
选择的方法是两步U-Boot安装程序,包括'write'和'activate'。它依赖于我们成功确定如果设备重新启动(所选分区)哪个 U-Boot 分区将 运行 以及当前 运行(启动分区)的能力。我们已经解决了这个问题。
但我们缺少的一点是 UBoot 在某些情况下将控制转移到 other UBoot 分区的能力。我们得到它仅基于 UBoot 环境执行不同的操作,如下所示:
首先,mmcboot
添加了一个前缀,以便它检查控制权转移,特别是它被设置为 run ub_xfer_chk ; <original content of mmcboot>
。
其次,我们有一个变量 ub_xfer_flag
通常设置为 0
。
第三,我们有校验函数ub_xfer_chk
,定义为:
if test ${ub_xfer_flag} -eq 1 ; then
echo Soft-booting other UBoot...
setenv ub_xfer_flag 0
saveenv
weave_magic
fi
weave_magic
代码是我们遇到麻烦的地方 :-) 这个想法是,这会将另一个 UBoot 分区加载到内存中(在 0x1780000
的 CONFIS_SYS_TEXT_BASE
处)并且执行它就像实际设备已经完成一样。
我们已经通过使用 reset
代替 weave_magic
测试了此解决方案的主要内容,它成功地重启了设备一次,因此我们确信我们可以保证它的安全。
那么我的具体问题是:我如何说服 U-Boot 从另一个分区加载第二个副本并 运行 它?
两个 UBoot 分区位于可从系统分区访问的 /dev/mmcblk3boot0
和 /dev/mmcblk3boot1
设备中,并且是 2M 文件,包括 1K 导入头和末尾的一些填充.
更新:
我们实际上取得了一些的成功,并设法使用以下命令从引导分区加载 IMX 映像:
ext4load mmc ${mmcdev}:${mmcpart} 0x17800000 ${bootdir}/u-boot.imx
但是,当尝试执行它时:
go 0x17800000
我们收到非法指令并立即重启:
pc : [<17800070>] lr : [<4ff83c64>]
sp : 4f579ac0 ip : 00000030 fp : 4f57be58
r10: 00000002 r9 : 4f579efc r8 : 4ffbe2b0
r7 : 4f57be68 r6 : 17800000 r5 : fffff200 r4 : 000002cc
r3 : 17800000 r2 : 4f57be6c r1 : 4f57be6c r0 : 00000000
Flags: nZCv IRQs off FIQs off Mode SVC_32
Resetting CPU ...
所以我猜那不是该文件开头的可执行代码。关于从这里去哪里有什么想法吗?
IMX文件中的实际代码不在开头。你可以通过使用 excellent on-line disassembler 和 armv5 big-endian no-thumb
架构来发现这个事实,找出开头的字节经常给你无效的 and/or not-very-sensible 代码:
ldtdmi a1, [a1], -a2 ; <UNPREDICTABLE>
strne a1, [a1, a1]
andeq a1, a1, a1
ldrbne pc, [pc, -ip, lsr #8]! ; <UNPREDICTABLE>
在任何情况下,IMX 文件开头的数据已知是 header 信息(开头的 d1
是一个 "magic" 标记,表示 IVT header 之后还应该有一个 DCD 块。然而,即使 超出 IVT 和 DCD 块(基于它们在 header 字段中声称的长度),代码不合理。
但是,在一大块 0x00
字节之后的偏移量 0xc00
处有可行的信息:
00000be0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000bf0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000c00: 0f00 00ea 14f0 9fe5 14f0 9fe5 14f0 9fe5 ................
00000c10: 14f0 9fe5 14f0 9fe5 14f0 9fe5 14f0 9fe5 ................
将偏移量 0xc00
处的十六进制字节放入反汇编程序,并调整分支跳过的区域,显示有效的 和 合理的 ARM 代码。
而且,事实上,通过以下方式剥离 IMX 文件:
dd if=u-boot.imx bs=1 skip=3072 of=ub-at-c00.imx
应该给你一个可以启动的文件:
ext4load mmc ${mmcdev}:${mmcpart} 0x17800000 ${bootdir}/ub-at-c00.imx
go 0x17800000
当我们这样做时,它输出:
U-Boot 2014.04 (Nov 07 2018 - 19:05:32)
CPU: Freescale i.MX6Q rev1.5 at 792 MHz
CPU: Temperature 32 C, calibration data: 0x5764e169
Reset cause: unknown reset
Board: DTI BRD0208 (Spitfire I) 05/01/2017
I2C: ready
DRAM: 1 GiB
我们知道这是较新的 UBoot,因为我们使用的普通 UBoot 输出日期是 10 月而不是 11 月。
不幸的是,它在那一刻挂起,看门狗定时器最终启动并重新启动回到原来的 UBoot,但我怀疑这与 UBoot 不喜欢设备的当前状态有关(即,它不我不喜欢将它初始化两次)。
所以我们必须弄清楚如何说服它这样做,但至少我们已经让它启动了自己的另一个副本,这就是问题所在。