kernel如何得到uboot启动信息

转载:http://blog.csdn.net/lanyzh0909/article/details/8917636

一、uboot的的配置和编译

1、配置:make smdk6410_config

SRCTREE             := $(CURDIR)

MKCONFIG   := $(SRCTREE)/mkconfig

 

smdk6410_config       unconfig

       @$(MKCONFIG) $(@:_config=) arm s3c64xx smdk6410 samsung s3c6410

      

 

mkconfig  smdk6410 arm s3c64xx smdk6410 samsung s3c6410

s0        s1       s2  s3       s4      s5       s6

生成如下两个文件:

include/config.mk include/config.h

建立两个软链接文件:

ln -s asm-arm asm

ln -s arch-smdk6410 asm-arm/arch

 

2make

   在编译到最后看到了如下一句:

   arm-linux-ld -Bstatic -T /home/uboot/u-boot-6410/board/samsung/smdk6410/u-boot.lds -Ttext 0xc7e00000 ........

   通过上述可知,uboot.bin的链接地址为:0xc7e00000(整个地址是在board/samsung/smdk6410/config.mk定义),链接脚本为:u-boot.lds

   注意:u-boot.lds中定义了个“.u_boot_cmd”段,地址范围从__u_boot_cmd_start__u_boot_cmd_end

  

二、uboot的源码分析:

       uboot重要的功能如下:

       1)关看门狗

       2)初始化时钟

       3)初始化SDRAM

       4)初始化flash

       5)初始化网卡、usb、串口等

       6)加载内核并且启动内核喂你好你在干麻耶

        u-boot.lds中可以看出“start.o”放在最前面,那么也就注定start.s是整个uboot第一个运行的文件,这样我们就可以从start.s开始分析

       uboot

      

       start.s做了如下的功能:

       1)进入设置为svc

       2)关看门狗

       3)屏蔽中断

       4)初始化

       5)设置stack

       6)时钟

       7)代码重定位,从nand flash  sd ram

       8)bss

       9start_armboot

      

       在进入了start_armboot之后工作流程如下图:

       

最后,从env变量中获取到bootcmd参数(nand read 0xc0008000 0x100000 0x500000;bootm 0xc0008000),执行到了” nand read 0xc0008000 0x100000 0x500000”命令,从nand flash 中将内核到内存中,之后就执行bootm 0xc0008000。最后将会调用如下函数:

do_bootm ->do_bootm_linux->theKernel

1do_bootm:从0x500000中读取UImage的头部,填充到一个全局变量header 中。结构定义为:

[cpp]   view plain copy
  1. typedef struct image_header  
  2.     uint32_t    ih_magic;     
  3.     uint32_t    ih_hcrc;      
  4.     uint32_t    ih_time;      
  5.     uint32_t    ih_size;      
  6.     uint32_t    ih_load;      
  7.     uint32_t    ih_ep;        
  8.     uint32_t    ih_dcrc;      
  9.     uint8_t     ih_os;        
  10.     uint8_t     ih_arch;      
  11.     uint8_t     ih_type;      
  12.     uint8_t     ih_comp;      
  13.     uint8_t     ih_name[IH_NMLEN];    
  14. image_header_t;  

其中我们关心的是“ih_load”和“ih_ep”两个成员,ih_load指定了内核应该在内存的地址,ih_ep指定了执行内核时的入口地址。

2、知道了内核的在内存的地址和内核的入口地址,我们就可以开始启动内核了,但是在启动内核之前,还需要一些信息(如: bootargs,内存的大小、串口的波特率等)告诉内核。这些信息的收集就由“do_bootm_linux”收集。将信息收集好后,怎么样告诉内核呢?很简单,就是按照双方约定内存地址中开辟一块内存,按照双方约定的格式存储就好了!存储的格式如下:

[cpp]   view plain copy
  1. struct tag_header  
  2.     u32 size;  
  3.     u32 tag;  
  4. };  
  5.   
  6. struct tag  
  7.     struct tag_header hdr;  
  8.     union  
  9.         struct tag_core     core;  
  10.         struct tag_mem32    mem;  
  11.         struct tag_videotext    videotext;  
  12.         struct tag_ramdisk  ramdisk;  
  13.         struct tag_initrd   initrd;  
  14.         struct tag_serialnr serialnr;  
  15.         struct tag_revision revision;  
  16.         struct tag_videolfb videolfb;  
  17.         struct tag_cmdline  cmdline;  
  18.   
  19.           
  20.         struct tag_acorn    acorn;  
  21.   
  22.           
  23.         struct tag_memclk   memclk;  
  24.     u;  
  25. };  

添加这些信息首先调用setup_start_tag (bd),添加完后调用setup_end_tag (bd)

 

