天天看點

基于squashfs的gluebi檔案系統開發

 1

UBI Development

What is UBI

1. UBI不是一個Flash Translation Layer,它和FTL沒有任何關系。

2. 工作在bare flashes,它不能工作在MMC, eMMC, SD, mini-SD, micro-SD, USB flash裝置上;UBI工作于raw flash devices上,大部分出現在嵌入式裝置上。

Overview

UBI全稱"Unsorted Block Images"。它是工作于raw flash devices之上的volume管理系統,它管理一個單一physical flash裝置上的多個logical volume,能夠把I/O負載均勻的分發到flash chip上。

在一定意義上,UBI可以和Logical Volume Manager相比較。LVM映射logical sector到實體sectors,UBI映射logical eraseblcok到physical eraseblocks。但是除了映射,UBI還實作了wear-leveling和透明的I/O錯誤管理。

一個UBI volume是一組連續的logical eraseblocks(LEBs)。每一個邏輯eraseblcok可以被映射為任意的physical eraseblock。這個映射是由UBI管理,并且對上層隐藏了global wear-leveling機制(記錄per-physical eraseblock erase counters 以及透明的移動more worn-out資料到less worn-out上)。

UBI volume在建立時确定尺寸大小,也可以在日後改變(volume是dynamic re-sizable)。UBI有user-space工具可以用來管理UBI volumes。

有兩種UBI volume,dynamic和static。static volumes是隻讀的,内容由CRC-32 checksums保護;而dynamic volume是read-write,上層負責確定資料的完整性。

UBI處理壞塊,上層不需要關心壞塊管理。UBI有一個保留的physical eraseblocks pool,當一個physical eraseblock變成壞塊,UBI透明的用一個好的physical block替換這個壞塊。UBI把新出現的physical eraseblock的資料移動到好physical eraseblock。UBI volume對發生的事毫無察覺。 NAND flash在讀寫操作時可能會發生bit-flips。Bit-flips通過ECC checksums糾正,但是積累到一定資料可能會發生資料丢失。UBI會移動發生bit-flips的資料到另外一個physical eraseblocks。這個過程叫scrubbing。scrubbing過程是背景的,并且對上層透明。(以上兩點客戶要求使用UBI的主要原因)

下面是UBI主要功能的一個短清單:

1. UBI提供動态生成,删除或re-sized的volume;

2. UBI實作全flash裝置的wear-leveling(比如,你寫的一個UBI volume的邏輯塊,可以寫入flash chip的任何physical eraseblocks);

3. UBI透明的處理所有physical eraseblocks;

4. UBI通過bit-flips使得資料丢失的可能性最小化。

下面是MTD分區和UBI volumes的比較,他們有一些相似之處:

(客戶很在意這個)

1. 都是由eraseblocks組成的 - UBI volumes是邏輯eraseblocks,而MTD分區是實體的。

2. 都支援下面三個基本操作 - read, write, erase

2

但是UBI volumes和MTD分區相比有如下優點:

1. UBI volumes沒有eraseblock wear-leveling 限制,是以使用者不需要考慮這個,上層軟體實作更簡單。

2. UBI volumes沒有bad eraseblocks,這也使上層軟體不需要做壞塊管理,是以上層軟體也更簡單。

3. UBI volumes是動态的,可以建立,删除和動态resize,而MTD分區是靜态的。

4. UBI 處理bit-flips,同樣使得上層軟體更簡單。

5. UBI提供volume update操作which makes it easy to detect interrupted software updates and recover。

6. UBI 提供了原子邏輯塊修改操作,這個操作保證在修改logical eraseblock的内容過程中,發生unclean reboots不會造成資料丢失; 這對于上層軟體可能是非常有用的

7. UBI有一個un-map操作,un-maps一個邏輯eraseblock到physical eraseblock的映射。schedules the physical eraseblock for erasure and returns;這是非常快的并且使得上層軟體避免實作他們自己的機制。

現在我們使用的gluebi是一個驅動,用來在MTD裝置上模拟UBI volumes。這看起來很奇怪,因為UBI工作在MTD裝置之上,而gluebi又在UBI上模拟另外一個MTD裝置。但是這種做法可以使我們更靈活的使用各種檔案系統的特性,比如我們現在的方案是把squashfs使用gluebi的驅動寫入到一個UBI volume上。這樣不僅發揮了squashfs優點(高壓縮、隻讀),而且還能充分利用UBI的壞塊管理機制,延長nand flash的壽命。

