天天看點

檔案系統與存儲:MBR/EBR類型分區建立

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:

檔案系統與存儲:MBR/EBR類型分區建立

主引導記錄最開頭是第一階段引導代碼。其中的硬碟引導程式的主要作用是檢查分區表是否正确并且在系統硬體完成自檢以後将控制權交給硬碟上的引導程式(如GNUGRUB)。它不依賴任何作業系統,而且啟動代碼也是可以改變的,進而能夠實作多系統引導。

------這裡為00,應為不需要作業系統引導,隻是單系統,是以我們是可以做一個手機多個作業系統的。

3 核心什麼時候讀取MBR的分區表和建立block裝置的節點呢?以及其作用?

首先建立磁盤(比如一塊emmc,一塊sd卡,一個硬碟)的塊裝置節點,先了解兩個知識點:

1)linux核心中支援的磁盤類型:(做分區表都是根據磁盤類型來做的分區)

static int(*check_part[])(struct parsed_partitions *) = {

#ifdefCONFIG_ACORN_PARTITION_ICS

adfspart_check_ICS,

#endif

#ifdefCONFIG_ACORN_PARTITION_POWERTEC

adfspart_check_POWERTEC,

#endif

#ifdefCONFIG_ACORN_PARTITION_EESOX

adfspart_check_EESOX,

#endif

#ifdefCONFIG_ACORN_PARTITION_CUMANA

adfspart_check_CUMANA,

#endif

#ifdefCONFIG_ACORN_PARTITION_ADFS

adfspart_check_ADFS,

#endif

#ifdefCONFIG_EFI_PARTITION

efi_partition,                

#endif

#ifdefCONFIG_SGI_PARTITION

sgi_partition,

#endif

#ifdefCONFIG_LDM_PARTITION

ldm_partition,                

#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 /[email protected]

    # Mount /system rw first to give thefilesystem a chance to save a checkpoint

    #mount ext4 [email protected] /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卡是:[email protected]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, &sect);//讀取邏輯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;

}

//占用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) {

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 0x00x83EXT2類型.size=429MB CACHE

------ID表示 Partition Type 也就是分區檔案系統類型

分區類型定義在:genhd.h

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)

{

…..

根據擷取到的分區表

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 /[email protected]

    # Mount /system rw first to give thefilesystem a chance to save a checkpoint

    #mount ext4 [email protected] /system waitcommit=1,data=journal,noauto_da_alloc

    mount ext4 /[email protected] /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 /[email protected] /system noatime roremount wait

    exec /sbin/e2fsck -pfD /[email protected]

    exec /sbin/tune2fs -O has_journal/[email protected]

    exec /system/bin/ext4_resize

    mount ext4 /[email protected] /data noatimenosuid nodev wait noauto_da_alloc,discard

    exec /sbin/e2fsck -p /[email protected]

    exec /sbin/tune2fs -O has_journal/[email protected]

    mount ext4 /[email protected] /cache noatimenosuid nodev wait noauto_da_alloc,discard

    # mount cip partitions

    exec /sbin/e2fsck -p /[email protected]

mountext4 /[email protected] /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 [email protected] /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 [email protected] /system ro remount

    mount [email protected] /data nosuid nodev

    mount [email protected] /cache nosuid nodev

    write/proc/bootprof "INIT:NAND:Mount_END"

2)其次:

Do_mount () 函數定義在builtins.c

{

elseif (!strncmp(source, "[email protected]", 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;

}