那这内存地址是在哪里呢?我们定义一个gd全局变量,内存地址保存在gd->bd-> bi_boot_params 中,对gb赋值是在函数“start_armboot”!gd的结构体的定义如下:

[cpp]   view plain copy
  1. typedef struct bd_info  
  2.     int         bi_baudrate;      
  3.     unsigned long   bi_ip_addr;   
  4.     unsigned char   bi_enetaddr[6];   
  5.     struct environment_s           *bi_env;  
  6.     ulong           bi_arch_number;   
  7.     ulong           bi_boot_params;   
  8.     struct                
  9.      
  10.     ulong start;  
  11.     ulong size;  
  12.               bi_dram[CONFIG_NR_DRAM_BANKS];  
  13. #ifdef CONFIG_HAS_ETH1  
  14.       
  15.     unsigned char   bi_enet1addr[6];  
  16. #endif  
  17. bd_t  
  18.   
  19. typedef struct  global_data  
  20.     bd_t        *bd;  
  21.     unsigned long   flags;  
  22.     unsigned long   baudrate;  
  23.     unsigned long   have_console;     
  24.     unsigned long   reloc_off;    
  25.     unsigned long   env_addr;     
  26.     unsigned long   env_valid;    
  27.     unsigned long   fb_base;      
  28. #ifdef CONFIG_VFD  
  29.     unsigned char   vfd_type;     
  30. #endif  
  31. #if 0  
  32.     unsigned long   cpu_clk;      
  33.     unsigned long   bus_clk;  
  34.     unsigned long   ram_size;     
  35.     unsigned long   reset_status;     
  36. #endif  
  37.     void        **jt;         
  38. gd_t;  

3、有了上述信息和配置后我们就可以开始启动内核,调用

theKernel (0, bd->bi_arch_number, bd->bi_boot_params),之后我们的linux内核就开始工作了,uboot的使命就完成了!

 

以下参考:http://blog.csdn.net/songqqnew/article/details/6847392

 

从uboot启动内核的形式theKernel (0, machid, bd->bi_boot_params)
可以看出uboot给内核传递了3个参数,第1个是0,第2个是机器码,第3个是参数列表在SDRAM的起始位置
刚好满足一下调用内核的条件
• R0=0。
• R1=机器类型ID;
• R2=启动参数标记列表在RAM 中起始基地址

在 uboot/board/davinci/dm365evm的board_init函数中
 uboot中:

机器码:
gd->bd->bi_arch_number = MACH_TYPE_DAVINCI_DM365_EVM
而#define MACH_TYPE_DAVINCI_DM365_EVM  1939 定义在arch\arm\include\asm\Mach-types.h中

 

 kernel中:
需对应内核的linux/arch/arm/mach-davinci/Board-dm365-evm.c中一行代码
MACHINE_START(DAVINCI_DM365_EVM, "DaVinci_DM365x_EVM")
而DAVINCI_DM365_EVM定义在linux/asm

#define DAVINCI_DM365_EVM 1939

 

注:

machine type 不匹配
在内核自解压完成以后内核会首先会进入 bl      __lookup_machine_type函数(在arch/arm/kernel/head.S中),检查machine_type是否匹配,如果不匹配会跳入__error_a函数(在arch/arm/kernel/head-common.S中),导致启动失败

 


②指定参数位置:

在uboot:

 uboot/board/davinci/dm365evm 的board_init函数中

gd->bd->bi_boot_params=PHYS_SDRAM_1+0x100  //

#definde PHYS_SDRAM_1 0x80000000 定义在include\configs\Davin_dm365evm.h

 

在kernel中:
对应内核的linux/arch/arm/mach-davinci/Board-dm365-evm.c中一行代码
.boot_params    = (0x80000100),
如果uboot没有给出gd->bd->bi_boot_params的值,则linux默认去这个地址寻址tag
如果uboot给出了gd->bd->bi_boot_params的值,则linux则按照uboot的给的这个地址去寻址tag

所以即使uboot中设置    gd->bd->bi_boot_params = 0x30000000或 0x30000200或 0x300000300(或许设置一个空闲的内存区就可以)
而内核的.boot_params    = S3C2410_SDRAM_PA + 0x100,(就用不到了)
也能顺利启动内核,已试过

在试验中发现uboot中设置gd->bd->bi_boot_params=0或将gd->bd->bi_boot_params注释掉,都未能顺利启动内核。貌似在uboot必须为gd->bd->bi_boot_params指定一个值才行,而linux的.boot_params 始终都没有用到。


gd是一个全局结构体指针,用于uboot中各个文件中重要的参数传递,其成员见http://blog.csdn.net/songqqnew/article/details/6847699
看一下uboot在sdram 0x30000100处给内核传递了什么东东,见http://blog.csdn.net/songqqnew/article/details/6847609
参考嵌入式Linux应用开发完全手册ch15.1 p243

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值