查看: 709|回复: 2

[经验] 4412开发板学习笔记--Bootloader基本介绍

[复制链接]

43

主题

0

好友

665

积分

举人

Rank: 4

该用户从未签到

发表于 2016-6-27 16:17:19 |显示全部楼层
转自迅为iTOP-4412开发板实战教程书籍:http://www.topeetboard.com
1.  Bootloader简介
在专用的嵌入式目标板上运行Linux系统已经变得越来越流行。一个嵌入式Linux系统从软件的角度,通常可以分为四个层次。
(1) 引导加载程序。包括固化在固件(firmware)中的boot代码(可选),和BootLoader两大部分。
(2) Linux内核。特定于目标板的定制内核以及内核的启动参数。
(3) 文件系统。包括根文件系统和建立于Flash内存设备之上的文件系统。
(4) 用户应用程序。特定于用户的应用程序。有时在用户应用程序和内核层之间可能还会包括一个嵌入式图形用户界面。
引导加载程序是系统加电后运行的第一段软件代码。例如没在PC机中的引导加载程序由BIOS(其本质就是一段固件程序)和位于硬盘MBR中的OS BootLoader(比如,LILO和GRUB等)一起组成。BIOS在完成硬件检测和资源分配后,将硬盘MBR中的BootLoader读到系统的RAM中,然后将控制权交给OS BootLoader。BootLoader的主要运行任务就是将内核映象从硬盘上读到 RAM 中,然后跳转到内核的入口点去运行,也即开始启动操作系统。
而在嵌入式系统中,通常并没有像BIOS那样的固件程序(注,有的嵌入式CPU也会内嵌一段短小的启动程序),因此整个系统的加载启动任务就完全由BootLoader来完成。
简单地说,BootLoader就是在操作系统内核运行之前运行的一段小程序,功能类似BIOS。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。
注意由于BootLoader是严重地依赖于硬件而实现的,因此,在嵌入式世界里建立一个通用的BootLoader几乎是不可能的。
2.  Bootloader的种类
嵌入式系统世界已经有各种各样的Bootloader,种类划分也有多种方式。除了按照处理器体系结构不同划分以外,还有功能复杂程度的不同。
首先区分一下“Bootloader”和“Monitor”的概念。严格来说,“Bootloader”只是引导设备并且执行主程序的固件;而“Monitor”还提供了更多的命令行接口,可以进行调试、读写内存、烧写Flash、配置环境变量等。“Monitor”在嵌入式系统开发过程中可以提供很好的调试功能,开发完成以后,就完全设置成了一个“Bootloader”。所以,习惯上大家把它们统称为Bootloader。下表列出了Linux 的开放源码引导程序及其支持的体系结构。表中给出了X86 、ARM、PowerPC体系结构的常用引导程序。
Bootloader
描 述
x86
ARM
PowerPC
LILO
Linux磁盘引导程
GRUB
GNULILO替代程
Loadlin
DOS引导Linux
ROLO
ROM引导Linux而不需要BIOS
Etherboot
通过以太网卡启动Linux系统的固件
LinuxBIOS
完全替代BUISLinux引导程序
BLOB
LART等硬件平台的引导程
U-boot
通用引导程
RedBoot
基于eCos的引导程
如上表所示,可以看出对于每种体系结构,都有一系列开放源码Bootloader可以选用。
3.   Uboot源码结构
解压就可以得到全部Uboot源程序。在顶层目录下有18 个子目录,分别存放和管理不
同的源程序。这些目录中所要存放的文件有其规则,可以分为3类。
第1类目录与处理器体系结构或者开发板硬件直接相关;
第2类目录是一些通用的函数或者驱动程序;
第3类目录是Uboot 的应用程序、工具或者文档。
下表列出了Uboot顶层目录下各级目录存放原则。
目 录
特 性
解 释 说 明
board
平台依赖
存放电路板相关的目录文件,例如:cpu86smdk210samsung 等目录
cpu
平台依赖
存放CPU相关的目录文件,例如:mpc8xxppc4xxarm720tmipsxscalei386等目录
lib_ppc
平台依赖
存放对PowerPC 体系结构通用的文件,主要用于实现PowerPC 平台通用的函数
lib_arm
平台依赖
存放对ARM体系结构通用的文件,主要用于实现ARM平台通用的函数
lib_i386
平台依赖
存放对X86体系结构通用的文件,主要用于实现X86平台通用的函数
include
通用
头文件和开发板配置文件,所有开发板的配置文件都在configs目录下
common
通用
通用的多功能函数实现
lib_generic
通用
通用库函数的实现
net
通用
存放网络的程序
fs
通用
存放文件系统的程序
post
通用
存放上电自检程序
drivers
通用
通用的设备驱动程序
disk
通用
硬盘接口程序
examples
应用例程
一些独立运行的应用程序例子
tools
工具
存放制作S-Record 或者U-Boot 格式的映像等工具,例如mkimage
doc
文档
开发使用文档
Uboot的源代码包含对几十种处理器、数百种开发板的支持。对于特定的开发板,配置编译过程只需要其中部分程序。
4.   Uboot分析
本节从理论上分析关于Uboot启动的一些基础知识。
下图中可以看出,Uboot引导程序分为BL1、BL2、U-boot、TZSW四个部分。
图片1.jpg
另外可以看到Booting分区有严格的规定,BL1部分是15KB,BL2部分是16KB,U-boot是328K。例如,Uboot部分最终需要做补齐的,就是补齐到328K。Uboot不论怎么编译都是328K。
Uboot分段启动
下图是exnoys4412 Datasheet中和启动相关的框图。
图片2.jpg
如上图所示,通过控制启动模式(OM),处理器上电以后,开始执行IROM中的代码,这段代码是原厂三星固化在芯片中,是无法修改的。
由上图可知,BL1可以放在4个引导设备中:NAND、SD/MMC、eMMC、USB。
IROM启动以后,会去找BL1,也就是bootloader1,BL1执行完以后会去找BL2。BL2会运行Uboot,Uboot引导Linux内核,内核启动完毕,Uboot的生命周期完全结束。运行顺序为:IROM--->BL1----->BL2---->Uboot---->Linux。
整个Uboot是分段启动。BL1运行在IRAM(不是IROM)中,不要将IRAM误解为DDR3内存,因为这个时候DDR3还没有被初始化,就是说DDR3的控制器还没有初始化。IRAM是可以上电就能使用的,可以这样理解,iRAM就是4412芯片内部特殊的RAM,不用初始化就能用。iRAM造价高,所以很小,总共才256K,所以不能把操作系统装进来,甚至无法将Uboot全部运行,要分段去启动,这样就分成了BL1和BL2。
BL1的安全性分析
bootloader在系统启动的最前面运行,如果bootloader被攻破的话,危险级别几乎都会是致命的,所以这部分内容也一直是黑客们进行漏洞挖掘的领域。
智能机的安全问题越来越重要,手机中如果在Uboot中被“种”了病毒,病毒把通讯录或者私密视频到处网上发等,关键是“种”的病毒是无法杀掉的。可以这么说如果能够控制bootloader,那么iphone的越狱、Android的root以及在手机上安装第三方的ROM就都不成问题。bootloader是安全问题的重中之重,要保护bootloader的安全,防止bootloader被篡改。
出于安全性考虑,在上电启动执行IROM程序以后,加载BL1的时候,要对BL1进行多种安全检验,防止BL1是假的,然后BL1会对BL2进行各种检验,直至操作系统Linux ,这样保证整个系统是干净五毒的!下图是BL1的结构。
图片3.jpg
如下图所示,最上面的16个字节,number of sector(BL1 size)  也就是BL1的大小, Checksum Value也就是累加和校验。就是说把整个BL1主体部分的内容累加和放到这里,然后实际计算下整个累加和,做对比,如果不对,就说明BL1是假的或错误的,不予执行。
图片4.jpg
然后是BL1的第二部分,如下图所示。就算第一部分能作假,看下BL1的第二部分Encrypted BL1,实际就是经过加密的BL1代码,在Uboot中这部分没有源码,只有二进制文件,这段二进制文件由三星提供。
图片5.jpg
如下图所示,BL1的第三部分,这里放了客户和三星的公钥以及签名文件。
图片6.jpg
经过分析可知,在三星bootloader给用户提供了三重安全保障。
BL2分析
BL2的结构如下图所示。BL2 Binary部分其实就是14K,然后下面是chechsum(校验),signature(签名),Padding(补齐)。可以看到BL2的主体部分没有加密,但下面有签名。
图片7.jpg
Padding(补齐),需要将BL2代码扩充到16K,补齐部分全部使用00000000。
在Uboot的makefile编译文件中,有下面几句编译命令:
@./sdfuse_q/chksum
@./sdfuse_q/add_padding
@rm bl2a*
当Uboot生成以后,会通过add_padding进行后续处理,通过这个处理后,就补齐了。
需要注意的是,用户的BL1和BL2是没有经过secure boot的,也就是没有的安全认证内容,但是BL1和BL2本身还是安全的,三星提供了安全保障,BL1不再对BL2进行secure认证了。
在iTOP-4412开发板Uboot源码中,有两个文件需要注意。
E4412.TZ.SSCR.EVT1.1.bin         这个就是一个要求认证的BL1,它会对下级的BL2进行签名认证。
Exynos4412_V21.prv BL2                这个是私钥来签名,用于对BL2的签名
5.   Uboot常用命令
Uboot在硬件初始化完成之后,会进入一个无限循环,等待用户输入命令。U-boot发展到现在,它的命令行模式已经非常接近Linux下的shell了。
如下图所示,在控制台使用命令help可以查看所有默认支持的命令。
图片8.jpg
在iTOP-4412开发板中,命令如下表所示。
命令
功能介绍
bdinfo
打印开发的信息
boot
加载和启动镜像
bootd
boot
bootelf
引导一段代码到内存
bootm
加载和启动一个应用到内存
bootvx
引导虚拟机的镜像
coninfo
打印串口设备信息
echo
打印变量到控制台
ext2load
加载Ext2格式二进制文件
ext2ls
显示目录默认列表
go
启动固定地址的应用
iminfo
打印映像头部信息
reset
重启
6.  裸机程序安装DNW驱动
DNW驱动在网盘“iTOP-4412开发板视频教程及其相关”→“06-裸机程序实验文档以及工具文件”→”tools/USB驱动/dnw_driver“目录下面,我们提供了xp系统、win7-32位、win7-64位三种系统下面的驱动。下面我们以win7 64位系统的驱动为例来讲解一下DNW驱动的安装。
首先使用串口线连接iTOP-4412开发板的调试串口到PC机,使用USB连接线连接iTOP-4412开发板的USB OTG接口到PC机的USB口。
打开“tools”目录下的dnw.exe软件。
选择“Serial Port->Connect",连接到iTOP-4412开发板的串口,启动开发板,可以看到dnw软件会输出启动信息,在Uboot进入”倒数秒“的时候,按键盘的任意按键,将进入Uboot命令行。在Uboot的命令行输入“dnw”, 如下图所示。
图片9.jpg
在PC上右键点击“计算机”,选择“管理”, 打开”计算机管理“,然后鼠标点击上图左侧一栏里面的“设备管理器”,将会列出设备列表。
在中间一栏的“其他设备”里,可以看到“SEC S3C6400X Test B/D”这个未知设备,需要为这个设备安装DNW驱动,鼠标右键点击“SEC S3C6400X Test B/D”选择“更新驱动程序软件(P)...”,如下图所示。
图片10.jpg
打开“更新驱动程序软件”对话框,然后选择“浏览计算机以查找驱动程序软件(R)”,将会显示弹出如下图所示对话框。
图片11.jpg
点击上图的”浏览“,找到驱动,将会出现“windows安全”的对话框,然后点击的“始终安装此驱动程序软件”,开始安装驱动。
安装完成后,点击“关闭”按钮,关闭对话框。
在设备管理器里面看到DNW的设备了,如下图所示:
图片12.jpg
通过上面的操作,DNW的驱动已经安装完成了,现在可以使用DNW下载裸机程序到开发板。
下载裸机程序到开发板上
重新启动我们的开发板,进入到Uboot命令行下面,然后输入“dnw 40008000”(这句的意思是启动DNW,设置程序下载到0x40008000地址), 如下图所示:
图片13.jpg
然后选择“USB Port->Transmit->Transmit”,如下图所示:
图片14.jpg
弹出传输文件对话框之后,选择裸机程序,这里选择的是”led.bin“程序。led.bin文件在在网盘“iTOP-4412开发板视频教程及其相关”→“06-裸机程序实验文档以及工具文件”→”tools/例程/led“目录下面。
然后点击“打开”按钮,这时我们在打开“USB Port->Transmit”,可以看到刚才选择的led.bin,如下图所示。
图片15.jpg
然后选择上图红色方框内的led.bin,下载到内存,下载完成后,串口输出如下图所示:
图片16.jpg
从上图我们可以看到led.bin下载到了内存0x40008000的地址,接下来在dnw软件上输入“go 40008000”使cpu从0x40008000地址开始运行,如下图所示。
图片17.jpg
运行上面的命令后,就可以看到iTOP-4412开发板上的两个led开始交替闪烁了。
裸机led的程序实现
裸机led的程序实现需要启动文件start.S、代码文件led.c和编译文件Makefile。
start.S文件:
.global _start
_start:
        //disable watch dog
        ldr        r0, =0x10060000
              mov        r1, #0
              str        r1, [r0]
        //turn on icache
        mrc        p15, 0, r0, c1, c0, 0
        //bic        r0, r0, #0x00002300        /* clear bits 13, 9:8 (--V- --RS) */
        //bic        r0, r0, #0x00000087        /* clear bits 7, 2:0 (B--- -CAM) */
        //orr        r0, r0, #0x00000002        /* set bit 2 (A) Align */
        //orr        r0, r0, #0x00001000        /* set bit 12 (I) I-Cache */
       