UBI在每一個非壞physical eraseblcok的起始位置,儲存兩個小的64-byte的頭:

1.erase counter header(or EC header)包含physical eraseblock 的擦除計數和一些其它重要資訊;

2.volume identifier header(or VID header)儲存volume ID 和邏輯eraseblock(LEB)号,這兩個資訊可以确定這個PEB屬于哪個volume,以及邏輯位置; VID還包含了其他的一些資訊。

這就是為什麼eraseblocks要小于physical eraseblock ——頭占據了一部分flash空間。

所有的UBI headers 使用CRC-32保護,請查閱linux源碼中的:drivers/mtd/ubi/ubi-media.h檔案檢視header的内容。

當UBI attach到一個MTD device,首先掃描它,讀所有的headers,檢查CRC-32 checksums,存儲erase counters和logical-to-physical eraseblock映射資訊到RAM。

當UBI删除一個PEB,它寫EC header,包含增加的erase count value。這意味着PEBs一直有EC header,除了從删除結束到EC header被寫入的這個空檔,如果在這時發生了unclean reboot,造成EC header丢失。在這種情況下,UBI寫一個新的EC header,erase counter為MTD device掃描後的平均erase counter。

當UBI關聯一個PEB和LEB時,VID頭被寫入PEB中。讓我們考慮下面操作發生時,頭部發生的變化:

The LEB un-map操作就是取消LEB和PEB之間的關聯,PEB被erasure。PEB

3

被擦除,EC header被寫入,但是VID header并沒有被寫入。LEB map操作或者對un-mapped LEB的寫操作:UBI首先找到一個 PEB然後寫如VID header(EC header一定已經存在了)。注意,對于一個已經mapped LEB的寫操作,直接把資料寫入PEB而不會修改UBI headers。

UBI維護着兩個per-PEB頭因為它需要在不同的時間寫不同資訊到flash上:

在PEB删除後,EC頭立刻寫入PEB

當一個UBI關聯一個PEB和LEB時,VID頭寫入PEB

當EC header寫入PEB,UBI并不知道這個PEB要關聯的volume ID和LEB number。這就是為什麼UBI需要兩個寫操作,來寫兩個分離的headers

UBI volume table

volume table是on-flash資料結構,儲存着這個 UBI裝置上每一個volume的資訊。volume table是一個volume table records的數組,每一個record包含以下資訊:

volume size;

volume name;

volume type;

volume alignment;

update maker;

auto-resize flag;

CRC - 32 checksum for this record.

每一個record描述一個UBI volume,記錄在volume table array的index對應着這個記錄的volume ID,比如UBI volume0被volume table的record0描述。volume table内的records數目受限于LEB尺寸,但是不能大于128。這就意味着最大的volume數目不能大于128。

每當UBI volume被建立,删除,re-sized,re-named或者updated時,相應的volume table record被修改。UBI維護着兩個volume table以維護掉電發生後的可用性。

Implementation details

olume table駐留在一個特定目标的UBI volume中,叫做layout volume。這個volume包含兩個LEBS - 每一個對應一個volume table的copy。layout volume是一個内部的UBI volume,user不能看到也不能通路它。當讀或者寫layout volume時,UBI使用和正常user volumes相同的機制。

UBI在updating volume table内容時,使用下列算法。

準備volume table在記憶體中的内容

un-map layout volume的LEB0

寫新的volume table到LEB0

un-map layout volume的LEB1

寫新的voume table到LEB1

重新整理UBI工作隊列,確定un-mapped LEBs對應的PEBs被删除掉。

當attaching MTD裝置時,UBI確定兩個volume table拷貝是相同的。unclean reboot可能會導緻他們不相同,這是UBI選擇LEB0的内容copy到LEB1中(因為LEB0是新的)。如果有一個volume table被損壞了,UBI會從另外一個volume

4

table恢複過來

Minimum flash input/output unit

UBI使用flash的抽象模型。簡而言之,從UBI的角度看,flash(MTD裝置)包含着eraseblocks,這些eraseblocks可以是好的,也可以是壞的。沒有一個好的eraseblock可以讀,寫或者删除。好的eraseblocks也可以被mark為bad。

flash read和write是有最小I/O unit尺寸的,這依賴于flash類型。

NOR flash通常有最小的I/O機關為1byte,因為NOR flash通常允許讀寫單個位元組。一些NOR flash最小I/O unit可能為16或者32,比如帶ECC的NOR flash。

