uboot学习及内核更换&&设备树及rootfs学习

官方文档
在前面

uboot常见命令学习

环境变量

Environment Variables环境变量
autostart 如果值为yes,则会在以下命令后自动执行bootm加载镜像

bootelf - Boot from an ELF image in memory
bootp - boot image via network using BOOTP/TFTP protocol
dhcp - boot image via network using DHCP/TFTP protocol
diskboot - boot from ide device
nboot - boot from NAND device
nfs - boot image via network using NFS protocol
rarpboot - boot image via network using RARP/TFTP protocol
scsiboot - boot from SCSI device
tftpboot - boot image via network using TFTP protocol
usbboot - boot from USB device

bootcmd 用户不进bootshell自动执行的命令
bootargs 传递给操作系统或镜像的参数
bootfile tftp时的镜像名
ipaddr tftpboot用到的ip地址
serverip tftpboot用到的tftp服务器地址

网络控制台

Network console
uboot启用network console
需要设置CONFIG_NETCONSOLE=y以启用特性。
使用方法:
使用ncip设置目的地址和端口号(默认6666),比如你的服务器ip是192.168.1.1:

=> setenv nc 'setenv stdout nc;setenv stdin nc'
=> setenv ncip 192.168.1.1
=> saveenv
=> run nc

在主机侧,使用脚本来访问控制台:

tools/netconsole <ip> [port]

主机侧也可以使用主机名
参考《【调试】netconsole的使用》
linux启用network console
如果想开启这个功能,需要内核编译支持,我这里的选项默认是:

CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=n

如果将netconsole编译进内核自动加载,还需要在内核启动参数中传递进去。格式如下:

netconsole=[src-port]@[src-ip]/[<dev>],[tgt-port]@<tgt-ip>/[tgt-macaddr]

例子:

netconsole=4444@10.0.0.1/eth1,9353@10.0.0.2/12:34:56:78:9a:bc
netconsole=@/,@192.168.3.1/

然后查看linux控制台输出:

nc -u -l -p 6666

uboot标准启动

U-Boot Standard Boot
bootdev 可保存或访问发行版的设备
bootmeth 扫描bootdev发现bootflow的方法
bootflow 描述启动方法(发行版提供)

其他

bootmenu 生成一个选单

升级uboot或内核

uboot.bin和uimg以及booti和bootm的区别

参考文章《编译生成uImage过程——mips平台》

uboot.bin是U-boot bootloader的二进制文件。
uImage是一个小内核映像,带有Uboot的修改头,使U-boot能够加载此内核映像

booti和bootm命令的区别

bootz是启动zImage,而bootm是启动uImage,其中booti专门用来启动ARM64的kernel image。

制作uImage

使用uboot的tools目录下的mkimage命令可以创建用于uboot的镜像,即uImage。
先加下这个命令:

$ sudo update-alternatives --install /usr/bin/mkimage mkimage /home/wsl/project/raspberry_pi/u-boot/tools/mkimage 10

常见参数

Usage: ./mkimage [-T type] -l image
          -l ==> list image header information
          -T ==> parse image file as 'type'
          -q ==> quiet
       ./mkimage [-x] -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image
          -A ==> set architecture to 'arch'
          -O ==> set operating system to 'os'
          -T ==> set image type to 'type'
          -C ==> set compression type 'comp'
          -a ==> set load address to 'addr' (hex)
          -e ==> set entry point to 'ep' (hex)
          -n ==> set image name to 'name'
          -R ==> set second image name to 'name'
          -d ==> use image data from 'datafile'
          -x ==> set XIP (execute in place)
          -s ==> create an image with no data
          -v ==> verbose
       ./mkimage [-D dtc_options] [-f fit-image.its|-f auto|-f auto-conf|-F] [-b <dtb> [-b <dtb>]] [-E] [-B size] [-i <ramdisk.cpio.gz>] fit-image
           <dtb> file is used with -f auto, it may occur multiple times.
          -D => set all options for device tree compiler
          -f => input filename for FIT source
          -i => input filename for ramdisk file
          -E => place data outside of the FIT structure
          -B => align size in hex for FIT structure and header
          -b => append the device tree binary to the FIT
          -t => update the timestamp in the FIT
