加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

uboot从bootm跳到内核

(2014-03-18 23:28:59)
标签:

it

分类: uboot移植
main_loop中执行的最重要的操作便是引导内核。引导分两步。第一步先读取内核镜像uImage到内存。然后再使用bootm引导内核。
读取内核只是进行内存复制,因此仅仅需要分析bootm。
Cpp代码 
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
  1.   
  2.   
  3.   
  4. 引导应用程序在内存中的镜像。  
  5. common/cmd_bootm.c  
  6. int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  
  7.  
  8.     ulong        iflag;  
  9.     ulong        load_end 0;  
  10.     int        ret;  
  11.     boot_os_fn    *boot_fn;  
  12.     检查是否有子命令  
  13.     if (argc 1)  
  14.         char *endp;  
  15.         simple_strtoul(argv[1], &endp, 16);  //调用字符串转无符号整形的函数,endp指向尾字符。  
  16.            
  17.         if ((*endp != 0) && (*endp != ':'&& (*endp != '#'))    //是否有子命令。一般不会有,所以这个路径不会执行。  
  18.             return do_bootm_subcommand(cmdtp, flag, argc, argv);  
  19.      
  20.     if (bootm_start(cmdtp, flag, argc, argv)) //bootm_start的分析见下一篇文章。这个函数执行成功返回0,失败返回1。这个函数主要用于获取镜像的信息并存入images。  
  21.         return 1;  
  22.       
  23.     iflag disable_interrupts();//禁用中断。  
  24.     ret bootm_load_os(images.os, &load_end, 1);//将镜像的数据从images.os.image_start复制到images.os.load  打印:Loading Kernel Image ... OK  
  25.     if (ret 0) {//上个函数调用失败才会进入这个路径  
  26.         if (ret == BOOTM_ERR_RESET)  
  27.             do_reset (cmdtp, flag, argc, argv);  
  28.         if (ret == BOOTM_ERR_OVERLAP)  
  29.             if (images.legacy_hdr_valid)  
  30.                 if (image_get_type (&images.legacy_hdr_os_copy) == IH_TYPE_MULTI)  
  31.                     puts ("WARNING: legacy format multi component "  
  32.                         "image overwritten\n");  
  33.             else  
  34.                 puts ("ERROR: new format image overwritten "  
  35.                     "must RESET the board to recover\n");  
  36.                 show_boot_progress (-113);  
  37.                 do_reset (cmdtp, flag, argc, argv);  
  38.              
  39.          
  40.         if (ret == BOOTM_ERR_UNIMPLEMENTED)  
  41.             if (iflag)  
  42.                 enable_interrupts();  
  43.             show_boot_progress (-7);  
  44.             return 1;  
  45.          
  46.      
  47.     lmb_reserve(&images.lmb, images.os.load, (load_end images.os.load));//由于没有定义CONFIG_LMB,这个函数调用被定义为一个空的宏。  
  48.     if (images.os.type == IH_TYPE_STANDALONE) {//处理单独的程序镜像。显然引导内核时不会进入这个路径。  
  49.         if (iflag)  
  50.             enable_interrupts();  
  51.           
  52.         bootm_start_standalone(iflag, argc, argv);  
  53.         return 0;  
  54.      
  55.     show_boot_progress (8);  
  56.     boot_fn boot_os[images.os.os];//根据操作系统的类型获取引导操作系统的函数, boot_os代码如下。  
  57.     if (boot_fn == NULL)  
  58.         if (iflag)  
  59.             enable_interrupts();  
  60.         printf ("ERROR: booting os '%s' (%d) is not supported\n" 
  61.             genimg_get_os_name(images.os.os), images.os.os);  
  62.         show_boot_progress (-8);  
  63.         return 1;  
  64.      
  65.     arch_preboot_os();//禁用中断,重设中断向量  
  66.     boot_fn(0, argc, argv, &images);//调用do_bootm_linux,分析在下面。  
  67.     show_boot_progress (-9);  
  68. #ifdef DEBUG  
  69.     puts ("\n## Control returned to monitor resetting...\n");  
  70. #endif  
  71.     do_reset (cmdtp, flag, argc, argv);  
  72.     return 1;  
  73.  


2。boot_os
Cpp代码 
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
  1. static boot_os_fn *boot_os[]  
  2. #ifdef CONFIG_BOOTM_LINUX  
  3.     [IH_OS_LINUX] do_bootm_linux,  
  4. #endif  
  5. #ifdef CONFIG_BOOTM_NETBSD  
  6.     [IH_OS_NETBSD] do_bootm_netbsd,  
  7. #endif  
  8. #ifdef CONFIG_LYNXKDI  
  9.     [IH_OS_LYNXOS] do_bootm_lynxkdi,  
  10. #endif  
  11. #ifdef CONFIG_BOOTM_RTEMS  
  12.     [IH_OS_RTEMS] do_bootm_rtems,  
  13. #endif  
  14. #if defined(CONFIG_CMD_ELF)  
  15.     [IH_OS_VXWORKS] do_bootm_vxworks,  
  16.     [IH_OS_QNX] do_bootm_qnxelf,  
  17. #endif  
  18. #ifdef CONFIG_INTEGRITY  
  19.     [IH_OS_INTEGRITY] do_bootm_integrity,  
  20. #endif  
  21. };  


3。do_bootm_linux
之前所做的引导工作都是与操作系统无关的,接下来都是针对linux 的。
可以看到,参数flag传过来的是0。
Cpp代码 
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
  1. arch/arm/lib/bootm.c  
  2. int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)  
  3.  
  4.     bd_t    *bd gd->bd;  
  5.     char    *s;  
  6.     int    machid bd->bi_arch_number;  
  7.     void    (*theKernel)(int zero, int arch, uint params);  
  8. #ifdef CONFIG_CMDLINE_TAG//如果定义了这个宏,将会把bootargs传给内核。  
  9.     char *commandline getenv ("bootargs");//获取bootargs环境变量。  
  10. #endif  
  11.     if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))  
  12.         return 1;  
  13.     theKernel (void (*)(intintuint))images->ep;//镜像的入口地址处也就是需要执行的函数入口  
  14.     getenv ("machid");  
  15.     if (s)  
  16.         machid simple_strtoul (s, NULL, 16);  
  17.         printf ("Using machid 0x%x from environment\n"machid);  
  18.      
  19.     show_boot_progress (15);  
  20.     debug ("## Transferring control to Linux (at address lx) ...\n" 
  21.            (ulong) theKernel);  
  22. //下面将会初始化传给内核的标签(tag),这些标签里包含了必要的环境变量和参数。  
  23. #if defined (CONFIG_SETUP_MEMORY_TAGS) || \  
  24.     defined (CONFIG_CMDLINE_TAG) ||  
  25.     defined (CONFIG_INITRD_TAG) ||  
  26.     defined (CONFIG_SERIAL_TAG) ||  
  27.     defined (CONFIG_REVISION_TAG)  
  28.     setup_start_tag (bd);  
  29. #ifdef CONFIG_SETUP_MEMORY_TAGS  
  30.     setup_memory_tags (bd);//内存有关的定义  
  31. #endif  
  32. #ifdef CONFIG_CMDLINE_TAG  
  33.     setup_commandline_tag (bd, commandline);//将bootargs传给tag  
  34. #endif  
  35. #ifdef CONFIG_INITRD_TAG  
  36.     if (images->rd_start && images->rd_end)//没有ramdisk所以不会执行这个路径  
  37.         setup_initrd_tag (bd, images->rd_start, images->rd_end);  
  38. #endif  
  39.     setup_end_tag (bd);  
  40. #endif  
  41.       
  42.     printf ("\nStarting kernel ...\n\n");//引导内核之前最后一次打印信息。  
  43.     cleanup_before_linux ();//禁用中断和cache.  
  44.     theKernel (0, machid, bd->bi_boot_params);//跳到内核中执行。<<<<全剧终>>>>  
  45.       
  46.     return 1;  
  47.  



