Linux系统编程之启动流程分析
一、Linux嵌入式系统启动方式主要有:
(1)NandFlash启动
(2)SD/MMC卡启动
(3)EMMC启动
(4)USB设备启动
二、U-boot概念:
U-boot是常用的一种嵌入式操作系统启动程序,是著名的开源BootLoader程序,可以启动Linux、Android等系统。
作为BootLoader,u-boot最基本的作用就是:
(1)把操作系统镜像从介质(flash、nand、SD卡等)加载到内存中,即在Linux系统中可以从SD卡、flash等存储设备启动系统。
(2)在内存中启动操作系统时可以向操作系统传递配置信息。
(3)此外,U-boot还有一个简单的控制台,利用串口和用户交互以提供一些额外的辅助功能,例如在OS启动前查看内存、数据拷贝、查看OS镜像信息、检查坏块等。
U-boot全称为:Universal Bootload,它是一个通用的启动代码载入器,Linux本身不能自己把自己读取到内存中运行,所以它就需要一个loader(载入器)读入内存并运行。其实U-boot可以在很多种CPU架构中运行,同时也支持很多开发板,但是每种CPU架构之间有差别,或者开发板的资源不同,假如在某款开发板能够正常引导启动操作系统,但是这并不意味着在其他类型的开发板就可以引导启动系统,所以建立一个统一的BootLoader是不太可能的,但是经过大师们的努力,能够通过简单的配置,就可以实现引导启动很多操作系统,也就是所说的BootLoader的移植。
选择U-boot的理由:
(1)源码开放;
(2)支持多种嵌入式操作系统内核,如Linux、VxWorks等;
(3)支持多个处理器系列,如PowerPC、ARM、x86、MIPS、XScale;
(4)较高的可靠性以及稳定性;
(5)高度灵活的功能设置,适合uboot调试;
(6)丰富的设备驱动源码,如串口、以太网、SDRAM、FLASH、LCD、NVRAM、EEPROM、RTC、键盘等;
(7)较为丰富的开发调试文档与强大的网络技术支持。
三、BootLoader简介
3.1 BootLoader概念
简单地说,bootloader 就是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。
通常,bootloader 是严重地依赖于硬件而实现的,特别是在嵌入式世界。因此,在嵌入式世界里建立一个通用的bootloader几乎是不可能的。尽管如此,我们仍然可以对bootloader归纳出一些通用的概念来,以指导用户特定的bootloader设计与实现。
3.2 BootLoader启动方式
CPU上电或复位时,会从某个地址开始执行。ARM结构的CPU从地址0x0000000开始,通常这个地址处就存放了BL1+bootloader这样一上电就可以执行(bootloader相当于BL2)。
从开发和用户使用角度来分析,Bootlaoder可以分为以下两种操作模式(Operation Mode)。
(1)自启动模式(Boot laoding):
这种模式下,bootloader从目标机上的某个固态存储设备上将操作系统加载到RAM中运行,整个过程并没有用户的介入。产品发布后,bootloader工作在这种模式下。
(2)交互模式或者下载(Downlaoding)模式:
在这种模式下,开发人员可以使用各种命令,通过串口连接或网络连接等通信手段从主机下载文件(比如内核映像、文件系统映像)到RAM中,可以被bootloader写到目标机上的固态存储介质中,或者直接进入系统的引导。
U-boot能够同时支持这两种工作模式,而且允许用户在这两种模式之间进行切换。比如,U-Boot在启动时处于正常的自启动模式,但是它会延时若干秒(这可以设置),等待终端用户按下任意键,而将U-boot切换到交互模式。如果在指定时间内没有用户按键,则U-Boot继续启动LINUX内核。
3.3 Bootloader的结构
嵌入式LINUX系统从软件的角度通常可以分为4个层次:
(1)Bootloader
引导加载程序,包括固化在固件(firmware)中的boot代码(可选)和Bootloader两大部分。有些CPU在运行Bootloader之前先运行一段固化的程序(固件,firmware),比如x86结构的CPU就是先运行BIOS中的固件,然后才运行硬盘第一个分区(MBR)中的Bootloader。在大多嵌入式系统中并没有固件,Bootloader是上电后执行的第一个程序。
(2)LINUX内核
特定于嵌入式板子的定制内核以及内核的启动参数。内核的启动参数可以是内核默认的,或是由Bootloader传递给它的。
(3)文件系统
包括根文件系统和建立于FLASH内存设备之上的文件系统。里面包含了LINUX系统能够运行所必须的应用程序、库等,比如可以给用户提供操作LINUX的控制界面和shell程序、动态连接和程序运行时需要的glibc或uClibc库等。
(4)用户应用程序
特定于用户的应用程序,它们也存储在文件系统中。有时在用户应用程序和内核层之间可能还会包括一个嵌入式图形用户界面。常用的嵌入式GUI有:Qtopia和MiniGUI等。
显然,在嵌入式系统的固态存储设备上有相应的分区来存储它们,如下图所示为一个典型的分区结构。
BootLoader | Boot parameters | Kernel | Root filesystem |
“Boot parameters”分区中存放一些可设置的参数,比如IP地址、串口波特率、要传递给内核的命令行参数等。正常启动过程中,Bootloader首先运行,然后它将内核复制到内存中(也有些内核可以直接在固态存储设备上直接运行),并且在内存某个固定的地址设置好要传递给内核的参数,最后运行内核。内核启动之后,它会挂接(mount)根文件系统(“Root filesystem”),启动文件系统中的应用程序。
小知识点:Kernel含义:
Kernel 操作系统内核:操作系统内核是指大多数操作系统的核心部分。它由操作系统中用于管理存储器、文件、外设和系统资源的那些部分组成。操作系统内核通常运行进程,并提供进程间的通信。
3.4 常用Bootloader介绍
现在Bootloader种类繁多,比如X86上有LILO、GRUB等。对于ARM架构的CPU,有U-Boot、Vivi等。它们各有特点,下面列出Linux的开发源代码的Bootloader及其支持的体系结构,如下图2.2所示:
开放源码的linux引导程序 |
|||||
Bootloader |
Monitor |
描述 |
X86 |
ARM |
PowerPC |
LILO |
否 |
linux磁盘引导程序 |
是 |
否 |
否 |
GRUB |
否 |
GNU的LILO替代程序 |
是 |
否 |
否 |
Loadlin |
否 |
从DOS引导linux |
是 |
否 |
否 |
ROLO |
否 |
从ROM引导linux而不需要BIOS |
是 |
否 |
否 |
Etherboot |
否 |
通过以太网卡启动linux系统的固件 |
是 |
否 |
否 |
LinuxBIOS |
否 |
完全替代BUIS的linux引导程序 |
是 |
否 |
否 |
BLOB |
是 |
LART等硬件平台的引导程序 |
否 |
是 |
否 |
U-Boot |
是 |
通用引导程序 |
是 |
是 |
是 |
RedBoot |
是 |
基于eCos的引导程序 |
是 |
是 |
是 |
Vivi |
是 |
Mizi公司针对SAMSUNG的ARM CPU设计的引导程序 |
否 |
是 |
否 |
四、BootLoader启动流程分析
4.1 执行IROM中固化的代码程序(此代码由SOC生产厂商提供)(BL0)
iROM会初始化硬件环境,关键的是IROM会从启动设备下载BL1到SRAM中执行初始化硬件部分;
在irom中根据以上流程图,即关中断和MMU,关D-cache与I-cache,失效TLB表,让CORE1进入空闲,初始化栈,初始化Zi,RW段,注册函数指针,判断启动方式,从对应启动设备中加载BL1到SRAM中,然后对BL1进行校验和检测,加密校验,解密处理,最后跳转到BL1代码执行。
4.2 BL1(BootLoader1)执行
重启初始化IRQ、SVC模式的栈,判断启动设备,然后从对应的启动设备中加载BL2到SRAM中,然后判断是否启动安全模式,如果是,则对BL2进行校验,校验通过则跳转到BL2代码中执行。
4.3 执行BL2
重新初始化IRQ,SVC模式的栈,设置时钟,初始化外扩的DRAM,判断启动设备,然后从相应的启动设备中读取OS或FW到DRAM中,然后判断是否启动安全模式,如果是,则对BL2进行校验,校验通过则跳转到OS或FW代码中执行。
4.4 扇区分布
4.5 三者关系
(Interal ROM固化代码)BL0将BL1(bootloader的前16扇区-BL1)加载到iRAM;BL1然后在iRAM中运行将BL2(剩下的bootloader)加载到SDRAM;BL2加载内核,把OS在SDRAM中运行起来,最终OS是运行在SDRAM(内存)中的。
4.6 内部RAM被出厂配置的分区
本文地址:https://blog.csdn.net/qianxiang1534/article/details/107391260
下一篇: restful api接口封装