Chinaunix首页 | 论坛 | 博客

OS

  • 博客访问: 2280336
  • 博文数量: 691
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2660
  • 用 户 组: 普通用户
  • 注册时间: 2014-04-05 12:49
个人简介

不浮躁

文章分类

全部博文(691)

文章存档

2019年(1)

2017年(12)

2016年(99)

2015年(207)

2014年(372)

分类: 嵌入式

2015-12-13 12:05:45

U-boot 中有一个用来保存很多有用信息的全局结构体-- gd_t ( global data 缩
写),其中包括了 bd 变量,可以说 gd_t 结构体包括了 u-boot 中所有重要全局变量。
最后传递给内核的参数,都是从 gd 和 bd 中来的,如上述的 setup_memory_tags 函数
作用就是用 bd 中的值来初始化 RAM 相应的 tag 。
对于 ARM 平台这个结构体的定义大致如下:
include/asm-arm/global_data.h
typedef struct global_data {
bd_t *bd;
unsigned long flags;
unsigned long baudrate;
unsigned long have_console; /* serial_init() was called */
unsigned long reloc_off; /* Relocation Offset */
unsigned long env_addr; /* Address of Environment struct */
unsigned long env_valid; /* Checksum of Environment valid? */
unsigned long fb_base; /* base address of frame buffer */
void **jt; /* jump table */
} gd_t;
在 U-boot 中使用 gd 结构之前要用先用宏 DECLARE_GLOBAL_DATA_PTR 来
声明。这个宏的定义如下:
include/asm-arm/global_data.h
#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")
从这个宏的定义可以看出, gd 是一个保存在 ARM 的 r8 寄存器中的 gd_t 结构
体的指针。
说明:本文的版本为U-boot-1.3.4 、Linux-2.6.28 ,平台是ARM 。
//补充一下:
来自:http://hi.baidu.com/armfans/blog/item/306cd5035f24ff084afb514b.html
bootloader巧妙地利用函数指针及传参规范将R0:0x0,R1:机器号,R2:参数地址传递
给内核.由于R0,R1比较简单,不需要再作说明.需要花点时间了解的是R2寄存器.
R2寄存器传递的是一个指针,这个指针指向一个TAG区域.UBOOT和Linux内核之
间正是通过这个扩展了的TAG区域来进行复杂参数的传递,如 command line,文件系
统信息等等,用户也可以扩展这个TAG来进行更多参数的传递.TAG区域存放的地址,
也就是R2的值,是在/board /yourboard/youboard.c里的board_init函数中初始化的,
如在UB4020中初始化为:gd->bd->bi_boot_params = 0x30000100;,这是一个绝对地
址.
TAG区的结构比较简单,可以视为一个一个TAG的排列(数组?),每一个TAG传
递一种特定类型的参数.各种系统TAG的定义可以参考./include/asm-arm/setup.h.
下面是一个TAG区的例子:
0x30000100 00000005 54410001 00000000 00000000
0x30000110 00000000 0000000F 54410009 746F6F72
0x30000120 65642F3D 61722F76 7220306D 6F632077
0x30000130 6C6F736E 74743D65 2C305379 30303639
0x30000140 696E6920 6C2F3D74 78756E69 EA006372
0x30000150 00000004 54420005 30300040 00200000
0x30000160 00000000 00000000
我们可以看到一共有三个TAG:
第一个TAG的长度是5个字,类型是ATAG_CORE(54410001),有三个元素,均为
全零.TAG区必须以这个TAG开头.
第二个TAG的长度是F个字,类型是ATAG_CMDLINE(54410009),这是一个字符串,
是向内核传递的kernel command line
第三个TAG的长度是4个字,类型是ATAG_INITRD2(54410005),有两个元素,第
一个是start:30300040(30300000+40),第二个是size:200000(2M)
如果说还有第四个TAG,那就是末尾的两个全零,这是TAG结束的标志.
这些TAG是在./lib_arm/arm_linux.c中的do_bootm_linux函数中建立起来的.具
体建立哪些TAG,由相应的控制宏决定.具体可以参考相应代码.例子中第一个TAG是
起始TAG,如果环境变量中有bootargs,则建立第二个TAG,如果bootm有两个参数(引
导文件系统),则会读取文件系统头部的必要信息,建立第三个TAG.
内核启动后,将根据R2寄存器的值找到这些TAG,并根据TAG类型,调用相应的处
理函数进行处理,从而获取内核运行的必要信息.
阅读(2474) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~