NAND flashed通常有512,2048或者4096 bytes的最小I/O unit,對應着NAND page size。NAND flashed存儲per-NAND page ECC到OOB area,意味着寫整個NAND page以便計算ECC code,讀整個NAND page以便校驗ECC code

最小I/O機關對MTD裝置來說是非常重要的,它影響很多事情,比如:

VID header的實體位置依賴于min. I/O unit。LEB的尺寸也依賴于它;通常來說,I/O unit越大,LEB越小,UBI flash空間開銷越大,因為EC header和VID header都占用一個I/O unit

所有對LEBs的寫都應該和min. I/O unit對齊,是min. I/O unit的倍數;reads沒有這個限制,但是要記住,MTD級的所有讀都是min. I/O unit的倍數; 隻是上層通過buffering 讀資料屏蔽了這個特點。

NAND flash sub-pages

像之前所說的,所有的UBI I/O必須是min. I/O unit,也就是NAND flash的page size。然而一些SLC NAND flashes允許更小的I/O units,這在MTD術語稱為sub-pages。不是所有的NAND都有sub-pages。

MLC NANDs 沒有sub-pages。

SLC NANDs通常有sub-pages。比如512-bytes NAND pages通常包含2x256-bytes的sub-pages,2048-byte NAND pages 包含4x256 bytes sub-pages。

SLC OneNAND chips,2048 bytes NAND page size有4x512-bytes sub-pages。

如果NAND flash支援sub-pages,那麼ECC codes的計算可以以sub-page為機關,而不是per-NAND。在這種情況下可以read和write sub-pages單獨的。

很明顯,盡管NAND chip支援sub-pages,NAND controller可能disallow。事實上,如果管理flash的controller計算ECC是per-NAND,那麼就不可能進行sub-page級的I/O操作。

使用sub-pages可以減少flash 空間開銷,比如對于128KiB eraseblock,page size是2048-bytes。如果沒有sub-pages,EC占據第一個2048,VID herder占據第二個2048,是以LEB size變成124KiB。反之支援sub-pages,UBI把EC 和VID分别放在第一和第二個512位元組,是以LEB變成了126KiB。

Sub-pages僅僅在UBI内部使用,用來存放EC VID headers,UBI API不允許使用者使用sub-page I/O unit。這是因為sub-page writes可能很慢,寫一個sub-page,驅動可能會寫整個NAND page,但是會把和本次操作無關的sub-pages都寫入0xff。這也就是說寫四個sub-pages可能比寫整個NAND pages慢四倍。是以,UBI僅對headers使用sub-pages,但是在UBI API中不存在這個概念。

UBI header position

EC header存放在PEB的偏移0處,占據64bytes;VID header位于下一個min. I/O unit或者sub-page處,占據64 bytes。例如:

5

對于NOR flash,1 byte min. I/O unit,VID header位于PEB 64處

對于沒有sub-pages的NAND flash,VID header位于第二個NAND page

對于有sub-pages的NAND flash,VID header位于第二個sub-page

Flash space overhead

UBI使用一定數量的flash space來儲存管理資訊,是以減少了flash device可供UBI使用者使用的空間,這些開銷包括:

2PEB用來存儲volume table

1 PEB保留用來wear-leveling purpose

1 PEB 保留用來atomic LEB change操作

一定資料的PEBs被用來PEB handling;這适用NAND flash,但是不适用NOR flash;保留的PEBs百分比是可配置的,預設是1%

Saving erase counters

當使用UBI時,儲存erase counters 到flash media上很重要。也就是說,每個physical eraseblock有一個叫做erase counter header用來存儲這個physical eraseblock被删除的次數。當然,保持這個erase counter不丢失也同樣重要,這意味這你删除flash和寫ubi image的工具要考慮erase counter。mtd-utils包含着ubuformat工具可以正确執行這些操作

How UBI flasher should work

以下是UBI flasher程式在删除flash或者flashing UBI images時要做的事:

首先,掃描整個flash來收集erase counter。也就是它讀每一個PEB的EC header,檢查每一個header的CRC32 checksum,保留erase counter到ram中。不需要讀取VID headers。忽略掉bad PEBS。

計算平均erase counter。當PEBs的EC header被損壞或丢失時,用平均erase counter。這樣的PEBs可能是由于unclean reboots引起的,當然數量不會太多。如果目标是删除flash,那麼每個PEB被删除,正确的EC header被寫到PEB中。EC header中應該包含增增加的erase counter。bad PEBs應該被忽略。對于NAND flashes, 當erasing或者writing時發生I/O錯誤時,PEB被标記為bad。如果目的是燒寫UBI image,那麼燒寫工具應該對每一個PEB做如下工作:

1.從UBI image中讀取這個PEB的内容到一個buffer中,buffer必須是min I/O unit倍數

2.把buffer中未填滿的部分都寫入0xff

3.删除PEB

4.改變buffer中的EC header

5.寫這個buffer到physical eraseblock

在實踐中,UBI image通常都小于UBI volume,是以flasher要正确的燒寫PEBs,正确的處理删除的PEBs.

注意:

1.在寫UBI image時,UBI image寫到哪個eraseblocks是無所謂的,比如,image的第一個eraseblock可以寫入第一個PEB,或者第二個,或者最後一個。

2.如果你實作一個産線UBI images燒寫工具。那麼flasher不需要改變EC headers,因為這是新的flash,是以每一個PEB的erase counter應該為0。這意味着産線flasher更簡單。

6

如果你的UBI image 包含UBIFS file system,并且你的flash是NAND, you may have to drop 0xff bytes the end of input PEB data. this is very importtant, although not required for all NAND flashes. Sometimes a failure to do this may result in very unpleasant problems which might be diffcult to debug later. So we recommend to always do this.

原因是UBIFS對待僅包含oxff byte的NAND pages為free。例如,假定PEB的第一個NAND page有一些資料,第二個是empty,第三個有一些資料,第四個和其他的都是空的,在這種情況下,UBIFS認為從第四個 page開始的NANDpages是空閑的,并且會向這些page寫資料。然而,如果flasher程式已經向這些pages寫了0xff,結果導緻他們被寫了兩次!然而,一些NAND flashes要求他們的NAND pages僅被寫一次,即便這些資料包含的都是0xff bytes。

flash不得不做的是drop掉所有到PEB結尾的empty NAND pages。沒必要drop掉所有的空NAND pages,僅需要最後一個。這就意味着flasher不需要掃描整個buffer,查找0xff。隻需從buffer末尾開始查找知道第一個non-0xff byte,這是非常快的。

另外一個替代方法,是在生成UBIFS檔案系統時使用mkfs.ubifs增加free space fixup選項。這将允許你的flasher不需要擔心PEBs末尾的0xff。這在你使用一個産線燒寫程式寫一個UBI image時非常有用。

Marking eraseblocks as bad

這一節是針對那些允許出現壞塊的NAND flashes和其他的flashes。UBI在兩種情況下mark physical eraseblocks為壞塊:

1. eraseblock寫操作失敗,在這種情況下,UBI把這個PEB的資料移到其他的PEB(data recovery),然後調用對這個PEB的診斷

2. 删除操作出現EIO error,在這種情況下,直接把PEB标記為壞塊。

診斷是在背景處理的,目的是檢測這個physical eraseblock是否真的壞了。寫失敗可能有多種原因,包括驅動的bugs或者上層file system 的bug(比如,檔案系統多次寫了同一個NAND page)。整個診斷過程包括如下步驟:

删除eraseblock;

讀取eraseblock,確定僅包含0xff bytes;

寫測試模式bytes;

讀取eraseblock,檢查模式串;

重複幾個其他的模式(0xA5, 0x5A, 0x00)

如果eraseblock通過了torture test,那麼不會被标記為壞塊。注意,在診斷測試過程中,bit-flip發生是把eraseblock mark為壞塊的很好理由,請參考torture_prb函數。

Scalability issues

不幸的是,UBI擴充性是和flash size線性相關的。UBI初始化時間線性依賴flash 的PEB數量。這意味着flash越大,UBI初始化的時間也越大。這個初始化時間也依賴flash的I/O速度同時輕微的依賴CPU速度,因為UBI在attach時會掃描MTD裝置 - 它讀取erase EC和VID headers從每個單個PEB;headers 很小,是以這意味對于NOR flash需要讀取128 bytes per-PEB,而對NAND flash需要讀取1~2NAND pages per-PEB;這當然遠小于JFFS2 mount MTD裝置所需的

7

讀寫資料量,所有UBI attaches MTD裝置要遠快于JFFS2在MTD裝置上 mount一個檔案系統。

UBI 為每一個EC和VID headers 計算CRC-32 checksum,這将消耗CPU,盡管這個flash I/O負載比較非常小。

Implementation details

一般來說,UBI需要三個表:

volume table:包含per-volume資訊,比如volume 尺寸,類型等;

eraseblock association(EBA) table:包含logical to physical eraseblock映射資訊;比如,當讀一個LEB時,UBI首先查找對應的PEB number,然後讀取這個PEB;

