1、bd_t结构体:用于保存开发板相关的参数
在include\asm-arm\u-boot.h
typedef struct bd_info {
int bi_baudrate; /* serial console baudrate */
unsigned long bi_ip_addr; /* IP Address */
unsigned char bi_enetaddr[6]; /* Ethernet adress MAC地址*/
struct environment_s *bi_env;
ulong bi_arch_number; /* unique id for this board 板子ID*/
ulong bi_boot_params; /* where this board expects params 启动参数*/
struct /* RAM configuration :RAM配置*/
{
ulong start;
ulong size;
} bi_dram[CONFIG_NR_DRAM_BANKS];
#ifdef CONFIG_HAS_ETH1//如果有定义第二块网卡就···,实际没有定义,忽略
/* second onboard ethernet port */
unsigned char bi_enet1addr[6];
#endif
} bd_t;
主要使用于armlinux.c文件用来定义u-boot传递给kernel的参数
================================================================================================
2、gd_t结构体:成员主要是系统的初始化参数
在include/am-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 重定位偏移,实际定向的位置与编译连接时指定的位置之差,一般为0*/
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 */
#ifdef CONFIG_VFD
unsigned char vfd_type; /* display type */
#endif
#if 0
unsigned long cpu_clk; /* CPU clock in Hz! */
unsigned long bus_clk;
unsigned long ram_size; /* RAM size */
unsigned long reset_status; /* reset status register at boot */
#endif
void **jt; /* jump table */
} gd_t;
#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8") //指定使用r8通用寄存器来传递参数
//这是一个全局的数据结构型指针。使用:
在include/asm-arm/global_data.h中有:
#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8") //定义一个指向gd_t结构体的寄存器指针变量gd
在lib_arm/board.c中:
gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
在bd_t结构体中:
ulong bi_boot_params;
在board\tq2440\tq2440.c中:
gd->bd->bi_boot_params = 0x30000100; //这就设定了uboot传递给内核的启动参数的存放地址0x30000100
========================================================================================================
3、建立启动参数tags
上面说明了内核启动参数的存放地址,下面就来分析这些启动参数uboot是如何建立的。
首先建立tag的结构体,在include/asm-arm/setup.h中
(1)先定义tag成员的结构体:
struct tag_header {
u32 size;//这个tag的大小
u32 tag;//我觉得是用来标记这个tag的身份,就是kernel读每一个tag的时候要靠这些来识别tag
};
struct tag_core {
u32 flags; /* bit 0 = read-only */
u32 pagesize;
u32 rootdev;
};
struct tag_mem32 {
u32 size;
u32 start; /* physical start address */
};
struct tag_mem32 {
u32 size;
u32 start; /* physical start address */
};
还有其他的,这里没有一一列出来
(2)接着又在这个文件的后面定义tag的数据结构:
static struct tag *params;
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;
};
中间定义了一个union共同体,这样可以节省空间。
用函数来建立每一个tag,即初始化每一个tag成员的初值,在lib_arm/armlinux.c文件里头定义tag的初始化函数:
(1)先设置可以指向tag的指针变量:
static struct tag *params;
(2)接着开始初始化第一个tag:setup_start_tag
static void setup_start_tag (bd_t *bd)
{
params = (struct tag *) bd->bi_boot_params;
params->hdr.tag = ATAG_CORE;//0x54410001
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指针,让他能够指向bi_boot_params启动参数的起始地址,接着设置其他东西,最后指向下一个tag的地址。
其他tag函数的功能分析和这个大同小异,不再一一分析。
还有就是这些函数是在do_bootm_linux()函数里面被调用。
========================================================================================================================
4、uboot要附加到zImage的头部数据结构
首先是在include/image.h头文件里面定义了tag的头的结构体:
typedef struct image_header {
uint32_t ih_magic; /* Image Header Magic Number */
uint32_t ih_hcrc; /* Image Header CRC Checksum */
uint32_t ih_time; /* Image Creation Timestamp */
uint32_t ih_size; /* Image Data Size */
uint32_t ih_load; /* Data Load Address */
uint32_t ih_ep; /* Entry Point Address */
uint32_t ih_dcrc; /* Image Data CRC Checksum */
uint8_t ih_os; /* Operating System */
uint8_t ih_arch; /* CPU architecture */
uint8_t ih_type; /* Image Type */
uint8_t ih_comp; /* Compression Type */
uint8_t ih_name[IH_NMLEN]; /* Image Name */
} image_header_t;
在lib_arm/armlinux.c的do_bootm_linux()函数里面有引用image_header_t结构体:
image_header_t *hdr = &header;//这个header地址是内核的头部起始地址,即内核的加载地址
最终这个结构体是正真要被mkimage工具固化到zImage头部的。 uboot的重要的数据结构就基本是这些了。
===========================================================================================================
5、uboot自身的环境变量:
在include/configs/ta2440.h里面设定环境变量的存放地址:
#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x1F0000)
//#define CFG_ENV_IS_IN_FLASH1 //不存放在nor Flash中
#define CFG_ENV_IS_IN_NAND 1 //将环境变量存放到nand Flash中
#define CFG_ENV_OFFSET 0x40000 //环境变量存放处的偏移地址
#define CFG_ENV_SIZE64 0xc000
#define CFG_ENV_SIZE 0x20000
#define CFG_NAND_BASE 0
“saveenv”看看究竟存放的地址,具体实现函数先不分析,“print”看看环境变量存放了哪些信息
EmbedSky> print
bootargs=noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0
【其实是:
bootargs=“noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0”
root=/dev/mtdblock2:
指定根文件系统位于第三个Flash分区(noinitrd当没有使用ramdisk启动系统时要加上这个参数)
ramdisk就是把内存当做硬盘来使用
init=/linuxrc:
指定第一个应用程序是谁
console=ttySAC0:指定内核的打印信息从哪里打印出来】
bootcmd=nboot 0x32000000 kernel; bootm 0x32000000
bootdelay=0
baudrate=115200
ethaddr=0a:1b:2c:3d:4e:5f
ipaddr=192.168.1.6
serverip=192.168.1.8
netmask=255.255.255.0
stdin=serial
stdout=serial
stderr=serial
mtdids=nand0=nandflash0
mtdparts=mtdparts=nandflash0:[email protected](bios),128k(params),128k(toc),512k(eboot),1024k(logo),2m(kernel),-(root)
partition=nand0,0
mtddevnum=0
mtddevname=bios
Environment size: 453/131068 bytes