1. 程式人生 > >linux驅動由淺入深系列:塊裝置驅動之一(高通eMMC分割槽例項)

linux驅動由淺入深系列:塊裝置驅動之一(高通eMMC分割槽例項)

塊裝置驅動的模型還是基本基於字元裝置驅動的,可以簡單理解為塊裝置僅僅增加了操作緩衝區,對使用者請求順序進行佇列重拍等等。字元裝置驅動的相關分析可以檢視本部落格相關的博文。 

按照本部落格的行文習慣,在具體分析塊裝置驅動程式碼之前,我們會從整體上了解一下研究物件的特徵,以及使用者空間的使用方法。下面我們就自己寫一個小工具(可以讀取Rom中任意一個物理扇區的內容)來分析一下高通的分割槽資訊。

在使用者空間看到的塊裝置當然是以塊裝置節點展現的,如下圖。其中mmcblk開頭的就是今天我們分析的重點,可以看到這些檔名分為三類:mmcblk0、mmcblk0pX、mmcblk0rpmb。其中mmcblk0是裝置節點,其餘的為該裝置的分割槽節點(mmcblk0rpmb RPMB是Replay Protected Memory Block的縮寫,他的存在目的是用來給系統存放一些特殊的、需要進行訪問授權的資料。暫時不做考慮)。Mmcblk0是當前系統的第一個mmc裝置(為我們的eMMC儲存器),如果插入tf卡,應該會出現mmcblk1裝置。


下面我們來實現一個使用者空間的小程式來讀取eMMC中的原始資料進行分析。

我們在external/資料夾下建立radia_test.c、android.mk,程式碼如下:

radia_test.c

/*************************************************************************
    File Name: radia_test.c
    Author: [email protected]
    Created Time: 2017.6.9
	brief:adjust audio parameters
 ************************************************************************/
#include <stdio.h> 
#include <errno.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <stdlib.h>
#include <string.h>
#include <linux/fs.h> 

//extern int errno; 

int get_disk_sector(int fd){ 
	int sectorsize; 

	ioctl(fd, BLKSSZGET, §orsize) ; 

	return sectorsize; 
} 
/** 
* read_disk_sector: 
* @dev: raw disk FILE * 
* @sector: 
* return is the disk sectorsize 
* */ 
int read_disk_sector(int fd, unsigned long sector, char **p){ 
	int sectorsize; 
	FILE *fp; 

	/* get disk sector size */ 
	sectorsize = get_disk_sector(fd); 
	if (sectorsize == 0){ 
	fprintf(stderr, "get disk sector size failed\n"); 
	return (-1); 
	} 

	/* seek it */ 
	lseek(fd, 0 ,SEEK_SET);

	//注,在offset設定得過大時,lseek可能返回OVERFLOW的錯誤,但實際上,它已經執行了定位,只是返回的值超出了範圍。返回值為-1時,此時要判斷一下錯誤號
	if (lseek(fd, (sectorsize * sector), SEEK_CUR) == -1 ){ 
	fprintf(stderr, "seek to %d failed\n" 
	, sectorsize * sector); 
	return (-1); 
	} 
	/* read it */ 
	*p = (char *)malloc(sectorsize); 
	if (*p == NULL){ 
	fprintf(stderr, "malloc memory failed\n"); 
	return (-1); 
	} 

	return read(fd, *p, sectorsize); 
} 
/* dump data for display */ 
void dump_disk_sector(char *p, int size){ 
	int i; 
	for (i = 0; i< size; i++){ 
		if (i % 16 == 0 && i != 0) 
			printf("\n"); 
		printf("0x%02x,", (unsigned int )*p++ & 0xff); 
	} 

	printf("\n"); 
	return ; 
} 

int main(int argc, char **argv){ 
	char *d; 
	int size, sector_num; 
	int fd; 
	char dev[50] = "/dev/block/mmcblk0"; 

	printf("enter read mmcblk0 sector:\n");
	if(argc != 3)
		printf("error num of arg!\n");
	else{
		strcpy(dev, argv[1]);
		sscanf(argv[2], "%d", §or_num);
		printf("read sector_num:%d\n", sector_num);
	}
	/* open it */ 
	fd = open(dev, O_RDONLY); 
	if (fd == -1){ 
	//fprintf(stderr, "open %s failed %s\n", dev, strerror(errno)); 
	return (-1); 
	} 

	size = read_disk_sector(fd, sector_num, &d); 
	printf("sector size:%d\n", size);
	close(fd); 

	if (size <= 0) return (0); 

	dump_disk_sector(d, size); 

	free(d); 

	return (0); 
}

