uboot分析之bootm_start

bootm命令执行过程中调用了bootm_start函数,这个函数比较重要,所以先分析它。

1.common/cmd_bootm.c

 
  1. static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  
  2. {  
  3.     void        *os_hdr;  
  4.     int     ret;  
  5.     memset ((void *)&images, 0, sizeof (images));//images是一个bootm_headers_t类型的全局变量。见下面的分析。   
  6.     images.verify = getenv_yesno ("verify");//从环境变量中检查是否要对镜像的数据(不是镜像头)进行校验。   
  7.     bootm_start_lmb();//不做任何有意义的工作,除了定义# define lmb_reserve(lmb, base, size)   
  8.     /* get kernel image header, start address and length */寻找可用的内核镜像,见下面的分析。主要根据传入的参数检查镜像的合法性并获取信息。  
  9.     os_hdr = boot_get_kernel (cmdtp, flag, argc, argv,  
  10.             &images, &images.os.image_start, &images.os.image_len);//返回指向内存中镜像头的指针   
  11.     if (images.os.image_len == 0) {  
  12.         puts ("ERROR: can't get kernel image!/n");  
  13.         return 1;  
  14.     }  
  15.     /* get image parameters */  
  16.     switch (genimg_get_format (os_hdr)) {//根据镜像魔数获取镜像类型   
  17.     case IMAGE_FORMAT_LEGACY:  
  18.         images.os.type = image_get_type (os_hdr);//镜像类型   
  19.         images.os.comp = image_get_comp (os_hdr);//压缩类型   
  20.         images.os.os = image_get_os (os_hdr);//操作系统类型   
  21.         images.os.end = image_get_image_end (os_hdr);//当前镜像的尾地址   
  22.         images.os.load = image_get_load (os_hdr);//镜像数据的载入地址   
  23.         break;  
  24.     default:  
  25.         puts ("ERROR: unknown image format type!/n");  
  26.         return 1;  
  27.     }  
  28.     /* find kernel entry point */  
  29.     if (images.legacy_hdr_valid) {//如果镜像已经通过验证   
  30.         images.ep = image_get_ep (&images.legacy_hdr_os_copy);//获取入口地址,填充images.ep 。   
  31.     } else {  
  32.         puts ("Could not find kernel entry point!/n");  
  33.         return 1;  
  34.     }  
  35.     if (((images.os.type == IH_TYPE_KERNEL) ||  
  36.          (images.os.type == IH_TYPE_MULTI)) &&  
  37.         (images.os.os == IH_OS_LINUX)) {  
  38.         /* find ramdisk */3250的配置中这个函数不做任何工作  
  39.         ret = boot_get_ramdisk (argc, argv, &images, IH_INITRD_ARCH,  
  40.                 &images.rd_start, &images.rd_end);  
  41.         if (ret) {  
  42.             puts ("Ramdisk image is corrupt or invalid/n");  
  43.             return 1;  
  44.         }  
  45.     }  
  46.     images.os.start = (ulong)os_hdr;//指向内存中镜像的头地址   
  47.     images.state = BOOTM_STATE_START;//标记引导状态   
  48.     return 0;  
  49. }  
 

总结一下这个函数的主要工作:第一步校验镜像的正确性,获取镜像的信息(根据镜像头),第二部将第一步获取的信息存入images(主要是填充image_info_t类型的os成员)

2. bootm_headers_t

 
  1. typedef struct bootm_headers {  
  2.     /* 
  3.      * Legacy os image header, if it is a multi component image 
  4.      * then boot_get_ramdisk() and get_fdt() will attempt to get 
  5.      * data from second and third component accordingly. 
  6.      */  
  7.     image_header_t    *legacy_hdr_os;        /* image header pointer */  
  8.     image_header_t    legacy_hdr_os_copy;    /* header copy */  
  9.     ulong        legacy_hdr_valid;  
  10. #ifndef USE_HOSTCC   
  11.     image_info_t    os;        /* os image info */  
  12.     ulong        ep;        /* entry point of OS */  
  13.     ulong        rd_start, rd_end;/* ramdisk start/end */  
  14.     ulong        ft_len;        /* length of flat device tree */  
  15.     ulong        initrd_start;  
  16.     ulong        initrd_end;  
  17.     ulong        cmdline_start;  
  18.     ulong        cmdline_end;  
  19.     bd_t        *kbd;  
  20. #endif   
  21.     int        verify;        /* getenv("verify")[0] != 'n' */  
  22. #define    BOOTM_STATE_START        (0x00000001)   
  23. #define    BOOTM_STATE_LOADOS        (0x00000002)   
  24. #define    BOOTM_STATE_RAMDISK    (0x00000004)   
  25. #define    BOOTM_STATE_FDT        (0x00000008)   
  26. #define    BOOTM_STATE_OS_CMDLINE    (0x00000010)   
  27. #define    BOOTM_STATE_OS_BD_T    (0x00000020)   
  28. #define    BOOTM_STATE_OS_PREP    (0x00000040)   
  29. #define    BOOTM_STATE_OS_GO        (0x00000080)   
  30.     int        state;  
  31. } bootm_headers_t;  
  32. /* 
  33.  * Legacy format image header, 
  34.  * all data in network byte order (aka natural aka bigendian). 
  35.  */内核镜像头  include/image.h  
  36. typedef struct image_header {  
  37.     uint32_t    ih_magic;        /* Image Header Magic Number    */镜像头部幻数,为#define IH_MAGIC    0x27051956  
  38.     uint32_t    ih_hcrc;            /* Image Header CRC Checksum    */镜像头部crc校验码  
  39.     uint32_t    ih_time;            /* Image Creation Timestamp    */镜像创建时间戳  
  40.     uint32_t    ih_size;            /* Image Data Size        */镜像数据大小(不算头部)1828536  
  41.     uint32_t    ih_load;            /* Data     Load  Address        */数据将要载入的内存地址   80008000  
  42.     uint32_t    ih_ep;            /* Entry Point Address        */镜像入口地址        80008000             
  43.     uint32_t    ih_dcrc;            /* Image Data CRC Checksum    */镜像数据校验码  
  44.     uint8_t        ih_os;        /* Operating System        */操作系统类型    #define IH_OS_LINUX        5  
  45.     uint8_t        ih_arch;        /* CPU architecture        */CPU架构类型    #define IH_ARCH_ARM        2  
  46.     uint8_t        ih_type;        /* Image Type            */镜像类型        IH_TYPE_KERNEL  
  47.     uint8_t        ih_comp;    /* Compression Type        */压缩类型        IH_COMP_NONE  
  48.     uint8_t        ih_name[IH_NMLEN];    /* Image Name        */镜像名字Linux-2.6.27.8,#define IH_NMLEN        32  
  49. } image_header_t;  
  50. 镜像信息      include/image.h  
  51. typedef struct image_info {  
  52.     ulong        start, end;            /* start/end of blob */镜像的起始地址和尾地址  
  53.     ulong        image_start, image_len;         /* start of image within blob, len of image */镜像数据的开始地址和长度  
  54.     ulong        load;                /* load addr for the image */镜像数据的装载地址  
  55.     uint8_t        comp, type, os;            /* compression, type of image, os type */压缩类型,镜像类型和操作系统类型  
  56. } image_info_t;  
 

