linux MMC framework(6) - 分區MBR/GPT及Debug

  • 瞭解分區

1.概述

  分區信息被存放在分區表中。目前有兩種主流的模式:傳統的 Master Boot Record 和新的 GUID Partition Table。後者功能更強大,解決了許多MBR的限制。

1.1.MBR

  主引導記錄(Master Boot Record),又叫做主引導扇區,是計算機開機後訪問硬盤時所必須要讀取的首個扇區,它在硬盤上的三維地址爲(柱面,磁頭,扇區)=(0,0,1)。

  主引導扇區則是整個硬盤的第一扇區(主分區的第一個扇區)。MBR就保存在主引導扇區中。另外,這個扇區裏還包含了硬盤分區表DPT(Disk Partition Table),和結束標誌字(Magic number)。扇區總計512字節,MBR佔446字節(0000H - 01BDH),DPT佔據64個字節(01BEH - 01FDH),最後的magic number佔2字節(01FEH – 01FFH)。
在這裏插入圖片描述

  MBR是由分區程序(如Fdisk,Parted)所產生的,它不依賴任何操作系統,而且硬盤引導程序也是可以改變的,從而能夠實現多系統引導。

  從主引導記錄的結構可以知道,它僅僅包含一個64個字節的硬盤分區表。由於每個分區信息需要16個字節,所以對於採用MBR型分區結構的硬盤(其磁盤卷標類型爲MS-DOS),最多隻能識別4個主要分區。所以對於一個採用此種分區結構的硬盤來說,想要得到4個以上的主要分區是不可能的。這裏就需要引出擴展分區了。

  擴展分區也是主分區(Primary partition)的一種,但它與主分區的不同在於理論上可以劃分爲無數個邏輯分區,每一個邏輯分區都有一個和MBR結構類似的擴展引導記錄(EBR)。在MBR分區表中最多4個主分區或者3個主分區+1個擴展分區,也就是說擴展分區只能有一個,然後可以再細分爲多個邏輯分區。

  在Linux系統中,硬盤分區命名爲sda1-sda4或者hda1-hda4(其中a表示硬盤編號可能是a、b、c等等)。在MBR硬盤中,分區號1-4是主分區(或者擴展分區),邏輯分區號只能從5開始。

  在MBR分區表中,一個分區最大的容量爲2T,且每個分區的起始柱面必須在這個disk的前2T內。你有一個3T的硬盤,根據要求你至少要把它劃分爲2個分區,且最後一個分區的起始扇區要位於硬盤的前2T空間內。如果硬盤太大則必須改用GPT。

1.1.1.MBR分區方案特點:

  • 最多支持四個主分區
  • 在Linux上使用擴展分區和邏輯分區最多可以創建15個分區
  • 由於分區中的數據以32位存儲,使用MBR分區是最大支持2T空間
  • fdisk管理工具只能創建MBR分區

1.2.GPT

  GPT分區:全稱爲Globally Unique Identifier Partition Table,也叫做GUID分區表,它是UEFI 規範的一部分。由於硬盤容量的急速增長,MBR的2.2T容量難以滿足要求,而UEFI BIOS的推廣也爲GPT的實現打下了堅實的技術基礎,GPT應運而生。

  全局唯一標識分區表(GUID Partition Table)是一個實體硬盤的分區結構。它是EFI(可擴展固件接口標準)的一部分,用來替代BIOS中的主引導記錄分區表。但因爲MBR分區表不支持容量大於2.2TB(2.2 × 1012字節)的分區,所以也有一些BIOS系統爲了支持大容量硬盤而用GPT分區表取代MBR分區表。

  在MBR硬盤中,分區信息直接存儲於主引導記錄(MBR)中(主引導記錄中還存儲着系統的引導程序)。但在GPT硬盤中,分區表的位置信息儲存在GPT頭中。但出於兼容性考慮,硬盤的第一個扇區仍然用作MBR,之後纔是GPT頭。

  在與支持最大卷爲2 TB(Terabytes)並且每個磁盤最多有4個主分區(或3個主分區,1個擴展分區和無限制的邏輯驅動器)的MBR磁盤分區的樣式相比,GPT磁盤分區樣式支持最大卷爲18 EB(Exabytes)(1EB=1048576TB)並且每磁盤的分區數沒有上限,只受到操作系統限制(由於分區表本身需要佔用一定空間,最初規劃硬盤分區時,留給分區表的空間決定了最多可以有多少個分區,IA-64版Windows限制最多有128個分區,這也是EFI標準規定的分區表的最小尺寸)。與MBR分區的磁盤不同,至關重要的平臺操作數據位於分區,而不是位於非分區或隱藏扇區。另外,GPT分區磁盤有備份分區表來提高分區數據結構的完整性。

  在其中轉換爲GPT的時候可以創建兩個隱藏分區,ESP和MSR。ESP是efi系統分區用於保存引導文件,MSR是微軟的保留分區,用於安裝操作系統。
