【移植】02.bootloader
【嵌入式八股】一、语言篇https://www.nowcoder.com/creation/manager/columnDetail/mwQPeM
【嵌入式八股】二、计算机基础篇https://www.nowcoder.com/creation/manager/columnDetail/Mg5Lym
【嵌入式八股】三、硬件篇https://www.nowcoder.com/creation/manager/columnDetail/MRVDlM
【嵌入式八股】四、嵌入式Linux篇(本专栏)https://www.nowcoder.com/creation/manager/columnDetail/MQ2bb0
bootloader
08.什么是bootloader?
嵌入式芯片启动过程全解析,彻底理解bootloader_哔哩哔哩_bilibili
Bootloader(引导加载程序)是一段位于计算机系统启动区的特殊程序,主要负责加载操作系统的内核(kernel)并将控制权交给它,从而启动计算机系统。Bootloader 是计算机启动过程中的第一个程序,它需要能够识别和加载操作系统内核、初始化硬件设备并设置一些基本参数等。
在 Linux 操作系统中,常用的 Bootloader 有 LILO、GRUB、u-boot 等。其中,GRUB 是最常见的 Bootloader,它能够识别多种文件系统格式,支持网络引导、多操作系统启动等功能。u-boot 是一款开源的 Bootloader,主要用于嵌入式系统中,支持多种处理器架构和设备,能够通过网络、串口等多种方式进行引导。
09.BootLoader的启动过程大多可以分为哪两个阶段?
第一阶段是汇编的,完成一些依赖于CPU体系结构的初始化,并调用第二阶段的代码。
第二阶段是C语言的,进一步完成硬件初始化,建立内存映射,并将内核映像和根文件系统读取到内存中,然后调用内核。
10.Uboot的启动流程
uboot启动过程中做了那些事?
arch级的初始化
-
关闭中断,设置svc模式
-
禁用MMU、TLB
-
关键寄存器的设置,包括时钟、看门狗的寄存器
板级的初始化
-
C语言执行环境初始化(堆栈环境的设置)
-
前置板级初始化(重定位前),包括时钟、定时器、环境变量、串口、内存的初始化(到C语言了,前面都是汇编)
-
进行代码重定向
代码重定向之后的板级初始化
- 后置板级初始化(重定位后)、串口(进一步初始化)、看门狗、中断、定时器、网卡等等的初始化。
- 内核映象和根文件系统映象重定位(从 Flash上读到SDRAM空间中)
- 启动内核或进入命令行状态,等待终端输入命令以及对命令进行处理,为内核设置启动参数
- 跳转到Linux内核所在的地址运行(直接修改PC寄存器的值为Linux内核所在的地址)
转到Linux内核所在的地址运行现在发展出了新形式,非传统方式启动内核。将内核作为根文件系统的一个文件,通过/boot/extlinux/extlinux.conf配置内核启动路径(原理:内存加载ramdisk放内核运行,因为现在内核是应用层的一个文件),方便更换内核,甚至板子自己编译内核,自己替换
11.Uboot启动之前还需要做哪些事情?
u-boot不是上电的第一个程序,第一个是固化在cpu内部iRom中的程序(只读),厂商会提供一些可信固件(如flash内存时钟等最初始的一些初始化),还有提供一些加密验证功能,避免破解和黑客攻击。
12.为什么uboot中汇编和C程序都有
如果都是汇编,难写难维护
如果都是C,不能操作各种特殊寄存器、异常操作和工作模式转换,只能汇编来操作。还要给C语言的环境初始化,如一些栈的设置,也得汇编操作。
13.Uboot如何引导内核启动的?
- 加载内核映像:首先,U-Boot 需要加载 Linux 内核映像(通常是一个 zImage 或者 Image 文件)到内存中,以便之后的启动。可以使用 U-Boot 提供的命令
load
或者loady
来从存储介质(如 Flash、SD 卡等)中加载内核映像。 - 设置启动参数:在加载内核映像之后,U-Boot 需要设置启动参数,包括 Linux 内核的启动地址、命令行参数、设备树文件等。这些参数可以使用 U-Boot 提供的环境变量来设置,如
bootargs
、bootcmd
等。 - 启动内核:最后,U-Boot 调用
bootm
命令启动 Linux 内核。bootm
命令会把内核映像加载到内存中,然后跳转到内核的启动地址开始执行。在启动内核之前,U-Boot 还会将设置的启动参数传递给内核。
14.uboot和内核如何完成参数传递?
在启动 Linux 内核的过程中,U-Boot 和内核之间需要进行参数传递,这些参数通常包括内核的启动参数、设备树文件、根文件系统等信息。U-Boot 和内核之间的参数传递可以通过以下几种方式实现:
- 命令行参数:U-Boot 可以通过环境变量
bootargs
设置 Linux 内核的启动参数,如串口波特率、根文件系统、IP 地址等。这些参数会被传递给内核作为启动参数,内核启动后可以通过/proc/cmdline
文件读取这些参数。 - 设备树文件:U-Boot 可以加载设备树文件,并将设备树地址和大小传递给内核。内核在启动时会将设备树文件加载到内存中,并用于初始化硬件和设备驱动。U-Boot 通过
bootm
命令的-d
参数指定设备树文件的地址,内核启动后可以通过of_flat_dt
系列函数来访问设备树信息。 - 内存映像地址:U-Boot 可以将 Linux 内核的内存映像地址传递给内核,以便内核启动时能够正确加载和执行。这通常通过
bootm
命令的-s
参数来指定。 - 其他参数:除了上述参数之外,U-Boot 还可以通过其他方式向内核传递参数,如通过寄存器或者内存地址来传递参数。这些方式需要在 U-Boot 和内核中进行相应的设置和处理。
15.为什么要给内核传递参数呢?
在 Linux 系统中,内核是整个系统的核心组件,负责管理和控制硬件设备、文件系统、进程等资源。在内核启动时,可以通过传递一些参数来配置内核的行为和功能,这些参数可以影响内核的启动、初始化、设备驱动等方面。给内核传递参数可以帮助内核更好地适应不同的硬件平台和应用场景,提高系统的稳定性和可靠性,方便用户进行系统的定制和调试。
以下是一些常见的需要传递给内核的参数:
- 内核启动参数:包括 rootfs(根文件系统)、console(控制台)、loglevel(日志级别)等,这些参数可以用来指定内核的启动方式和基本配置。
- 设备树文件:包含了系统硬件的描述信息,包括处理器、内存、外设等信息,内核通过设备树文件可以识别硬件设备,并加载相应的设备驱动。
- 内核模块参数:在内核运行过程中,可以通过加载和卸载内核模块的方式来扩展内核功能,对于某些内核模块,还可以通过传递参数来定制其行为和功能。
- 调试信息:在调试内核时,可以通过传递一些调试参数来获取更详细的信息,如调试等级、调试标志等。
16.如何给内核传递参数?
在 Linux 系统中,可以通过多种方式向内核传递参数,包括以下几种:
-
命令行参数:通过 U-Boot、GRUB 或其他引导加载程序,在内核启动时通过命令行参数的形式向内核传递参数。这些参数可以包括根文件系统、控制台、日志级别等,具体的参数格式和语法可以参考内核文档。
-
环境变量:通过设置 U-Boot、GRUB 或其他引导加载程序的环境变量,在内核启动时自动加载环境变量中的参数。常用的环境变量包括
bootargs
、bootcmd
等,具体的环境变量格式和用法可以参考引导加载程序的文档。 -
设备树文件:设备树是一种描述硬件设备的结构化数据格式,在内核启动时可以通过设备树文件来描述硬件设备,并将设备树文件的地址和大小传递给内核。设备树文件中可以包括一些参数,例如设备地址、时钟频率等。在内核启动时,内核会解析设备树文件,并读取其中的参数。
-
内核模块参数:内核模块是一种可以动态加载和卸载的代码模块,在加载模块时可以通过模块参数向模块传递参数。内核模块参数可以在模块代码中定义,并通过insmod或modprobe命令传递参数。例如,在加载名为mymodule的内核模块时,可以通过以下命令传递参数:
modprobe mymodule myparam=value
- sysfs文件系统:sysfs是一种虚拟文件系统,用于描述内核设备、驱动程序和其他内核对象的属性。可以通过sysfs文件系统来传递参数。在sysfs文件系统中,每个属性对应一个文件,
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
查阅整理上千份嵌入式面经,将相关资料汇集于此,主要包括: 0.简历面试 1.语言篇 2.计算机基础 3.硬件篇 4.嵌入式Linux【本专栏】 (建议PC端查看)