erase counter EC table:包含着每一個實體删除塊的erase counter;UBI 磨損平衡子系統使用這個表來發現PEB的 erase counter。

volume table維護在flash上。它僅僅在UBI volumes被建立,删除和re-sized時改變。這種操作很少且對速度沒有要求,UBI可以負擔一個慢的簡單的方法來管理volume table。

EBA和EC表在每次LEB被映射或者PEB被删除時都會改變,是以需要這兩個表的管理方法要快而且高效。

UBI可以在flash上,維護EBA和EC tables。這無法避免的引入了journaling, journal replay, journal commit等等。換句話說,這将引入許多複雜性。但是這可以使得EBA和EC在算法上是可擴充的。

UBI的一個需求是on-flash上格式的簡化,因為UBI作者不得不在boot-loader中讀取UBI volumes,而在boot-loader的代碼中有很嚴格的限制,基本上很難在boot-loader代碼中加入複雜的journal scanning和replay code。

是以UBI沒有在flash media上維護EBA和EC tables。而是在每次attach MTD裝置時構造它。這意味着UBI不得不掃描整個flash,從每個PEB讀取EC和VID header以便構造in-RAM EC和EBA tables。

這個設計的缺點是很差的可擴充性以及NAND flashes空間的負載(大約1.5~3%的flash空間,2KiB NAND page,128KiB eraseblock),優點是簡單以及可靠性。

當然,可以建立UBI2,維護這些表在分離的flash area。UBI2将不和UBI相容,因為他們有完全不同的on-flash格式,但是使用者接口是完全一樣的,這将保證UBI上層軟體的相容性。

Volume auto-resize

衆所周知NAND chips有一定數目的physical eraseblocks被廠商mark為壞塊。壞塊随機的分布并且資料是不同的,盡管廠商通常保證前幾個physical eraseblocks不是壞的并且壞塊的總數不會超過一定的數目。比如,一個新的256MiB的oneNAND chips保證不超過40128KiB PEBs(當然,在使用過程中,這個數量會增加)。這大概是2%的flash size ,當需要建立一個UBI image用來在産線上刷如終端使用者裝置,你應該定義所有volume的确切尺寸。但是又有total flash size是依賴于初始壞塊總數的,是以很難這麼做。解決這個問題的一個明顯方法是假定最壞的情況,當所有的chips都有一個bad PEBs的最大值。但是實際中,大部分chips僅僅有幾個bad PEBs,遠小于這個最大值。一

8

般來說,這沒什麼問題,這将增加可靠性,因為UBI一直使用裝置上的所有PEBs。另一方面UBI無論如何要保留一定數目的physical eraseblocks用做壞塊處理,預設情況下是1%。是以上面提到的OneNAND chip将有%1 PEB保留給UBI,0~2%PEB不可以被使用。

但是有另外一個替代辦法:一個volume可以有auto-resize mark,這意味着當UBI第一次運作時它的尺寸可以enlarged。在volume size調整後,UBI移除auto-resize标志後這個volume不能再re-sized。auto-resize flag存儲在volume table僅僅一個volume可以被mark為auto-resize。

UBI operations

LEB un-map

LEB un-map操作的實作是ubi_leb_unmap() kernel API。從linux 核心2.6.29開始un-map操作通過UBI_IOCEBUNMAP ioctl指令暴露給user-space程式。這個ioctl應該被UBI volume character devices調用

LEB un-map操作:

首先un-maps LEB和相應的PEB

然後排程這個PEB的擦除并傳回;

un-map不會等待擦除的結束;

PEB有UBI背景線程負責擦除

當讀取一個un-mapped LEB時,UBI傳回全0xff bytes,是以un-map操作可以被認為是一個非常快的erase operation。但是有一點需要注意。

假定你un-map LEB numL從PEB numP。因為P不是同步删除的,而是僅僅排程了删除操作,這可能在unclean reboots時給個”驚喜“;如果在P實體删除前恰好發生了reboot。在UBI再次attaches到MTD裝置上時,會發現L仍然mapped到UBI。事實上,UBI将掃描整個MTD裝置發現哪個P對應L,然後把這個映射加到EBA table。

但是一旦你寫資料到numL,或者使用LEB map操作,numL映射一個新的PEB,老資料就變成了曆史,因為即便此時發生了unclean reboot,UBI仍然會選擇numL的最新映射。

Implementation details

