最近闲了5,6个月了, 偶尔拿出来自己之前的myir开发板,想玩一玩。想学点uboot移植的内容。
就自己看看了正点原子的教程。自己又在myir的官网看了有最新的uboot版本可以更新,所以自己尝试自己搞一下。先简单介绍一个自己的开发环境:
board: myir imx6ull-iot 板子, 256nand + 256dDDR.
官方提供的最新uboot版本路径:
MYIR (myir-tech.com)
上面写的有这连个BSP版本.
V1 | GA | 2018-05-12 | 初始版本,Linux4.1.15 |
V2 | RC | 2022-07-27 | 软件升级至Linux5.10.9 |
本来的呢,我想这用V2 bsp版本的uboot-source直接编译一个uboot,然后用到V1的mfg tool 直接烧录的。
虽然烧录的没问题,但是启动的时候遇到这个问题,zimage: Bad magic!
U-Boot 2020.04-gf362e0d-dirty (Dec 15 2022 - 13:23:48 +0800)CPU: i.MX6ULL rev1.0 528 MHz (running at 396 MHz)
CPU: Commercial temperature grade (-40C to 115C) at 46C
Reset cause: POR
Model: i.MX6 ULL 14x14 EVK Board
Board: MX6ULL 14x14 EVK
DRAM: 256 MiB
NAND: 256 MiB
MMC: FSL_SDHC: 0
Loading Environment from NAND... *** Warning - bad CRC, using default environment[*]-Video Link 0 (480 x 272)
In: serial
Out: serial
Err: serial
Net:
Warning: ethernet@2188000 (eth0) using random MAC address - 4e:46:c0:a0:25:3f
eth0: ethernet@2188000
Fastboot: Normal
Normal Boot
Hit any key to stop autoboot: 3 2 1 0 NAND read: device 0 offset 0x600000, size 0xa0000010485760 bytes read: OKNAND read: device 0 offset 0x1000000, size 0x1000001048576 bytes read: OK
zimage: Bad magic!
=>
从这个情况看uboot 是已经启动了,当时怀疑是不是必须要跟V2 BSP的kernel 匹配呢? 不匹配不能用?? 后来思考,既然是更新的uboot,当然也应该能用的,也许某些地方需要修改。
从这个log看,应该是zimage 启动的时候没有启动成功,然后就刷回原来的V1的uboot, 打印了一下
uboot env参数;具体V1的参数如下:
baudrate=115200board_name=MYS6ULLboard_rev=14X14bootargs=console=ttymxc0,115200 ubi.mtd=3 root=ubi0:rootfs rootfstype=ubifs mtdparts=gpmi-nand:5m(boot),10m(kernel),1m(dtb),-(rootfs)bootcmd=nand read ${loadaddr} 0x500000 0xA00000;nand read ${fdt_addr} 0xF00000 0x100000;bootz ${loadaddr} - ${fdt_addr}bootcmd_mfg=run mfgtool_args;bootz ${loadaddr} ${initrd_addr} ${fdt_addr};bootdelay=3console=ttymxc0ethact=FEC0ethprime=FECfdt_addr=0x83000000 // 1fdt_high=0xffffffffinitrd_addr=0x83800000initrd_high=0xffffffffloadaddr=0x80800000 // 2mfgtool_args=setenv bootargs console=${console},${baudrate} rdinit=/linuxrc g_mass_storage.stall=0 g_mass_storage.removable=1 g_mass_storage.file=/fat g_mass_storage.ro=1 g_mass_storage.idVendor=0x066F g_mass_storage.idProduct=0x37FF g_mass_storage.iSerialNumber="" mtdparts=gpmi-nand:5m(boot),10m(kernel),1m(dtb),-(rootfs) clk_ignore_unused panel=TFT43AB
从上面看我们是有4个分区: 5M - boot, 10M - kernel, 1M - dtb, 剩下的rootfs.
然后停留在boot当中,想用bootz 启动,但是直接执行bootz 0x80800000 - 0x83000000
还是报这个错误。 zimage: Bad magic!
当时就怀疑是不是执行这个需要操作一下其他的呢?
后来就搜了一下bootz的启动参数意义, 具体解释如下:
bootz命令根据给定的kernel、dtb在ddr中的地址,去启动内核。可以通过多种方式(tftp命令、fatload命令等方式将zImage、dtb加载到ddr指定位置)
输入参数1:zImage_addr
输入参数2:dtb_addr
也就是说他是从DDR当中的kernel 和dtb的地址去启动内核的
# if zimage_addr=80800000 dtb_addr=83000000
tftp 80800000 zImage
tftp 83000000 xxxx.dtb
bootz 80800000 - 83000000
又看了一下boot命令的含义:
boot命令执行uboot环境变量bootcmd中定义好的一组命令来启动系统。这一组命令一般包含
1)将kernel dtb拷贝到ddr指定位置的命令
2)bootz或者bootm命令
# 执行boot命令则执行环境变量bootcmd中定义好的命令
# 测试该命令,可以自定定义bootcmd命令,如下所示:
# 下面使用双引号包含多个命令,命令之间用分号隔开,单引号也可以
setenv bootcmd "tftp 80800000 zImage;tftp 83000000 xxxx.dtb;bootz 80800000 - 83000000"
saveenv # 做测试可以不保存,如果保存了,聚会写入环境变量区
boot
也就是说boot命令是直接执行的我们在uboot 用print打印出来的bootcmd的命令。
从上面的bootcmd= " " 这个参数,我们可以看到,会执行nand read 命令;
这就是理解为什么bootz我们直接启动失败了,因为现在Image dts 这些东西现在还是存在nand里面,你需要先读出来读到DDR里面啊。
所以就跟进了uboot命令的 nand read。
nand read 理解:
此命令用于从 NAND 中的指定地址读取指定大小的数据到 DRAM 中,命令格式如下:
nand read addr off size
addr 是目的地址,off 是要读取的 NAND 中的数据源地址,size 是要读取的数据大小。比如我们读取设备树(dtb)文件到 0x83000000 地址处,命令如下:
nand read 0x83000000 0x6000000 0x19000
从上面的nand read 命令,我们可以看出原来V1版本的bootcmd的格式可以分解为是:
bootargs=console=ttymxc0,115200 ubi.mtd=3 root=ubi0:rootfs rootfstype=ubifs mtdparts=gpmi-nand:5m(boot),10m(kernel),1m(dtb),-(rootfs)
bootcmd=nand read ${loadaddr} 0x500000 0xA00000;nand read ${fdt_addr} 0xF00000 0x100000;bootz ${loadaddr} - ${fdt_addr}
1. nand read 0x80800000 0x500000 0xA00000
2. nand read 0x83000000 0xF00000 0x100000
3. bootz 0x80800000 - 0x83000000
所以执行了以上3条命令,boot可以启动内核。
回到原来的问题,但是我现在的问题还是没解决呢(用v2的bsp uboot镜像,只烧uboot还是没启动内核)。
所以这个时候想是不是这个地方出现问题呢???
又换成V2版本uboot烧录之后启动到显示 bad zImage magic ,然后执行上面的这3条命令。
uboot 也启动成功了。看来问题就定位了,原来是bootz的启动有问题。
打印了一下V2uboot的启动地址和boot cmd 参数。
bootargs=console=ttymxc0,115200 ubi.mtd=rootfs root=ubi0:rootfs rootfstype=ubifs mtdparts=gpmi-nand:5m(boot),10m(kernel),1m(dtb),-(rootfs)
bootcmd=nand read ${loadaddr} 0x600000 0xA00000;nand read ${fdt_addr} 0x1000000 0x100000;if test ${tee} = yes; then nand read ${tee_addr} 0x6000000 0x400000;bootm ${tee_addr} - ${fdt_addr};else bootz ${loadaddr} - ${fdt_addr};fi
V2 boot arg:
bootargs=console=ttymxc0,115200 ubi.mtd=rootfs root=ubi0:rootfs rootfstype=ubifs mtdparts=gpmi-nand:5m(boot),1m(env),10m(kernel),1m(dtb),-(rootfs)
bootcmd=nand read ${loadaddr} 0x600000 0xA00000;nand read ${fdt_addr} 0x1000000 0x100000;if test ${tee} = yes; then nand read ${tee_addr} 0x6000000 0x400000;bootm ${tee_addr} - ${fdt_addr};else bootz ${loadaddr} - ${fdt_addr};fi
对比一下V1 bsp版本的是不是有很大区别:
从上我们可以看出 V2 mtdparts 多了一个env的分区。
bootcmd参数也是有变化的,相比较之前多了一个tee的判断,这个tee我们不必去管他,因为print打印出来的变量值是no。所以没有问题,具体这个是干什么的呢?这个我猜测是和安全相关的tee 分区。有兴趣的可以了解一下android的tee这个东西。好了,回到原来的问题:
V2的nand read 地址也是有所偏移:
这个时候我们基本可以确定了问题。按照上述修改,修改成和V1 bsp的启动参数一样的就可以了。
具体修改目录如下:
进到 uboot的include/configs/mys-6ull-14x14.h
进行如下修改:
#define MFG_NAND_PARTITION "mtdparts=gpmi-nand:64m(nandboot),16m(nandkernel),16m(nanddtb),16m(nandtee),-(nandrootfs)"*/
-#define MFG_NAND_PARTITION "mtdparts=gpmi-nand:5m(boot),1m(env),10m(kernel),1m(dtb),-(rootfs) "
+#define MFG_NAND_PARTITION "mtdparts=gpmi-nand:5m(boot),10m(kernel),1m(dtb),-(rootfs) "#else#define MFG_NAND_PARTITION ""#endif
@@ -92,8 +92,8 @@BOOTARGS_CMA_SIZE \MFG_NAND_PARTITION \"\0" \
- "bootcmd=nand read ${loadaddr} 0x600000 0xA00000;"\
- "nand read ${fdt_addr} 0x1000000 0x100000;"\
+ "bootcmd=nand read ${loadaddr} 0x500000 0xA00000;"\
+ "nand read ${fdt_addr} 0xF00000 0x100000;"\"if test ${tee} = yes; then " \"nand read ${tee_addr} 0x6000000 0x400000;"\"bootm ${tee_addr} - ${fdt_addr};" \
修改内核启动参数的读取nand地址偏移量和分区情况。
然后编译,烧录。
问题解决。
移植过程当中学习到的东西:
uboot 命令: nand read 命令,bootz 命令,print命令