以下内容源于网络资源的学习与整理,如有侵权请告知删除。
在文章如何将镜像烧写至iNand(fastboot命令的源码分析)中写到,system、kernel、bootloader的烧写都是write_to_ptn函数直接或间接调用do_mmcops函数来完成的。这里简单分析该函数。
- x210 # help mmc
- mmc read
addr blk# cnt - mmc write
addr blk# cnt - mmc rescan
- mmc list - list available devices
-
- x210 # mmc list
- S3C_HSMMC0_dev0
- S3C_HSMMC2_dev1
-
- x210 # mmc read 0 3A000000 17 32
- MMC read: dev # 0, block # 17, count 32 ...32 blocks read: OK
-
- x210 #
(1)列出mmc设备:mmc list
列出系统中的mmc设备。
(2)读/写mmc设备:mmc read/write
device num:表示mmc设备的编号。开发板上可能有多个mmc设备,比如X210开发板的inand编号为0,外接的SD卡编号是1。
addr:表示将mmc设备上的数据读取到哪个内存地址(将哪个内存地址的内容写入mmc设备)。
blk:表示从mmc设备的哪个扇区开始读取(写入)。
cnt:表示读取(写入)多少个扇区的数据。
比如“mmc read 0 3A000000 17 32”,表示从mmc设备0上,以第17扇区为开始,读取32个扇区的数据,存储到以内存地址3A000000为开始的内存空间中。
因为环境变量就存储在inand的第17扇区开始的32个扇区内,因此这条命令其实就是把环境变量读取到内存3A000000开始的内存空间中,后续我们可以用md命令来验证一下。
一开始我以为这条命令中的17、32是16进制的,因为uboot默认采用16进制,但其实是十进制的,这取决于mmc这个命令对应的源码中如何对参数进行解析的。
注意读取到某个地址为开始的内存空间,这段内存空间不能与uboot在内存中的空间有重叠,否则uboot会被覆盖。因为uboot的链接地址对应的物理地址是33E00000,而内存空间的物理地址范围是0x30000000~0x4FFFFFFF(见博客uboot中的虚拟地址映射),所以这里选取一个比较安全的地址3A000000作为测试。
拓展:可以用md命令打印查看某段内存中的值。
经过测试证明,第二个参数是十六进制的数字,而且以字节为单位的。
- x210 # mmc read 0 3A000000 17 32
- MMC read: dev # 0, block # 17, count 32 ...32 blocks read: OK
-
- x210 # help md
- md [.b, .w, .l] address [# of objects]
- - memory display
-
- x210 # md.b 3A000000 9
- 3a000000: ca 25 4f 80 6d 74 64 70 61 .%O.mtdpa
-
- x210 # md.b 3A000000 22
- 3a000000: ca 25 4f 80 6d 74 64 70 61 72 74 3d 38 30 30 30 .%O.mtdpart=8000
- 3a000010: 30 20 34 30 30 30 30 30 20 33 30 30 30 30 30 30 0 400000 3000000
- 3a000020: 00 62 .b
- x210 #
-
- x210 # md.b 3A000000 200
- 3a000000: ca 25 4f 80 6d 74 64 70 61 72 74 3d 38 30 30 30 .%O.mtdpart=8000
- 3a000010: 30 20 34 30 30 30 30 30 20 33 30 30 30 30 30 30 0 400000 3000000
- 3a000020: 00 62 6f 6f 74 64 65 6c 61 79 3d 33 00 62 61 75 .bootdelay=3.bau
- 3a000030: 64 72 61 74 65 3d 31 31 35 32 30 30 00 65 74 68 drate=115200.eth
- 3a000040: 61 64 64 72 3d 30 30 3a 34 30 3a 35 63 3a 32 36 addr=00:40:5c:26
- 3a000050: 3a 30 61 3a 35 62 00 73 65 72 76 65 72 69 70 3d :0a:5b.serverip=
- 3a000060: 31 39 32 2e 31 36 38 2e 31 2e 31 34 31 00 67 61 192.168.1.141.ga
- 3a000070: 74 65 77 61 79 69 70 3d 31 39 32 2e 31 36 38 2e tewayip=192.168.
- 3a000080: 31 2e 31 00 69 70 61 64 64 72 3d 31 39 32 2e 31 1.1.ipaddr=192.1
- 3a000090: 36 38 2e 31 2e 38 38 00 6e 65 74 6d 61 73 6b 3d 68.1.88.netmask=
- 3a0000a0: 32 35 35 2e 32 35 35 2e 32 35 35 2e 30 00 62 6f 255.255.255.0.bo
- 3a0000b0: 6f 74 61 72 67 73 3d 63 6f 6e 73 6f 6c 65 3d 74 otargs=console=t
- 3a0000c0: 74 79 53 41 43 32 2c 31 31 35 32 30 30 20 72 6f tySAC2,115200 ro
- 3a0000d0: 6f 74 3d 2f 64 65 76 2f 6d 6d 63 62 6c 6b 30 70 ot=/dev/mmcblk0p
- 3a0000e0: 32 20 72 77 20 69 6e 69 74 3d 2f 6c 69 6e 75 78 2 rw init=/linux
- 3a0000f0: 72 63 20 72 6f 6f 74 66 73 74 79 70 65 3d 65 78 rc rootfstype=ex
- 3a000100: 74 33 00 62 6f 6f 74 63 6d 64 3d 6d 6f 76 69 20 t3.bootcmd=movi
- 3a000110: 72 65 61 64 20 6b 65 72 6e 65 6c 20 33 30 30 30 read kernel 3000
- 3a000120: 38 30 30 30 3b 20 62 6f 6f 74 6d 20 33 30 30 30 8000; bootm 3000
- 3a000130: 38 30 30 30 00 00 73 6f 6c 65 3d 74 74 79 53 41 8000..sole=ttySA
- 3a000140: 43 32 2c 31 31 35 32 30 30 00 69 70 61 64 64 72 C2,115200.ipaddr
- 3a000150: 3d 31 39 32 2e 31 36 38 2e 31 2e 38 38 00 62 6f =192.168.1.88.bo
- 3a000160: 6f 74 63 6d 64 3d 6d 6f 76 69 20 72 65 61 64 20 otcmd=movi read
- 3a000170: 6b 65 72 6e 65 6c 20 33 30 30 30 38 30 30 30 3b kernel 30008000;
- 3a000180: 20 62 6f 6f 74 6d 20 33 30 30 30 38 30 30 30 00 bootm 30008000.
- 3a000190: 00 6e 6f 6e 65 00 00 38 2e 31 2e 32 30 00 00 30 .none..8.1.20..0
- 3a0001a0: 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0...............
- 3a0001b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
- 3a0001c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
- 3a0001d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
- 3a0001e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
- 3a0001f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
- x210 #
当执行mmc相关命令时,实际执行的是do_mmcops函数。
该函数位于/common/cmd_mmc.c文件中,内容与分析如下:
- /*以“mmc read 0 3A000000 17 32”为例进行说明
- argc=6
- argv[0]="mmc"
- argv[1]="read"
- argv[2]="0" 选取哪个mmc设备
- argv[3]="3A000000" 读取到哪个内容地址
- argv[4]="17" 从哪个扇区开始读写
- argv[5]="32" 读取多少个扇区
- */
-
- int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
- {
- int rc = 0;
-
- switch (argc) {
-
- default: /* at least 5 args */
- if (strcmp(argv[1], "read") == 0)
- {
-
- int dev = simple_strtoul(argv[2], NULL, 10);//dev=0
-
- void *addr = (void *)simple_strtoul(argv[3], NULL, 16);//读取数据到哪个内存地址
- u32 cnt = simple_strtoul(argv[5], NULL, 10);//读取多少个扇区
- u32 blk = simple_strtoul(argv[4], NULL, 10);//从哪个扇区开始读写
- u32 n;
- u32 read_cnt;
- u32 cnt_to_read;
- void *addr_to_read;
- struct mmc *mmc = find_mmc_device(dev);//寻找dev=0的这个设备
-
- if (!mmc)
- return 1;
-
- printf("\nMMC read: dev # %d, block # %d, count %d ...",
- dev, blk, cnt);
-
- rc = mmc_init(mmc);
- if(rc)
- return rc;
-
- n = 0;
- addr_to_read = addr;
- do {
- if (cnt - n > MAXIMUM_BLOCK_COUNT)
- cnt_to_read = MAXIMUM_BLOCK_COUNT;
- else
- cnt_to_read = cnt - n; //设备0
- read_cnt = mmc->block_dev.block_read(dev, blk, cnt_to_read, addr_to_read);
- n += read_cnt;
- blk += read_cnt;
- addr_to_read += read_cnt * 512;
- if(cnt_to_read != read_cnt) {
- printf("%d blocks read: %s\n",
- n, "ERROR");
- return -1;
- }
- } while(cnt > n);
-
- /* flush cache after read */
- flush_cache((ulong)addr, cnt * 512); /* FIXME */
-
- printf("%d blocks read: %s\n",
- n, "OK");
- return 0;
- }
- else if (strcmp(argv[1], "write") == 0)
- {
- int dev = simple_strtoul(argv[2], NULL, 10);
- void *addr = (void *)simple_strtoul(argv[3], NULL, 16);
- u32 cnt = simple_strtoul(argv[5], NULL, 10);
- int blk = simple_strtoul(argv[4], NULL, 10);
- u32 n;
- u32 written_cnt;
- u32 cnt_to_write;
- void *addr_to_write = addr;
- struct mmc *mmc = find_mmc_device(dev);
-
-
- if (!mmc)
- return 1;
-
- printf("\nMMC write: dev # %d, block # %d, count %d ... ",
- dev, blk, cnt);
-
- rc = mmc_init(mmc);
- if(rc)
- return rc;
-
- n = 0;
- addr_to_write = addr;
- do {
- if (cnt - n > MAXIMUM_BLOCK_COUNT)
- cnt_to_write = MAXIMUM_BLOCK_COUNT;
- else
- cnt_to_write = cnt - n;
-
- written_cnt = mmc->block_dev.block_write(dev, blk, cnt_to_write, addr_to_write);
- n += written_cnt;
- blk += written_cnt;
- addr_to_write += written_cnt * 512;
- if(cnt_to_write != written_cnt) {
- printf("%d blocks written: %s\n",
- n, "ERROR");
- return -1;
- }
- } while(cnt > n);
-
- printf("%d blocks written: %s\n",
- n, "OK");
- return 0;
- } else {
- printf("Usage:\n%s\n", cmdtp->usage);
- rc = 1;
- }
-
- return rc;
- }
- }