這一節描述在發生unclean reboot後,UBI如何區分一個LEB的older和newer的PEB,假定我們un-map LEB L到PEB P1的映射,此時UBI排程了P1的erasure。然後我們向L寫資料,意味着UBI找到另外一個PEB P2,映射L到P2,然後寫資料到P2,如果在P1被實體删除前,發生unclean reboot,我們得到了2個PEBs(P1, P2)對應同一個LEB L

為了處理這種情況,UBI維護一個全局64-bit sequence number variable。這個可變序列号每次映射一個LEB時都會增加并且存儲到PEB的VID header中,是以每一個VID header有一個唯一的序列号,序列号越大,VID越年輕。當UBI attach到MTD裝置時,初始化全局sequence number為VID headers中的最大值加1。

在上面的情況,很顯然UBI會選擇higher sequence number (P2) 然後抛棄lower sequence number(P1)

注意:如果unclean reboot發生在,磨損平衡而執行的移動一個PEB資料到另

9

外一個PEB的過程中,或者atomic LEB change操作時發生。在這種情況下不能簡單的選擇新的PEB,必須確定新的資料是否已經寫到new PEB。

LEB map

LEB map操作映射一個從前un-mapped 邏輯eraseblock到一個實體eraseblock。比如,如果要為LEB A映射,UBI首先發現相應的PEB,然後把VID header寫入PEB,然後修正in-memory EBA table。VID header将指向LEB A,這個操作完成後,所有到LEB A的操作最終都會到mapped PEB

LEB映射操作是通過ubi_leb_map() UBI kernel API函數,或者通過UBI_IOCEBMAP ioctl

LEB map操作接受dtype類型參數,這個參數建議LEB将儲存的資料類型,dtype有如下類型:

UBI_SHORTTERM - LEB存儲的是短期資料,也就是這個資料很快就會被擦除;UBI将映射LEB到一個low erase counter的PEB。

UBI_SHORTTERM - LEB存儲的是長期資料,UBI映射這個LEB到high erase counter的PEB。

UBI_UNKNOWN - 在大多數情況下使用,當你無法确定是否為長期或者短期

記住dtype僅僅是一個hint。如果無法确定,請使用UBI_UNKNOWN。

Stealth Project設計流程:

1.将我們生成的squashfs使用如下配置打包成gluebi驅動能工作的檔案:

2.設定bootargs:root=/dev/mtdblock8 ubi.mtd=5 rootfstype=squashfs

root=/dev/mtdblock8 中的8為linux啟動之後ubiattach後建立的新分區,在我們規劃的最後一個分區之後,可以使用cat /proc/mtd檢視。

ubi.mtd=5 其中5為我們規劃分區中存儲application的分區号

rootfstype 為實際的檔案系統,即源檔案系統類型

3.修改loader更新讀寫:

loader更新的時候,考慮到UBI的bad block管理以及啟動掃描flash等特性,我們不采取直接更新gluebi volume的方式,而是采用往建立好的ubi volume上面寫源檔案系統的方式來操作。同時在loader校驗資料的時候直接按ubi volume來讀取和寫入資料。

a. format application分區為ubi。

skyapi_syscall_system(SK_SYSCALL_MODE_SYNC,"ubiformat /dev/mtd5 -y", 0);

b. attach MTD device to UBI

skyapi_syscall_system(SK_SYSCALL_MODE_SYNC,"ubiattach /dev/ubi_ctrl -m 5", 0);

mode=ubi

image=$UBIIMG ##檔案源:rootfs.squash

vol_id=0

vol_size=${vol_size}MiB ##vol_size為自動擷取的squashfs檔案大小

vol_type=dynamic

vol_name=rootfs

vol_flags=autoresize

10

c. 建立一個名為rootfs的volume,并使volume size盡量大

skyapi_syscall_system(SK_SYSCALL_MODE_SYNC,"ubimkvol /dev/ubi0 -N rootfs -m", 0);

d.使用以下interface将更新資料寫入volume:

e.當要從flash上讀出資料來校驗時,使用以下interface read

static int ubi_write(char *ubi_vol, unsigned char *buffer, unsigned int size)

{

int fd = -1, ret;

long long bytes;

fd = open(ubi_vol, O_RDWR);

if (fd < 0)

{

printf("ERROR:[ubi_write] Open %s fail \n",*ubi_vol);

return 0;

}

bytes = size;

if (ioctl(fd, UBI_IOCVOLUP, &bytes))

{

close(fd);

printf("ERROR:[ubi_write] ioctl %s fail \n",*ubi_vol);

return 0;

}

ret = write(fd, buffer, size);

close(fd);

return ret;

}

