Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

189 lines
6.9 KiB

//
// GPT (GUID Partition Table) declarations.
//
//
// DO WE EVER ALLOW GPT_TABLEs TO NOT BE PACKED UP AGAINST THEIR HEADER?
// IF NOT, DO WE ALLOW PEOPLE TO MAKE ASSUMPTIONS ABOUT THEIR LOCATION?
// DO WE NEED THE POINTER?
//
//
// Rules:
// None of these structures ever appear at LBA 0, because
// we put a "fake" MBR there (the legacy defense MBR).
// Therefore, LBA of 0 is useable as NULL.
//
// For All Entry's, StartingLBA must be >= FirstUsableLBA.
// For All Entry's, EndingLBA must be <= LastUsableLBA.
//
// 0 is not a valid GUID. Therefore, emtpy GPT_ENTRY's will
// have a PartitionType of 0.
// However, if an entry is otherwise valid, but has a PartitionID
// of 0, this means a GUID needs to be generated and placed there.
//
// LBA = Logical Block Address == Sector Number. Always count from 0.
//
// Block size (sector size) could be any number >= sizeof(GPT_ENTRY)
// AND >= sizeof(GPT_HEADER). In practice, always >= 512 bytes.
//
// A block, B, is free for allocation to a partition if and only if
// it is in the range FirstUsableLBA <= B <= LastUsableLBA AND it
// is not already allocated to some other parition.
//
// GPT partitions are always contiguous arrays of blocks. however,
// they need NOT be packed on the disk, their order in the GPT need
// NOT match their order on the disk, there may be blank entries
// in the GPT table, etc. Building an accurate view of the parititon
// *requires* reading the entire GPT_TABLE into memory. In practice,
// it will always be small enough for this to be easy.
//
#pragma pack (4)
//
// Each partition is described by a GPT_ENTRY.
//
#define PART_NAME_LEN 36
typedef struct {
EFI_GUID PartitionType; // declartion of this partition's type
EFI_GUID PartitionID; // Unique ID for this particular partition
// (unique to this instance)
EFI_LBA StartingLBA; // 0 based block (sector) address of the
// first block included in the partition.
EFI_LBA EndingLBA; // 0 based block (sector) address of the
// last block included in the partition.
// If StartingLBA == EndingLBA then the
// partition is 1 block long. this is legal.
UINT64 Attributes; // Always ZERO for now
CHAR16 PartitionName[PART_NAME_LEN]; // 36 unicode characters of name
} GPT_ENTRY, *PGPT_ENTRY;
C_ASSERT (sizeof (GPT_ENTRY) == 128);
//
// All of the GPT_ENTRY's are gathered into a GPT_TABLE, which
// is stored as a linear array of blocks on the disk.
//
typedef struct {
GPT_ENTRY Entry[1]; // Always an integer number of Entry's
// per sector. Always at least 1 sector.
// Can be any number of sectors...
} GPT_TABLE, *PGPT_TABLE;
//
// A main and a backup header each describe the disk, and each points
// to it's own copy of the GPT_TABLE...
//
typedef struct {
UINT64 Signature; // GPT PART
UINT32 Revision;
UINT32 HeaderSize;
UINT32 HeaderCRC32; // computed using 0 for own init value
UINT32 Reserved0;
EFI_LBA MyLBA; // 0 based sector number of the first
// sector of this structure
EFI_LBA AlternateLBA; // 0 based sector (block) number of the
// first sector of the secondary
// GPT_HEADER, or 0 if this is the
// secondary.
EFI_LBA FirstUsableLBA; // 0 based sector number of the first
// sector that may be included in a partition.
EFI_LBA LastUsableLBA; // last legal LBA, inclusive.
EFI_GUID DiskGUID; // The unique ID of this LUN/spindle/disk
EFI_LBA TableLBA; // The start of the table of entries...
UINT32 EntriesAllocated; // Number of entries in the table, this is
// how many allocated, NOT how many used.
UINT32 SizeOfGPT_ENTRY; // sizeof(GPT_ENTRY) always mult. of 8
UINT32 TableCRC32; // CRC32 of the table.
// Reserved and zeros to the end of the block
// Don't declare an array or sizeof() gives a nonsense answer..
} GPT_HEADER, *PGPT_HEADER;
C_ASSERT (sizeof (GPT_HEADER) == 92);
#define GPT_HEADER_SIGNATURE 0x5452415020494645
#define GPT_REVISION_1_0 0x00010000
#define ENTRY_DEFAULT 128
//#define ENTRY_DEFAULT 8 // TESTING ONLY
#define ENTRY_SANITY_LIMIT 1024
//
// GPT Disk Layout
//
/*
+---------------------------------------------------+
LBA=0 | "Fake" MBR to ward off legacy parition apps |
+---------------------------------------------------+
LBA=1 | Primary GPT_HEADER |
+---------------------------------------------------+
LBA=2 | Primary GPT_TABLE starts |
... ... ...
LBA=n | Primary GPT_TABLE ends |
+---------------------------------------------------+
LBA=n+1 | FirstUsableLBA = this block |
... ... ...
LBA=x | LastUsableLBA = this block |
+---------------------------------------------------+
LBA=x+1 | Secondary GPT_TABLE starts |
... ... ...
LBA=z | Secondary GPT_TABLE ends |
+---------------------------------------------------+
LBA=z+n | Secondary GPT_HEADER starts |
... ... ...
LAST | Secondary GPT_HEADER ends at last sector of disk |
+---------------------------------------------------+
SO:
Primary GPT_HEADER is always at LBA=1
Secondary GPT_HEADER is at LBA=Last so long as GPT_HEADER fits
in 1 sector, which we require.
Primary Table is stacked up after the primary header,
which points to it anyway.
Secondary Table is stacked up before the secondary header,
which points to it anyway.
*/
//
// ------------------ Functions To Manipulate GPT ---------------
//
typedef struct _LBA_BLOCK {
EFI_LBA Header1_LBA;
EFI_LBA Table1_LBA;
EFI_LBA Header2_LBA;
EFI_LBA Table2_LBA;
} LBA_BLOCK, *PLBA_BLOCK;
EFI_STATUS
ReadGPT(
EFI_HANDLE DiskHandle,
PGPT_HEADER *Header,
PGPT_TABLE *Table,
PLBA_BLOCK *LbaBlock,
UINTN *DiskType
);
EFI_STATUS
WriteGPT(
EFI_HANDLE DiskHandle,
PGPT_HEADER Header,
PGPT_TABLE Table,
PLBA_BLOCK LbaBlock
);
EFI_STATUS
CreateGPT(
EFI_HANDLE DiskHandle,
UINTN EntryRequest
);
#pragma pack ()