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

一、do_movi函数分析

当执行movi相关命令时,实际执行的是do_movi函数。

x210 # help movi
movi init - Initialize moviNAND and show card info
movi read  {u-boot | kernel} {addr} - Read data from sd/mmc
movi write {fwbl1 | u-boot | kernel} {addr} - Write data to sd/mmc
movi read  rootfs {addr} [bytes(hex)] - Read rootfs data from sd/mmc by size
movi write rootfs {addr} [bytes(hex)] - Write rootfs data to sd/mmc by size
movi read  {sector#} {bytes(hex)} {addr} - instead of this, you can use "mmc read"
movi write {sector#} {bytes(hex)} {addr} - instead of this, you can use "mmc write"x210 # movi read kernel 30008000
reading kernel.. 1073, 8192
MMC read: dev # 0, block # 1073, count 8192 ...8192 blocks read: OK
completed
x210 # 

该函数位于/common/cmd_movi.c文件中,根据是否定义了CONFIG_GENERIC_MMC这个宏来选择不同的内容。因为在/include/configs/X210_sd.h文件定义了这个宏,所以这里的do_movi函数是底下的那个。

删除条件编译语句后,该函数的内容与分析(以“movi read kernel 30008000”为例进)如下:

/*
执行命令“ movi read kernel 30008000 ”时,
argc=4,argv[0]="movi",argv[1]="read",argv[2]="kenel",argv[3]="30008000"
*/int do_movi(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{char *cmd;ulong addr, start_blk, blkcnt;uint rfs_size;char run_cmd[100];uint rw = 0, attribute = 0;int i;member_t *image;struct mmc *mmc;int dev_num = 0;#if defined(CONFIG_VOGUES)//不满足int boot_dev;
#endifcmd = argv[1];// cmd="read"switch (cmd[0]) {case 'i'://i即initraw_area_control.magic_number = 0;run_command("mmcinfo", 0);return 1;case 'r':  //r即read,选择这个rw = 0;  /* read case */break;case 'w'://w即writerw = 1; /* write case */break;default:goto usage;}cmd = argv[2];//cmd="kernel"switch (cmd[0]) {case 'f'://f即fwbl1if (argc != 4)goto usage;attribute = 0x0;addr = simple_strtoul(argv[3], NULL, 16);break;case 'u'://u即u-bootif (argc != 4)goto usage;attribute = 0x2;addr = simple_strtoul(argv[3], NULL, 16);break;case 'k'://k即kernel,选择这个if (argc != 4)goto usage;attribute = 0x4;addr = simple_strtoul(argv[3], NULL, 16);//把字符串形式的数字转为数字,此时addr=30008000break;case 'r'://r即rootfsif (argc != 5)goto usage;attribute = 0x8;addr = simple_strtoul(argv[3], NULL, 16);break;default:goto usage;}#if defined(CONFIG_VOGUES)//不满足boot_dev = movi_boot_src();if (boot_dev) {/* boot device is NOR *//* read kernel from eMMC */mmc = find_mmc_device(0);printf("MMC #0 is boot device\r\n");} else {/* boot device is SD card *//* read kernel from SD card */mmc = find_mmc_device(1);printf("MMC #1 is boot device\r\n");}
#else//执行这个mmc = find_mmc_device(dev_num);//这里的dev_num在开头就赋值为0,表示inand。
#endifmmc_init(mmc);//初始化/* firmware BL1 r/w */if (attribute == 0x0) {//不满足,因为attribute = 0x4/* on write case we should write BL1 1st. */for (i=0, image = raw_area_control.image; i<15; i++) {if (image[i].attribute == attribute)break;}start_blk = image[i].start_blk;blkcnt = image[i].used_blk;printf("%s FWBL1 .. %ld, %ld ", rw ? "writing":"reading",start_blk, blkcnt);sprintf(run_cmd,"mmc %s 0 0x%lx 0x%lx 0x%lx",rw ? "write":"read",addr, start_blk, blkcnt);run_command(run_cmd, 0);printf("completed\n");return 1;}/* u-boot r/w */if (attribute == 0x2) {//不满足,因为attribute = 0x4/* on write case we should write BL2 1st. */
#if defined(CONFIG_FUSED) for (i=0, image = raw_area_control.image; i<15; i++) {if (image[i].attribute == 0x1)break;}start_blk = image[i].start_blk;blkcnt = image[i].used_blk;printf("%s BL1.. %ld, %ld ", rw ? "writing":"reading",start_blk, blkcnt);sprintf(run_cmd,"mmc %s 0 0x%lx 0x%lx 0x%lx",rw ? "write":"read",addr, start_blk, blkcnt);run_command(run_cmd, 0);printf("completed\n");
#elseif (rw) {start_blk = raw_area_control.image[1].start_blk;blkcnt = raw_area_control.image[1].used_blk;printf("Writing BL1 to sector %ld (%ld sectors).. ",start_blk, blkcnt);movi_write_bl1(addr);}
#endiffor (i=0, image = raw_area_control.image; i<15; i++) {if (image[i].attribute == attribute)break;}start_blk = image[i].start_blk;blkcnt = image[i].used_blk;printf("%s bootloader.. %ld, %ld ", rw ? "writing":"reading",start_blk, blkcnt);#if defined(CONFIG_SECURE_BOOT)
#define BL2_SIZE 8192sprintf(run_cmd,"mmc %s 0 0x%lx 0x%lx 0x%lx",rw ? "write":"read",addr + BL2_SIZE, start_blk, blkcnt);
#elsesprintf(run_cmd,"mmc %s 0 0x%lx 0x%lx 0x%lx",rw ? "write":"read",addr, start_blk, blkcnt);
#endifrun_command(run_cmd, 0);printf("completed\n");return 1;}/* kernel r/w */if (attribute == 0x4) {//满足,因为attribute = 0x4for (i=0, image = raw_area_control.image; i<15; i++) {if (image[i].attribute == attribute)//根据attribute来匹配到底是哪个image[](即raw分区表中的哪个分区)break;}start_blk = image[i].start_blk;//计算这个分区的信息(起始扇区号、)blkcnt = image[i].used_blk;printf("%s kernel.. %ld, %ld ", rw ? "writing" : "reading",start_blk, blkcnt);#if defined(CONFIG_VOGUES)//不满足if (boot_dev)sprintf(run_cmd, "mmc %s 0 0x%lx 0x%lx 0x%lx",rw ? "write" : "read", addr, start_blk, blkcnt);elsesprintf(run_cmd, "mmc %s 1 0x%lx 0x%lx 0x%lx",rw ? "write" : "read", addr, start_blk, blkcnt);#else//执行这个sprintf(run_cmd, "mmc %s 0 0x%lx 0x%lx 0x%lx",rw ? "write" : "read", addr, start_blk, blkcnt);//rw=0,所以是read#endifrun_command(run_cmd, 0);//最终调用run_command函数来运行命令printf("completed\n");return 1;}/* root file system r/w */if (attribute == 0x8) {//不满足,因为attribute = 0x4rfs_size = simple_strtoul(argv[4], NULL, 16);for (i=0, image = raw_area_control.image; i<15; i++) {if (image[i].attribute == attribute)break;}start_blk = image[i].start_blk;blkcnt = rfs_size/MOVI_BLKSIZE +((rfs_size&(MOVI_BLKSIZE-1)) ? 1 : 0);image[i].used_blk = blkcnt;printf("%s RFS.. %ld, %ld ", rw ? "writing":"reading",start_blk, blkcnt);sprintf(run_cmd,"mmc %s 0 0x%lx 0x%lx 0x%lx",rw ? "write":"read",addr, start_blk, blkcnt);run_command(run_cmd, 0);printf("completed\n");return 1;}return 1;usage:printf("Usage:\n%s\n", cmdtp->usage);return -1;
}

二、init_raw_area_table函数分析

注意到上面的do_movi函数中频繁用到member_t *image这个变量。

其中member_t是struct member结构体的别名,这个结构体的一个实例就表示一个分区的信息。

/** start_blk: start block number for image* used_blk: blocks occupied by image* size: image size in bytes* attribute: attributes of image*            0x1: u-boot parted (BL1)*            0x2: u-boot (BL2)*            0x4: kernel*            0x8: root file system*            0x10: environment area*            0x20: reserved* description: description for image* by scsuh*/
typedef struct member {uint start_blk;uint used_blk;uint size;uint attribute; /* attribute of image */char description[16];
} member_t; /* 32 bytes */

在/common/cmd_movi.c文件中,init_raw_area_table函数构建了一个raw分区表。

raw分区表的数据类型如下(这个数据类型的一个实例就是一个raw分区表):

/** magic_number: 0x24564236* start_blk: start block number for raw area* total_blk: total block number of card* next_raw_area: add next raw_area structure* description: description for raw_area* image: several image that is controlled by raw_area structure* by scsuh*/
typedef struct raw_area {uint magic_number; /* to identify itself */uint start_blk; /* compare with PT on coherency test */uint total_blk;uint next_raw_area; /* should be sector number */char description[16];member_t image[15];
} raw_area_t; /* 512 bytes */
//定义raw_area_t数据类型的一个变量raw_area_control,即定义一个分区表
//后面将填充这个变量的image[]成员(image[]成员表示具体分区的信息)
raw_area_t raw_area_control;
int init_raw_area_table (block_dev_desc_t * dev_desc)
{struct mmc *host = find_mmc_device(dev_desc->dev);/* when last block does not have raw_area definition. */if (raw_area_control.magic_number != MAGIC_NUMBER_MOVI) {int i = 0;member_t *image;u32 capacity;if (host->high_capacity) {capacity = host->capacity;#ifdef CONFIG_S3C6410if(IS_SD(host))capacity -= 1024;#endif} else {capacity = host->capacity;}dev_desc->block_read(dev_desc->dev,capacity - (eFUSE_SIZE/MOVI_BLKSIZE) - 1,1, &raw_area_control);if (raw_area_control.magic_number == MAGIC_NUMBER_MOVI) {return 0;}dbg("Warning: cannot find the raw area table(%p) %08x\n",&raw_area_control, raw_area_control.magic_number);/* add magic number */raw_area_control.magic_number = MAGIC_NUMBER_MOVI;/* init raw_area will be 16MB */raw_area_control.start_blk = 16*1024*1024/MOVI_BLKSIZE;raw_area_control.total_blk = capacity;raw_area_control.next_raw_area = 0;strcpy(raw_area_control.description, "initial raw table");image = raw_area_control.image;//指向分区表的开头位置#if defined(CONFIG_EVT1)#if defined(CONFIG_FUSED)/* image 0 should be fwbl1 */image[0].start_blk = (eFUSE_SIZE/MOVI_BLKSIZE);image[0].used_blk = MOVI_FWBL1_BLKCNT;image[0].size = FWBL1_SIZE;image[0].attribute = 0x0;strcpy(image[0].description, "fwbl1");dbg("fwbl1: %d\n", image[0].start_blk);#endif
#endif/* image 1 should be bl2 */
#if defined(CONFIG_EVT1)#if defined(CONFIG_FUSED)image[1].start_blk = image[0].start_blk + MOVI_FWBL1_BLKCNT;#elseimage[1].start_blk = (eFUSE_SIZE/MOVI_BLKSIZE);#endif
#elseimage[1].start_blk = capacity - (eFUSE_SIZE/MOVI_BLKSIZE) -MOVI_BL1_BLKCNT;
#endifimage[1].used_blk = MOVI_BL1_BLKCNT;image[1].size = SS_SIZE;image[1].attribute = 0x1;strcpy(image[1].description, "u-boot parted");dbg("bl1: %d\n", image[1].start_blk);/* image 2 should be environment */
#if defined(CONFIG_EVT1)image[2].start_blk = image[1].start_blk + MOVI_BL1_BLKCNT;
#elseimage[2].start_blk = image[1].start_blk - MOVI_ENV_BLKCNT;
#endifimage[2].used_blk = MOVI_ENV_BLKCNT;image[2].size = CFG_ENV_SIZE;image[2].attribute = 0x10;strcpy(image[2].description, "environment");dbg("env: %d\n", image[2].start_blk);/* image 3 should be bl2 */
#if defined(CONFIG_EVT1)image[3].start_blk = image[2].start_blk + MOVI_ENV_BLKCNT;
#elseimage[3].start_blk = image[2].start_blk - MOVI_BL2_BLKCNT;
#endifimage[3].used_blk = MOVI_BL2_BLKCNT;image[3].size = PART_SIZE_BL;image[3].attribute = 0x2;strcpy(image[3].description, "u-boot");dbg("bl2: %d\n", image[3].start_blk);/* image 4 should be kernel */
#if defined(CONFIG_EVT1)image[4].start_blk = image[3].start_blk + MOVI_BL2_BLKCNT;
#elseimage[4].start_blk = image[3].start_blk - MOVI_ZIMAGE_BLKCNT;
#endifimage[4].used_blk = MOVI_ZIMAGE_BLKCNT;image[4].size = PART_SIZE_KERNEL;image[4].attribute = 0x4;strcpy(image[4].description, "kernel");dbg("knl: %d\n", image[4].start_blk);/* image 5 should be RFS */
#if defined(CONFIG_EVT1)image[5].start_blk = image[4].start_blk + MOVI_ZIMAGE_BLKCNT;
#elseimage[5].start_blk = image[4].start_blk - MOVI_ROOTFS_BLKCNT;
#endifimage[5].used_blk = MOVI_ROOTFS_BLKCNT;image[5].size = PART_SIZE_ROOTFS;image[5].attribute = 0x8;strcpy(image[5].description, "rfs");dbg("rfs: %d\n", image[5].start_blk);for (i=6; i<15; i++) {raw_area_control.image[i].start_blk = 0;raw_area_control.image[i].used_blk = 0;}}
}

由于CONFIG_FUSED 宏没有定义,故总共5个分区:

image数组 扇区号 分区名 大小
image[1] 1-16 u-boot parted,即BL1 8KB
image[2] 17-48 environment 16KB
image[3] 49-1072 u-boot,即BL2 512KB
image[4] 1073-9264 kernel 4MB
image[5] 9265-62512 rfs,即rootfs 26MB

注意,这里定义的image[5]的扇区号与大小,好像不是很适合实际情况?

movi命令下的分区表、fastboot命令下的分区表,两者相辅相成,利用movi或者fastboot flash命令时,参数中的bootLoader、kernel、system等标签都可以从这两张表中找到对应的地址。

关于fastboot命令下的分区表,见博客如何将镜像烧写至iNand(fastboot命令的源码分析)。

movi命令(do_movi函数的源码分析)相关推荐

  1. Linux中mknod命令实现原理以及源码分析

    本篇文章以mknod创建字符设备文件进行讲解 字符设备驱动的Demo例子可参考该篇文章 Linux 编写简单驱动并测试 1. mknod 命令 mknod /dev/hello c 520 0 该命令 ...

  2. 【SA8295P 源码分析】16 - TouchScreen Panel (TP)线程函数 tp_recv_thread() 源码分析

    [SA8295P 源码分析]16 - TouchScreen Panel (TP)线程函数 tp_recv_thread 源码分析 一.TP 线程函数:tp_recv_thread() 二.处理&am ...

  3. c++ 退出函数_UCOSIII源码分析之——bsp_os.c文件分析

    点击上方公众号名称关注,获得更多内容 ✎ 编 者 悟 语 对于坚持做的人来说,每一次的"如期而至",其实并不需要什么"期待",也没有什么"悬念&quo ...

  4. kotlin 添加第一个 集合_Flutter开发必学Dart语法篇之集合操作符函数与源码分析...

    简述: 在上一篇文章中,我们全面地分析了常用集合的使用以及集合部分源码的分析.那么这一节讲点更实用的内容,绝对可以提高你的Flutter开发效率的函数,那就是集合中常用的操作符函数.这次说的内容的比较 ...

  5. dart string 转 bool_Dart语法篇之集合操作符函数与源码分析(三)

    简述: 在上一篇文章中,我们全面地分析了常用集合的使用以及集合部分源码的分析.那么这一节讲点更实用的内容,绝对可以提高你的Flutter开发效率的函数,那就是集合中常用的操作符函数.这次说的内容的比较 ...

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

    以下内容源于网络资源的学习与整理,如有侵权请告知删除. 参考博客 u-boot sdfuse命令烧录分析----从SD卡加载内核_white_bugs的博客-CSDN博客 一.将镜像文件烧写至iNan ...

  7. 【SA8295P 源码分析】00 - 系列文章链接汇总

    [SA8295P 源码分析]00 - 系列文章链接汇总 2023年5月25日 Note: 从今天开始,正式开始全力分析SA8295P 源码,主要是利用工作之余的时间来分析代码,争取把这个平台吃透. 本 ...

  8. scrapy源码分析(六)---------------CrawlProcess

    上一篇教程中讲到crawl命令最终会执行CrawlProcess的crawl和start方法.这一篇对CrawlProcess的源码进行详细分析,来了解一下是如何进行爬取任务的. 先看一下CrawlP ...

  9. jQuery源码分析系列

    声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://git ...

最新文章

  1. Opencv 实现图像的离散傅里叶变换(DFT)、卷积运算(相关滤波)
  2. java 微信转账 ca_error_C#关于微信红包开发问题:CA证书出错,请登录微信支付商户平台下载证书...
  3. 论文浅尝 | BERT:Pre-training of Deep Bidirectional Transformers
  4. pythonopencv人脸相似度_图像相似度算法的个人见解(pythonopencv)-Go语言中文社区...
  5. 《Algorithms》Comparable 实现选择排序
  6. Effective_STL 学习笔记(十七) 使用 “交换技巧” 来修整过剩的容量
  7. 翻译连载 | 附录 B: 谦虚的 Monad-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇...
  8. 【数学基础】机器学习中的几个熵
  9. 题解报告:hdu 1575 Tr A
  10. Delphi2007使用心得
  11. 对象转json字符串(带转义字符)
  12. linux 配置 NTP 服务器
  13. 华为交换机 查ip冲突_华为交换机根据ip查端口号
  14. nox模拟器(安卓5.1)adb连接
  15. 主引导记录(MBR)的反汇编分析
  16. 数据库三范式 无重复列 完全依赖主键 属性不依赖非主属性
  17. ubuntu中snap包的安装、更新删除与简单使用
  18. 玫琳凯在Skin of Color Society线上活动期间公布突破性研究
  19. 魔镜魔镜谁最美 康得新“魔镜”一分钟给答案
  20. 论文写作——参考文献浅谈

热门文章

  1. 历史的碎片,一页页飘落,好事者拣起自己中意的那页--马云的早年故事
  2. CocosCreator优化之DrawCall漫谈
  3. LimeSDR实验教程(10) DVB-S发射和接收
  4. vue+elementUI实现日期快选组件
  5. 机器学习笔记(十一)特征选择和稀疏学习
  6. 华硕、技嘉驱动程序曝权限提升、代码执行漏洞
  7. 记录一次nodejs 从高得地图根据地名获取经纬度
  8. 中国IT领袖峰会 以5G与人工智能为主题
  9. css中怎么代码可以换行吗,css强制换行代码怎么写?
  10. Semi-supervised Semantic Segmentation with Error Localization Network(基于误差定位网络的半监督语义分割 )