zoukankan      html  css  js  c++  java
  • u-boot学习(五):u-boot启动内核

    u-boot的目的是启动内核。内核位于Flash中,那么u-boot就要将内核转移到内存中。然后执行命令执行之。这些操作是由bootcmd命令完毕的。

    bootcmd=nand read.jffs2 0x30007FC0 kernel;bootm 0x30007FC0

    nand read.jffs2 0x30007FC0 kernel 从Flash读出内核,kernel代表从kernel分区读出内核到0x30007FC0。

    1、为什么会用0x30007FC0这么怪的地址呢,由于真实的内核映像文件是uImage文件。它包括:头部+真正的内核。而头部大小正好是64字节。64字节+0x30007FC0正好是0x30008000,这个0x30008000就是真正内核的载入地址,这样安排。就不用又一次移动内核了。

    2、另一个概念就是kernel分区。事实上这是分区的概念,我们在include/configs/100ask24x0.h中将分区写死,分区的名字并不重要。重要的是起始地址以及分区的大小。

    #define MTDPARTS_DEFAULT "mtdparts=nandflash0:256k@0(bootloader)," 
                                "128k(params)," 
                                "2m(kernel)," 
                                "-(root)"
    bootm 0x30007FC0命令在读取完内核后启动内核,调用do_bootm函数。它有零个作用:

    1、依据头部移动内核到合适的位置(上面分析了,此处不需移动)。

    2、启动do_bootm_linux。它也有两个作用:告诉内核一些參数,即设置启动參数;跳到入口地址启动内核。


    Bootloader与内核的交互是单向的。Bootloader将各类參数传给内核。

    因为它们不能同一时候执行。传递办法仅仅有一个:Bootloader将參数放在某个约定的地方后。再启动内核,内核启动后从这个地方获得參数。

    除了约定好參数存放的地址外,还要规定參数的结构。内核期望以标记列表的形式来传递启动參数。

    标记,就是一种数据结构;标记列表,就是挨着存放的多个标记。标记列表以标记ATAG_CORE開始,以标记ATAG_NONE结束。标记的数据结构为tag,它由一个tag_header结构和一个联合(union)组成。

    tag_header结构表示标记的类型及长度,比方是表示内存还是表示命令行參数等。

    对于不同类型的标记使用不同的联合(union)。比方表示内存时使用tag_mem32。表示命令时使用tag_cmdline。数据结构tag和tag_header定义在inlcude/asm/setup.h头文件里。

    struct tag_header {
    	u32 size;
    	u32 tag;
    };
    
    struct tag {
    	struct tag_header hdr;
    	union {
    		struct tag_core		core;
    		struct tag_mem32	mem;
    		struct tag_videotext	videotext;
    		struct tag_ramdisk	ramdisk;
    		struct tag_initrd	initrd;
    		struct tag_serialnr	serialnr;
    		struct tag_revision	revision;
    		struct tag_videolfb	videolfb;
    		struct tag_cmdline	cmdline;
    
    		/*
    		 * Acorn specific
    		 */
    		struct tag_acorn	acorn;
    
    		/*
    		 * DC21285 specific
    		 */
    		struct tag_memclk	memclk;
    	} u;
    };
    
    能够利用这些结构设置标记ATAG_CORE、设置内存标记、设置命令行标记、设置标记ATAG_CORE。源代码中的setup_memory_tags、setup_commadnline_tag函数完毕内存标记和命令标记的设置,一般设置这两个标记就能够了。

    设置完标记后,最后通过theKernel(0, bd->bi_arch_number, bd->bi_boot_params)调用内核。当中,theKernel指向内核存放的地址(对于ARM架构的CPU。一般是上面提到的0x30008000),bd->bi_arch_number就是第二阶段代码中board_init函数设置的机器类型ID,而bd->bi_boot_params就是标记列表的開始地址。

    參考:韦东山 《嵌入式Linux应用开发全然手冊》


  • 相关阅读:
    ConcurrentHashMap、Collections.synchronizedMap、Hashtable讨论(区别)java集合框架【3】 java1.5新特性
    struts2中方法拦截器(Interceptor)的中的excludeMethods与includeMethods的理解
    java抽象类详解以及与接口区别
    乐观锁理解
    URI和URL的区别
    JavaScript编程笔记
    2007年3月9日早上来到深圳……
    axWindowsMediaPlayer1控件循环播放方法
    C#中调用存储过程笔记(原)
    js日期选择控件(Asp.Net可用)
  • 原文地址:https://www.cnblogs.com/jhcelue/p/6919093.html
Copyright © 2011-2022 走看看