android.mk
LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_SRC_FILES:= radia_test.c
LOCAL_MODULE := radia_test
LOCAL_MODULE_TAGS := optional

include $(BUILD_EXECUTABLE)

使用mm命令編譯出radia_test的bin檔案。 

adb push radia_test  /system/bin

使用方法,第一個引數為塊裝置檔案的路徑,第二個引數為扇區號。

如下讀出eMMC中的0 扇區資料:



可能比較抽象,簡單介紹一下GPT分割槽的結構:


結構

LBA 0

GPT分割槽表的最開頭,處於相容性考慮仍然儲存了一份傳統的MBRLBA 0),這個MBR也叫做保護性MBRProtective MBR)。

保護性MBR保護GPT磁碟不受以前釋出的MBR磁碟工具(比如FDISKWindowsNT磁碟管理器)的危害。這些工具不能感知GPT,也無法正確地訪問GPT磁碟。不能識別GPT的舊軟體在訪問GPT磁碟時只解釋保護性MBR。這些工具通過解釋保護性MBR,將GPT磁碟看成一個封裝的(可能無法識別)分割槽,而不是錯誤地當成一個未分割槽的磁碟,並且拒絕對硬碟進行操作,除非使用者特別要求刪除這個分割槽。這就避免了意外刪除分割槽的危險。例如,當在32位的Windows XP系統中掛載GPT磁碟時,會將其識別為GPT保護分割槽GPT Protective Partition,並且使用者無法對這個分割槽進行任何操作(除非使用命令列工具)[2],這是因為32位的Windows XP並不支援GPT,它僅僅只是知道掛載的是一個GPT磁碟而已。

在支援從GPT啟動的作業系統中,這裡也用於儲存第一階段的啟動程式碼。在這個MBR中,只有一個標識為0xEE的分割槽,以此來表示這塊硬碟使用GPT分割槽表。

另外,能夠識別GPT分割槽表的作業系統會檢查保護MBR中的分割槽表,如果分割槽型別不是0xEE或者MBR分割槽表中有多個項,也會拒絕對硬碟進行操作。

在使用MBR/GPT混合分割槽表的硬碟中,這部分儲存了GPT分割槽表的一部分分割槽(通常是前四個分割槽),可以使不支援從GPT啟動的作業系統從這個MBR啟動,啟動後只能操作MBR分割槽表中的分割槽。如就是使用這種方式啟動Windows

LBA 1

分割槽表頭LBA 1)定義了硬碟的可用空間以及組成分割槽表的項的大小和數量。在使用64的機器上,最多可以建立128個分割槽,即分割槽表中保留了128個項,其中每個都是128位元組。(EFI標準要求分割槽表最小要有16,384位元組,即128個分割槽項的大小)

分割槽表頭還記錄了這塊硬碟的GUID,記錄了分割槽表頭本身的位置和大小(位置總是在LBA 1)以及備份分割槽表頭和分割槽表的位置和大小(在硬碟的最後)。它還儲存著它本身和分割槽表的CRC32校驗。韌體、載入程式和作業系統在啟動時可以根據這個校驗值來判斷分割槽表是否出錯,如果出錯了,可以使用軟體從硬碟最後的備份GPT中恢復整個分割槽表,如果備份GPT也校驗錯誤,硬碟將不可使用。所以GPT硬碟的分割槽表不可以直接使用16進位制編輯器修改。

分割槽表頭的格式

起始位元組

 長度

 內容

0

8位元組

