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. }

uboot分析之bootm_start相关推荐

  1. u-boot分析之编译体验(零)

    目录 u-boot分析之编译体验 1. 嵌入式系统与pc系统的启动对比概述 2.如何应用补丁文件生成uboot.bin文件,步骤: 3. uboot里要实现的功能 3.1 uboot最终目的是启动内核 ...

  2. u-boot分析(四)---设置异常向量表|设置SVC模式

    u-boot分析(四) 通过前三篇的分析,我们对u-boot已经有了整体的认识和掌握,但是我们仍然对于其部分硬件是如何初始化的不太清楚,所以接下来几篇博文我将会对我们在http://www.cnblo ...

  3. u-boot分析(八)----串口初始化

    u-boot分析(八) 上篇博文我们按照210的启动流程,分析到了内存初始化,今天我们继续按照u-boot的启动流程对串口的初始化进行分析. 今天我们会用到的文档: 1.        2440芯片手 ...

  4. U-BOOT分析(二)之顶层Makefile文件(1)

    U-BOOT分析(二)之顶层Makefile文件(1) U-BOOT版本 u-boot版本:    u-boot-2021.01.tar.bz2 Makefile && make简介 ...

  5. U-Boot移植教程之一:U-Boot分析与启动过程

    内容来自 韦东山<嵌入式Linux应用开发完全手册> 一.Bootloader的引出 当系统上电时,并不是直接进入Linux系统的,而是需要先执行一段程序来把单片机的硬件外围初始化好,比如 ...

  6. u-boot分析之两阶段代码分析(三)

    目录 u-boot(三)启动文件 1,概述 2,uboot第一阶段代码分析: 汇编 2,uboot第二阶段代码分析 C:_start_armboot C:main_loop u-boot(三)启动文件 ...

  7. u-boot分析之命令实现(四)

    目录 u-boot(四)命令实现 分析run_command 小结 自定义一个命令 代码 makefile u-boot(四)命令实现 命令是如何实现的? 输入命令 执行函数,根据命令去寻找函数 所以 ...

  8. u-boot分析之内核启动(五)

    目录 u-boot(五)内核启动 概述 分区空间 内核文件格式 内核复制跳转 内核启动 机器ID 启动参数 (起始tag)setup_start_tag 内存设置 根文件系统,启动程序,串口设备 (结 ...

  9. u-boot分析之makefile分析(二)

    目录 u-boot(二)makefile 引入 目录结构(1.1.6) 配置文件 目标 配置具体的单板 编译阶段 过程 链接入口 配置链接地址 附录 附录A:mkconfig解析 附录B 链接脚本 u ...

最新文章

  1. linux查看上下文切换命令,Linux性能优化,Linux查看CPU上下文切换
  2. 如何寻找属于自己的高富帅和大公司!
  3. [Jarvis OJ - PWN]——Typo(内涵peak小知识)
  4. JAVA Collection笔记(2012/9/19)
  5. acl审计软件_什么是IT审计员?风险评估的重要角色
  6. 第一阶段 XHTML.定位样式
  7. stdafx.h预编译头
  8. python 字符串%和format_Python必懂知识点,格式化字符串,到底用.format还是%
  9. FDA批准首个无需人类医生指导的AI,可独立诊断眼科疾病
  10. 12项目管理--项目采购管理
  11. 孪生支持向量机基本原理
  12. 郑州大学计算机上机模拟题库,郑州大学VB考试模拟试题
  13. 执行mvn clean报错Plugin org.apache.maven.plugins:maven-clean-plugin:2.5 or one of its dependencies could
  14. python培训湖南
  15. POJ1007 DNA Sorting中英对照翻译与参考解答
  16. 【问题描述】建立一个通讯录的结构记录,包括姓名、生日、电话号码。输入n(n<10)个朋友的信息,再按他们的年龄从大到小的顺序依次输出其信息
  17. python设计石头剪刀布游戏_用python制作剪刀石头布游戏
  18. qutip+mayavi可视化波片对光偏振态的影响
  19. 广告roi怎么计算公式_ROI是什么意思,怎么计算的?
  20. 导入Excel表格数据(一)

热门文章

  1. linux scp 跨服务器,scp跨服务器拷贝,后台运行
  2. centos g++ 升级_今夏最潮装备来了!G-SHOCK推出seethru 冰韧系列
  3. 极光推送android 区分开发测试,给自己的项目做极光推送的步骤
  4. 虚拟的云服务器需要重启吗,虚拟主机重启服务器吗
  5. 计算机导论中的名词解释,计算机导论期末考试试题及答案
  6. android 判断文件是否存在_每日一课 | Python检查文件是否存在
  7. 深入理解javascript原型和闭包(17)——补this
  8. 维度爆炸?Python实现数据压缩竟如此简单!
  9. oracle查询等于外的,Oracle 查询、更新基本操作
  10. syslog源码_Gunicorn源码分析01--目录结构