分享

uboot分析之bootm

 向往~ 2011-09-08

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

1.common/cmd_bootm.c

Cpp代码 复制代码
  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

Cpp代码 复制代码
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
  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
Cpp代码 复制代码
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
  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
Cpp代码 复制代码
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
  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. }  

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多