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

I bet you dont want to know.

文章分类

全部博文(28)

分类: LINUX

2008-08-01 23:44:11

do_bootm_linux函数源码分析(ARM)
do_bootm函数位于common/cmd_bootm.c文件中。do_bootm函数调用
do_bootm_linux函数启动linux内核,当定义了CONFIG_PPC时将使用
common/cmd_bootm.c文件中的do_bootm_linux函数;当系统中没有定义该宏时,系统将使用lib_arm/armlinux.c文件中定义的do_bootm_linux函数。注意:这两个函数有很大的区别!
 lib_arm/armlinux.c中do_bootm_linux函数源代码:
void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
       ulong addr, ulong *len_ptr, int verify)
{
 DECLARE_GLOBAL_DATA_PTR;
 ulong len = 0, checksum;
 ulong initrd_start, initrd_end;
 ulong data;
 void (*theKernel)(int zero, int arch, uint params);
 image_header_t *hdr = &header;
 bd_t *bd = gd->bd;
#ifdef CONFIG_CMDLINE_TAG
 char *commandline = getenv ("bootargs");
#endif
 theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep); // 设置kernal加载地址
 
 // 用户自定义了initrd之后需要加载进来
 // 整个过程需要进行头部以及整个数据内部校验
 // 类似于内核的加载校验,这里省略了。
 // 下面仅仅列出了无randisk时的处理:
 initrd_start = 0;
 initrd_end = 0;
 SHOW_BOOT_PROGRESS (15);
// 在psbec270.h文件中定义了如下宏
// #define CONFIG_CMDLINE_TAG
// #define CONFIG_SETUP_MEMORY_TAGS
// #define CONFIG_INITRD_TAG
// 根据上面不同的宏加载不同的TAG
// 注意的是必须定义CONFIG_CMDLINE_TAG和CONFIG_SETUP_MEMORY_TAGS
// 除非内核已经根据系统初始化了这些值, 否则必须定义, 不定义将导致无法启动.
#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
    defined (CONFIG_CMDLINE_TAG) || \
    defined (CONFIG_INITRD_TAG) || \
    defined (CONFIG_SERIAL_TAG) || \
    defined (CONFIG_REVISION_TAG) || \
    defined (CONFIG_LCD) || \
    defined (CONFIG_VFD)
 setup_start_tag (bd);
#ifdef CONFIG_SETUP_MEMORY_TAGS
 // 设置memory tags
 setup_memory_tags (bd);
#endif
#ifdef CONFIG_CMDLINE_TAG
 // 设置启动命令行tags
 setup_commandline_tag (bd, commandline);
#endif
#ifdef CONFIG_INITRD_TAG
 if (initrd_start && initrd_end) // 存在ramdisk时设置initrdtag
  setup_initrd_tag (bd, initrd_start, initrd_end);
#endif
 setup_end_tag (bd);
#endif
 // 接下来开始调用执行内核启动
 printf ("\nStarting kernel ...\n\n");
 // 启动之前先做一些清理工作,见下面说明
 cleanup_before_linux ();
 // 调用内核需要传递的参数如下:
 // R0:必须为0
 // R1:机器类型ID,本机为ARM(bd->bi_arch_number)
 // R2:启动参数列表在内存中的位置(bd->bi_boot_params)
 theKernel (0, bd->bi_arch_number, bd->bi_boot_params);
}
// 清理工作,调用内核之前必须满足如下条件才可以:
// CPU模式:
//  必须禁止中断(IRQs和FIQs);
//   CPU 必须 SVC 模式;
// Cache和MMU的设置:
//  MMU 必须关闭;
//  指令 Cache 可以打开也可以关闭;
//  数据 Cache 必须关闭;
int cleanup_before_linux (void)
{
 unsigned long i;
 disable_interrupts ();   // 禁止中断
 // 关闭指令和数据cache
 asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
 i &= ~(C1_DC | C1_IC);
 asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
 i = 0;
 asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (i));
 return (0);
}
 

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