Signing / verified boot options: [-k keydir] [-K dtb] [ -c <comment>] [-p addr] [-r] [-N engine]
          -k => set directory containing private keys
          -K => write public keys to this .dtb file
          -g => set key name hint
          -G => use this signing key (in lieu of -k)
          -c => add comment in signature node
          -F => re-sign existing FIT image
          -p => place external data at a static position
          -r => mark keys used as 'required' in dtb
          -N => openssl engine to use for signing
          -o => algorithm to use for signing
       ./mkimage -V ==> print version information and exit
Use '-T list' to see a list of available image types
Long options are available; read the man page for details

参考《uboot-tool工具命令mkimage详解uboot-tool工具命令mkimage详解》,一个典型的生成命令如下:

mkimage -A arm64 -O linux -T kernel -a 0x00080000 -e 0x00080040 -C none -n kernel-myconfig -d arch/arm64/boot/Image kernel.uImage

比较关键的是-e参数,-e 指定映象运行的入口点地址,这个地址就是-a参数指定的值加上0x40(因为前面有个mkimage添加的0x40个字节的头),关于参数,这里还有一份更全的文档可以参考。
使用上述命令后,内核无法启动,报错:

Working FDT set to 0
   Loading Kernel Image
FDT and ATAGS support not compiled in

resetting ...

因为没指定dtb文件的地址。

更换内核

暂时搞了这么几个env,可以用来运行

booti_kernel=booti ${kernel_addr_r} - ${fdt_addr}
dhcp_get_kernel=dhcp ${kernel_addr_r} kernel-myconfig.img
dhcpboot=run dhcp_get_kernel;run booti_kernel
fat_get_kernel=fatload mmc 0:1 ${kernel_addr_r} kernel-myconfig.img
fatboot=run fat_get_kernel;run booti_kernel

保存内核文件

使用fatwrite把文件写到sd卡中去:

U-Boot> help fatwrite
fatwrite - write file into a dos filesystem

Usage:
fatwrite <interface> <dev[:part]> <addr> <filename> [<bytes> [<offset>]]
    - write file 'filename' from the address 'addr' in RAM
      to 'dev' on 'interface'

具体操作:

fatwrite mmc 0:1 ${kernel_addr_r} kernel-myconfig.img 1abf200
28045824 bytes written in 4530 ms (5.9 MiB/s)

更换uboot

暂时用了个笨办法,先用dhcp把u-boot.bin取过来,然后用fatwrite写到boot分区,然后reset重新启动

uboot环境变量例子

一个自定义的uboot环境变量

HWID=TS-SG5036FX:02:04:01:0E:101:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
ID=000000000000000000
appauto=1
baudrate=115200
boardmodel=RTL9311_6x8214QF_1x8218E_4XGE_24GF_8GE_4XF
boot_flag=0
bootargs=mem=512M console=ttyS0,115200 rd_start=0x82000000 rd_size=0xd00000 root=/dev/ram0 rw init=/linuxrc
bootcmd=boota
bootdelay=1
bootflag=0
da=tftp 0x81000000 boot.bin.img; flwrite
dh_keyboard=0
dr=tftp 0x81000000 krootfs.bin.img; flwrite
drb=tftp 0x81000000 krootfs_backup.bin.img; flwrite
ethact=rtl9310#0
ethaddr=20:23:04:19:13:38
fileaddr=81000000
filesize=D74F38
gatewayip=172.14.48.1
ipaddr=172.14.49.120
ledModeInitSkip=0
netmask=255.255.255.0
serverip=10.33.7.176
stderr=serial
stdin=serial
stdout=serial
tk=tftp 0x81000000 krootfs.bin.img; bootm 0x81000000
up=tftp 0x81000000 update.img; flwrite

另一个:

=> printenv
HWID=TS-S6452-48GT4XF:02:04:03:01:1000:00:00:00:00:00:00:00:00:30:04:00:00:00:00:02:00
arch=arm
baudrate=115200
board=verif_soc928
board_name=verif_soc928
board_version=newboard
boot_nand=mw 0x83000000 0x0 0x2500000;tftpboot 0x83000000 fip_nand.bin;bootm 0x84400000 0x86000000:0x1600000 0x84200000
bootargs=console=ttyAMA0,115200 earlycon=pl011,mmio32,0x30225000 root=/dev/ram0 loglevel=0  startcode_version=1.1.21 uboot_version=1.1.21
bootcmd=run nos_bootcmd
bootdelay=2
cpu=armv8
dtbfilesize=1048576
fdtcontroladdr=b7fb3060
filesize=384000
mtdids=nand0=nand0
mtdparts=nand0:18m@0x0(boot),1m@0x1200000(env),512k@0x1300000(dgs),512k@0x1380000(private),492m@0x1400000(switch)
nos_basemac=00:3a:45:7f:e2:28
nos_boot=main
nos_bootcmd=ubi part switch; ubifsmount ubi0; if ubifsls main_uImage; then ubifsload 0x90000000 main_uImage; else ubifsload 0x90000000 backup_uImage; fi; bootm 0x90000000
rootfsfilesize=33554432
soc=soc928
stderr=uart@30225000
stdin=uart@30225000
stdout=uart@30225000
uimagefilesize=29360128
vendor=netfactory

另一个:

=> printenv 
arch=arm
baudrate=115200
board=verif_soc928
board_name=verif_soc928
board_version=newboard
boot_nand=mw 0x83000000 0x0 0x2500000;tftpboot 0x83000000 fip_nand.bin;bootm 0x84400000 0x86000000:0x1600000 0x84200000
bootargs=console=ttyAMA0,115200 earlycon=pl011,mmio32,0x30225000 root=/dev/ram0 loglevel=0  startcode_version=1.1.20 uboot_version=1.1.20
bootcmd=run nos_bootcmd
bootdelay=2
cpu=armv8
dtbfilesize=1048576
fdtcontroladdr=b7faf610
mtdids=nand0=nand0
mtdparts=nand0:18m@0x0(boot),54m@0x1200000(image0),54m@0x4800000(image1),1m@0x7f00000(env),128m@0x8000000(nos0),256m@0x10000000(nos1)
nos_basemac=00:3a:45:7a:a5:4f
nos_boot=pollux
nos_boot_castor=ubi part image0;run nos_ubiboot
nos_boot_pollux=ubi part image1;run nos_ubiboot
nos_bootcmd=if test $nos_boot = pollux; then run nos_boot_pollux; else run nos_boot_castor; fi;
nos_hardware_model=arm64-sf9228_48t6x_evb_a
nos_ubiboot=ubifsmount ubi0;ubifsload 0x90000000 uImage;bootm 0x90000000
rootfsfilesize=33554432
soc=soc928
stderr=uart@30225000
stdin=uart@30225000
stdout=uart@30225000
uimagefilesize=29360128
vendor=netfactory

一些答疑:

1.demo板设备和之前到的带壳设备的区别?版本是否通用?
没区别,通用
2.为何要升级uboot?
在uboot低于1.1.18时,需要先升级uboot,目的是支持内核双分区和内核升级功能
3.内核uImage与nos的bin文件为何要分开升级?nos不是文件系统吗
打包文件里的uImage由kernel/dtb/rootfs三个部分组成;nos是ubifs.
4.为何用uImage在uboot升级完内核之后还要再上传一遍内核?是因为bootm没实际写入吗?
tftpboot 0x90000000 uImage;bootm 0x90000000。下载到内存再引导
5.为何要擦除?有何作用?
分区发生变化
6.升级NOS的方式换了吗?不需要再使用命令升级了?
继续使用sys-update

裁剪内核模块(未完成)

pi@link:/lib/modules $ du -sh 6.1.21-v8+/
25M	6.1.21-v8+/
pi@link:/lib/modules $ du -sh 6.1.72-v8+/
333M	6.1.72-v8+/

新编译的树莓派的内核模块太多了,原版只有25m,新编的有300多m。

FIT Image相关知识学习

mkimage根据its的信息,把kernel,initramfs,dtb等编译成itb文件,可以直接在uboot中使用bootm启动,不需要在指定三个地址

一个制作rootfs的例子

	cd $(TARGET_OUTPUT_ROOTFS) && $(FIND) . | cpio -H newc -o --owner=root:root > $(TARGET_OUTPUT_ROOT)/rootfs.cpio
	cd $(TARGET_OUTPUT_ROOT) && gzip -f rootfs.cpio && $(RSYNC) rootfs.cpio.gz rootfs.cpio-$(ROOTFS_VERSION).gz

一个制作itb的例子,也即fit的镜像

MKUIMAGE = cd $(KERNELDIR)/arch/$(ARCH)/boot/ \
           && $(RSYNC) $(TARGET_OUTPUT_ROOT)/rootfs.cpio.gz rootfs.cpio.gz \
           && $(RSYNC) $(KERNELDIR)/../configs/$(LINUX_ITS) $(LINUX_ITS) \
		   && export PATH=$(KERNELDIR)/scripts/dtc:$(PATH) \
           && mkimage -f $(LINUX_ITS) image.itb

its文件例子:

/dts-v1/;
/{
    description = "U-Boot uImage source file for nos project";
    #address-cells = <1>;
    images{
        kernel{
            description = "Linux-5.10";
            data = /incbin/("./Image.gz");
            type = "kernel";
            arch = "arm64";
            os = "linux";
            compression = "gzip";
            load = <0x80200000>;
            entry = <0x80200000>;
            hash{
                algo = "crc32";
            };
        };
    
        initramfs {
            description = "initramfs";
            data = /incbin/("./rootfs.cpio.gz");
            type = "ramdisk";
            arch = "arm64";
            os = "linux";
            compression = "none";
            load = <0x84100000>;
            entry = <0x84100000>;
            hash {
                algo = "crc32";
            };
        };

        dtb {
            description = "nos-S6452.dtb";
            data = /incbin/("./dts/netfactory/soc928-nos-S6452.dtb");
            type = "flat_dt";
            arch = "arm64";
            os = "linux";
            compression = "none";
            load = <0x82300000>;
            hash {
                algo = "crc32";
            };
        };
	};

    configurations {
        default = "48GE";
        48GE {
            description = "48GE-r0";
            kernel = "kernel";
            ramdisk = "initramfs";
            fdt = "dtb";
        };
    };
};

分区查看

/proc/mtd存储系统磁盘分区信息

$ cat /proc/mtd 
dev:    size   erasesize  name
mtd0: 01200000 00020000 "boot"
mtd1: 00100000 00020000 "env"
mtd2: 00080000 00020000 "dgs"
mtd3: 00080000 00020000 "private"
mtd4: 1ec00000 00020000 "switch"

树莓派升级方案

需求:
1.无须反复插拔sd卡,通过网络即可升级
2.如果sd卡文件系统损坏,rootfs还有备份,或者能够拷贝出来(采用nfs作为root?)
3.如果新更换的内核有问题,要保证原系统还能启动,不受影响

方案1:
通过网络下载内核文件到boot分区,手动修改config.txt指定新的文件
缺点:会反复写sd卡
方案2:
从内存启动,不写入sd卡,考虑升级的便利性,通过树莓派编译uboot及内核中的尝试可知,在树莓派上,大概率已经自动把dtb文件加载到内存了。
可以参考《使用 u-boot 和 rootfs/Initramfs 启动 Raspberry Pi 4》类似的办法,来实现

参考

u-boot FIT image介绍
Device Tree: DTS/DTB/FDT
【Linux设备树】设备树基础 DTS,DTSI,DTC及DTB之间的关系
嵌入式ARM64 Linux内核FIT uimage方式启动
secure boot (一)fit image
df、cat /proc/mtd的区别
树莓派驱动之设备树覆盖
linux支持 zImage rootfs dtb 剥离 及 zImage和dtb拼接
Device Tree(六)Kernel 启动之 FIT-uImage
覆盖设备树(Devices-tree overlays)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值