4.
Cpp代码 
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
  1. arch/arm/include/asm  
  2.   
  3. #define ATAG_CORE    0x54410001  
  4. struct tag_core  
  5.     u32 flags;          
  6.     u32 pagesize;  
  7.     u32 rootdev;  
  8. };  
  9.   
  10. #define ATAG_CMDLINE    0x54410009  
  11. struct tag_cmdline {//bootargs保存在它的后面  
  12.     char    cmdline[1];      
  13. };  
  14.   
  15.   
  16. #define ATAG_INITRD    0x54410005  
  17.   
  18. #define ATAG_INITRD2    0x54420005  
  19. struct tag_initrd {//描述ramdisk的分布  
  20.     u32 start;      
  21.     u32 size;      
  22. };  
  23.   
  24. #define ATAG_MEM    0x54410002  
  25. struct tag_mem32  
  26.     u32    size;  
  27.     u32    start;      
  28. };  
  29. struct tag_header  
  30.     u32 size;  
  31.     u32 tag;  
  32. };  
  33. struct tag  
  34.     struct tag_header hdr;  
  35.     union  
  36.         struct tag_core        core;  
  37.         struct tag_mem32    mem;  
  38.         struct tag_videotext    videotext;  
  39.         struct tag_ramdisk    ramdisk;  
  40.         struct tag_initrd        initrd;  
  41.         struct tag_serialnr    serialnr;  
  42.         struct tag_revision    revision;  
  43.         struct tag_videolfb    videolfb;  
  44.         struct tag_cmdline    cmdline;  
  45.           
  46.         struct tag_acorn    acorn;  
  47.           
  48.         struct tag_memclk    memclk;  
  49.     u;  
  50. };  