在這裏插入圖片描述

  • PMBR:當不支持GPT的分區工具試圖對硬盤進行操作時(例如MS-DOS和Linux的fdisk程序),它可以根據這份PMBR以傳統方式啓動,過程和MBR+BIOS完全一致,極大地提高了兼容性。而支持GPT的系統在檢測PMBR後會直接跳到GPT表頭讀取分區表。和MBR類似,分區表中存儲了某個分區的起始和結束位置及其文件系統屬性信息,而分區纔是實際存在的物理磁盤的一部分。

  • GPT HDR:GPT表頭,主要定義了分區表中項目數及每項大小,還包含硬盤的容量信息。在64位的Windows Server 2003的機器上,最多可以創建128個分區,即分區表中保留了128個項,其中每個都是128字節。(也是EFI標準中的最低要求:分區表最小要有16,384字節)分區表頭還記錄了這塊硬盤的GUID,分區表頭位置(總是LBA1)和大小,也包含了備份分區表頭和分區表的位置和大小信息(LBA-1~LBA-34)。同時還儲存着它本身和分區表的CRC32校驗。固件、引導程序和操作系統在啓動時可以根據這個校驗值來判斷分區表是否出錯,如果出錯,可以使用軟件從硬盤最後的備份GPT中恢復整個分區表,如果備份GPT也校驗錯誤,硬盤將不可使用。具體內容如下表:
    在這裏插入圖片描述

  • Partition Table:分區表,包含分區的類型GUID(如:EFI系統分區的GUID類型是{C12A7328-F81F-11D2-BA4B-00A0C93EC93B}),名稱,起始終止位置,該分區的GUID以及分區屬性。其內容如下:
    在這裏插入圖片描述

1.2.1.GPT分區方案特點

  • 是UEFI標準的一部分,主板必須要支持UEFI標準
  • GPT分區列表支持最大128PB(1PB=1024TB)
  • 可以定義128個分區
  • 沒有主分區,擴展分區和邏輯分區的概念,所有分區都能格式化
  • gdisk管理工具可以創建GPT分區

1.3.兩種硬盤分區模式分別對應的BIOS啓動方式:

  • 硬盤分區格式爲MBR格式,啓動模式爲Legacy;
  • 硬盤分區格式爲GUID(GPT)格式,啓動模式爲UEFI。

2.fdisk tool [使用參考]

  It does not understand GPTs (GUID partition tables) and it is not designed for large partitions. In these cases, use the more advanced GNU parted.

fdisk命令參數介紹
p、打印分區表。
n、新建一個新分區。
d、刪除一個分區。
q、退出不保存。
w、把分區寫進分區表,保存並退出。

3.掛載分區

   /etc/fstab 文件負責配置Linux開機時自動掛載的分區。系統啓動時會自動從其中讀取信息,並將此文件中指定的文件系統掛載到指定的目錄。格式如下:
