u-boot启动流程分析

本文以MPC8308(powerpc架构),测试板HX软件包为依据,详细内容可参考HX源码



一、嵌入式系统

一个嵌入式 Linux 系统从软件的角度看通常可以分为四个层次:
1.引导加载程序。包括固化在固件(firmware)中的boot 代码(可选),和 Boot Loader 两大部分。 
2. Linux 内核。特定于嵌入式板子的定制内核以及内核的启动参数。
3. 文件系统。包括根文件系统和建立于 Flash 内存设备之上文件系统。通常用 ram disk 来作为 root fs。
4. 用户应用程序。

二、BootLoader的作用
Boot Loader 就是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,

从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。


Boot Loader 主要依赖于CPU的体系结构和具体的嵌入式板级设备的配置


三、结合代码具体分析

1.上电
CPU 在复位时通常都从地址 0x00000000 取它的第一条
指令。而基于 CPU 构建的嵌入式系统通常都有某种类型的固态存储设备(比如: ROM、 EEPROM
或 FLASH 等)被映射到这个预先安排的地址上。

以下摘自mpc8308芯片手册:
4.3.2.2.1 Boot Memory Space (BMS)
The device defines the default boot ROMmemory space to be 8 Mbytes at addresses 0x0000_0000 to 0x007F_FFFF or0xFF80_0000 to 0xFFFF_FFFF. When the core comes out of reset, if it isenabled to boot, it fetches boot code from one of two addresses, 0x0000_0100or 0xFFF0_0100, and exceptions are vectored to the physical addresses,0x000n_nnnn or 0xFFFn_nnnn appropriately.

就是CPU会设置8Mbytes的启动空间,启动地址可能是从0x0000_0000开始或者0xFF80_0000。而取指令的地址也因空间不同而不同,第一种地址是从0x0000_0100开始,另外一种是从0xFFF0_0100开始。(详细见:/学习资料/u-boot分析/PowerPC上电复位的过程描述)

/cpu/mpc83xx/u-boot.lds中定义了整个img的入口函数/cpu/mpc83xx/start.S

/mpc83xx.h 

通过调用系统复位中断从System reset偏移向量0x100来获取指令

system.map中_start的线性地址

2.空间结构图

同时装有 Boot Loader、内核的启动参数、内核映像和根文件系统映像
的固态存储设备的典型空间分配结构图。

HX flash分区如下:

定义在MPC8308EDD.h

#define MTDPARTS_DEFAULT "mtdparts=nand_mtd:0x00080000@0x00000000(uboot),"\
"0x00020000@0x00080000(uenv),"\
"0x3FF60000@0x000A0000(ubifs)"

 

 

3.两个阶段

stage1:依赖于 CPU 体系结构的代码,比如设备初始化代码等,通常都放在其中,而且通常都用汇编语言来实现,以达到短小精悍的目的。

stage2 则通常用C 语言来实现,这样可以实现给复杂的功能,而且代码会具有更好的可读性和可移植性。
 

4.u-boot环境变量和ubifs

MPC8308EDD.h中的宏

#define CONFIG_EXTRA_ENV_SETTINGS      (自定义的)

刚烧入u-boot(flash)时,环境变量是

uchar default_environment[] (/common/env_common.c 默认环境变量+自定义变量)

+CONFIG_EXTRA_ENV_SETTINGS

"bootcmd=run dnalli\0"

然后执行bootcmd后会下载set_env.uscr脚本并按脚本添加和修改部分环境变量

其中:

set rt 'run ramargs addipubi part ubifs; ubifsmount kernel; ubifsload $loadaddredd_uImage; ubifsload $ramdiskaddr edd_uRamdisk; ubifsload $fdtaddr edd.dtb;bootm $loadaddr $ramdiskaddr $fdtaddr'

set bootcmd 'run rt'

这两条将设置下次启动后要执行的bootcmd,下面着重解析 run rt

run ramargs主要设置终端设备/ttyS0,波特率115200,指定根文件系统root=/dev/ram

run addip 主要设置localip,serverip,gateway,netmask,hostname

这里主要讲一下关于ubi的配置,配置u-boot支持ubi系统,参考Uboot201106的Ubifs文件系统移植

在MPC8308EDD.h中添加UBI宏和MTD分区信息宏,重新编译烧录后可以看到如下命令行:

ubi     - ubi commands

ubifsload- load file from an UBIFS filesystem

ubifsls - list files in a directory

ubifsmount- mount UBIFS volume

version - print monitor version

 

1.ubi part ubifs/common/cmd_ubi.c

激活分区ubifs,在boot下执行

=> mtdpart

device nand0<nand_mtd>, # parts = 3 

 #: name               size           offset          mask_flags

 0: uboot              0x00080000     0x00000000      0

 1: uenv               0x00020000     0x00080000      0

 2: ubifs              0x3ff60000     0x000a0000      0

可以看到nand分区uboot uenv ubifs,从代码可以看出对这一分区做了一些初始化操作

do_ubi-->ubi_dev_scan-->ubi_init-->

ubi_msg("attaching mtd%d to ubi%d", mtd->index,ubi_num);-->

ubi_attach_mtd_dev-->io_init-->

ubi_msg("physical eraseblock size:  %d bytes (%d KiB)", ubi->peb_size, ubi->peb_size >>10); 

ubi_msg("logical eraseblock size:    %dbytes", ubi->leb_size);

ubi_msg("smallest flash I/O unit:    %d",ubi->min_io_size);

此时可通过ubi part命令查看已激活分区

=> ubi part 

Device 0: nand0, partition ubifs

 

2.ubifsmountkernel

挂载分区,名称为“kernel”,打印信息如下:

UBIFS: mounted UBI device 0, volume 0, name "kernel"

这时可以通过ubifsls命令查看该文件系统内的文件

=> ubifsls

          2006232 Tue May 19 12:10:47 2015  edd_uImage

          7481360 Wed May 20 04:00:20 2015  edd_uRamdisk

            5667  Tue May 19 12:10:47 2015  edd.dtb

三个文件的由来:

当内核、ramdisk编译完成后,将edd_uImage edd.dtb edd_uRamdisk拷贝到相对路径bin下,并按照ubifs的格式组合成目标文件kernel.img

mkfs.ubifs -r ./bin -m 2048 -e 129024 -c 300-o kernel.img

kernel升级时run dnk如下

set dnk 'tftp 0x3000000 kernel.img; ubi partubifs; ubi write 0x3000000 kernel $kernel_img'

将kernel_img写入ubifs分区

3.ubifsload $loadaddr edd_uImage; ubifsload $ramdiskaddredd_uRamdisk; ubifsload $fdtaddr edd.dtb;

loadaddr=1000000               edd_uImage

ramdiskaddr=2000000          edd_uRamdisk

fdtaddr=C00000                   edd.dtb

将三个文件load到已规划好的内存空间中,最后执行bootm引导内核启动

 

 

 

 

 

 

 

 

 

 

 



 

 

 



 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值