uboot启动内核的实现

来源:互联网 发布:简单 三维建模软件 编辑:程序博客网 时间:2024/06/01 10:40
[cpp] view plaincopy
  1. cmd_tbl_t *find_cmd (const char *cmd)  
  2. {  
  3.     int len = &__u_boot_cmd_end - &__u_boot_cmd_start;  
  4.     return find_cmd_tbl(cmd, &__u_boot_cmd_start, len);  
  5. }  
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. cmd_tbl_t *find_cmd (const char *cmd)  
  2. {  
  3.     int len = &__u_boot_cmd_end - &__u_boot_cmd_start;  
  4.     return find_cmd_tbl(cmd, &__u_boot_cmd_start, len);  
  5. }  
//这里的两个参数__u_boot_cmd_end,__u_boot_cmd_start都是在u-boot.lds中定义的
//是uboot所有命令的结构体的一个列表的起始地址和结束地址。
[cpp] view plaincopy
  1. /*************************************************************************** 
  2.  * find command table entry for a command 
  3.  */  
  4. cmd_tbl_t *find_cmd_tbl (const char *cmd, cmd_tbl_t *table, int table_len)  
  5. {  
  6.     cmd_tbl_t *cmdtp;  
  7.     cmd_tbl_t *cmdtp_temp = table;  /*Init value */  
  8.     const char *p;  
  9.     int len;  
  10.     int n_found = 0;  
  11.   
  12.     /* 
  13.      * Some commands allow length modifiers (like "cp.b"); 
  14.      * compare command name only until first dot. 
  15.      */  
  16.     len = ((p = strchr(cmd, '.')) == NULL) ? strlen (cmd) : (p - cmd);  
  17.  //从首地址开始逐条往下查找,看能否找到相应的命令,如果找到就返回相应命令的结构体指针,找不到就返回NULL  
  18.     for (cmdtp = table;                  
  19.          cmdtp != table + table_len;  
  20.          cmdtp++) {  
  21.         if (strncmp (cmd, cmdtp->name, len) == 0) {  
  22.             if (len == strlen (cmdtp->name))  
  23.                 return cmdtp;   /* full match */  
  24.   
  25.             cmdtp_temp = cmdtp; /* abbreviated command ? */  
  26.             n_found++;  
  27.         }  
  28.     }  
  29.     if (n_found == 1) {         /* exactly one match */  
  30.         return cmdtp_temp;  
  31.     }  
  32.   
  33.     return NULL;    /* not found or ambiguous command */  
  34. }  
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. /*************************************************************************** 
  2.  * find command table entry for a command 
  3.  */  
  4. cmd_tbl_t *find_cmd_tbl (const char *cmd, cmd_tbl_t *table, int table_len)  
  5. {  
  6.     cmd_tbl_t *cmdtp;  
  7.     cmd_tbl_t *cmdtp_temp = table;  /*Init value */  
  8.     const char *p;  
  9.     int len;  
  10.     int n_found = 0;  
  11.   
  12.     /* 
  13.      * Some commands allow length modifiers (like "cp.b"); 
  14.      * compare command name only until first dot. 
  15.      */  
  16.     len = ((p = strchr(cmd, '.')) == NULL) ? strlen (cmd) : (p - cmd);  
  17.  //从首地址开始逐条往下查找,看能否找到相应的命令,如果找到就返回相应命令的结构体指针,找不到就返回NULL  
  18.     for (cmdtp = table;                  
  19.          cmdtp != table + table_len;  
  20.          cmdtp++) {  
  21.         if (strncmp (cmd, cmdtp->name, len) == 0) {  
  22.             if (len == strlen (cmdtp->name))  
  23.                 return cmdtp;   /* full match */  
  24.   
  25.             cmdtp_temp = cmdtp; /* abbreviated command ? */  
  26.             n_found++;  
  27.         }  
  28.     }  
  29.     if (n_found == 1) {         /* exactly one match */  
  30.         return cmdtp_temp;  
  31.     }  
  32.   
  33.     return NULL;    /* not found or ambiguous command */  
  34. }  
到了这里我们得到了命令的结构体指针,就可以与命令的处理函数来交互了。下面继续看run_command()
[cpp] view plaincopy
  1.         /* found - check max args */  
  2.         //检测最大参数个数   
  3.         if (argc > cmdtp->maxargs) {  
  4.             cmd_usage(cmdtp);  
  5.             rc = -1;  
  6.             continue;  
  7.         }  
  8.   
  9. #if defined(CONFIG_CMD_BOOTD)   
  10.         /* avoid "bootd" recursion */  
  11.         if (cmdtp->cmd == do_bootd) {  
  12. #ifdef DEBUG_PARSER   
  13.             printf ("[%s]\n", finaltoken);  
  14. #endif   
  15.             if (flag & CMD_FLAG_BOOTD) {  
  16.                 puts ("'bootd' recursion detected\n");  
  17.                 rc = -1;  
  18.                 continue;  
  19.             } else {  
  20.                 flag |= CMD_FLAG_BOOTD;  
  21.             }  
  22.         }  
  23. #endif   
  24.   
  25.         /* OK - call function to do the command */  
  26.         if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) {//执行命令处理函数  
  27.             rc = -1;  
  28.         }  
  29.   
  30.         repeatable &= cmdtp->repeatable;  
  31.   
  32.         /* Did the user stop this? */  
  33.         //处理用户输入的ctrl+c   
  34.         if (had_ctrlc ())  
  35.             return -1;  /* if stopped then not repeatable */  
  36.     }  
  37.   
  38.     return rc ? rc : repeatable;  
  39. }  
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1.         /* found - check max args */  
  2.         //检测最大参数个数  
  3.         if (argc > cmdtp->maxargs) {  
  4.             cmd_usage(cmdtp);  
  5.             rc = -1;  
  6.             continue;  
  7.         }  
  8.   
  9. #if defined(CONFIG_CMD_BOOTD)  
  10.         /* avoid "bootd" recursion */  
  11.         if (cmdtp->cmd == do_bootd) {  
  12. #ifdef DEBUG_PARSER  
  13.             printf ("[%s]\n", finaltoken);  
  14. #endif  
  15.             if (flag & CMD_FLAG_BOOTD) {  
  16.                 puts ("'bootd' recursion detected\n");  
  17.                 rc = -1;  
  18.                 continue;  
  19.             } else {  
  20.                 flag |= CMD_FLAG_BOOTD;  
  21.             }  
  22.         }  
  23. #endif  
  24.   
  25.         /* OK - call function to do the command */  
  26.         if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) {//执行命令处理函数  
  27.             rc = -1;  
  28.         }  
  29.   
  30.         repeatable &= cmdtp->repeatable;  
  31.   
  32.         /* Did the user stop this? */  
  33.         //处理用户输入的ctrl+c  
  34.         if (had_ctrlc ())  
  35.             return -1;  /* if stopped then not repeatable */  
  36.     }  
  37.   
  38.     return rc ? rc : repeatable;  
  39. }  
到了这里命令的处理流程就完成了。下面我们重点来说明一下,cmdtp是怎么定义的。

cmd_tbl_t *cmdtp;

[cpp] view plaincopy
  1. struct cmd_tbl_s {  
  2.     char        *name;      /* Command Name命令名称     */  
  3.     int     maxargs;    /* maximum number of arguments  最大参数个数*/  
  4.     int     repeatable; /* autorepeat allowed?  是否允许重复输入    */  
  5.                     /* Implementation function  */  
  6.     int     (*cmd)(struct cmd_tbl_s *, intintchar *[]);//命令处理函数  
  7.     char        *usage;     /* Usage message(short) 比较短的帮助信息*/  
  8. #ifdef  CONFIG_SYS_LONGHELP   
  9.     char        *help;      /* Help  message(long)比较长的帮助信息  */  
  10. #endif   
  11. #ifdef CONFIG_AUTO_COMPLETE   
  12.     /* do auto completion on the arguments */  
  13.     int     (*complete)(int argc, char *argv[], char last_char, int maxv, char *cmdv[]);  
  14. #endif   
  15. };  
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. struct cmd_tbl_s {  
  2.     char        *name;      /* Command Name命令名称     */  
  3.     int     maxargs;    /* maximum number of arguments  最大参数个数*/  
  4.     int     repeatable; /* autorepeat allowed?  是否允许重复输入    */  
  5.                     /* Implementation function  */  
  6.     int     (*cmd)(struct cmd_tbl_s *, intintchar *[]);//命令处理函数  
  7.     char        *usage;     /* Usage message(short) 比较短的帮助信息*/  
  8. #ifdef  CONFIG_SYS_LONGHELP  
  9.     char        *help;      /* Help  message(long)比较长的帮助信息  */  
  10. #endif  
  11. #ifdef CONFIG_AUTO_COMPLETE  
  12.     /* do auto completion on the arguments */  
  13.     int     (*complete)(int argc, char *argv[], char last_char, int maxv, char *cmdv[]);  
  14. #endif  
  15. };  
