2006-04-22 00:54:32 +02:00
|
|
|
/*++
|
|
|
|
|
|
|
|
Copyright (c) 2006, Intel Corporation
|
|
|
|
All rights reserved. This program and the accompanying materials
|
|
|
|
are licensed and made available under the terms and conditions of the BSD License
|
|
|
|
which accompanies this distribution. The full text of the license may be found at
|
|
|
|
http://opensource.org/licenses/bsd-license.php
|
|
|
|
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
|
|
|
|
|
|
Module Name:
|
|
|
|
|
|
|
|
Gpt.c
|
|
|
|
|
|
|
|
Abstract:
|
|
|
|
|
|
|
|
Decode a hard disk partitioned with the GPT scheme in the EFI 1.0
|
|
|
|
specification.
|
|
|
|
|
|
|
|
--*/
|
|
|
|
|
|
|
|
#include "Partition.h"
|
|
|
|
|
2007-01-31 05:57:46 +01:00
|
|
|
STATIC
|
2006-04-22 00:54:32 +02:00
|
|
|
BOOLEAN
|
|
|
|
PartitionValidGptTable (
|
|
|
|
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
|
|
|
|
IN EFI_DISK_IO_PROTOCOL *DiskIo,
|
|
|
|
IN EFI_LBA Lba,
|
|
|
|
OUT EFI_PARTITION_TABLE_HEADER *PartHeader
|
|
|
|
);
|
|
|
|
|
2007-01-31 05:57:46 +01:00
|
|
|
STATIC
|
2006-04-22 00:54:32 +02:00
|
|
|
BOOLEAN
|
|
|
|
PartitionCheckGptEntryArrayCRC (
|
|
|
|
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
|
|
|
|
IN EFI_DISK_IO_PROTOCOL *DiskIo,
|
|
|
|
IN EFI_PARTITION_TABLE_HEADER *PartHeader
|
|
|
|
);
|
|
|
|
|
2007-01-31 05:57:46 +01:00
|
|
|
STATIC
|
2006-04-22 00:54:32 +02:00
|
|
|
BOOLEAN
|
|
|
|
PartitionRestoreGptTable (
|
|
|
|
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
|
|
|
|
IN EFI_DISK_IO_PROTOCOL *DiskIo,
|
|
|
|
IN EFI_PARTITION_TABLE_HEADER *PartHeader
|
|
|
|
);
|
|
|
|
|
2007-01-31 05:57:46 +01:00
|
|
|
STATIC
|
2006-04-22 00:54:32 +02:00
|
|
|
VOID
|
|
|
|
PartitionCheckGptEntry (
|
|
|
|
IN EFI_PARTITION_TABLE_HEADER *PartHeader,
|
|
|
|
IN EFI_PARTITION_ENTRY *PartEntry,
|
|
|
|
OUT EFI_PARTITION_ENTRY_STATUS *PEntryStatus
|
|
|
|
);
|
|
|
|
|
2007-01-31 05:57:46 +01:00
|
|
|
STATIC
|
2006-04-22 00:54:32 +02:00
|
|
|
BOOLEAN
|
|
|
|
PartitionCheckCrcAltSize (
|
|
|
|
IN UINTN MaxSize,
|
|
|
|
IN UINTN Size,
|
|
|
|
IN OUT EFI_TABLE_HEADER *Hdr
|
|
|
|
);
|
|
|
|
|
2007-01-31 05:57:46 +01:00
|
|
|
STATIC
|
2006-04-22 00:54:32 +02:00
|
|
|
BOOLEAN
|
|
|
|
PartitionCheckCrc (
|
|
|
|
IN UINTN MaxSize,
|
|
|
|
IN OUT EFI_TABLE_HEADER *Hdr
|
|
|
|
);
|
|
|
|
|
2007-01-31 05:57:46 +01:00
|
|
|
STATIC
|
2006-04-22 00:54:32 +02:00
|
|
|
VOID
|
|
|
|
PartitionSetCrcAltSize (
|
|
|
|
IN UINTN Size,
|
|
|
|
IN OUT EFI_TABLE_HEADER *Hdr
|
|
|
|
);
|
|
|
|
|
2007-01-31 05:57:46 +01:00
|
|
|
STATIC
|
2006-04-22 00:54:32 +02:00
|
|
|
VOID
|
|
|
|
PartitionSetCrc (
|
|
|
|
IN OUT EFI_TABLE_HEADER *Hdr
|
|
|
|
);
|
|
|
|
|
2007-01-23 11:28:32 +01:00
|
|
|
EFI_STATUS
|
2006-04-22 00:54:32 +02:00
|
|
|
PartitionInstallGptChildHandles (
|
|
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
|
|
IN EFI_HANDLE Handle,
|
|
|
|
IN EFI_DISK_IO_PROTOCOL *DiskIo,
|
|
|
|
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
|
|
|
|
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
|
|
|
|
)
|
|
|
|
/*++
|
|
|
|
|
|
|
|
Routine Description:
|
|
|
|
Install child handles if the Handle supports GPT partition structure.
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
This - Calling context.
|
|
|
|
Handle - Parent Handle
|
|
|
|
DiskIo - Parent DiskIo interface
|
|
|
|
BlockIo - Parent BlockIo interface
|
|
|
|
DevicePath - Parent Device Path
|
|
|
|
|
|
|
|
Returns:
|
2007-01-23 11:28:32 +01:00
|
|
|
EFI_SUCCESS - Valid GPT disk
|
|
|
|
EFI_MEDIA_CHANGED - Media changed Detected
|
|
|
|
!EFI_SUCCESS - Not a valid GPT disk
|
2006-04-22 00:54:32 +02:00
|
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
UINT32 BlockSize;
|
|
|
|
EFI_LBA LastBlock;
|
|
|
|
MASTER_BOOT_RECORD *ProtectiveMbr;
|
|
|
|
EFI_PARTITION_TABLE_HEADER *PrimaryHeader;
|
|
|
|
EFI_PARTITION_TABLE_HEADER *BackupHeader;
|
|
|
|
EFI_PARTITION_ENTRY *PartEntry;
|
|
|
|
EFI_PARTITION_ENTRY_STATUS *PEntryStatus;
|
|
|
|
UINTN Index;
|
2007-01-23 11:28:32 +01:00
|
|
|
EFI_STATUS GptValid;
|
2006-04-22 00:54:32 +02:00
|
|
|
HARDDRIVE_DEVICE_PATH HdDev;
|
|
|
|
|
|
|
|
ProtectiveMbr = NULL;
|
|
|
|
PrimaryHeader = NULL;
|
|
|
|
BackupHeader = NULL;
|
|
|
|
PartEntry = NULL;
|
|
|
|
PEntryStatus = NULL;
|
|
|
|
|
|
|
|
BlockSize = BlockIo->Media->BlockSize;
|
|
|
|
LastBlock = BlockIo->Media->LastBlock;
|
|
|
|
|
|
|
|
DEBUG ((EFI_D_INFO, " BlockSize : %d \n", BlockSize));
|
|
|
|
DEBUG ((EFI_D_INFO, " LastBlock : %x \n", LastBlock));
|
|
|
|
|
2007-01-23 11:28:32 +01:00
|
|
|
GptValid = EFI_NOT_FOUND;
|
2006-04-22 00:54:32 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// Allocate a buffer for the Protective MBR
|
|
|
|
//
|
|
|
|
ProtectiveMbr = AllocatePool (BlockSize);
|
|
|
|
if (ProtectiveMbr == NULL) {
|
2007-01-23 11:28:32 +01:00
|
|
|
return EFI_NOT_FOUND;
|
2006-04-22 00:54:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Read the Protective MBR from LBA #0
|
|
|
|
//
|
|
|
|
Status = BlockIo->ReadBlocks (
|
|
|
|
BlockIo,
|
|
|
|
BlockIo->Media->MediaId,
|
|
|
|
0,
|
|
|
|
BlockIo->Media->BlockSize,
|
|
|
|
ProtectiveMbr
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
2007-01-23 11:28:32 +01:00
|
|
|
GptValid = Status;
|
2006-04-22 00:54:32 +02:00
|
|
|
goto Done;
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// Verify that the Protective MBR is valid
|
|
|
|
//
|
|
|
|
if (ProtectiveMbr->Partition[0].BootIndicator != 0x00 ||
|
I fixed following bugs.
1. In dependency.c, DXE Dispatcher doesn't check the dependency expression boundary correctly.
2. In page.c, a misspelling code in DXE core memory service code, duplicate code.
3. In gcd.c, according to DXE CIS 0-91 spec, When GcdAllocateType is EfiGcdAllocateMaxAddressSearchBottomUp or EfiGcdAllocateMaxAddressSearchTopDown, then the GCD memory space map is searched from the lowest address up to BaseAddress (or from BaseAddress down to the lowest address) looking for unallocated memory ranges of Length bytes. Here, BaseAddress itself is inclusive, that is, any range in [0, BaseAddress] is allowable. But current code BaseAddress to be exclusive.
4. In Ebcinit.c, EbcDebugRegisterPeriodicCallback() not check whether it is already registered.
5. In Ebcinit.c, EbcDebugRegisterExceptionCallback() not check whether it is already registered.
6. In Ebcinit.c, EbcDebugSignalException() does not assign value to EbcContext.ControlFlags.
7. In Ebcinit.c, EBC: StatusCodeValue should use EFI_SOFTWARE_EBC_EXCEPTION.
8. In Ebcinit.c, EbcDebugRegisterExceptionCallback() does not check ExceptionType
9. In ElTorito.c, BlockIo and DiskIo failed in SCT when there is CD in CD-ROM.
10. In Mbr.c, MBR code can't handle some situations. That is when there are 3 partitions in HD, if delete the first partition, it will not be able to recognize the other two partitions, and if delete the second partition, it will not be able to recognize the third partition.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@1749 6f19259b-4bc3-4df7-8a09-765794883524
2006-10-16 04:48:19 +02:00
|
|
|
ProtectiveMbr->Partition[0].OSIndicator != PMBR_GPT_PARTITION ||
|
2006-04-22 00:54:32 +02:00
|
|
|
UNPACK_UINT32 (ProtectiveMbr->Partition[0].StartingLBA) != 1
|
|
|
|
) {
|
|
|
|
goto Done;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Allocate the GPT structures
|
|
|
|
//
|
|
|
|
PrimaryHeader = AllocateZeroPool (sizeof (EFI_PARTITION_TABLE_HEADER));
|
|
|
|
if (PrimaryHeader == NULL) {
|
|
|
|
goto Done;
|
|
|
|
}
|
|
|
|
|
|
|
|
BackupHeader = AllocateZeroPool (sizeof (EFI_PARTITION_TABLE_HEADER));
|
|
|
|
|
|
|
|
if (BackupHeader == NULL) {
|
|
|
|
goto Done;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Check primary and backup partition tables
|
|
|
|
//
|
|
|
|
if (!PartitionValidGptTable (BlockIo, DiskIo, PRIMARY_PART_HEADER_LBA, PrimaryHeader)) {
|
|
|
|
DEBUG ((EFI_D_INFO, " Not Valid primary partition table\n"));
|
|
|
|
|
|
|
|
if (!PartitionValidGptTable (BlockIo, DiskIo, LastBlock, BackupHeader)) {
|
|
|
|
DEBUG ((EFI_D_INFO, " Not Valid backup partition table\n"));
|
|
|
|
goto Done;
|
|
|
|
} else {
|
|
|
|
DEBUG ((EFI_D_INFO, " Valid backup partition table\n"));
|
|
|
|
DEBUG ((EFI_D_INFO, " Restore primary partition table by the backup\n"));
|
|
|
|
if (!PartitionRestoreGptTable (BlockIo, DiskIo, BackupHeader)) {
|
|
|
|
DEBUG ((EFI_D_INFO, " Restore primary partition table error\n"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PartitionValidGptTable (BlockIo, DiskIo, BackupHeader->AlternateLBA, PrimaryHeader)) {
|
|
|
|
DEBUG ((EFI_D_INFO, " Restore backup partition table success\n"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (!PartitionValidGptTable (BlockIo, DiskIo, PrimaryHeader->AlternateLBA, BackupHeader)) {
|
|
|
|
DEBUG ((EFI_D_INFO, " Valid primary and !Valid backup partition table\n"));
|
|
|
|
DEBUG ((EFI_D_INFO, " Restore backup partition table by the primary\n"));
|
|
|
|
if (!PartitionRestoreGptTable (BlockIo, DiskIo, PrimaryHeader)) {
|
|
|
|
DEBUG ((EFI_D_INFO, " Restore backup partition table error\n"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PartitionValidGptTable (BlockIo, DiskIo, PrimaryHeader->AlternateLBA, BackupHeader)) {
|
|
|
|
DEBUG ((EFI_D_INFO, " Restore backup partition table success\n"));
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
DEBUG ((EFI_D_INFO, " Valid primary and Valid backup partition table\n"));
|
|
|
|
|
|
|
|
//
|
|
|
|
// Read the EFI Partition Entries
|
|
|
|
//
|
|
|
|
PartEntry = AllocatePool (PrimaryHeader->NumberOfPartitionEntries * sizeof (EFI_PARTITION_ENTRY));
|
|
|
|
if (PartEntry == NULL) {
|
|
|
|
DEBUG ((EFI_D_ERROR, "Allocate pool error\n"));
|
|
|
|
goto Done;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = DiskIo->ReadDisk (
|
|
|
|
DiskIo,
|
|
|
|
BlockIo->Media->MediaId,
|
|
|
|
MultU64x32(PrimaryHeader->PartitionEntryLBA, BlockSize),
|
|
|
|
PrimaryHeader->NumberOfPartitionEntries * (PrimaryHeader->SizeOfPartitionEntry),
|
|
|
|
PartEntry
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
2007-01-23 11:28:32 +01:00
|
|
|
GptValid = Status;
|
2006-04-22 00:54:32 +02:00
|
|
|
DEBUG ((EFI_D_INFO, " Partition Entry ReadBlocks error\n"));
|
|
|
|
goto Done;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEBUG ((EFI_D_INFO, " Partition entries read block success\n"));
|
|
|
|
|
|
|
|
DEBUG ((EFI_D_INFO, " Number of partition entries: %d\n", PrimaryHeader->NumberOfPartitionEntries));
|
|
|
|
|
|
|
|
PEntryStatus = AllocateZeroPool (PrimaryHeader->NumberOfPartitionEntries * sizeof (EFI_PARTITION_ENTRY_STATUS));
|
|
|
|
if (PEntryStatus == NULL) {
|
|
|
|
DEBUG ((EFI_D_ERROR, "Allocate pool error\n"));
|
|
|
|
goto Done;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Check the integrity of partition entries
|
|
|
|
//
|
|
|
|
PartitionCheckGptEntry (PrimaryHeader, PartEntry, PEntryStatus);
|
|
|
|
|
|
|
|
//
|
|
|
|
// If we got this far the GPT layout of the disk is valid and we should return true
|
|
|
|
//
|
2007-01-23 11:28:32 +01:00
|
|
|
GptValid = EFI_SUCCESS;
|
2006-04-22 00:54:32 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// Create child device handles
|
|
|
|
//
|
|
|
|
for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) {
|
|
|
|
if (CompareGuid (&PartEntry[Index].PartitionTypeGUID, &gEfiPartTypeUnusedGuid) ||
|
|
|
|
PEntryStatus[Index].OutOfRange ||
|
|
|
|
PEntryStatus[Index].Overlap
|
|
|
|
) {
|
|
|
|
//
|
|
|
|
// Don't use null EFI Partition Entries or Invalid Partition Entries
|
|
|
|
//
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
ZeroMem (&HdDev, sizeof (HdDev));
|
|
|
|
HdDev.Header.Type = MEDIA_DEVICE_PATH;
|
|
|
|
HdDev.Header.SubType = MEDIA_HARDDRIVE_DP;
|
|
|
|
SetDevicePathNodeLength (&HdDev.Header, sizeof (HdDev));
|
|
|
|
|
|
|
|
HdDev.PartitionNumber = (UINT32) Index + 1;
|
|
|
|
HdDev.MBRType = MBR_TYPE_EFI_PARTITION_TABLE_HEADER;
|
|
|
|
HdDev.SignatureType = SIGNATURE_TYPE_GUID;
|
|
|
|
HdDev.PartitionStart = PartEntry[Index].StartingLBA;
|
|
|
|
HdDev.PartitionSize = PartEntry[Index].EndingLBA - PartEntry[Index].StartingLBA + 1;
|
|
|
|
CopyMem (HdDev.Signature, &PartEntry[Index].UniquePartitionGUID, sizeof (EFI_GUID));
|
|
|
|
|
|
|
|
DEBUG ((EFI_D_INFO, " Index : %d\n", Index));
|
|
|
|
DEBUG ((EFI_D_INFO, " Start LBA : %x\n", HdDev.PartitionStart));
|
|
|
|
DEBUG ((EFI_D_INFO, " End LBA : %x\n", PartEntry[Index].EndingLBA));
|
|
|
|
DEBUG ((EFI_D_INFO, " Partition size: %x\n", HdDev.PartitionSize));
|
|
|
|
DEBUG ((EFI_D_INFO, " Start : %x", MultU64x32 (PartEntry[Index].StartingLBA, BlockSize)));
|
|
|
|
DEBUG ((EFI_D_INFO, " End : %x\n", MultU64x32 (PartEntry[Index].EndingLBA, BlockSize)));
|
|
|
|
|
|
|
|
Status = PartitionInstallChildHandle (
|
|
|
|
This,
|
|
|
|
Handle,
|
|
|
|
DiskIo,
|
|
|
|
BlockIo,
|
|
|
|
DevicePath,
|
|
|
|
(EFI_DEVICE_PATH_PROTOCOL *) &HdDev,
|
|
|
|
PartEntry[Index].StartingLBA,
|
|
|
|
PartEntry[Index].EndingLBA,
|
|
|
|
BlockSize,
|
|
|
|
CompareGuid(&PartEntry[Index].PartitionTypeGUID, &gEfiPartTypeSystemPartGuid)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
DEBUG ((EFI_D_INFO, "Prepare to Free Pool\n"));
|
|
|
|
|
|
|
|
Done:
|
|
|
|
if (ProtectiveMbr != NULL) {
|
2007-03-16 03:33:49 +01:00
|
|
|
FreePool (ProtectiveMbr);
|
2006-04-22 00:54:32 +02:00
|
|
|
}
|
|
|
|
if (PrimaryHeader != NULL) {
|
2007-03-16 03:33:49 +01:00
|
|
|
FreePool (PrimaryHeader);
|
2006-04-22 00:54:32 +02:00
|
|
|
}
|
|
|
|
if (BackupHeader != NULL) {
|
2007-03-16 03:33:49 +01:00
|
|
|
FreePool (BackupHeader);
|
2006-04-22 00:54:32 +02:00
|
|
|
}
|
|
|
|
if (PartEntry != NULL) {
|
2007-03-16 03:33:49 +01:00
|
|
|
FreePool (PartEntry);
|
2006-04-22 00:54:32 +02:00
|
|
|
}
|
|
|
|
if (PEntryStatus != NULL) {
|
2007-03-16 03:33:49 +01:00
|
|
|
FreePool (PEntryStatus);
|
2006-04-22 00:54:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return GptValid;
|
|
|
|
}
|
|
|
|
|
2007-01-31 05:57:46 +01:00
|
|
|
STATIC
|
2006-04-22 00:54:32 +02:00
|
|
|
BOOLEAN
|
|
|
|
PartitionValidGptTable (
|
|
|
|
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
|
|
|
|
IN EFI_DISK_IO_PROTOCOL *DiskIo,
|
|
|
|
IN EFI_LBA Lba,
|
|
|
|
OUT EFI_PARTITION_TABLE_HEADER *PartHeader
|
|
|
|
)
|
|
|
|
/*++
|
|
|
|
|
|
|
|
Routine Description:
|
|
|
|
Check if the GPT partition table is valid
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
BlockIo - Parent BlockIo interface
|
|
|
|
DiskIo - Disk Io protocol.
|
|
|
|
Lba - The starting Lba of the Partition Table
|
|
|
|
PartHeader - Stores the partition table that is read
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
TRUE - The partition table is valid
|
|
|
|
FALSE - The partition table is not valid
|
|
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
UINT32 BlockSize;
|
|
|
|
EFI_PARTITION_TABLE_HEADER *PartHdr;
|
|
|
|
|
|
|
|
BlockSize = BlockIo->Media->BlockSize;
|
|
|
|
|
|
|
|
PartHdr = AllocateZeroPool (BlockSize);
|
|
|
|
|
|
|
|
if (PartHdr == NULL) {
|
|
|
|
DEBUG ((EFI_D_ERROR, "Allocate pool error\n"));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// Read the EFI Partition Table Header
|
|
|
|
//
|
|
|
|
Status = BlockIo->ReadBlocks (
|
|
|
|
BlockIo,
|
|
|
|
BlockIo->Media->MediaId,
|
|
|
|
Lba,
|
|
|
|
BlockSize,
|
|
|
|
PartHdr
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
2007-03-16 03:33:49 +01:00
|
|
|
FreePool (PartHdr);
|
2006-04-22 00:54:32 +02:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CompareMem (&PartHdr->Header.Signature, EFI_PTAB_HEADER_ID, sizeof (UINT64)) != 0 ||
|
|
|
|
!PartitionCheckCrc (BlockSize, &PartHdr->Header) ||
|
|
|
|
PartHdr->MyLBA != Lba
|
|
|
|
) {
|
|
|
|
DEBUG ((EFI_D_INFO, " !Valid efi partition table header\n"));
|
2007-03-16 03:33:49 +01:00
|
|
|
FreePool (PartHdr);
|
2006-04-22 00:54:32 +02:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
CopyMem (PartHeader, PartHdr, sizeof (EFI_PARTITION_TABLE_HEADER));
|
|
|
|
if (!PartitionCheckGptEntryArrayCRC (BlockIo, DiskIo, PartHeader)) {
|
2007-03-16 03:33:49 +01:00
|
|
|
FreePool (PartHdr);
|
2006-04-22 00:54:32 +02:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEBUG ((EFI_D_INFO, " Valid efi partition table header\n"));
|
2007-03-16 03:33:49 +01:00
|
|
|
FreePool (PartHdr);
|
2006-04-22 00:54:32 +02:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2007-01-31 05:57:46 +01:00
|
|
|
STATIC
|
2006-04-22 00:54:32 +02:00
|
|
|
BOOLEAN
|
|
|
|
PartitionCheckGptEntryArrayCRC (
|
|
|
|
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
|
|
|
|
IN EFI_DISK_IO_PROTOCOL *DiskIo,
|
|
|
|
IN EFI_PARTITION_TABLE_HEADER *PartHeader
|
|
|
|
)
|
|
|
|
/*++
|
|
|
|
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Check if the CRC field in the Partition table header is valid
|
|
|
|
for Partition entry array
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
BlockIo - parent BlockIo interface
|
|
|
|
DiskIo - Disk Io Protocol.
|
|
|
|
PartHeader - Partition table header structure
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
|
|
TRUE - the CRC is valid
|
|
|
|
FALSE - the CRC is invalid
|
|
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
UINT8 *Ptr;
|
|
|
|
UINT32 Crc;
|
|
|
|
UINTN Size;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Read the EFI Partition Entries
|
|
|
|
//
|
|
|
|
Ptr = AllocatePool (PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry);
|
|
|
|
if (Ptr == NULL) {
|
|
|
|
DEBUG ((EFI_D_ERROR, " Allocate pool error\n"));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = DiskIo->ReadDisk (
|
|
|
|
DiskIo,
|
|
|
|
BlockIo->Media->MediaId,
|
|
|
|
MultU64x32(PartHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),
|
|
|
|
PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,
|
|
|
|
Ptr
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
2007-03-16 03:33:49 +01:00
|
|
|
FreePool (Ptr);
|
2006-04-22 00:54:32 +02:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
Size = PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry;
|
|
|
|
|
|
|
|
Status = gBS->CalculateCrc32 (Ptr, Size, &Crc);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
DEBUG ((EFI_D_ERROR, "CheckPEntryArrayCRC: Crc calculation failed\n"));
|
2007-03-16 03:33:49 +01:00
|
|
|
FreePool (Ptr);
|
2006-04-22 00:54:32 +02:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2007-03-16 03:33:49 +01:00
|
|
|
FreePool (Ptr);
|
2006-04-22 00:54:32 +02:00
|
|
|
|
|
|
|
return (BOOLEAN) (PartHeader->PartitionEntryArrayCRC32 == Crc);
|
|
|
|
}
|
|
|
|
|
2007-01-31 05:57:46 +01:00
|
|
|
STATIC
|
2006-04-22 00:54:32 +02:00
|
|
|
BOOLEAN
|
|
|
|
PartitionRestoreGptTable (
|
|
|
|
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
|
|
|
|
IN EFI_DISK_IO_PROTOCOL *DiskIo,
|
|
|
|
IN EFI_PARTITION_TABLE_HEADER *PartHeader
|
|
|
|
)
|
|
|
|
/*++
|
|
|
|
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Restore Partition Table to its alternate place
|
|
|
|
(Primary -> Backup or Backup -> Primary)
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
BlockIo - parent BlockIo interface
|
|
|
|
DiskIo - Disk Io Protocol.
|
|
|
|
PartHeader - the source Partition table header structure
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
|
|
TRUE - Restoring succeeds
|
|
|
|
FALSE - Restoring failed
|
|
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
UINTN BlockSize;
|
|
|
|
EFI_PARTITION_TABLE_HEADER *PartHdr;
|
|
|
|
EFI_LBA PEntryLBA;
|
|
|
|
UINT8 *Ptr;
|
|
|
|
|
|
|
|
PartHdr = NULL;
|
|
|
|
Ptr = NULL;
|
|
|
|
|
|
|
|
BlockSize = BlockIo->Media->BlockSize;
|
|
|
|
|
|
|
|
PartHdr = AllocateZeroPool (BlockSize);
|
|
|
|
|
|
|
|
if (PartHdr == NULL) {
|
|
|
|
DEBUG ((EFI_D_ERROR, "Allocate pool error\n"));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
PEntryLBA = (PartHeader->MyLBA == PRIMARY_PART_HEADER_LBA) ? \
|
|
|
|
(PartHeader->LastUsableLBA + 1) : \
|
|
|
|
(PRIMARY_PART_HEADER_LBA + 1);
|
|
|
|
|
|
|
|
CopyMem (PartHdr, PartHeader, sizeof (EFI_PARTITION_TABLE_HEADER));
|
|
|
|
|
|
|
|
PartHdr->MyLBA = PartHeader->AlternateLBA;
|
|
|
|
PartHdr->AlternateLBA = PartHeader->MyLBA;
|
|
|
|
PartHdr->PartitionEntryLBA = PEntryLBA;
|
|
|
|
PartitionSetCrc ((EFI_TABLE_HEADER *) PartHdr);
|
|
|
|
|
|
|
|
Status = BlockIo->WriteBlocks (BlockIo, BlockIo->Media->MediaId, PartHdr->MyLBA, BlockSize, PartHdr);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
goto Done;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ptr = AllocatePool (PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry);
|
|
|
|
if (Ptr == NULL) {
|
|
|
|
DEBUG ((EFI_D_ERROR, " Allocate pool effor\n"));
|
|
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
|
|
goto Done;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = DiskIo->ReadDisk (
|
|
|
|
DiskIo,
|
|
|
|
BlockIo->Media->MediaId,
|
|
|
|
MultU64x32(PartHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),
|
|
|
|
PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,
|
|
|
|
Ptr
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
goto Done;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = DiskIo->WriteDisk (
|
|
|
|
DiskIo,
|
|
|
|
BlockIo->Media->MediaId,
|
|
|
|
MultU64x32(PEntryLBA, BlockIo->Media->BlockSize),
|
|
|
|
PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,
|
|
|
|
Ptr
|
|
|
|
);
|
|
|
|
|
|
|
|
Done:
|
2007-03-16 03:33:49 +01:00
|
|
|
FreePool (PartHdr);
|
|
|
|
FreePool (Ptr);
|
2006-04-22 00:54:32 +02:00
|
|
|
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2007-01-31 05:57:46 +01:00
|
|
|
STATIC
|
2006-04-22 00:54:32 +02:00
|
|
|
VOID
|
|
|
|
PartitionCheckGptEntry (
|
|
|
|
IN EFI_PARTITION_TABLE_HEADER *PartHeader,
|
|
|
|
IN EFI_PARTITION_ENTRY *PartEntry,
|
|
|
|
OUT EFI_PARTITION_ENTRY_STATUS *PEntryStatus
|
|
|
|
)
|
|
|
|
/*++
|
|
|
|
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Check each partition entry for its range
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
PartHeader - the partition table header
|
|
|
|
PartEntry - the partition entry array
|
|
|
|
PEntryStatus - the partition entry status array recording the status of
|
|
|
|
each partition
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
VOID
|
|
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
EFI_LBA StartingLBA;
|
|
|
|
EFI_LBA EndingLBA;
|
|
|
|
UINTN Index1;
|
|
|
|
UINTN Index2;
|
|
|
|
|
|
|
|
DEBUG ((EFI_D_INFO, " start check partition entries\n"));
|
|
|
|
for (Index1 = 0; Index1 < PartHeader->NumberOfPartitionEntries; Index1++) {
|
|
|
|
if (CompareGuid (&PartEntry[Index1].PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
StartingLBA = PartEntry[Index1].StartingLBA;
|
|
|
|
EndingLBA = PartEntry[Index1].EndingLBA;
|
|
|
|
if (StartingLBA > EndingLBA ||
|
|
|
|
StartingLBA < PartHeader->FirstUsableLBA ||
|
|
|
|
StartingLBA > PartHeader->LastUsableLBA ||
|
|
|
|
EndingLBA < PartHeader->FirstUsableLBA ||
|
|
|
|
EndingLBA > PartHeader->LastUsableLBA
|
|
|
|
) {
|
|
|
|
PEntryStatus[Index1].OutOfRange = TRUE;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (Index2 = Index1 + 1; Index2 < PartHeader->NumberOfPartitionEntries; Index2++) {
|
|
|
|
|
|
|
|
if (CompareGuid (&PartEntry[Index2].PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PartEntry[Index2].EndingLBA >= StartingLBA && PartEntry[Index2].StartingLBA <= EndingLBA) {
|
|
|
|
//
|
|
|
|
// This region overlaps with the Index1'th region
|
|
|
|
//
|
|
|
|
PEntryStatus[Index1].Overlap = TRUE;
|
|
|
|
PEntryStatus[Index2].Overlap = TRUE;
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DEBUG ((EFI_D_INFO, " End check partition entries\n"));
|
|
|
|
}
|
|
|
|
|
2007-01-31 05:57:46 +01:00
|
|
|
STATIC
|
2006-04-22 00:54:32 +02:00
|
|
|
VOID
|
|
|
|
PartitionSetCrc (
|
|
|
|
IN OUT EFI_TABLE_HEADER *Hdr
|
|
|
|
)
|
|
|
|
/*++
|
|
|
|
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Updates the CRC32 value in the table header
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Hdr - The table to update
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
|
|
None
|
|
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PartitionSetCrcAltSize (Hdr->HeaderSize, Hdr);
|
|
|
|
}
|
|
|
|
|
2007-01-31 05:57:46 +01:00
|
|
|
STATIC
|
2006-04-22 00:54:32 +02:00
|
|
|
VOID
|
|
|
|
PartitionSetCrcAltSize (
|
|
|
|
IN UINTN Size,
|
|
|
|
IN OUT EFI_TABLE_HEADER *Hdr
|
|
|
|
)
|
|
|
|
/*++
|
|
|
|
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Updates the CRC32 value in the table header
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Size - The size of the table
|
|
|
|
Hdr - The table to update
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
|
|
None
|
|
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
UINT32 Crc;
|
|
|
|
|
|
|
|
Hdr->CRC32 = 0;
|
|
|
|
gBS->CalculateCrc32 ((UINT8 *) Hdr, Size, &Crc);
|
|
|
|
Hdr->CRC32 = Crc;
|
|
|
|
}
|
|
|
|
|
2007-01-31 05:57:46 +01:00
|
|
|
STATIC
|
2006-04-22 00:54:32 +02:00
|
|
|
BOOLEAN
|
|
|
|
PartitionCheckCrc (
|
|
|
|
IN UINTN MaxSize,
|
|
|
|
IN OUT EFI_TABLE_HEADER *Hdr
|
|
|
|
)
|
|
|
|
/*++
|
|
|
|
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Checks the CRC32 value in the table header
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
MaxSize - Max Size limit
|
|
|
|
Hdr - The table to check
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
|
|
TRUE if the CRC is OK in the table
|
|
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
return PartitionCheckCrcAltSize (MaxSize, Hdr->HeaderSize, Hdr);
|
|
|
|
}
|
|
|
|
|
2007-01-31 05:57:46 +01:00
|
|
|
STATIC
|
2006-04-22 00:54:32 +02:00
|
|
|
BOOLEAN
|
|
|
|
PartitionCheckCrcAltSize (
|
|
|
|
IN UINTN MaxSize,
|
|
|
|
IN UINTN Size,
|
|
|
|
IN OUT EFI_TABLE_HEADER *Hdr
|
|
|
|
)
|
|
|
|
/*++
|
|
|
|
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Checks the CRC32 value in the table header
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
MaxSize - Max Size Limit
|
|
|
|
Size - The size of the table
|
|
|
|
Hdr - The table to check
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
|
|
TRUE if the CRC is OK in the table
|
|
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
UINT32 Crc;
|
|
|
|
UINT32 OrgCrc;
|
|
|
|
EFI_STATUS Status;
|
|
|
|
|
|
|
|
Crc = 0;
|
|
|
|
|
|
|
|
if (Size == 0) {
|
|
|
|
//
|
|
|
|
// If header size is 0 CRC will pass so return FALSE here
|
|
|
|
//
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (MaxSize && Size > MaxSize) {
|
|
|
|
DEBUG ((EFI_D_ERROR, "CheckCrc32: Size > MaxSize\n"));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// clear old crc from header
|
|
|
|
//
|
|
|
|
OrgCrc = Hdr->CRC32;
|
|
|
|
Hdr->CRC32 = 0;
|
|
|
|
|
|
|
|
Status = gBS->CalculateCrc32 ((UINT8 *) Hdr, Size, &Crc);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
DEBUG ((EFI_D_ERROR, "CheckCrc32: Crc calculation failed\n"));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// set results
|
|
|
|
//
|
|
|
|
Hdr->CRC32 = Crc;
|
|
|
|
|
|
|
|
//
|
|
|
|
// return status
|
|
|
|
//
|
2006-07-26 17:23:35 +02:00
|
|
|
DEBUG_CODE_BEGIN ();
|
2006-04-22 00:54:32 +02:00
|
|
|
if (OrgCrc != Crc) {
|
|
|
|
DEBUG ((EFI_D_ERROR, "CheckCrc32: Crc check failed\n"));
|
|
|
|
}
|
2006-07-26 17:23:35 +02:00
|
|
|
DEBUG_CODE_END ();
|
2006-04-22 00:54:32 +02:00
|
|
|
|
|
|
|
return (BOOLEAN) (OrgCrc == Crc);
|
|
|
|
}
|