簽名("EFI PART"

8

4位元組

修訂

12

4位元組

分割槽表頭的大小

16

4位元組

分割槽表頭(第091位元組)的CRC32校驗,在計算時,把這個欄位作為0處理,需要計算出分割槽序列的CRC32校驗後再計算本欄位

20

4位元組

保留,必須是 0

24

8位元組

當前LBA(這個分割槽表頭的位置)

32

8位元組

備份LBA(另一個分割槽表頭的位置)

40

8位元組

第一個可用於分割槽的LBA(主分割槽表的最後一個LBA + 1

48

8位元組

最後一個可用於分割槽的LBA(備份分割槽表的第一個LBA − 1

56

16位元組

硬碟GUID(在UNIX系統中也叫UUID

72

8位元組

分割槽表項的起始LBA(在主分割槽表中是2

80

4位元組

分割槽表項的數量

84

4位元組

一個分割槽表項的大小(通常是128

88

4位元組

分割槽序列的CRC32校驗

92

*

保留,剩餘的位元組必須是0(對於512位元組LBA的硬碟即是420個位元組)


主分割槽表和備份分割槽表的頭分別位於硬碟的第二個扇區(LBA 1)以及硬碟的最後一個扇區。備份分割槽表頭中的資訊是關於備份分割槽表的。[3]

LBA 2–33

LBA 2–33的位置存放的是分割槽表項GPT分割槽表使用簡單而直接的方式表示分割槽。一個分割槽表項的前16位元組是分割槽型別GUID。例如,EFI系統分割槽的GUID型別是{C12A7328-F81F-11D2-BA4B-00A0C93EC93B}。接下來的16位元組是該分割槽唯一的GUID(這個GUID指的是該分割槽本身,而之前的GUID指的是該分割槽的型別)。再接下來是分割槽起始和末尾的64LBA編號,以及分割槽的名字和屬性。[3]

GPT分割槽表項的格式

起始位元組

 長度

 內容

0

16位元組

分割槽型別GUID

16

16位元組

分割槽GUID

32

8位元組

起始LBA(小端格式)

40

8位元組

末尾LBA

48

8位元組

屬性標籤(如:60表示"只讀")

56

72位元組

分割槽名(可以包括36個UTF-16(小端格式)字元)

瞭解了GPT的大概內容,我們再回來看讀取到的0 sector,其中分割槽表位置指示的分割槽型別為0xee。僅僅起保護作用,不做過多分析。

重點來看第1 sector:


按照上面的知識,我們可以瞭解到當前磁碟有0x34個分割槽,一個分割槽表項的大小為0x80等等。

讀取第2、3、4sector:看到各個分割槽的相關資訊,如分割槽其實位置,結束位置等。




上面有五十個分割槽節點,都是高通平臺把ROM按需進行的分割。ls –al /dev/block/platform/soc/7824900.sdhci/by-name可以看到各個分割槽的別名:


如下是各個分割槽的簡介:

 LabelPurpose of this partition


Modem     Partition for modem
FscCookie partition to store Modem File System’s cookies.
Ssd          Partition for ssd diag module. stores the encrypted RSA keys
sbl1          Partition for secondary boot loader
sbl1bak     Back up Partition for secondary boot loader
Rpm         Partition for rpm image
Rpmbak    Back up  Partition for rpm image
Tz            Partition for tz image
tzbak        Back up  Partition for tz image
Hyp          Partition for hypervisor image
hypbak     Back up  Partition for hypervisor image
Dsp          Partition for adsp dymanic loaders image
modemst1     Copy of Modem File System (Encrypted)
modemst2     Copy of Modem File System (Encrypted)
DDR         Partition for DDR.
Fsg          Golden copy or backup of Modem File System (Encrypted). Also used to pre-populate the file system.
Sec          Sec.dat contains fuse settings, mainly for secure boot and oem setting
splash      The splash screen is displayed during the apps bootloader (also called the LK). The display driver in LK will read the splash image data from a separate eMMC partition named as ’splash’
aboot        Partition for apps boot loader
abootbak  Back up Partition for apps boot loader
boot         This is the boot partition of your android device,It includes the android kernel and the ramdisk.
recovery   This is specially designed for backup. The recovery partition can be considered as an alternative boot partition
devinfo     Device information including:iis_unlocked, is_tampered, is_verified, charger_screen_enabled, display_panel, bootloader_version, radio_version All these attirbutes are set based on some specific conditions and written on devinfo partition,.
system    This partition contains the entire Android OS, other than the kernel and the ramdisk. This includes the Android GUI and all the system applications that come pre-installed on the device
cache      This is the partition where Android stores frequently accessed data and app components
persist     Partition entry for persist image. which contains data which shouldn’t be changed after the device shipped, for example: calibration data of chips(wifi, bt, camera, etc.), certificates and other security related files. 
misc        This partition contains miscellaneous system settings in form of on/off switches. These settings may include CID (Carrier or Region ID), USB configuration and certain hardware settings etc
keystore  Partition for keystore service.
config      Partition needed during display panel initialization. More info at Display_panel_configuration_in_Device_Tree
oem        "It is meant for storing OEM specific info. Customer in this case can decide whether he wants to keep this partition or not typically reserved partitions are kept for future use
limits      Partition to store LMh params on 8976 target. LMh (Limits management) driver in SBL writes the LMh HW trimmed data into separate partition and uses the same data for later reboots
mota       Backup partition for M ota upgrade
devcfg     Partition needed by TZ for M upgrades.
Dip         Partition needed for  SafeSwitch, feature (FR26255) designed to allow OEMs and carriers to address new smartphone theft bill issues.
mdtp       Partition needed for  SafeSwitch, feature (FR26255) designed to allow OEMs and carriers to address new smartphone theft bill issues.
userdata  Partition for userdata image       
cmnlib     Verified boot feature introduced in M needLK to load cmnlib corresponding partitions
keymaster     Verified boot feature introduced in M needs LK to load keymaster from corresponding partitions
syscfg     Syscfg is internal testing for Vmin and CPR  characterization
mcfg        All MBNs place holder in flash. Specific MBN would be loaded by mcfg image based on the SIM/Carrier.
msadp     used for modem debug policy
apdp        used for persisting the debug policy. "Debug policy" is used to better support development and debug on secure/fuse-blown devices One instance of the debug policy will be signed for the AP
dpo         This partition will store a policy override


相關推薦

linux驅動由淺入深系列裝置驅動之一eMMC分割槽例項

塊裝置驅動的模型還是基本基於字元裝置驅動的,可以簡單理解為塊裝置僅僅增加了操作緩衝區,對使用者請求順序進行佇列重拍等等。字元裝置驅動的相關分析可以檢視本部落格相關的博文。 按照本部落格的行文習慣,在具體分析塊裝置驅動程式碼之前,我們會從整體上了解一下研究物件的特徵,以及使用者

linux驅動由淺入深系列裝置驅動之三裝置驅動結構分析,以mmc為例

linux驅動由淺入深系列:塊裝置驅動之一(高通eMMC分割槽例項)前一篇文章介紹了塊裝置驅動在linux框架張的位置關係,本文來分析一下驅動本身。塊裝置驅動的模型還是基本基於字元裝置驅動的,可以簡單理解為塊裝置僅僅增加了操作緩衝區,對使用者操作請求進行佇列重排。因此只在有了

linux驅動由淺入深系列PBL-SBL1-(bootloader)LK-Android啟動過程詳解之一MSM8953啟動例項【轉】

本文轉載自:https://blog.csdn.net/radianceblau/article/details/73229005 對於嵌入式工程師瞭解晶片啟動過程是十分有必要的,在分析、除錯各種問題的時候都有可能涉及到這方面的知識。同時這部分知識也是比較複雜的,因為其中涉及到晶片內部架構,啟動各個階段軟體

linux驅動由淺入深系列usb子系統之三usb系統中的裝置、配置、介面、端點概念及程式碼解釋

一個usb裝置對應一個或多個配置 一個配置包含一個或多個usb介面 一個usb介面可能存在一種或多種設定 一個設定會使用零個或多個usb端點裝置 裝置就是一個usb物理裝置,一個usb裝置可以只包含一個簡單功能的device,也可以包含一個由hub連線的多個裝置,叫作複合裝

Linux驅動開發04裝置驅動和網路裝置驅動

介紹 因為塊裝置驅動和網路裝置驅動實際中用得較少,所以只給出驅動模板,我也沒有具體測試,等到實際用到是再研究吧,溜了溜了。 塊裝置驅動模板 struct xxx_dev { int size; struct request_q

linux驅動由淺入深系列usb子系統之四android平臺滑鼠驅動程式碼分析

android上的usb口是支援OTG(on the go)的,USB OTG既可以作為Host又可以作為Device,我們本文來看一下android手機作為Host連線滑鼠的情況。OTG是如何做到既可以做Host又可以作為Device的呢 標準usb接頭中有四根線:vbu

linux驅動由淺入深系列ALSA框架詳解 音訊子系統之二

本文以高通平臺為例,介紹一下android下的音訊結構。android使用的是tinyALSA作為音訊系統,使用方法和基本框架與linux中常用的ALSA音訊子系統是一致的。ALSA音訊框架ALSA(Advanced Linux Sound Architecture)是一個開

linux驅動由淺入深系列輸入子系統之二(編寫一個gpio_key驅動)

本系列導航: 在上一篇文章中我們大致瞭解了linux input subsystem的功能及應用層的使用,本文我們一起來看一看驅動程式碼的編寫。接下來一篇,計劃寫一下應用層如何模擬按鍵訊息,產生與按下實際按鍵相同的效果。 在“linux驅動由淺入深系列:驅動程式的基

linux驅動由淺入深系列tinyalsa(tinymix/tinycap/tinyplay/tinypcminfo)音訊子系統之一

目前linux中主流的音訊體系結構是ALSA(Advanced Linux Sound Architecture),ALSA在核心驅動層提供了alsa-driver,在應用層提供了alsa-lib,應用程式只需要呼叫alsa-lib提供的API就可以完成對底層硬體的操作。說的

linux驅動由淺入深系列輸入子系統之三(應用層模擬input_event)

本系列導航: 在上一篇文章中編寫了gpio_key的驅動,可以看到每次gpio_key按下會上報event到/dev/input /event7節點。其實在應用層是可以完全模擬出這個按鍵過程的,原理是向EV_KEY型別的eventX訊息節點write event將

linux驅動由淺入深系列usb子系統之一(域、包、事務、傳輸的基本概念)

本文從usb協議的物理層講起,對usb建立一個整體的概念再進行逐步細化。 下圖是usb2.0協議的物理層連線,其中包括一根地線、一根電源線(在usb2.0中電源線僅支援到5V 500mA,目前隨著人們需求的日益膨脹,在後續協議中usb線提供的供電能力正在不斷增加)、兩根差分

linux驅動由淺入深系列顯示子系統之二(基於android的分析)

上一篇文章中介紹了應用層對顯示系統的使用,我們操作framebuffer在螢幕上畫出了圖形。這次我們一起來看一下android中顯示子系統各個模組的功能。android系統音訊系統在高通平臺上的框圖:HWUIUI硬體加速,從Androd 3.0(Honeycomb)開始,An

linux驅動由淺入深系列sensor架構例項分析之一

本系列導航: 最初的時候晶片廠家對sensor的處理和對待其它外設一樣都是直接掛在processor上,sensor的驅動也和其他linux或android的驅動一樣,生成對應的裝置節點給上層提供資料(關於此類linux基礎驅動的知識,可以參考本部落格其他博文)

linux驅動由淺入深系列驅動程式的基本結構概覽之一第一個驅動程式

本系列導航: 提到linux驅動程式,首先應該知道它是linux的核心模組。那麼想要編寫驅動程式,就要首先認識一下linux的核心模組機制。Linux核心模組是使得複雜而龐大的linux核心條理清晰、可裁剪、高相容性的重要特性。 Linux核心模組的特點: 1, 

linux驅動由淺入深系列顯示子系統之一(通過FrameBuffer在螢幕上畫出圖形)

顯示子系統對應用層提供的介面叫做framebuffer,一般位於/dev/fb0(下文示例運行於adroid的平臺位於/dev/graphics/fb0,不過它們都是一樣的),它為上層提供了統一的對顯示卡的描述。首先要明確的是lcd顯示子系統雖然複雜,但其任然是基本的字元裝

linux驅動由淺入深系列camera驅動之二基於平臺的V4L2結構及程式碼分析

在上一篇文章中介紹了camera的基礎知識和相關概念,我們一起來了解一下驅動相關的程式碼結構。本文以高通+android平臺為示例,首先看一下整體框圖:這張圖是從整體上來看的1,圖中最下面的是kernel層的驅動,其中按照V4L2架構實現了camera sensor等驅動,向

linux集群系列(1) --- LVS之load balancingNET、DR、TUN

lvs lb nat 一、簡介 1.1. 負載均衡集群:LB (load balancing) 負載均衡集群為企業需求提供了更實用的系統。如名稱所暗示的,該系統使負載可以在計算機集群中盡可能平均地分攤處理。該負載可能是需要均衡的應用程序處理負載或網絡流量負載。這樣的系統非常適合於運行同

Linux Device Drivers》第十六章 裝置驅動程式——note

簡介 一個塊裝置驅動程式主要通過傳輸固定大小的隨機資料來訪問裝置 Linux核心視塊裝置為與字元裝置相異的基本裝置型別 Linux塊裝置驅動程式介面使得塊裝置可以發揮其最大的功效,但是其複雜程式又是程式設計者必須面對的一個問題 一個數據塊指的是固

Linux驅動開發11裝置樹】nanopi的PWM驅動

介紹 前兩節利用裝置樹實現了nanopi的LED驅動和按鍵驅動,這一節來實現nonapi的PWM驅動。PWM驅動在核心中也有相應的實現,因此這裡只是按照要求新增裝置樹檔案即可。這一節和之前一樣,首先修改裝置樹檔案進行測試,然後分析核心相應的軟體實現。 新增裝置樹節點 因為在s

Linux驅動開發10裝置樹】nanopi的按鍵驅動

介紹 這一節在nanopi上實現按鍵驅動,和LED驅動一樣,通用的按鍵驅動在linux核心中已經實現好,我們只需要按照要求寫好裝置樹即可,不用我們自己實現按鍵驅動。這一節中首先修改裝置樹並測試按鍵驅動,然後分析drivers/input/keyboard/gpio_keys.c檔案,