可以看出命令的结构体包含这些项中有一个是命令处理函数,这会命令跟函数关联的重点。那么每个命令的结构体是在哪定义的呢?这里涉及到一个宏U_BOOT_CMD(),这个宏就是定义一个这样的结构体然后,编译的时候,编译器会自动将这个结构体计入到命令列表里面去。我们以bootcmd为例子来屡一下整个过程

在我用的板子上有环境变量bootcmd=booti mmc3,也就是说,系统启动的时候要执行booti mmc3这条命令,那么booti的结构体的定义在\bootable\bootloader\uboot-imx\common\cmd_bootm.c

[cpp] view plaincopy
  1. U_BOOT_CMD(  
  2.     booti,  3,  1,  do_booti,  
  3.     "booti   - boot android bootimg from memory\n",  
  4.     "[<addr> | mmc0 | mmc1 | mmc2 | mmcX] [<partition>] \n    - boot application image stored in memory or mmc\n"  
  5.     "\t'addr' should be the address of boot image which is zImage+ramdisk.img\n"  
  6.     "\t'mmcX' is the mmc device you store your boot.img, which will read the boot.img from 1M offset('/boot' partition)\n"  
  7.     "\t 'partition' (optional) is the partition id of your device, if no partition give, will going to 'boot' partition\n"  
  8. );  
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. U_BOOT_CMD(  
  2.     booti,  3,  1,  do_booti,  
  3.     "booti   - boot android bootimg from memory\n",  
  4.     "[<addr> | mmc0 | mmc1 | mmc2 | mmcX] [<partition>] \n    - boot application image stored in memory or mmc\n"  
  5.     "\t'addr' should be the address of boot image which is zImage+ramdisk.img\n"  
  6.     "\t'mmcX' is the mmc device you store your boot.img, which will read the boot.img from 1M offset('/boot' partition)\n"  
  7.     "\t 'partition' (optional) is the partition id of your device, if no partition give, will going to 'boot' partition\n"  
  8. );  


