首页 > 其他分享 >U-boot引导内核流程分析

U-boot引导内核流程分析

时间:2023-07-23 17:25:56浏览次数:57  
标签:kernel 流程 boot 地址 内核 镜像 环境变量

原文地址:https://blog.csdn.net/qq_28992301/article/details/51873201


U-boot引导内核流程分析

1. 加载内核

当U-boot完成重定位和初始化外设后,它将正式进入工作状态,可以加载内核镜像到DDR的链接地址中了,具体的地址也可以通过bootcmd这个环境变量来指定,内核镜像有两种加载方式:

  • 一种是通过tftp将镜像文件直接引导入DDR中内核的链接地址(对于s5pv210来说是30008000),这种方法很适合调试
  • 另一种是从存储介质中的特定扇区读取,这个扇区可以通过分区表来确定(关于分区表以后再续)

2.判断镜像

  • 加载内核到DDR的链接地址后,U-boot将读取镜像的头信息,然后在头信息的特定位置找到MAGIC_NUM,由此来判断镜像的种类。这里就要说一下内核镜像的种类了,内核镜像主要分为zImage和uImage
    • zImage:当内核编译完成之后首先生成的是一个elf文件,此文件类似于windows下的exe,是可以在操作系统下运行的,故里面有许多的信息;可是我们的kernel是个裸机程序,不需要在操作系统下运行,删除这些信息后体积便能缩为1/10,这就成了我们熟悉的.bin文件,但是因为一些原因这个文件名字起成了Image…而不是Image.bin….;其实这个Image文件已经能用了,但是由于一些历史原因,Image一般要经过压缩变成zImage再使用,这个zImage文件比Image文件更小,它是自解压的,它的头部是一段信息和解压程序,解压程序可以把后面真正的代码自动解压出来,并不需要U-boot的协助
    • uImage:uImage是U-boot自己发明的一种内核镜像格式,是在zImage的基础上在加上一段信息和一段校验头,共64字节。那么将zImage加工为uImage的工具在哪呢,在U-boot根目录下/tools中的mkimage程序,只需将其复制到/usr/local/bin/,编译内核时输入make uImage,然后就能产生uImage了
  • 判断完镜像种类后U-boot将对镜像头进行校验,然后再次读取头信息,从头信息的特定位置找到这个镜像的各种信息(镜像长度,镜像种类,入口地址)

4.相关环境变量

引导内核有关的环境变量有bootcmd和bootargs。之所以要有这两个环境变量其实是为了灵活,为了在U-boot不重新编译的情况下可以用不同的方式启动

  • 关于bootcmd,其实是U-boot内部好几个命令组成的命令集,负责引导内核的操作,以x210板载的bootcmd为例,bootcmd=movi read kernel 30008000;bootm 30008000;这其实是两句命令,第一句的意思是从inand的kernel分区读取内容到DDR内的地址30008000,第二句的意思是使用bootm启动命令到DDR的地址30008000处执行内核。其中,这个30008000是由内核的链接地址所确定的
  • 关于bootargs,其实是U-boot传递给内核的参数,以x210板载的bootargs为例,bootargs=console=ttySAC2,115200 root=dev/mmcblk0p2 rw init=/linuxrc rootfstype=ext3,其中,console=ttySAC2,115200意思是引导后的控制台使用串口2,波特率115200;root=/dev/mmcblk0p2 rw意思是根文件系统在SD卡端口0设备(inand)第二分区,并且可读可写;init=/linuxrc意思是linux的进程1(init)进程的路径;rootfstype=ext3 意思是根文件系统的类型是ext3

5.传参及引导

  • 最后把入口地址(ep)转化为一个函数指针theKernel = (void (*)(int, int, uint))ep,然后通过函数指针去执行镜像(即执行内核的第一句代码)。至此一去不复返,U-boot彻底结束了它的使命
void    (*theKernel)(int zero, int arch, uint params);//定义了一个函数指针
//中间代码略过
theKernel = (void (*)(int, int, uint))ep;//把入口地址赋给函数指针
//中间代码略过
theKernel (0, machid, bd->bi_boot_params);//跳到内核入口执行内核,再也不返回

执行前传递给内核三个参数:

  • 0:这个参数固定为0
  • 机器码:只有uboot的机器码和内核镜像中的机器码相同时,内核才能被正确启动,机器码的值第一顺序备选是环境变量machid,如果环境变量里面没有,则第二顺序备选是gd->bd->bi_arch_num(x210_sd.h中硬编码配置的)
  • bd->bi_boot_params:这是全局变量结构体gd中的硬件信息结构体bd中的变量bi_boot_params,它的值为U-boot传给kernel的众多参数数据结构——tag的首地址。各个tag里面分别有许多有用的信息,比如环境变量bootargs的各种参数就在tag里,一般来说有关tag的代码是不用动的,只要考虑那些用来创建tag的宏(x210.h内)就行了

6.补充:新版uboot与内核的传参与引导

