Bootloader分析

Bootloader 是引导程序,在PC上用于引导Linux的是LILO、GRUB,在嵌入式系统中,Bootloader就是在操作系统内核运行之前运行的一段小程序。

通过这段小程序,可以初始化硬件设备、建立内存空间的映射图,使系统的软硬件环境处于合适的状态,为最终调用系统内核做好准备


Bootloader依赖于硬件而实现,每种不同的CPU体系结构都有不同的Bootloader,有些Bootloader也支持多种体系结构的CPU,如U-Boot

<1>Bootloader下载安装

一般来说CPU复位后都会从固定地址开始执行程序,不过都需要把Bootloader下载到系统最初开始执行的地址对应的固态存储器内。这个往往利用到JTAG接口

<2>Bootloader控制方法

Bootloader在目标机运行起来后,需要与Bootloader进行交互控制,此时一般会利用串口来进行I/O

<3>Bootloader的操作模式

大多数Bootloader包含两种不同的操作模式:“启动加载”模式 和“下载”模式

启动加载模式: 该模式下Bootloader自动加载操作系统并将控制权交给操作系统,整个过程没有人工干预

下载模式:该模式下药提供存储器分析管理、固态存储器擦除和写入、能下载内核、文件系统映像到存储器


Bootloader主要任务

由于系统在Flash中的访问速度大大慢于RAM,因此大部分系统都是加载到RAM中来执行的,从操作系统的角度来看,Bootloader的目标是正确地调用内核来执行

大多数Bootloader分为stage1 和 stage2两大部分,依赖于CPU体系结构的代码,如设备初始化代码等,通常都放在stage1中,通常是汇编语言实现

stage2通常用C语言来实现,这样既可以实现复杂的功能,代码又具有良好的可读性和可移植性


Bootloader的 stage1:

1、硬件设备初始化

2、为加载Bootloader的stage2准备RAM空间

3、拷贝Bootloader的stage2到RAM空间中

4、设置好堆栈

5、跳转到stage2的C入口处


Bootloader的stage2:

1、初始化本阶段要使用到的硬件设备

2、检测系统内存映射

3、将kernel 和根文件系统映像从flash上读到RAM空间中

4、为内核设置启动参数

5、调用内核


Blob源码文件结构:

根目录下有一个Configure.in文件, configure文件是由 命令autoconf 根据 configure.in文件自动生成

分析Blob实现原理,整个Blob的编译肯定需要在Makefile控制下进行,而Makefile是由 automake命令根据Makefile.am来生成 Makefile.in

最终由 configure 把 makefile.in变成最终的Makefile


终上分析,我们应该要先从Makefile.am开始入手,在源码的所有目录下都有一个Makefile.am文件,最重要的是src/Blob目录下的Makefile.am


<1>打开 src/Blob下的Makefile.am,可以清楚发现Blob分为了两个阶段:

# --- Blob frist stage loader ------------------------------

 . . .

Blob_elf32_SOURCES = \

        start.S \

       testmem.S


从上面可以看出,src/Blob目录下的start.S是整个Blob的入口,从start.S开始跟踪程序

<2> start.S的分析

. . .

.globl _start

_start:

    b    reset

. . . . . .

该程序中出现指令 b reset, reset标号在 src/Blob/xlli/mainstone 的 start.s 文件中找到

<3> start.s文件分析

 .include  "xlli_Bulverde_defs.inc"                  @ Bulverde specific include file

 .include  "xlli_Mainstone_defs.inc"                @ Mainstone specific include file

. . .

.globl reset

reset:

. . .

      bl  normal_boot

. . .

程序在 start.s 中开始 调用 src/Blog/xlli/mainstone目录里的xlli_LowLev_Init.s里的各个功能模块对系统进行初始化,start.s的执行顺序如下

1、检查状态信息

2、调用xlli_LowLev_Init.s模块进行以下几部分操作

【1】读取板载配置信息

【2】初始化GPIO

【3】初始化时钟系统

【4】初始化电源及内部SRAM

【5】初始化Memory控制器

【6】初始化Memory时钟速率

【7】初始化实时时钟

3、跳回到 start.S的normal_boot标号处

<4>start.S从normal_boot标号后,调用testmem.s的testram模块,对Blob起始地址1MRAM空间进行检查(写入0xaa,0x55,然后读出检查),

检查结束后就把blob第二阶段代码复制进内存空间,接下来跳转到RAM中Blob的其实地址BLOB_START处,执行第二阶段的任务


<5> 分析第二阶段前,先说明连接程序入口点的概念,设置该入口点有以下几种方法,优先级从高到低,高优先级覆盖低优先级

【1】用命令行ld选项 -e指定

【2】脚本语言中使用ENTRY(_start)指定

【3】程序中出现的start符号指定

【4】.text段的起始地址指定

【5】物理地址0x0


链接器是如何进行程序链接的,在src/Blob下的 rest-ld-script.in文件中有介绍,具体的看该源代码,以下是部分代码

. . .

OUTPUT_ARCH(arm)

ENTRY(_trampoline)

. . .

从上面可以看出 _trampoline是 Blob stage2的入口,可以从同一目录下的trampoline.S找到该标号

<6>trampoline.S的分析

.text

.globl _trampoline

_trampoline:

  . . .

 bl  main

 b   _trampoline

. . .

该程序首先清除BSS段(该段存放着未初始化变量),然后CPU跳转到main()函数中执行,trampoline(弹簧床的意思),会一直执行main()函数

<7> main函数的分析

main函数主要功能有 初始化串口和网络,加载内核镜像文件,在BLOB命令行模式下实现用户交互,具体包括:

【1】初始化Flash

【2】设置网络IP

【3】初始化串口

【4】初始化icache

【5】初始化LED

【6】初始化网络设备

【7】准备BLOB命令

【8】初始化Flash Block Table;

【9】初始化 Flash Partition Table

【10】装载内核镜像文件

【11】打印基本的欢迎信息,等待用户终端,进入BLOB命令行或直接启动Linux kernel


其中main中要进行说明的是 init_subsystems()函数,该函数实际上是通过.initlist段来调用所有的初始化程序,具体的函数可查阅资料。









  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值