在這裏插入圖片描述
  <file system> <dir> <type> <options> <dump> <pass>,字段通過空格或 Tab 分隔。

  • <file systems>:要掛載的分區或存儲設備

  • <dir>:<file systems>的掛載位置。

  • <type>:要掛載的設備或分區的文件系統類型 (ext2 / ext3 / ext4 / reiserfs / xfs / jfs / smbfs / iso9660 / vfat / ntfs / swap / auto)。如果是auto,mount 命令會猜測使用的文件系統類型,對 CDROM 和 DVD 等移動設備是非常有用的。

  • <options>:掛載所帶參數。有些mount參數專屬於特定的文件系統:

auto:在啓動時或鍵入了 mount,-a 命令時自動掛載。
noauto:只在你的命令下被掛載。
exec:允許執行此分區的二進制文件。
noexec:不允許執行此文件系統上的二進制文件。
ro/rw:以(只讀/讀寫)模式掛載文件系統。
umask:設置目錄和文件的權限過濾。
 fmask/dmask:設置(文件/目錄)的權限過濾。它們是mount的選項,針對fat/ntfs文件系統,適用於fstab配置(linux的/etc/fstab 文件,Android中沒有)。其值爲掩碼,即二進制屏蔽。想得到權限5,必須設置掩碼爲2(7&(!(1<<1)))。
user:允許任意用戶掛載此文件系統。若無顯示定義,隱含啓用 noexec, nosuid, nodev 參數。
users:允許所有 users 組中的用戶掛載文件系統.
nouser:只能被 root 掛載。
owner:允許設備所有者掛載.
sync/async:I/O (同步/異步)進行。
dev/nodev:(解析/ 不解析)文件系統上的塊特殊設備。
suid/nosuid:(允許/禁止) suid 操作和設定 sgid 位。使一般用戶運行程序時臨時提升權限。
noatime:不更新文件系統上文件的inode 訪問記錄,可以提升性能(參見 atime 參數)。
nodiratime:不更新文件系統上目錄的inode 訪問記錄,可以提升性能(參見 atime 參數)。
relatime:實時更新 inode access 記錄。只有在記錄中的訪問時間早於當前訪問纔會被更新。(與 noatime 相似,但不會打斷如 mutt 或其它程序探測文件在上次訪問後是否被修改的進程。),可以提升性能(參見 atime 參數)。
flush:vfat 的選項,更頻繁的刷新數據,複製對話框或進度條在全部數據都寫入後才消失。
defaults:使用文件系統的默認掛載參數,例如 ext4 的默認參數爲:rw, suid, dev, exec, auto, nouser, async.
  • <dump>:dump 工具通過它決定何時作備份。dump 會檢查其內容,用數字決定是否對這個文件系統備份。0 忽略, 1 則備份。大部分用戶沒有安裝 dump , 應設爲 0。
  • <pass>:fsck 通過 的值決定需要檢查的文件系統的檢查順序。0 表示設備不會被 fsck 檢查。 根目錄應當獲得最高的優先權 1。其它所有需要被檢查的設備設置爲 2。

4.分區測試

dd if=<Input File> of=<Output File> bs=<Bytes> count=<Count>

參數註釋:

  • if=文件名:輸入文件名,缺省爲標準輸入。即指定源文件。< if=input file >
  • of=文件名:輸出文件名,缺省爲標準輸出。即指定目的文件。< of=output file >
  • ibs=bytes:一次讀入bytes個字節,即指定一個塊大小爲bytes個字節。
  • obs=bytes:一次輸出bytes個字節,即指定一個塊大小爲bytes個字節。
  • bs=bytes:同時設置讀入/輸出的塊大小爲bytes個字節。
  • cbs=bytes:一次轉換bytes個字節,即指定轉換緩衝區大小。
  • skip=blocks:從輸入文件開頭跳過blocks個塊後再開始複製。
  • seek=blocks:從輸出文件開頭跳過blocks個塊後再開始複製。
    • 注意:通常只用當輸出文件是磁盤或磁帶時纔有效,即備份到磁盤或磁帶時纔有效。
  • count=blocks:僅拷貝blocks個塊,塊大小等於ibs指定的字節數。
  • conv=conversion:用指定的參數轉換文件。

注意:指定數字的地方若以下列字符結尾,則乘以相應的數字:b=512;c=1;k=1024;w=2