5.
Cpp代码 
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
  1. arch/arm/include/asm/setup.h  
  2. #define tag_next(t)    ((struct tag *)((u32 *)(t) (t)->hdr.size))//跳到下一个tag地址处  
  3. arch/arm/lib/bootm.c  
  4. static void setup_start_tag (bd_t *bd)  
  5.  
  6.     params (struct tag *) bd->bi_boot_params;  //CFG_ENV_ADDR(0x80000100)设置环境变量的头地址。  
  7.     params->hdr.tag ATAG_CORE;            //第一个tag默认为 tag_core。ATAG_CORE 是默认的开始类型。  
  8.     params->hdr.size tag_size (tag_core);  
  9.     params->u.core.flags 0;  
  10.     params->u.core.pagesize 0;  
  11.     params->u.core.rootdev 0;  
  12.     params tag_next (params);        //跳到下一个tag地址处  
  13.  
  14. #ifdef CONFIG_SETUP_MEMORY_TAGS  
  15. static void setup_memory_tags (bd_t *bd)//设置内存分布的tag  
  16.  
  17.     int i;  
  18.     for (i 0; CONFIG_NR_DRAM_BANKS; i++) {//如果有多个内存芯片,则会循环多次。对3250来说,只有一片。  
  19.         params->hdr.tag ATAG_MEM;  
  20.         params->hdr.size tag_size (tag_mem32);  
  21.         params->u.mem.start bd->bi_dram[i].start;//内存块的开始地址。PHYS_SDRAM_1;在smartarm3250.h中,起始地址(0x80000000)  
  22.         params->u.mem.size bd->bi_dram[i].size;//内存块的大小  
  23.         params tag_next (params);//跳到下一个tag地址处  
  24.      
  25.  
  26. #endif   
  27. static void setup_commandline_tag (bd_t *bd, char *commandline)  
  28.  
  29.     char *p;  
  30.     if (!commandline)  
  31.         return 
  32.       
  33.     for (p commandline; *p == 'p++);//跳过开头的空格  
  34.       
  35.     if (*p == '\0' 
  36.         return 
  37.     params->hdr.tag ATAG_CMDLINE;  
  38.     params->hdr.size  
  39.         (sizeof (struct tag_header) strlen (p) 4) >> 2;  
  40.     strcpy (params->u.cmdline.cmdline, p);//将bootargs复制到cmdline后面。  
  41.     params tag_next (params);//跳到下一个tag地址处  
  42.  
  43. #ifdef CONFIG_INITRD_TAG  
  44. static void setup_initrd_tag (bd_t *bd, ulong initrd_start, ulong initrd_end)  
  45.  
  46.       
  47.     params->hdr.tag ATAG_INITRD2;  
  48.     params->hdr.size tag_size (tag_initrd);  
  49.     params->u.initrd.start initrd_start;  
  50.     params->u.initrd.size initrd_end initrd_start;  
  51.     params tag_next (params);  
  52.  
  53. #endif   
  54. static void setup_end_tag (bd_t *bd)  
  55.  
  56.     params->hdr.tag ATAG_NONE;//最后一个tag是一个空类型,标志这tag的结束。  
  57.     params->hdr.size 0;  
  58.  
http://daimajishu.iteye.com/blog/1087397

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有