此系列博客,仅对Xilinx平台PS端(ARM部分)开发做介绍,不对PL(FPGA)做过多介绍。
目录
7.5 bootm_os_get_boot_func
七. bootz启动Linux内核
7.1 images全局变量
此全局变量在启动Linux内核时多处会用到,至关重要
结构体定义在 include/image.h中
变量定义在 common/bootm.c或者cmd/bootm.c
7.2 do_bootz
bootz 命令的执行函数为 do_bootz,在文件 cmd/bootz.c 中定义
- 执行bootz_start
- 关闭中断
- 设置启动系统为Linux
- do_bootm_states 来执行不同的 BOOT 阶段,这里要执行的 BOOT 阶段有:BOOTM_STATE_OS_PREP 、BOOTM_STATE_OS_FAKE_GO 和BOOTM_STATE_OS_GO
7.3 bootz_start
- 设置系统镜像启动位置,(启动脚本中设置)
- 判断是否为Linux镜像,从传递进来的参数 image(也就是系统镜像首地址)中获取 zimage 头
- bootm_find_images:查找设备树(dtb)文件
7.4 do_bootm_states
根据不同的 BOOT 状态执行不同的代码段
1.BOOTM_STATE_OS_PREP:
调用函数 do_bootm_linux,do_bootm_linux也是调用 boot_prep_linux 来完成具体的处理过程。boot_prep_linux 主要用于处理环境变量bootargs,bootargs 保存着传递给 Linux kernel 的参数
2. BOOTM_STATE_OS_GO:
调用函数 boot_selected_os 启动 Linux 内核,此函数第 4 个参数为 Linux 系镜像头,第 5 个参数就是 Linux 系统启动函数,boot_fn在这里实际就是 do_bootm_linux
7.5 bootm_os_get_boot_func
查找对应系统的启动函数
7.6 do_bootm_linux
启动Linux内核的函数,在arch/arm/bootm.c中
调用boot_prep_linux: 设备树的chosen节点下添加子节点bootargs存放启动参数bootargs的值
调用boot_jump_linux:
1.kernel_entry(armv7使用): 此函数是进入 Linux 内核的, 此函数有三个参数:zero,arch,params,第一个参数 zero 同样为 0;第二个参数为机器 ID;第三个参数 ATAGS 或者设备树(DTB)首地址,ATAGS 是传统的方法,用于传递一些命令行信息啥的,如果使用设备树的话就要传递设备树(DTB)
2.获取kernel_entry(armv7使用): 函数 kernel_entry 并不是 uboot 定义的,而是 Linux 内核定义的,Linux 内核镜像文件的第一行代码就是函数 kernel_entry,而 images->ep 保存着 Linux内核镜像的起始地址,起始地址保存的正是 Linux 内核第一行代码
3. announce_and_cleanup: 打印一些信息并做一些清理工作
4. do_nonsec_virt_switch: armv8架构支持多核,唤醒其他CPU
5.跳转到内核armv8_switch_to_el2: 第一个参数images->ft_addr传递Linux内核使用的设备树地址,保存在X0寄存器,第四个参数images->ep传递了内核入口函 数,armv8_switch_to_el2中,br x4:x4寄存器的值为传递过来的内核入口函数地址
八. 环境变量
8.1 bootargs
bootargs 保存着 uboot 传递给 Linux 内核的参数,uboot会将此变量值保存在Linux设备树的chosen节点下,也可以提前在设备树设置
Linux内核最后会在设备树中的chosen节点查找此变量的值; bootargs 环境变量也可以由 mmcargs 设置的,mmcargs 环境变量如下: mmcargs=setenv bootargs console=${console},${baudrate} root=${mmcroot}
其中 console=ttymxc0,baudrate=115200,mmcroot=/dev/mmcblk1p2 rootwait rw,因此将
mmcargs 展开以后就是:
mmcargs=setenv bootargs console= ttymxc0, 115200 root= /dev/mmcblk1p2 rootwait rw
可以看出环境变量 mmcargs 就是设置 bootargs 的值为:
“console= ttymxc0, 115200 root= /dev/mmcblk1p2 rootwait rw”,bootargs 就是设置了很多的参数的值,这些参数 Linux 内核会使 用到,常用的参数有:
1、console
console 用来设置 linux 终端(或者叫控制台),也就是通过什么设备来和 Linux 进行交互,是
串口还是 LCD 屏幕?如果是串口的话应该是串口几等等。一般设置串口作为 Linux 终端,这样 我们就可以在电脑上通过 SecureCRT 来和 linux 交互了。这里设置 console 为 ttymxc0,因为 linux
启动以后串口 1 在 linux 下的设备文件就是/dev/ttymxc0,在 Linux 下,一切皆文件。
ttymxc0 后面有个“,115200”,这是设置串口的波特率,console=ttymxc0,115200 综合起来就是设置 ttymxc0(也就是串口 1)作为 Linux 的终端,并且串口波特率设置为115200。
2、root
root 用来设置根文件系统的位置,root=/dev/mmcblk1p2 用于指明根文件系统存放在
mmcblk1 设备的分区 2 中。EMMC 版本的核心板启动 linux 以后会存在/dev/mmcblk0、
/dev/mmcblk1、/dev/mmcblk0p1、/dev/mmcblk0p2、/dev/mmcblk1p1 和/dev/mmcblk1p2 这样的文件,其中/dev/mmcblkx(x=0~n)表示 mmc 设备,而/dev/mmcblkxpy(x=0~n,y=1~n)表示 mmc 设备x 的分区 y。/dev/mmcblk1 表示 EMMC,而/dev/mmcblk1p2 表示
EMMC 的分区 2。
root 后面有“rootwait rw”,rootwait 表示等待 mmc 设备初始化完成以后再挂载,否则的话mmc 设备还没初始化完成就挂载根文件系统会出错的。rw 表示根文件系统是可以读写的,不加rw 的话可能无法在根文件系统中进行写操作,只能进行读操作。
3、rootfstype
此选项一般配置 root 一起使用,rootfstype 用于指定根文件系统类型,如果根文件系统为ext 格式的话此选项无所谓。如果根文件系统是 yaffs、jffs 或 ubifs 的话就需要设置此选项,指定根文件系统的类型
8.2 bootcmd
bootcmd 保存着 uboot 默认命令,uboot 倒计时结束以后就会执行 bootcmd 中的命令。这些命令一般都是用来启动 Linux 内核的,比如读取 EMMC 或 者 NAND Flash 中的 Linux 内核镜像文件和设备树文件到 DRAM 中,然后启动 Linux 内核。
如果 EMMC 或者 NAND 中没有保存 bootcmd 的值,那么 uboot 就会使用默认的值(include/env_default.h),板子第一次运行 uboot 的时候都会使用默认值来设置 bootcmd 环境变量
uboot 的启动流程就到此结束,下一篇将会介绍Linux内核启动过程