#ifdef CONFIG_SYS_ICACHE_OFF
            // clear bit 12 (I) I-cache
            bic        r0, r0, #0x00001000
#else
            // set bit 12 (I) I-cache
            orr        r0, r0, #0x00001000
#endif
               mcr        p15, 0, r0, c1, c0, 0
        //mcr p15, 0, r0, c7, c5, 0        @ invalidate icache
        //set stack
        ldr        sp, =0x02050000
        bl        led_blink
halt:
        b halt
led.c文件:
#define         GPL2CON         (*(volatile unsigned long *) 0x11000100)
#define         GPL2DAT         (*(volatile unsigned long *) 0x11000104)
#define         GPK1CON         (*(volatile unsigned long *) 0x11000060)
#define         GPK1DAT                (*(volatile unsigned long *) 0x11000064)
//GPL2_0, GPK1_1
void delay(int r0)
{
    volatile int count = r0;
    while (count--)
        ;
}
void led_blink()
{
        GPL2CON = 0x00000001;
        GPK1CON = 0x00000010;
       
        while(1)                                                       
        {
                GPL2DAT = 1;
                GPK1DAT = 0;
                delay(0x80000);
                GPL2DAT = 0;
                GPK1DAT = 0x2;
                delay(0x80000);
        }
}
Makefile文件:
led.bin: start.o led.o
        arm-none-linux-gnueabi-ld -Ttext 0x0 -o led.elf $^
        arm-none-linux-gnueabi-objcopy -O binary led.elf led.bin
        arm-none-linux-gnueabi-objdump -D led.elf > led_elf.dis
%.o : %.S
        arm-none-linux-gnueabi-gcc -o $@ $< -c -nostdlib
%.o : %.c
        arm-none-linux-gnueabi-gcc -o $@ $< -c -nostdlib
clean:
        rm *.o *.elf *.bin *.dis  -f

回复

使用道具 举报

0

主题

0

好友

149

积分

童生

Rank: 2

  • TA的每日心情
    无聊
    2016-11-3 13:52
  • 签到天数: 11 天

    [LV.3]偶尔看看II

    发表于 2016-11-3 09:29:33 |显示全部楼层
    新手小白向高手学习学习
    回复

    使用道具 举报

    2

    主题

    0

    好友

    191

    积分

    童生

    Rank: 2

  • TA的每日心情
    开心
    8 小时前
  • 签到天数: 10 天

    [LV.3]偶尔看看II

    发表于 6 天前 |显示全部楼层
    进来学习学习  
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    关闭

    站长推荐上一条 /6 下一条


    手机版|爱板网 |网站地图  

    GMT+8, 2016-12-5 18:34 , Processed in 0.167283 second(s), 12 queries , Memcache On.

    苏公网安备 32059002001056号

    Powered by Discuz!

    回顶部