• 如何将镜像烧写至iNand(fastboot命令的源码分析)


    以下内容源于网络资源的学习与整理,如有侵权请告知删除。

    参考博客

    u-boot sdfuse命令烧录分析----从SD卡加载内核_white_bugs的博客-CSDN博客

    一、如何将镜像文件烧写至iNand

    步骤1:完成准备工作。

    (1)准备fastboot相关软件包。

    (2)用usb转otg数据线连接电脑和开发板。

    (3)正确安装fastboot的驱动。

    在uboot控制台输入fastboot后,如果尚未安装驱动,在windows端的设备管理器相应项目下会显示问号(或感叹号),此时选中该项目,右键选择属性,选择更新驱动程序,然后选择驱动包所在的路径,勾选“包括子文件夹”,点击下一项即可。

    上述操作可能存在数字签名问题,解决方法见win10禁止数字签名

    正确安装fastboot驱动之后显示的内容如下:

    (4)准备好待烧录的镜像文件。

    X210开发板光盘资料中有Linux镜像文件和Android镜像文件。

    这里假定要烧录Linux镜像文件,包括linux内核镜像文件、QT4.8文件系统镜像、uboot镜像,它们位于开发板资料X210V3S_B\linux\QT4.8目录中,账号与密码分别是root、123456。

    为了操作方便,这里将镜像文件和fastboot软件包的内容放在同一目录。

    步骤2:在uboot控制台下输入命令fastboot。

    步骤3:开始烧写uboot、内核以及根文件系统镜像。

    (1)在window命令窗口中切换到fastboot软件包所在的路径。

    (2)输入“fastboot devices”查看是否有设备,没有不能进行下一步内容。

    (3)利用“fastboot flash inand的分区名 镜像文件路径”命令烧写各个镜像文件。

    【1】烧录uboot镜像文件

    在windows端输入“fastboot flash bootloader uboot.bin”时,windows控制台与uboot控制台显示内容如下。

    1. C:\Users\34316\Desktop\fastboot>fastboot flash bootloader uboot.bin
    2. sending 'bootloader' (384 KB)... OKAY
    3. writing 'bootloader'... OKAY
    1. Received 17 bytes: download:00060000
    2. Starting download of 393216 bytes
    3. downloading of 393216 bytes finished
    4. Received 16 bytes: flash:bootloader
    5. flashing 'bootloader'
    6. Writing BL1 to sector 1 (16 sectors).. checksum : 0xed75e
    7. writing bootloader.. 49, 1024
    8. MMC write: dev # 0, block # 49, count 1024 ... 1024 blocks written: OK
    9. completed
    10. partition 'bootloader' flashed

    【2】对iNand进行重新分区

    在烧写完uboot之后一般要重启,此时开发板会运行刚才烧写的uboot,然后在uboot控制台输入“fdisk -c 0”对iNand进行分区。

    对iNand重新分区的原因,是之前的uboot(博文uboot的初体验中提到的九鼎的uboot)对inand的system分区只有120左右MB,放不下本次提供的200多MB的根文件系统镜像,如果继续用之前的uboot规划的分区,烧写根文件系统时会提示文件太大放不能进分区。如下所示:

    1. C:\Users\34316\Desktop\fastboot>fastboot flash system rootfs_qt4.ext3
    2. sending 'system' (262144 KB)... OKAY
    3. writing 'system'... FAILED (remote: image too large for partition)
    4. C:\Users\34316\Desktop\fastboot>

    我们在【1】中烧录的uboot.bin已经重新设置了分区信息,烧录并运行它之后,执行“fdisk -c 0”就可以对inand重新分区。

    之前的uboot对inand的分区情况如下:

    1. x210 # fdisk -p 0 //查看编号为0的设备(即iNand)的分区情况
    2. partion # size(MB) block start # block count partition_Id
    3. 1 258 22374 529518 0x83
    4. 2 120 551892 246114 0x83
    5. 3 101 798006 208824 0x83
    6. 4 3222 1006830 6600330 0x83
    7. x210 #

    新的uboot对inand的分区情况如下:

    1. x210 # fdisk -p 0
    2. partion # size(MB) block start # block count partition_Id
    3. 1 258 22374 529518 0x83
    4. 2 258 551892 529518 0x83
    5. 3 101 1081410 208824 0x83
    6. 4 3084 1290234 6316926 0x83
    7. x210 #

    对比可知,重新分区后inand的分区2变为了258MB。

    注意,开发板光盘资料中的Linux镜像文件和Android镜像文件,它们的uboot对inand的system分区都是258MB。只有之前的uboot(博文uboot的初体验中提到的九鼎的uboot)对inand的system分区是120左右 MB。

    【3】烧录内核镜像文件

    重新分区之后,在uboot控制台输入fastboot命令,然后在windows控制台输入“fastboot flash kernel zImage-qt ”。此时windows控制台与uboot控制台显示的内容如下:

    1. C:\Users\34316\Desktop\fastboot>fastboot flash kernel zImage-qt
    2. sending 'kernel' (3566 KB)... OKAY
    3. writing 'kernel'... OKAY
    1. Received 17 bytes: download:0037b800
    2. Starting download of 3651584 bytes
    3. ...
    4. downloading of 3651584 bytes finished
    5. Received 12 bytes: flash:kernel
    6. flashing 'kernel'
    7. writing kernel.. 1073, 8192
    8. MMC write: dev # 0, block # 1073, count 8192 ... 8192 blocks written: OK
    9. completed
    10. partition 'kernel' flashed

    【4】烧录根文件系统镜像文件

    在windows控制台输入“fastboot flash system rootfs_qt4.ext3 ”,windows控制台与uboot控制台显示的内容如下:

    1. C:\Users\34316\Desktop\fastboot>fastboot flash system rootfs_qt4.ext3
    2. sending 'system' (262144 KB)... OKAY
    3. writing 'system'... OKAY
    1. Received 17 bytes: download:10000000
    2. Starting download of 268435456 bytes
    3. ................................................................................
    4. ................................................................................
    5. ................................................................................
    6. ...............
    7. downloading of 268435456 bytes finished
    8. Received 12 bytes: flash:system
    9. flashing 'system'
    10. MMC write: dev # 0, block # 551892, count 529518 ... 529518 blocks written: OK
    11. partition 'system' flashed

    二、fastboot命令的源码分析

    接下来将分析fastboot命令在uboot端的源码。

    我们在uboot(分区信息尚未修改的uboot)控制台输入fastboot时显示下面信息:

    1. x210 # fastboot
    2. [Partition table on MoviNAND]
    3. ptn 0 name='bootloader' start=0x0 len=N/A (use hard-coded info. (cmd: movi))
    4. ptn 1 name='kernel' start=N/A len=N/A (use hard-coded info. (cmd: movi))
    5. ptn 2 name='ramdisk' start=N/A len=0x300000(~3072KB) (use hard-coded info. (cmd: movi))
    6. ptn 3 name='config' start=0xAECC00 len=0x1028DC00(~264759KB)
    7. ptn 4 name='system' start=0x10D7A800 len=0x782C400(~123057KB)
    8. ptn 5 name='cache' start=0x185A6C00 len=0x65F7000(~104412KB)
    9. ptn 6 name='userdata' start=0x1EB9DC00 len=0xC96D1400(~3300165KB)
    10. Insert a OTG cable into the connector!

    在修改分区信息之后的uboot控制台输入fastboot时显示下面信息(可见从system开始就不同):

    1. x210 # fastboot
    2. [Partition table on MoviNAND]
    3. ptn 0 name='bootloader' start=0x0 len=N/A (use hard-coded info. (cmd: movi))
    4. ptn 1 name='kernel' start=N/A len=N/A (use hard-coded info. (cmd: movi))
    5. ptn 2 name='ramdisk' start=N/A len=0x300000(~3072KB) (use hard-coded info. (cmd: movi))
    6. ptn 3 name='config' start=0xAECC00 len=0x1028DC00(~264759KB)
    7. ptn 4 name='system' start=0x10D7A800 len=0x1028DC00(~264759KB)
    8. ptn 5 name='cache' start=0x21008400 len=0x65F7000(~104412KB)
    9. ptn 6 name='userdata' start=0x275FF400 len=0xC0C6FC00(~3158463KB)

    可见这里有bootloader、kernel、…、userdata等标签,似乎是分区标志,但它们不是真正意义上的分区(因为没有写进主引导扇区中),它们只是用来表征iNand中某段存储空间的字符串,或者说用来表征iNand中某个(以扇区为单位的)偏移地址的字符串(这两种说法意思一样,前者指整段空间,后者指整段空间的开头)。

    比如在uboot下使用movi命令(例如bootcmd这个环境变量,movi read kernel xxx,将iNand中的内核镜像读取到内存的xxx地址),或者使用“fastboot flash kernel 内核镜像文件”将镜像文件烧写到iNand中的kernel分区时,参数“kernel”只是一个(表征iNand中某个扇区地址的)字符串。

    这些标签分别对应着iNand中哪些扇区地址?为什么给出一个kernel参数,就知道它对应着iNand中哪个扇区地址呢?下面将进行这方面的分析。

    1、set_partition_table函数

    我们知道,uboot执行fastboot命令时,会调用do_fastboot函数。通览do_fastboot函数,其中与分区有关的是set_partition_table函数。该函数定义在/common/cmd_fastboot.c文件中。

    删除条件编译等内容,该函数内容如下:

    1. static int set_partition_table()
    2. //删除一些条件编译的代码
    3. #elif defined(CFG_FASTBOOT_SDMMCBSP)
    4. {
    5. int start, count;
    6. unsigned char pid;
    7. pcount = 0;
    8. #if defined(CONFIG_FUSED) //没有定义这个宏
    9. /* FW BL1 for fused chip */
    10. strcpy(ptable[pcount].name, "fwbl1");
    11. ptable[pcount].start = 0;
    12. ptable[pcount].length = 0;
    13. ptable[pcount].flags = FASTBOOT_PTENTRY_FLAGS_USE_MOVI_CMD;
    14. pcount++;
    15. #endif
    16. /* Bootloader */
    17. strcpy(ptable[pcount].name, "bootloader");
    18. ptable[pcount].start = 0;
    19. ptable[pcount].length = 0;
    20. ptable[pcount].flags = FASTBOOT_PTENTRY_FLAGS_USE_MOVI_CMD;
    21. pcount++;
    22. /* Kernel */
    23. strcpy(ptable[pcount].name, "kernel");
    24. ptable[pcount].start = 0;
    25. ptable[pcount].length = 0;
    26. ptable[pcount].flags = FASTBOOT_PTENTRY_FLAGS_USE_MOVI_CMD;
    27. pcount++;
    28. /* Ramdisk */
    29. strcpy(ptable[pcount].name, "ramdisk");
    30. ptable[pcount].start = 0;
    31. ptable[pcount].length = 0x300000;
    32. ptable[pcount].flags = FASTBOOT_PTENTRY_FLAGS_USE_MOVI_CMD;
    33. pcount++;
    34. /* Config */
    35. get_mmc_part_info("0", 1, &start, &count, &pid);
    36. if (pid != 0x83)
    37. goto part_type_error;
    38. strcpy(ptable[pcount].name, "config");
    39. ptable[pcount].start = start * CFG_FASTBOOT_SDMMC_BLOCKSIZE;
    40. ptable[pcount].length = count * CFG_FASTBOOT_SDMMC_BLOCKSIZE;
    41. ptable[pcount].flags = FASTBOOT_PTENTRY_FLAGS_USE_MMC_CMD;
    42. pcount++;
    43. /* System */
    44. get_mmc_part_info("0", 2, &start, &count, &pid);
    45. if (pid != 0x83)
    46. goto part_type_error;
    47. strcpy(ptable[pcount].name, "system");
    48. ptable[pcount].start = start * CFG_FASTBOOT_SDMMC_BLOCKSIZE;
    49. ptable[pcount].length = count * CFG_FASTBOOT_SDMMC_BLOCKSIZE;
    50. ptable[pcount].flags = FASTBOOT_PTENTRY_FLAGS_USE_MMC_CMD;
    51. pcount++;
    52. /* Cache */
    53. get_mmc_part_info("0", 3, &start, &count, &pid);
    54. if (pid != 0x83)
    55. goto part_type_error;
    56. strcpy(ptable[pcount].name, "cache");
    57. ptable[pcount].start = start * CFG_FASTBOOT_SDMMC_BLOCKSIZE;
    58. ptable[pcount].length = count * CFG_FASTBOOT_SDMMC_BLOCKSIZE;
    59. ptable[pcount].flags = FASTBOOT_PTENTRY_FLAGS_USE_MMC_CMD;
    60. pcount++;
    61. /* Data */
    62. get_mmc_part_info("0", 4, &start, &count, &pid);
    63. if (pid != 0x83)
    64. goto part_type_error;
    65. strcpy(ptable[pcount].name, "userdata");
    66. ptable[pcount].start = start * CFG_FASTBOOT_SDMMC_BLOCKSIZE;
    67. ptable[pcount].length = count * CFG_FASTBOOT_SDMMC_BLOCKSIZE;
    68. ptable[pcount].flags = FASTBOOT_PTENTRY_FLAGS_USE_MMC_CMD;
    69. pcount++;
    70. #if 1 // Debug
    71. fastboot_flash_dump_ptn();
    72. #endif
    73. //省略部分代码
    74. }

    由此可知,这个函数只设置了config、system、cache、userdata这些标签所对应的空间(起始扇区、扇区数目、标志),没有对bootloader、kernel、ramdisk这些标签进行设置。

    如何设置的呢?以config标签为例说明设置过程。

    首先,代码“get_mmc_part_info("0", 1, &start, &count, &pid);”,其第一个参数0表示存储设备的编号为0,也就是iNand;第二个参数1表示这个存储设备的分区1(下面2,3,4是分区2,3,4);第三第四第五个参数前面的&,表示它们是输出型参数,其中start表示分区1的以扇区为单位的起始地址,count表示分区1有多少个扇区。这个函数返回时,start=22374,count=529518。

    然后,将分区1的(以扇区为单位的)起始地址转换成以字节为单位的起始地址,将分区1的扇区总数转换成以字节为单位的空间大小。这里的CFG_FASTBOOT_SDMMC_BLOCKSIZE值为512,因为一个扇区大小是512字节。

    因为22374*512=11455488(10)= AECC00(16),529518*512=1028DC00(16),因此config标签对应的空间信息为:start=AECC00,length=1028DC00。

    这与执行fastboot命令时显示的数据是一样的(执行fastboot命令时之所以会显示信息,是因为函数do_fastboot中间接调用了fastboot_flash_dump_ptn函数,该函数用来打印这些信息)。

    同理可以得到其他标签对应的空间的信息,这里不赘述。

    注意,config标签所对应的空间与分区1是一致的,因为本来就是先调用get_mmc_part_info函数来获取分区1的数据,然后用这些数据来填充(congfig标签所对应的空间的数据结构)ptable[0]。

    同理system标签所对应的空间与分区2的空间是一致的。我们知道,system标签所对应的空间是用来烧录根文件系统的(“fastboot flash system rootfs_qt4.ext3 ”),也就是说根文件系统将来存储在system标签所对应的空间,由于这个空间与分区2的空间一致,所以可以说根文件系系统位于分区2,因此uboot给kernel传参时,bootargs里面有一个项目“root=mmcblk0p2 rw”,表示的就是根文件系统在设备0的第2分区。

    同理cache、userdata标签所对应的空间与分区3、分区4一致。

    因此,fastboot命令体系下的“分区表”如下。

    分区号分区名称
    ptable[0]bootloader(暂无对应)
    ptable[1]kernel(暂无对应)
    ptable[2]ramdisk(暂无对应)
    ptable[3]config(对应着分区1)
    ptable[4]system(对应着分区2)
    ptable[5]cache(对应着分区3)
    ptable[6]userdata(对应着分区4)

    上面写到,set_partition_table函数只是设置了config、system、cache、userdata这些标签对应的空间,没有对bootloader、kernel、ramdisk这些标签进行设置(只是简单地设置为0)。

    我们利用fastboot flash来烧录镜像时,使用bootloader,kernel,system这三个标签指代iNand中某些地址。其中system标签对应的空间是分区2,那bootLoader、kernel标签对应什么空间呢?

    注意到执行fastboot时,关于bootloader、kernel、ramdisk标签,显示的内容中有“(use hard-coded info. (cmd: movi))”,这说明这三个标签可能以硬编码方式写在了movi命令对应的函数中。比如bootcmd这个环境变量的值是“movi read kernel 30008000; bootm 30008000”,将iNand中的内核镜像读取到内存的30008000地址时,就使用了“kernel”这个标签。

    因此我们对do_movi函数进行分析(见博文do_movi函数的源码分析),发现该命令体系下也有一个“分区表”(像fastboot命令一样,这分区表也没有写入主引导区),叫做raw分区表,分区表里有u-boot、kerne、rfs等分区,这些分区都有实实在在的范围,而不像fastboot命令体系下bootLoader、kernel、ramdisk分区那样没有实实在在的范围(简单地设置为0而已)。

    fastboot命令体系下的kernel分区,兴许对应着movi命令体系下的kernel分区,因为两者都是用字符串“kernel”表示。fastboot命令体系下的bootloader分区,与movi命令体系下的u-boot分区,两者的名字不同但意义一样,会不会也是对应关系呢?如果是,执行“fastboot flash bootloader uboo.bin”时,bootloader这个标签是如何转为u-boot的?

    另外经过思考,既然使用“movi write u-boot xxx”时,表示将内存地址xxx处的内容写进(也就是烧录)到iNand的u-boot分区,使用“fastboot flash bootloader uboo.bin”时表示将uboot的镜像文件写进bootloader分区,两者操作本质一样,那fastboot flash在uboot端应该也采用movi命令。

    选择几个执行“fastboot flash bootloader uboo.bin”时在uboot中显示的内容的关键词,定位到位于/common/cmd_fastboot.c文件中的rx_handler函数。

    该函数的部分内容如下:

    1. static int rx_handler (const unsigned char *buffer, unsigned int buffer_size)
    2. {
    3. //省略部分代码
    4. /* flashFlash what was downloaded */
    5. if (memcmp(cmdbuf, "flash:", 6) == 0)
    6. {
    7. //省略部分代码
    8. struct fastboot_ptentry *ptn;
    9. ptn = fastboot_flash_find_ptn(cmdbuf + 6);
    10. //省略部分代码
    11. /* Normal case */
    12. if (write_to_ptn(ptn, (unsigned int)interface.transfer_buffer, download_bytes))
    13. {
    14. printf("flashing '%s' failed\n", ptn->name);
    15. sprintf(response, "FAILfailed to flash partition");
    16. }
    17. else
    18. {
    19. printf("partition '%s' flashed\n", ptn->name);
    20. sprintf(response, "OKAY");
    21. }
    22. }
    23. }

    其中的write_to_ptn函数内容与分析如下:

    1. /*
    2. 该函数功能是将镜像写进fastboot命令体系下的分区。
    3. 以执行“fastboot flash bootloader uboot.bin”为例进行说明。
    4. 以执行“fastboot flash system rootfs_qt4.ext3”为例进行说明。
    5. 以执行“fastboot flash kernel zImage-qt”为例进行说明。
    6. */
    7. //fastboot命令体系下的某个分区名,储存着待烧录数据的某个内存地址,待烧写的数据长度
    8. static int write_to_ptn(struct fastboot_ptentry *ptn, unsigned int addr, unsigned int size)
    9. {
    10. int ret = 1;
    11. char device[32], part[32];
    12. char start[32], length[32], buffer[32];
    13. char *argv[6] = { NULL, "write", NULL, NULL, NULL, NULL, };
    14. /* 此时argv[1]="write"。
    15. 根据下面的分析,write_to_ptn函数调用do_movi函数或者do_mmcops来完成烧写。
    16. 填充这个字符指针数组,其实是在构造“movi write u-boot xxxxx”或者“mmc write system …”字符串。
    17. */
    18. int argc = 0;
    19. if ((ptn->length != 0) && (size > ptn->length))
    20. {//对于bootloader(kernel),因为bootloader(kernel)的ptn->length=0,所以不会执行。
    21. //如果要烧写的根文件系统镜像小于system分区,则不会执行;如果大于该分区,则会报错返回。
    22. printf("Error: Image size is larger than partition size!\n");
    23. return 1;
    24. }
    25. printf("flashing '%s'\n", ptn->name);// 打印信息“ flashing 'bootloader'”或者“ flashing 'system' ”。
    26. if (ptn->flags & FASTBOOT_PTENTRY_FLAGS_USE_MMC_CMD)//(注意这里是_MMC_)表示在烧写system分区
    27. {
    28. argv[2] = device;//argv[0]=NULL,argv[1]="write"
    29. argv[3] = buffer;
    30. argv[4] = start;
    31. argv[5] = length;
    32. sprintf(device, "mmc %d", 1); //argv[2]="mmc 1"
    33. sprintf(buffer, "0x%x", addr);//argv[3]="0x内存地址",表示储存着待烧录数据的某个内存地址
    34. sprintf(start, "0x%x", (ptn->start / CFG_FASTBOOT_SDMMC_BLOCKSIZE)); //argv[4]="0x分区起始扇区"(system分区起始扇区号)
    35. sprintf(length, "0x%x", (ptn->length / CFG_FASTBOOT_SDMMC_BLOCKSIZE));//argv[5]="0x分区扇区总数"(system分区扇区的总数)
    36. ret = do_mmcops(NULL, 0, 6, argv);//烧录system,即文件系统。可以分析下其内部代码。
    37. /*
    38. argv[0]=NULL
    39. argv[1]="write"
    40. argv[2]="mmc 1"
    41. argv[3]="0x内存地址"
    42. argv[4]="0x分区起始扇区"
    43. argv[5]="0x分区扇区总数"
    44. */
    45. }
    46. else if (ptn->flags & FASTBOOT_PTENTRY_FLAGS_USE_MOVI_CMD)//(注意这里是_MOVI_)表示是在烧写bootloader,或者kernel
    47. {
    48. argv[2] = part;//argv[0]=NULL,argv[1]="write"
    49. argv[3] = buffer;
    50. argc = 4;//argc = 4
    51. /* use the partition name that can be understood by a command, movi */
    52. if (!strcmp(ptn->name, "bootloader"))//简单理解为,给bootloader换个别名
    53. {
    54. strncpy(part, "u-boot", 7);//将fastboot的分区“bootloader”转换成movi中的分区“u-boot”,这里argv[2]="u-boot"
    55. }
    56. else if (!strcmp(ptn->name, "ramdisk"))//没涉及到这个,略过
    57. {
    58. strncpy(part, "rootfs", 7);
    59. argv[4] = length;
    60. sprintf(length, "0x%x", ((size + CFG_FASTBOOT_SDMMC_BLOCKSIZE - 1)/CFG_FASTBOOT_SDMMC_BLOCKSIZE ) * CFG_FASTBOOT_SDMMC_BLOCKSIZE);
    61. argc++;//argc = 5
    62. }
    63. /* kernel, fwbl1 */ //这里表示在烧写kernel
    64. else
    65. {
    66. argv[2] = ptn->name;//因为kernel在fastboot中的分区名和在movi中的分区名一致,所以直接赋值
    67. }
    68. sprintf(buffer, "0x%x", addr);//argv[3]="0x内存地址"(表示储存着待烧录数据的某个内存地址)
    69. ret = do_movi(NULL, 0, argc, argv);
    70. /* argc=4,
    71. argv[0]=NULL
    72. argv[1]="write"
    73. argv[2]="u-boot"
    74. argv[3]="0x内存地址"
    75. argv[4]="0x数据长度"//当烧录uboot时,这个为NULL
    76. argv[5]=NULL
    77. */
    78. /* the return value of do_movi is different from usual commands. Hence the followings. */
    79. ret = 1 - ret;
    80. }
    81. return ret;
    82. }

    由此可知:

    (1)我们使用“fastboot flash system rootfs_qt4.ext3”,将文件系统镜像文件rootfs_qt4.ext3烧写至iNand的system分区时,最后其实是通过write_to_ptn函数调用do_mmcops(NULL, 0, 6, argv)函数来实现的。

    (2)我们使用“fastboot flash kernel zImage-qt”,将内核镜像文件zImage-qt烧写至iNand的kernel分区时,最后其实是通过write_to_ptn函数调用do_movi(NULL,0,argc,argv)函数来实现的。

    (3)我们使用“fastboot flash bootloader uboot.bin”,将uboot镜像文件uboot.bin烧写至iNand的bootloader分区时,最后其实是通过write_to_ptn函数调用do_movi(NULL,0,argc,argv)函数来实现的。由于fastboot命令中的bootloader分区,在movi命令中叫做“u-boot”分区,为了让movi命令能识别,因此需要将“bootloader”改为“u-boot”。正如注释所说:/* use the partition name that can be understood by a command, movi */

    关于do_movi函数源码的解释,见movi命令(do_movi函数的源码分析)

    这里简单说明一下do_movi函数的内部流程。首先根据传参argv,来判断是读or写iNand(这里是写),判断写什么内容(kernel?uboot?rootfs?)。如果是写,则先合成run_cmd这个字符数组的内容,然后调用run_command(run_cmd, 0)函数来执行run_cmd这个字符数组内容所对应的指令。

    run_cmd这个字符数组的内容一般是“mmc write 0 内存地址addr 开始扇区startblk 扇区长度blklen”(表示从内存addr中读取数据到iNand中的第startblk扇区,读取长度是blklen)。

    可知do_movi函数需要执行mmc命令,而mmc命令又对应着函数do_mmcops,另外system分区的烧写也是由这个函数完成的,因此有必要分析do_mmcops函数(该函数主要实现从MMC中读数据或者写数据到MMC中)。

    关于do_mmcops函数源码的解释,见mmc命令(do_mmcops函数的源码分析)

    另外补充说明一下,在do_movi函数中,当判断出是烧写uboot时,通过调用movi_write_bl1(addr)函数将bl1烧写在iNand的1~16扇区;通过调用run_command(run_cmd, 0)函数将bl2烧写iNand的49~xxx扇区。也就是说,利用fastboo将uboot烧写至iNand时,也是分段的。BL1这一部分在1~19扇区,BL2(整个uboot)在49~xxx扇区。

    三、fdisk\fastboot\movi三者的分区表关系

  • 相关阅读:
    PyQt5_pyqtgraph鼠标在折线图上画线段
    如何将vue-element-admin中的excel导入导出功能模块, 单独拿出来用 更新中...
    python替换word文件中的图片
    Delta Lake 是什么?
    神经开放域信息抽取综述
    qt-mvvm代码分析
    qt 无边框窗口、任务栏图标支持放大缩小、捕获任务栏图标关闭事件
    用循环结构程序自动化计算——计数循环
    洞察行业趋势:2024年平台工程预测
    差分数组入门
  • 原文地址:https://blog.csdn.net/oqqHuTu12345678/article/details/127669183