0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Tina Linux存儲開發(fā)指南

嵌入式Linux那些事 ? 來源:嵌入式Linux那些事 ? 作者:嵌入式Linux那些事 ? 2023-03-06 11:10 ? 次閱讀

Tina Linux 存儲開發(fā)指南

1 概述

1.1 編寫目的

介紹TinaLinux Flash,分區(qū),文件系統(tǒng)等存儲相關(guān)信息,指導(dǎo)方案的開發(fā)定制。

1.2 適用范圍

Tina V3.0 及其后續(xù)版本。

1.3 相關(guān)人員

適用于TinaLinux 平臺的客戶及相關(guān)技術(shù)人員。

2 分區(qū)管理

2.1 分區(qū)配置文件

在全志平臺中,通過sys_partition.fex 文件配置分區(qū)。在Tina 中,可以在lunch 選擇方案后,通過命令cconfigs 快速跳轉(zhuǎn)到分區(qū)配置目錄,通常情況下,其路徑如下。

tina/device/config/chips/<芯片編號>/configs/<方案名>/linux/sys_partition.fex

tina/device/config/chips/<芯片編號>/configs/<方案名>/linux/sys_partition_nor.fex

#以上路徑不存在,則使用

tina/device/config/chips/<芯片編號>/configs/<方案名>/sys_partition.fex

?

說明 sys_partition_nor.fex 適用于nor。 sys_partition.fex 適用于rawnand/spinand/mmc。

2.2 分區(qū)配置格式

以rootfs 分區(qū)為例:

[partition]

name = rootfs

size = 20480

downloadfile = "rootfs.fex"

user_type = 0x8000

每個分區(qū)以[partition] 標識,分區(qū)屬性及其意義如下表。

屬性 含義 必選 備注
name 分區(qū)名 Y
size 分區(qū)大小 Y 單位:扇區(qū)(512B),注1
downlodefile 分區(qū)燒入的鏡像文件 N 注2
verify 量產(chǎn)后校驗標識 N (默認)1:使能;0:禁用,注3
user_type 分區(qū)屬性 N 注 4
keydata 量產(chǎn)時是否擦除本分區(qū) N 0x8000:使用;其他無效

說明:

最后一個分區(qū)(UDISK),不設(shè)置size,表示分配所有剩余空間。

downloadfile 支持絕對路徑和相對路徑,相對于tina/out/<方案名>/image。

verify 決定是否校驗downloadfile 中指定的鏡像,若為ext4 稀疏鏡像,務(wù)必禁用。

歷史遺留,目前只對UBI 方案有效。bit0為1 時,表示創(chuàng)建靜態(tài)卷,反之為動態(tài)卷。

創(chuàng)建downloadfile 的資源鏡像包看章節(jié)分區(qū)資源鏡像文件。 [partition] 標識用戶空間的邏輯分區(qū),在UBI 方案中,表現(xiàn)為UBI 卷。此外,在sys_partiton.fex中存在特殊的配置MBR,用于配置MBR 空間大小,此配置在UBI 方案中無效。例如:

[mbr]

size = 2048

MBR 分區(qū)以Kbyte 為單位,對用戶不可見,屬于隱藏空間,其大小也必須滿足對齊原則。

警告 一般情況下,不建議用戶修改mbr 分區(qū)的大小。

2.3 常見分區(qū)及其用途

分區(qū)名 用途 大小 備注
boot 內(nèi)核鏡像分區(qū) 比實際鏡像等大或稍大即可
rootfs 根文件系統(tǒng)鏡像 比實際鏡像等大或稍大即可
extend 擴展系統(tǒng)鏡像 參考OTA 文檔 參考OTA 文檔僅小容量OTA 方案使用
recovery 恢復(fù)系統(tǒng)鏡像 參考OTA 文檔 僅限大容量OTA 方案使用
private 存儲SN、MAC 等數(shù)據(jù) 使用默認大小即可 量產(chǎn)時默認不丟失
misc 存儲系統(tǒng)狀態(tài)、刷機狀態(tài) 使用默認大小即可
env 存放Uboot 使用的數(shù)據(jù) 使用默認大小即可
pstore 內(nèi)核奔潰日志轉(zhuǎn)存分區(qū) 使用默認大小即可
rootfs_data 根目錄覆蓋分區(qū) 根據(jù)需求配置 注1
UDISK 用戶數(shù)據(jù)分區(qū) 不需要配置大小 注2

說明:

rootfs_data 分區(qū)通過overlayfs 覆蓋根文件系統(tǒng),以支持squashfs 根文件系統(tǒng)的可寫,此時對根文件系統(tǒng)寫入的數(shù) 據(jù)實際是保存到rootfs_data 分區(qū),因此rootfs_data 分區(qū)的容量標識著根文件系統(tǒng)最大可寫數(shù)據(jù)量。

UDISK 作為最后一個分區(qū),不需要設(shè)置size,表示分配剩余所有空間給UDISK。

2.4 分區(qū)大小與對齊

分區(qū)大小的對齊要求與不同介質(zhì)(nor/nand/mmc)、不同存儲方案相關(guān)。不按對齊要求配置,可能出現(xiàn)文件系統(tǒng)異常,分區(qū)邊界數(shù)據(jù)丟失等現(xiàn)象。對齊規(guī)則如下表。

介質(zhì) 對齊大小 備注
nor 64K 對齊物理擦除塊大小,注1
(nftl) spinand 驅(qū)動超級塊大小 注2
(ubi) spinand 2 × 物理塊- 2 × 頁 注3
rawnand 驅(qū)動超級塊大小 與物料相關(guān),16M 對齊可基本兼容
emmc 16M 與物料相關(guān),16M 對齊可基本兼容

說明

nor 的擦除塊常見為64K,即在sys_partition_nor.fex 中分區(qū)size 進行128 對齊。在id 表配置為4K 擦除且使能內(nèi)核CONFIG_MTD_SPI_NOR_USE_4K_SECTORS 時,也可使用4K 對齊。推薦使用默認64K 對齊。

在常見的128M Spi Nand 中,為256K 對齊,即在sys_partition.fex 中分區(qū)size 進行512 對齊。

在常見的128M Spi Nand 中,需要和邏輯擦除塊(super block)對齊,1 個super block 包含兩個物理擦除塊,常見的物理擦除塊128K,1 個邏輯的超級塊為256K,但是需要使用每個物理塊的第一個page(2K)來作為ubi 所需的信息頭部,所以實際的為(256k-2*2k),為252K 對齊,即在sys_partition.fex 中分區(qū)size 進行504 對齊。

警告 如果分區(qū)不對齊,可能會出現(xiàn)以下情況。 ? nor/rawnand/spinand 可能會導(dǎo)致數(shù)據(jù)丟失。 ? mmc 不會造成數(shù)據(jù)丟失,但可能導(dǎo)致性能損失。

如果分區(qū)使用ubifs 文件系統(tǒng),分區(qū)最小為5M ,否則大概率提示空間不夠。 如果分區(qū)使用ext4 文件系統(tǒng),分區(qū)最小為3M ,否則無法形成日志,會有掉電變磚風(fēng)險。

技巧

在ext4 與日志章節(jié)有描述判斷創(chuàng)建的ext4 文件系統(tǒng)是否支持日志的方法。

在分區(qū)資源鏡像文件章節(jié)指導(dǎo)如何創(chuàng)建帶文件系統(tǒng)的資源鏡像、分區(qū)大小、文件系統(tǒng)大小、文件大小更多內(nèi)容,請參考總?cè)萘空f明。

2.5 分區(qū)與文件系統(tǒng)

常見的分區(qū)與文件系統(tǒng)對應(yīng)關(guān)系如下表。

分區(qū)名 默認文件系統(tǒng) 文件系統(tǒng)特性 備注
rootfs squashfs 壓縮、只讀 為了安全,根文件系統(tǒng)建議只讀
rootfs_data jffs2/ext4/ubifs 可寫 注1
UIDSK jffs2/ext4/ubifs 可寫 注1
boot vfat 裸數(shù)據(jù)分區(qū),部分方案為vfat
private vfat 注2
misc none 裸數(shù)據(jù)分區(qū)
env none 裸數(shù)據(jù)分區(qū)
pstore pstore 轉(zhuǎn)存奔潰日志

說明

可寫的分區(qū),nor 為jffs2;UBI 方案為ubifs;其他為ext4。

private 默認為裸數(shù)據(jù),使用dragonSN 工具燒錄后會成為vfat 文件系統(tǒng)。

只讀文件系統(tǒng)推薦使用squashfs??蓪懳募到y(tǒng),nor 推薦jffs2,UBI 方案推薦ubifs,其他推薦ext4。更多文件系統(tǒng)信息,請參考文件系統(tǒng)支持情況。

2.6 分區(qū)資源鏡像文件

