一、Boot Loader的概念和功能 1、嵌入式Linux软件结构与分布 在一般情况下嵌入式Linux系统中的软件主要分为以下及部分: (1)引导加载程序:其中包括内部ROM中的固化启动代码和Boot Loader两部分。 而这个内部固化ROM是厂家在芯片生产时候固化的,作用基本上是引导Boot Loader。有的芯片比较复杂,比如Omap3,他在flash中没有代码的时候有许多启动方式:USB、UART或以太网等等。而S3C24x0则很简单,只有Norboot和Nandboot。 (2)Linux kernel 和drivers。 (3)文件系统。包括根文件系统和建立于Flash内存设备之上的文件系统(EXT4、UBI、CRAMFS等等)。它是提供管理系统的各种配置文件以及系统执行用户应用程序的良好运行环境的载体。 (4)应用程序。用户自定义的应用程序,存放于文件系统之中。 在Flash 存储器中,他们的 一般分布如下:
![](http://blogimg.chinaunix.net/blog/upfile2/100411172651.png)
但是以上只是大部分情况下的分布,也有一些可能根文件系统是initramfs,被一起压缩到了内核映像里,或者没有Bootloader参数区,等等。
2、在嵌入式Linux中为什么要有BootLoader 在linux内核的启动运行除了内核映像必须在主存的适当位置,CPU还必须具备一定的条件:
1. CPU 寄存器的设置: | R0=0; R1=Machine ID(即Machine Type Number,定义在linux/arch/arm/tools/mach-types); R2=内核启动参数在 RAM 中起始基地址; | 2. CPU 模式: | 必须禁止中断(IRQs和FIQs); CPU 必须 SVC 模式; | 3. Cache 和 MMU 的设置: | MMU 必须关闭; 指令 Cache 可以打开也可以关闭; 数据 Cache 必须关闭; |
但是在CPU刚上电启动的时候,一般连内存控制器都没有配置过,根本无法在内存中运行程序,更不可能处在Linux内核的启动环境中。为了初始化CPU及其他外设,使得Linux内核可以在系统主存中跑起来,并让系统符合Linux内核启动的必备条件,必须要有一个先于内核运行的程序,他就是所谓的引导加载程序(Boot Loader)。 而Boot Loader并不是Linux才需要,是几乎所有的运行操作系统的设备都具备的。我们的PC的BOIS就是Boot Loader的一部分(只是前期引导,后面一般还有外存中的各种Boot Loader),对于Linux PC来说,Boot Loader = BIOS + GRUB/LILO。
3、Boot Loader的功能和选择 通过上面的讲述,我们可以知道:Boot Loader是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境,最后从别处(Flash、以太网、UART)载入内核映像并跳到入口地址。 由于BootLoader直接操作硬件,所以她严重依赖于硬件,而且依据所引导的操作系统的不同,也有不同的选择对于嵌入式世界中更是如此。就S3C24x0而言,如果是引导Linux,一般选用韩国的mizi公司设计的vivi或者DENX软件工程中心的U-boot,如果是引导Win CE,就选用Eboot。如果是开发StrongARM 构架下的LART,就可选用由Jan-Derk Bakker 和 Erik Mouw发布的Blob(Boot Loader Object)。如果是要引导eCos系统,就可以选用同是Redhat公司开发的Redboot。 所以在嵌入式世界中建立一个通用的 BootLoader 几乎是不可能的,而有可能的是让一个 Boot Loader代码支持多种不同的构架和操作系统,并让她方便移植。U-boot就是支持多平台多操作系统的一个杰出代表。这也是为什么我喜欢用U-boot的原因,因为如果在开发S3C2440时熟悉了U-boot,再转到别的平台的时候就可以很快地完成这个平台下的U-boot移植,而且U-boot的代码结构越来越合理,对于新功能的添加也十分容易。 值得一提的是国内的一个开源项目maxwit中的g-bios也是一个不错的开源BootLoader,同样支持多平台。
*推荐阅读:嵌入式系统 Boot Loader 技术内幕 二、U-boot简介 U-Boot是Das U-Boot的简称,其含义是Universal Boot Loader,是遵循GPL条款的开放源码项目。一开始德国DENX软件工程中心的Wolfgang Denk基于8xxROM和FADSROM的源码创建了PPCBoot工程项目,此后不断添加处理器的支持。后来,Sysgo Gmbh把PPCBoot移植到ARM平台上,创建了ARMBoot工程项目。然后以PPCBoot工程和ARMBoot工程为基础,创建了U-Boot工程,2002年12月17日第一个版本U-Boot-0.2.0发布,同时PPCBoot和ARMboot停止维护。而今,U-Boot作为一个主流、通用的Bootloader,成功地被移植到包括主流的PowerPC、ARM、X86 、MIPS、NIOS、XScale等体系结构的上百种开发板,成为功能最多、灵活性最强,并且开发最积极的开源BootLoader。目前。U-Boot仍然由DENX的Wolfgang Denk维护。
二、U-boot的开发情况和资源 一开始U-boot的版本号是由X.Y.Z来表示的,从0.2.0一直到1.3.4,之后便开始使用年份加月份的表示方法,2008.11到现在的2010.3平均每3个多月出一个新版本,每次代码的结构和定义都会有一些修正和改进。我从1.2.0开始移植U-boot到S3C24x0,到现在的2010.03,发现U-boot的代码越来越规整,功能越来越强,但是移植的难度反而越来越小,需要修改的地方越来越少。 而对于U-boot,不仅仅有主线版本,在U-boot的Git代码仓库中还有各个CPU构架的分支版本,这些分支会在一定的时候将修改汇入主线。值得注意的是U-boot-V2,这是下一代的U-boot,代码的构架比较新,现在正处在开发的阶段,但针对S3C2440的支持似乎可以了,还没有时间尝试。 下面总结一下关于U-boot源代码的网络资源:
三、开发环境准备
开发前的准备有以下几个方面: 1 、交叉编译工具链的安装。 我在前段时间使用了Crosstool-ng编译出了for ARMv4t的交叉编译工具,Gcc的版本是4.3.2,可以用来编译最新版的Linux内核,当然也可以轻松的编译U-Boot. 请看:《用crosstool-ng建立Linux 交叉编译环境》 在编译好交叉编译工具链后,关键是要在环境变量的PATH中添加编译工具的路径(也就是arm-*-linux-*-gcc所在的路径),在编译时系统才找得到命令。 在Ubuntu下的修改方法:
并在最后加上:
PATH="<交叉编译工具的路径> PATH"
| 2、网络服务的设置 在使用U-boot的时候常常会用到宿主机的TFTP和NFS这两种网络服务,所以最好在开发前设置好。我为了记录以前写过两篇手记,记录这两个服务的安装配置过程,供大家参考。 Ubuntu下安装配置NFS网络服务手记 Ubuntu下安装配置TFTP服务手记 3、串口终端程序 在使用U-boot的时候,必然会用到串口与开发板进行通信,所以串口终端程序必不可少。在Linux下的串口终端程序有minicom、C-kermit,还有一个图形化的串口终端:gtkterm。 但是我个人一般比较喜欢用C-kermit,因为在Linux下是通过串口kermit协议传输文件到开发板,就属C-kermit比较好用。 下面我就简单介绍下C-kermit安装配置的大致步骤: (1)安装ckermit程序; (2)编写ckermit的配置文件~/.kermrc。 下面是一个很简单的安装和配置脚本,供大家参考:
#!/bin/sh echo install C-kermit ... sudo apt-get install ckermit if [ "$?" = "0" ] then echo "install ckermit OK!!" else echo "install ckermit error !!!" # exit 1 fi
#如果是USB转串口,就是类似/dev/ttyUSB0的设备,如果是原生的硬件串口,就是类似/dev/ttyS0的设备节点。 #根据你使用的串口,设备节点编号可能有变,你可以ls /dev/tty*看看你用的到底有什么设备节点。 cat >~/.kermrc <<EOF set line /dev/ttyUSB0 set speed 115200 set carrier-watch off set handshake none set flow-control none robust set file type bin set file name u-boot.bin set rec pack 1000 set send pack 1000 set window 5 c
EOF
| 四、U-boot的使用(一) 我一贯认为:对于一个技术类的东西,你连用都不会用,那根本就不可能会开发。就好像一个人连Linux不会用,那还谈何开发Linux程序呢? 同样的要开发和移植U-boot,首先要对U-boot有一定的了解,起码要会使用。 所以这里我们首先熟悉一下U-boot的使用以及如何将U-boot烧入mini2440。 当然在这之前首先必须保证你的板子上已经有了U-boot。如果没有那就先烧上一个吧。针对mini2440的U-boot-2009.11的bin文件我已经上传到了博客中,可以直接烧入,请到这里下载: u-boot-2009.11 for mini2440 Source release 把它烧到mini2440的NAND或者NOR Flash的起始地址即可,你可以使用OpenJTAG下载烧写:
关于OpenOCD的安装和配置(以mini2440+OpenJTAG为例) 也可以用板上已有的boottloader烧写,也可以适用H-JTAG用并口烧(这是最直接最快的)。
常用的U-boot命令详解 U-boot发展到现在,他的命令行模式已经非常接近Linux下的shell了,在我编译的U-boot-2009.11中的命令行模式模式下支持“Tab”键的命令补全和命令的历史记录功能。而且如果你输入的命令的前几个字符和别的命令不重复,那么你就只需要打这几个字符即可,比如我想看这个U-boot的版本号,命令就是“ version”,但是在所有的命令中没有其他任何一个的命令是由“v”开头的,所以只需要输入“v”即可。
[u-boot@MINI2440]# version
U-Boot 2009.11 ( 4月 04 2010 - 12:09:25) [u-boot@MINI2440]# v
U-Boot 2009.11 ( 4月 04 2010 - 12:09:25) [u-boot@MINI2440]# base Base Address: 0x00000000 [u-boot@MINI2440]# ba Base Address: 0x00000000
|
由于U-boot支持的命令实在太多,一个一个细讲不现实,也没有必要。所以下面我挑一些烧写和引导常用命令介绍一下,其他的命令大家就举一反三,或者“help”吧! (1)获取帮助 命令:help 或 ? 功能:查看当前U-boot版本中支持的所有命令。
[u-boot@MINI2440]# help ? - alias for 'help' askenv - get environment variables from stdin base - print or set address offset bdinfo - print Board Info structure bmp - manipulate BMP image data boot - boot default, i.e., run 'bootcmd' bootd - boot default, i.e., run 'bootcmd' bootelf - Boot from an ELF image in memory bootm - boot application image from memory bootp - boot image via network using BOOTP/TFTP protocol bootvx - Boot vxWorks from an ELF image cmp - memory compare coninfo - print console devices and information cp - memory copy crc32 - checksum calculation date - get/set/reset date & time dcache - enable or disable data cache dhcp - boot image via network using DHCP/TFTP protocol echo - echo args to console editenv - edit environment variable eeprom - EEPROM sub-system erase - erase FLASH memory exit - exit script fatinfo - print information about filesystem fatload - load binary file from a dos filesystem fatls - list files in a directory (default /) flinfo - print FLASH memory information fsinfo - print information about filesystems fsload - load binary file from a filesystem image go - start application at address 'addr' help - print online help i2c - I2C sub-system icache - enable or disable instruction cache iminfo - print header information for application image imls - list all images found in flash imxtract- extract a part of a multi-image itest - return true/false on integer compare loadb - load binary file over serial line (kermit mode) loads - load S-Record file over serial line loadx - load binary file over serial line (xmodem mode) loady - load binary file over serial line (ymodem mode) loop - infinite loop on address range ls - list files in a directory (default /) md - memory display mm - memory modify (auto-incrementing address) mmc - MMC sub-system mtest - simple RAM read/write test mw - memory write (fill) nand - NAND sub-system nboot - boot from NAND device nfs - boot image via network using NFS protocol nm - memory modify (constant address) ping - send ICMP ECHO_REQUEST to network host printenv- print environment variables protect - enable or disable FLASH write protection rarpboot- boot image via network using RARP/TFTP protocol reginfo - print register information reset - Perform RESET of the CPU run - run commands in an environment variable saveenv - save environment variables to persistent storage setenv - set environment variables showvar - print local hushshell variables sleep - delay execution for some time source - run script from memory test - minimal test like /bin/sh tftpboot- boot image via network using TFTP protocol unzip - unzip a memory region usb - USB sub-system usbboot - boot from USB device version - print monitor version
| 如果你想获取某条命令的更详细的帮助,可以使用:
help <你想要查的指令> 或者 ? <你想要查的指令> , 甚至 h <你想要查的指令缩写>。
| 以bmp指令为例:
[u-boot@MINI2440]# help bmp bmp - manipulate BMP image data
Usage: bmp info <imageAddr> - display image info bmp display <imageAddr> [x y] - display image at x,y [u-boot@MINI2440]# ? bmp bmp - manipulate BMP image data
Usage: bmp info <imageAddr> - display image info bmp display <imageAddr> [x y] - display image at x,y [u-boot@MINI2440]# h bm bmp - manipulate BMP image data
Usage: bmp info <imageAddr> - display image info bmp display <imageAddr> [x y] - display image at x,y
| (2)环境变量(environment variables,简称ENV)与相关指令 和shell类似,U-Boot也有环境变量。一些U-boot默认的环境变量如下:
环 境 变 量 | 解 释 说 明 | bootdelay
| 执行自动启动(bootcmd中的命令)的等候秒数
| baudrate
| 串口控制台的波特率
| netmask
| 以太网的网络掩码
| ethaddr
| 以太网的MAC地址
| bootfile
| 默认的下载文件名
| bootargs
| 传递给Linux内核的启动参数
| bootcmd
| 自动启动时执行命令
| serverip
| TFTP服务器端的IP地址
| ipaddr
| 本地的IP地址
| stdin
| 标准输入设备,一般是串口
| stdout
| 标准输出,一般是串口,也可是LCD(VGA)
| stderr
| 标准出错,一般是串口,也可是LCD(VGA)
| 要看到你的板上的ENV值可使用printenv命令,例如我的板子:
[u-boot@MINI2440]# printenv bootargs=noinitrd root=/dev/nfs rw nfsroot<f | |