diff options
Diffstat (limited to 'Core/CORE_DXE/Partition')
-rw-r--r-- | Core/CORE_DXE/Partition/ElTorito.c | 470 | ||||
-rw-r--r-- | Core/CORE_DXE/Partition/ElTorito.h | 264 | ||||
-rw-r--r-- | Core/CORE_DXE/Partition/Gpt.c | 606 | ||||
-rw-r--r-- | Core/CORE_DXE/Partition/Gpt.h | 161 | ||||
-rw-r--r-- | Core/CORE_DXE/Partition/Mbr.c | 407 | ||||
-rw-r--r-- | Core/CORE_DXE/Partition/Mbr.h | 171 | ||||
-rw-r--r-- | Core/CORE_DXE/Partition/Partition.c | 1006 | ||||
-rw-r--r-- | Core/CORE_DXE/Partition/Partition.cif | 16 | ||||
-rw-r--r-- | Core/CORE_DXE/Partition/Partition.h | 188 | ||||
-rw-r--r-- | Core/CORE_DXE/Partition/Partition.sdl | 4 |
10 files changed, 3293 insertions, 0 deletions
diff --git a/Core/CORE_DXE/Partition/ElTorito.c b/Core/CORE_DXE/Partition/ElTorito.c new file mode 100644 index 0000000..749ba74 --- /dev/null +++ b/Core/CORE_DXE/Partition/ElTorito.c @@ -0,0 +1,470 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/CORE_DXE/Partition/ElTorito.c 21 8/28/12 3:14p Pats $ +// +// $Revision: 21 $ +// +// $Date: 8/28/12 3:14p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/CORE_DXE/Partition/ElTorito.c $ +// +// 21 8/28/12 3:14p Pats +// [TAG] EIP99287 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] Problem booting certain HDD emulation ElTorito CD/DVD's. +// [RootCause] If the CD has ElTorito and ISO9660 partitions, the block +// sizeread will be the ISO9660 block size, but the ElTorito partition +// needs the HDD block size +// [Solution] Set block size to HDD block size if HDD emulation detected. +// [Files] Eltorito.c +// +// 20 5/10/12 5:54a Rameshr +// [TAG] EIP88924 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] UEFI 2.3.1 SCT block io read test fail +// [RootCause] If the CD has two Boot image , two blockio will be +// installed by Partition driver. But the second blockIo , LastBlock value +// is wrong +// [Solution] 2nd logical blockIO LastBlock size calculation corrected. +// [Files] Eltorito.c +// +// 19 9/27/11 7:43p Yul +// [TAG] EIP69053 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] System cannot boot to WINPE from CD/DVD. +// [RootCause] Blocksize change +// [Solution] Blocksize change +// [Files] EIOorito.c +// +// 18 5/10/11 11:21a Pats +// [TAG] - EIP 57859 +// [Category]- BUG FIX +// [Severity]- Normal +// [Symptom] - On EFI shell, though CD media is recognized as a Block +// device, is not recognized as a File system. +// [RootCause] - Blocksize change from EIP 30719. +// [Solution] - Removed change from EIP 30719. +// [Files] - ElTorito.c +// +// 17 4/16/10 4:24p Pats +// EIP 30719: Support for the HDD with sector size more than 512bytes. +// +// 16 10/20/09 5:02p Felixp +// Check for a block I/O device errors is added in +// ElToritoCreateChildHandle function. +// +// 14 7/09/09 5:01p Oleksiyy +// Files clean-up +// +// 13 4/23/09 11:54a Oleksiyy +// Memory free error fix +// +// 12 2/19/09 1:02p Artems +// EIP 19052 Minor improvement to support CD burned with Windows Explorer +// +// 11 1/16/09 3:02p Felixp +// New Feature: +// CD-ROM handling code is updated to create additional logical instance +// of the Bock I/O protocol +// based on primary volume descriptor of the CR-ROM. +// The instance is used by the ISO 9660 file systems driver +// (separate eModule. Not part of the Core) to implement file system +// protocol. +// The new parittion driver funcionality is only enabled when ISO 9660 +// file systems driver +// ($/Source/Modules/FsIso9660) is included into the project. +// +// 10 1/07/08 4:21p Robert +// Updated for coding standard +// +// 9 4/24/07 5:31p Robert +// Updated Headers to compile with CHM creation +// +// 8 3/22/07 5:39p Robert +// Updated Files for coding standard +// +// 7 8/24/06 12:34p Felixp +// x64 support (fixes for warnings/errors) +// +// 5 5/19/06 10:47p Felixp +// Device Path code updated to use NEXT_NODE/NODE_LENGTH/SET_NODE_LENGTH +// macros to remove direct access to the Length field +// +// 3 5/05/05 5:07p Robert +// When reading the data for the Volume Descriptor. There was no check +// for the Status of the Read Blocks call. If this returned an error then it +// was continuing on. Now it exits when an error is found +// +// 2 2/11/05 6:13p Felixp +// Code optimized by using DPAddNode instead of DPAdd +// +// 2 1/18/05 3:22p Felixp +// PrintDebugMessage renamed to Trace +// +// 3 12/21/04 4:53p Markw +// Modified device path defines for consistency. +// +// 2 12/02/04 5:54p Robert +// Partition driver version works +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: ElTorito.c +// +// Description: EFI El Torito Partition Support Functions +// +//<AMI_FHDR_END> +//********************************************************************** + +//============================================================================= +// Includes +#include "Partition.h" +#include "ElTorito.h" +#include "mbr.h" + +extern BOOLEAN Iso9660FileSystemSupportEnabled; +EFI_GUID VendorDpGuid = AMI_ISO9660_MEDIA_GUID; + +//============================================================================= +// Local Variables + +//============================================================================= +// Function Definitions + + + +//<AMI_PHDR_START> +//============================================================================= +// Procedure: ElToritoCreateChildHandle +// +// Description: Searches CDROM disk for El Torito bootable partitions +// and creates a child handle for each one found +// +// Input: +// *This - Pointer to the instance of this blockIo protocol +// *BlockIo - Pointer to the parent blockIo Protocol +// *DiskIo - Pointer to the parent DiskIo protocol +// *DevicePath - Pointer to the Parent's device path +// ControllerHandle - the parent's controller handle +// +// Output: +// +// Returns: +// EFI_SUCCESS - Partition found +// EFI_INVALID_MEDIA - a parameter passed in or in the data structure +// is invalid +// EFI_NO_MEDIA - No partitions found +// EFI_OUT_OF RESOURCES - Not enough resources to allocate memory +// +// Referrals: ReadBlocks AllocatePool MemCmp FreePool Div64 SetMem +// CreateChildHandle DPAddNode SET_NODE_LENGTH +// +//============================================================================= +//<AMI_PHDR_END> +EFI_STATUS ElToritoCreateChildHandle ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_HANDLE ControllerHandle +) +{ + PARTITION_DATA PData, DData; + EFI_STATUS Status; + EFI_LBA Lba; + BOOT_RECORD_DESC *VolDesc = NULL; + EL_TORITO_ENTRIES *Entry = NULL, *StartEntry = NULL; + CDROM_DEVICE_PATH CdDp; + UINT32 BlockSize; + UINT16 Checksum; + UINT16 *Temp = NULL; + UINTN Idx; + UINT32 VolSize; + UINT32 Sectors; + UINTN BootEntry; + UINTN Dummy; + + AMI_ISO9660_DEVICE_PATH VendorDp; + PRIMARY_VOLUME_DESC_HEADER *PrimVolDesc; + + +// TODO: The El Torito spec says that the Boot Record Volume only exists on the last session +// we need to find the last session on the CD + + // Verify that the CDROM is using the correct block size + if (BlockIo->Media->BlockSize != CDROM_BLOCK_SIZE) + { + return EFI_INVALID_PARAMETER; + } + + // Allocate memory for the Boot Record Volume + Status = gBS->AllocatePool(EfiBootServicesData, BlockIo->Media->BlockSize, &VolDesc); + + if (EFI_ERROR(Status)) + return EFI_OUT_OF_RESOURCES; + + // CDROM Spec says sector 16 contains the Primary Volume descriptor + Lba = CDROM_BOOT_PRI_VOL_DESCRIPTOR_SECTOR; + + Status = BlockIo->ReadBlocks( BlockIo, BlockIo->Media->MediaId, Lba, + BlockIo->Media->BlockSize, VolDesc ); + if (EFI_ERROR(Status)) + { + gBS->FreePool(VolDesc); + return EFI_INVALID_PARAMETER; + } + + // Check for valid volume descriptor signature + if (MemCmp (VolDesc->IsoId, "CD001", 5)) + { + gBS->FreePool(VolDesc); + return EFI_INVALID_PARAMETER; + } + +//*********************************************************************** +// Add Logical partition for ISO 9660 support +//*********************************************************************** + PrimVolDesc = (PRIMARY_VOLUME_DESC_HEADER *)VolDesc; + BlockSize = CDROM_BLOCK_SIZE; + + //Set Vendor device path + VendorDp.Dp.Header.Type = MEDIA_DEVICE_PATH; + VendorDp.Dp.Header.SubType = MEDIA_VENDOR_DP; + VendorDp.Dp.Guid = VendorDpGuid; + VendorDp.VolumeSize = PrimVolDesc->VolSpaceSize; + VendorDp.Root = PrimVolDesc->Root; + MemCpy(VendorDp.VolumeLabel, PrimVolDesc->VolId, 32); + SET_NODE_LENGTH(&VendorDp.Dp.Header,sizeof(AMI_ISO9660_DEVICE_PATH)); + + + // clear the data structure + gBS->SetMem(&DData, sizeof(PARTITION_DATA), 0); + + // create new device path + DData.DevPath = DPAddNode(DevicePath, &(VendorDp.Dp.Header)); + + // save pertinent info + DData.Handle = NULL; + DData.ParentBlockIo = BlockIo; + DData.ParentDiskIo = DiskIo; + DData.StartingLba = 0; + DData.EndingLba = BlockIo->Media->LastBlock; + + // Store Parent Handle + DData.ParentHandle = ControllerHandle; + +//*********************************************************************** +// End of ISO 9660 support +//*********************************************************************** + + // Get the Volume Space Size from Primary Volume Descriptor, + // the 32-bit numerical value is stored in Both-Little and Big Endian + VolSize = VolDesc->VolSpaceSize[0]; + + + // El Torito Spec says sector 17 contains the Boot Record + // Volume: Read and verify the data + Lba = CDROM_BOOT_REC_VOL_DESCRIPTOR_SECTOR; + + Status = BlockIo->ReadBlocks( BlockIo, BlockIo->Media->MediaId, Lba, + BlockIo->Media->BlockSize, VolDesc ); + + if (EFI_ERROR(Status)) + { + gBS->FreePool(VolDesc); + VolDesc = NULL; + goto EndOfEltorito; + } + + // Validate the info in the Boot Record + if ((VolDesc->BootIndicator != 0) || ( MemCmp (VolDesc->IsoId, "CD001", 5)) || + (VolDesc->Version != 1) || (MemCmp(VolDesc->Identifier, EL_TORITO_SPEC, 23) ) ) + { + // not a valid boot Record + gBS->FreePool(VolDesc); + VolDesc = NULL; + goto EndOfEltorito; + } + + // There is a valid boot record. move on to the Boot catalog + Lba = VolDesc->BootCatalog; + + Status = gBS->AllocatePool(EfiBootServicesData, BlockIo->Media->BlockSize, &StartEntry); + + if (EFI_ERROR(Status)) + { + gBS->FreePool(VolDesc); + VolDesc = NULL; + goto EndOfEltorito; + } + + // Now load the Boot Catalog and find all the partitions + BlockIo->ReadBlocks( BlockIo, BlockIo->Media->MediaId, Lba, + BlockIo->Media->BlockSize, StartEntry ); + + // get pointer to the first entry in the Boot Record + Entry = (EL_TORITO_ENTRIES *)StartEntry; + + if ((Entry->ValEntry.HeaderId != 1) || (Entry->ValEntry.Sig != 0xaa55)) + { + gBS->FreePool(VolDesc); + VolDesc = NULL; + gBS->FreePool(StartEntry); + StartEntry = NULL; + goto EndOfEltorito; + } + + // Now Calculate checksum + Checksum = 0; + Temp = (UINT16 *)Entry; + + for (Idx = 0; Idx < 16; Idx++) + Checksum += Temp[Idx]; + + // if the checksum is not 0 then the Boot catalog is considered invalid + if (Checksum) + { + gBS->FreePool(VolDesc); + VolDesc = NULL; + gBS->FreePool(StartEntry); + StartEntry = NULL; + goto EndOfEltorito; + } + + // The checksum is zero so here we go + + // Find and install the Boot entries + // loop through the boot catalog looking for bootable entries + // start at the second entry in the boot catalog, + // the first is the validation entry + Entry++; + + for ( Idx = 0, BootEntry = 0; Idx < ((CDROM_BLOCK_SIZE/ sizeof(EL_TORITO_ENTRIES)) - 1); + Idx++, Entry++) + { + // if it isn't bootable, get next entry + if (Entry->DefaultEntry.BootId != CDROM_BOOTABLE) + continue; + + + BlockSize = BlockIo->Media->BlockSize; + if( (BlockSize == 0) || (BlockSize == 0xFFFFFFFF) ) { + BlockSize = 512; + } + TRACE((TRACE_DXE_CORE, "BlockSize is %d, MediaID is %d\n", BlockSize, BlockIo->Media->MediaId)); + + Sectors = Entry->DefaultEntry.SectorCount; + TRACE((TRACE_DXE_CORE, "Sector count is %d\n", Sectors)); + TRACE((TRACE_DXE_CORE, "Media Type is %d\n", Entry->DefaultEntry.MediaType)); + + // use this switch to set the Partition Size + switch (Entry->DefaultEntry.MediaType) + { + case FLOPPY_144: + Sectors = FLOPPY_144_SIZE_LBA; + break; + case FLOPPY_288: + Sectors = FLOPPY_288_SIZE_LBA; + break; + case FLOPPY_12: + Sectors = FLOPPY_12_SIZE_LBA; + break; + + case NO_EMULATION: + BlockSize = CDROM_BLOCK_SIZE; + break; + + case HARD_DRIVE: + BlockSize = 512; + break; + default: + continue; + } + + + if ((Idx != 0) && (BootEntry == 0)) + BootEntry++; + + CdDp.BootEntry = (UINT32) BootEntry++; + + CdDp.PartitionStart = Entry->DefaultEntry.LoadLba; + + if (Sectors < 2) + CdDp.PartitionSize = (VolSize > BlockIo->Media->LastBlock + 1) ? + (UINT32)(BlockIo->Media->LastBlock - CdDp.PartitionStart + 1) : + (UINT32)(VolSize - CdDp.PartitionStart); + + else + CdDp.PartitionSize = Div64(Sectors* BlockSize + BlockIo->Media->BlockSize - 1, + BlockIo->Media->BlockSize, &Dummy ); + + // set up the device path for the partition + CdDp.Header.Type = MEDIA_DEVICE_PATH; + CdDp.Header.SubType = MEDIA_CDROM_DP; + SET_NODE_LENGTH(&CdDp.Header,sizeof(CDROM_DEVICE_PATH)); + + // clear the data structure + gBS->SetMem(&PData, sizeof(PARTITION_DATA), 0); + + // create new device path + PData.DevPath = DPAddNode(DevicePath, &CdDp.Header); + + // save pertinent info + PData.Handle = NULL; + PData.ParentBlockIo = BlockIo; + PData.ParentDiskIo = DiskIo; + PData.StartingLba = CdDp.PartitionStart; + PData.EndingLba = CdDp.PartitionStart + CdDp.PartitionSize - 1; + + // Store Parent Handle + PData.ParentHandle = ControllerHandle; + + // This is a valid GPT partition: Add a child instance + Status = CreateChildHandle(This, &PData, BlockSize); + } + +EndOfEltorito: + + if (VolDesc != NULL) gBS->FreePool(VolDesc); + + if (StartEntry != NULL) gBS->FreePool(StartEntry); + + if (Iso9660FileSystemSupportEnabled) + { + Status = CreateChildHandle(This, &DData, CDROM_BLOCK_SIZE); + } + + return Status; +} +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/CORE_DXE/Partition/ElTorito.h b/Core/CORE_DXE/Partition/ElTorito.h new file mode 100644 index 0000000..ebbd7ba --- /dev/null +++ b/Core/CORE_DXE/Partition/ElTorito.h @@ -0,0 +1,264 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/CORE_DXE/Partition/ElTorito.h 5 7/09/09 5:01p Oleksiyy $ +// +// $Revision: 5 $ +// +// $Date: 7/09/09 5:01p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/CORE_DXE/Partition/ElTorito.h $ +// +// 5 7/09/09 5:01p Oleksiyy +// Files clean-up +// +// 4 1/16/09 3:02p Felixp +// New Feature: +// CD-ROM handling code is updated to create additional logical instance +// of the Bock I/O protocol +// based on primary volume descriptor of the CR-ROM. +// The instance is used by the ISO 9660 file systems driver +// (separate eModule. Not part of the Core) to implement file system +// protocol. +// The new parittion driver funcionality is only enabled when ISO 9660 +// file systems driver +// ($/Source/Modules/FsIso9660) is included into the project. +// +// 2 12/02/04 5:54p Robert +// Partition driver version works +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: <ElTorito.h> +// +// Description: EFI El Torito Partition Generic Driver Header. +// +//<AMI_FHDR_END> +//********************************************************************** +#ifndef __EL_TORITO_H__ +#define __EL_TORITO_H__ + +#define CDROM_BOOT_PRI_VOL_DESCRIPTOR_SECTOR 16 +#define CDROM_BOOT_REC_VOL_DESCRIPTOR_SECTOR 17 + +#define CDROM_BLOCK_SIZE 2048 + +#define CDROM_BOOTABLE 0x88 + + +#define NO_EMULATION 0x00 +#define FLOPPY_12 0x01 +#define FLOPPY_144 0x02 +#define FLOPPY_288 0x03 +#define HARD_DRIVE 0x04 + + +#define HD_BLOCK_SIZE 512 +#define FLOPPY_144_SIZE_LBA 720 +#define FLOPPY_288_SIZE_LBA 1440 +#define FLOPPY_12_SIZE_LBA 615 + +#define EL_TORITO_SPEC "EL TORITO SPECIFICATION" + +// {BA7C46D1-9C5E-4fc8-943D-1A491F23FE01} +#define AMI_ISO9660_MEDIA_GUID \ + { 0xba7c46d1, 0x9c5e, 0x4fc8, 0x94, 0x3d, 0x1a, 0x49, 0x1f, 0x23, 0xfe, 0x1 } + + +//<AMI_GHDR_START> +//------------------------------------------------------------------ +// Name: Data_Structures +// +// Description: +// Data Structures needed for El Torito +// +// BOOT_RECORD - Data Structure definition of a boot record +// that is contained within an El Torito Disk +// +// EL_TORITO_ENTRIES - A union of possible structs that could be +// contained within an entry on the disk +// +//------------------------------------------------------------------ +//<AMI_GHDR_END> +#pragma pack(1) + +typedef struct _BOOT_RECORD +{ + UINT8 BootIndicator; + CHAR8 IsoId[5]; + UINT8 Version; + CHAR8 Identifier[32]; + UINT8 Unused[32]; + UINT32 BootCatalog; + UINT8 Unused2[5]; + UINT32 VolSpaceSize[2]; +} BOOT_RECORD_DESC; + + + +typedef union +{ + struct + { + UINT8 HeaderId; + UINT8 PlatformId; + UINT16 Res0; + CHAR8 Id[24]; + UINT16 Checksum; + UINT16 Sig; + } ValEntry; + + + struct + { + UINT8 BootId; + UINT8 MediaType; + UINT16 LoadSegment; + UINT8 SystemType; + UINT8 Unused; + UINT16 SectorCount; + UINT32 LoadLba; + } DefaultEntry; + + + struct + { + UINT8 HeaderId; + UINT8 PlatformId; + UINT16 NumSectionEntries; + CHAR8 IdString[28]; + } SecHeader; + + + struct + { + UINT8 BootId; + UINT8 MediaType; + UINT16 LoadSegment; + UINT8 SystemType; + UINT8 Unused; + UINT16 SectorCount; + UINT32 LoadLba; + UINT8 SelectionType; + UINT8 Criteria[19]; + } SecEntry; + +} EL_TORITO_ENTRIES; + +typedef struct +{ + UINT8 VolDescType; + CHAR8 StdId[5]; + UINT8 VolDescVer; +} VOLUME_DESCRIPTOR_HEADER; + +typedef struct +{ + UINT32 Year; + UINT16 Month; + UINT16 Day; + UINT16 Hour; + UINT16 Minute; + UINT16 Second; + UINT16 HSecond; + INT8 Offset; +} CD_DATE_TIME; + +typedef struct +{ + UINT8 Year; + UINT8 Month; + UINT8 Day; + UINT8 Hour; + UINT8 Minute; + UINT8 Second; + INT8 Offset; +} FILE_DATE_TIME; + +typedef struct +{ + UINT8 RecordLength; + UINT8 ExtAttrRecLength; + UINT64 StartLba; + UINT64 DataLength; + FILE_DATE_TIME RecTime; + UINT8 Flags; + UINT8 FileUnitSize; + UINT8 InterleaveGap; + UINT32 VolSeqNum; + UINT8 FileIdLength; + UINT8 FileId[1]; +} ROOT_DIR_HEADER; + +typedef struct +{ + VOLUME_DESCRIPTOR_HEADER Header; + UINT8 Flags; + CHAR8 SysId[32]; + CHAR8 VolId[32]; + UINT64 Unused; + UINT64 VolSpaceSize; + CHAR8 EscSeq[32]; + UINT32 VolSetSize; + UINT32 VolSeqNum; + UINT32 LBlockSize; + UINT64 PathTblSize; + UINT32 LPathTbl1; + UINT32 LPathTbl2; + UINT32 MPathTbl1; + UINT32 MPathTbl2; + ROOT_DIR_HEADER Root; + CHAR8 VolSetId[128]; + CHAR8 PublisherId[128]; + CHAR8 DataPrepId[128]; + CHAR8 ApplicationId[128]; + CHAR8 CopyrightFileId[37]; + CHAR8 AbstractFileId[37]; + CHAR8 BiblioFileId[37]; + CD_DATE_TIME CreationTime; + CD_DATE_TIME ModifyTime; + CD_DATE_TIME ExpireTime; + CD_DATE_TIME EffectiveTime; + UINT8 FileStrucVer; + UINT8 Unused1; +} PRIMARY_VOLUME_DESC_HEADER; + +typedef struct +{ + VENDOR_DEVICE_PATH Dp; + UINT64 VolumeSize; + ROOT_DIR_HEADER Root; + CHAR8 VolumeLabel[32]; +} AMI_ISO9660_DEVICE_PATH; + +#pragma pack() + +#endif +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/CORE_DXE/Partition/Gpt.c b/Core/CORE_DXE/Partition/Gpt.c new file mode 100644 index 0000000..3a1fe92 --- /dev/null +++ b/Core/CORE_DXE/Partition/Gpt.c @@ -0,0 +1,606 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/CORE_DXE/Partition/Gpt.c 16 7/19/12 10:26a Artems $ +// +// $Revision: 16 $ +// +// $Date: 7/19/12 10:26a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/CORE_DXE/Partition/Gpt.c $ +// +// 16 7/19/12 10:26a Artems +// [TAG] EIP94126 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] GPT system recovery can't work and backup GPT partition +// will also be destroyed after GPT recovery. +// [RootCause] Incorrect LBA used to restore GPT partition +// [Solution] Use correct LBA +// [Files] Gpt.c +// +// 15 5/02/11 5:57p Artems +// EIP 59571: New partition driver functionality as per UEFI spec v.2.3.1 +// +// 14 11/23/10 4:43p Vyacheslava +// [TAG] EIP45145 +// [Category] New Feature +// [Description] A new feature has done by Cire Lin: We're did the code +// for repairing GPT table. If CRC checking fails then it will run +// CopyGpt() to repair GPT table. +// +// 13 4/16/10 4:24p Pats +// EIP 30719: Support for the HDD with sector size more than 512bytes. +// +// 12 2/04/10 2:07p Oleksiyy +// Minor fixes +// +// 11 7/09/09 5:01p Oleksiyy +// Files clean-up +// +// 10 4/03/09 5:24p Oleksiyy +// EIP 20879: Linux GPT discovering logic improvement. +// +// 9 1/07/08 4:21p Robert +// Updated for coding standard +// +// 8 4/24/07 6:07p Robert +// Update for CHM compliance +// +// 7 4/12/07 7:04p Robert +// Coding Standard Updates +// +// 6 3/22/07 5:39p Robert +// Updated Files for coding standard +// +// 5 10/10/06 3:22p Yakovlevs +// Bug fixes. The GPT Partition Driver working now. +// +// 4 5/19/06 10:47p Felixp +// Device Path code updated to use NEXT_NODE/NODE_LENGTH/SET_NODE_LENGTH +// macros to remove direct access to the Length field +// +// 3 2/11/05 6:14p Felixp +// - Code optimized by using DPAddNode instead of DPAdd +// - bug fixes +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: Gpt.c +// +// Description: EFI GPT Partition Generic Driver. +// This file detects whether or not the system has a GPT format +// for the drive and sets up all partitions on the drive +// +//<AMI_FHDR_END> +//********************************************************************** + +//----------------------------------------------------------------------------- +// Includes +#include "Partition.h" +#include "Gpt.h" +#include "Mbr.h" + +//----------------------------------------------------------------------------- +// global variables + + +//----------------------------------------------------------------------------- +// Function Definitions + + +//----------------------------------------------------------------------------- +//<AMI_PHDR_START> +// Procedure: AdjustBufferSize +// +// Description: Calculates correct Buffer size for BlockIO trasfer +// +// Input: EFI_BLOCK_IO_PROTOCOL *BlockIo BlockIo Protocol Interface +// UINTN *BufferSize Pointer To the Size Needed +// +// Output: Modifies Buffer Size to reflect correct number of bytes +// +// Returns: Nothing +// +// Referrals: +// +//<AMI_PHDR_END> +//----------------------------------------------------------------------------- + +VOID AdjustBufferSize(IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN OUT UINTN *BufferSize) +{ + UINTN sz; + + // Calculate the size of trazaction + sz=BlockIo->Media->BlockSize * (*BufferSize/BlockIo->Media->BlockSize); + + if (*BufferSize % BlockIo->Media->BlockSize) sz+=BlockIo->Media->BlockSize; + + *BufferSize=sz; +} + + +//----------------------------------------------------------------------------- +//<AMI_PHDR_START> +// +// Procedure: CopyGpt +// +// Description: Copies a valid GPT to the location of an invalid one +// +// Input: +// BlockIo - pointer to the BlockIo partition so we can read and write +// to the Block Device +// DiskIo - Unused at this time +// Destination - Pointer to where the valid GPT will be copied +// Source - Pointer to a valid GPT +// +// Output: None - A valid GPT will be written to the Destination address +// +// Returns: None +// +// Referrals: CopyMem ReadBlocks CalculateCrc32 AllocatePool AdjustBufferSize +// WriteBlocks FreePool +// +//<AMI_PHDR_END> +//----------------------------------------------------------------------------- + +VOID CopyGpt( + EFI_BLOCK_IO_PROTOCOL *BlockIo, + EFI_DISK_IO_PROTOCOL *DiskIo, + GPT_HEADER *Destination, + GPT_HEADER *Source +) +{ + EFI_STATUS Status; + UINT8 *EntryArray; + EFI_LBA EntryLba; + UINTN Size; + UINT32 Crc32; + + // Calculate Buffer Size for Enrty array + Size = Source->NumberOfPartitionEntries * Source->SizeOfPartitionEntry; + AdjustBufferSize(BlockIo, &Size); + + if (Source->MyLba == 1) + EntryLba = Source->LastUsableLba + 1; + else + EntryLba = Source->AlternateLba + 1; + + // Copy the GPT Header + gBS->CopyMem( Destination, Source, sizeof(GPT_HEADER) ); + + Destination->MyLba = Source->AlternateLba; + Destination->AlternateLba = Source->MyLba; + Destination->PartitionEntryLba = EntryLba; + Destination->Crc32 = 0; + Destination->Header.CRC32 = 0; + + // Allocate Memory for Source Patrition Table Array + Status = gBS->AllocatePool( EfiBootServicesData, Size, &EntryArray ); + + // Zero it out + gBS->SetMem( EntryArray, Size, 0 ); + + // Read Source's Partition Table Entry Array to the buffer + Status = BlockIo->ReadBlocks( + BlockIo, + BlockIo->Media->MediaId, + Source->PartitionEntryLba, + Size, + EntryArray + ); + + // Calculate CRC32 of GIUID Partition Table Entry Array + gBS->CalculateCrc32( + (UINT8*)EntryArray, + Source->NumberOfPartitionEntries * Source->SizeOfPartitionEntry, + &Crc32 + ); + Destination->Crc32 = Crc32; + + gBS->CalculateCrc32( + (UINT8*)Destination, + sizeof(GPT_HEADER), + &Crc32 + ); + Destination->Header.CRC32 = Crc32; + + + // Write to Destination Partition Header Block + Status = BlockIo->WriteBlocks( + BlockIo, + BlockIo->Media->MediaId, + Destination->MyLba, + BlockIo->Media->BlockSize, + Destination + ); + + // Write Destination Partition Table Entry Array + Status = BlockIo->WriteBlocks( + BlockIo, + BlockIo->Media->MediaId, + Destination->PartitionEntryLba, + Size, + EntryArray + ); + + gBS->FreePool(EntryArray); +} + + +//<AMI_PHDR_START> +//============================================================================= +// Procedure: ValidateGptHeader +// +// Description: Checks if the GPT table is valid +// +// Input: +// BlockIo - Pointer to the Parent BlockIo instance +// GptHeader - Pointer to a memory area that contains the GPT header +// to validate +// HdrLoc - Header location +// +// Output: None +// +// Returns: +// EFI_SUCCESS - GPT is valid +// EFI_INVALID_PARAMETER - checks to see if the CRC, signature, and Header +// Location are vlaid +// EFI_OUT_OF_RESOURCES - Not enough free memory to allocate to read the +// GPT entry table +// +// Referrals: CalculateCrc32 MemCmp AdjustBufferSize AllocatePool ReadBlocks +// FreePool +// +//============================================================================= +//<AMI_PHDR_END> +EFI_STATUS ValidateGptHeader( + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN GPT_HEADER *GptHeader, + IN EFI_LBA HdrLoc +) +{ + EFI_STATUS Status; + UINT32 Crc; + UINT32 Temp32; + UINTN Size; + PARTITION_ENTRY *GptEntryTable; + + + // Get CRC of the Partition Header + Temp32 = GptHeader->Header.CRC32; + GptHeader->Header.CRC32 = 0; + + gBS->CalculateCrc32((UINT8*)GptHeader, sizeof(GPT_HEADER), &Crc); + GptHeader->Header.CRC32 = Crc; + + // Check calculated CRC + // Check signature + // Check that MyLBA parameter points to the location of the current Header + if (MemCmp(EFI_GPT_HEADER_ID, &GptHeader->Header.Signature, sizeof(UINT64)) + || (Temp32 != Crc) + || (GptHeader->MyLba != HdrLoc) ) + return EFI_INVALID_PARAMETER; + + // Calculate the size of trasaction + Size = GptHeader->NumberOfPartitionEntries * + GptHeader->SizeOfPartitionEntry; + AdjustBufferSize(BlockIo,&Size); + + // allocate memory for the Entry array + Status = gBS->AllocatePool( EfiBootServicesData, Size, &GptEntryTable); + + if (EFI_ERROR(Status)) return EFI_OUT_OF_RESOURCES; + + // get the data from the entry array + BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId, + GptHeader->PartitionEntryLba, + Size, GptEntryTable); + + // calculate the CRC value for the entry array + gBS->CalculateCrc32((UINT8*)GptEntryTable, + GptHeader->NumberOfPartitionEntries* + GptHeader->SizeOfPartitionEntry, &Crc); + + // the the allocated memory + if (GptEntryTable != NULL ) gBS->FreePool(GptEntryTable); + + // check if the CRC that was calculated matches the value that was stored + if (Crc != GptHeader->Crc32) return EFI_INVALID_PARAMETER; + + // All checks passed, the GPT is valid + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//============================================================================= +// Procedure: VerifyPartionTables +// +// Description: Check if either GPT is valid. if only one is then fix the other +// if both are bad, then it is not a valid GPT system. return error +// +// Input: +// BlockIo - pointer to the BlockIo partition so we can read and write +// to the Block Device +// DiskIo - Unused at this time +// +// Output: +// GPT - pointer to a memory space for one GPT +// +// Returns: EFI_SUCCESS - If a valid GPT is found +// EFI_UNSUPPORTED - if no valid GPT is found +// EFI_OUT_OF_RESOURCES - not enough allocateable memory is available +// +// Referrals: AllocatePool ReadBlocks FreePool AdjustBufferSize +// ValidateGPTHeader CopyGPT CopyMem +// +// Notes +// +//============================================================================= +//<AMI_PHDR_END> +EFI_STATUS VerifyPartionTables( + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + OUT GPT_HEADER *Gpt +) +{ + EFI_STATUS Status; + GPT_HEADER *Primary = NULL; + GPT_HEADER *Secondary = NULL; + MASTER_BOOT_RECORD *Pmbr = NULL; + UINTN Size; + UINT8 i, FoundPP = 0; + + // Allocate a buffer for the Protective MBR + Status = gBS->AllocatePool(EfiBootServicesData, BlockIo->Media->BlockSize, &Pmbr); + + if (EFI_ERROR(Status)) return EFI_OUT_OF_RESOURCES; + + // Read the Protective MBR from LBA #0 + Status = BlockIo->ReadBlocks (BlockIo, BlockIo->Media->MediaId, 0, + BlockIo->Media->BlockSize, Pmbr); + + if (EFI_ERROR (Status)) + { + gBS->FreePool(Pmbr); + return Status; + } + + for (i=0; i < 4; i++) + + // See if Protective MBR is valid and if not free allocated memory and return EFI_UNSUPPORTED + if ((Pmbr->PartRec[i].BootIndicator == 0x00) && (Pmbr->PartRec[i].OSType == 0xee) && + (Pmbr->PartRec[i].StartingLba == 1)) FoundPP++; + + if (FoundPP == 0) + { + gBS->FreePool(Pmbr); + return EFI_UNSUPPORTED; + } + + // Allocate memory to hold the data for the Primary and Secondary GPT headers + // Allocate Primary + Size=sizeof(GPT_HEADER); + AdjustBufferSize(BlockIo, &Size); + + Status = gBS->AllocatePool(EfiBootServicesData, Size, &Primary); + + // if error is returned, exit with No resources available + if (EFI_ERROR(Status)) + { + gBS->FreePool(Pmbr); + return EFI_OUT_OF_RESOURCES; + } + + // Allocate for secondary header + Status = gBS->AllocatePool(EfiBootServicesData, Size, &Secondary); + + // if error, free memory allocated for primary and then exit with no resources available + if (EFI_ERROR(Status)) + { + gBS->FreePool(Pmbr); + gBS->FreePool(Primary); + return EFI_OUT_OF_RESOURCES; + } + + // Read primary and backup table + BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId, 1, Size, Primary); + BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId, BlockIo->Media->LastBlock, Size, Secondary); + + // read primary header from the block device and verify if it is valid + if (EFI_ERROR(ValidateGptHeader(BlockIo, Primary, 1))) + { + // if primary is not valid, check secondary to see if it is valid + if (EFI_ERROR(ValidateGptHeader(BlockIo, Secondary, BlockIo->Media->LastBlock))) + { + gBS->FreePool(Pmbr); + gBS->FreePool(Primary); + gBS->FreePool(Secondary); + return EFI_UNSUPPORTED; + } + + // if secondary table is good, copy to primary + else + { + CopyGpt(BlockIo, DiskIo, Primary, Secondary); + } + } + + // if primary is good, check secondary + else + { + // if secondary is bad, copy primary to secondary + if (EFI_ERROR(ValidateGptHeader(BlockIo, Secondary, BlockIo->Media->LastBlock))) + { + CopyGpt(BlockIo, DiskIo, Secondary, Primary); + } + } + + // now that both tables are fixed, copy to GPT output variable and exit + gBS->CopyMem(Gpt, Primary, sizeof(GPT_HEADER)); + + // before we exit free all memory allocation and exit with success + gBS->FreePool(Pmbr); + gBS->FreePool(Primary); + gBS->FreePool(Secondary); + + return EFI_SUCCESS; +} + + + +//<AMI_PHDR_START> +//============================================================================= +// Procedure: GPTDiscoverPartitions +// +// Description: Searches GPT Table for partitions +// +// Input: +// *This - Pointer to the instance of this blockIo protocol +// *BlockIo - Pointer to the parent blockIo Protocol +// *DiskIo - Pointer to the parent DiskIo protocol +// *DevicePath - Pointer to the Parent's device path +// ControllerHandle - the parent's controller handle +// +// Output: None +// +// Returns: +// EFI_SUCCESS - Driver loaded +// other - Driver not loaded +// +// Referrals: AllocatePool FreePool VerifyPartionTables AdjustBufferSize +// MemCmp SetMem CopyMem CreateChildHandle SET_NODE_LENGTH +// +//============================================================================= +//<AMI_PHDR_END> +EFI_STATUS GptDiscoverPartitions ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_HANDLE ControllerHandle +) +{ + EFI_STATUS Status; + GPT_HEADER *Gpt = NULL; + UINT8 *EntryArray = NULL; + PARTITION_ENTRY *PartEntry=NULL; + HARDDRIVE_DEVICE_PATH HdDp; + PARTITION_DATA PData; + UINTN Idx; + UINTN Size; + + + // Allocate memory for a valid GPT partiton header + Status = gBS->AllocatePool(EfiBootServicesData, sizeof(GPT_HEADER), &Gpt); + + if (EFI_ERROR(Status)) + return EFI_OUT_OF_RESOURCES; + +// EFI_DEADLOOP(); + // verify that the GPT headers on this BlockIo device are valid + if (EFI_ERROR(VerifyPartionTables(BlockIo, DiskIo, Gpt )) ) + { + gBS->FreePool(Gpt); + return EFI_INVALID_PARAMETER; + } + + // If this gets executed, then the Headers are valid and the Entry array + // has the correct CRC value + // Now parse through the Entry Array and create instances for each + // partition on the media + // Check Entry Table Crc + Size = Gpt->NumberOfPartitionEntries * Gpt->SizeOfPartitionEntry; + AdjustBufferSize(BlockIo, &Size); + + Status = gBS->AllocatePool(EfiBootServicesData, Size, &EntryArray); + + if (EFI_ERROR(Status)) + { + gBS->FreePool(Gpt); + return EFI_OUT_OF_RESOURCES; + } + + BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId, + Gpt->PartitionEntryLba, Size, EntryArray); + + for (Idx = 0; Idx < Gpt->NumberOfPartitionEntries; Idx++) + { + PartEntry = (PARTITION_ENTRY *)(EntryArray + Idx * Gpt->SizeOfPartitionEntry); + + // Check to see if this is an unused partition + if (!(MemCmp(&PartEntry->PartitionTypeGuid, &gUnusedPartitionGuid, sizeof(EFI_GUID)))) + continue; // This is an unused partition + + if(PartEntry->Attributes & 0x2) //bit 1 of Attributes set? + continue; //no BlockIo for this partition - UEFI spec 2.3.1 p.5.3.3 table 19 + + // clear the data structure + gBS->SetMem(&PData, sizeof(PARTITION_DATA), 0); + + // set up the device path for the partition + HdDp.Header.Type = MEDIA_DEVICE_PATH; + HdDp.Header.SubType = MEDIA_HARDDRIVE_DP; + SET_NODE_LENGTH(&HdDp.Header,sizeof(HARDDRIVE_DEVICE_PATH)); + + // Idx is 0 based so add one so that partitionNumber is 1 based + HdDp.PartitionNumber = (UINT32) Idx + 1; + HdDp.PartitionStart = PartEntry->StartingLba; + HdDp.PartitionSize = PartEntry->EndingLba - PartEntry->StartingLba + 1; + gBS->CopyMem(&HdDp.Signature, &PartEntry->UniquePartitionGuid, + sizeof(EFI_GUID)); + HdDp.MBRType = MBR_TYPE_EFI_PARTITION_TABLE_HEADER; + HdDp.SignatureType = SIGNATURE_TYPE_GUID; + + PData.DevPath = DPAddNode(DevicePath, &HdDp.Header); + + // save pertinent info + PData.Handle = NULL; + PData.ParentHandle = ControllerHandle; + PData.ParentBlockIo = BlockIo; + PData.ParentDiskIo = DiskIo; + PData.StartingLba = PartEntry->StartingLba; + PData.EndingLba = PartEntry->EndingLba; + gBS->CopyMem(&PData.PartGuid, &PartEntry->PartitionTypeGuid, + sizeof (EFI_GUID)); + + // This is a valid GPT partition: Add a child instance + Status = CreateChildHandle(This, &PData, BlockIo->Media->BlockSize); + + } + + gBS->FreePool(Gpt); + gBS->FreePool(EntryArray); + + return EFI_SUCCESS; +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/CORE_DXE/Partition/Gpt.h b/Core/CORE_DXE/Partition/Gpt.h new file mode 100644 index 0000000..120b90a --- /dev/null +++ b/Core/CORE_DXE/Partition/Gpt.h @@ -0,0 +1,161 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/CORE_DXE/Partition/Gpt.h 6 7/09/09 5:01p Oleksiyy $ +// +// $Revision: 6 $ +// +// $Date: 7/09/09 5:01p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/CORE_DXE/Partition/Gpt.h $ +// +// 6 7/09/09 5:01p Oleksiyy +// Files clean-up +// +// 5 1/08/08 4:37p Robert +// +// 4 1/08/08 4:00p Robert +// +// 3 1/07/08 4:21p Robert +// Updated for coding standard +// +// 2 4/24/07 6:06p Robert +// Update for CHM compliance +// +// 1 1/28/05 1:17p Felixp +// +// 2 1/18/05 3:22p Felixp +// PrintDebugMessage renamed to Trace +// +// 1 12/22/04 6:19p Admin +// +// 1 12/22/04 6:18p Admin +// +// 2 12/02/04 5:54p Robert +// Partition driver version works +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: <GPT.h> +// +// Description: EFI GPT Partition Generic Driver Header. +// +//<AMI_FHDR_END> +//********************************************************************** + +#ifndef _GPT_H_ +#define _GPT_H_ + +#pragma pack(1) + +#define EFI_GPT_HEADER_ID "EFI PART" + +// GUID Partition Table Header +//<AMI_STHDR_START> +//============================================================================ +// Structure: GPT_HEADER +// +// Description: Data Structure definition of the GPT table +// +// Fields: +// Header - EFI_TABLE_HEADER - defines generic EFI header information +// MyLba - EFI_LBA - The LBA that contains this GPT data structure +// AlternateLba - EFI_LBA - The LBA that contains the alternative GPT +// data structure +// FirstUsableLba - EFI_LBA - the first logical block that can be used +// in a partition that is defined by the GPT +// LastUsableLba - EFI_LBA - the last logical block that can be used +// in a partition that is defined by the GPT +// DiskGuid - EFI_GUID - Unique GUID to identify this hard drive +// PartitionEntryLba - EFI_LBA - the starting LBA of the GUID Partition +// Entry Array +// NumberOfPartitionEntries - UINT32 - the number of partition entries +// in the Array +// SizeOfPartitionEntry - UINT32 - the size of each partition entry +// Crc32 - UINT32 - crc value of the entire GPT block +// +// Referral: +// EFI_TABLE_HEADER EFI_LBA EFI_GUID +//============================================================================ +//<AMI_STHDR_END> +typedef struct +{ + EFI_TABLE_HEADER Header; + EFI_LBA MyLba; + EFI_LBA AlternateLba; + EFI_LBA FirstUsableLba; + EFI_LBA LastUsableLba; + EFI_GUID DiskGuid; + EFI_LBA PartitionEntryLba; + UINT32 NumberOfPartitionEntries; + UINT32 SizeOfPartitionEntry; + UINT32 Crc32; +} GPT_HEADER; + +// GPT Partition Entry +//<AMI_STHDR_START> +//============================================================================ +// Structure: PARTITION_ENTRY +// +// Description: Data Structure definition of a partion entry in the GPT table +// +// Fields: +// PartitionTypeGuid - EFI_GUID - contains GUID that defines that type +// of GUID +// UniquePartitionGuid - EFI_GUID - contains unique GUID for each +// partition +// StartingLba - EFI_LBA - first LBA of the partition +// EndingLba - EFI_LBA - last logical block address +// Attributes - UINT64 - UEFI defined attributes +// Bit 0 - Partition is required for platform to function +// Bits 1 - 47 - undefined +// Bits 48 - 64 - reserved for GUID specific use +// PartitionName[36] - CHAR16 - unicode string containing the name of +// the partition +// +// Referral: +// EFI_LBA +//============================================================================ +//<AMI_STHDR_END> +typedef struct +{ + EFI_GUID PartitionTypeGuid; + EFI_GUID UniquePartitionGuid; + EFI_LBA StartingLba; + EFI_LBA EndingLba; + UINT64 Attributes; + CHAR16 PartitionName[36]; +} PARTITION_ENTRY; + + +#pragma pack() + +#endif +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/CORE_DXE/Partition/Mbr.c b/Core/CORE_DXE/Partition/Mbr.c new file mode 100644 index 0000000..7ccdae8 --- /dev/null +++ b/Core/CORE_DXE/Partition/Mbr.c @@ -0,0 +1,407 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/CORE_DXE/Partition/Mbr.c 12 4/16/10 4:24p Pats $ +// +// $Revision: 12 $ +// +// $Date: 4/16/10 4:24p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/CORE_DXE/Partition/Mbr.c $ +// +// 12 4/16/10 4:24p Pats +// EIP 30719: Support for the HDD with sector size more than 512bytes. +// +// 11 2/04/10 3:03p Oleksiyy +// EIP 31633 Minor Fix +// +// 10 7/09/09 5:01p Oleksiyy +// Files clean-up +// +// 9 11/13/08 6:10p Felixp +// Bug fix in MbrCreateChildHandle: unsed part of the signature (12 bytes) +// in hard driver device path was never initialized. +// +// 8 1/07/08 4:21p Robert +// Updated for coding standard +// +// 7 4/25/07 11:52a Robert +// Updated for CHM and coding standard commpliance +// +// 5 5/19/06 10:47p Felixp +// Device Path code updated to use NEXT_NODE/NODE_LENGTH/SET_NODE_LENGTH +// macros to remove direct access to the Length field +// +// 3 7/12/05 5:01p Robert +// The Free BSD operating system created a partition that referenced +// itself. This was not checked for in the partition driver so an +// infinite loop was created. +// this reference now causes an error condition.. +// +// 2 2/11/05 6:13p Felixp +// Code optimized by using DPAddNode instead of DPAdd +// +// 6 12/21/04 4:54p Markw +// Modified device path defines for consistency. +// +// 5 12/02/04 5:54p Robert +// Partition driver version works +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: Mbr.c +// +// Description: EFI Mbr Partition Generic Driver. This file finds all +// the partitions defined in the MBR found on a Device +// +//<AMI_FHDR_END> +//********************************************************************** +//----------------------------------------------------------------------------- +// Includes +#include "partition.h" +#include "mbr.h" + + +//----------------------------------------------------------------------------- +// Global Variables +EFI_GUID gMbrPartition = EFI_PART_TYPE_LEGACY_MBR_GUID; + + + +//----------------------------------------------------------------------------- +// Function Prototypes + + + +//----------------------------------------------------------------------------- +// Function Definitions + +//----------------------------------------------------------------------------- +//<AMI_PHDR_START> +// Procedure: CheckValidMbr +// +// Description: Makes sure the Master Boot Record has valid partitions +// +// Input: +// *BlockIo - Pointer to the parent blockIo Protocol +// *Mbr - pointer to a data structure that contains the MBR for +// the current drive +// +// Output: None +// +// Returns: +// TRUE - MBR is valid +// FALSE - MBR is invalid +// +// Referrals: ReadBlocks +// +//<AMI_PHDR_END> +//----------------------------------------------------------------------------- + +BOOLEAN CheckValidMbr( + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN MASTER_BOOT_RECORD *Mbr +) +{ + EFI_STATUS Status; + EFI_LBA EndLba; + UINT8 PartitionFound = 0; + UINT8 Idx; + UINT8 Loop2; + + // read the first block of the Harddrive + Status = BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId, 0, + BlockIo->Media->BlockSize, Mbr); + + if (Mbr->Sig != MBR_SIGNATURE) + return FALSE; + + // check for valid LBA range for all the partitions + for (Idx = 0; Idx < NUM_MBR_PARTITIONS; Idx++) + { + // ignore partitions whose OSType or Size is zero + if ((Mbr->PartRec[Idx].OSType == 0) + || (Mbr->PartRec[Idx].SizeInLba == 0)) + continue; + + if (Mbr->PartRec[Idx].StartingLba == 0) + continue; + + PartitionFound++; + + EndLba = Mbr->PartRec[Idx].StartingLba + + Mbr->PartRec[Idx].SizeInLba - 1; + + // check to make sure the partition does not exceed the length + // of the disk + if (EndLba > BlockIo->Media->LastBlock) + return FALSE; + + // Now loop through all partitions to make sure they don't overlap + for (Loop2 = Idx+1; Loop2 < NUM_MBR_PARTITIONS; Loop2++) + { + // ignore partitions whose OSType or Size is zero + if ((Mbr->PartRec[Loop2].OSType == 0) + || (Mbr->PartRec[Loop2].SizeInLba == 0)) + continue; + + // check for overlapping partitions + if ( EndLba >= Mbr->PartRec[Loop2].StartingLba ) + return FALSE; + } + } + + if (PartitionFound) + return TRUE; + else + return FALSE; +} + + + +//----------------------------------------------------------------------------- +//<AMI_PHDR_START> +// Procedure: MbrCreateChildHandle +// +// Description: Searches Master Boot Record for partitions +// +// Input: +// *This - Pointer to the instance of this blockIo protocol +// *BlockIo - Pointer to the parent blockIo Protocol +// *DiskIo - Pointer to the parent DiskIo protocol +// *DevicePath - Pointer to the Parent's device path +// ControllerHandle - the parent's controller handle +// +// Output: None +// +// Returns: +// EFI_SUCCESS - Driver loaded +// other - Driver not loaded +// +// Referrals: AllocatePool FreePool CheckValidMbr SetMem ReadBlocks +// CopyMem CreateChildHandle SET_NODE_LENGTH +//<AMI_PHDR_END> +//----------------------------------------------------------------------------- + +EFI_STATUS MbrCreateChildHandle( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_HANDLE ControllerHandle +) +{ + EFI_STATUS Status; + MASTER_BOOT_RECORD *Mbr = NULL; + MASTER_BOOT_RECORD *ExtPart = NULL; + UINT8 Idx; + UINT32 PartitionExists = 0; + PARTITION_DATA PData; + EFI_GUID *PartType = NULL; + EFI_LBA Lba; + HARDDRIVE_DEVICE_PATH HdDp; + + + // allocate memory for the MBR and then read the data from the disk + Status = gBS->AllocatePool( EfiBootServicesData, + BlockIo->Media->BlockSize, &Mbr); + + if (EFI_ERROR(Status)) + return EFI_OUT_OF_RESOURCES; + + // check to see if the current drive has a valid MBR and a valid + // partition on the drive + if (CheckValidMbr(BlockIo, Mbr) == FALSE) + { + gBS->FreePool(Mbr); + return EFI_INVALID_PARAMETER; + } + + // To get here there is a valid partition + // create a handle for the partitions + + // set up the device path header for the partition + HdDp.Header.Type = MEDIA_DEVICE_PATH; + HdDp.Header.SubType = MEDIA_HARDDRIVE_DP; + SET_NODE_LENGTH(&HdDp.Header,sizeof(HARDDRIVE_DEVICE_PATH)); + + // Loop through the partitions + for (Idx=0; Idx < NUM_MBR_PARTITIONS; Idx++) + { + // skip over empty partitions + if ((Mbr->PartRec[Idx].OSType == 0) + || (Mbr->PartRec[Idx].SizeInLba == 0)) + continue; + + // Take care of repetative data assignment + // clear the data structure + gBS->SetMem(&PData, sizeof(PARTITION_DATA), 0); + + // set up the device path for the partition + HdDp.MBRType = MBR_TYPE_MASTER_BOOT_RECORD; + HdDp.SignatureType = SIGNATURE_TYPE_MBR; + pBS->SetMem(&HdDp.Signature,sizeof(HdDp.Signature),0); + PData.Handle = NULL; + PData.ParentBlockIo = BlockIo; + PData.ParentDiskIo = DiskIo; + + + // Now that a valid partition is found process it + // TODO: are there any other types of extended partitions + // if so, add them to this if statement + if ((Mbr->PartRec[Idx].OSType == EXTENDED_PARTITION) || + (Mbr->PartRec[Idx].OSType == WIN95_EXTENDED_PARTITION)) + { + // process the logical partitions that may or may not exist + Status = gBS->AllocatePool( EfiBootServicesData, + BlockIo->Media->BlockSize, &ExtPart); + + if (EFI_ERROR(Status)) + { + gBS->FreePool(Mbr); + return EFI_OUT_OF_RESOURCES; + } + + // defines where to start reading the next MBR/partition + // table from + Lba = Mbr->PartRec[Idx].StartingLba; + + // loop through logical partitions: any number of + // possible partitions + while (TRUE) + { + // if the table points back to itself, exit + if ( Lba == 0) + break; + + // get Partition table from the first block of the device + Status = BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId, + Lba, BlockIo->Media->BlockSize, ExtPart); + + // check to see if the disk was read + // Also check for All logical partitions having an OSType + // of 0x05 or EXTENDED_PARTITION + if (EFI_ERROR(Status)) + { + gBS->FreePool(Mbr); + gBS->FreePool(ExtPart); + return Status; + } + + // make sure this is a valid partition + if (ExtPart->PartRec[0].OSType == NO_PARTITION) + break; + + // check for problems that make the partition invalid + if ((Lba + ExtPart->PartRec[0].SizeInLba) > + (Mbr->PartRec[Idx].StartingLba + + Mbr->PartRec[Idx].SizeInLba)) + break; + + // register the Partition + HdDp.PartitionNumber = ++PartitionExists; + + // notice that the start of the partition is after the + // partition table + HdDp.PartitionStart = ExtPart->PartRec[0].StartingLba + Lba; + HdDp.PartitionSize = ExtPart->PartRec[0].SizeInLba; + gBS->CopyMem(&HdDp.Signature, &ExtPart->UniqueMbrSig, + sizeof(UINT32)); + PData.StartingLba = HdDp.PartitionStart; + PData.EndingLba = HdDp.PartitionStart + + ExtPart->PartRec[0].SizeInLba - 1; + + // create device path + PData.DevPath = DPAddNode(DevicePath, &HdDp.Header); + + // Store Parent Handle + PData.ParentHandle = ControllerHandle; + + // if the OSType member is 0xEF this variable set. + // otherwise it is left as 0 + if (ExtPart->PartRec[0].OSType == EFI_SYSTEM_PARTITION) + gBS->CopyMem(&PData.PartGuid, &gMbrPartition, + sizeof (EFI_GUID)); + + // This is a valid GPT partition: Add a child instance + Status = CreateChildHandle(This, &PData, BlockIo->Media->BlockSize); + + // check to see if the next partition is an extended partition + if ((ExtPart->PartRec[1].OSType != EXTENDED_PARTITION) && + (ExtPart->PartRec[1].OSType != WIN95_EXTENDED_PARTITION) ) + break; + + // get set up for the next partition. The Starting Lba + // address is a relative address inside the extended + // partition add the starting address of the extended + // partition to get the actual LBA where it starts + Lba = ExtPart->PartRec[1].StartingLba + + Mbr->PartRec[Idx].StartingLba; + } + } + + else // process primary partition + { + // set up the device path for the partition + HdDp.PartitionNumber = ++PartitionExists; + HdDp.PartitionStart = Mbr->PartRec[Idx].StartingLba; + HdDp.PartitionSize = Mbr->PartRec[Idx].SizeInLba; + gBS->CopyMem(HdDp.Signature, &Mbr->UniqueMbrSig, sizeof(UINT32)); + + // create device path + PData.DevPath = DPAddNode(DevicePath, &HdDp.Header); + + // save pertinent info + PData.StartingLba = Mbr->PartRec[Idx].StartingLba; + PData.EndingLba = Mbr->PartRec[Idx].StartingLba + + Mbr->PartRec[Idx].SizeInLba - 1; + + // Store Parent Handle + PData.ParentHandle = ControllerHandle; + + // if the OSType member is 0xEF is this variable set. + // otherwise it is left as 0 + if (Mbr->PartRec[Idx].OSType == 0xEF) + gBS->CopyMem(&PData.PartGuid, &gMbrPartition, + sizeof (EFI_GUID)); + + // This is a valid GPT partition: Add a child instance + Status = CreateChildHandle(This, &PData, BlockIo->Media->BlockSize); + + } + } + + gBS->FreePool(Mbr); + gBS->FreePool(ExtPart); + + return EFI_SUCCESS; +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/CORE_DXE/Partition/Mbr.h b/Core/CORE_DXE/Partition/Mbr.h new file mode 100644 index 0000000..2aa5123 --- /dev/null +++ b/Core/CORE_DXE/Partition/Mbr.h @@ -0,0 +1,171 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/CORE_DXE/Partition/Mbr.h 7 7/09/09 5:01p Oleksiyy $ +// +// $Revision: 7 $ +// +// $Date: 7/09/09 5:01p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/CORE_DXE/Partition/Mbr.h $ +// +// 7 7/09/09 5:01p Oleksiyy +// Files clean-up +// +// 6 1/08/08 3:10p Robert +// +// 5 1/08/08 3:08p Robert +// +// 4 1/07/08 4:21p Robert +// Updated for coding standard +// +// 3 4/25/07 11:53a Robert +// Updated for CHM and Coding Standard Compliance +// +// 2 4/24/05 12:45a Felixp +// Definitions of SIGNATURE_TYPE_xxx macroses removed since they are +// already defined in DevicePath.h +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: <Mbr.h> +// +// Description: EFI Mbr Partition Generic Driver Header. This header +// contains Data structures and Definitions needed to recognize +// partitions in an MBR +// +//<AMI_FHDR_END> +//********************************************************************** +#ifndef _MBR_H +#define _MBR_H + +#define MBR_SIGNATURE 0xaa55 +#define NUM_MBR_PARTITIONS 4 + +// Type definitions for the Hard drive device path +#define MBR_TYPE_MASTER_BOOT_RECORD 0x01 +#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02 + +// Needed Partition Type definitions for MBR +#define NO_PARTITION 0x0 +#define EXTENDED_PARTITION 0x05 +#define WIN95_EXTENDED_PARTITION 0x0f + + +//<AMI_GHDR_START> +//------------------------------------------------------------------ +// Name: Data_Structures +// +// Description: +// Data Structures needed for MBR +// +// MASTER_BOOT_RECORD - Data Structure definition of the +// MBR located in the first block on an MBR drive +// +// MBR_PARTITION - Data Structure definition for each +// partition in the MBR +// +//------------------------------------------------------------------ +//<AMI_GHDR_END> + +#pragma pack(1) + +//<AMI_STHDR_START> +//============================================================================ +// Structure: MBR_PARTITION +// +// Description: Data Structure that defines a partition within the MBR +// +// Fields: +// BootIndicator - UINT8 - indicates whether this partition is bootable +// StartHead - UINT8 - unused in EFI +// StartSector - UINT8 - unused in EFI +// StartTrack - UINT8 - unused in EFI +// OSType - UINT8 - defines type of the partition +// EndHead - UINT8 - unused in EFI +// EndSector - UINT8 - unused in EFI +// EndTrack - UINT8 - unused in EFI +// StartingLba - UINT32 - LBA where the partiton starts on the hard drive +// SizeInLba - UINT32 - LBA where the partiton ends on the hard drive +// +// Referral: +// None +//============================================================================ +//<AMI_STHDR_END> +typedef struct _MBR_PARTITION +{ + UINT8 BootIndicator; + UINT8 StartHead; + UINT8 StartSector; + UINT8 StartTrack; + UINT8 OSType; + UINT8 EndHead; + UINT8 EndSector; + UINT8 EndTrack; + UINT32 StartingLba; + UINT32 SizeInLba; +} MBR_PARTITION; + + +// MBR Partition table +//============================================================================ +// Structure: MASTER_BOOT_RECORD +// +// Description: Data Structure that mimicks the structure of a Master Boot +// Record on a hard drive +// +// Fields: +// BootCode[440] - UINT8 - executable code in the first 440 bytes of a +// hard drive +// UniqueMbrSig - UINT32 - Uniques signature associated with the hard +// drive +// Unknown - UINT16 - an unknown portion of the data structure +// PartRec[4] - MBR_PARTITION - an array of partition entries that +// define the partitions that exist on the hard drive +// Sig - UINT16 - 0xaa55 - value that indicates this is an MBR +// +// Referral: +// MBR_PARTITION +//============================================================================ +//<AMI_STHDR_END> +typedef struct _MASTER_BOOT_RECORD +{ + UINT8 BootCode[440]; + UINT32 UniqueMbrSig; + UINT16 Unknown; + MBR_PARTITION PartRec[4]; + UINT16 Sig; +} MASTER_BOOT_RECORD; + + +#pragma pack() +#endif + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/CORE_DXE/Partition/Partition.c b/Core/CORE_DXE/Partition/Partition.c new file mode 100644 index 0000000..78cbb10 --- /dev/null +++ b/Core/CORE_DXE/Partition/Partition.c @@ -0,0 +1,1006 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/CORE_DXE/Partition/Partition.c 21 10/27/11 3:57p Artems $ +// +// $Revision: 21 $ +// +// $Date: 10/27/11 3:57p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/CORE_DXE/Partition/Partition.c $ +// +// 21 10/27/11 3:57p Artems +// EIP 73250: Verified DriverBinding Stop function frees all resources +// allocated by Start function +// +// 20 10/25/11 12:01p Artems +// EIP 70530: Fixed bugs reported by SCT 2.3.1 +// +// 19 8/12/11 12:16p Artems +// EIP 64107: Added changes for module to be compliant with UEFI +// specification v 2.3.1 +// +// 18 5/02/11 5:58p Artems +// EIP 59571: Extended partition driver functionality - support of BlockIO +// protocol version 3 +// +// 17 2/05/11 3:52p Artems +// Removed previous check-in changes +// +// 16 1/06/11 5:59p Oleksiyy +// [TAG] EIP28607 +// [Category] Improvement +// [Description] System was hanging for some time if Floppy Media +// removed while writing in meda in progress. +// EFI_TPL_CALLBACK priority level rised during media related calls. +// [Files] DiskIo.c, Info.c, MediaAccess.c, Open.c, Partition.c +// +// 15 2/04/10 3:06p Oleksiyy +// EIP 31633 Minor fixes. OpenProtocol error status handling added to +// DriverBindingStop function. +// +// 14 8/28/09 9:10a Felixp +// Component Name protocol implementation is upadted to support both +// ComponentName and ComponentName2 protocols +// (based on value of the EFI_SPECIFICATION_VERSION SDL token). +// +// 13 7/09/09 5:01p Oleksiyy +// Files clean-up +// +// 12 1/16/09 11:25a Felixp +// Bug fix in the DriverBindingStop function. +// The stop function was unconditionally closing disk I/O protocol. +// The protocol should only be closed when no child devices exist. +// +// 11 1/07/08 4:21p Robert +// Updated for coding standard +// +// 10 4/26/07 9:32a Robert +// Updated for CHM and Coding Standard compliance +// +// 8 3/23/07 5:13p Robert +// More coding standard changes and updated the copyright date +// +// 7 3/22/07 5:39p Robert +// Updated Files for coding standard +// +// 6 10/10/06 3:43p Yakovlevs +// Uncommented GPT Partition discovery +// +// 5 8/24/06 12:34p Felixp +// x64 support (fixes for warnings/errors) +// +// 3 10/28/05 8:36p Felixp +// DriverBindingSupported: Device Path test changed from BY_DRIVER to +// TEST_PROTOCOL +// +// 2 2/08/05 12:50p Felixp +// Bug fix in ReadBlocks and WriteBlocks: attemp to read/write +// Last LBA on the partition returned EFI_INVALID_PARAMETER +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: Partition.c +// +// Description: EFI Partition Generic Driver. Provides the Driver +// Binding protocol and a Block I/O protocol for Partition detection +// and interaction +// +//<AMI_FHDR_END> +//********************************************************************** +//;------------------------------------------------------------------------- +// Includes +#include "partition.h" + + +//;------------------------------------------------------------------------- +// Global Variables +EFI_BOOT_SERVICES *gBS; +EFI_GUID gUnusedPartitionGuid = EFI_PART_TYPE_UNUSED_GUID; +static EFI_GUID gEfiDriverBindingProtocolGuid = EFI_DRIVER_BINDING_PROTOCOL_GUID; + +EFI_STATUS gDevicePathStatus = EFI_SUCCESS; +EFI_STATUS gDiskIoStatus = EFI_SUCCESS; + +//;------------------------------------------------------------------------- +//GUID Variables +static EFI_GUID gDevicePathGuid = EFI_DEVICE_PATH_PROTOCOL_GUID; +EFI_GUID gBlockIoGuid = EFI_BLOCK_IO_PROTOCOL_GUID; +EFI_GUID gDiskIoGuid = EFI_DISK_IO_PROTOCOL_GUID; + +//;------------------------------------------------------------------------- +// Function Prototypes +EFI_STATUS DriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ); + +EFI_STATUS EFIAPI DriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ); + +EFI_STATUS EFIAPI DriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer); + +EFI_STATUS Reset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification); + +EFI_STATUS ReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer ); + +EFI_STATUS WriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer ); + +EFI_STATUS FlushBlocks ( IN EFI_BLOCK_IO_PROTOCOL *PartBlockIo); + +//;------------------------------------------------------------------------- +// Protocol Definition +EFI_BLOCK_IO_PROTOCOL mPartitionBlockIo = +{ + EFI_BLOCK_IO_PROTOCOL_REVISION3, + NULL, + Reset, + ReadBlocks, + WriteBlocks, + FlushBlocks +}; + + +//;------------------------------------------------------------------------- +// Partition Driver Binding Procol +EFI_DRIVER_BINDING_PROTOCOL gPartitionDriverBinding = +{ + DriverBindingSupported, + DriverBindingStart, + DriverBindingStop, + 0x10, + NULL, + NULL +}; + + +//;------------------------------------------------------------------------- +// Function Definitions +#ifdef EFI_DEBUG +#ifndef EFI_COMPONENT_NAME2_PROTOCOL_GUID //old Core +#ifndef LANGUAGE_CODE_ENGLISH +#define LANGUAGE_CODE_ENGLISH "eng" +#endif +static BOOLEAN LanguageCodesEqual( + CONST CHAR8* LangCode1, CONST CHAR8* LangCode2 +){ + return LangCode1[0]==LangCode2[0] + && LangCode1[1]==LangCode2[1] + && LangCode1[2]==LangCode2[2]; +} +static EFI_GUID gEfiComponentName2ProtocolGuid = EFI_COMPONENT_NAME_PROTOCOL_GUID; +#endif +//Driver Name +static UINT16 *gDriverName=L"AMI Partition Driver"; + +//<AMI_PHDR_START> +//-------------------------------------------------------------------------- +// +// Procedure: ComponentNameGetControllerName +// +// Description: Retrieves a Unicode string that is the user readable name of +// the controller that is being managed by an EFI Driver. +// +// Input: +// This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL +// instance. +// ControllerHandle - The handle of a controller that the driver specified +// by This is managing. This handle specifies the controller whose +// name is to be returned. +// ChildHandle - The handle of the child controller to retrieve the name +// of. This is an optional parameter that may be NULL. It will be +// NULL for device drivers. It will also be NULL for a bus drivers +// that wish to retrieve the name of the bus controller. It will +// not be NULL for a bus driver that wishes to retrieve the name of +// a child controller. +// Language - A pointer to a three character ISO 639-2 language identifier. +// This is the language of the controller name that that the caller +// is requesting, and it must match one of the languages specified +// in Supported Languages. The number of languages supported by a +// driver is up to the driver writer. +// +// Output: +// ControllerName - A pointer to the Unicode string to return. This +// Unicode string is the name of the controller specified by +// ControllerHandle and ChildHandle in the language specified by +// Language from the point of view of thedriver specified by This. +// +// Returns: +// EFI_SUCCESS - The Unicode string for the user readable name in the +// language specified by Language for the driver specified by This +// was returned in DriverName. +// EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. +// EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid +// EFI_HANDLE. +// EFI_INVALID_PARAMETER - Language is NULL. +// EFI_INVALID_PARAMETER - ControllerName is NULL. +// EFI_UNSUPPORTED - The driver specified by This is not currently +// managing the controller specified by ControllerHandle and +// ChildHandle. +// EFI_UNSUPPORTED - The driver specified by This does not support the +// language specified by Language. +// +// Referrals: +// +// Notes: +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> +static EFI_STATUS ComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME2_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName ) +{ + return EFI_UNSUPPORTED; +} + +//<AMI_PHDR_START> +//-------------------------------------------------------------------------- +// Procedure: ComponentNameGetDriverName +// +// Description: Returns the Driver Name if the language is supported +// +// Input: +// This - Pointer to the instance of this driver +// Language - Current operating language +// DriverName - return parameter that will contain the Driver's Name +// +// Output: DriverName - return parameter that will contain the Driver's Name +// +// Returns: +// EFI_SUCCESS - Driver loaded +// EFI_INVALID_PARAMETER - If the Language or DriverName variable is +// not defined +// EFI_UNSUPPORTED - If the current laungage is not supported +// +// Referrals: +// +// Notes: +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> +static EFI_STATUS ComponentNameGetDriverName( + IN EFI_COMPONENT_NAME2_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName) +{ + //Supports only English + if (!Language || !DriverName) return EFI_INVALID_PARAMETER; + + if (!LanguageCodesEqual( Language, LANGUAGE_CODE_ENGLISH)) + return EFI_UNSUPPORTED; + else + *DriverName=gDriverName; + + return EFI_SUCCESS; +} + +//Component Name Protocol +static EFI_COMPONENT_NAME2_PROTOCOL gComponentName = +{ + ComponentNameGetDriverName, + ComponentNameGetControllerName, + LANGUAGE_CODE_ENGLISH +}; +#endif + + +//<AMI_PHDR_START> +//-------------------------------------------------------------------------- +// Procedure: PartitionEntryPoint +// +// Description: Register Driver Binding protocol for this driver. +// +// Input: +// ImageHandle - Identification Handle for the Partition +// Block I/O driver +// *SystemTable - Pointer to the EFI System Table +// +// Returns: +// EFI_SUCCESS - Driver Binding Protocol Loaded +// other - Driver Binding Protocol not loaded +// +// Referrals: InitAmiLib InstallMultipleProtocolInterfaces +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS PartitionEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable +) +{ + EFI_STATUS Status; + + InitAmiLib(ImageHandle, SystemTable); + + gBS = SystemTable->BootServices; + + // initiaize the ImageHandle and DriverBindingHandle + gPartitionDriverBinding.DriverBindingHandle = NULL; + gPartitionDriverBinding.ImageHandle = ImageHandle; + + // Install driver binding protocol here + Status = gBS->InstallMultipleProtocolInterfaces ( + &gPartitionDriverBinding.DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, + &gPartitionDriverBinding, +#ifdef EFI_DEBUG + &gEfiComponentName2ProtocolGuid, &gComponentName, +#endif + NULL); + + + return Status; +} + + +//<AMI_PHDR_START> +//-------------------------------------------------------------------------- +// Procedure: DriverBindingSupported +// +// Description: Test to see if this driver supports ControllerHandle. Any +// ControllerHandle than contains a BlockIo and DiskIo protocol can be +// supported. +// +// Input: +// This - Protocol instance pointer. +// ControllerHandle - Handle of device to test +// RemainingDevicePath - Not used +// +// Output: None +// +// Returns: +// EFI_SUCCESS - This driver supports this device +// EFI_ALREADY_STARTED - This driver is already running on this device +// other - This driver does not support this device +// +// Referrals: OpenProtocol CloseProtocol +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> +static EFI_STATUS DriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath +) +{ + EFI_DISK_IO_PROTOCOL *DiskIo; + EFI_STATUS Status; + + // see if the DevicePath is installed on controllerHandle + Status = gBS->OpenProtocol(ControllerHandle, &gDevicePathGuid, + NULL, This->DriverBindingHandle, + ControllerHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL); + + if (EFI_ERROR(Status)) + return Status; + + // Close the Device Path Protocol once the tests have been done + gBS->CloseProtocol(ControllerHandle, &gDevicePathGuid, + This->DriverBindingHandle, ControllerHandle); + + // see if the DiskIo has already been started on controllerHandle + Status = gBS->OpenProtocol(ControllerHandle, &gDiskIoGuid, + &DiskIo, This->DriverBindingHandle, + ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER); + + if (EFI_ERROR(Status)) + return Status; + + // Close the DiskIo protocol once the tests have been done + gBS->CloseProtocol(ControllerHandle, &gDiskIoGuid, + This->DriverBindingHandle, ControllerHandle); + + // Now check for BlockIo Protocol + Status = gBS->OpenProtocol(ControllerHandle, &gBlockIoGuid, + NULL, This->DriverBindingHandle, ControllerHandle, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL); + + // return the status of finding the BlockIo protocol. + // if it gets this far the driver supports this device + return Status; +} + + +//<AMI_PHDR_START> +//-------------------------------------------------------------------------- +// Procedure: DriverBindingStart +// +// Description: Start this driver on ControllerHandle by opening a Block IO and +// Disk IO protocol, reading Device Path, and creating a child handle with +// a Disk IO and device path protocol. +// +// Input: +// This - Protocol instance pointer. +// ControllerHandle - Handle of device to bind driver to +// RemainingDevicePath - Not used +// +// Output: None +// +// Return: +// EFI_SUCCESS - This driver is added to DeviceHandle +// other - This driver does not support this device +// +// Referrals: OpenProtocol CloseProtocol GptDiscoverPartitions +// ElToritoCreateChildHandle MbrCreateChildHandle +// +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> +static EFI_STATUS EFIAPI DriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath +) +{ + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_DISK_IO_PROTOCOL *DiskIo; + + // Open the BlockIo protocol first because we are opening it by + // GET_PROTOCOL, if this fails it does not need to be closed. It is + // opened by GET_PROTOCOL because DiskIo already opens it BY_DRIVER + Status = gBS->OpenProtocol(ControllerHandle, &gBlockIoGuid, + &BlockIo, This->DriverBindingHandle, + ControllerHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + + if (EFI_ERROR (Status)) + return Status; + + Status = gBS->OpenProtocol(ControllerHandle, &gDevicePathGuid, + &ParentDevicePath, This->DriverBindingHandle, + ControllerHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + + if (EFI_ERROR (Status)) + return Status; + + // Check to see if the Controller has already been started by + // another driver + // Now open the DiskIo protocol for the controller + Status = gBS->OpenProtocol(ControllerHandle, &gDiskIoGuid, + &DiskIo, This->DriverBindingHandle, + ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER); + + if (EFI_ERROR (Status)) + { + // if there is an error, close all opened protocols, only close + // this one if + // Close the Device Path protocol once the tests have been done + gBS->CloseProtocol(ControllerHandle, &gDevicePathGuid, + This->DriverBindingHandle, ControllerHandle); + + return Status; + } + + + // parse the devices and create the child handles + if (BlockIo->Media->MediaPresent == TRUE) + { + Status = EFI_NOT_FOUND; + + // search for the children + Status = GptDiscoverPartitions(This, BlockIo, DiskIo, + ParentDevicePath, ControllerHandle); + + if (EFI_ERROR(Status)) + Status = ElToritoCreateChildHandle(This, BlockIo, DiskIo, + ParentDevicePath, ControllerHandle); + + if (EFI_ERROR(Status)) + Status = MbrCreateChildHandle(This, BlockIo, DiskIo, + ParentDevicePath, ControllerHandle); + } + + else + Status = EFI_NO_MEDIA; + + + // Now close all protocols That were not already started + if (EFI_ERROR(Status) ) + { + gBS->CloseProtocol(ControllerHandle, &gDevicePathGuid, + This->DriverBindingHandle, ControllerHandle); + + gBS->CloseProtocol(ControllerHandle, &gDiskIoGuid, + This->DriverBindingHandle, ControllerHandle); + } + + return Status; +} + + +//<AMI_PHDR_START> +//-------------------------------------------------------------------------- +// Procedure: DriverBindingStop +// +// Description: Stop this driver on ControllerHandle. Support stoping +// any child handles created by this driver. +// +// Input: +// This - Protocol instance pointer. +// DeviceHandle - Handle of device to stop driver on +// NumberOfChildren - Number of Children in the ChildHandleBuffer +// ChildHandleBuffer - List of handles for the children we need to stop. +// +// Output: None +// +// Return: +// EFI_SUCCESS - This driver is removed DeviceHandle +// other - This driver was not removed from this device +// +// Referrals: CloseProtocol OpenProtocol FlushBlocks MemCmp FreePool +// UninstallMultipleProtocolInterfaces +// +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> +static EFI_STATUS EFIAPI DriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer +) +{ + + EFI_HANDLE Handle = *ChildHandleBuffer; + PARTITION_DATA *Child = NULL; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_GUID *PartType = NULL; + BOOLEAN ChildrenLeft = FALSE; + EFI_STATUS Status; + UINTN Idx = 0; + + + // Close these protocols if there are no children left + if (NumberOfChildren == 0) + { + gBS->CloseProtocol(ControllerHandle, &gDiskIoGuid, + This->DriverBindingHandle, ControllerHandle); + + return EFI_SUCCESS; + } + + // There are children, uninstall protocols and uninstall interfaces, + // and free memory + while (Idx < NumberOfChildren) + { + Status = gBS->OpenProtocol(ChildHandleBuffer[Idx], &gBlockIoGuid, + (VOID **)&BlockIo, This->DriverBindingHandle, + ControllerHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR(Status)) + { + Idx++; + continue; + } + + Child = (PARTITION_DATA *)BlockIo; + + // clear all buffers for the current device + BlockIo->FlushBlocks(BlockIo); + + // now close all handles + gBS->CloseProtocol(ControllerHandle, &gDiskIoGuid, + This->DriverBindingHandle, ChildHandleBuffer[Idx]); + + // look for a non 0 Partition type GUID + // if non zero, set the point to the address, otherwise leave pointer + // as zero + if (MemCmp(&Child->PartGuid, &gUnusedPartitionGuid, sizeof(EFI_GUID))) + PartType = &Child->PartGuid; + + // Create the new handle for the child device + Status = gBS->UninstallMultipleProtocolInterfaces ( + ChildHandleBuffer[Idx], + &gDevicePathGuid, Child->DevPath, + &gBlockIoGuid, &Child->BlockIo, + PartType, NULL, + NULL ); + + if (EFI_ERROR(Status)) + ChildrenLeft = TRUE; + + // free the memory that was allocated for The Child handle and the + // device path for the child handle + + + if (Child->DevPath != NULL) + gBS->FreePool(Child->DevPath); + + if (Child->BlockIo.Media != NULL) + gBS->FreePool(Child->BlockIo.Media); + + gBS->FreePool(Child); + + + // Increment Child Handle Pointer + Idx++; + + // clear PartGuid pointer for the next child + PartType = NULL; + } + + // if there are childrem left, exit with error + if (ChildrenLeft == TRUE) + return EFI_DEVICE_ERROR; + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//-------------------------------------------------------------------------- +// Procedure: Reset +// +// Description: Reset the parent Block Device. +// +// Input: +// This - Protocol instance pointer. +// ExtendedVerification - Driver may perform diagnostics on reset. +// +// Output: None +// +// Return: +// EFI_SUCCESS - The device was reset. +// EFI_DEVICE_ERROR - The device is not functioning properly and could +// not be reset. +// +// Referrals: ParentBlockIo->Reset +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS Reset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification +) +{ + PARTITION_DATA *PartData; + + if (This == NULL) + return EFI_INVALID_PARAMETER; + + // Find the parent's BlockIo Protocol + PartData = (PARTITION_DATA *) This; + + return PartData->ParentBlockIo->Reset(PartData->ParentBlockIo, + ExtendedVerification); +} + + +//<AMI_PHDR_START> +//-------------------------------------------------------------------------- +// Procedure: ReadBlocks +// +// Description: Reads blocks from the parent device +// +// Input: +// This - Protocol instance pointer. +// MediaId - Id of the media, changes every time the media is replaced. +// Lba - The starting Logical Block Address to read from +// BufferSize - Size of Buffer, must be a multiple of device block size. +// +// Output: +// Buffer - Buffer containing read data +// +// Return: +// EFI_SUCCESS - The data was read correctly from the device. +// EFI_DEVICE_ERROR - The device reported an error while performing the read. +// EFI_NO_MEDIA - There is no media in the device. +// EFI_MEDIA_CHANGED - The MediaId does not match the current device. +// EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the +// device. +// EFI_INVALID_PARAMETER - The read request contains device addresses that are not +// valid for the device. +// +// Referrals: Mul64 ReadDisk +// +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS ReadBlocks ( IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + PARTITION_DATA *PartData; + EFI_DISK_IO_PROTOCOL *DiskIo; + UINT64 Start; + + if (This == NULL) + return EFI_INVALID_PARAMETER; + + // Find the parent BlockIo Protocol + PartData = (PARTITION_DATA *) This; + + if(MediaId != PartData->BlockIo.Media->MediaId) + return EFI_MEDIA_CHANGED; + + if(BufferSize == 0) + return EFI_SUCCESS; + + if (BufferSize % PartData->BlockIo.Media->BlockSize != 0) + return EFI_BAD_BUFFER_SIZE; + + // calculate the byte from which to start the read + Start = (Mul64(PartData->StartingLba, + PartData->ParentBlockIo->Media->BlockSize) + + Mul64(Lba, This->Media->BlockSize)); + + // check to see if the read will go beyond the end of the + // current partition + if ( ((Start + BufferSize - 1) >= + Mul64(PartData->EndingLba+1, + PartData->ParentBlockIo->Media->BlockSize)) || + (Buffer == NULL)) + return EFI_INVALID_PARAMETER; + + + // Make call directly to DiskIo of the device + + DiskIo = PartData->ParentDiskIo; + + return DiskIo->ReadDisk(DiskIo, MediaId, Start, BufferSize, Buffer); +} + + +//<AMI_PHDR_START> +//-------------------------------------------------------------------------- +// Procedure: WriteBlocks +// +// Description: Write blocks to the parent device +// +// Input: +// This - Protocol instance pointer. +// MediaId - Id of the media, changes every time the media is replaced. +// Lba - The starting Logical Block Address to read from +// BufferSize - Size of Buffer, must be a multiple of device block size. +// Buffer - Buffer containing read data +// +// Output: None +// +// Return: +// EFI_SUCCESS - The data was written correctly to the device. +// EFI_WRITE_PROTECTED - The device can not be written to. +// EFI_DEVICE_ERROR - The device reported an error while performing the write. +// EFI_NO_MEDIA - There is no media in the device. +// EFI_MEDIA_CHANGED - The MediaId does not match the current device. +// EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the +// device. +// EFI_INVALID_PARAMETER - The write request contains a LBA that is not +// valid for the device. +// +// Referrals: Mul64 WriteDisk +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS WriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer +) +{ + PARTITION_DATA *PartData; + EFI_DISK_IO_PROTOCOL *DiskIo; + UINT64 Start; + + if (This == NULL) + return EFI_INVALID_PARAMETER; + + // Find the parent BlockIo Protocol + PartData = (PARTITION_DATA *) This; + + if(MediaId != PartData->BlockIo.Media->MediaId) + return EFI_MEDIA_CHANGED; + + if (BufferSize % PartData->BlockIo.Media->BlockSize != 0) + return EFI_BAD_BUFFER_SIZE; + + // calculated the start address of the write command + Start = Mul64(PartData->StartingLba, + PartData->ParentBlockIo->Media->BlockSize) + + Mul64(Lba, This->Media->BlockSize); + + if ( ((Start + BufferSize - 1) >= + Mul64(PartData->EndingLba+1, + PartData->ParentBlockIo->Media->BlockSize)) || + (Buffer == NULL)) + return EFI_INVALID_PARAMETER; + + DiskIo = PartData->ParentDiskIo; + + return DiskIo->WriteDisk(DiskIo, MediaId, Start, BufferSize, Buffer); +} + + +//<AMI_PHDR_START> +//-------------------------------------------------------------------------- +// Procedure: FlushBlocks +// +// Description: Flush the parent Block Device. +// +// Input: This - Protocol instance pointer. +// +// Output: None +// +// Return: +// EFI_SUCCESS - All outstanding data was written to the device +// EFI_DEVICE_ERROR - The device reported an error while writing back +// the data +// EFI_NO_MEDIA - There is no media in the device. +// +// Referrals: ParentBlockIo->FlushBlocks +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS FlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This +) +{ + PARTITION_DATA *PartData; + + if (This == NULL) + return EFI_INVALID_PARAMETER; + + PartData = (PARTITION_DATA *) This; + + // return the same value that the device specific BlockIo instance returns + return PartData->ParentBlockIo->FlushBlocks(PartData->ParentBlockIo); +} + + +//<AMI_PHDR_START> +//-------------------------------------------------------------------------- +// Procedure: CreateChildHandle +// +// Description: Generic create child handle for the partition driver. This +// should work for GPT, MBR, and El Torito. +// +// Input: +// *This - Pointer to the current instance of the blockIo protocol +// *PData - a pointer to the start of the private data structure for +// the partition +// BlockSize - the blocksize for the partition +// +// Output: +// +// Return: +// EFI_SUCCESS - Child created +// other - no child created +// +// Referrals: AllocatePool FreePool CopyMem MemCmp Div64 OpenProtocol +// InstallMultipleProtocolInterfaces UninstallMultipleProtocolInterfaces +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS CreateChildHandle( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN PARTITION_DATA *PData, + IN UINT32 BlockSize +) +{ + PARTITION_DATA *Child; + EFI_BLOCK_IO_MEDIA *Media; + EFI_STATUS Status; + EFI_GUID *PartType = NULL; + UINTN Temp; + + + // allocate memory for the Child handle + Status = gBS->AllocatePool(EfiBootServicesData, sizeof(PARTITION_DATA), &Child); + if (EFI_ERROR(Status)) + return EFI_OUT_OF_RESOURCES; + + Status = gBS->AllocatePool(EfiBootServicesData, sizeof(EFI_BLOCK_IO_MEDIA), &Media); + if (EFI_ERROR(Status)) { + gBS->FreePool(Child); + return EFI_OUT_OF_RESOURCES; + } + + // Copy the data from one location to the other, + gBS->CopyMem(Child, PData, sizeof(PARTITION_DATA)); + + // get the BlockIo protocol for the partition driver and the + // media information from the parent device + gBS->CopyMem(&Child->BlockIo, &mPartitionBlockIo, sizeof(EFI_BLOCK_IO_PROTOCOL)); + + // just point to the media info for the device, that way we don't have to + // worry about changing values + Child->BlockIo.Media = Media; + + gBS->CopyMem(Media, PData->ParentBlockIo->Media, sizeof(EFI_BLOCK_IO_MEDIA)); + + Media->LogicalPartition = TRUE; + Media->BlockSize = BlockSize; + Media->IoAlign = 1; //no alignment requirements + Media->LowestAlignedLba = 0; //added in Revision 2 + Media->LogicalBlocksPerPhysicalBlock = 0; //added in Revision 2 + Media->OptimalTransferLengthGranularity = 0; //added in Revision 3 + + // Calculate the last block of the partition + Media->LastBlock = Div64( Mul64(PData->EndingLba - PData->StartingLba + 1, + Child->ParentBlockIo->Media->BlockSize), + BlockSize, &Temp) - 1; + + // look for a non 0 Partition type GUID + // if non zero, set the point to the address, otherwise leave + // pointer as zero + if (MemCmp(&Child->PartGuid, &gUnusedPartitionGuid, sizeof(EFI_GUID))) + PartType = &Child->PartGuid; + + // Create the new handle for the child device + Child->Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &Child->Handle, + &gDevicePathGuid, Child->DevPath, + &gBlockIoGuid, &Child->BlockIo, + PartType, NULL, + NULL ); + + // Now open the diskIo protocol for the child, if the install multiple + // protocol interface returns SUCCESS + if (!EFI_ERROR(Status)) { + Status = gBS->OpenProtocol ( Child->ParentHandle, + &gDiskIoGuid, + &Child->ParentDiskIo, + This->DriverBindingHandle, + Child->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); + + if (EFI_ERROR(Status)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + &Child->Handle, + &gDevicePathGuid, Child->DevPath, + &gBlockIoGuid, &Child->BlockIo, + PartType, NULL, + NULL ); + //free all resources + gBS->FreePool(Child->DevPath); + gBS->FreePool(Media); + gBS->FreePool(Child); + } + } + + return Status; +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/CORE_DXE/Partition/Partition.cif b/Core/CORE_DXE/Partition/Partition.cif new file mode 100644 index 0000000..feaa5cb --- /dev/null +++ b/Core/CORE_DXE/Partition/Partition.cif @@ -0,0 +1,16 @@ +<component> + name = "Partition" + category = ModulePart + LocalRoot = "Core\CORE_DXE\Partition\" + RefName = "Partition" +[files] +"Partition.sdl" +"ElTorito.c" +"ElTorito.h" +"Gpt.c" +"Gpt.h" +"Mbr.c" +"Mbr.h" +"Partition.c" +"Partition.h" +<endComponent> diff --git a/Core/CORE_DXE/Partition/Partition.h b/Core/CORE_DXE/Partition/Partition.h new file mode 100644 index 0000000..047cfc8 --- /dev/null +++ b/Core/CORE_DXE/Partition/Partition.h @@ -0,0 +1,188 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/CORE_DXE/Partition/Partition.h 10 8/12/11 12:16p Artems $ +// +// $Revision: 10 $ +// +// $Date: 8/12/11 12:16p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/CORE_DXE/Partition/Partition.h $ +// +// 10 8/12/11 12:16p Artems +// EIP 64107: Added changes for module to be compliant with UEFI +// specification v 2.3.1 +// +// 9 7/09/09 5:01p Oleksiyy +// Files clean-up +// +// 8 1/08/08 2:47p Robert +// +// 7 1/08/08 2:47p Robert +// +// 6 1/07/08 4:21p Robert +// Updated for coding standard +// +// 5 4/25/07 12:44p Robert +// updates for CHM and Coding Standard Compliance +// +// 3 4/24/05 12:45a Felixp +// Definitions of SIGNATURE_TYPE_xxx macroses removed since they are +// already defined in DevicePath.h +// +// 6 12/14/04 6:14p Robert +// Added component name protocol support +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: Partition.h +// +// Description: EFI Partition Generic Driver Header. This file +// contains the GUIDs used by this driver. It also contains +// Definitions and Data Structures needed by the generic portion of +// the Partition driver. +// +// +//<AMI_FHDR_END> +//********************************************************************** + +#ifndef _PARTITION_H +#define _PARTITION_H + + +#include <AmiDxeLib.h> + +// protocols consumed +#include <protocol\BlockIo.h> +#include <protocol\DiskIo.h> +#include <protocol\DevicePath.h> +#include <protocol\DriverBinding.h> +#include <Protocol\ComponentName2.h> + +extern EFI_BOOT_SERVICES *gBS; +extern EFI_GUID gUnusedPartitionGuid; + +//============================================================================= +// GUID Definitions + +#define EFI_PART_TYPE_UNUSED_GUID \ + { 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + +#define EFI_PART_TYPE_EFI_SYSTEM_PART_GUID \ + { 0xc12a7328, 0xf81f, 0x11d2, 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b} + +#define EFI_PART_TYPE_LEGACY_MBR_GUID \ + { 0x024dee41, 0x33e7, 0x11d3, 0x9d, 0x69, 0x00, 0x08, 0xc7, 0x81, 0xf3, 0x9f} + + + +#define MBR_TYPE_PCAT 0x01 +#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02 + +#define EFI_SYSTEM_PARTITION 0xef + + +//============================================================================= +// Structure definitions + +//<AMI_STHDR_START> +//============================================================================ +// Structure: OPCODE_CMD +// +// Description: Data Structure definition of the Private data for each instance +// of the Partition Block I/O driver +// +// Fields: +// BlockIo - EFI_BLOCK_IO_PROTOCOL - Pointer to the EFI_BLOCK_IO_PROTOCOL +// protocol for this partition +// Handle - EFI_HANDLE - child handle for this partition +// ParentBlockIo - EFI_BLOCK_IO_PROTOCOL * - pointer to the +// EFI_BLOCK_IO_PROTOCOL of the parent device +// ParentDiskIo - EFI_DISK_IO_PROTOCOL * - pointer to the +// EFI_DISK_IO_PROTOCOL of the parent device +// DevPath - EFI_DEVICE_PATH_PROTOCOL * - pointer to the device path +// for this device +// StartingLba - EFI_LBA - The starting Lba of the current partition +// EndingLba - EFI_LBA - The ending Lba of the current partition +// PartGuid - EFI_GUID - The GUID assigned to the partition +// ParentHandle - EFI_HANDLE - the handle assigned to the parent device +// +// Referral: +// None +//============================================================================ +//<AMI_STHDR_END> +typedef struct _PARTITION_DATA +{ + EFI_BLOCK_IO_PROTOCOL BlockIo; + EFI_HANDLE Handle; + EFI_BLOCK_IO_PROTOCOL *ParentBlockIo; + EFI_DISK_IO_PROTOCOL *ParentDiskIo; + EFI_DEVICE_PATH_PROTOCOL *DevPath; + + EFI_LBA StartingLba; + EFI_LBA EndingLba; + EFI_GUID PartGuid; + + EFI_HANDLE ParentHandle; +} PARTITION_DATA; + + +//============================================================================= +// Function Prototypes +EFI_STATUS CreateChildHandle(EFI_DRIVER_BINDING_PROTOCOL *This, PARTITION_DATA *PData, + UINT32 BlockSize); + +EFI_STATUS GptDiscoverPartitions ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_HANDLE ControllerHandle +); + +EFI_STATUS ElToritoCreateChildHandle ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_HANDLE ControllerHandle +); + +EFI_STATUS MbrCreateChildHandle( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_HANDLE ControllerHandle +); + +#endif + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/CORE_DXE/Partition/Partition.sdl b/Core/CORE_DXE/Partition/Partition.sdl new file mode 100644 index 0000000..a846251 --- /dev/null +++ b/Core/CORE_DXE/Partition/Partition.sdl @@ -0,0 +1,4 @@ +PATH + Name = "PARTITION_DIR" +End + |