4.1.Example

4.1.1.dd if=/dev/zero of=/tmp/1G.txt bs=1K count=1024000

  • 輸入源爲 /dev/zero,每次寫入1K個字節,執行1024000次,相當於寫了1G的內容到 /tmp/1G.txt.

4.1.2.dd if=/dev/fd0 of=disk.img count=1 bs=1440k (即塊大小爲1.44M)

4.1.3.創建硬盤的映像

  爲硬盤創建一個圖像文件並將其保存在其他存儲設備。這種備份方式有很多好處:一是易於使用,二是這種備份方法的速度快於其他方法的備份,也能讓你更快速的恢復數據。

創建一個硬盤/dev/sda的image命令:

[root@linuxprobe ~]# dd if=/dev/sda of=~/sdadisk.img

恢復硬盤映像文件恢復數據:

[root@linuxprobe ~]# dd if=sdadisk.img of=/dev/sdb
sdadisk.img文件是/dev/sda的映像,將恢復/dev/sda的映像到/dev/sdb

5.Debug

5.1.加載驅動成功後,查看log:

root@colibri-imx6ull:~# dmesg | egrep "(sdhci|mmc)"
[    1.880782] sdhci: Secure Digital Host Controller Interface driver
[    1.890679] sdhci: Copyright(c) Pierre Ossman
[    1.898540] sdhci-pltfm: SDHCI platform and OF driver helper
[    1.909980] sdhci-esdhc-imx 2190000.usdhc: Got CD GPIO
[    1.984346] mmc0: SDHCI controller on 2190000.usdhc [2190000.usdhc] using ADMA

5.2.cat /proc/devcies

Block devices:
179 mmc

5.3./dev目錄

brw-rw----    1 0        0         179,   0 Jan  1 00:00 mmcblk0
brw-rw----    1 0        0         179,   1 Jan  1 00:00 mmcblk0p1
brw-rw----    1 0        0         179,  10 Jan  1 00:00 mmcblk0p10
brw-rw----    1 0        0         179,  11 Jan  1 00:00 mmcblk0p11
brw-rw----    1 0        0         179,  12 Jan  1 00:00 mmcblk0p12
brw-rw----    1 0        0         179,  13 Jan  1 00:00 mmcblk0p13
brw-rw----    1 0        0         179,  14 Jan  1 00:00 mmcblk0p14
brw-rw----    1 0        0         179,  15 Jan  1 00:00 mmcblk0p15
brw-rw----    1 0        0         179,  16 Jan  1 00:00 mmcblk0p16
brw-rw----    1 0        0         179,  17 Jan  1 00:00 mmcblk0p17
brw-rw----    1 0        0         179,   2 Jan  1 00:00 mmcblk0p2
brw-rw----    1 0        0         179,   3 Jan  1 00:00 mmcblk0p3
brw-rw----    1 0        0         179,   4 Jan  1 00:00 mmcblk0p4
brw-rw----    1 0        0         179,   5 Jan  1 00:00 mmcblk0p5
brw-rw----    1 0        0         179,   6 Jan  1 00:00 mmcblk0p6
brw-rw----    1 0        0         179,   7 Jan  1 00:00 mmcblk0p7
brw-rw----    1 0        0         179,   8 Jan  1 00:00 mmcblk0p8
brw-rw----    1 0        0         179,   9 Jan  1 00:00 mmcblk0p9

  如上所示:mmcblk0 代表當前的sdcard,mmcblk0p1- mmcblk0p17代表sdcard的分區。

5.4./sys/block/

