1 linux启动的几个阶段:
对应关系
阶段1 |
阶段2 |
阶段3 |
|
Boise(引导从u盘,硬盘,cdrom等启动) |
Grub |
Kernel |
系统 |
preloader(完成下载+启动引导) |
Lk |
kernel |
Systermimg |
android智能机上 分区表再各个阶段的作用:
注意:Dumchar是debug信息用(用户模式读写某分区镜像等),分区表的建立等由内核block子系统来完成。dumchar调试如下:
Dumchar_info的分区信息在哪里创建:???
/dev/bootimg
/dev/otp
/dev/nvram
dumchar_probe () ---
{
for (l = 0; l<PART_NUM; l++){
if(!strcmp(dumchar_devices[l].dumname,"otp")){
dumchar_device[l]= device_create(dumchar_class, NULL, MKDEV(major, l),NULL,"otp_bak");
}else{
dumchar_device[l]= device_create(dumchar_class, NULL,MKDEV(major, l),NULL, dumchar_devices[l].dumname);
}
}
。。。。。
}
而且绑定了dumchar_fops:
structfile_operations dumchar_fops = {
.owner= THIS_MODULE,
.llseek= dumchar_llseek,
.read = dumchar_read,
.write = dumchar_write,
.unlocked_ioctl= dumchar_ioctl,
.open= dumchar_open,
.release= dumchar_release,
};
所以可以读写分区。获取分区的方法:
1.flashtool :---根据scat读取分区
2.adb 获取:
Adb shell dd if=/dev/bootimg of=/sdcard/boot.img bs=6291456 count=1
-----获取bootimg分区 bs=6291456 (mtk一般是6MB)。这里是把整个bootimage分区读出,也是可以的,正确的读法是根据
---------然后可以使用split_bootimg.pl 脚本从bootimg中提取出roofs;
Adb pull /dev/bootimg 就是bootimg分区开始 读取flash
Adb pull /dev/mbr 就是mbr分区开始 读取flash,
2 分析MBR:
主引导记录最开头是第一阶段引导代码。其中的硬盘引导程序的主要作用是检查分区表是否正确并且在系统硬件完成自检以后将控制权交给硬盘上的引导程序(如GNUGRUB)。它不依赖任何操作系统,而且启动代码也是可以改变的,从而能够实现多系统引导。
------这里为00,应为不需要操作系统引导,只是单系统,所以我们是可以做一个手机多个操作系统的。
3 内核什么时候读取MBR的分区表和建立block设备的节点呢?以及其作用?
首先建立磁盘(比如一块emmc,一块sd卡,一个硬盘)的块设备节点,先了解两个知识点:
1)linux内核中支持的磁盘类型:(做分区表都是根据磁盘类型来做的分区)
static int(*check_part[])(struct parsed_partitions *) = {
/*
* Probe partition formats with tables at diskaddress 0
* that also have an ADFS boot block at 0xdc0.
*/
#ifdefCONFIG_ACORN_PARTITION_ICS
adfspart_check_ICS,
#endif
#ifdefCONFIG_ACORN_PARTITION_POWERTEC
adfspart_check_POWERTEC,
#endif
#ifdefCONFIG_ACORN_PARTITION_EESOX
adfspart_check_EESOX,
#endif
/*
* Now move on to formats that only havepartition info at
* disk address 0xdc0. Since these may also have stale
* PC/BIOS partition tables, they need to comebefore
* the msdos entry.
*/
#ifdefCONFIG_ACORN_PARTITION_CUMANA
adfspart_check_CUMANA,
#endif
#ifdefCONFIG_ACORN_PARTITION_ADFS
adfspart_check_ADFS,
#endif
#ifdefCONFIG_EFI_PARTITION
efi_partition, /*this must come before msdos */
#endif
#ifdefCONFIG_SGI_PARTITION
sgi_partition,
#endif
#ifdefCONFIG_LDM_PARTITION
ldm_partition, /*this must come before msdos */
#endif
#ifdefCONFIG_MSDOS_PARTITION
msdos_partition,---------------》手机上基本上是这种。
#endif
#ifdefCONFIG_OSF_PARTITION
osf_partition,
#endif
#ifdefCONFIG_SUN_PARTITION
sun_partition,
#endif
#ifdefCONFIG_AMIGA_PARTITION
amiga_partition,
#endif
#ifdefCONFIG_ATARI_PARTITION
atari_partition,
#endif
#ifdefCONFIG_MAC_PARTITION
mac_partition,
#endif
#ifdefCONFIG_ULTRIX_PARTITION
ultrix_partition,
#endif
#ifdefCONFIG_IBM_PARTITION
ibm_partition,
#endif
#ifdefCONFIG_KARMA_PARTITION
karma_partition,
#endif
#ifdefCONFIG_SYSV68_PARTITION
sysv68_partition,
#endif
NULL
};
2)EMMC情况下:#ls /dev/block/
/dev/block/mmcblk0代表第一个SD磁盘
/dev/block/mmcblk0p1 代表第一个SD卡设备的第一个分区;
brw------- root root 179, 0 2012-08-15 18:07mmcblk0----emmc本身--MBR
brw------- root root 179, 8 2012-08-15 18:07mmcblk0boot0---pl
brw------- root root 179, 16 2012-08-15 18:07mmcblk0boot1---dsp
brw------- root root 179, 1 2012-08-15 18:07mmcblk0p1-----ebr1
brw------- root root 179, 2 2012-08-15 18:07mmcblk0p2
brw------- root root 179, 3 2012-08-15 18:07mmcblk0p3
brw------- root root 179, 4 2012-08-15 18:07mmcblk0p4
brw------- root root 179, 5 2012-08-15 18:07mmcblk0p5
brw------- root root 179, 6 2012-08-15 18:07mmcblk0p6
4 分区检查和建立过程:emmc设备与mtd设备为例:
目录:
1)mmc设备:对MMC驱动 =mmc_driver为例
2)MTD设备:nand flash=:
---------------------------------------------------------/////-----------------------------------------
1)mmc设备:对MMC驱动 =mmc_driver为例
Emmc 的基于mbr、ebr的分区类型的分区创建过程,主要4步:
Step1: mmc设备与mmc度驱动绑定:
step2:mmc注册到通用块子系统,建立 emmc的系统分区:disk节点和boot0/1分区节点(不是用户分区user data):
brw-------root root 179, 0 2012-08-15 18:07 mmcblk0----emmc本身--MBR
brw-------root root 179, 8 2012-08-15 18:07 mmcblk0boot0---pl
brw-------root root 179, 16 2012-08-15 18:07 mmcblk0boot1---dsp
Block.c (kernel\drivers\mmc\card):mmc_blk_probe()。
step3: 内核获取分区表:rescan_partitions()---》if (!get_capacity(disk) || !(state = check_partition()))
依次使用内核支持的磁盘类型(注意不是文件系统),来轮询disk。返回各个分区的信息(查看是否有MBR和DBR等分区信息):
for (p = 1; p < state->limit; p++)//获取如下两个关键字:各个分区大小和分区的起始扇区
sector_t size =state->parts[p].size;分区大小
sector_t from =state->parts[p].from;分区的起始扇区。
step4:绑定建立各个用户分区的/dev/block/mmcblk0pxxx节点:rescan_partitions()----》add_partition()
以上4步都是在mmc_blk_probe中调起完成;
Step5:从应用层开始mount各个分区:
是init进程,通过解析init.rc:
onfs_property:ro.mount.fs=EXT4
write /proc/bootprof"INIT:eMMC:Mount_START"
exec /sbin/e2fsck -p /emmc@android
# Mount /system rw first to give thefilesystem a chance to save a checkpoint
#mount ext4 emmc@android /system waitcommit=1,data=journal,noauto_da_alloc
……..
//////////////----------------------------------------------------------------------------------////////////////////////////
下面细节分析各个步骤:
Step1:mmc设备与mmc度驱动绑定:
mmc设备与mmc度驱动如何绑定?步骤分为:
步骤1)首先是emmc的设备先挂载,也就是emmc的控制器先初始化设备:
然后在挂载mmc设备驱动时,执行驱动程序中的xx_mmc_probe(),检测host设备中挂载的sd设备。此时probe函数会创建一个host设备,然后开启一个延时任务mmc_rescan()。
驱动挂载成功后,mmc_rescan()函数被执行,然后对卡进行初始化(步骤后面详细讲述)。
假如扫描到总线上挂有有效的设备,就调用相对应的函数把设备装到系统中,mmc_attach_sdio()、mmc_attach_sd()、mmc_attach_mmc()这三个函数分别是装载sdio设备,sd卡和mmc卡的。
在sd卡中,驱动循环发送ACMD41、CMD55给卡,读取OCR寄存器,成功后,依次发送CMD2(读CID)、CMD3(得到RCA)、CMD9(读CSD)、CMD7(选择卡)。后面还有几个命令分别是ACMD41&CMD51,使用CMD6切换一些功能,如切换到高速模式。
经过上述步骤,已经确定当前插入的卡是一张有效、可识别的存储卡。然后调用mmc_add_card()把存储卡加到系统中。正式与系统驱动连接在一起。
步骤2)mmc驱动程序去probe设备(也就是完成mmc设备上的分区初始化):
卡设备加到系统中后,通知mmc块设备驱动。块设备驱动此时调用probe函数,即mmc_blk_probe()函数,mmc_blk_probe()首先分配一个新的mmc_blk_data结构变量,然后调用mmc_init_queue,初始化blk队列。然后建立一个线程mmc_queue_thread()。
例如mtk的流程:
比如SD卡(or emmcflash)在识别到之后:
1)添加设备(就是step1的流程):mmc_add_card()----->device_add(&card->dev);----->bus_probe_device()---->device_attach()--:参数card传到mmc bus,这样当mmc驱动 mmc_blk_probe()的就能probe这个mmc设备。
2)与MMC驱动绑定:mmc_driver:
Block.c(kernel\drivers\mmc\card): .probe =mmc_blk_probe,:
mmc块设备驱动:mmc_blk_probe(struct mmc_card *card)---->mmc_add_disk()
---》通用块设备子系统:add_disk()---》register_disk()//注册到通用块子系统中
----->blkdev_get()------》__blkdev_get()----》
---->rescan_partitions()--->check_partition()查看是否有MBR和DBR等分区信息.
磁盘与驱动绑定后,就进入mmc_blk_probe();
step2:mmc注册到通用块子系统,建立 emmc的系统分区:disk节点和boot0/1分区节点(非用户分区user data):
emmc的系统分区:disk节点和boot0/1分区节点:/dev/block/mmcblk0boot0/boot1
brw-------root root 179, 0 2012-08-15 18:07 mmcblk0----emmc本身--MBR
brw-------root root 179, 8 2012-08-15 18:07 mmcblk0boot0---pl
brw-------root root 179, 16 2012-08-15 18:07 mmcblk0boot1---dsp
代码分析:建立emmc磁盘分区节点的代码:注意只是创建节点文件,但是还没有绑定分区的信息(扇区起始,大小);
Block.c (kernel\drivers\mmc\card):
staticint mmc_blk_probe(struct mmc_card *card)//分析
这里主要两个步骤:
步骤1:根据card(也就是emmc磁盘)参数,分配好 磁盘的节点文件 和 磁盘的分区的节点文件
步骤2:增加(绑定)磁盘到 步骤1创建好的节点文件。
{
….
md= mmc_blk_alloc(card);//分配disk节点/dev/block/mmcblk0----》分配函数mmc_blk_alloc_req(){
….
snprintf(md->disk->disk_name,sizeof(md->disk->disk_name),
"mmcblk%d%s",md->name_idx, subname ? subname : "");
...
}
...
if (mmc_blk_alloc_parts(card, md))//分配disk的分区的节点:/dev/block/mmcblk0boot0/boot1
…..
if (mmc_add_disk(md))//增加disk 到节点:/dev/block/mmcblk0 ,同时会调起到 step3:和step4 完成用户分区的节点/dev/block/mmcblk0pxx节点建立
gotoout;
list_for_each_entry(part_md,&md->part, part) { 循环增加disk的分区到各自节点:一般是两个part节点,/dev/block/mmcblk0boot0和 boot1
if(mmc_add_disk(part_md))
gotoout;
}
…..
}
建立 emmc的系统分区:disk节点和boot0/1分区节点(不是用户分区user data):
static structmmc_blk_data *mmc_blk_alloc_req(structmmc_card *card,
struct device *parent,
sector_t size,
bool default_ro,
const char *subname,
int area_type)
{
…..
snprintf(md->disk->disk_name,sizeof(md->disk->disk_name),
"mmcblk%d%s",md->name_idx, subname ? subname : "");
………
)
问题:参数card 从何而来?
因为参数card里面的card->part[idx] 决定步骤2中创建节点的分区参数。sd卡是:sd.c@mmc_sd_init_card(),这里以mmc为例,
mmc_attach_mmc()---->mmc_init_card()--->mmc_alloc_card()构造新的card参数。
mmc_get_ext_csd(){获取extcsd参数
mmc_send_ext_csd()---》mmc_send_cxd_data()
{
...
sg_init_one(&sg,data_buf, len);初始化scatterlist缓冲。“在SD/MMC代码中,在发起request的时候,都是通过scatterlist来发送数据的,定义在mmc_data里面”
...
mmc_set_data_timeout()发送MMC_SEND_EXT_CSD
}
sd控制器驱动处理:MMC_SEND_EXT_CSD命令:
Sd.c msdc_do_request ()
{
if(cmd->opcode == MMC_SEND_EXT_CSD) {
msdc_get_data(ext_csd,data,host->dma_xfer);
通过sg库函数。ext_csd信息放到scatterlist 缓冲:
staticint msdc_get_data(u8 *dst, struct mmc_data *data, int dma_xfer)
{
intleft;
u8*ptr;
structscatterlist *sg = data->sg;
intnum = data->sg_len;
while(num) {
left= msdc_sg_len(sg,dma_xfer);
ptr= (u8 *) sg_virt(sg);
memcpy(dst,ptr, left);
sg= sg_next(sg);
dst+= left;
num--;
}
return0;
}
}
然后使用ext CSD: mmc_read_ext_csd()---->
for (idx = 0; idx <MMC_NUM_BOOT_PARTITION; idx++) {
part_size= ext_csd[EXT_CSD_BOOT_MULT] << 17;
mmc_part_add(card, part_size,
EXT_CSD_PART_CONFIG_ACC_BOOT0+ idx,
"boot%d", idx, true,--------------------》用的是boot%d,
MMC_BLK_DATA_AREA_BOOT);
}
利用ext csd参数 构造出一个card:
static inline void mmc_part_add(struct mmc_card *card, unsigned int size,
unsignedint part_cfg, char *name, int idx, bool ro,
intarea_type)
{
card->part[card->nr_parts].size = size;
card->part[card->nr_parts].part_cfg = part_cfg;
sprintf(card->part[card->nr_parts].name, name, idx);
card->part[card->nr_parts].force_ro = ro;
card->part[card->nr_parts].area_type= area_type;
card->nr_parts++;
}
也就是card->part来自ext_csd. ext_csd存放的是什么呢?就是emmc的‘系统分区‘,不是user分区,如下:
4 Default Areas ofMemory Device
–2 x Boot Area Partitions for Booting(可以使128k,4mb 8mb不等)
–1 x Replay Protected Memory Block Area Partition-----RPMB
–1 x User Data Area
step3: 内核获取分区表:rescan_partitions()---》if (!get_capacity(disk) || !(state = check_partition()))
调用流程:
mmc块设备驱动:mmc_blk_probe----->mmc_add_disk()
Genhd.c(trunk\kernel-3.10\block):void add_disk(structgendisk *disk)
---》通用块设备子系统:add_disk()---》register_disk()//注册到通用块子系统中
----->blkdev_get()----------__blkdev_get()----》
---->rescan_partitions()--->:
每个磁盘有几个分区,每个分区的起始扇区是多少,每个分区的扇区个数是多少是怎么来的?
答案:--check_partition()依次使用内核支持的磁盘类型(注意不是文件系统),来轮询disk。返回各个分区的信息(查看是否有MBR和DBR等分区信息):
for (p = 1; p < state->limit;p++)//获取如下两个关键字:分区的扇区大小和分区的起始扇区
sector_tsize = state->parts[p].size;分区大小
sector_t from =state->parts[p].from;分区的起始扇区。
3.1 轮询disk:
while (!res&& check_part[i]) {
memset(state->parts,0, state->limit * sizeof(state->parts[0]));
res= check_part[i++](state);
3.2 对于msdoc系统:check_partition 会调起 msdos_partition:
分析:
int msdos_partition(structparsed_partitions *state)
{
sector_tsector_size = bdev_logical_block_size(state->bdev) / 512;
Sectorsect;
unsignedchar *data;
structpartition *p;
structfat_boot_sector *fb;
intslot;
data = read_part_sector(state, 0, §);//读取逻辑0号扇区-也就是512个字节
if(!data)
return-1;
if(!msdos_magic_present(data + 510)) {
put_dev_sector(sect);
return0;
}
if(aix_magic_present(state, data)) {
put_dev_sector(sect);
strlcat(state->pp_buf," [AIX]", PAGE_SIZE);
return0;
}
/*
* Now that the 55aa signature is present, thisis probably
* either the boot sector of a FAT filesystemor a DOS-type
* partition table. Reject this in case theboot indicator
* is not 0 or 0x80.
*/
//占用512个字节的MBR中,偏移地址01BEH--01FDH的64个字节,为4个分区项内容(分区信息表),所以这里+0x1be。
p = (struct partition *) (data + 0x1be);
for(slot = 1; slot <= 4; slot++, p++) {
if(p->boot_ind != 0 && p->boot_ind != 0x80) {
/*
* Even without a valid boot inidicator value
* its still possible this is valid FATfilesystem
* without a partition table.
*/
fb= (struct fat_boot_sector *) data;
if(slot == 1 && fb->reserved && fb->fats
&&fat_valid_media(fb->media)) {
strlcat(state->pp_buf,"\n", PAGE_SIZE);
…….
……..
for (slot = 1 ; slot <= 4 ; slot++, p++) {//获取如下两个关键字:分区大小和分区的起始扇区
sector_t start = start_sect(p)*sector_size;
sector_t size = nr_sects(p)*sector_size;
if(!size)
continue;
if (is_extended_partition(p)) {-----》处理扩展分区,EBR1 EBR2
查看 mbr 信息:例如
$ file MBR
MBR: x86 boot sector;
partition 1: ID=0x5,starthead 0, startsector 32, 4294967295 sectors;//ID=0x05 表示扩展 Dos 分区--------->跳转到 EBR1
partition 2: ID=0x83,starthead 0, startsector 44096, 10240 sectors; //0x83 表示该分区是 EXT2 类型,size=5MBSEC_RO
partition 3: ID=0x83,starthead 0, startsector 67392, 786432 sectors; ////0x83 表示该分区是 EXT2类型,size=384MB ANDROID
partition 4: ID=0x83,starthead 0, startsector 855872, 878592 sectors, code offset 0x0////0x83EXT2类型.size=429MB CACHE
------ID表示 Partition Type 也就是分区文件系统类型
分区类型定义在:genhd.h
/*
* prevent someone doing mkfs or mkswap on an
* extended partition, but leave room for LILO
* FIXME: this uses one logical sector for >512b
* sector, although it may not beenough/proper.
*/
sector_tn = 2;
n= min(size, max(sector_size, n));
put_partition(state, slot, start, n);--》读取该扩展分区,同样读取逻辑扇区0 512个字节
……………
什么作用?利用mbr里面的分区信息:用户在访问用户分区的时候,提供偏移地址?
有些平台需要,比如82 使用的是线性地址。92用的是逻辑地址。如下82的错:
由于MBR分区必须要处于Userarea,因此这时就会出现访问地址的offset计算错误。通常在开机uart kernel log中会看到类似如下的错误提示:
[ 3.309425] (2)[62:mmcqd/0][MSDC] msdc0 -> Address offset in USERREGION(Capacity 14912 MB) is 0xffffe400 <- msdc_cal_offset() : L<3104>PID<mmcqd/0><0x3e>
[ 3.309449] (2)[62:mmcqd/0][MSDC] msdc0-> XXX Address offset error(-7168),please check MBR start address!! <-msdc_cal_offset() : L<3106> PID<mmcqd/0><0x3e>
分区信息和块设备节点建立之后,各个分区的文件系统都不一样(ext ,fat等),如何mount时候如何区分呢?根据mount的参数(文件系统类型)
DBR(也就是superblock(超级块)):
DBR(DOS BOOT RECORD,DOS引导记录),位于柱面0,磁头1,扇区1,即逻辑扇区0。DBR分为两部分:DOS引导程序和BPB(BIOS参数块)。其中DOS引导程序完成DOS系统文件(IO.SYS,MSDOS.SYS)的定位与装载,而BPB用来描述本DOS分区的磁盘信息,BPB位于DBR偏移0BH处,共13字节。它包含逻辑格式化时使用的参数,可供DOS计算磁盘上的文件分配表,目录区和数据区的起始地址,BPB之后三个字提供物理格式化(低格)时采用的一些参数。引导程序或设备驱动程序根据这些信息将磁盘逻辑地址(DOS扇区号)转换成物理地址(绝对扇区号)。
由此可见,DBR是DOS系统的专用名词,相当于类unix操作系统中的superblock(超级块)(ext2,ext3,ext4等类unix操作系统专有的文件系统格式)
故,如果我们不使用FAT等基于DOS的文件系统格式是不需要使用DBR的。在此处,是个干扰项。
superblock(超级块):包含对整个文件系统的描述,包含mount需要的信息。(对于那些MBR(与文件系统无关),DBR信息(文件系统类型有关));
vfs_kern_mount函数---->type->get_sb()
//例如对于ext2文件系统来说,get_sb()方法其实是ext2_get_sb();
//对yaffs2类型的文件系统,该函数是: yaffs2_read_super()
//对应FAT文件系统get_sb实际上是msdos_get_sb()。
step4:绑定建立各个分区的/dev/block/mmcblk0pxx节点:
int rescan_partitions(struct gendisk *disk, struct block_device*bdev)
{
…..
/* add partitions */根据获取到的分区表
for (p = 1; p < state->limit; p++) {
sector_tsize, from;
structpartition_meta_info *info = NULL;
….
part= add_partition(disk, p, from, size,
state->parts[p].flags,
&state->parts[p].info);
…...
}
…..
----》
add_partition()
{
…
///.建立节点:/dev/block/mmcblk0pxx
dname= dev_name(ddev);
printk("add_partition dname=%s partno=%d\n",dname,partno);
if(isdigit(dname[strlen(dname) - 1]))
dev_set_name(pdev, "%sp%d", dname,partno);设置分区名称:/dev/block/mmcblk0pxx
else
dev_set_name(pdev, "%s%d", dname,partno);设置disk节点:/dev/block/mmcblk0
device_initialize(pdev);
pdev->class= &block_class;
pdev->type= &part_type;
pdev->parent= ddev;
……...
}
Step5:从应用层开始mount各个分区:
分区和block设备节点建立之后,谁来mount?
是init进程,通过解析init.rc:
onfs_property:ro.mount.fs=EXT4
write /proc/bootprof"INIT:eMMC:Mount_START"
exec /sbin/e2fsck -p /emmc@android
# Mount /system rw first to give thefilesystem a chance to save a checkpoint
#mount ext4 emmc@android /system waitcommit=1,data=journal,noauto_da_alloc
mount ext4 /emmc@android /system waitcommit=1,noauto_da_alloc
# RIL need to do this before the folder/system changed to read only
chown radio system /system/etc/ril
chmod 0770 /system/etc/ril
chmod 0444 /system/etc/ril/oper.lis
# Wifi thermal need to chmod before systemis changed to read only
chown root system /system/etc/throttle.sh
chmod 0750 /system/etc/throttle.sh
mount ext4 /emmc@android /system noatime roremount wait
exec /sbin/e2fsck -pfD /emmc@usrdata
exec /sbin/tune2fs -O has_journal/emmc@usrdata
exec /system/bin/ext4_resize
mount ext4 /emmc@usrdata /data noatimenosuid nodev wait noauto_da_alloc,discard
exec /sbin/e2fsck -p /emmc@cache
exec /sbin/tune2fs -O has_journal/emmc@cache
mount ext4 /emmc@cache /cache noatimenosuid nodev wait noauto_da_alloc,discard
# mount cip partitions
exec /sbin/e2fsck -p /emmc@custom
mountext4 /emmc@custom /custom
write /proc/bootprof"INIT:eMMC:Mount_END"
Emmc 的FAT分区和外置SD卡 是由vold来mount的。
---------------------------------------------------------/////-----------------------------------------
2)MTD设备:nand flash=:
1)MTD驱动层:
mediatek/platform/mt6577/kernel/drivers/nand/nand.c
mtd_device_register(mtd,g_exist_Partition, part_num);------>
------->add_mtd_partitions(structmtd_info *mtd)---->not->add(mtd);
2)FTL和NFTL(for nand flash)层
mtdblock.c已经注册register_mtd_blktrans();
staticstruct mtd_notifier blktrans_notifier = {
.add= blktrans_notify_add,
.remove= blktrans_notify_remove,
};
not->add(mtd);---blktrans_notify_add()--------》mtdblock_add_mtd()-----》mtdblock_add_mtd()
---->add_mtd_blktrans_dev()------->register_disk()通用层,略, 后面同以上sd卡
Nand flash就没有MBRebr相关的概念了
如何mount?
只要ubi_attach_mtd然后mount即可。
1)首先init.rc
on fs_property:ro.mount.fs=UBIFS
write/proc/bootprof "INIT:NAND:Mount_START"
mount ubifsubi@system /system
# Wifi thermal needto chmod before system is changed to read only
chown root system/system/etc/throttle.sh
chmod 0750/system/etc/throttle.sh
mount ubifsubi@system /system ro remount
mount ubifsubi@userdata /data nosuid nodev
mount ubifsubi@cache /cache nosuid nodev
write/proc/bootprof "INIT:NAND:Mount_END"
2)其次:
Do_mount () 函数定义在builtins.c
{
elseif (!strncmp(source, "ubi@", 4)) {
n = ubi_attach_mtd(source + 4);//绑定mtd分区关联到ubi
if (n < 0) {
return -1;
}
sprintf(tmp, "/dev/ubi%d_0",n);
if (wait)
wait_for_file(tmp,COMMAND_RETRY_TIMEOUT);
if (mount(tmp, target, type, flags, options) <0) {//mount ubi分区
ubi_detach_dev(n);
return -1;
}
goto exit_success;
}
原文地址:http://blog.csdn.net/honour2sword/article/details/45247713