3。boot_get_kernel

 
  1. /** 
  2.  * boot_get_kernel - find kernel image 
  3.  * @os_data: pointer to a ulong variable, will hold os data start address 
  4.  * @os_len: pointer to a ulong variable, will hold os data length 
  5.  * 
  6.  * boot_get_kernel() tries to find a kernel image, verifies its integrity 
  7.  * and locates kernel data. 
  8.  * 
  9.  * returns: 
  10.  *     pointer to image header if valid image was found, plus kernel start 
  11.  *     address and length, otherwise NULL 
  12.  */  
  13. 寻找可用的内核镜像  
  14. static void *boot_get_kernel (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],  
  15.         bootm_headers_t *images, ulong *os_data, ulong *os_len)  
  16. {  
  17.     image_header_t    *hdr;  
  18.     ulong        img_addr;  
  19.     /* find out kernel image address */  
  20.     if (argc < 2) {//如果参数太少   
  21.         img_addr = load_addr;    //使用默认的镜像载入地址,这个地址是在配置头文件中定义的 ulong load_addr = CONFIG_SYS_LOAD_ADDR;   
  22.         debug ("*  kernel: default image load address = 0x%08lx/n",  
  23.                 load_addr);  
  24.     } else {  
  25.         img_addr = simple_strtoul(argv[1], NULL, 16);//参数足够的话,把第二个参数转化为16进制作为地址   
  26.         debug ("*  kernel: cmdline image address = 0x%08lx/n", img_addr);  
  27.     }  
  28.     show_boot_progress (1);  
  29.     /* copy from dataflash if needed */  
  30.     img_addr = genimg_get_image (img_addr);//对于3250,这个函数什么都没做。因为没有dataflash.   
  31.     /* check image type, for FIT images get FIT kernel node */  
  32.     *os_data = *os_len = 0;  
  33.     switch (genimg_get_format ((void *)img_addr)) {//根据上面得到的镜像的地址,获取镜像的类型。这个函数根据镜像头部的魔数返回类型。   
  34.     case IMAGE_FORMAT_LEGACY:  
  35.         printf ("## Booting kernel from Legacy Image at %08lx .../n",   //打印引导消息   
  36.                 img_addr);  
  37.         hdr = image_get_kernel (img_addr, images->verify);//检验镜像的合法性(校验码、魔数、架构类型等),并打印信息。见下面的分析。   
  38.         if (!hdr)  
  39.             return NULL;  
  40.         show_boot_progress (5);  
  41.         /* get os_data and os_len */  
  42.         switch (image_get_type (hdr)) {  
  43.         case IH_TYPE_KERNEL:  
  44.             *os_data = image_get_data (hdr);//镜像数据的地址,也就是紧挨着镜像头的地址。   
  45.             *os_len = image_get_data_size (hdr);//镜像数据部分大小   
  46.             break;  
  47.         case IH_TYPE_MULTI:  
  48.             image_multi_getimg (hdr, 0, os_data, os_len);  
  49.             break;  
  50.         case IH_TYPE_STANDALONE:  
  51.             *os_data = image_get_data (hdr);  
  52.             *os_len = image_get_data_size (hdr);  
  53.             break;  
  54.         default:  
  55.             printf ("Wrong Image Type for %s command/n", cmdtp->name);  
  56.             show_boot_progress (-5);  
  57.             return NULL;  
  58.         }  
  59.         /* 
  60.          * copy image header to allow for image overwrites during kernel 
  61.          * decompression. 
  62.          */拷贝一份镜像的头部到images中。  
  63.         memmove (&images->legacy_hdr_os_copy, hdr, sizeof(image_header_t));  
  64.         /* save pointer to image header */  
  65.         images->legacy_hdr_os = hdr;//images中指针指向镜像的头部   
  66.         images->legacy_hdr_valid = 1;//镜像已经检验合格,置标志量   
  67.         show_boot_progress (6);  
  68.         break;  
  69.     default:  
  70.         printf ("Wrong Image Format for %s command/n", cmdtp->name);  
  71.         show_boot_progress (-108);  
  72.         return NULL;  
  73.     }  
  74.     debug ("   kernel data at 0x%08lx, len = 0x%08lx (%ld)/n",  
  75.             *os_data, *os_len, *os_len);  
  76.     return (void *)img_addr;  
  77. }  
 

4。image_get_kernel

 
  1. common/cmd_bootm.c  
  2. static image_header_t *image_get_kernel (ulong img_addr, int verify)  
  3. {  
  4.     image_header_t *hdr = (image_header_t *)img_addr;  
  5.     if (!image_check_magic(hdr)) {    //检查镜像头部的魔数是否等于 IH_MAGIC   
  6.         puts ("Bad Magic Number/n");  
  7.         show_boot_progress (-1);  
  8.         return NULL;  
  9.     }  
  10.     show_boot_progress (2);  
  11.     if (!image_check_hcrc (hdr)) {//检查镜像头部的校验码(hcrc为0时镜像头的校验码)   
  12.         puts ("Bad Header Checksum/n");  
  13.         show_boot_progress (-2);  
  14.         return NULL;  
  15.     }  
  16.     show_boot_progress (3);  
  17.     image_print_contents (hdr);//根据传入的镜像头地址,打印镜像的信息,见下面的分析。   
  18. /* 
  19.    Image Name:   Linux-2.6.27.8 
  20.    Image Type:   ARM Linux Kernel Image (uncompressed) 
  21.    Data Size:    1828536 Bytes = 1.7 MiB 
  22.    Load Address: 80008000 
  23.    Entry Point:  80008000 
  24. */  
  25.     if (verify) {//是否要对镜像的数据部分进行校验   
  26.         puts ("   Verifying Checksum ... ");  
  27.         if (!image_check_dcrc (hdr)) {  
  28.             printf ("Bad Data CRC/n");  
  29.             show_boot_progress (-3);  
  30.             return NULL;  
  31.         }  
  32.         puts ("OK/n");  
  33.     }  
  34.     show_boot_progress (4);  
  35.     if (!image_check_target_arch (hdr)) {//检查是否是IH_ARCH_ARM架构   
  36.         printf ("Unsupported Architecture 0x%x/n", image_get_arch (hdr));  
  37.         show_boot_progress (-4);  
  38.         return NULL;  
  39.     }  
  40.     return hdr;  
  41. }  

你可能感兴趣的:(command,移植,u-boot)