[root@xxx mmcblk0]# ls -l
total 0
-r--r--r--    1 0        0             4096 Jan  1 00:03 alignment_offset
lrwxrwxrwx    1 0        0                0 Jan  1 00:03 bdi -> ../../../../../../../virtual/bdi/179:0
-r--r--r--    1 0        0             4096 Jan  1 00:03 capability
-r--r--r--    1 0        0             4096 Jan  1 00:00 dev
lrwxrwxrwx    1 0        0                0 Jan  1 00:03 device -> ../../../mmc0:59b4
-r--r--r--    1 0        0             4096 Jan  1 00:03 discard_alignment
-r--r--r--    1 0        0             4096 Jan  1 00:03 ext_range
-rw-r--r--    1 0        0             4096 Jan  1 00:03 force_ro
drwxr-xr-x    2 0        0                0 Jan  1 00:03 holders
-r--r--r--    1 0        0             4096 Jan  1 00:03 inflight
drwxr-xr-x    4 0        0                0 Jan  1 00:00 mmcblk0p1
drwxr-xr-x    4 0        0                0 Jan  1 00:00 mmcblk0p10
drwxr-xr-x    4 0        0                0 Jan  1 00:00 mmcblk0p11
drwxr-xr-x    4 0        0                0 Jan  1 00:00 mmcblk0p12
drwxr-xr-x    4 0        0                0 Jan  1 00:00 mmcblk0p13
drwxr-xr-x    4 0        0                0 Jan  1 00:00 mmcblk0p14
drwxr-xr-x    4 0        0                0 Jan  1 00:00 mmcblk0p15
drwxr-xr-x    4 0        0                0 Jan  1 00:00 mmcblk0p16
drwxr-xr-x    4 0        0                0 Jan  1 00:00 mmcblk0p17
drwxr-xr-x    4 0        0                0 Jan  1 00:00 mmcblk0p2
drwxr-xr-x    4 0        0                0 Jan  1 00:00 mmcblk0p3
drwxr-xr-x    4 0        0                0 Jan  1 00:00 mmcblk0p4
drwxr-xr-x    4 0        0                0 Jan  1 00:00 mmcblk0p5
drwxr-xr-x    4 0        0                0 Jan  1 00:00 mmcblk0p6
drwxr-xr-x    4 0        0                0 Jan  1 00:00 mmcblk0p7
drwxr-xr-x    4 0        0                0 Jan  1 00:00 mmcblk0p8
drwxr-xr-x    4 0        0                0 Jan  1 00:00 mmcblk0p9
drwxr-xr-x    2 0        0                0 Jan  1 00:03 power
drwxr-xr-x    3 0        0                0 Jan  1 00:03 queue
-r--r--r--    1 0        0             4096 Jan  1 00:03 range
-r--r--r--    1 0        0             4096 Jan  1 00:03 removable
-r--r--r--    1 0        0             4096 Jan  1 00:03 ro
-r--r--r--    1 0        0             4096 Jan  1 00:03 size
drwxr-xr-x    2 0        0                0 Jan  1 00:03 slaves
-r--r--r--    1 0        0             4096 Jan  1 00:03 stat
lrwxrwxrwx    1 0        0                0 Jan  1 00:03 subsystem -> ../../../../../../../../class/block
-rw-r--r--    1 0        0             4096 Jan  1 00:03 uevent

//cd mmcblk0p3
[root@xxx mmcblk0p3]# ls -l
total 0
-r--r--r--    1 0        0             4096 Jan  1 00:05 alignment_offset
-r--r--r--    1 0        0             4096 Jan  1 00:00 dev
-r--r--r--    1 0        0             4096 Jan  1 00:05 discard_alignment
drwxr-xr-x    2 0        0                0 Jan  1 00:05 holders
-r--r--r--    1 0        0             4096 Jan  1 00:05 inflight
-r--r--r--    1 0        0             4096 Jan  1 00:05 partition
drwxr-xr-x    2 0        0                0 Jan  1 00:05 power
-r--r--r--    1 0        0             4096 Jan  1 00:05 ro
-r--r--r--    1 0        0             4096 Jan  1 00:05 size
-r--r--r--    1 0        0             4096 Jan  1 00:05 start
-r--r--r--    1 0        0             4096 Jan  1 00:05 stat
lrwxrwxrwx    1 0        0                0 Jan  1 00:05 subsystem -> ../../../../../../../../../class/block
-rw-r--r--    1 0        0             4096 Jan  1 00:05 uevent

