zoukankan      html  css  js  c++  java
  • u-boot 2011.09 调用kernel 的流程

    这段时候我总是觉得有个问题,u-boot 的存在是不是就是为了调用kernel 而存在的。

    所以,粗浅的跟了一下这个流程,还有很多细节上的东西没有做好,往指正。

    u-boot-2011.9 调用内核代码跟踪
    1. _start  board_init_r  main_loop.
    这个流程是u-boot 的一个整体的流程。

    2. main_loop()
    这个函数主要执行一些u-boot 最后的一些工作,

     347 #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)                        
     348     s = getenv ("bootdelay");                                                   
     349     bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;         
     350                                                                                 
     351     debug ("### main_loop entered: bootdelay=%d
    
    ", bootdelay);               
     352                                                                                 

    这里是设置系统的启动延时的时间。
    如果在include/configs/ok335x.h 里面设置了宏定义CONFIG_BOOTDELAY大于零
    那么在延时期间中断便可进入shell 终端界面。

     371         s = getenv ("bootcmd");                                                 
     372                                                                                 
     373     debug ("### main_loop: bootcmd="%s"
    ", s ? s : "<UNDEFINED>");           
     374                                                                                 
     375     if (bootdelay >= 0 && s && !abortboot (bootdelay)) {                        
     376 # ifdef CONFIG_AUTOBOOT_KEYED                                                   
     377         int prev = disable_ctrlc(1);    /* disable Control C checking */        
     378 # endif                                                                         
     379                                                                                 
     380 # ifndef CONFIG_SYS_HUSH_PARSER                                                 
     381         run_command (s, 0);                                                     

    这里面就有关于u-boot 调用kernel 的方法。
    Bootcmd 的定义在common/env_common.c 里面。

     51 #ifdef  CONFIG_BOOTARGS                                                         
     52     "bootargs=" CONFIG_BOOTARGS         ""                                    

    这是关于bootcmd 的定义。
    在c语言中一个字符串其实本质上代表的就是的指针。
    Bootcmd 指向的是CONFIG_BOOTCOMMAND 这个地址。

    CONFIG_BOOTCOMMAND 这个宏的定义在include/configs/ok335x.h 里面。

    193 #define CONFIG_BOOTCOMMAND                                                     
    194     " if test $bootdev = MMC; then "                                           
    195         "mmc dev ${mmcdev}; mmc rescan;"                                       
    196         "echo SD/MMC found on device ${mmcdev};"                               
    197         "if run loadbootenv; then "                                            
    198             "echo Loaded environment from ${bootenv};"                         
    199             "run importbootenv;"                                               
    200         "fi;"                                                                  
    201         "if test -n $uenvcmd; then "                                           
    202             "echo Running uenvcmd ...;"                                        
    203             "run uenvcmd;"                                                     
    204         "fi;"                                                                  
    205         "if run loaduimagefat; then "                                          
    206             "run mmcboot;"                                                     
    207         "elif run loaduimage; then "                                           
    208             "run mmcboot;"                                                     
    209         "else "                                                                
    210             "echo Could not find ${bootfile} ;"                                
    211         "fi;"                                                                  
    212     "else "                                                                    
    213         "run nandboot;"                                                        
    214     "fi;"                                                                      

    这边的话我们是直接运行run nandboot ;

    149     "nandboot=echo Booting from nand ...; "                                    
    150         "run nandargs; "                                                       
    151         "nandecc hw 2;"                                                        
    152         "nand read ${loadaddr} ${nandsrcaddr} ${nandimgsize}; "                
    153         "bootm ${loadaddr}"                                                  

    最后运行bootm ${loadaddr} ,就可以运行kernel 。

    3. run_command() 函数
    这个函数的实现在common/main.c 里面。
    运行run_command 函数,如果成功运行,返回1或者0,如果没有运行则返回-1。
    命令结构体。

     46 struct cmd_tbl_s {                                                              
     47     char        *name;      /* Command Name         */                          
     48     int     maxargs;    /* maximum number of arguments  */                      
     49     int     repeatable; /* autorepeat allowed?      */                          
     50                     /* Implementation function  */                              
     51     int     (*cmd)(struct cmd_tbl_s *, int, int, char * const []);              
     52     char        *usage;     /* Usage message    (short) */                      
     53 #ifdef  CONFIG_SYS_LONGHELP                                                     
     54     char        *help;      /* Help  message    (long)  */                      
     55 #endif                                                                          
     56 #ifdef CONFIG_AUTO_COMPLETE                                                     
     57     /* do auto completion on the arguments */                                   
     58     int     (*complete)(int argc, char * const argv[], char last_char, int maxv, char *c    mdv[]);
     59 #endif                                                                          
     60 };                                                                              
     61                                                                                 
     62 typedef struct cmd_tbl_s    cmd_tbl_t;                                          


    最后运行这条命令。

    1372         /* OK - call function to do the command */                              
    1373         if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) {                      
    1374             rc = -1;                                                            
    1375         }                                                                       

    4. bootm 命令分析

    在run_command 里面,以及前面的分析可以得出,最终,他会调用
    bootm 命令,并且指向kernel 的地址。
    bootm 命令的实现是在common/cmd_bootm.c 中实现。

     585 /*******************************************************************/           
     586 /* bootm - boot application image from image in memory */                       
     587 /*******************************************************************/           
     588                                                                                 
     589 int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])        
     590 {                                                                               


    其实这个函数做了三个很重要的功能。
    bootm_start : 内核启动前的准备工作,获取内核的信息并检查。
    bootm_load_os : 检查内核的文件格式,是否需要解压。
    boot_fn : 内核启动函数的调用, 我们调用的是do_bootm_linux 函数。

    1) bootm_start
    从do_bootm 调用了这一个函数。

     625     if (bootm_start(cmdtp, flag, argc, argv))                                   
     626         return 1;                                                               


    有时候我们加载内核不成功,很多时候会报can’t get kernel image就是在这里报的。
    从下可以看到,我们又调用了boot_get_kernel 函数。

     214 static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
     215 {                                                                               
     216     void        *os_hdr;                                                        
     217     int     ret;                                                                
     218                                                                                 
     219     memset ((void *)&images, 0, sizeof (images));                               
     220     images.verify = getenv_yesno ("verify");                                    
     221                                                                                 
     222     bootm_start_lmb();                                                          
     223                                                                                 
     224     /* get kernel image header, start address and length */                     
     225     os_hdr = boot_get_kernel (cmdtp, flag, argc, argv,                          
     226             &images, &images.os.image_start, &images.os.image_len);             
     227     if (images.os.image_len == 0) {                                             
     228         puts ("ERROR: can't get kernel image!
    ");                              
     229         return 1;                                                               
     230     }                                                                           

    这个函数的作用其实是:找到kernel 镜像。

     839 static void *boot_get_kernel (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]     ,           
     840         bootm_headers_t *images, ulong *os_data, ulong *os_len)                 
     841 {                                                                               
     842     image_header_t  *hdr;                                                       
     843     ulong       img_addr;                                                       
     869     } else {                                                                    
     870         img_addr = simple_strtoul(argv[1], NULL, 16);                           
     871         debug ("*  kernel: cmdline image address = 0x%08lx
    ", img_addr);       
     872     }                                                                           
     873                                                                                 
     874     show_boot_progress (1);                                                     
     875                                                                                 
     876     /* copy from dataflash if needed */                                         
     877     img_addr = genimg_get_image (img_addr);                                     
     878                                                                                 
     879     /* check image type, for FIT images get FIT kernel node */                  
     880     *os_data = *os_len = 0;                                                     
     881     switch (genimg_get_format ((void *)img_addr)) {                             
     882     case IMAGE_FORMAT_LEGACY:                                                   
     883         printf ("## Booting kernel from Legacy Image at %08lx ...
    ",           
     884                 img_addr);                                                      
     885         hdr = image_get_kernel (img_addr, images->verify);                      

    打印一句调试信息。
    然后通过image_get_kernel 获取kernel.

     741 static image_header_t *image_get_kernel (ulong img_addr, int verify)            
     742 {                                                                               
     743     image_header_t *hdr = (image_header_t *)img_addr;                           
     744                                                                                 
     745     if (!image_check_magic(hdr)) {                                              
     746         puts ("Bad Magic Number
    ");                                            
     747         show_boot_progress (-1);                                                
     748         return NULL;                                                            
     749     }                                                                           
     750     show_boot_progress (2);                                                     
     751                                                                                 
     752     if (!image_check_hcrc (hdr)) {                                              
     753         puts ("Bad Header Checksum
    ");                                         
     754         show_boot_progress (-2);                                                
     755         return NULL;                                                            
     756     }                                                                           
     757                                                                                 
     758     show_boot_progress (3);                                                     
     759     image_print_contents (hdr);                                                 
     760                                                                                 
     761     if (verify) {                                                               
     762         puts ("   Verifying Checksum ... ");                                    
     763         if (!image_check_dcrc (hdr)) {                                          
     764             printf ("Bad Data CRC
    ");                                          
     765             show_boot_progress (-3);                                            
     766             return NULL;                                                        
     767         }                                                                       
     768         puts ("OK
    ");                                                          
     769     }                                                                           
     770     show_boot_progress (4);                                                     
     771                                                                                 
     772     if (!image_check_target_arch (hdr)) {                                       
     773         printf ("Unsupported Architecture 0x%x
    ", image_get_arch (hdr));       
     774         show_boot_progress (-4);                                                
     775         return NULL;                                                            
     776     }                                                                           
     777     return hdr;                                                                 
     778 }                                                                               
     300 void image_print_contents (const void *ptr)                                     
     301 {                                                                               
     302     const image_header_t *hdr = (const image_header_t *)ptr;                    
     303     const char *p;                                                              
     304                                                                                 
     305 #ifdef USE_HOSTCC                                                               
     306     p = "";                                                                     
     307 #else                                                                           
     308     p = "   ";                                                                  
     309 #endif                                                                          
     310                                                                                 
     311     printf ("%sImage Name:   %.*s
    ", p, IH_NMLEN, image_get_name (hdr));       
     312 #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC)
     313     printf ("%sCreated:      ", p);                                             
     314     genimg_print_time ((time_t)image_get_time (hdr));                           
     315 #endif                                                                          
     316     printf ("%sImage Type:   ", p);                                             
     317     image_print_type (hdr);                                                     
     318     printf ("%sData Size:    ", p);                                             
     319     genimg_print_size (image_get_data_size (hdr));                              
     320     printf ("%sLoad Address: %08x
    ", p, image_get_load (hdr));                 
     321     printf ("%sEntry Point:  %08x
    ", p, image_get_ep (hdr));                   
     322                                                                                 
     323     if (image_check_type (hdr, IH_TYPE_MULTI) ||                                
     324             image_check_type (hdr, IH_TYPE_SCRIPT)) {                           
     325         int i;                                                                  
     326         ulong data, len;                                                        
     327         ulong count = image_multi_count (hdr);                                  
     328                                                                                 
     329         printf ("%sContents:
    ", p);                                            
     330         for (i = 0; i < count; i++) {                                           
     331             image_multi_getimg (hdr, i, &data, &len);                           
     332                                                                                 
     333             printf ("%s   Image %d: ", p, i);                                   
     334             genimg_print_size (len);                                            
     335                                                                                 
     336             if (image_check_type (hdr, IH_TYPE_SCRIPT) && i > 0) {              
     337                 /*                                                              
     338                  * the user may need to know offsets                            
     339                  * if planning to do something with                             
     340                  * multiple files                                               
     341                  */                                                             
     342                 printf ("%s    Offset = 0x%08lx
    ", p, data);                   
     343             }                                                                   
     344         }                                                                       
     345     }                                                                           
     346 }                                                                               
     347                                                                             

    打印内核信息。打印校验和校验是否正确。


    OK,到此从image_get_kernel - > boot_get_kernel 回来。

     772     if (!image_check_target_arch (hdr)) {                                       
     773         printf ("Unsupported Architecture 0x%x
    ", image_get_arch (hdr));       
     774         show_boot_progress (-4);                                                
     775         return NULL;                                                            
     776     }                                                                           
     777     return hdr;                                                                 
     778 }   

    返回内核地址。

    再从boot_get_kernel 回到bootm_start

     232     /* get image parameters */                                                  
     233     switch (genimg_get_format (os_hdr)) {                                       
     234     case IMAGE_FORMAT_LEGACY:                                                   
     235         images.os.type = image_get_type (os_hdr);                               
     236         images.os.comp = image_get_comp (os_hdr);                               
     237         images.os.os = image_get_os (os_hdr);                                   
     238                                                                                 
     239         images.os.end = image_get_image_end (os_hdr);                           
     240         images.os.load = image_get_load (os_hdr);                               
     241         break;                                                                  

    获取内核的参数并保存。

     275     default:                                                                    
     276         puts ("ERROR: unknown image format type!
    ");                           
     277         return 1;                                                               

    有时候我们加载内核失败会报这个错误。

     280     /* find kernel entry point */                                               
     281     if (images.legacy_hdr_valid) {                                              
     282         images.ep = image_get_ep (&images.legacy_hdr_os_copy);                  

    找到内核的入口。

     297     if (((images.os.type == IH_TYPE_KERNEL) ||                                  
     298          (images.os.type == IH_TYPE_MULTI)) &&                                  
     299         (images.os.os == IH_OS_LINUX)) {                                        
     300         /* find ramdisk */                                                      
     301         ret = boot_get_ramdisk (argc, argv, &images, IH_INITRD_ARCH,            
     302                 &images.rd_start, &images.rd_end);                              
     303         if (ret) {                                                              
     304             puts ("Ramdisk image is corrupt or invalid
    ");                     
     305             return 1;                                                           
     306         }                                                                       

    获取虚拟磁盘。

     321     images.os.start = (ulong)os_hdr;                                            
     322     images.state = BOOTM_STATE_START;                                           
     323                                                                                 
     324     return 0;                                                                   
     325 }                                                                               

    保存内核开启地址,并给开始的状态。

    从bootm_start 回到do_bootm.

     625     if (bootm_start(cmdtp, flag, argc, argv))                                   
     626         return 1;                                                               

    正常情况下bootm_start 是返回0,所以不会执行return 1;
    2) bootm_load_os 函数

     648     ret = bootm_load_os(images.os, &load_end, 1);                               

    获取文件类型,打印调试信息。

     327 #define BOOTM_ERR_RESET     -1                                                  
     328 #define BOOTM_ERR_OVERLAP   -2                                                  
     329 #define BOOTM_ERR_UNIMPLEMENTED -3                                              
     330 static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress)   
     331 {                                                                               
     332     uint8_t comp = os.comp;                                                     
     333     ulong load = os.load;                                                       
     334     ulong blob_start = os.start;                                                
     335     ulong blob_end = os.end;                                                    
     336     ulong image_start = os.image_start;                                         
     337     ulong image_len = os.image_len;                                             
     338     uint unc_len = CONFIG_SYS_BOOTM_LEN;                                        
     339 #if defined(CONFIG_LZMA) || defined(CONFIG_LZO)                                 
     340     int ret;                                                                    
     341 #endif /* defined(CONFIG_LZMA) || defined(CONFIG_LZO) */                        
     342                                                                                 
     343     const char *type_name = genimg_get_type_name (os.type);                     
     344                                                                                 
     345     switch (comp) {                                                             
     346     case IH_COMP_NONE:                                                          
     347         if (load == blob_start || load == image_start) {                        
     348             printf ("   XIP %s ... ", type_name);                               
     349         } else {                                                                
     350             printf ("   Loading %s ... ", type_name);                           
     351             memmove_wd ((void *)load, (void *)image_start,                      
     352                     image_len, CHUNKSZ);                                        
     353         }                                                                       
     354         *load_end = load + image_len;                                           
     355         puts("OK
    ");                                                           
     356         break;                                                                  
     436     flush_cache(load, (*load_end - load) * sizeof(ulong));                      
     437                                                                                 
     438     puts ("OK
    ");                                                              
     439     debug ("   kernel loaded at 0x%08lx, end = 0x%08lx
    ", load, *load_end);    
     440     if (boot_progress)                                                          
     441         show_boot_progress (7);                                                 
     442                                                                                 
     443     if ((load < blob_end) && (*load_end > blob_start)) {                        
     444         debug ("images.os.start = 0x%lX, images.os.end = 0x%lx
    ", blob_start, blob_end     );
     445         debug ("images.os.load = 0x%lx, load_end = 0x%lx
    ", load, *load_end);  
     446                                                                                 
     447         return BOOTM_ERR_OVERLAP;                                               
     448     }                                                                           
     449                                                                                 
     450     return 0;                                                                   
     451 }                                                                               

    从bootm_load_os 回到do_bootm

     648     ret = bootm_load_os(images.os, &load_end, 1);                               
     649                                                                                 
     650     if (ret < 0) {                                                              
     651         if (ret == BOOTM_ERR_RESET)                                             
     652             do_reset (cmdtp, flag, argc, argv);                                 
     653         if (ret == BOOTM_ERR_OVERLAP) {                                         
     654             if (images.legacy_hdr_valid) {                                      
     655                 if (image_get_type (&images.legacy_hdr_os_copy) == IH_TYPE_MULTI)
     656                     puts ("WARNING: legacy format multi component "             
     657                         "image overwritten
    ");                                 
     658             } else {                                                            
     659                 puts ("ERROR: new format image overwritten - "                  
     660                     "must RESET the board to recover
    ");                       
     661                 show_boot_progress (-113);                                      
     662                 do_reset (cmdtp, flag, argc, argv);                             
     663             }                                                                   
     664         }                                                                       
     665         if (ret == BOOTM_ERR_UNIMPLEMENTED) {                                   
     666             if (iflag)                                                          
     667                 enable_interrupts();                                            
     668             show_boot_progress (-7);                                            
     669             return 1;                                                           
     670         }                                                                       
     671     }                                                                           

    如果刚才出错,那么检查错误编号,打印错误信息。

     690     boot_fn = boot_os[images.os.os];                                            
     691                                                                                 
     692     if (boot_fn == NULL) {                                                      
     693         if (iflag)                                                              
     694             enable_interrupts();                                                
     695         printf ("ERROR: booting os '%s' (%d) is not supported
    ",               
     696             genimg_get_os_name(images.os.os), images.os.os);                    
     697         show_boot_progress (-8);                                                
     698         return 1;                                                               
     699     }                                                                           
     700                                                                                 
     701     arch_preboot_os();                                                          
     702                                                                                 
     703     boot_fn(0, argc, argv, &images);                                            
     704                                                                                 

    其实这一步调用的是do_bootm_linux

     134 static boot_os_fn *boot_os[] = {                                                
     135 #ifdef CONFIG_BOOTM_LINUX                                                       
     136     [IH_OS_LINUX] = do_bootm_linux,                                             
     137 #endif                                                                          
     138 #ifdef CONFIG_BOOTM_NETBSD                                                      
     139     [IH_OS_NETBSD] = do_bootm_netbsd,                                           
     140 #endif                                                                          
     141 #ifdef CONFIG_LYNXKDI                                                           
     142     [IH_OS_LYNXOS] = do_bootm_lynxkdi,                                          
     143 #endif                                                                          
     144 #ifdef CONFIG_BOOTM_RTEMS                                                       
     145     [IH_OS_RTEMS] = do_bootm_rtems,                                             
     146 #endif                                                                          
     147 #if defined(CONFIG_BOOTM_OSE)                                                   
     148     [IH_OS_OSE] = do_bootm_ose,                                                 
     149 #endif                                                                          
     150 #if defined(CONFIG_CMD_ELF)                                                     
     151     [IH_OS_VXWORKS] = do_bootm_vxworks,                                         
     152     [IH_OS_QNX] = do_bootm_qnxelf,                                              
     153 #endif                                                                          
     154 #ifdef CONFIG_INTEGRITY                                                         
     155     [IH_OS_INTEGRITY] = do_bootm_integrity,                                     
     156 #endif                                                                          
     157 };                                                                              

    do_bootm_linux 函数其实在arch/arm/lib/bootm.c里面

     96 int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)   
     97 {                                                                               
     98     bd_t    *bd = gd->bd;                                                       
     99     char    *s;                                                                 
    100     int machid = bd->bi_arch_number;                                            
    101     void    (*kernel_entry)(int zero, int arch, uint params);                   
    102                                                                                 
    103 #ifdef CONFIG_CMDLINE_TAG                                                       
    104     char *commandline = getenv ("bootargs");                                    
    105 #endif                                                                          
    106                                                                                 
    107     if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))                             
    108         return 1;                                                               
    109                                                                                 
    110     s = getenv ("machid");                                                      
    111     if (s) {                                                                    
    112         machid = simple_strtoul (s, NULL, 16);                                  
    113         printf ("Using machid 0x%x from environment
    ", machid);                
    114     }                                                                           
    115                                                                                 
    116     show_boot_progress (15);                                                    
    117                                                                                 
    118 #ifdef CONFIG_OF_LIBFDT                                                         
    119     if (images->ft_len)                                                         
    120         return bootm_linux_fdt(machid, images);                                 
    121 #endif                                                                          
    122                                                                                 
    123     kernel_entry = (void (*)(int, int, uint))images->ep;                        
    124                                                                                 
    125     debug ("## Transferring control to Linux (at address %08lx) ...
    ",         
    126            (ulong) kernel_entry);                                               
    127                                                                                 

    声明一个函数指针。
    把镜像入口给kernel_entry 这个函数指针。

    128 #if defined (CONFIG_SETUP_MEMORY_TAGS) ||                                      
    129     defined (CONFIG_CMDLINE_TAG) ||                                            
    130     defined (CONFIG_INITRD_TAG) ||                                             
    131     defined (CONFIG_SERIAL_TAG) ||                                             
    132     defined (CONFIG_REVISION_TAG)                                               
    133     setup_start_tag (bd);                                                       
    134 #ifdef CONFIG_SERIAL_TAG                                                        
    135     setup_serial_tag (&params);                                                 
    136 #endif                                                                          
    137 #ifdef CONFIG_REVISION_TAG                                                      
    138     setup_revision_tag (&params);                                               
    139 #endif                                                                          
    140 #ifdef CONFIG_SETUP_MEMORY_TAGS                                                 
    141     setup_memory_tags (bd);                                                     
    142 #endif                                                                          
    143 #ifdef CONFIG_CMDLINE_TAG                                                       
    144     setup_commandline_tag (bd, commandline);                                    
    145 #endif                                                                          
    146 #ifdef CONFIG_INITRD_TAG                                                        
    147     if (images->rd_start && images->rd_end)                                     
    148         setup_initrd_tag (bd, images->rd_start, images->rd_end);                
    149 #endif                                                                          
    150     setup_end_tag(bd);                                                          
    151 #endif                                                                          

    初始化开始标签。
    初始化串口。
    初始化版本信息。
    初始化内存。
    初始化命令行。
    End.

    153     announce_and_cleanup();                                                     
    154                                                                                 
    155     kernel_entry(0, machid, bd->bi_boot_params);                                
    156     /* does not return */                                                       
    157                                                                                 
    158     return 1;                                                                   
    159 }                                                                               

    正式进入内核。

    参考:http://blog.csdn.net/g_salamander/article/details/8463854

  • 相关阅读:
    nullnull聚类小文(二)
    classjavaCore Java Question List #6
    设置仿真器HJTAG ARM仿真器和MDK 联调设置
    二分图判断hdu 1829 A Bug's Life
    信息掩码游戏地图掩码相关(msk)
    导航accessibilityAndroid 抽屉导航
    算法nodehdu 2112 hdu today
    链接函数hdu 1234开门人和关门人
    分配器内存一步一步写STL:空间配置器(1)
    程序连接如何使用JLink V8 烧写程序到NOR Flash
  • 原文地址:https://www.cnblogs.com/chenfulin5/p/5942273.html
Copyright © 2011-2022 走看看