在sys_partition.fex中通過downloadfile 指定需要燒錄到分區(qū)的資源鏡像文件。大多數(shù)情況下,資源鏡像文件都構(gòu)建在文件系統(tǒng)上,通過某些命令實現(xiàn)把系統(tǒng)需要的文件,例如音頻文件、視頻文件等資源,打包成一個帶文件系統(tǒng)的鏡像包,并在燒錄時把鏡像包燒寫入存儲 介質(zhì)。 創(chuàng)建不同文件系統(tǒng)鏡像的命令不一樣,常見有以下幾種:

文件系統(tǒng) 創(chuàng)建鏡像命令
vfat mkfs.vfat
ext4 make_ext4fs
ubifs mkfs.ubifs
squashfs mksquashfs4

為了最大程度利用空間,一般會使文件系統(tǒng)等于物理分區(qū)大小,即創(chuàng)建文件系統(tǒng)時使用分區(qū)表劃定的分區(qū)大小來創(chuàng)建。

如果不希望硬編碼大小,則可在打包時從分區(qū)表獲得大小,再傳給文件系統(tǒng)創(chuàng)建工具,具體的實現(xiàn)可以參考tina/scripts/pack_img.sh 中的make_data_res() 和make_user_res() 等函數(shù)。

2.6.1 創(chuàng)建squashfs 鏡像

生成squashfs 的命令,可參考編譯過程的log 得到,或者在網(wǎng)上搜索squashfs 生成方式。 例如在scripts/pack_img.sh 中定義一個函數(shù)

function make_user_squash()

{

local SOURCE_DATE_EPOCH=$(${PACK_TOPDIR}/scripts/get_source_date_epoch.sh)

# 這一行指定要打包到文件系統(tǒng)的數(shù)據(jù)

local USER_PART_FILE_PATH=${PACK_TOPDIR}/target/allwinner/方案名字/user_sq

local USER_PART_SQUASHFS=${PACK_TOPDIR}/out/${PACK_BOARD}/image/user_sq.squashfs

local USER_PART_DOWNLOAD_FILE=${PACK_TOPDIR}/out/${PACK_BOARD}/image/user_sq.fex

cd ${ROOT_DIR}/image

[ -e $USER_PART_FILE_PATH ] && {

#這里用了gzip,需要更高壓縮率可改成xz

${PACK_TOPDIR}/out/host/bin/mksquashfs4 $USER_PART_FILE_PATH $USER_PART_SQUASHFS

-noappend -root-owned -comp gzip -b 256k

-processors 1 -fixed-time $SOURCE_DATE_EPOCH

dd if=${USER_PART_SQUASHFS} of=${USER_PART_DOWNLOAD_FILE} bs=128k conv=sync

}

cd -

}

找個地方調(diào)用下即可。 這里不用傳入分區(qū)表的原因是,制作squashfs 不需要指定文件系統(tǒng)大小,只讀的文件系統(tǒng)大小完全取決于文件內(nèi)容。

2.6.2 創(chuàng)建vfat 鏡像

mkfs.vfat <輸出鏡像> -C <文件系統(tǒng)大小>