static int ubi_read(char *ubi_vol, unsigned char *buffer, unsigned int size)

{

int fd = -1, ret;

fd = open(ubi_vol, O_RDONLY);

if (fd < 0)

{

printf("ERROR:[ubi_read] Open %s fail \n",*ubi_vol);

return 0;

}

ret = read(fd, buffer, size);

close(fd);

return ret;

}

11

注:在對UBI的attach操作之後,進行讀寫完一定要deattch,以保證操作流程的完整性。

附:User-space tools

[email protected]:~# ubiattach -help

ubiattach version 1.5.0 - a tool to attach MTD device to UBI.

Usage: ubiattach [<UBI control device node file name>]

[-m <MTD device number>] [-d <UBI device number>] [-p <path to device>]

[--mtdn=<MTD device number>] [--devn=<UBI device number>]

[--dev-path=<path to device>]

UBI control device defaults to /dev/ubi_ctrl if not supplied.

Example 1: ubiattach -p /dev/mtd0 - attach /dev/mtd0 to UBI

Example 2: ubiattach -m 0 - attach MTD device 0 (mtd0) to UBI

Example 3: ubiattach -m 0 -d 3 - attach MTD device 0 (mtd0) to UBI

and create UBI device number 3 (ubi3)

-d, --devn=<number> the number to assign to the newly created UBI device

(assigned automatically if this is not specified)

-p, --dev-path=<path> path to MTD device node to attach

-m, --mtdn=<number> MTD device number to attach (alternative method, e.g

if the character device node does not exist)

-O, --vid-hdr-offset VID header offset (do not specify this unless you really

know what you are doing, the default should be optimal)

-h, --help print help message

-V, --version print program version

---------------------------------------------------------------------

[email protected]:~# ubidetach -help

ubidetach version 1.4.8 - tool to remove UBI devices (detach MTD devices from UBI)

Usage: ubidetach [<UBI control device node file name>]

[-d <UBI device number>] [-m <MTD device number>] [-p <path to

12

device>]

[--devn=<UBI device number>] [--mtdn=<MTD device number>]

[--dev-path=<path to device>]

UBI control device defaults to /dev/ubi_ctrl if not supplied.

Example 1: ubidetach -p /dev/mtd0 - detach MTD device /dev/mtd0

Example 2: ubidetach -d 2 - delete UBI device 2 (ubi2)

Example 3: ubidetach -m 0 - detach MTD device 0 (mtd0)

-d, --devn=<UBI device number> UBI device number to delete

-p, --dev-path=<path to device> or alternatively, MTD device node path to detach

-m, --mtdn=<MTD device number> or alternatively, MTD device number to detach

-h, --help print help message

-V, --version print program version

---------------------------------------------------------------------

[email protected]:~# ubimkvol -help

ubimkvol version 1.5.0 - a tool to create UBI volumes.

Usage: ubimkvol <UBI device node file name> [-h] [-a <alignment>] [-n <volume ID>] [-N <name>]

[-s <bytes>] [-S <LEBs>] [-t <static|dynamic>] [-V] [-m]

[--alignment=<alignment>][--vol_id=<volume ID>] [--name=<name>]

[--size=<bytes>] [--lebs=<LEBs>] [--type=<static|dynamic>] [--help]

[--version] [--maxavsize]

Example: ubimkvol /dev/ubi0 -s 20MiB -N config_data - create a 20 Megabytes volume

named "config_data" on UBI device /dev/ubi0.

-a, --alignment=<alignment> volume alignment (default is 1)

-n, --vol_id=<volume ID> UBI volume ID, if not specified, the volume ID

will be assigned automatically

-N, --name=<name> volume name

-s, --size=<bytes> volume size volume size in bytes, kilobytes (KiB)

or megabytes (MiB)

-S, --lebs=<LEBs count> alternative way to give volume size in

13

logical

eraseblocks

-m, --maxavsize set volume size to maximum available size

-t, --type=<static|dynamic> volume type (dynamic, static), default is dynamic

-h, -?, --help print help message

-V, --version print program version

---------------------------------------------------------------------

[email protected]:~# ubiformat -help

ubiformat version 1.5.0 - a tool to format MTD devices and flash UBI images

Usage: ubiformat <MTD device node file name> [-s <bytes>] [-O <offs>] [-n]

[-f <file>] [-S <bytes>] [-e <value>] [-x <num>] [-y] [-q] [-v] [-h] [-v]

