extern void uart0_init(void);
extern void nand_read(unsigned int addr, unsigned char *buf, unsigned int len);
extern void puts(char *str);
extern void puthex(unsigned int val);
u-boot 传参数给内核分析参考http://blog.csdn.net/qingkongyeyue/article/details/52312095
//定义tag结构体
static struct tag *params;
//开始标志函数
void setup_start_tag(void)
{
params = (struct tag *)0x30000100;
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);
}
//内存相关标志函数
void setup_memory_tags(void)
{
params->hdr.tag = ATAG_MEM;
params->hdr.size = tag_size (tag_mem32);
params->u.mem.start = 0x30000000;
params->u.mem.size = 64*1024*1024;
params = tag_next (params);
}
//获取字符串大小函数
int strlen(char *str)
{
int i = 0;
//循环取字符,直到最后一个
while (str[i]){
i++;
}
return i;
}
//字符串拷贝函数
void strcpy(char *dest, char *src)
{
//循环拷贝直到出现结束字符
while ((*dest++ = *src++) != '\0');}
//命令行参数相关标志
void setup_commandline_tag(char *cmdline)
{
int len = strlen(cmdline) + 1;
params->hdr.tag = ATAG_CMDLINE;
params->hdr.size = (sizeof (struct tag_header) + len + 3) >> 2;
strcpy (params->u.cmdline.cmdline, cmdline);
params = tag_next (params);
}
//结束标志函数
void setup_end_tag(void)
{
params->hdr.tag = ATAG_NONE;
params->hdr.size = 0;
}
//主函数
int main(void)
{
//定义函数指针theKernel
void (*theKernel)(int zero, int arch, unsigned int params);volatile unsigned int *p = (volatile unsigned int *)0x30008000;
/* 0. 帮内核设置串口: 内核启动的开始部分会从串口打印一些信息,但是内核一开始没有初始化串口 */
uart0_init();
/* 1. 从NAND FLASH里把内核读入内存 */
puts("Copy kernel from nand\n\r");
//bootloader不支持烧写,使用u-boot烧写,uImage=64字节的头部+zImage(真正的内核),从下面可以看出uImage存在0x60000,zImage存在0x60000+64
真正的内核源地址0x60000+64,目的地址0x30008000,内核大小0x200000(2M)
nand_read(0x60000+64, (unsigned char *)0x30008000, 0x200000);puthex(0x1234ABCD);
puts("\n\r");
puthex(*p);
puts("\n\r");
/* 2. 设置参数 */
puts("Set boot params\n\r");
//表参数设置的开始
setup_start_tag();
//告诉内核,内存有多大
setup_memory_tags();
//命令行参数 root=/dev/mtdblock3表示根文件系统在哪里 init=/linuxrc console=ttySAC0表示内核启动时,内核的打印信息从哪个串口打印出来
setup_commandline_tag("noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0");
//表参数设置的结束
setup_end_tag();/* 3. 跳转执行 */
puts("Boot kernel\n\r");
//函数指针指向0x30008000
theKernel = (void (*)(int, int, unsigned int))0x30008000;
第一个参数是0,第二个参数是机器ID(板子属于哪一类)(参考u-boot程序),第3个参数是存放传给内核的参数的位置0x30000100
theKernel(0, 362, 0x30000100);/*
* mov r0, #0
* ldr r1, =362
* ldr r2, =0x30000100
跳过去执行内核,因为函数指针指向0x30008000。内核代码肯定会解析机器ID这个参数,并把传给内核的参数的位置0x30000100记下来,以后去这个地址读出保存的参数
* mov pc, #0x30008000*/
puts("Error!\n\r");
/* 如果一切正常, 不会执行到这里 */
return -1;
}