uboot加载kernel,ramdisk,dtb的内存布局问题

uboot在加载kernel,ramdisk,dtb时,要注意内存布局。
否则,会出现各种问题,例如
machine ID问题,calibrating delay 问题等等。
这些都是因为kernel在启动时,找不到dtb而产生的。
又例如
ramdisk could not found 问题。
这是因为kernel启动时,不能在initrd指定的问题找到有效格式的RAMDISK导致的。
这些问题,都涉及到uboot加载时的内存布局。

我们加载时,会用到
load_uimage或者load_zimage命令行。

load_uimage=fatload mmc 0 ${kernel_load_address} ${kernel_image} && fatload mmc 0 ${devicetree_load_address} ${devicetree_image} && fatload mmc 0 ${ramdisk_load_address} ${ramdisk_image}

load_zimage=fatload mmc 0 ${kernel_zimage_load_address} ${kernel_zimage} && fatload mmc 0 ${devicetree_load_address} ${devicetree_image} && fatload mmc 0 ${ramdisk_zimage_load_address} ${ramdisk_zimage}

kernel_load_address=0x2080000
ramdisk_load_address=0x7fffc0
devicetree_load_address=0x1000000
kernel_zimage_load_address=0x8000
ramdisk_zimage_load_address=0x800000

kernel_zimage=zImage
ramdisk_zimage=zramdisk.image.gz
ramdisk_image=uramdisk.image.gz

可以看到,他们都是用到fatload命令,从SD卡中读取文件到指定的内存地址中。

如果需要用uImage启动,那么uenvcmd如下:
uenvcmd=run mmc_loadbit_fat && echo Copying Linux from SD to RAM… && run load_uimage && echo run kernel_boot_uimage… && run kernel_bootm

如果需要从zImage启动,那么uenvcmd如下:
uenvcmd=run mmc_loadbit_fat && echo Copying Linux from SD to RAM… && run load_zimage && echo run kernel_boot_zimage… && run kernel_bootz

两者的区别在于:
uImage用的是bootm命令启动的。

kernel_bootm=bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}

而zImage用的是bootz命令启动的。
kernel_bootz=bootz ${kernel_zimage_load_address}

在新版uboot中,我们使用bootz命令,只是希望它取代go命令。并不希望它完成搬移RAMDISK和DTB的功能。
所以bootz的操作,就是在指定的地址上,解压zImage,然后跳转到start address,启动内核。

这里就涉及到bootm对uImage的处理方式的理解了。
bootm识别UBOOT格式的镜像,uImage相比zImage,多了0x40个字节的U_HEADER。
(1)当bootm识别出加载的是uImage时,且TYPE为kernel,那么会去比较source address 和load address。
如果两者相等,那么不执行move操作。
然后会记下entry address,之后start kernel时,会跳转到entry address。后续操作和bootz一样。
所以,此时,entry addr = 0x40 + load addr。
如果两者不相等,那么执行move操作。
注意,这个时候,bootm的特殊地方就来了。
为了避免跑飞,bootm在搬移kernel时,去掉了U_HEADER,然后把净剩载荷move到load address上。也就是说,zImage被move。
所以,此时,entry addr = load addr。

(2)当bootm识别出加载的是uImage时,且TYPE为RAMDISK
由于不是kernel,所以不记下load address 和 entry address。
然后move到RAM的高段地址区。并返回一个地址区间start和end,供内核进行虚拟地址映射使用。

(3)当bootm识别出加载的是DTB时,
由于不是UIMAGE格式,所以不存在load address和entry address。
然后move到RAM的高段地址区。并返回一个地址区间start和end,供内核进行虚拟地址映射使用。

由于TYPE的区别,我们在mkimage时,使用的选项是不同的。
生成kernel的命令如下:
mkimage -A arm -O linux -T kernel -C none -a 00008000 -e 00008000 -n linux-kernel -d ./zImage ./uImage
生成kernel的命令如下:
mkimage -A arm -O linux -T ramdisk -C gzip -n uboot ramdisk -d ./zramdisk.image.gz ./uramdisk.image.gz

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值