[--sub-page-size=<bytes>] [--vid-hdr-offset=<offs>] [--no-volume-table]

[--flash-image=<file>] [--image-size=<bytes>] [--erase-counter=<value>]

[--ubi-ver=<num>] [--yes] [--quiet] [--verbose] [--help] [--version]

Example 1: ubiformat /dev/mtd0 -y - format MTD device number 0 and do

not ask questions.

Example 2: ubiformat /dev/mtd0 -q -e 0 - format MTD device number 0,

be quiet and force erase counter value 0.

-s, --sub-page-size=<bytes> minimum input/output unit used for UBI

headers, e.g. sub-page size in case of NAND

flash (equivalent to the minimum input/output

unit size by default)

-O, --vid-hdr-offset=<offs> offset if the VID header from start of the

physical eraseblock (default is the next

minimum I/O unit or sub-page after the EC

header)

-n, --no-volume-table only erase all eraseblock and preserve erase

counters, do not write empty volume table

-f, --flash-image=<file> flash image file, or '-' for stdin

-S, --image-size=<bytes> bytes in input, if not reading from file

-e, --erase-counter=<value> use <value> as the erase counter value for all

14

eraseblocks

-x, --ubi-ver=<num> UBI version number to put to EC headers

(default is 1)

-Q, --image-seq=<num> 32-bit UBI image sequence number to use

(by default a random number is picked)

-y, --yes assume the answer is "yes" for all question

this program would otherwise ask

-q, --quiet suppress progress percentage information

-v, --verbose be verbose

-h, -?, --help print help message

-V, --version print program version

---------------------------------------------------------------------

[email protected]:~# ubinfo -help

ubinfo version 1.4.8 - a tool to print UBI information.

Usage 1: ubinfo [-d <UBI device number>] [-n <volume ID> | -N <volume name>] [-a] [-h] [-V]

[--vol_id=<volume ID> | --name <volume name>] [--devn <UBI device number>] [--all] [--help] [--version]

Usage 2: ubinfo <UBI device node file name> [-a] [-h] [-V] [--all] [--help] [--version]

Usage 3: ubinfo <UBI volume node file name> [-h] [-V] [--help] [--version]

Example 1: ubinfo - (no arguments) print general UBI information

Example 2: ubinfo -d 1 - print information about UBI device number 1

Example 3: ubinfo /dev/ubi0 -a - print information about all volumes of UBI

device /dev/ubi0

Example 4: ubinfo /dev/ubi1_0 - print information about UBI volume /dev/ubi1_0

Example 5: ubinfo -a - print all information

-d, --devn=<UBI device number> UBI device number to get information about

-n, --vol_id=<volume ID> ID of UBI volume to print information about

-N, --name=<volume name> name of UBI volume to print information about

-a, --all print information about all devices and volumes,

or about all volumes if the UBI device was

15

specified

-h, --help print help message

-V, --version print program version

---------------------------------------------------------------------

[email protected]:~# mtdinfo -help

mtdinfo version 1.4.8 - a tool to print MTD information.

Usage: mtdinfo <MTD node file path> [--map | -M] [--ubi-info | -u]

mtdinfo --all [--ubi-info | -u]

mtdinfo [--help | --version]

Options:

-u, --ubi-info print what would UBI layout be if it was put

on this MTD device

-M, --map print eraseblock map

-a, --all print information about all MTD devices

Note: `--all' may give less info per device

than, e.g., `mtdinfo /dev/mtdX'

-h, --help print help message

-V, --version print program version

Examples:

mtdinfo /dev/mtd0 print information MTD device /dev/mtd0

mtdinfo /dev/mtd0 -u print information MTD device /dev/mtd0

and include UBI layout information

mtdinfo -a print information about all MTD devices

---------------------------------------------------------------------

[email protected]:~# ubiupdatevol -help

ubiupdatevol version 1.4.8 - a tool to write data to UBI volumes.

Usage: ubiupdatevol <UBI volume node file name> [-t] [-s <size>] [-h] [-V] [--truncate]

[--size=<size>] [--help] [--version] <image file>

Example 1: ubiupdatevol /dev/ubi0_1 fs.img - write file "fs.img" to UBI volume /dev/ubi0_1

Example 2: ubiupdatevol /dev/ubi0_1 -t - wipe out UBI volume /dev/ubi0_1

-t, --truncate truncate volume (wipe it out)

16

-s, --size=<bytes> bytes in input, if not reading from file

-h, --help print help message

-V, --version print program version

繼續閱讀