可知booti的处理函数是do_booti
[cpp] view plaincopy
  1. /* booti <addr> [ mmc0 | mmc1 [ <partition> ] ] */  
  2. int do_booti(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  
  3. {  
  4.     unsigned addr = 0;  
  5.     char *ptn = "boot";  
  6.     int mmcc = -1;  
  7.     boot_img_hdr *hdr = (void *)boothdr;  
  8.   
  9.     if (argc < 2)   //至少有1个有效参数  
  10.         return -1;  
  11.   
  12.     if (!strncmp(argv[1], "mmc", 3))  
  13.         mmcc = simple_strtoul(argv[1]+3, NULL, 10); //得到启动的mmc名字  
  14.     else  
  15.         addr = simple_strtoul(argv[1], NULL, 16);  
  16.   
  17.     if (argc > 2)  
  18.         ptn = argv[2];  
  19.   
  20.     if (mmcc != -1) {  
  21. #ifdef CONFIG_MMC   
  22.         struct fastboot_ptentry *pte;  
  23.         struct mmc *mmc;  
  24.         disk_partition_t info;  
  25.         block_dev_desc_t *dev_desc = NULL;  
  26.         unsigned sector, partno = -1;  
  27.   
  28.         memset((void *)&info, 0 , sizeof(disk_partition_t));  
  29.         /* i.MX use MBR as partition table, so this will have 
  30.            to find the start block and length for the 
  31.            partition name and register the fastboot pte we 
  32.            define the partition number of each partition in 
  33.            config file 
  34.          */  
  35.         mmc = find_mmc_device(mmcc);    //查找启动的mmc设备  
  36.         if (!mmc) {  
  37.             printf("booti: cannot find '%d' mmc device\n", mmcc);  
  38.             goto fail;  
  39.         }  
  40.         dev_desc = get_dev("mmc", mmcc);//得到设备描述  
  41.         if (NULL == dev_desc) {  
  42.             printf("** Block device MMC %d not supported\n", mmcc);  
  43.             goto fail;  
  44.         }  
  45.   
  46.         /* below was i.MX mmc operation code */  
  47.         if (mmc_init(mmc)) {    //初始化mmc  
  48.             printf("mmc%d init failed\n", mmcc);  
  49.             goto fail;  
  50.         }  
  51.   
  52. #ifdef CONFIG_ANDROID_BOOT_PARTITION_MMC   
  53. #ifdef CONFIG_ANDROID_RECOVERY_PARTITION_MMC  
  54.         if (!strcmp(ptn, "boot"))  
  55.             partno = CONFIG_ANDROID_BOOT_PARTITION_MMC;  
  56.         if (!strcmp(ptn, "recovery"))  
  57.             partno = CONFIG_ANDROID_RECOVERY_PARTITION_MMC;  
  58.   
  59.         if (get_partition_info(dev_desc, partno, &info)) {  //获取mmc的分区信息  
  60.             printf("booti: device don't have such partition:%s\n", ptn);  
  61.             goto fail;  
  62.         }  
  63. #endif   
  64. #endif   
  65.   
  66. #ifdef CONFIG_FASTBOOT   
  67.         。。。。。。。。//没配置fastboot   
  68. #else   
  69. //    这里首先说明一下bootimage的构成   
  70.     /* 
  71. ** +-----------------+ 
  72. ** | boot header     | 1 page 
  73. ** +-----------------+ 
  74. ** | kernel          | n pages 
  75. ** +-----------------+ 
  76. ** | ramdisk         | m pages 
  77. ** +-----------------+ 
  78. ** | second stage    | o pages 
  79. ** +-----------------+ 
  80. ** 
  81. ** n = (kernel_size + page_size - 1) / page_size 
  82. ** m = (ramdisk_size + page_size - 1) / page_size 
  83. ** o = (second_size + page_size - 1) / page_size 
  84. ** 
  85. ** 0. all entities are page_size aligned in flash 
  86. ** 1. kernel and ramdisk are required (size != 0) 
  87. ** 2. second is optional (second_size == 0 -> no second) 
  88. ** 3. load each element (kernel, ramdisk, second) at 
  89. **    the specified physical address (kernel_addr, etc) 
  90. ** 4. prepare tags at tag_addr.  kernel_args[] is 
  91. **    appended to the kernel commandline in the tags. 
  92. ** 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr 
  93. ** 6. if second_size != 0: jump to second_addr 
  94. **    else: jump to kernel_addr 
  95. */  
  96.         if (mmc->block_dev.block_read(mmcc, info.start,//读取mmc的第一块数据,即boot header  
  97.                           1, (void *)hdr) < 0) {  
  98.             printf("booti: mmc failed to read bootimg header\n");  
  99.             goto fail;  
  100.         }  
  101.             /* flush cache after read */  
  102.             //这是个空函数   
  103.         flush_cache((ulong)hdr, 512); /* FIXME *///  
  104.   
  105.         if (memcmp(hdr->magic, BOOT_MAGIC, 8)) {//看是否是android  
  106.             printf("booti: bad boot image magic\n");  
  107.             goto fail;  
  108.         }  
  109.   
  110.         sector = info.start + (hdr->page_size / 512);//得到kernel的首地址  
  111. #endif   
  112.         if (mmc->block_dev.block_read(mmcc, sector, //读取kernel到内存中  
  113.                           (hdr->kernel_size / 512) + 1,  
  114.                           (void *)hdr->kernel_addr) < 0) {  
  115.             printf("booti: mmc failed to read kernel\n");  
  116.             goto fail;  
  117.         }  
  118.         /* flush cache after read */  
  119.         flush_cache((ulong)hdr->kernel_addr, hdr->kernel_size); /* FIXME */  
  120.         sector += ALIGN_SECTOR(hdr->kernel_size, hdr->page_size) / 512;得到ramdisk的首地址  
  121.         if (mmc->block_dev.block_read(mmcc, sector, //读取ramdisk到内存中  
  122.                           (hdr->ramdisk_size / 512) + 1,  
  123.                           (void *)hdr->ramdisk_addr) < 0) {  
  124.             printf("booti: mmc failed to read kernel\n");  
  125.             goto fail;  
  126.         }  
  127.         /* flush cache after read */  
  128.         flush_cache((ulong)hdr->ramdisk_addr, hdr->ramdisk_size); /* FIXME */  
  129. #else   
  130.         return -1;  
  131. #endif   
  132.     } else {  
  133.         //如果没有得到mmc设备,就从参数中得到bootimage的地址然后初始化hdr  
  134.         unsigned kaddr, raddr;  
  135.   
  136.         /* set this aside somewhere safe */  
  137.         memcpy(hdr, (void *) addr, sizeof(*hdr));  
  138.   
  139.         if (memcmp(hdr->magic, BOOT_MAGIC, 8)) {  
  140.             printf("booti: bad boot image magic\n");  
  141.             return 1;  
  142.         }  
  143.   
  144.         bootimg_print_image_hdr(hdr);  
  145.   
  146.         kaddr = addr + hdr->page_size;  
  147.         raddr = kaddr + ALIGN_SECTOR(hdr->kernel_size, hdr->page_size);  
  148.   
  149.         memmove((void *) hdr->kernel_addr, (void *)kaddr, hdr->kernel_size);  
  150.         memmove((void *) hdr->ramdisk_addr, (void *)raddr, hdr->ramdisk_size);  
  151.     }  
  152.   
  153.     printf("kernel   @ %08x (%d)\n", hdr->kernel_addr, hdr->kernel_size);  
  154.     printf("ramdisk  @ %08x (%d)\n", hdr->ramdisk_addr, hdr->ramdisk_size);  
  155.   
  156.     do_booti_linux(hdr);//启动内核   
  157.   
  158.     puts ("booti: Control returned to monitor - resetting...\n");  
  159.     do_reset (cmdtp, flag, argc, argv);  
  160.     return 1;  
  161.   
  162. fail:  
  163. #ifdef CONFIG_FASTBOOT   
  164.     return do_fastboot(NULL, 0, 0, NULL);  
  165. #else   
  166.     return -1;  
  167. #endif   
  168. }  
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. /* booti <addr> [ mmc0 | mmc1 [ <partition> ] ] */  
  2. int do_booti(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  
  3. {  
  4.     unsigned addr = 0;  
  5.     char *ptn = "boot";  
  6.     int mmcc = -1;  
  7.     boot_img_hdr *hdr = (void *)boothdr;  
  8.   
  9.     if (argc < 2)   //至少有1个有效参数  
  10.         return -1;  
  11.   
  12.     if (!strncmp(argv[1], "mmc", 3))  
  13.         mmcc = simple_strtoul(argv[1]+3, NULL, 10); //得到启动的mmc名字  
  14.     else  
  15.         addr = simple_strtoul(argv[1], NULL, 16);  
  16.   
  17.     if (argc > 2)  
  18.         ptn = argv[2];  
  19.   
  20.     if (mmcc != -1) {  
  21. #ifdef CONFIG_MMC  
  22.         struct fastboot_ptentry *pte;  
  23.         struct mmc *mmc;  
  24.         disk_partition_t info;  
  25.         block_dev_desc_t *dev_desc = NULL;  
  26.         unsigned sector, partno = -1;  
  27.   
  28.         memset((void *)&info, 0 , sizeof(disk_partition_t));  
  29.         /* i.MX use MBR as partition table, so this will have 
  30.            to find the start block and length for the 
  31.            partition name and register the fastboot pte we 
  32.            define the partition number of each partition in 
  33.            config file 
  34.          */  
  35.         mmc = find_mmc_device(mmcc);    //查找启动的mmc设备  
  36.         if (!mmc) {  
  37.             printf("booti: cannot find '%d' mmc device\n", mmcc);  
  38.             goto fail;  
  39.         }  
  40.         dev_desc = get_dev("mmc", mmcc);//得到设备描述  
  41.         if (NULL == dev_desc) {  
  42.             printf("** Block device MMC %d not supported\n", mmcc);  
  43.             goto fail;  
  44.         }  
  45.   
  46.         /* below was i.MX mmc operation code */  
  47.         if (mmc_init(mmc)) {    //初始化mmc  
  48.             printf("mmc%d init failed\n", mmcc);  
  49.             goto fail;  
  50.         }  
  51.   
  52. #ifdef CONFIG_ANDROID_BOOT_PARTITION_MMC  
  53. #ifdef CONFIG_ANDROID_RECOVERY_PARTITION_MMC  
  54.         if (!strcmp(ptn, "boot"))  
  55.             partno = CONFIG_ANDROID_BOOT_PARTITION_MMC;  
  56.         if (!strcmp(ptn, "recovery"))  
  57.             partno = CONFIG_ANDROID_RECOVERY_PARTITION_MMC;  
  58.   
  59.         if (get_partition_info(dev_desc, partno, &info)) {  //获取mmc的分区信息  
  60.             printf("booti: device don't have such partition:%s\n", ptn);  
  61.             goto fail;  
  62.         }  
  63. #endif  
  64. #endif  
  65.   
  66. #ifdef CONFIG_FASTBOOT  
  67.         。。。。。。。。//没配置fastboot  
  68. #else  
  69. //    这里首先说明一下bootimage的构成  
  70.     /* 
  71. ** +-----------------+ 
  72. ** | boot header     | 1 page 
  73. ** +-----------------+ 
  74. ** | kernel          | n pages 
  75. ** +-----------------+ 
  76. ** | ramdisk         | m pages 
  77. ** +-----------------+ 
  78. ** | second stage    | o pages 
  79. ** +-----------------+ 
  80. ** 
  81. ** n = (kernel_size + page_size - 1) / page_size 
  82. ** m = (ramdisk_size + page_size - 1) / page_size 
  83. ** o = (second_size + page_size - 1) / page_size 
  84. ** 
  85. ** 0. all entities are page_size aligned in flash 
  86. ** 1. kernel and ramdisk are required (size != 0) 
  87. ** 2. second is optional (second_size == 0 -> no second) 
  88. ** 3. load each element (kernel, ramdisk, second) at 
  89. **    the specified physical address (kernel_addr, etc) 
  90. ** 4. prepare tags at tag_addr.  kernel_args[] is 
  91. **    appended to the kernel commandline in the tags. 
  92. ** 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr 
  93. ** 6. if second_size != 0: jump to second_addr 
  94. **    else: jump to kernel_addr 
  95. */  
  96.         if (mmc->block_dev.block_read(mmcc, info.start,//读取mmc的第一块数据,即boot header  
  97.                           1, (void *)hdr) < 0) {  
  98.             printf("booti: mmc failed to read bootimg header\n");  
  99.             goto fail;  
  100.         }  
  101.             /* flush cache after read */  
  102.             //这是个空函数  
  103.         flush_cache((ulong)hdr, 512); /* FIXME *///  
  104.   
  105.         if (memcmp(hdr->magic, BOOT_MAGIC, 8)) {//看是否是android  
  106.             printf("booti: bad boot image magic\n");  
  107.             goto fail;  
  108.         }  
  109.   
  110.         sector = info.start + (hdr->page_size / 512);//得到kernel的首地址  
  111. #endif  
  112.         if (mmc->block_dev.block_read(mmcc, sector, //读取kernel到内存中  
  113.                           (hdr->kernel_size / 512) + 1,  
  114.                           (void *)hdr->kernel_addr) < 0) {  
  115.             printf("booti: mmc failed to read kernel\n");  
  116.             goto fail;  
  117.         }  
  118.         /* flush cache after read */  
  119.         flush_cache((ulong)hdr->kernel_addr, hdr->kernel_size); /* FIXME */  
  120.         sector += ALIGN_SECTOR(hdr->kernel_size, hdr->page_size) / 512;得到ramdisk的首地址  
  121.         if (mmc->block_dev.block_read(mmcc, sector, //读取ramdisk到内存中  
  122.                           (hdr->ramdisk_size / 512) + 1,  
  123.                           (void *)hdr->ramdisk_addr) < 0) {  
  124.             printf("booti: mmc failed to read kernel\n");  
  125.             goto fail;  
  126.         }  
  127.         /* flush cache after read */  
  128.         flush_cache((ulong)hdr->ramdisk_addr, hdr->ramdisk_size); /* FIXME */  
  129. #else  
  130.         return -1;  
  131. #endif  
  132.     } else {  
  133.         //如果没有得到mmc设备,就从参数中得到bootimage的地址然后初始化hdr  
  134.         unsigned kaddr, raddr;  
  135.   
  136.         /* set this aside somewhere safe */  
  137.         memcpy(hdr, (void *) addr, sizeof(*hdr));  
  138.   
  139.         if (memcmp(hdr->magic, BOOT_MAGIC, 8)) {  
  140.             printf("booti: bad boot image magic\n");  
  141.             return 1;  
  142.         }  
  143.   
  144.         bootimg_print_image_hdr(hdr);  
  145.   
  146.         kaddr = addr + hdr->page_size;  
  147.         raddr = kaddr + ALIGN_SECTOR(hdr->kernel_size, hdr->page_size);  
  148.   
  149.         memmove((void *) hdr->kernel_addr, (void *)kaddr, hdr->kernel_size);  
  150.         memmove((void *) hdr->ramdisk_addr, (void *)raddr, hdr->ramdisk_size);  
  151.     }  
  152.   
  153.     printf("kernel   @ %08x (%d)\n", hdr->kernel_addr, hdr->kernel_size);  
  154.     printf("ramdisk  @ %08x (%d)\n", hdr->ramdisk_addr, hdr->ramdisk_size);  
  155.   
  156.     do_booti_linux(hdr);//启动内核  
  157.   
  158.     puts ("booti: Control returned to monitor - resetting...\n");  
  159.     do_reset (cmdtp, flag, argc, argv);  
  160.     return 1;  
  161.   
  162. fail:  
  163. #ifdef CONFIG_FASTBOOT  
  164.     return do_fastboot(NULL, 0, 0, NULL);  
  165. #else  
  166.     return -1;  
  167. #endif  
  168. }  
这个函数主要就是把boot.img文件按照格式读取到hdr结构体中传递给do_booti_linux(hdr);进而进一步启动内核我们想继续看do_booti_linux()
[cpp] view plaincopy
  1. void do_booti_linux (boot_img_hdr *hdr)  
  2. {  
  3.     ulong initrd_start, initrd_end;  
  4.     void (*theKernel)(int zero, int arch, uint params);  
  5.     bd_t *bd = gd->bd;  
  6. #ifdef CONFIG_CMDLINE_TAG   
  7.     char *commandline = getenv("bootargs");//读取环境变量中的bootargs  
  8.   
  9.     /* If no bootargs env, just use hdr command line */  
  10.     if (!commandline)  
  11.         commandline = (char *)hdr->cmdline;  
  12.   
  13.     /* XXX: in production, you should always use boot.img 's cmdline !!! */  
  14.   
  15.     printf("kernel cmdline: \n\tuse %s command line:\n\t%s \n",  
  16.            getenv("bootargs") ? "uboot" : "boot.img",  
  17.            commandline);  
  18. #endif   
  19.   
  20.     theKernel = (void (*)(intint, uint))(hdr->kernel_addr);//得到内存中kernel的main函数指针  
  21.   
  22.     initrd_start = hdr->ramdisk_addr;  
  23.     initrd_end = initrd_start + hdr->ramdisk_size;  
  24.   
  25. #if defined (CONFIG_SETUP_MEMORY_TAGS)  
  26.     setup_start_tag(bd);  
  27. #ifdef CONFIG_SERIAL_TAG   
  28.     setup_serial_tag (¶ms);  
  29. #endif   
  30. #ifdef CONFIG_REVISION_TAG   
  31.     setup_revision_tag (¶ms);  
  32. #endif   
  33. #ifdef CONFIG_SETUP_MEMORY_TAGS   
  34.     setup_memory_tags (bd);  
  35. #endif   
  36. #ifdef CONFIG_CMDLINE_TAG   
  37.     setup_commandline_tag (bd, commandline);//将命令行参数加入到bd中  
  38. #endif   
  39. #ifdef CONFIG_INITRD_TAG   
  40.     if (hdr->ramdisk_size)  
  41.         setup_initrd_tag (bd, initrd_start, initrd_end);  
  42. #endif   
  43. #if defined (CONFIG_VFD) || defined (CONFIG_LCD)  
  44.     setup_videolfb_tag ((gd_t *) gd);  
  45. #endif   
  46.     setup_end_tag (bd);  
  47. #endif   
  48.   
  49.     /* we assume that the kernel is in place */  
  50.     printf ("\nStarting kernel ...\n\n");  
  51.   
  52. #ifdef CONFIG_USB_DEVICE   
  53.     {  
  54.         extern void udc_disconnect (void);  
  55.         udc_disconnect ();  
  56.     }  
  57. #endif   
  58.   
  59.     cleanup_before_linux ();  
  60.   
  61.     theKernel (0, bd->bi_arch_number, bd->bi_boot_params);//直接传递参数启动kernel  
  62. }  
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. void do_booti_linux (boot_img_hdr *hdr)  
  2. {  
  3.     ulong initrd_start, initrd_end;  
  4.     void (*theKernel)(int zero, int arch, uint params);  
  5.     bd_t *bd = gd->bd;  
  6. #ifdef CONFIG_CMDLINE_TAG  
  7.     char *commandline = getenv("bootargs");//读取环境变量中的bootargs  
  8.   
  9.     /* If no bootargs env, just use hdr command line */  
  10.     if (!commandline)  
  11.         commandline = (char *)hdr->cmdline;  
  12.   
  13.     /* XXX: in production, you should always use boot.img 's cmdline !!! */  
  14.   
  15.     printf("kernel cmdline: \n\tuse %s command line:\n\t%s \n",  
  16.            getenv("bootargs") ? "uboot" : "boot.img",  
  17.            commandline);  
  18. #endif  
  19.   
  20.     theKernel = (void (*)(intint, uint))(hdr->kernel_addr);//得到内存中kernel的main函数指针  
  21.   
  22.     initrd_start = hdr->ramdisk_addr;  
  23.     initrd_end = initrd_start + hdr->ramdisk_size;  
  24.   
  25. #if defined (CONFIG_SETUP_MEMORY_TAGS)  
  26.     setup_start_tag(bd);  
  27. #ifdef CONFIG_SERIAL_TAG  
  28.     setup_serial_tag (¶ms);  
  29. #endif  
  30. #ifdef CONFIG_REVISION_TAG  
  31.     setup_revision_tag (¶ms);  
  32. #endif  
  33. #ifdef CONFIG_SETUP_MEMORY_TAGS  
  34.     setup_memory_tags (bd);  
  35. #endif  
  36. #ifdef CONFIG_CMDLINE_TAG  
  37.     setup_commandline_tag (bd, commandline);//将命令行参数加入到bd中  
  38. #endif  
  39. #ifdef CONFIG_INITRD_TAG  
  40.     if (hdr->ramdisk_size)  
  41.         setup_initrd_tag (bd, initrd_start, initrd_end);  
  42. #endif  
  43. #if defined (CONFIG_VFD) || defined (CONFIG_LCD)  
  44.     setup_videolfb_tag ((gd_t *) gd);  
  45. #endif  
  46.     setup_end_tag (bd);  
  47. #endif  
  48.   
  49.     /* we assume that the kernel is in place */  
  50.     printf ("\nStarting kernel ...\n\n");  
  51.   
  52. #ifdef CONFIG_USB_DEVICE  
  53.     {  
  54.         extern void udc_disconnect (void);  
  55.         udc_disconnect ();  
  56.     }  
  57. #endif  
  58.   
  59.     cleanup_before_linux ();  
  60.   
  61.     theKernel (0, bd->bi_arch_number, bd->bi_boot_params);//直接传递参数启动kernel  
  62. }  
到了这里uboot就已经驱动了kernel。整个过程比较简单,关键是uboot命令实现过程很重要,在自己移植uboot时候很有肯恩更要修改这些代码。需要进一步掌握
0 0
原创粉丝点击