mcopy -s -v -i <輸出鏡像> <資源文件所在文件夾>/* ::

可參考pack_img.sh(在其中搜索mkfs.vfat 找到相關(guān)代碼)。

2.6.3 創(chuàng)建ext4 鏡像

使用tina/out/host/bin/make_ext4fs 創(chuàng)建ext4 鏡像,推薦的使用方法如下:

make_ext4fs -l <文件系統(tǒng)大小> -b <塊大小> -m 0 -j <日志塊個數(shù)> <輸出的鏡像保存路徑> <資源文件所在文件

夾>

其中, ? -m 0: 表示不需要要為root 保留空間。 ? -j < 日志塊個數(shù)>: 日志總大小為塊大小* 日志塊個數(shù)。

例如:

make_ext4fs -l 20m -b 1024 -m 0 -j 1024 ${ROOT_DIR}/img/data.fex ${FILE_PATH}

如果空間不夠大,會顯示類似如下的錯誤日志:

$ ./bin/make_ext4fs -l 10m -b 1024 -m 0 -j 1024 data.fex ./bin

Creating filesystem with parameters:

Size: 10485760

Block size: 1024

Blocks per group: 8192

Inodes per group: 1280

Inode size: 256

Journal blocks: 1024

Label:

Blocks: 10240

Block groups: 2

Reserved blocks: 0

Reserved block group size: 63

error: ext4_allocate_best_fit_partial: failed to allocate 7483 blocks, out of space?

上述錯誤中,資源文件達到100+M,但是創(chuàng)建的鏡像-l 指定的大小只有10M,導(dǎo)致空間不夠而報錯。只需要擴大鏡像大小即可。 如需使用分區(qū)大小作為文件系統(tǒng)大小,可參考pack_img.sh(在其中搜索make_ext4fs 找到相關(guān)代碼)。

技巧 鏡像大小可以根據(jù)分區(qū)大小設(shè)置,也可以根據(jù)資源大小設(shè)置,后通過稀疏和resize 處理,即可保證最短燒錄時間和動態(tài)匹配分區(qū)大小。見稀疏ext4 鏡像和動態(tài)resize 章節(jié)。

2.6.3.1 稀疏ext4 鏡像

如果資源文件只有10M,但創(chuàng)建了100M 的鏡像文件,導(dǎo)致燒錄100M 的文件拖慢了燒錄速度。此時可以采用稀疏ext4 鏡像。

tina/out/host/bin/img2simg <原鏡像> <輸出鏡像>

稀疏鏡像的原理,類似與把文件系統(tǒng)沒用到的無效數(shù)據(jù)全刪掉,把文件系統(tǒng)壓縮??蓞⒖紁ack_img.sh 中的函數(shù)sparse_ext4() 的實現(xiàn)與運用。

2.6.3.2 動態(tài)resize

如果擔(dān)心創(chuàng)建鏡像時指定的大小與實際的分區(qū)大小不匹配,可以在設(shè)備啟動后執(zhí)行resize2fs 動態(tài)調(diào)整文件系統(tǒng)的大小。 例如:

resize2fs /dev/by-name/UDISK

命令后不指定大小,則默認為分區(qū)大小。通過這方法可以讓打包鏡像創(chuàng)建的文件系統(tǒng)大小匹配分區(qū)大小。 此命令可直接寫入啟動腳本,在掛載前執(zhí)行。每次啟動都執(zhí)行一遍不會有不良影響。

2.6.4 創(chuàng)建ubifs 鏡像

使用tina/out/host/bin/make.ubifs 創(chuàng)建ubifs 鏡像,推薦的使用方法如下:

mkfs.ubifs -x <壓縮方式> -b <超級頁大小> -e <邏輯擦除塊大小> -c <最大邏輯擦除塊個數(shù)> -r <資源文件所在 文件夾> -o <輸出的鏡像保存路徑> 壓縮方式可選none lzo zlib, 壓縮率zlib > lzo > none 對常見的128MB spinand,1 page = 2048 bytes, 1 block = 64 page, 則 超級頁大小為2048 * 2 = 4096 邏輯擦除塊大小為2048 * 2 * 64 = 262144 最大邏輯擦除塊個數(shù),可簡單設(shè)置為一個較大的值,例如128MB / ( 2048 bytes * 2 * 64) = 512 則最終的命令為: mkfs.ubifs -x zlib -b 4096 -e 262144 -c 512 -r ${FILE_PATH} -o ${ROOT_DIR}/img/data_ubifs. fex

2.7 根文件系統(tǒng)改用ubifs

使用suqashfs + overlayfs(ubifs) 方案實現(xiàn)根目錄可寫,但是ubifs 會占用大量的空間存放元數(shù)據(jù),造成空間浪費。理論上,UBIFS 可直接作為根文件系統(tǒng),其穩(wěn)定性和可壓縮性足夠保證安全和提高空間利用率。

警告 請謹慎使用,UBIFS 作為根文件系統(tǒng)只是理論安全,全志暫無量產(chǎn)方案佐證。

修改步驟如下:

執(zhí)行cdevice ,修改跳轉(zhuǎn)目錄下的Makefile 在FEATURES 變量中添加ubifs 和nand

執(zhí)行make menuconfig 使能在Target Image 頁面下使能ubifs 在Utilities->mtdutils 頁面中使能mtd-utils-mkfs.ubifs

執(zhí)行cconfigs ,修改跳轉(zhuǎn)目錄下的env-XXX.cfg 把rootfstype 值改為ubifs 在對應(yīng) 存儲介質(zhì)的setargs_XXX 的root 值改為root=ubi0_X ,其中X 表示對應(yīng)的第幾個分區(qū);刪除 ubi.block 項。

執(zhí)行make kernel_menuconfig,取消使能overlayfs

在sys_partition.fex 中刪除rootfs_data 分區(qū)

2.8 總?cè)萘空f明

在全志的驅(qū)動中,會預(yù)留一部分空間存儲特殊數(shù)據(jù),因此提供給用戶分區(qū)空間不等于實際Flash總?cè)萘俊?/p>

分區(qū)表可用空間= flash總?cè)萘? 保留空間

不同存儲介質(zhì),其保留空間會有差異。

存儲介質(zhì) 保留空間 備注
nor 512K 對應(yīng)bootloader 分區(qū),包含分區(qū)表,boot0,uboot
(nftl) nand 總?cè)萘康?/10~1/8 注1,注2
(UBI) spinand
mmc 20M 包含boot0,uboot 等

最新spinor 的存儲分布, 隱藏空間1MB,其中mbr 占用16KB,mbr 往前共占用1008KB,uboot 往前共占用64KB,其中包括boot0 和uboot 中間4KB 的預(yù)留區(qū)域,這段區(qū)域用于存放flash 的spi 采樣點等信息。

|boot0|4kb|uboot|mbr |分區(qū)表可見的用戶分區(qū)|

說明

(nftl) nand 的隱藏空間對用戶不可見,包含分區(qū)表MBR 分區(qū),boot0,uboot, 磨損算法、壞塊保留等。對128M 的 spinand 來說,用戶可用空間一般為108M。

由于出廠壞塊的存在,可能會導(dǎo)致每一顆Flash 呈現(xiàn)的用戶可用總?cè)萘坎煌?,但全?nftl) nand 保證總?cè)萘坎粫S著使 用過程出現(xiàn)壞塊而導(dǎo)致可用容量減少。

UBI 方案中,除了必要的mtd 物理分區(qū)之外(boot0/uboot/pstore 等),其余空間劃分到一個mtd 物理分區(qū)。在此 mtd 物理分區(qū)中根據(jù)sys_partition.fex 的劃分構(gòu)建ubi 卷。UBI 的機制,每個塊都需要預(yù)留1~2 個頁作為EC/VID 頭。因此可用容量會小于mtd 物理分區(qū)容量。

對于非ubi 方案,用戶空間可通過下面的命令查看用戶可用分區(qū)大小,大小單位為KB。

# cat /proc/partitions major minor #blocks name 93 0 112384 nand0 93 1 256 nand0p1 93 2 5120 nand0p2 93 3 10240 nand0p3 93 4 10240 nand0p4 93 5 7168 nand0p5 93 6 64 nand0p6 93 7 512 nand0p7 93 8 256 nand0p8 93 9 76463 nand0p9

如例子中的結(jié)果,nand0 分為多個分區(qū),每個nand0px 對應(yīng)一個分區(qū)表中的分區(qū)。對于ubi 方案,整個nand 分為若干mtd??墒褂靡韵旅畈榭?/p>

# cat /proc/mtd dev: size erasesize name mtd0: 00100000 00040000 "boot0" mtd1: 00300000 00040000 "uboot" mtd2: 00100000 00040000 "secure_storage" mtd3: 00080000 00040000 "pstore" mtd4: 07a80000 00040000 "sys"

如例子中的結(jié)果,整個nand 分為5 個mtd。 ? mtd0 存放boot0, size 1 MB ? mtd1 存放uboot, size 3 MB ? mtd2 存放secure_storage, size 1 MB ? mtd3 存放pstore, size 512 KB ? mtd4 則會進一步分為多個ubi 卷,占用剩余所有空間

以上所有mtd 的size 相加,應(yīng)該恰好等于flash 總size。分區(qū)表中定義的每個邏輯分區(qū),會對應(yīng)mtd sys 上的ubi 卷??墒褂靡韵旅畈榭?/p>

# ubinfo -a UBI version: 1 Count of UBI devices: 1 UBI control device major/minor: 10:51 Present UBI devices: ubi0 ubi0 Volumes count: 12 Logical eraseblock size: 258048 bytes, 252.0 KiB Total amount of logical eraseblocks: 489 (126185472 bytes, 120.3 MiB) Amount of available logical eraseblocks: 0 (0 bytes) Maximum count of volumes 128 Count of bad physical eraseblocks: 1 Count of reserved physical eraseblocks: 19 Current maximum erase counter value: 3 Minimum input/output unit size: 4096 bytes Character device major/minor: 247:0 Present volumes: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 Volume ID: 0 (on ubi0) Type: static Alignment: 1 Size: 1 LEBs (258048 bytes, 252.0 KiB) Data bytes: 258048 bytes (252.0 KiB) State: OK Name: mbr Character device major/minor: 247:1 ----------------------------------- Volume ID: 1 (on ubi0) Type: dynamic Alignment: 1 Size: 2 LEBs (516096 bytes, 504.0 KiB) State: OK Name: boot-resource Character device major/minor: 247:2 ----------------------------------- ... #此處省略若干卷 ----------------------------------- Volume ID: 11 (on ubi0) Type: dynamic Alignment: 1 Size: 242 LEBs (62447616 bytes, 59.6 MiB) State: OK Name: UDISK Character device major/minor: 247:12

如例子中的結(jié)果 ? volume 0 為mbr, 占1 LEBs(252 KB),對應(yīng)分區(qū)表本身 ? volume 1 為boot-resource, 占2 LEBs(504 KB),對應(yīng)分區(qū)表中第一個分區(qū) ? … ? volume 11 為UDISK, 占242 LEBs(59.8 MB),對應(yīng)分區(qū)表中最后一個分區(qū) 常見的關(guān)于容量的疑惑與解答。

問:df 查看UDISK 分區(qū)大小,明明分區(qū)有50M,怎么顯示總大小只有40+M? 答:df 顯示的是文件系統(tǒng)的大小,文件系統(tǒng)本身需要額外的空間存儲元數(shù)據(jù),導(dǎo)致實際可用空間 會比分區(qū)大小略少。

問:df 查看boot 分區(qū)大小,為什么顯示的大小比實際分區(qū)大? 答:boot 分區(qū)是通過鏡像燒寫的形式格式化的fs,創(chuàng)建鏡像時設(shè)置的文件系統(tǒng)的大小并不等于分 區(qū)實際大小,導(dǎo)致此時文件系統(tǒng)大小并不能體現(xiàn)實際分區(qū)大小。

問:df 查看squashfs 使用率總是100%? 答:squashfs 是只讀壓縮文件系統(tǒng),文件系統(tǒng)大小取決于總文件大小,使用率總是100%,跟分 區(qū)大小無關(guān)。

說明

文件大小 我們常說的文件大小,指的是文件內(nèi)容有多少字節(jié)。但在一個文件系統(tǒng)中,空間分配以塊為單位,必然會造成內(nèi)部碎片。假 設(shè)塊為4K,如果文件大小為1K,文件系統(tǒng)依然為其分配4K 的塊,就會造成3K 的空間浪費。

文件系統(tǒng)大小 文件系統(tǒng)大小,指的是文件系統(tǒng)元數(shù)據(jù)中標識的可用大小。形象來說,是df 命令或者statfs() 函數(shù)反饋的大小。文件系 統(tǒng)大小不一定等于分區(qū)大小,既可大于分區(qū)大小,也可小于分區(qū)大小。

分區(qū)大小 在劃分分區(qū)時規(guī)定的大小,往往是sys_partition.fex 中指定的大小。

2.9 特殊隱藏空間

不管是nor,nand 還是mmc,都需要一些隱藏空間存儲特殊數(shù)據(jù),例如boot0/uboot/dtb/sys_config。用戶無法使用這些隱藏空間。 此外,nand 驅(qū)動還需要額外的空間以實現(xiàn)磨損平衡、壞塊管理算法,因此nand 的隱藏空間更大。

隱藏空間大小見總?cè)萘空f明。

3 系統(tǒng)掛載

Tina 目前支持兩種啟動方式,分別是busybox 和procd,不同啟動方式,其自動掛載的配置不同。 此處的自動掛載指開機冷掛載以及熱插拔掛載,其中冷掛載指啟動時掛載,熱掛載指TF/U 盤等插拔設(shè)備時的掛載。

3.1 塊設(shè)備節(jié)點

Tina 中設(shè)備節(jié)點都在/dev 目錄下,對于不同存儲介質(zhì),生成的設(shè)備節(jié)點會不一樣。

存儲 介質(zhì)設(shè)備 節(jié)點備注
nand /dev/nand{a,b,c…} MBR 分區(qū)表
nand /dev/nand0p{1,2,3…} GPT 分區(qū)表
mmc /dev/mmcblk0p{1,2,3…}
nor /dev/mtdblock{0,1,2…}
TF 卡/dev/mmcblk{0,1}p{1,2…} 注1
U 盤 /dev/sda{1,2…}
SATA 硬盤/dev/sda{1,2…}

說明

若使用mmc 做內(nèi)部存儲介質(zhì),由于mmc 占用了mmcblk0的設(shè)備名,此時TF 卡的設(shè)備名序號遞增為mmcblk1,否則生 成mmcblk0的設(shè)備名。因此配置fstab 時尤其注意TF 設(shè)備名是否正確。 對sys_partition.fex 中設(shè)置的內(nèi)部存儲介質(zhì)的設(shè)備節(jié)點,會自動動態(tài)在/dev/by-name 中創(chuàng)建軟鏈 接。例如:

root@TinaLinux:/# ll /dev/by-name/ drwxr-xr-x 2 root root 220 Mar 1 15:05 . drwxr-xr-x 7 root root 3060 Mar 1 15:05 .. lrwxrwxrwx 1 root root 12 Mar 1 15:05 UDISK -> /dev/nand0p9 lrwxrwxrwx 1 root root 12 Mar 1 15:05 boot -> /dev/nand0p2 lrwxrwxrwx 1 root root 12 Mar 1 15:05 env -> /dev/nand0p1 lrwxrwxrwx 1 root root 12 Mar 1 15:05 misc -> /dev/nand0p6 lrwxrwxrwx 1 root root 12 Mar 1 15:05 private -> /dev/nand0p8 lrwxrwxrwx 1 root root 12 Mar 1 15:05 pstore -> /dev/nand0p7 lrwxrwxrwx 1 root root 12 Mar 1 15:05 recovery -> /dev/nand0p5 lrwxrwxrwx 1 root root 12 Mar 1 15:05 rootfs -> /dev/nand0p3 lrwxrwxrwx 1 root root 12 Mar 1 15:05 rootfs_data -> /dev/nand0p4

因此,在fstab 也可以使用/dev/by-name/XXXX的形式匹配設(shè)備。塊設(shè)備如果有分區(qū),會形成分區(qū)設(shè)備節(jié)點,以mmc、U 盤為例介紹設(shè)備節(jié)點名與分區(qū)的關(guān)系:

設(shè)備節(jié)點名 含義
/dev/mmcblk0 表示整個mmc 空間,包含所有分區(qū)
/dev/mmcblk0p1 表示mmc 中的第1 個分區(qū)
/dev/mmcblk0p2 表示mmc 中的第2 個分區(qū)
/dev/sda 表示整個U 盤,包含所有分區(qū)
/dev/sda1 表示U 盤內(nèi)的第1 個分區(qū)
/dev/sda2 表示U 盤內(nèi)的第2 個分區(qū)

熱插拔塊設(shè)備分區(qū)有以下特殊情況。

塊設(shè)備沒有分區(qū) 有一些特殊的TF 卡/U 盤沒有分區(qū),而是直接使用整個存儲,表現(xiàn)為只有/dev/mmcblk1 和 /dev/sda ,而沒有分區(qū)節(jié)點/dev/mmcblk1p1 和/dev/sda1 。此時需要直接掛載整個存儲 設(shè)備,Tina 大部分方案都支持這種特殊情況。

塊設(shè)備有多個分區(qū) 有一些特殊的TF 卡/U 盤被分為多個分區(qū),表現(xiàn)為存在多個/dev/mmcblk1p{1,2…} 和 /dev/sda{1,2…}。默認情況下,Tina 的fstab 配置為只支持掛載熱插拔存儲設(shè)備的第一個 分區(qū)到/mnt/SDCARD 或者/mnt/exUDISK。

3.2 掛載點

3.2.1 默認掛載設(shè)備目錄

Tina 中對常見的分區(qū)和熱插拔塊設(shè)備,有默認的掛載點。

存儲介質(zhì) 掛載節(jié)點 設(shè)備節(jié)點 備注
nor/nand/mmc /mnt/UDISK /dev/by-name/UDISK 注1
TF 卡 /mnt/SDCARD 或/mnt/extsd /dev/mmcblk{0,1}p1 注2
U 盤 /mnt/exUDISK /dev/sda1 注3
SATA 磁盤 /mnt/exUDISK /dev/sda1 注3

說明

/dev/by-name/UDISK 為sys_partition.fex 的UDISK 分區(qū)的軟連接。

當無分區(qū)時,默認掛載整個TF 卡; 當有1 個或多個分區(qū)時,只掛載第一分區(qū)。

當無分區(qū)時,默認掛載整個設(shè)備(/dev/sda),當有1 個或多個分區(qū)時,只掛載第一個分區(qū)。

3.2.2 新建掛載點

掛載文件系統(tǒng)需要有掛載點。 如果掛載點所在目錄可寫,則在掛載之前先創(chuàng)建目錄即可。

mkdir -p xxx

若掛載點所在目錄為只讀,則需要在制作文件系統(tǒng)時提前創(chuàng)建好。 如創(chuàng)建非空目錄,則在對應(yīng)方案的base-files 目錄創(chuàng)建。

procd-init: target/allwinner/方案/base-files busybox-init: target/allwinner/方案/busybox-init-base-files

如創(chuàng)建空目錄,由于git 不管理空目錄,因此需在Makefile 中動態(tài)創(chuàng)建,可仿照現(xiàn)有Makefile中創(chuàng)建UDISK 目錄的寫法。

procd-init: package/base-files/Makefile busybox-init: package/busybox-init-base-files/Makefile

3.3 procd 啟動下的掛載

procd 啟動時,自動掛載由procd、fstools、fstab 配合完成。如果需要修改冷/熱掛載規(guī)則,只需要修改fstab 配置文件即可。 SDK 中,配置文件位于:

tina/target/allwinner/<方案名>/base-files/etc

若只是調(diào)試或臨時修改掛載規(guī)則,只需要修改小機端的配置文件:

/etc/config/fstab

3.3.1 fstab 編寫格式

fstab 由多個config 組成,每個config 的基本格式示例如下:

config ‘xxxx’ option xxxx ‘xx’ option xxxx ‘xx’ option xxxx ‘xx’

config 有3 種類型,分別是mount|global|swap 。Tina SDK 中沒使用swap,在本文中不做介紹。

3.3.2 global 類型config

global 類型的config 是全局配置,示例如下。

config 'global' option anon_swap '0' option anon_mount '0' option auto_swap '1' option auto_mount '1' option delay_root '5' option check_fs '1'

配置項的意義如下表:

配置名稱 可選值 意義
anon_mount 0/1 注1
anon_swap 0/1 swap 使用,此處省略
auto_mount 0/1 只適用于設(shè)置熱插拔是否自動掛載塊設(shè)備
auto_swap 0/1 swap 使用,此處忽略
check_fs 0/1 建議配置為1,注2
delay_root 1,2,3… 注3

說明

anon_mount: 當fstab 中無匹配要掛載設(shè)備的uuid/label/device 屬性的配置節(jié)時, 是否采用默認掛載為 /mnt/“$device-name”。

check_fs: 是否在掛載前用/usr/sbin/e2fsck 檢查文件系統(tǒng)一致性(只適用于ext 系統(tǒng))。

delay_root: 對應(yīng)fstab 中target 為”/” 或”/overlay” 的設(shè)備節(jié)點不存在時,最長等待delay_root 秒。

3.3.3 mount 類型config

mount 類型的config 是具體的設(shè)備掛載配置,示例如下

config 'mount' option target '/mnt/UDISK' option device '/dev/by-name/UDISK' option options 'rw,sync' option enabled '1'

配置項的意義如下表:

配置名稱 意義 備注
target 掛載點 必須是絕對路徑,必須有效
device 設(shè)備名 通過設(shè)備名指定待掛載的設(shè)備,注1
uuid 設(shè)備UUID 通過fs 的UUID 指定待掛載的設(shè)備,注1
label 設(shè)備label 通過fs 的label 指定待掛載的設(shè)備,注1
enabled 是否使能 該節(jié)點是否有效(0/1)
options 掛載屬性 例如只讀掛載等,注2

device/uuid/label 是匹配掛載的設(shè)備,三者中至少要有一個有效。

默認掛載支持的屬性如下表:

配置名稱 意義 缺省值
ro / rw 只讀/ 可讀寫 rw
nosuid / suid 忽略suid/sgid 的文件屬性 suid
nodev / dev 不允許/允許訪問設(shè)備文件 dev
noexec / exec 不允許/允許執(zhí)行程序 exec
sync / async 同步/異步寫入 async
mand / nomand 允許/不允許強制鎖 nomand
irsync 同步更新文件夾 無效
noatime / atime 不更新/更新訪問時間(atime) atime
nodiratime / diratime 不更新/更新目錄訪問時間(atime) diratime
relatime / norelatime 允許/不允許根據(jù)ctime/mtime 更新actime n orelatime
strictatime 禁止根據(jù)內(nèi)核行為來更新atime, 但允許用戶空間修改 無效

3.4 busybox 啟動下的掛載

busybox 啟動時,通過pseudo_init 和rcS 完成大部分默認的掛載工作。

存儲節(jié)點 掛載路徑 用途
/dev/by-name/UDISK /mnt/UDISK 用戶數(shù)據(jù)
/dev/by-name/rootfs_data /overlay 作為overlay 使得rootfs 可寫
/dev/mmcblk{0,1}p1 /mnt/SDCARD 或/mnt/extsd TF 卡
/dev/sda1 /mnt/exUDISK U 盤

busybox 啟動使用默認掛載配置即可,如果需要修改,需要自行修改腳本。

tina/package/busybox-init-base-files/busybox-init-base-files/usr/bin/hotplug.sh

3.5 掛載文件系統(tǒng)

在分區(qū)表中增加的分區(qū)默認是空分區(qū),如需掛載成文件系統(tǒng)使用,則首先需要在分區(qū)中寫入一個文件系統(tǒng)。 方式一,在PC 端預(yù)先生成好一個文件系統(tǒng),并在分區(qū)表中指定為download_file,則啟動后可直接掛載。例如rootfs 分區(qū)就是在PC 端制作好文件系統(tǒng),燒錄時寫入rootfs 分區(qū)。 方式二,在小機端進行格式化。例如UDISK 分區(qū)就是在第一次啟動時,由啟動腳本進行格式化??蛻艨勺孕性谀骋粏幽_本或應(yīng)用中調(diào)用格式化工具(mkfs.xxx)進行格式化。如需參考,可仿照UDISK 分區(qū)的格式化:

procd-init: package/base-files/files/lib/preinit/79_format_partition busybox-init: package/busybox-init-base-files/files/pseudo_init

3.5.1 注意事項

一些格式化工具并未默認選中,需要時請自行在make menuconfig 界面配置。部分文件系統(tǒng)對分區(qū)大小有最低要求,如ext4,ubifs,如果在小機端調(diào)用格式化分區(qū)時報錯,可根據(jù)報錯信息提示增大分區(qū)。 對于private 分區(qū)默認為空,使用DragonSN 工具寫號后,則為vfat 格式的文件系統(tǒng)。對于ubi 方案來說,如果需要使用基于塊設(shè)備的文件系統(tǒng),則需要在ubi 之上模擬塊設(shè)備。在用戶空間可調(diào)用ubiblock 工具完成,注意這樣模擬出的塊設(shè)備是只讀的,如需可寫建議直接使用 ubifs。

詳見后文ubi 方案特殊說明。

4 文件系統(tǒng)支持情況

存儲介質(zhì) jffs2 squashfs ext4 vfat ntfs exfat ubifs
(NFTL) nand N Y Y Y Y N N
(UBI) spinand N Y Y(ro) Y(ro) Y(ro) N Y
mmc N Y Y Y Y N N
nor Y Y N N N N N
TF 卡 N N Y Y Y N N
U 盤 N N Y Y Y N N

說明

(ro) 表示只能實現(xiàn)只讀: ubi 卷可通過模擬塊設(shè)備,實現(xiàn)塊文件系統(tǒng)的讀,但不支持寫。

vfat(fat32)使用內(nèi)核原生的支持,exfat 需要在Linux-5.7 后社區(qū)才正式支持,因此此處標注為不支持。

ntfs 依賴于第三方工具ntfs-3g。

TF 卡/U 盤等,建議使用vfat 實現(xiàn)Window/Linux/MacOS 的最大兼容參考文章《多平臺大型文件系統(tǒng)比較》。

vfat/ntfs/exfat 等Window 文件系統(tǒng),不建議用做嵌入式存儲,除非您能保證其掉電安全和移植文件系統(tǒng)修復(fù)工具。

警告 關(guān)于文件系統(tǒng)的選擇,有以下幾點需要注意:

全志NFTL nand 可使用塊文件系統(tǒng)(ext4) 全志在驅(qū)動中實現(xiàn)磨損平衡和壞塊管理,向上呈現(xiàn)為塊設(shè) 備。因此可支持ext4,不需要且不支持常見的flash 文件系統(tǒng)(jffs2/yaffs/ubifs 等)。

為了保證掉電不變磚,根文件系統(tǒng)務(wù)必只讀(squashfs),或者ext4 掛載為ro 模式。

ext4/ubifs 等文件系統(tǒng)分區(qū)大小必須足夠大,以確保能正確創(chuàng)建日志塊,否則有掉電變磚風(fēng)險分區(qū)大小 請參考章節(jié)分區(qū)大小與對齊。

4.1 ext4 與日志

4.1.1 ext4 的日志

與服務(wù)器等長期穩(wěn)定供電的情況不同,嵌入式設(shè)備隨時有掉電的可能。不管在任意時間掉電,文件系統(tǒng)都需要保持一致性,換句話說,保證文件不會因為掉電丟失。如果文件系統(tǒng)只讀,則不需要日志。日志只是確保寫的安全。

說明 什么是文件系統(tǒng)的一致性? 文件系統(tǒng)元數(shù)據(jù)塊記錄了有什么文件,數(shù)據(jù)塊則保存了實際的文件內(nèi)容。一致性則表示,元數(shù)據(jù)塊記錄了存在某個文件,必定存 在對應(yīng)的數(shù)據(jù)塊,換句話說,就是保證元數(shù)據(jù)和數(shù)據(jù)的一致。 如果出現(xiàn),元數(shù)據(jù)記錄文件A 存在,但文件A 的數(shù)據(jù)塊是無效的,或者明明數(shù)據(jù)塊是有效的,但元數(shù)據(jù)并沒任何記錄,導(dǎo)致系 統(tǒng)并不知道文件存在,就出現(xiàn)了文件系統(tǒng)的不一致。

警告 保證文件不丟失,只保證之前寫入的文件數(shù)據(jù)正常,而非正在寫,且因為掉電導(dǎo)致沒寫完整的文件。對大多數(shù)文 件系統(tǒng)而言,更多時候會直接丟棄這沒寫完整的文件以保證一致性。

ext4 通過日志的形式保證文件系統(tǒng)一致性。其支持3 種日志模式:

日志模式 原理 特點
journal 元數(shù)據(jù)與數(shù)據(jù)都寫入日志 最安全,但性能最慢
writeback 只有元數(shù)據(jù)寫入日志,但不保證數(shù)據(jù)先落盤 性能最快,但最不安全
ordered 只有元數(shù)據(jù)寫入日志,且保證數(shù)據(jù)先落盤,元數(shù)據(jù)后落盤 折中,默認方案

考慮安全和性能的折中,建議使用ordered 的日志模式。系統(tǒng)默認使用的就是ordered 模式。我們在mount 命令中顯示的掛載參數(shù)可顯示使用的哪種日志。

$mount /dev/by-name/UDISK on /mnt/UDISK type ext4 (rw,....,data=ordered)

4.1.2 分區(qū)大小與日志

有時候分區(qū)太小,系統(tǒng)會默認把日志功能關(guān)閉??梢酝ㄟ^以下方法判斷:

$dumpe2fs <分區(qū)or 鏡像文件> ... Filesystem features: has_journal ... ... Journal backup: inode blocks Journal features: (none) 日志大小: 1024k Journal length: 1024 Journal sequence: 0x00000001 Journal start: 0 ...

在Filesystem features 中有has_journal 的標志表示支持日志。在Jorunal 片段中也詳細描述了日志塊的大小等信息。 如果創(chuàng)建的文件系統(tǒng)沒有日志,對大多數(shù)用戶而言,擴大分區(qū)大小是最簡單的做法。專業(yè)的做法可以通過縮小塊大小,取消預(yù)留塊等方式為日志騰挪出空間。 按以往經(jīng)驗,對小容量(<100M) 的存儲而言,在資源文件之外預(yù)留3-5M 的空間用于文件系統(tǒng)的元數(shù)據(jù)即可。

4.1.3 修復(fù)ext4

ext4 文件系統(tǒng)每次重啟后,建議都進行一次修復(fù),確保文件系統(tǒng)穩(wěn)定。 修復(fù)可以參考以下命令:

e2fsck -y <分區(qū)>

4.1.4 修復(fù)fat

TF 卡掛載fat 文件系統(tǒng),fat 文件系統(tǒng)不是日志型文件系統(tǒng),在掉電、帶電插拔等場景下不能保證文件系統(tǒng)數(shù)據(jù)的安全,所以建議啟動都進行一次修復(fù)。修復(fù)可以參考以下命令:

fsck_msdos -pfS /dev/mmcblk0p1

如章節(jié)global 類型config中描述,如果使用procd 引導(dǎo)啟動,在fstab 中使能check_fs,也可實現(xiàn)在掛載前自動修復(fù)。

5 UBI VS. NFTL

對nand 存儲介質(zhì),全志有兩套解決方案,分別是NFTL spi/raw nand 和UBI spi nand。UBI 存儲方案常用于小容量spinand,其實現(xiàn)原理跟NFTL 存儲方案完全不同。

5.1 NFTL Nand

這是全志實現(xiàn)的不開源的Nand 驅(qū)動,NFTL 全稱為NAND Flash Translation Layer,其可實現(xiàn)屏蔽Nand 的特性,對上呈現(xiàn)為塊設(shè)備。 我們常見的mmc 設(shè)備也是塊設(shè)備,可以簡單理解為,MMC = Nand Flash + 控制器+NFTL。所以通過全志的NFTL nand 驅(qū)動后,我們可以像mmc 設(shè)備一樣,以塊設(shè)備操作Nand。 例如,上層可以直接裸讀寫塊設(shè)備,常見的ota 更新也是基于這樣的實現(xiàn):

dd if=boot.fex of=/dev/by-name/boot

技巧

詳細的OTA 方法,請參見OTA 相關(guān)文檔。

全志的NFTL Nand 驅(qū)動中,預(yù)留一部分空間做算法和關(guān)鍵數(shù)據(jù)保存。預(yù)留空間大致為1/10 ~1/8 的可用空間。這里的可用空間是指剔除出廠壞塊之外的空間。由于每一顆Flash 的出廠壞塊數(shù)量不盡相同,因此最終呈現(xiàn)給用戶的可用空間不盡相同。用戶也不需要擔(dān)心使用過程中出現(xiàn)的壞塊導(dǎo)致用戶可用空間變小,在算法實現(xiàn)中,使用壞塊會體現(xiàn)在預(yù)留空間而不是用戶空間。 此外,Nand 的磨損平衡、壞塊管理等特性全由NFTL 驅(qū)動實現(xiàn)。換句話說,驅(qū)動保證用戶數(shù)據(jù)的穩(wěn)定,用戶可將其按塊設(shè)備使用。

5.2 UBI (spi) Nand

當前UBI 方案僅適用于小容量spinand。 UBI 方案是社區(qū)普遍使用的Flash 存儲方案,其構(gòu)建在mtd 設(shè)備之上,由UBI 子系統(tǒng)屏蔽Nand 特性,對接UBIFS 文件系統(tǒng)。其層次結(jié)構(gòu)由上往下大致如下:

層次 層級 功能
0 (最上層) UBIFS ubifs 文件系統(tǒng)
1 UBI 子系統(tǒng) Nand 特性管理
2 MTD 子系統(tǒng) 封裝Flash,向上提供統(tǒng)一接口
3 (最下層) Flash 具體的Flash 驅(qū)動

我們把MTD 分區(qū)稱為物理分區(qū),把UBI 卷(分區(qū)) 成為邏輯分區(qū),因為 ? MTD 分區(qū)是按Flash 的物理地址區(qū)間劃分分區(qū) ? UBI 卷(分區(qū)) 是動態(tài)映射的區(qū)間 全志的UBI 方案中,創(chuàng)建了這些MTD 物理分區(qū):

分區(qū)名 大小 作用
boot0 4/8 個物理塊 存放boot0
uboot 4/20M 存放uboot
secure storage 8 個物理塊 存放關(guān)鍵數(shù)據(jù)
pstore 512K 奔潰日志轉(zhuǎn)存
sys 剩余空間 提供給ubi 子系統(tǒng)劃分邏輯分區(qū)

驅(qū)動會在sys 的MTD 物理分區(qū)上根據(jù)sys_partition.fex構(gòu)建UBI 邏輯分區(qū)(卷)。 UBI 設(shè)備向上呈現(xiàn)為字符設(shè)備,無法直接使用諸如ext4 這樣基于塊設(shè)備的文件系統(tǒng)。但UBI 子系統(tǒng)支持模擬只讀的塊設(shè)備,即把UBI 邏輯卷模擬成只讀的塊設(shè)備?;诖耍梢宰龅礁募到y(tǒng)依然使用squashfs 這樣的塊文件系統(tǒng)。 社區(qū)為UBI 設(shè)備專門設(shè)計了ubifs 文件系統(tǒng)。經(jīng)過驗證,其配合UBI 子系統(tǒng)可保證數(shù)據(jù)掉電安全以及提供通用文件系統(tǒng)所有功能,甚至還提供文件系統(tǒng)壓縮功能。 除此之外,UBI 設(shè)備更新(OTA 更新)也不能直接裸寫設(shè)備,需要通過ubiupdateval 命令更新。 技巧:詳細的OTA 方法,請參見OTA 相關(guān)文檔。

5.3 ubi 相關(guān)工具

5.3.1 ubinfo

輸出指定ubi 設(shè)備信息。 例子:

ubinfo /dev/by-name/rootfs #查看rootfs卷的信息 ubinfo -a #查看所有卷的信息

可參考總?cè)萘空f明

5.3.2 ubiupdatevol

更新指定卷上的數(shù)據(jù)。 例子:

ubiupdatevol -t /dev/by-name/boot #清除boot卷的數(shù)據(jù) ubiupdatevol /dev/by-name/boot /tmp/boot.img #將/tmp/boot.img寫到boot卷,卷上原有數(shù)據(jù)會完全丟失

可參考總?cè)萘空f明

可參考模擬塊設(shè)備

5.3.3 ubiblock

基于一個ubi 卷,生成模擬的只讀塊設(shè)備 例子:

ubiblock -c /dev/by-name/test #將test卷生成一個塊設(shè)備節(jié)點

可參考模擬塊設(shè)備

5.3.4 其他

在tina 方案上,燒錄固件時已經(jīng)完成mtd 和ubi 卷的創(chuàng)建,啟動時自動attach 并掛載對應(yīng)的分區(qū),無需再自行處理。因此以下命令一般不會用到。 ubiformat: 將裸mtd 格式化成ubi ubiattach: 將mtd 關(guān)聯(lián)到ubi ubidetach: 將ubi 與mtd 解除關(guān)聯(lián)ubimkvol: 創(chuàng)建ubi 卷 ubirmvol: 移除ubi 卷

6 rootfs_data 及UDISK

6.1 overlayfs 簡介

Tina 默認根文件系統(tǒng)格式使用squashfs 格式,這是一種只讀壓縮的文件系統(tǒng)。很多應(yīng)用則需要文件系統(tǒng)可寫,特別是/etc 等存放較多配置文件的目錄,為了滿足可寫的需求,Tina 默認使用overlayfs 技術(shù)。overlayfs 是一種堆疊文件系統(tǒng),可以將底層文件系統(tǒng)和頂層文件系統(tǒng)的目錄進行合并呈現(xiàn)。

6.2 使用rootfs_data 作為overlayfs

Tina 常用的方式是專門劃分一個rootfs_data 分區(qū), 先格式化成可寫的文件系統(tǒng)(如ext4/ubifs), 再進一步掛載為overyfs, 成為新的根, 讓上層應(yīng)用認為rootfs 是可寫的。 rootfs_data 分區(qū)的大小就決定了應(yīng)用能修改多少文件。具體原理和細節(jié)請參考網(wǎng)上公開資料,此處僅舉簡單例子輔助理解。

底層(即rootfs 分區(qū)的文件系統(tǒng))不存在文件A,應(yīng)用創(chuàng)建A,則A 只存在于上層(即 rootfs_data 分區(qū))。

底層存在文件B,應(yīng)用刪除B,則B 仍然存在于底層,但上層會創(chuàng)建一個特殊文件屏蔽掉,導(dǎo) 致對應(yīng)用來說B 就看不到了,起到刪除的效果。

底層存在文件C,上層修改C,則C 會先被整個拷貝到上層,C 本身多大就需占用多大的上 層空間,在這個基礎(chǔ)上應(yīng)用對上層的C 進行修改。 基于以上理解,可按需配置rootfs_data 的大小。一般開發(fā)期間會配置得較大,量產(chǎn)時可減小 (考慮實際只會修改少量配置文件)甚至去除(需要確認所有應(yīng)用均不依賴rootfs 可寫)。

6.3 使用UDISK 作為overlayfs

如果希望overlayfs 的空間盡可能較大,也可考慮直接使用UDISK 分區(qū)作為上層文件系統(tǒng)空間。 可將target/allwinner/xxx/base-files/etc/config/fstab 中的rootfs_data 分區(qū)及UDISK 分區(qū)的掛載配置disable 掉。

config 'mount' option target '/overlay' option device '/dev/by-name/rootfs_data' option options 'rw,sync,noatime' option enabled '0' #此行改成0 config 'mount' option target '/mnt/UDISK' option device '/dev/by-name/UDISK' option options 'rw,async,noatime' option enabled '0'

再新增一個配置,將UDISK 直接掛載到/overlay 目錄。

config 'mount' option target '/overlay' option device '/dev/by-name/UDISK' option options 'rw,sync,noatime' option enabled '1'

6.4 如何清空rootfs_data 和UDISK

出于恢復(fù)出廠設(shè)置或其他需要,有時需要清空rootfs_data 和UDISK。 一般不建議在文件系統(tǒng)仍處于掛載狀態(tài)時直接操作對應(yīng)的底層分區(qū),因此建議需要清空時,不要直接操作對應(yīng)塊設(shè)備,而是先設(shè)置標志并重啟,再在掛載對應(yīng)分區(qū)前的啟動腳本中檢測到對應(yīng)標志后,對分區(qū)進行重新格式化。 當前79_format_partition 中實現(xiàn)了一個clean_parts 功能, 會檢測env 分區(qū)中的parts_clean 變量并清空對應(yīng)分區(qū)的頭部。清空后,rootfs_data 和UDISK 分區(qū)會自動重新觸發(fā)格式化。

# to clean rootfs_data and UDISK, please run fw_setenv parts_clean rootfs_data:UDISK reboot

具體實現(xiàn)請查看

package/base-files/files/lib/preinit/79_format_partition

7 關(guān)鍵數(shù)據(jù)保護

設(shè)備上保存的一些關(guān)鍵的數(shù)據(jù),例如mac,SN 號等,一般要求在重新刷機時不丟失。以下介紹刷機數(shù)據(jù)不丟失的解決方案。

7.1 邏輯分區(qū)保護方案

7.1.1 分區(qū)設(shè)置

此處的邏輯分區(qū),是指在分區(qū)表(sys_partition.fex/sys_partition_nor.fex) 中定義的分區(qū)。名字為private 的分區(qū)會特殊處理,默認刷機數(shù)據(jù)不丟失。 其他名字的分區(qū),如果指定keydata=0x8000 屬性,則刷機數(shù)據(jù)不丟失。對于private 分區(qū)或設(shè)置了keydata=0x8000 屬性的分區(qū),請勿設(shè)置downloadfile。

7.1.2 實現(xiàn)原理

對private 分區(qū)(配置了keydata=0x8000 屬性同理) 保護的方式是,擦除之前先申請一片內(nèi)存,然后根據(jù)flash 中的舊分區(qū)表,讀出private 分區(qū)內(nèi)容。 接著進行擦除,然后再按照新的分區(qū)表,將private 分區(qū)內(nèi)容寫回flash 上新分區(qū)所在位置。

7.1.3 常見用法

使用全志的DragonSN 工具,選擇私有key 模式,將key 寫入private 分區(qū)。寫入后private分區(qū)默認會是一個vfat 文件系統(tǒng),啟動后掛載/dev/by-name/private,即可讀出key。DragonSN 的具體用法請參考工具自帶文檔。

不使用DragonSN 工具, 由應(yīng)用自行負責(zé)寫入數(shù)據(jù)和讀出數(shù)據(jù), 直接在用戶空間操作/dev/by-name/private 節(jié)點即可。量產(chǎn)時可自行開發(fā)PC 端工具,通過adb 命令來完成key 的寫入。

7.1.4 ubi 方案特殊說明

7.1.4.1 模擬塊設(shè)備

對于nand nftl 方案,emmc 方案,nor 方案,邏輯分區(qū)是對應(yīng)到一個塊設(shè)備,即對于private分區(qū),可以直接讀寫/dev/by-name/private 節(jié)點,也可以借助DragonSN 工具制作成一個vfat文件系統(tǒng),再掛載使用,掛載后文件系統(tǒng)是可讀寫的。 但對于nand ubi 方案,邏輯分區(qū)是對應(yīng)到ubi 卷,由于ubi 的特性,無法再直接寫數(shù)據(jù)到/dev/by-name/private 節(jié)點,需要通過ubiupdatevol 工具來更新卷,或者自行在應(yīng)用中按照ubi 卷更新步驟操作。 當基于ubi 卷構(gòu)建vfat 文件系統(tǒng)時,需要先基于ubi 卷模擬塊設(shè)備,且掛載上的vfat 文件系統(tǒng)是只讀的。操作示例如下。

#查看private分區(qū)對應(yīng)的ubi節(jié)點 root@TinaLinux:/# ll /dev/by-name/private lrwxrwxrwx 1 root root 11 Jan 1 00:00 /dev/by-name/private -> /dev/ ubi0_4 #創(chuàng)建模擬的塊設(shè)備 root@TinaLinux:/# ubiblock -c /dev/ubi0_4 block ubiblock0_4: created from ubi0:4(private) #掛載 root@TinaLinux:/# mkdir /tmp/private root@TinaLinux:/# mount -t vfat /dev/ubiblock0_4 /tmp/private/ #可以讀取內(nèi)容 root@TinaLinux:/# ls /tmp/private/ ULI magic.bin #查看掛載情況,為ro root@TinaLinux:/# mount | grep private /dev/ubiblock0_4 on /tmp/private type vfat (ro,relatime,fmask=0022,dmask=0022,codepage=437, iocharset=iso8859-1,shortname=mixed,errors=remount-ro)

7.1.4.2 在設(shè)備端制作vfat 鏡像

由于ubifs 需占用17 個LEB,比較占空間,對于只在工廠一次性寫入信息,后續(xù)只讀的場景,一種可考慮的方案是使用vfat 文件系統(tǒng)。 首先選上kernel 的loopback 支持:

make kernel_menuconfig 選上Device Drivers --> [*] Block Devices --> <*>Loopback device support

分區(qū)表中建立分區(qū),假設(shè)為test 分區(qū)隨后可以在小機端準備一個vfat 鏡像:

dd if=/dev/zero of=/mnt/UDISK/test.img bs=1M count=1 mkfs.vfat /mnt/UDISK/test.img mkdir -p /tmp/test mount /mnt/UDISK/test.img /tmp/test 此時可向/tmp/test 寫入文件 umount /tmp/test

將鏡像寫入卷中:

ubiupdatevol /dev/by-name/test /mnt/UDISK/test

后續(xù)按上文介紹的方法,使用模擬塊設(shè)備掛載,注意使用模擬塊設(shè)備掛載后就是只讀的了。

7.1.5 可能造成數(shù)據(jù)丟失的情況

出現(xiàn)以下情況,會導(dǎo)致private 分區(qū)數(shù)據(jù)丟失。

配置了強制擦除,例如sys_config.fex 中配置了eraseflag = 0x11。

無法讀取flash 上的分區(qū)表或private 分區(qū)。這個可能的原因包括flash 上的數(shù)據(jù)被破壞了 等。

新的分區(qū)表不包含private 分區(qū)。

在燒錄過程中掉電。如上所述,燒錄時是讀出-> 擦除-> 寫回,在擦除之后,寫回之前掉電,則數(shù)據(jù)丟失。 檢測到private 分區(qū),開始執(zhí)行保護private 分區(qū)的代碼,但執(zhí)行過程中出錯,如malloc 失敗,private 無法讀取等,則會導(dǎo)致燒錄失敗。出現(xiàn)malloc 失敗問題一般是因為板子上燒錄了Android固件。因為安卓的private 分區(qū)比較大,而tina 的uboot 分配給malloc 的空間比較小。 這個時候,需要打包一份不保護private 分區(qū)的tina 固件先進行一次燒錄,即可解決問題。具體的:將sys_config.fex 的eraseflag 改為0x11,強制擦除?;蛘吲R時移除sys_partition.fex中的private 分區(qū)。

7.2 物理區(qū)域保護方案

另一種保護數(shù)據(jù)不丟失的思路是,在flash 上劃定一塊物理區(qū)域,燒錄時默認不擦除。在Tina 上實現(xiàn)的secure storage 區(qū)域即具有這種特性。secure storage 區(qū)域用于保存key,可代替private 分區(qū),理論上更為安全(被燒錄時誤擦除和被別的應(yīng)用誤寫的可能性較低)。

7.2.1 nand nftl 方案實現(xiàn)

nand nftl 方案中,預(yù)留了一塊物理區(qū)域,用于secure storage。這塊區(qū)域不是邏輯分區(qū),用戶空間不可見。燒錄時不會擦除這塊區(qū)域。在用戶空間讀寫secure storage 需要使用ioctl,由內(nèi)核nand 驅(qū)動來協(xié)助完成。

7.2.2 nand ubi 方案實現(xiàn)

nand ubi 方案中,預(yù)留了一塊物理區(qū)域,用于secure storage,對上表現(xiàn)為一個mtd 分區(qū)。用戶空間可見。燒錄時不會擦除這塊區(qū)域。在用戶空間讀寫secure storage 需要使用ioctl,由內(nèi)核來協(xié)助完成。理論上也可以直接讀寫mtd 設(shè)備節(jié)點,但不推薦,使用這種方式應(yīng)用需要自行處理壞塊等問題。

7.2.3 emmc 方案實現(xiàn)

預(yù)留了一塊物理區(qū)域,默認是偏移6M-6.25M 的區(qū)域,作為secure storage。在用戶空間讀寫,可以直接通過mmcblk0 節(jié)點讀寫指定偏移。

7.2.4 nor 方案實現(xiàn)

暫未實現(xiàn)。

7.2.5 常見用法

使用全志的DragonSN 工具,選擇安全key 模式,將key 寫入secure storage 區(qū)域。啟動后在用戶空間調(diào)用庫讀出key。DragonSN 的具體用法請參考工具自帶文檔。

不使用DragonSN 工具,由應(yīng)用自行在用戶空間調(diào)用庫寫入數(shù)據(jù)和讀出數(shù)據(jù)。量產(chǎn)時可自行開發(fā)PC 端工具,通過adb 命令來完成key 的寫入。

7.2.6 secure storage 格式

secure storage 有預(yù)設(shè)的格式,簡單總結(jié)如下 ? secure storage 總大小為256KB,因為有備份,所以實際能用128KB。 ? 128KB 分為32 個item, 即每個item 是4KB。 ? item0 用作secure_sotrage_map,所以用戶能用的實際為31 個item。 ? 每個item 內(nèi)部為鍵值對的格式,包含CRC 校驗,其中用戶可存儲的key 長度最多為3KB。 ? secure_storage_map 中是以“name:length” 的格式保存所有item 的信息,所以所有item的“name:length” 字符串長度總和不能超過secure_storage_map 中data 的長度。一般而言,31 個3KB 的key 可以滿足需求,如果無法滿足,例如需要更多數(shù)量的key,則一種解決方式是上層應(yīng)用自行將多個key 拼接起來,只要總大小不超過3KB 即可當成一個key 寫入 secure storage。讀出時應(yīng)用自行反向解析出目標key 即可。

7.2.7 在uboot 中讀寫

基于以上介紹的格式,uboot 中封裝了pst 命令。

pst - read data from secure storageerase flag in secure storage Usage: pst pst read|erase [name] pst read, then dump all data pst read name, then dump the dedicate data pst write name, string, write the name = string pst erase, then erase all secure storage data pst erase key_burned_flag, then erase the dedicate data

7.2.8 在用戶空間讀寫

Tina 提供了讀寫庫。

make menuconfig 選中Allwinner --> <*> libsec_key --> [*] Enable secure storage key support

如果選上demo,則會編譯出demo 程序sec_key_test。

root@TinaLinux:/# sec_key_test -h -w : write key to sst and private -r : read key from sst or private -t 0: write some key to secure storage -t 1: repetitve read + verify some key from secure storage -t 2: repetitve write + verify some key from secure storage -t 3: verify some key from secure storage -t 4: write some key to private -t 5: repetitve read + verify some key from private -t 6: repetitve write + verify some key from private -t 7: verify some key from private -l : list -d : printf hex -h : help

更詳細的使用方式請參考:

tina/package/allwinner/libkey/readme.txt

7.3 secure storage 區(qū)域與private 分區(qū)比較

刷機不丟失的特性: ? private 分區(qū)每次刷機,是先讀出到dram,擦除flash,再寫入flash。刷機中途掉電可能丟失 ? secure storage 則是刷機過程完全不會擦除。理論上secure storage 的數(shù)據(jù)更安全。

用戶空間誤操作的可能: ? private 分區(qū)可以用常規(guī)分區(qū)更新命令清除掉。 ? secure storage 需要通過ioctl 專用接口訪問。

數(shù)據(jù)格式: ? private 分區(qū)可以裸分區(qū)讀寫,也可以格式化成文件系統(tǒng)。 ? secure storage 已限制為鍵值對,key 的長度也有限制。

存放位置: ? private 分區(qū)大小由分區(qū)表配置,是一個可見的普通分區(qū)。 ? secure storage 是flash 上的保留區(qū)域,大小固定,分區(qū)表中不可見。

? private 分區(qū)沒有備份,請避免寫入時掉電。或者自行在private 分區(qū)中構(gòu)建備份。 ? secure storage 默認是雙備份。

在uboot 訪問: ? private 分區(qū),uboot 通過通用的讀寫flash 接口或文件系統(tǒng)接口訪問,取決于數(shù)據(jù)格式。 ? sectre storage 區(qū)域,有固定格式,通過uboot 提供的secure storage 專用接口訪問。

校驗: ? private 分區(qū)如果是裸數(shù)據(jù),是否校驗由應(yīng)用自行處理。如果是文件系統(tǒng),則由文件系統(tǒng)特性決定。 ? secure storage 格式中帶了crc 校驗。

審核編輯:湯梓紅
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 存儲
    +關(guān)注

    關(guān)注

    13

    文章

    4314

    瀏覽量

    85846
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11304

    瀏覽量

    209499
  • 開發(fā)指南
    +關(guān)注

    關(guān)注

    0

    文章

    34

    瀏覽量

    7541
  • Tina
    +關(guān)注

    關(guān)注

    2

    文章

    45

    瀏覽量

    16983
收藏 人收藏

    評論

    相關(guān)推薦

    Tina_Linux系統(tǒng)裁剪開發(fā)指南

    Tina_Linux系統(tǒng)裁剪開發(fā)指南1 概述2 Tina系統(tǒng)裁剪簡介2.1 boot0裁剪2.2 uboot裁剪2.3 內(nèi)核裁剪2.3.1 刪除不使用的功能2.3.2 刪除不使用的驅(qū)動2.3.3
    的頭像 發(fā)表于 03-06 09:52 ?1560次閱讀

    EAC0945 linux開發(fā)指南

    EAC0945 linux開發(fā)指南
    發(fā)表于 09-28 12:40

    EAC0945 linux開發(fā)指南

    `EAC0945 linux開發(fā)指南`
    發(fā)表于 10-31 12:18

    Rockchip Linux SDK uboot logo開發(fā)指南

    arm嵌入式vs-rk3399 板卡uboot logo 開發(fā)指南概述:本文檔主要介紹 rockchip linux sdk uboot logo 顯示的相關(guān)功能、配置以及開發(fā)過程中的注意事項。適用于 rockhip
    發(fā)表于 10-09 08:12

    Tiny6410 Linux開發(fā)指南詳解

    Tiny6410 Linux 開發(fā)指南
    發(fā)表于 07-08 17:12 ?210次下載
    Tiny6410 <b class='flag-5'>Linux</b><b class='flag-5'>開發(fā)指南</b>詳解

    A64開發(fā)板LCD開發(fā)指南

    A64開發(fā)板LCD開發(fā)指南,驅(qū)動開發(fā)指南
    發(fā)表于 06-21 17:02 ?0次下載

    彩光燈開發(fā)指南

    彩光燈開發(fā)指南
    發(fā)表于 12-29 20:15 ?0次下載

    Linux的平臺下Mini210S裸機程序開發(fā)指南

    Linux的平臺下Mini210S裸機程序開發(fā)指南
    發(fā)表于 10-29 10:52 ?59次下載
    <b class='flag-5'>Linux</b>的平臺下Mini210S裸機程序<b class='flag-5'>開發(fā)指南</b>

    Rockchip Linux SDK的開發(fā)指南的詳細資料說明

    本文檔的主要內(nèi)容詳細介紹的是Rockchip Linux SDK的開發(fā)指南的詳細資料說明。
    發(fā)表于 01-10 17:17 ?74次下載
    Rockchip <b class='flag-5'>Linux</b> SDK的<b class='flag-5'>開發(fā)指南</b>的詳細資料說明

    Tina_Linux_系統(tǒng)軟件開發(fā)指南

    Tina_Linux_系統(tǒng)軟件開發(fā)指南
    的頭像 發(fā)表于 03-02 15:25 ?1833次閱讀
    <b class='flag-5'>Tina_Linux</b>_系統(tǒng)軟件<b class='flag-5'>開發(fā)指南</b>

    Tina Linux配置開發(fā)指南

    Tina Linux配置開發(fā)指南
    的頭像 發(fā)表于 03-02 15:28 ?1.6w次閱讀
    <b class='flag-5'>Tina</b> <b class='flag-5'>Linux</b>配置<b class='flag-5'>開發(fā)指南</b>

    Linux NOR開發(fā)指南

    Linux NOR開發(fā)指南
    的頭像 發(fā)表于 03-06 09:55 ?970次閱讀
    <b class='flag-5'>Linux</b> NOR<b class='flag-5'>開發(fā)指南</b>

    Tina Linux圖形系統(tǒng)開發(fā)指南

    本文檔將介紹 Allwinner Tina Linux 中已經(jīng)移植好的窗口系統(tǒng),以及怎么使用,包括 MiniGUI、QT5、EFL、GTK+(WebkitGtk、Midori)、DirectFB、Wayland,整體結(jié)構(gòu) 。
    的頭像 發(fā)表于 03-06 11:00 ?3148次閱讀
    <b class='flag-5'>Tina</b> <b class='flag-5'>Linux</b>圖形系統(tǒng)<b class='flag-5'>開發(fā)指南</b>

    Tina Linux音頻開發(fā)指南

    介紹Tina平臺音頻模塊的使用方法。
    的頭像 發(fā)表于 03-06 11:02 ?6416次閱讀
    <b class='flag-5'>Tina</b> <b class='flag-5'>Linux</b>音頻<b class='flag-5'>開發(fā)指南</b>

    Tina Linux PMU開發(fā)指南

    介紹使用Tina PMU 驅(qū)動的使用方法。
    的頭像 發(fā)表于 03-06 11:05 ?2103次閱讀
    <b class='flag-5'>Tina</b> <b class='flag-5'>Linux</b> PMU<b class='flag-5'>開發(fā)指南</b>