近年来的内核在启动时还需要dts文件,于是比较新的uboot都实现了传递dtb的功能,为了使能设备树,需要在编译U-boot的时候在config文件中加入:#define CONFIG_OF_LIBFDT

  • 一般分为三种情况:
    • 利用U-boot的命令,在引导kernel时将dts传入。这种方式需要将dtb的地址写到uboot中(一般是环境变量),比如:首先将kernel载入内存,然后用fdt addr ${fdtaddr}命令将dtb载入内存,最后使用bootz ${loadaddr} ${initrdaddr} ${fdtaddr}来引导内核,(其中initrd是临时文件系统,嵌入式中用得极少)实际使用时用“-”代替:bootz ${loadaddr} - ${fdtaddr}。总之,U-boot中的命令和环境变量是很灵活的,可以随意组合
    • 将dts和kernel打包为pImage。这种方式无需将dtb的地址写到uboot中(但uboot中要实现读pImage头部的功能),uboot可以去pImage的头部信息处读取到dtb的地址,然后传给传递给kernel
    • 启用kernel中”ARM_APPENDED_DTB”选项,该选项的意思是将dtb和kernel打包在一起,如此一来kernel启动时会去紧挨着它的地方寻找dtb,这样就不需要uboot来传递dtb地址了

7.引导时可能出现的问题

最后强调一下,如果U-boot确认无误可以启动起来,而kernel的启动却出现了问题,那么一般是三种情况

  1. 对于老版本的U-boot,有大概率是U-boot传给kernel参数的时候出了问题,着重注意一下创建tag的宏有没有正常定义,如CONFIG_CMDLINE_TAG、CONFIG_MTDPARTITION等
  2. kernel的链接地址与加载地址不符,链接地址可以通过kernel的head.S获知,详见kernel启动汇编阶段分析
  3. kernel的自解压地址与链接地址不符,zImage这类kernel格式必须把自己解压到自己的链接地址,自解压地址在kernel源码目录arch/arm/mach-xxxx/Makefile.boot文件中
  4. 环境变量未被正常设置

标签:kernel,流程,boot,地址,内核,镜像,环境变量
From: https://www.cnblogs.com/bruce1992/p/17575269.html

相关文章

  • git的版本控制流程
    1、git是一款版本控制工具例如我们常用的淘宝,每次升级,版本号就会加一。那么我们怎么控制版本号呢?--使用git。 2、最常使用的git指令gitadd.暂存gitcommit-m"***"提交到本地gitpull将远程仓库代码下拉到本地gitpush提交到远程仓库不建议使用【GitBash】中......
  • 软件工程的基本流程
    目录软件工程的基本流程需求分析阶段数据流图软件工程的基本流程需求分析阶段:产品经理与客户/用户沟通,收集需求,明确项目目标和范围。确定功能和特性,创建产品需求文档(PRD)或用户故事。项目规划阶段:定义项目的时间表和里程碑。确定团队成员的角色和职责。分配资源和预......
  • springboot项目报错找不到mapper文件
    在使用SpringBoot中的MyBatis-Plus(简称MP)时,出现无法找到mapper.xml文件的错误,可能有以下几个原因:1.未正确配置mapper.xml文件路径:在SpringBoot中,可以通过在application.properties或application.yml文件中设置mybatis-plus.mapper-locations属性来指定mapper.xm......
  • springboot启动依赖冲突(log4j2)
    报错示例:LoggerFactoryisnotaLogbackLoggerContextbutLogbackison1.解决方案:<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId><......
  • springboot项目启动找不到外部入口url怎么办?
    启动类下输出控制面板直接打印@Slf4j@SpringBootApplicationpublicclassSpringboot03Application{publicstaticvoidmain(String[]args)throwsUnknownHostException{ConfigurableApplicationContextcontext=SpringApplication.run(Springboot03App......
  • 【嵌入式】构建嵌入式Linux系统(uboot、内核、文件系统)
    原文:https://zhuanlan.zhihu.com/p/573207792?utm_id=0知识架构及层次Linux内核由三部分构成:Bootloader:启动引导系统(可执行文件)Kernel:内核(可执行文件)RootFileSystem:根文件系统嵌入式Linux系统构成及启动略析嵌入式Linux启动类同4X100米接力跑,是由多个部分共同完成......
  • SpringBoot项目集成Mybatis Generator代码生成器
    添加依赖在项目的pom.xml文件中添加以下依赖<!--mybatisgenerator自动生成代码插件--><plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId>......
  • SpringBoot开发符合S3协议的文件存储服务
    背景公司最近的业务大量涉及安可项目,要求避免使用第三方组件,原有开发框架支持本地文件存储/Minio/各类云存储,现在要求文件独立存储且文件服务需要自研,经调研评估后决定基于SpringBoot开发文件存储服务,使用s3协议标准,这样可以直接使用aws-sdk接入无需再开发客户端,且安全安全性方面......
  • SpringBoot 自动装载 Bean
    我们在工作中经常会遇到这样的场景,我们写了很多非常实用的工具类,这些类在多个项目工程中使用非常频繁。如果在每个要使用的项目工程中都去编写加载bean的代码的话,那么重复的代码就太多了。如果你想追求完美只写一份代码的话,使用SpringBoot的自动装载的特性是一个很不错的方案......
  • typec role switch流程
    smblite_lib_typec_port_type_setschedule_delayed_work(&chg->role_reversal_check, msecs_to_jiffies(ROLE_REVERSAL_DELAY_MS));smblite_lib_typec_role_check_workstaticvoidsmblite_lib_typec_role_check_work(structwork_struct*work){s......