免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 979 | 回复: 0
打印 上一主题 下一主题

Uboot-1.1.2 for PXA270源码分析-do_bootm_linux函数源码分析PPC [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-08-01 23:42 |只看该作者 |倒序浏览
do_bootm_linux函数源码分析(PPC)
static 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 sp;
ulong len, checksum;
ulong initrd_start, initrd_end;
ulong cmd_start, cmd_end;
ulong initrd_high;
ulong data;
int initrd_copy_to_ram = 1;
char    *cmdline;
char *s;
bd_t *kbd;
void (*kernel)(bd_t *, ulong, ulong, ulong, ulong); // 内核启动函数指针
image_header_t *hdr = &header;

/*
  * Booting a (Linux) kernel image
  *
  * Allocate space for command line and board info - the
  * address should be as high as possible within the reach of
  * the kernel (see CFG_BOOTMAPSZ settings), but in unused
  * memory, which means far enough below the current stack
  * pointer.
  */
asm( "mr %0,1": "=r"(sp) : );  // 获取当前堆栈地址
sp -= 2048;      // 为了不破坏Uboot的堆栈地址, 向下移动2K
// CFG_BOOTMAPSZ是linux内核启动代码可以做重新映射的最大地址, 所有的可以
// 被linux处理的数据都必须放在这个地址空间以内! 故当上面得到的地址大于
// CFG_BOOTMAPSZ时必须使之等于CFG_BOOTMAPSZ.
if (sp > CFG_BOOTMAPSZ)  // 保证sp指针位于CFG_BOOTMAPSZ内
  sp = CFG_BOOTMAPSZ;
sp &= ~0xF;      // 堆栈指针16字节对齐
debug ("=> set upper limit to 0x%08lX\n", sp);  // 打印堆栈上限地址
// 设置命令行地址(CFG_BARGSIZE=256), 基本上是在地址的最顶端了
cmdline = (char *)((sp - CFG_BARGSIZE) & ~0xF); // 16字节对齐
kbd = (bd_t *)(((ulong)cmdline - sizeof(bd_t)) & ~0xF); // kbd设置在命令行的下面
if ((s = getenv("bootargs")) == NULL)    // 读取保存的命令行参数
  s = "";
strcpy (cmdline, s);     // 拷贝命令行参数到cmdline处
cmd_start    = (ulong)&cmdline[0];  // 取命令行的起始和结束地址
cmd_end      = cmd_start + strlen(cmdline); // 命令行结束地址
*kbd = *(gd->bd);      // 拷贝开发板相关的参数到kbd中
if ((s = getenv ("clocks_in_mhz")) != NULL) { // 设置系统频率(MHz)
  kbd->bi_intfreq /= 1000000L;
  kbd->bi_busfreq /= 1000000L;
}
// 设置内核入口点做为kernel函数的入口
kernel = (void (*)(bd_t *, ulong, ulong, ulong, ulong))hdr->ih_ep;

// 检查参数中是否存在Ramdisk
if (argc >= 3) {      // bootm的命令行的第三个参数,Ram disk
  …
} else if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1])) {
  …
} else {
  SHOW_BOOT_PROGRESS (14); // 启动的第14阶段
  len = data = 0;     // 设置data为0(不使用Ramdisk)
}
if (!data) {       // 不使用 Ram disk
  debug ("No initrd\n");
}
if (data) {        // 使用 Ram disk需要加载Ramdisk盘
     if (!initrd_copy_to_ram) { /* zero-copy ramdisk support */
  initrd_start = data;
  initrd_end = initrd_start + len;
     } else {
  initrd_start  = (ulong)kbd - len;
  initrd_start &= ~(4096 - 1); /* align on page */
  if (initrd_high) {
   ulong nsp;
   /*
    * the inital ramdisk does not need to be within
    * CFG_BOOTMAPSZ as it is not accessed until after
    * the mm system is initialised.
    *
    * do the stack bottom calculation again and see if
    * the initrd will fit just below the monitor stack
    * bottom without overwriting the area allocated
    * above for command line args and board info.
    */
   asm( "mr %0,1": "=r"(nsp) : );
   nsp -= 2048;  /* just to be sure */
   nsp &= ~0xF;
   if (nsp > initrd_high) /* limit as specified */
    nsp = initrd_high;
   nsp -= len;
   nsp &= ~(4096 - 1); /* align on page */
   if (nsp >= sp)
    initrd_start = nsp;
  }
  SHOW_BOOT_PROGRESS (12);
  debug ("## initrd at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n",
   data, data + len - 1, len, len);
  initrd_end    = initrd_start + len;
  printf ("   Loading Ramdisk to %08lx, end %08lx ... ",
   initrd_start, initrd_end);
#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
  {
   size_t l = len;
   void *to = (void *)initrd_start;
   void *from = (void *)data;
   while (l > 0) {
    size_t tail = (l > CHUNKSZ) ? CHUNKSZ : l;
    WATCHDOG_RESET();
    memmove (to, from, tail);
    to += tail;
    from += tail;
    l -= tail;
   }
  }
#else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */
  memmove ((void *)initrd_start, (void *)data, len);
#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
  puts ("OK\n");
     }
} else {
  initrd_start = 0;
  initrd_end = 0;
}
debug ("## Transferring control to Linux (at address %08lx) ...\n",
  (ulong)kernel);
SHOW_BOOT_PROGRESS (15);   // 第15阶段就开始转动内核执行了
// 传递给内核的参数列表:
// r3: 开发板相关信息
// r4: Ramdisk起始地址, 不使用则直接置0
// r5: Ramdisk结束地址, 不使用则直接置0
// r6: 命令行参数起始地址
// r7: 命令行参数结束地址
(*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end); // 启动内核
}
(本文章发表于psbec的个人blog,未经本人许可,不得用于商业用途。任何个人、媒体、其他网站不得私自抄袭;网络媒体转载请注明出处,增加原文链接,否则属于侵权行为。如有任何问题,请留言或者发邮件给psbec,地址
han.psbec@gmail.com
)

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/63631/showart_1101141.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP