标题：Boot Loader
作用原理
⒈ Boot Loader 所支持的 CPU 和嵌入式板 
每种不同的 CPU 体系结构都有不同的Boot Loader。有些 Boot Loader 也支持多种体系结构的 CPU，比如 U-Boot 就同时支持 ARM 体系结构和MIPS 体系结构。除了依赖于 CPU的体系结构外，Boot Loader 实际上也依赖于具体的嵌入式板级设备的配置。这也就是说，对于两块不同的嵌入式板而言，即使它们是基于同一种 CPU 而构建的，要想让运行在一块板子上的 Boot Loader 程序也能运行在另一块板子上，通常也都需要修改 Boot Loader 的源程序。
⒉ Boot Loader 的安装媒介（Installation Medium） 
系统加电或复位后，所有的CPU 通常都从某个由 CPU 制造商预先安排的地址上取指令。比如，基于 ARM7TDMI core 的 CPU 在复位时通常都从地址 0x00000000 取它的第一条指令。而基于CPU 构建的嵌入式系统通常都有某种类型的固态存储设备（比如：ROM、EEPROM 或 FLASH 等）被映射到这个预先安排的地址上。因此在系统加电后，CPU 将首先执行Boot Loader 程序。
⒊ 用来控制 Boot Loader 的设备或机制 
主机和目标机之间一般通过串口建立连接，Boot Loader 软件在执行时通常会通过串口来进行 I/O，比如：输出打印信息到串口，从串口读取用户控制字符等。
⒋ Boot Loader 的启动过程是单阶段（Single Stage）还是多阶段（Multi-Stage） 
通常多阶段的 Boot Loader 能提供更为复杂的功能，以及更好的可移植性。从固态存储设备上启动的 
⒌ Boot Loader 的操作模式 (Operation Boot Loader 大多都是 2 阶段的启动过Mode)
⒍ BootLoader 与主机之间进行文件传输所用的通信设备及协议 程，也即启动过程可以分为 stage 1和 stage 2 两部分。而至于在 stage 1 和 stage 2 具体完成哪些任务将在下面几篇讨论。
Linux世界里Boot Loader的解析
网上关于Linux的BOOTLOADER文章不少了，但是大都是vivi,blob等比较庞大的程序，读起来不太方便,编译出的文件也比较大，而且更多的是面向开发用的引导代码，做成产品时还要裁减，这一定程度影响了开发速度，对初学者学习开销也比较大，在此分析一种简单的BOOTLOADER，是在三星公司提供的2410 BOOTLOADER上稍微修改后的结果，编译出来的文件大小不超过4k，希望对大家有所帮助.
1.几个重要的概念COMPRESSED KERNEL and DECOMPRESSED KERNEL 
压缩后的KERNEL，按照文档资料，现在不提倡使用DECOMPRESSED KERNEL，而要使用COMPRESSED KERNEL，它包括了解压器.因此要在ram分配时给压缩和解压的KERNEL提供足够空间，这样它们不会相互覆盖. 
当执行指令跳转到COMPRESSED KERNEL后，解压器就开始工作，如果解压器探测到解压的代码会覆盖掉COMPRESSED KERNEL，那它会直接跳到COMPRESSED KERNEL后存放数据，并且重新定位KERNEL，所以如果没有足够空间，就会出错. 
Jffs2 File System 
可以使armlinux应用中产生的数据保存在FLASH上，我的板子还没用到这个. 
RAMDISK 
使用RAMDISK可以使ROOT FILE SYSTEM在没有其他设备的情况下启动.一般有两种加载方式，最常用的一种是，把COMPRESSED RAMDISK IMAGE放到指定地址，然后由BOOTLOADER把这个地址通过启动参数的方式ATAG_INITRD2传递给KERNEL.具体看代码分析. 
启动参数（摘自IBM developer) 
在调用内核之前，应该作一步准备工作，即：设置 Linux 内核的启动参数。Linux 2.4.x 以后的内核都期望以标记列表(tagged list）的形式来传递启动参数。启动参数标记列表以标记 ATAG_CORE 开始，以标记 ATAG_NONE 结束。每个标记由标识被传递参数的 tag_header 结构以及随后的参数值数据结构来组成。数据结构 tag 和 tag_header 定义在 Linux 内核源码的include/asm/setup.h 头文件中. 
在嵌入式 Linux 系统中，通常需要由 BOOTLOADER 设置的常见启动参数有：ATAG_CORE、ATAG_MEM、ATAG_CMDLINE、ATAG_RAMDISK、ATAG_INITRD等。
（注）参数也可以用COMMANDLINE来设定，在我的BOOTLOADER里，我两种都用了.
2.开发环境和开发板配置：CPU:S3C2410,BANK6上有64M的SDRAM（两块），BANK0上有32M NOR FLASH，串口当然是逃不掉的.这样，按照数据手册，地址分配如下： 
0x4000_0000开始是4k的片内DRAM. 
0x0000_0000开始是32M FLASH 16bit宽度 
0x3000_0000开始是64M SDRAM 32bit宽度 
注意：控制寄存器中的BANK6和BANK7部分必须相同. 
0x4000_0000（片内DRAM）存放4k以内的BOOTLOADER IMAGE 
0x3000_0100开始存放启动参数 
0x3120_0000 存放COMPRESSED KERNEL IMAGE 
0x3200_0000 存放COMPRESSED RAMDISK 
0x3000_8000 指定为DECOMPRESSED KERNEL IMAGE ADDRESS 
0x3040_0000 指定为DECOMPRESSED RAMDISK IMAGE ADDRESS 
开发环境：Redhat Linux,armgcc toolchain,armlinux KERNEL 
如何建立armgcc的编译环境：建议使用toolchain，而不要自己去编译armgcc，偶试过好多次，都以失败告终. 
先下载arm-gcc 3.3.2 toolchain 
将arm-linux-gcc-3.3.2.tar.bz2 解压到 /toolchain 
# tar jxvf arm-linux-gcc-3.3.2.tar.bz2 
# mv /usr/local/arm/3.3.2 /toolchain 
在makefile 中在把arch=arm CROSS_COMPILE设置成toolchain的路径 
还有就是INCLUDE = -I ../include -I /root/my/usr/local/arm/3.3.2/include.，否则库函数就不能用了
3.启动方式：可以放在FLASH里启动，或者用Jtag仿真器.由于使用NOR FLASH，根据2410的手册，片内的4K DRAM在不需要设置便可以直接使用，而其他存储器必须先初始化，比如告诉memory controller,BANK6里有两块SDRAM，数据宽度是32bit,= =.否则memory control会按照复位后的默认值来处理存储器.这样读写就会产生错误. 
所以第一步，通过仿真器把执行代码放到0x4000_0000，（在编译的时候，设定TEXT_BAS 
E=0x40000000) 
第二步，通过 AxD把linux KERNEL IMAGE放到目标地址（SDRAM）中，等待调用 
第三步，执行BOOTLOADER代码，从串口得到调试数据，引导armlinux
4.代码分析讲了那么多执行的步骤，是想让大家对启动有个大概印象，接着就是BOOTLOADER内部的代码分析了，BOOTLOADER文章内容网上很多，我这里精简了下，删除了不必要的功能. 
BOOTLOADER一般分为2部分，汇编部分和c语言部分，汇编部分执行简单的硬件初始化，C部分负责复制数据，设置启动参数，串口通信等功能. 
BOOTLOADER的生命周期： 
⒈ 初始化硬件，比如设置UART（至少设置一个），检测存储器= =. 
⒉ 设置启动参数，这是为了告诉内核硬件的信息，比如用哪个启动界面，波特率 = =. 
⒊ 跳转到Linux KERNEL的首地址. 
⒋ 消亡 
同时在linux中 GRUB（GRand Unified Bootloader）是一个系统默认自带的多重启动管理器。它可以在多个操作系统共存时选择引导哪个系统。尽管引导操作系统看上去是件平凡且琐碎的任务，但它实际上很重要。如果引导装入器不能很好地完成工作或者不具有弹性，那么就可能锁住系统或者无法引导计算机……