参考http://cgxcn.blog.163.com/blog/static/132312422009101133251202/
参考:http://blog.chinaunix.net/uid-14833587-id-76499.html
参考:http://lixuefeng26.blog.sohu.com/204383842.html
原理就是:uboot将要传递的参数,保存到一个指定的物理位置;然后linux从该物理位置获取数据即可
1.先看一下uboot自带的参数传递过程:
A. 首先说明两个结构体:
boot/u-boot/include/asm-mips
typedef struct global_data {
bd_t *bd;
unsigned long flags;
unsigned long baudrate;
unsigned long have_console; /* serial_init() was called */
unsigned long ram_size; /* RAM size */
unsigned long reloc_off; /* Relocation Offset */
unsigned long env_addr; /* Address of Environment struct */
unsigned long env_valid; /* Checksum of Environment valid? */
void **jt; /* jump table */
} gd_t
和
boot/u-boot/include/asm-mips
typedef struct bd_info {
int bi_baudrate; /* serial console baudrate */
unsigned long bi_ip_addr; /* IP Address */
unsigned char bi_enetaddr[6]; /* Ethernet adress */
unsigned long bi_arch_number; /* unique id for this board */
unsigned long bi_boot_params; /* where this board expects params */
unsigned long bi_memstart; /* start of DRAM memory */
unsigned long bi_memsize; /* size of DRAM memory in bytes */
unsigned long bi_flashstart; /* start of FLASH memory */
unsigned long bi_flashsize; /* size of FLASH memory */
unsigned long bi_flashoffset; /* reserved area for startup monitor */
} bd_t;
B. 在do_bootm_linux(boot/u-boot/lib_mips/mips_linux.c)中,有如下处理:
linux_params_init (UNCACHED_SDRAM (gd->bd->bi_boot_params), commandline); --- 此函数,就是将commandline所指示的启动参数,存放到UNCACHED_SDRAM (gd->bd->bi_boot_params)所指示的物理地址中;同时,利用全局变量linux_argc,linux_argv,linux_env来分别指示这些参数的总数,位置以及环境变量的位置
#if defined(CONFIG_AR7100) || defined(CONFIG_AR7240)
/* Pass the flash size as expected by current Linux kernel for AR7100 */
flash_size_mbytes = gd->bd->bi_flashsize/(1024 * 1024);
theKernel (linux_argc, linux_argv, linux_env, flash_size_mbytes); /*启动内核,也就是说从ntohl (hdr->ih_ep)这个地址开始运行(这里不是函数调用,而是直接运行此地址上的东西;具体就是kernel_entry),其传递的参数就是linux_argc, linux_argv, linux_env, flash_size_mbytes*/
#else
而在linux/kernels/mips-linux-2.6.31/arch/mips/kernel/head.S中,有:
NESTED(kernel_entry, 16, sp)
LONG_S a0, fw_arg0 # firmware arguments
LONG_S a1, fw_arg1[xxx3]
2. 那么,如果我们要将uboot下自定义的一些参数,传递给linux内核。该如何做? 这里,笔者由于工作需要,需要将uboot下记录的一个bootpara结构体参数,传递给linux内核。 实现方案如下:
² Cmd_bootm.c中的do_bootm函数,在:
case IH_COMP_LZMA:
printf (" Uncompressing %s ... ", name);
i = lzma_inflate ((unsigned char *)data, len, (unsigned char*)ntohl(hdr->ih_load), &unc_len);
if (i != LZMA_RESULT_OK) {
printf ("LZMA ERROR %d - must RESET board to recover\n", i);
SHOW_BOOT_PROGRESS (-6);
udelay(100000);
do_reset (cmdtp, flag, argc, argv);
}
/*当解压缩内核成功后,则意味着后面就要调用do_bootm_linux启动内核了;那么这个时候,需要将uboot下记录的boot_para信息,存放到内存的指定位置;
从而传递给linux内核;
所选择的存放位置,需要放在内核解压缩地址的前面(这里留1K空间,存放bootpara参数);这样才能不会影响内核的启动*/
#ifdef CONFIG_XXX_BOOT
else {
unsigned int save_position = ntohl(hdr->ih_load) - 1024; return 0;
}
[xxx1]实际对应linux_argv的值,也就是指向存放参数的地址
[xxx2]在prom_init中,就有使用fw_arg0,fw_arg1,fw_arg2,fw_arg3的处理了,利用这些参数,恢复成全局变量:arcs_cmdline的值
[xxx3]利用arcs_cmdline,得到command_line和boot_command_line的值
[xxx5]即uboot中,将linux内核释放到的内存地址
[xxx6]存储bootpara参数的地址
[xxx7]获取存储的bootpara参数内容