一个最简单的arm linux bootloader

Boot Loader 就是在linux操作系统内核运行之前运行的一段小程序。
可以分为以下几个步骤:初始化硬件设备、读取内核影像,设置启动参数,启动内核。
你可以通过一直U-boot来得到一个功能强大的boot loader,但是对于实际情况来说,
我们启动linux kernel只需要几个步骤就可以完成,写一个最简单的linux bootloader也是一件很轻松的事情。
这里介绍一个最简单的bootloader。
 
一、初始化硬件:
    1、初始化CPU时钟频率,禁止中断。
    2、关闭看门狗。
    3、初始化存储控制器。
    4、初始化linux需要用到的串口。
    5、设置堆栈,CPU 必须 SVC 模式, 禁止mmu和cache,进入C程序入口。
二、读取内核影像:
    1、由于内核影像存储在Nand Flash中,所以初始化NAND控制器。
    2、读出内核影像数据到(rambase + 0x8000)。
    3、因为我们的根文件系统直接在mtd中存在,没有用到ramdisk作为根文件系统,所以不需要加载initrd作为根文件系统。     
三、设置linux内核启动参数。     
    设置启动参数为 cmdline = "console=ttyS0 root=mtdblock0"     
    1、设置param_struct来传递参数。
   
void  linux_arg( char   * cmdline)
    
{
        
int i;
        
struct param_struct *params = (struct param_struct *)(rambase+0x100);
        
params->u1.s.page_size = 4096;
        
params->u1.s.nr_pages = (RAM_SIZE) >> 12;
        
for(i = 0; i < 24; i++)
            
params->commandline[i] = cmdline[i];
    }

    其中 param_struct 结构在arch/arm/kernel/compat.c中声明,
    /*This is the old deprecated way to pass parameters to the kernel*/
    在新的内核中启动参数以标记语言的形式来传递。 不过用以上的方法仍然可以启动现在最新的内核。
 
    2、以标记列表的形式来传递启动参数。
    启动参数标记列表以标记 ATAG_CORE 开始,以标记 ATAG_NONE 结束。
    每个标记由标识被传递参数的 tag_header 结构以及随后的参数值数据结构来组成。具体可以参考
    arch/arm/kernel/compat.c arch/arm/kernel/setup.c等。
    这里简单起见,只设置了 ATAG_CORE ATAG_CMDLINE。
   
#define  tag_next(t)   ((struct tag *)((__u32 *)(t) + (t)->hdr.size))
    
params   =  ( struct  tag  * )BOOT_PARAMS;
    
params -> hdr.tag  =  ATAG_CORE;
    
params -> hdr.size  =  tag_size(tag_core);
    
params -> u.core.flags  =   0 ;
    
params -> u.core.pagesize  =   0 ;
    
params -> u.core.rootdev  =   0 ;
    
params   =  tag_next( params );
   
    
params -> hdr.tag  =  ATAG_CMDLINE;
    
params -> hdr.size  =  ( sizeof ( struct  tag_header)  +  strlen(p)  +   1   +   4 >>   2 ;
    strcpy(
params -> u.cmdline.cmdline, p);
    
params   =  tag_next( params );
   
    
params -> hdr.tag  =  ATAG_NONE;
    
params -> hdr.size  =   0 ;

四、传递参数,运行内核。
    内核调用需要三个参数分别在三个寄存器中 R0, R1, R2。
      R0=0;
      R1=机器类型 ID;关于 Machine Type Number,可以参见 linux/arch/arm/tools/mach-types。
      R2=启动参数标记列表在 RAM 中起始基地址。
    可以用以下行数调用来传递参数和执行内核:
    void (*theKernel)(int zero, int arch, u32 addr) = (void (*)(int, int, u32))(rambase + 0x8000);
    theKernel(0, ARCH, rambase);
五、启动信息:
    串口收到"uncompressing linux.................. done, booting the kernel……"
    boot loader 已经成功地转起来了。
    整个启动程序代码只有3k左右, 可以用ads 或realview编译成功,可以正常启动linux, 在板子上可以很好的运行。
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值