Chinaunix首页 | 论坛 | 博客
  • 博客访问: 77634
  • 博文数量: 28
  • 博客积分: 1415
  • 博客等级: 上尉
  • 技术积分: 351
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-15 13:18
个人简介

I bet you dont want to know.

文章分类

全部博文(28)

分类: LINUX

2008-08-01 23:46:06

直接引导zImage
 下面的命令是我自己增加的命令,不使用uImage,直接引导zImage文件。具体方法是使用tftp命令从网络下载zImage文件到内存中或者直接读取flash数据,拷贝到内存中,假设拷贝到了A地址处,接下来就可以调用:
 # bootzimage A
来引导linux内核了,具体分析见下面说明。
 Uboot在设置启动命令的时候使用的是Tag方式,也就是内核现在期望使用的参数传递方式。还有一种引导设置方式,就是采用2.2以及以前版本使用的参数设置方式,2.4和2.6内核为了兼容之前版本参数设置,对老版本参数数据进行了解析,转换成了内部tag方式。这样我们完全可以使用老版本的参数传递方式。
 Setup.h文件中定义了老版本参数传递结构:
#define COMMAND_LINE_SIZE 1024  // 命令行最多1024字节
/* This is the old deprecated way to pass parameters to the kernel */
struct param_struct {
    union {
 struct {
     unsigned long page_size;  // 内存的页面大小
     unsigned long nr_pages;   // 内存页面数量
     unsigned long ramdisk_size;  // RAM disk配置, 可以不用
     unsigned long flags;  /* 12 */
#define FLAG_READONLY 1
#define FLAG_RDLOAD 4
#define FLAG_RDPROMPT 8
     unsigned long rootdev;  /* 16 */
     unsigned long video_num_cols; /* 20 */
     unsigned long video_num_rows; /* 24 */
     unsigned long video_x;  /* 28 */
     unsigned long video_y;  /* 32 */
     unsigned long memc_control_reg; /* 36 */
     unsigned char sounddefault;  /* 40 */
     unsigned char adfsdrives;  /* 41 */
     unsigned char bytes_per_char_h; /* 42 */
     unsigned char bytes_per_char_v; /* 43 */
     unsigned long pages_in_bank[4]; /* 44 */
     unsigned long pages_in_vram; /* 60 */
     unsigned long initrd_start;  /* 64 */
     unsigned long initrd_size;  /* 68 */
     unsigned long rd_start;  /* 72 */
     unsigned long system_rev;  /* 76 */
     unsigned long system_serial_low; /* 80 */
     unsigned long system_serial_high; /* 84 */
     unsigned long mem_fclk_21285;       /* 88 */
 } s;
 char unused[256];
    } u1;
    union {
 char paths[8][128];
 struct {
     unsigned long magic;
     char n[1024 - sizeof(unsigned long)];
 } s;
    } u2;
    char commandline[COMMAND_LINE_SIZE];  // 命令行启动参数
};
在整个结构中,最关键的部分是u1.s.page_size,u1.s.nr_pages和commandline域。这三个域也是必须设置的域!
代码如下:
#define LINUX_MACHINE_ID 406  // 见后面说明
#define LINUX_PAGE_SHIFT 12  // 页面大小4K
#define LINUX_PAGE_SIZE  (1<
int do_bootzimage(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
 int i;
 u32 addr;
 char *cmdline = getenv ("bootargs"); // 获得命令行参数
 void (*run)(int zero, int arch);   // 定义引导内核的函数原型
 
// 设置引导参数所处的位置
 struct param_struct *params = (struct param_struct *)0xa0000100;
 
 // 设置内核加载地址
 if (argc<2)
  addr = load_addr;  // 默认的加载地址
 else
// 调用命令时参数传递了地址, 那么就使用指定的地址
  addr = simple_strtoul(argv[1], NULL, 16); 
  // 接下来将结构的数据清零, 不用的全部清零, 防止出错
 for(i=0; i<(sizeof(struct param_struct)>>2); i++)
  ((u32 *)params)[i] = 0;
 
 // 设置u1.s.page_size和u1.s.nr_pages参数, 这两个参数由内核自动解析.
 params->u1.s.page_size = LINUX_PAGE_SIZE;
 params->u1.s.nr_pages = (0x04000000 >> LINUX_PAGE_SHIFT);
 // 拷贝命令行参数到命令位置
 memcpy(params->commandline, cmdline, strlen(cmdline));
 
 run = (void (*)(int, int))addr;
// 执行内核程序, 传递两个参数进去, 第2个参数指定了ARCH值, 必须与
// 内核配置的相同, 否则会出现”Error: a”错误!!
run(0, LINUX_MACHINE_ID);
}
// 最后定义bootzImage命令,实现函数是do_bootzimage。
U_BOOT_CMD(
 bootzimage, 2, 1, do_bootzimage,
 "bootzimage - boot zImage from ram.\n",
 " [addr] boot zImage directoly. "
);
 这里我们在引导的时候使用了老版本的参数传递方式,下面时Linux内核在进行参数解析时的代码,可以看到,内核将这些参数自动转换成能够识别的类型:
 内核(2.6.9)的init/main.c文件中的start_kernel()函数中调用了setup_arch()函数:
asmlinkage void __init start_kernel(void)
{
 char * command_line;
 extern struct kernel_param __start___param[], __stop___param[];
/*
 * Interrupts are still disabled. Do necessary setups, then
 * enable them
 */
 lock_kernel();
 page_address_init();
 printk(linux_banner);
 setup_arch(&command_line); // 这个函数中将对传递的参数进行解析
 setup_per_cpu_areas();

 setup_arch()函数位于体系结构相关的代码中,本例中存在于arch/arm/kernel/setup.c文件中。
 以下是该函数的部分内容

 struct tag *tags = (struct tag *)&init_tags;

 // 判断是不是tag的ATAG_CORE, 老式的参数是不能满足要求的, 如果是老式的
 // 参数那么将会执行convert_to_tag_list(tags)将老式参数转换成新的参数类型.
 if (tags->hdr.tag != ATAG_CORE)
  convert_to_tag_list(tags);
 convert_to_tag_list()函数实现在arch/arm/kernel/compat.c文件中,该函数随后调用build_tag_list()函数进行参数重组,具体可以参考内核的源代码。
 

(本文章发表于psbec的个人blog,未经本人许可,不得用于商业用途。任何个人、媒体、其他网站不得私自抄袭;网络媒体转载请注明出处,增加原文链接,否则属于侵权行为。如有任何问题,请留言或者发邮件给psbec,地址)
阅读(1466) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~