【Xilinx】MPSOC启动流程(六)- Uboot

此系列博客,仅对Xilinx平台PS端(ARM部分)开发做介绍,不对PL(FPGA)做过多介绍。

目录

七. bootz启动Linux内核

7.1 images全局变量

​​​​​​​7.2 do_bootz

​​​​​​​7.3 bootz_start

​​​​​​​7.4 do_bootm_states

​​​​​​​7.5 bootm_os_get_boot_func

​​​​​​​7.6 do_bootm_linux

八. 环境变量

8.1 bootargs

​​​​​​​8.2 bootcmd


七. 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 中定义

  1. 执行bootz_start
  2. 关闭中断
  3. 设置启动系统为Linux
  4. do_bootm_states 来执行不同的 BOOT 阶段,这里要执行的 BOOT 阶段有:BOOTM_STATE_OS_PREP 、BOOTM_STATE_OS_FAKE_GO 和BOOTM_STATE_OS_GO

​​​​​​​7.3 bootz_start

  1. 设置系统镜像启动位置,(启动脚本中设置)
  2. 判断是否为Linux镜像,从传递进来的参数 image(也就是系统镜像首地址)中获取 zimage 头
  3. 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=ttymxc0baudrate=115200mmcroot=/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 内核会使 用到,常用的参数有:

1console

console 用来设置 linux 终端(或者叫控制台),也就是通过什么设备来和 Linux 进行交互,是

串口还是 LCD 屏幕?如果是串口的话应该是串口几等等。一般设置串口作为 Linux 终端,这样 我们就可以在电脑上通过 SecureCRT 来和 linux 交互了。这里设置 console ttymxc0,因为 linux

启动以后串口 1 linux 下的设备文件就是/dev/ttymxc0,在 Linux 下,一切皆文件。

ttymxc0 后面有个“,115200”,这是设置串口的波特率,console=ttymxc0,115200 综合起来就是设置 ttymxc0(也就是串口 1)作为 Linux 的终端,并且串口波特率设置为115200

2root

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 的话可能无法在根文件系统中进行写操作,只能进行读操作。

3rootfstype

此选项一般配置 root 一起使用,rootfstype 用于指定根文件系统类型,如果根文件系统为ext 格式的话此选项无所谓。如果根文件系统是 yaffsjffs 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内核启动过程

猜你喜欢

转载自blog.csdn.net/qq_37755518/article/details/130213888