1.将分区信息写到硬盘的第一个设备节点的MBR结构中的分区表;
2.格式化分区到指定的文件系统类型。

MBR中存放分区表的位置在446-509,占用了64字节,MBR结构只支持4个主分区,所以

有4个16字节的区域,先简要说明一下MBR的分区表的结构:



从这个表格可以看出,相对于446-509的分区表区域,每个主分区的第5个字节存放的是文件

系统标志位,用来识别什么分区,用fdisk工具查看一下,有如下文件系统对应的十六进制标志:


若需要读取这些文件系统标志,只需读取MBR的450个位置,占用一个字节大小。


扯得太远了,回到正题,本文是要分析Android格式化sd卡的功能,在格式化部分,涉及到

了系统的一些函数,与vold无关,简单的说明一下即可。

Android系统在格式化sd卡的时候,首先会判断sd卡是否存在分区,如果sd卡不存在分区,

那么需要重新初始化MBR区域,所以上面简要的介绍了MBR结构中分区表的区域。


[cpp]  view plain copy

1. int Volume::formatVol() {  
2. if (getState() == Volume::State_NoMedia) {  
3.         errno = ENODEV;  
4. return -1;  
5. else if (getState() != Volume::State_Idle) {  
6.         errno = EBUSY;  
7. return -1;  
8.     }  
9. /*如果该分区为卸载,那么格式化失败,返回错误*/  
10. if (isMountpointMounted(getMountpoint())) {  
11. "Volume is idle but appears to be mounted - fixing");  
12.         setState(Volume::State_Mounted);  
13. // mCurrentlyMountedKdev = XXX  
14.         errno = EBUSY;  
15. return -1;  
16.     }  
17.   
18. char devicePath[255];  
19.     dev_t diskNode = getDiskDevice();  
20.     dev_t partNode;  
21.   
22. if (mDebug) {  
23. "Formatting volume %s (%s)", getLabel(), devicePath);  
24.     }  
25.     setState(Volume::State_Formatting);  
26.   
27. if (!mLastMountedKdev) {  
28.         dev_t deviceNodes[2];  
29. int n = getDeviceNodes(deviceNodes, 2);  
30. // initialize MBR if no partition, or has multiple partitions  
31. // but none is selected  
32. if ((diskNode == deviceNodes[0]) || (n > 1)) {  
33. "/dev/block/vold/%d:%d",  
34.                     MAJOR(diskNode), MINOR(diskNode));  
35. if (initializeMbr(devicePath)) {  
36. "Failed to initialize MBR (%s)", strerror(errno));  
37. // try to use whole disk  
38. else {  
39.                 partNode = MKDEV(MAJOR(diskNode), MINOR(diskNode) + 1);  
40.             }  
41. else {  
42.             partNode = deviceNodes[0];  
43.         }  
44. else {  
45.         partNode = mLastMountedKdev;  
46.     }  
47.   
48. "/dev/block/vold/%d:%d",  
49.             MAJOR(partNode), MINOR(partNode));  
50.   
51. int ret = Fat::format(devicePath, 0);  
52. "Failed to format (%s)", strerror(errno));  
53.   
54.     setState(Volume::State_Idle);  
55. return ret;  
56. }


格式化函数两个主要工作交给了initializeMbr和Fat::format函数:


1.initializeMbr函数负责初始化MBR;


2.Fat::format函数负责格式化分区


先来看initializeMbr函数的初始化工作:



[cpp]  view plain copy

1. int Volume::initializeMbr(const char *deviceNode) {  
2. struct disk_info dinfo;  
3.   
4. sizeof(dinfo));  
5.   
6. if (!(dinfo.part_lst = (struct part_info *) malloc(MAX_NUM_PARTS * sizeof(struct part_info)))) {  
7. "Failed to malloc prt_lst");  
8. return -1;  
9.     }  
10.   
11. sizeof(struct part_info));  
12.     dinfo.device = strdup(deviceNode);  
13.     dinfo.scheme = PART_SCHEME_MBR;  
14.     dinfo.sect_size = 512;  
15.     dinfo.skip_lba = 2048;  
16.     dinfo.num_lba = 0;  
17.     dinfo.num_parts = 1;  
18.   
19. struct part_info *pinfo = &dinfo.part_lst[0];  
20.   
21. "android_sdcard");  
22.     pinfo->flags |= PART_ACTIVE_FLAG;  
23.     pinfo->type = PC_PART_TYPE_FAT32;  
24.     pinfo->len_kb = -1;  
25.   
26. int rc = apply_disk_config(&dinfo, 0);  
27.   
28. if (rc) {  
29. "Failed to apply disk configuration (%d)", rc);  
30. goto out;  
31.     }  
32.   
33.  out:  
34.     free(pinfo->name);  
35.     free(dinfo.device);  
36.     free(dinfo.part_lst);  
37.   
38. return rc;  
39. }


这里贴出一些重要的结构体:



[cpp]  view plain copy

1. struct part_info {  
2. char *name;  
3.     uint8_t flags;  
4.     uint8_t type;  
5. /* in 1K-bytes */  
6. /* the LBA where this partition begins */  
7. };  
8. struct disk_info {  
9. char *device;  
10.     uint8_t scheme;  
11. int sect_size;       /* expected sector size in bytes. MUST BE POWER OF 2 */  
12. /* in sectors (1 unit of LBA) */  
13. /* the size of the disk in LBA units */  
14. struct part_info *part_lst;  
15. int num_parts;  
16. };


初始化完成后,将该结构体变量pinfo通过apply_disk_config函数进行设置:



[cpp]  view plain copy

1. int apply_disk_config(struct disk_info *dinfo, int test)  
2. {  
3. int fd;  
4. struct write_list *wr_lst = NULL;  
5. int rv;  
6.   
7. if (validate_and_config(dinfo, &fd, &wr_lst) != 0) {  
8. "Configuration is invalid.");  
9. goto fail;  
10.     }  
11.   
12. if ((rv = wlist_commit(fd, wr_lst, test)) >= 0)  
13.         rv = test ? 0 : sync_ptable(fd);  
14.   
15.     close(fd);  
16.     wlist_free(wr_lst);  
17. return rv;  
18.   
19. fail:  
20.     close(fd);  
21. if (wr_lst)  
22.         wlist_free(wr_lst);  
23. return 1;  
24. }


该函数先打开sd卡的设备节点,然后将MBR的初始化信息写到第一个block(512B)中,


这里涉及到非常多函数,不在vold的讨论范围。


写完MBR后,就要对分区进行格式化,要格式化成FAT32格式,Fat::format函数直接调用


系统命令newfs_msdos来格式化新分区,检测磁盘是,Fat::check函数直接调用系统命令


fsck_msdos来检测分区



最后格式化完成功,通知Framework,sd卡处于空闲状态:


[cpp]  view plain copy


    1. setState(Volume::State_Idle);



    然后,Framework又要重复挂载和卸载的操作了。