5.5./sys/bus/mmc/devices/mmc:59b4

[root@xxx mmc0:59b4]# ls -l
total 0
drwxr-xr-x    3 0        0                0 Jan  1 00:00 block
-r--r--r--    1 0        0             4096 Jan  1 00:06 cid
-r--r--r--    1 0        0             4096 Jan  1 00:06 csd
-r--r--r--    1 0        0             4096 Jan  1 00:06 date
lrwxrwxrwx    1 0        0                0 Jan  1 00:06 driver -> ../../../../../../bus/mmc/drivers/mmcblk
-r--r--r--    1 0        0             4096 Jan  1 00:06 dsr
-r--r--r--    1 0        0             4096 Jan  1 00:06 erase_size
-r--r--r--    1 0        0             4096 Jan  1 00:06 fwrev
-r--r--r--    1 0        0             4096 Jan  1 00:06 hwrev
-r--r--r--    1 0        0             4096 Jan  1 00:06 manfid
-r--r--r--    1 0        0             4096 Jan  1 00:06 name
-r--r--r--    1 0        0             4096 Jan  1 00:06 ocr
-r--r--r--    1 0        0             4096 Jan  1 00:06 oemid
drwxr-xr-x    2 0        0                0 Jan  1 00:06 power
-r--r--r--    1 0        0             4096 Jan  1 00:06 preferred_erase_size
-r--r--r--    1 0        0             4096 Jan  1 00:06 scr
-r--r--r--    1 0        0             4096 Jan  1 00:06 serial
-r--r--r--    1 0        0             4096 Jan  1 00:06 ssr
lrwxrwxrwx    1 0        0                0 Jan  1 00:06 subsystem -> ../../../../../../bus/mmc
-r--r--r--    1 0        0             4096 Jan  1 00:06 type
-rw-r--r--    1 0        0             4096 Jan  1 00:00 uevent

5.6./sys/kernel/debug/mmc0/

[root@xxx mmc0]# ls -l
total 0
-rw-------    1 0        0                0 Jan  1 00:00 clock
-r--------    1 0        0                0 Jan  1 00:00 ios
drwxr-xr-x    2 0        0                0 Jan  1 00:00 mmc0:59b4

[root@xxx mmc0]# cat ios 
clock:          400000 Hz
vdd:            21 (3.3 ~ 3.4 V)
bus mode:       2 (push-pull)
chip select:    0 (don't care)
power mode:     2 (on)
bus width:      0 (1 bits)
timing spec:    0 (legacy)
signal voltage: 0 (3.30 V)
driver type:    0 (driver type B)

5.7.gpio65 cd(card-detection) irq

[root@xxx]#  cat /proc/interrupts | egrep "(mmc|cd)"
103:          0  megahunt_pio_edge  65 Edge      d4280000.sdhci cd
166:         39     GICv3  92 Level     mmc0

[root@xxx ]# cat /d/gpio | grep cd
 gpio-65  (                    |cd                  ) in  lo   

6.遇到問題

6.1.格式化sdcard 分區失敗

#mkfs.ext4 /dev/mmcblk0p13
read-only file system while setting up superblock

#mount -t ext4 /dev/mmcblk0p13 /mnt/text

解決:在dtsi添加disable-wp;解除寫保護即可。

drivers/mmc/core/host.c:
if(device_property_read_bool(dev, "disable-wp"))
	host->cap2 |= MMC_CAP2_NO_WRITE_PROTECT;

7.問題

7.1.在加載sdcard驅動時,內核如何知道當前有幾個分區?

  檢測分區流程:
在這裏插入圖片描述
重點分析Check_partition:
在這裏插入圖片描述
核心部分是check_part,該結構體保存對應的解析分區的算法:
在這裏插入圖片描述
  項目中使用的是efi_partition,最後通過add_partition()將這些part信息添加到disk裏去。從開機Log看到有多少分區:
在這裏插入圖片描述
  通過平臺上定義的partition.xml]文件中進行驗證。

refer to

  • https://blog.csdn.net/kris_fei/article/details/77368338
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章