uboot 中 bootm 和 bootz 的区别
bootm
用于加载 uImage 和 ramdisk;
uImage 必须是 mkimage 打包过的内核映像(在 zImage 前加入了 64 字节的头信息,bootm 需要解析该信息);
在 uboot 命令行上的用法:
-
只加载 uImage:
1
bootm ${kernel_load_address}
-
加载 uImage 和 ramdisk:
1
bootm ${kernel_load_address} ${ramdisk_load_address}
-
加载 uImage、ramdisk 以及 dtb:
1
bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}
bootz
用于加载 zImage 和 ext4 根文件系统;
内核编译(make)后会生成两个文件:Image 和 zImage,区别在于 zImage 是压缩映像;
在 uboot 命令行上的用法:
命令示例:
tftp 80800000 zImage
tftp 83000000 imx6ull.dtb
bootz 80800000 – 83000000
1
bootz ${kernel_load_address} - ${devicetree_load_address}
uboot 中 bootargs 和 bootcmd
bootargs
类别介绍
bootargs 是记录启动参数的 uboot 环境变量,有如下类:
-
root :用来指定 rootfs 的位置
1 2 3 4
root=/dev/ram0 rw # ram root=/dev/nandd rw # nand root=/dev/mmcblk0p7 rw # mmc root=/dev/nfs # nfs
-
rootfstype :根文件系统类型,如果是 ext2 可不指明
1
rootfstype=yaffs2
-
console :指定调试串口
1 2
console=ttyS0,115200 console=ttySAC0,115200n8
-
mem :指定内存大小,非必须
1
mem=xxxM
-
ramdisk_size :指定创建的 ramdisk 的 size,默认 4M
1
ramdisk_size=xxx
-
initrd, noinitrd :没有使用 ramdisk 启动系统的时候,需要使用 noinitrd 这个参数
r_addr 表示 initrd 在内存中的位置,size 表示 initrd 的大小;
1
initrd=r_addr,size
-
init :指定进入 rootfs 后运行的第一个脚本
如下
/init
指的是 rootfs 根目录下的 init 文件,一般情况下是一个链接;1 2
inti=/init init=/etc/preinit
-
mtdparts :内存技术设备
要想这个参数起作用,内核需要勾选 mtd 驱动的支持:Device Drivers —> Memory Technology Device (MTD) support—> Command line partition table parsing
1
mtdparts=fc000000.nor_flash:1920k(linux),128k(fdt),20M(ramdisk),4M(jffs2),38272k(user),256k(env),384k(uboot)
-
ip :指定系统启动后网卡的 IP 地址,基于 nfs 的文件系统必须要有该参数
which netcard 指你的网卡名称,如 eth0;
如果为了使用 NFS 或者只为了 ping 通,那只需设置三个就行(ipaddr、serverip、网卡名),其他任意填;
1 2
ip=ip addr ip=ip addr:server ip addr:gateway:netmask::which netcard:off
常见示例
-
假设文件系统是 ramdisk,且直接就在内存中
1
setenv bootargs 'initrd=0x32000000,0xa00000 root=/dev/ram0 console=ttySAC0 mem=64M init=/linuxrc'
-
假设文件系统是 ramdisk,且在 flash 中
这种情况下需要在 bootcmd 环境变量中的 bootm 命令中指定 ramdisk 在 flash 中的地址,如 bootm kernel_addr ramdisk_addr (fdt_addr)
1
setenv bootargs 'mem=32M console=ttyS0,115200 root=/dev/ram rw init=/linuxrc'
-
假设文件系统是 jffs2 类型的,且在 flash 中
1
setenv bootargs 'mem=32M console=ttyS0,115200 noinitrd root=/dev/mtdblock2 rw rootfstype=jffs2 init=/linuxrc'
-
假设文件系统是基于 nfs 的
1
setenv bootargs 'noinitrd mem=64M console=ttySAC0 root=/dev/nfs nfsroot=192.168.0.3:/nfs ip=192.168.0.5:192.168.0.3:192.168.0.3:255.255.255.0::eth0:off'
或者
1
setenv bootargs ’noinitrd mem=64M console=ttySAC0 root=/dev/nfs nfsroot=192.168.0.3:/nfs ip=192.168.0.5‘
bootcmd
bootcmd 是记录每次启动时默认会执行的一系列命令的 uboot 环境变量;
uboot 命令行方式
比如在 uboot 命令行设置 bootcmd 环境变量,并保存:
第一次需要手动执行跳转,后续不需要;
1
2
3
4
5
setenv bootargs 'console=ttyS0,115200 root=/dev/mmcblk1p2 rootwait panic=10'
setenv bootcmd 'load mmc 1:1 0x41800000 sun8i-a33-sinlinx-sina33.dtb; load mmc 1:1 0x41000000 zImage; bootz 0x41000000 - 0x41800000'
saveenv
接着重启系统或输入 boot
(boot 命令会执行 bootcmd 环境变量中的指令);
文件方式
-
首先确保 uboot 中
include/configs/xxx.h
中存在目标定义1 2 3
#define CONFIG_EXTRA_ENV_SETTINGS \ "script=boot.scr\0" \ ... ...
-
新建 boot.cmd
1 2 3 4 5
setenv bootargs 'console=ttyS0,115200 root=/dev/mmcblk1p2 rootwait panic=10' load mmc 1:1 0x41800000 sun8i-a33-sinlinx-sina33.dtb load mmc 1:1 0x41000000 zImage bootz 0x41000000 - 0x41800000
-
将 boot.cmd 转换为 boot.scr
1
mkimage -C none -A arm -T script -d boot.cmd boot.scr
-
将 boot.scr 放入 boot 分区,复位即可(也可想办法编译到大包中,这样烧写大包后就可用);
和主线 uboot 对比制作 uboot 补丁
补丁是什么
补丁文件是通过对比 修改文件
和 源码文件
后得到的记录修改的文件。
-
发布时,我们只需要分享该补丁文件;
-
其他人收到该补丁文件,自行下载 uboot 主线源码上打上此补丁,就可以得到我们适配好的 uboot;
对比文件夹的方式制作
工作目录下有:
- uboot 源码压缩包(u-boot-2020.07.tar.bz2)
- 适配好的 uboot 文件夹(u-boot-2020.07)
1
2
3
4
5
6
7
8
9
10
11
# 1.进入 u-boot-2020.07 清除编译产生的文件(包括配置文件)
cd u-boot-2020.07
make distclean
# 2.返回工作目录,对适配好的 uboot 文件夹重命名,并解压源码生成原始 uboot 文件夹
cd ..
mv u-boot-2020.07 u-boot-2020.07-has-patch
tar -vxf u-boot-2020.07.tar.bz2
# 3.制作补丁 diff -urN OldDir NewDir > patch_name
diff -uNr u-boot-2020.07 u-boot-2020.07-has-patch > 0001-v2020.07.11.patch
通过 git diff 的方式制作
1
2
3
4
5
# 1.查看最近两次修改的 commit id
git log
# 2.制作补丁
git diff commitid_orginal commitid_new > test.patch
通过 git format-patch 的方式制作
1
2
3
4
5
6
7
8
9
10
11
### HEAD 后有几个 ^ 就会生成几个 patch,从最近一次开始生成
# 根据最近的一次提交生成 1 个 patch
git format-patch HEAD^
# 根据最近的两次提交生成 2 个 patch
git format-patch HEAD^^
### 根据数字生成对应数量的 patch,从最近一次开始生成
# 根据最近的一次提交生成 1 个 patch
git format-patch -1
# 根据最近的两次提交生成 2 个 patch
git format-patch -2
给主线 uboot 打补丁
补丁用了文件夹的方式的情况
1
2
3
# patch -p<数字n> < 补丁文件,其中数字 n 表示忽略前 n 级目录
# 补丁在 uboot 源码上级目录制作,这里在源码目录中打补丁,需要忽略 1 级目录
patch -Np1 < ../0001-v2020.07.11.patch
补丁用了 git diff 的方式的情况
1
git apply test.patch
补丁用了 git format-patch 的方式的情况
1
2
3
4
5
# 1.[可选]丢弃之前所有的 add 和 commit
git am --abort
# 2.打入 patch 目录中所有的补丁
git am patch/*.patch
打补丁后编译 uboot
1
2
3
make distclean
make xxx_config
make
额外的:全志 soc 使用 dd 命令快速更新固件方法
已知在 uboot 源码 /include/spare_head.h 中有宏定义:
#define BOOT0_SDMMC_START_ADDR (16)
#define UBOOT_START_SECTOR_IN_SDMMC (32800)
更新 boot0
boot0_sdcard.fex 由 boot0_sdcard_sun8iw11p1.bin 在 pack 后生成在 tools/pack/out 目录,一般大小为 32Kb;
16 来自宏定义 BOOT0_SDMMC_START_ADDR;
1
sudo dd if=boot0_sdcard.fex of=/dev/mmcblk0 bs=512 seek=16
更新 uboot
u-boot.fex 由 u-boot-sun8iw11p1.bin 在 pack 后生成在 tools/pack/out 目录,一般大小为 1024Kb;
32800 来自宏定义 UBOOT_START_SECTOR_IN_SDMM;
1
sudo dd if=u-boot.fex of=/dev/mmcblk0 bs=512 seek=32800