硬盘与文件系统
- 硬盘物理结构
- MBR分区
- GPU分区
- FAT
- ROM Layout
硬盘物理结构
以一个机械硬盘为例,内部包括磁片、主轴、速写磁头、传动手臂、传动轴、反力矩弹簧装置,SSD没有这样的结构,但都有一个相同的存储介质(主轴外一圈的部分)右边为存储介质的内部情况。
MBR分区
主引导记录MBR(Master Boot Record) Leagcy 启动最后就是通过读MBR做校验检测硬盘是否存在系统等
扇区0 | 扇区1 | 扇区2 | 扇区3 | … | … | 扇区N-2 | 扇区N-1 | 扇区N |
MBR |
通常磁盘512 Byte分为一个扇区(Logical Block Address 0)LBA0, MBR存放在磁盘的第一个扇区, 用4个字节(StartingLBA)表示该分区的起始扇区号,4个字节(SizelnLBA)表示该分区拥有的总扇区数,最大只能支持4个分区(每个分区最大是2T 4G扇区数x512B每扇区 =2TB)下图为MBR的组成:0X55 0xAA相当于标志符
MBR最多有四个分区,下表为分区信息结构:
存储字节位 | 内容及含义 |
第1字节 | 引导标志,若值为80H表示活动分区,若值为00H表示非活动分区 |
第2、3、4字节 | 本分区的起始磁头号、扇区号、柱面号。其中:磁头号——第2字节、扇区号——第3字节的低6位、柱面号——第3字节高2位+第4字节8位 |
第5字节 | 分区类型符 00H——表示该分区未用(即没有指定)、06H——FAT16基本分区、0BH——FAT32基本分区、05H——扩展分区、07H——NTFS分区、0FH——(LBA模式)扩展分区(83H为Linux分区等) |
第6、7、8字节 | 磁头号——第6字节、扇区号——第7字节的低6位、柱面号——第3字节高2位+第8字节 |
第9、10、11、12字节 | 本分区之前已用的扇区数 |
第13、14、15、16字节 | 本分区的总扇区数 |
GPU分区
GPT(GUID Partition table), 为了弥补MBR的不足, Intel设计了GPT分区。GPT分区支持更大容量, 更多分区(Windows最大支持128个), 更加安全(首尾部分分别保存了一份相同的分区表), 兼容MBR。
0号扇区称为保护性MBR,同MBR硬盘的0号扇区格式相同。其主要作用是兼容 MBR硬盘时代的工具,防止这些工具因不识别GPT格式而破坏硬盘。
扇区0 | 扇区1 | 扇区2 | 扇区3 | 扇区4 | … | … | 扇区N-2 | 扇区N-1 | 扇区N |
MBR | GPT头 | 分区表项1、2、3、4 | 分区表项5 | 分区表项6 | 备份GPT头 |
硬盘的1号扇区称为G P T头,存储了硬盘的结构信息,主要包括:G P T头标志 “EFIPART”、表头字节数、表头CRC32校验码、GPT头和备份表头地址、可用于分区的扇区范围
// GPT分区表项结构体
typedef struct {
EFI_GUID PartitionTypeGUID; //分区类型GUID, 0表示此项为空
EFI_GUID UniquePartitionGUID;//分区标志GUID
EFI_LBA StartingLBA; //分区的首扇区
EFI_LBA EndingLBA; //分区的尾扇区
UINT64 Attributes; //分区属性
CHARI6 PartitionName[36]; //分区名字符串,必须以0x0000结尾
} EFI_PARTITION_ENTRY;
FAT
每个UEFI系统至少有一个ESP(EFI System Partition)分区, 在这个分区上存放启动文件. EFI也要有读取文件的功能. UEFI内置的文件系统基于FAT开发.
文件配置表 (英文: File Allocation Table, 首字母缩略字: FAT)是一种由微软发明的并带有部分专利的文件系统, 供MS-DOS使用, 也是非NT内核的微软窗口使用的文件系统. FAT文件系统考虑当时计算机效能有限, 所以未被复杂化, 因而被几乎所有个人计算机的操作系统支持. 这特性使它成为理想的软盘和记忆卡文件系统, 也适合用作不同操作系统中的数据交流.
DrivIver Binding流程:
UEFI设计了一种简单的文件系统协议UEFI File System.
gEfiSimpleFileSystemProtocolGuid <MdePkg/include/Protocol/SimpleFileSystem.h>
struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL {
///
/// The version of the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL. The version
/// specified by this specification is 0x00010000. All future revisions
/// must be backwards compatible.
///
UINT64 Revision;
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME OpenVolume;
};
OpenVolume 打开的protocol结构:
// EFI_FILE_PROTOCOL为支持的文件系统提供文件IO访问。
// EFI_FILE_PROTOCOL提供对文件或目录内容的访问,也是对文件所在文件系统目录树中位置的引用。
// 对于任何给定的文件句柄,可以相对于该文件的位置打开其他文件,从而产生新的文件句柄。
struct _EFI_FILE_PROTOCOL {
///
/// The version of the EFI_FILE_PROTOCOL interface. The version specified
/// by this specification is EFI_FILE_PROTOCOL_LATEST_REVISION.
/// Future versions are required to be backward compatible to version 1.0.
///
UINT64 Revision;
EFI_FILE_OPEN Open;
EFI_FILE_CLOSE Close;
EFI_FILE_DELETE Delete;
EFI_FILE_READ Read;
EFI_FILE_WRITE Write;
EFI_FILE_GET_POSITION GetPosition;
EFI_FILE_SET_POSITION SetPosition;
EFI_FILE_GET_INFO GetInfo;
EFI_FILE_SET_INFO SetInfo;
EFI_FILE_FLUSH Flush;
EFI_FILE_OPEN_EX OpenEx;
EFI_FILE_READ_EX ReadEx;
EFI_FILE_WRITE_EX WriteEx;
EFI_FILE_FLUSH_EX FlushEx;
};
FAT驱动的核心函数 OpenVolume实体:
EFI_STATUS
EFIAPI
FatOpenVolume (
IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
OUT EFI_FILE_PROTOCOL **File
)
{
EFI_STATUS Status;
FAT_VOLUME *Volume;
FAT_IFILE *IFile;
Volume = VOLUME_FROM_VOL_INTERFACE (This);
FatAcquireLock ();
//
// Open Root file打开根目录
//
Status = FatOpenDirEnt (NULL, &Volume->RootDirEnt);
if (EFI_ERROR (Status)) {
goto Done;
}
//
// Open a new instance to the root
//
Status = FatAllocateIFile (Volume->Root, &IFile);
if (!EFI_ERROR (Status)) {
*File = &IFile->Handle;
}
Done:
Status = FatCleanupVolume (Volume, Volume->Root, Status, NULL);
FatReleaseLock ();
return Status;
}
OpenVolume ——>Open ——>Read/Write ——>Close
EFI_STATUS
EFIAPI
FatOpen (
IN EFI_FILE_PROTOCOL *FHand,
OUT EFI_FILE_PROTOCOL **NewHandle,
IN CHAR16 *FileName,
IN UINT64 OpenMode,
IN UINT64 Attributes
)
{
return FatOpenEx (FHand, NewHandle, FileName, OpenMode, Attributes, NULL);
}
;
EFI_STATUS
EFIAPI
FatRead (
IN EFI_FILE_PROTOCOL *FHand,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
)
{
return FatIFileAccess (FHand, ReadData, BufferSize, Buffer, NULL);
}
;
EFI_STATUS
EFIAPI
FatWrite (
IN EFI_FILE_PROTOCOL *FHand,
IN OUT UINTN *BufferSize,
IN VOID *Buffer
)
{
return FatIFileAccess (FHand, WriteData, BufferSize, Buffer, NULL);
}
ROM Layout
BIOS ROM 文件主要由 FV(Firmware Volume)类型, Data类型和FILE类型构成每一种类型都要定义好Offset和Length, 以防冲突