movi命令(do_movi函数的源码分析)

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

一、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-16u-boot parted,即BL18KB
image[2]17-48environment16KB
image[3]49-1072u-boot,即BL2512KB
image[4]1073-9264kernel4MB
image[5]9265-62512rfs,即rootfs26MB

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/460516.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[LeetCode]Search Insert Position

原题链接&#xff1a;http://oj.leetcode.com/problems/search-insert-position/ 题意描述&#xff1a; Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order. You …

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

以下内容源于网络资源的学习与整理&#xff0c;如有侵权请告知删除。 参考博客 u-boot sdfuse命令烧录分析----从SD卡加载内核_white_bugs的博客-CSDN博客 一、将镜像文件烧写至iNand的步骤 步骤1&#xff1a;完成准备工作。 &#xff08;1&#xff09;准备fastboot相关软件包…

你知道自己执行的是哪个jre吗?

多个JRE 我在做《Java日志工具之java.util.logging.Logger》的DEMO时&#xff0c;修改java.util.logging.Logger的配置文件&#xff0c;怎么修改都不起作用&#xff0c;因此打印了系统属性"java.home"&#xff0c;才知道自己使用的是 C:\Program Files\Java\jre7 &am…

无需写try/catch,也能正常处理异常

对于企业应用的开发者来说&#xff0c;异常处理是一件既简单又复杂的事情。说其简单&#xff0c;是因为相关的编程无外乎try/catch/finallythrow而已&#xff1b;说其复杂&#xff0c;是因为我们往往很难按照我们真正需要的策略来处理异常。我一直有这样的想法&#xff0c;理想…

vs2010插件

转载于:https://www.cnblogs.com/tinytiny/p/3608030.html

leetcode1——两数之和

一、提出问题 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复出现。 你可以按…

如何脱离SDK,使用DW5.5和phonegap以及JQMobile搭建开发环境

也许有些人是学C出身&#xff0c;对于Java几乎不了解。一时心血来潮想学学android开发&#xff0c;于是下载了Eclipse&#xff0c;安装了SDK&#xff0c;有模有样的学习起来。也许是懒惰了&#xff0c;对于java一直总是提不起精神。于是确定使用DreamweaverJquery mobilePhoneg…

leetcode2——两数相加

一、提出问题 给你两个非空的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照逆序的方式存储的&#xff0c;并且每个节点只能存储一位数字。请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外&#xff0c;这两个数都不会以…

32为Linux安卓AVD启动报错

2019独角兽企业重金招聘Python工程师标准>>> 当使用android的AVD时提示以下错误&#xff1a;Starting emulator for AVD NexusOne ERROR: 32-bit Linux Android emulator binaries are DEPRECATED, to use them you will have to do at least one of the following:…

填问卷,得《2015中国呼叫中心知识库现状与问题报告》

为了解中国呼叫中心知识库运营现状和存在的主要问题&#xff0c;掌握呼叫中心知识库的总体发展水平&#xff0c;中国知识管理中心&#xff08;KMCenter&#xff09;面向全国呼叫中心发起“2015中国呼叫中心知识库现状与问题调研”活动&#xff0c;主要通过问卷调研和典型用户访…

ARM汇编的特点

以下内容源于网络资源的学习与整理&#xff0c;如有侵权请告知删除。 一、LDR/STR架构 ARM采用RISC架构&#xff0c;CPU本身不能直接读取内存&#xff0c;需要先将内存中的内容加载到CPU的通用寄存器中才能被CPU处理。换言之&#xff0c;寄存器是CPU和内存进行数据交换的中介。…

持久代是方法区还是堆中的?

2019独角兽企业重金招聘Python工程师标准>>> 昨天跟一哥们讨论&#xff0c;持久代在方法区&#xff0c;属不属于堆中的? 它的意思是持久代不属于堆,属于方法区&#xff0c;而我则认为持久代属于方法区也属于堆。 结果今天上网一查,还真的是。下面是解释: 持久代”仅…

Web 前端攻防(2014版)-baidu ux前端研发部

http://fex.baidu.com/articles/page2/ Web 前端攻防&#xff08;2014版&#xff09; zjcqoo | 20 Jun 2014禁止一切外链资源 外链会产生站外请求&#xff0c;因此可以被利用实施 CSRF 攻击。 目前国内有大量路由器存在 CSRF 漏洞&#xff0c;其中相当部分用户使用默认的管理账…

Silverlight动态设置WCF服务Endpoint

2013-02-02 05:57 by jv9, 1763 阅读, 3 评论, 收藏, 编辑 去年12月收到一位朋友的邮件&#xff0c;咨询Silverlight使用WCF服务&#xff0c;应用部署后一直无法访问的问题&#xff0c;通过几次交流&#xff0c;才发现在他的项目中&#xff0c;全部使用静态URL作为WCF服务的End…

第4季3:Hi3518e的sensor接口引脚复用设置(load3518e文件)

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 在第2、3季的内容中&#xff0c;在板载系统的配置脚本即/etc/profile文件中&#xff0c;都有如下这句代码&#xff1a; ./load3518e -i -sensor ar0130 -osmem 32 -total 64 在第4季1&#xff1a…

iOS游戏开发 几个有利工具

2019独角兽企业重金招聘Python工程师标准>>> iOS游戏开发 几个有利工具 本文介绍的是iOS游戏开发 几个有利工具&#xff0c;为友们介绍几款开发工具&#xff0c;游戏爱好者记住了&#xff01;先来看内容。 AD&#xff1a; iOS游戏开发 几个有利工具是本文要介绍的内…

关于editor网页编辑器ueditor.config.js 配置图片上传

最近公司项目在做一个门户网站&#xff0c;其中新闻和简介等部分使用到了ueditor编辑器&#xff0c;但是上级明确指示需要图片上传这个功能&#xff0c;这时却发现图片上传功能不能正常使用&#xff0c;上传时一直报错&#xff0c;网上收了好几个处理办法&#xff0c;都说的不够…

[歪谈]拽一个贵人出来给你当炮架子

[歪谈]拽一个贵人出来给你"当炮架子" 我们在古装神话剧中经常会听到某个“先知”对前来算命的人说&#xff1a;你会在某某时刻遇到你的贵人。而这个贵人会在事业上助你一臂之力。 这里有个问题&#xff1a;贵人到底是什么&#xff1f;我们怎样去寻找我们的贵人。 前几…

第6季1:H264编码原理与基本概念

以下内容源于网络资源的学习与整理&#xff0c;如有侵权请告知删除。 参考博客 &#xff08;1&#xff09;H264 编码基本原理_ByteSaid的博客-CSDN博客_h264编码原理 &#xff08;2&#xff09;H264 编码简介_mydear_11000的博客-CSDN博客 &#xff08;3&#xff09;什么是I帧…

pureMVC简单示例及其原理讲解四(Controller层)

本节将讲述pureMVC示例中的Controller层。 Controller层有以下文件组成&#xff1a; AddUserCommand.asDeleteUserCommand.asModelPrepCommand.asViewPrepCommand.asStartupCommand.asAddUserCommand 。顾名思义&#xff0c;它是添加用户命令。让我们首先看看代码。 Addusercom…