summaryrefslogtreecommitdiff
path: root/EdkModulePkg/Universal/Disk/Partition/Dxe
diff options
context:
space:
mode:
authorbbahnsen <bbahnsen@6f19259b-4bc3-4df7-8a09-765794883524>2006-04-21 22:54:32 +0000
committerbbahnsen <bbahnsen@6f19259b-4bc3-4df7-8a09-765794883524>2006-04-21 22:54:32 +0000
commit878ddf1fc3540a715f63594ed22b6929e881afb4 (patch)
treec56c44dac138137b510e1fba7c3efe5e4d84bea2 /EdkModulePkg/Universal/Disk/Partition/Dxe
downloadedk2-platforms-878ddf1fc3540a715f63594ed22b6929e881afb4.tar.xz
Initial import.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'EdkModulePkg/Universal/Disk/Partition/Dxe')
-rw-r--r--EdkModulePkg/Universal/Disk/Partition/Dxe/ComponentName.c160
-rw-r--r--EdkModulePkg/Universal/Disk/Partition/Dxe/ElTorito.c277
-rw-r--r--EdkModulePkg/Universal/Disk/Partition/Dxe/ElTorito.h130
-rw-r--r--EdkModulePkg/Universal/Disk/Partition/Dxe/Gpt.c768
-rw-r--r--EdkModulePkg/Universal/Disk/Partition/Dxe/Gpt.h76
-rw-r--r--EdkModulePkg/Universal/Disk/Partition/Dxe/Mbr.c317
-rw-r--r--EdkModulePkg/Universal/Disk/Partition/Dxe/Mbr.h68
-rw-r--r--EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.c735
-rw-r--r--EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.h123
-rw-r--r--EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.mbd42
-rw-r--r--EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.msa81
-rw-r--r--EdkModulePkg/Universal/Disk/Partition/Dxe/build.xml47
12 files changed, 2824 insertions, 0 deletions
diff --git a/EdkModulePkg/Universal/Disk/Partition/Dxe/ComponentName.c b/EdkModulePkg/Universal/Disk/Partition/Dxe/ComponentName.c
new file mode 100644
index 0000000000..3821690f0c
--- /dev/null
+++ b/EdkModulePkg/Universal/Disk/Partition/Dxe/ComponentName.c
@@ -0,0 +1,160 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ ComponentName.c
+
+Abstract:
+
+--*/
+
+#include "Partition.h"
+
+//
+// EFI Component Name Functions
+//
+EFI_STATUS
+EFIAPI
+PartitionComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+EFI_STATUS
+EFIAPI
+PartitionComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+//
+// EFI Component Name Protocol
+//
+EFI_COMPONENT_NAME_PROTOCOL gPartitionComponentName = {
+ PartitionComponentNameGetDriverName,
+ PartitionComponentNameGetControllerName,
+ "eng"
+};
+
+static EFI_UNICODE_STRING_TABLE mPartitionDriverNameTable[] = {
+ {
+ "eng",
+ (CHAR16 *)L"Partition Driver(MBR/GPT/El Torito)"
+ },
+ {
+ NULL,
+ NULL
+ }
+};
+
+EFI_STATUS
+EFIAPI
+PartitionComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+/*++
+
+ Routine Description:
+ Retrieves a Unicode string that is the user readable name of the EFI Driver.
+
+ Arguments:
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ Language - A pointer to a three character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ DriverName - A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ Returns:
+ EFI_SUCCESS - The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ EFI_INVALID_PARAMETER - Language is NULL.
+ EFI_INVALID_PARAMETER - DriverName is NULL.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ language specified by Language.
+
+--*/
+{
+ return LookupUnicodeString (
+ Language,
+ gPartitionComponentName.SupportedLanguages,
+ mPartitionDriverNameTable,
+ DriverName
+ );
+}
+
+EFI_STATUS
+EFIAPI
+PartitionComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+/*++
+
+ Routine Description:
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ Arguments:
+ 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 SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ 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 the driver 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.
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/EdkModulePkg/Universal/Disk/Partition/Dxe/ElTorito.c b/EdkModulePkg/Universal/Disk/Partition/Dxe/ElTorito.c
new file mode 100644
index 0000000000..27beba171b
--- /dev/null
+++ b/EdkModulePkg/Universal/Disk/Partition/Dxe/ElTorito.c
@@ -0,0 +1,277 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ ElTorito.c
+
+Abstract:
+
+ Decode an El Torito formatted CD-ROM
+
+Revision History
+
+--*/
+
+#include "Partition.h"
+#include "ElTorito.h"
+
+BOOLEAN
+PartitionInstallElToritoChildHandles (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Handle,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+/*++
+
+Routine Description:
+ Install child handles if the Handle supports El Torito format.
+
+Arguments:
+ This - Calling context.
+ Handle - Parent Handle
+ DiskIo - Parent DiskIo interface
+ BlockIo - Parent BlockIo interface
+ DevicePath - Parent Device Path
+
+Returns:
+ TRUE - some child handle(s) was added
+ FALSE - no child handle was added
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 VolDescriptorLba;
+ UINT32 Lba;
+ EFI_BLOCK_IO_MEDIA *Media;
+ CDROM_VOLUME_DESCRIPTOR *VolDescriptor;
+ ELTORITO_CATALOG *Catalog;
+ UINTN Check;
+ UINTN Index;
+ UINTN BootEntry;
+ UINTN MaxIndex;
+ UINT16 *CheckBuffer;
+ CDROM_DEVICE_PATH CdDev;
+ UINT32 SubBlockSize;
+ UINT32 SectorCount;
+ BOOLEAN Found;
+ UINT32 VolSpaceSize;
+
+ Found = FALSE;
+ Media = BlockIo->Media;
+ VolSpaceSize = 0;
+
+ //
+ // CD_ROM has the fixed block size as 2048 bytes
+ //
+ if (Media->BlockSize != 2048) {
+ return FALSE;
+ }
+
+ VolDescriptor = AllocatePool ((UINTN) Media->BlockSize);
+
+ if (VolDescriptor == NULL) {
+ return FALSE;
+ }
+
+ Catalog = (ELTORITO_CATALOG *) VolDescriptor;
+
+ //
+ // the ISO-9660 volume descriptor starts at 32k on the media
+ // and CD_ROM has the fixed block size as 2048 bytes, so...
+ //
+ //
+ // ((16*2048) / Media->BlockSize) - 1;
+ //
+ VolDescriptorLba = 15;
+ //
+ // Loop: handle one volume descriptor per time
+ //
+ while (TRUE) {
+
+ VolDescriptorLba += 1;
+ if (VolDescriptorLba > Media->LastBlock) {
+ //
+ // We are pointing past the end of the device so exit
+ //
+ break;
+ }
+
+ Status = BlockIo->ReadBlocks (
+ BlockIo,
+ Media->MediaId,
+ VolDescriptorLba,
+ Media->BlockSize,
+ VolDescriptor
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ //
+ // Check for valid volume descriptor signature
+ //
+ if (VolDescriptor->Type == CDVOL_TYPE_END ||
+ CompareMem (VolDescriptor->Id, CDVOL_ID, sizeof (VolDescriptor->Id)) != 0
+ ) {
+ //
+ // end of Volume descriptor list
+ //
+ break;
+ }
+ //
+ // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte,
+ // the 32-bit numerical values is stored in Both-byte orders
+ //
+ if (VolDescriptor->Type == CDVOL_TYPE_CODED) {
+ VolSpaceSize = VolDescriptor->VolSpaceSize[1];
+ }
+ //
+ // Is it an El Torito volume descriptor?
+ //
+ if (CompareMem (VolDescriptor->SystemId, CDVOL_ELTORITO_ID, sizeof (CDVOL_ELTORITO_ID) - 1) != 0) {
+ continue;
+ }
+ //
+ // Read in the boot El Torito boot catalog
+ //
+ Lba = UNPACK_INT32 (VolDescriptor->EltCatalog);
+ if (Lba > Media->LastBlock) {
+ continue;
+ }
+
+ Status = BlockIo->ReadBlocks (
+ BlockIo,
+ Media->MediaId,
+ Lba,
+ Media->BlockSize,
+ Catalog
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "EltCheckDevice: error reading catalog %r\n", Status));
+ continue;
+ }
+ //
+ // We don't care too much about the Catalog header's contents, but we do want
+ // to make sure it looks like a Catalog header
+ //
+ if (Catalog->Catalog.Indicator != ELTORITO_ID_CATALOG || Catalog->Catalog.Id55AA != 0xAA55) {
+ DEBUG ((EFI_D_ERROR, "EltCheckBootCatalog: El Torito boot catalog header IDs not correct\n"));
+ continue;
+ }
+
+ Check = 0;
+ CheckBuffer = (UINT16 *) Catalog;
+ for (Index = 0; Index < sizeof (ELTORITO_CATALOG) / sizeof (UINT16); Index += 1) {
+ Check += CheckBuffer[Index];
+ }
+
+ if (Check & 0xFFFF) {
+ DEBUG ((EFI_D_ERROR, "EltCheckBootCatalog: El Torito boot catalog header checksum failed\n"));
+ continue;
+ }
+
+ MaxIndex = Media->BlockSize / sizeof (ELTORITO_CATALOG);
+ for (Index = 1, BootEntry = 1; Index < MaxIndex; Index += 1) {
+ //
+ // Next entry
+ //
+ Catalog += 1;
+
+ //
+ // Check this entry
+ //
+ if (Catalog->Boot.Indicator != ELTORITO_ID_SECTION_BOOTABLE || Catalog->Boot.Lba == 0) {
+ continue;
+ }
+
+ SubBlockSize = 512;
+ SectorCount = Catalog->Boot.SectorCount;
+
+ switch (Catalog->Boot.MediaType) {
+
+ case ELTORITO_NO_EMULATION:
+ SubBlockSize = Media->BlockSize;
+ break;
+
+ case ELTORITO_HARD_DISK:
+ break;
+
+ case ELTORITO_12_DISKETTE:
+ SectorCount = 0x50 * 0x02 * 0x0F;
+ break;
+
+ case ELTORITO_14_DISKETTE:
+ SectorCount = 0x50 * 0x02 * 0x12;
+ break;
+
+ case ELTORITO_28_DISKETTE:
+ SectorCount = 0x50 * 0x02 * 0x24;
+ break;
+
+ default:
+ DEBUG ((EFI_D_INIT, "EltCheckDevice: unsupported El Torito boot media type %x\n", Catalog->Boot.MediaType));
+ SectorCount = 0;
+ SubBlockSize = Media->BlockSize;
+ break;
+ }
+ //
+ // Create child device handle
+ //
+ CdDev.Header.Type = MEDIA_DEVICE_PATH;
+ CdDev.Header.SubType = MEDIA_CDROM_DP;
+ SetDevicePathNodeLength (&CdDev.Header, sizeof (CdDev));
+
+ if (Index == 1) {
+ //
+ // This is the initial/default entry
+ //
+ BootEntry = 0;
+ }
+
+ CdDev.BootEntry = (UINT32) BootEntry;
+ BootEntry++;
+ CdDev.PartitionStart = Catalog->Boot.Lba;
+ if (SectorCount < 2) {
+ CdDev.PartitionSize = VolSpaceSize;
+ } else {
+ CdDev.PartitionSize = DivU64x32 (
+ MultU64x32 (
+ SectorCount,
+ SubBlockSize
+ ) + Media->BlockSize - 1,
+ Media->BlockSize
+ );
+ }
+
+ Status = PartitionInstallChildHandle (
+ This,
+ Handle,
+ DiskIo,
+ BlockIo,
+ DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &CdDev,
+ Catalog->Boot.Lba,
+ Catalog->Boot.Lba + CdDev.PartitionSize - 1,
+ SubBlockSize,
+ FALSE
+ );
+ if (!EFI_ERROR (Status)) {
+ Found = TRUE;
+ }
+ }
+ }
+
+ gBS->FreePool (VolDescriptor);
+
+ return Found;
+}
diff --git a/EdkModulePkg/Universal/Disk/Partition/Dxe/ElTorito.h b/EdkModulePkg/Universal/Disk/Partition/Dxe/ElTorito.h
new file mode 100644
index 0000000000..f085315b4d
--- /dev/null
+++ b/EdkModulePkg/Universal/Disk/Partition/Dxe/ElTorito.h
@@ -0,0 +1,130 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ ElTorito.h
+
+Abstract:
+
+ Data Structures required for detecting ElTorito Partitions
+
+Revision History
+
+--*/
+
+#ifndef _ELTORITO_H_
+#define _ELTORITO_H_
+
+#pragma pack(1)
+//
+// CDROM_VOLUME_DESCRIPTOR.Types
+//
+#define CDVOL_TYPE_STANDARD 0x0
+#define CDVOL_TYPE_CODED 0x1
+#define CDVOL_TYPE_END 0xFF
+
+//
+// CDROM_VOLUME_DESCRIPTOR.Id
+//
+#define CDVOL_ID "CD001"
+
+//
+// CDROM_VOLUME_DESCRIPTOR.SystemId
+//
+#define CDVOL_ELTORITO_ID "EL TORITO SPECIFICATION"
+
+//
+// Indicator types
+//
+#define ELTORITO_ID_CATALOG 0x01
+#define ELTORITO_ID_SECTION_BOOTABLE 0x88
+#define ELTORITO_ID_SECTION_NOT_BOOTABLE 0x00
+#define ELTORITO_ID_SECTION_HEADER 0x90
+#define ELTORITO_ID_SECTION_HEADER_FINAL 0x91
+
+//
+// ELTORITO_CATALOG.Boot.MediaTypes
+//
+#define ELTORITO_NO_EMULATION 0x00
+#define ELTORITO_12_DISKETTE 0x01
+#define ELTORITO_14_DISKETTE 0x02
+#define ELTORITO_28_DISKETTE 0x03
+#define ELTORITO_HARD_DISK 0x04
+
+//
+// El Torito Volume Descriptor
+// Note that the CDROM_VOLUME_DESCRIPTOR does not match the ISO-9660
+// descriptor. For some reason descriptor used by El Torito is
+// different, but they start the same. The El Torito descriptor
+// is left shifted 1 byte starting with the SystemId. (Note this
+// causes the field to get unaligned)
+//
+typedef struct {
+ UINT8 Type;
+ CHAR8 Id[5]; // CD001
+ UINT8 Version;
+ CHAR8 SystemId[26];
+ CHAR8 Unused[38];
+ UINT8 EltCatalog[4];
+ CHAR8 Unused2[5];
+ UINT32 VolSpaceSize[2];
+} CDROM_VOLUME_DESCRIPTOR;
+
+//
+// Catalog Entry
+//
+typedef union {
+ struct {
+ CHAR8 Reserved[0x20];
+ } Unknown;
+
+ //
+ // Catalog validation entry (Catalog header)
+ //
+ struct {
+ UINT8 Indicator;
+ UINT8 PlatformId;
+ UINT16 Reserved;
+ CHAR8 ManufacId[24];
+ UINT16 Checksum;
+ UINT16 Id55AA;
+ } Catalog;
+
+ //
+ // Initial/Default Entry or Section Entry
+ //
+ struct {
+ UINT8 Indicator;
+ UINT8 MediaType : 4;
+ UINT8 Reserved1 : 4;
+ UINT16 LoadSegment;
+ UINT8 SystemType;
+ UINT8 Reserved2;
+ UINT16 SectorCount;
+ UINT32 Lba;
+ } Boot;
+
+ //
+ // Section Header Entry
+ //
+ struct {
+ UINT8 Indicator;
+ UINT8 PlatformId;
+ UINT16 SectionEntries;
+ CHAR8 Id[28];
+ } Section;
+
+} ELTORITO_CATALOG;
+
+#pragma pack()
+
+#endif
diff --git a/EdkModulePkg/Universal/Disk/Partition/Dxe/Gpt.c b/EdkModulePkg/Universal/Disk/Partition/Dxe/Gpt.c
new file mode 100644
index 0000000000..35ff1a8606
--- /dev/null
+++ b/EdkModulePkg/Universal/Disk/Partition/Dxe/Gpt.c
@@ -0,0 +1,768 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Gpt.c
+
+Abstract:
+
+ Decode a hard disk partitioned with the GPT scheme in the EFI 1.0
+ specification.
+
+--*/
+
+#include "Partition.h"
+#include "Gpt.h"
+#include "Mbr.h"
+
+BOOLEAN
+PartitionValidGptTable (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_LBA Lba,
+ OUT EFI_PARTITION_TABLE_HEADER *PartHeader
+ );
+
+BOOLEAN
+PartitionCheckGptEntryArrayCRC (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_PARTITION_TABLE_HEADER *PartHeader
+ );
+
+BOOLEAN
+PartitionRestoreGptTable (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_PARTITION_TABLE_HEADER *PartHeader
+ );
+
+VOID
+PartitionCheckGptEntry (
+ IN EFI_PARTITION_TABLE_HEADER *PartHeader,
+ IN EFI_PARTITION_ENTRY *PartEntry,
+ OUT EFI_PARTITION_ENTRY_STATUS *PEntryStatus
+ );
+
+BOOLEAN
+PartitionCheckCrcAltSize (
+ IN UINTN MaxSize,
+ IN UINTN Size,
+ IN OUT EFI_TABLE_HEADER *Hdr
+ );
+
+BOOLEAN
+PartitionCheckCrc (
+ IN UINTN MaxSize,
+ IN OUT EFI_TABLE_HEADER *Hdr
+ );
+
+VOID
+PartitionSetCrcAltSize (
+ IN UINTN Size,
+ IN OUT EFI_TABLE_HEADER *Hdr
+ );
+
+VOID
+PartitionSetCrc (
+ IN OUT EFI_TABLE_HEADER *Hdr
+ );
+
+BOOLEAN
+PartitionInstallGptChildHandles (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Handle,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+/*++
+
+Routine Description:
+ Install child handles if the Handle supports GPT partition structure.
+
+Arguments:
+ This - Calling context.
+ Handle - Parent Handle
+ DiskIo - Parent DiskIo interface
+ BlockIo - Parent BlockIo interface
+ DevicePath - Parent Device Path
+
+Returns:
+ TRUE - Valid GPT disk
+ FALSE - Not a valid GPT disk
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 BlockSize;
+ EFI_LBA LastBlock;
+ MASTER_BOOT_RECORD *ProtectiveMbr;
+ EFI_PARTITION_TABLE_HEADER *PrimaryHeader;
+ EFI_PARTITION_TABLE_HEADER *BackupHeader;
+ EFI_PARTITION_ENTRY *PartEntry;
+ EFI_PARTITION_ENTRY_STATUS *PEntryStatus;
+ UINTN Index;
+ BOOLEAN GptValid;
+ HARDDRIVE_DEVICE_PATH HdDev;
+
+ ProtectiveMbr = NULL;
+ PrimaryHeader = NULL;
+ BackupHeader = NULL;
+ PartEntry = NULL;
+ PEntryStatus = NULL;
+
+ BlockSize = BlockIo->Media->BlockSize;
+ LastBlock = BlockIo->Media->LastBlock;
+
+ DEBUG ((EFI_D_INFO, " BlockSize : %d \n", BlockSize));
+ DEBUG ((EFI_D_INFO, " LastBlock : %x \n", LastBlock));
+
+ GptValid = FALSE;
+
+ //
+ // Allocate a buffer for the Protective MBR
+ //
+ ProtectiveMbr = AllocatePool (BlockSize);
+ if (ProtectiveMbr == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Read the Protective MBR from LBA #0
+ //
+ Status = BlockIo->ReadBlocks (
+ BlockIo,
+ BlockIo->Media->MediaId,
+ 0,
+ BlockIo->Media->BlockSize,
+ ProtectiveMbr
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ //
+ // Verify that the Protective MBR is valid
+ //
+ if (ProtectiveMbr->Partition[0].BootIndicator != 0x00 ||
+ ProtectiveMbr->Partition[0].OSIndicator != 0xEE ||
+ UNPACK_UINT32 (ProtectiveMbr->Partition[0].StartingLBA) != 1
+ ) {
+ goto Done;
+ }
+
+ //
+ // Allocate the GPT structures
+ //
+ PrimaryHeader = AllocateZeroPool (sizeof (EFI_PARTITION_TABLE_HEADER));
+ if (PrimaryHeader == NULL) {
+ goto Done;
+ }
+
+ BackupHeader = AllocateZeroPool (sizeof (EFI_PARTITION_TABLE_HEADER));
+
+ if (BackupHeader == NULL) {
+ goto Done;
+ }
+
+ //
+ // Check primary and backup partition tables
+ //
+ if (!PartitionValidGptTable (BlockIo, DiskIo, PRIMARY_PART_HEADER_LBA, PrimaryHeader)) {
+ DEBUG ((EFI_D_INFO, " Not Valid primary partition table\n"));
+
+ if (!PartitionValidGptTable (BlockIo, DiskIo, LastBlock, BackupHeader)) {
+ DEBUG ((EFI_D_INFO, " Not Valid backup partition table\n"));
+ goto Done;
+ } else {
+ DEBUG ((EFI_D_INFO, " Valid backup partition table\n"));
+ DEBUG ((EFI_D_INFO, " Restore primary partition table by the backup\n"));
+ if (!PartitionRestoreGptTable (BlockIo, DiskIo, BackupHeader)) {
+ DEBUG ((EFI_D_INFO, " Restore primary partition table error\n"));
+ }
+
+ if (PartitionValidGptTable (BlockIo, DiskIo, BackupHeader->AlternateLBA, PrimaryHeader)) {
+ DEBUG ((EFI_D_INFO, " Restore backup partition table success\n"));
+ }
+ }
+ } else if (!PartitionValidGptTable (BlockIo, DiskIo, PrimaryHeader->AlternateLBA, BackupHeader)) {
+ DEBUG ((EFI_D_INFO, " Valid primary and !Valid backup partition table\n"));
+ DEBUG ((EFI_D_INFO, " Restore backup partition table by the primary\n"));
+ if (!PartitionRestoreGptTable (BlockIo, DiskIo, PrimaryHeader)) {
+ DEBUG ((EFI_D_INFO, " Restore backup partition table error\n"));
+ }
+
+ if (PartitionValidGptTable (BlockIo, DiskIo, PrimaryHeader->AlternateLBA, BackupHeader)) {
+ DEBUG ((EFI_D_INFO, " Restore backup partition table success\n"));
+ }
+
+ }
+
+ DEBUG ((EFI_D_INFO, " Valid primary and Valid backup partition table\n"));
+
+ //
+ // Read the EFI Partition Entries
+ //
+ PartEntry = AllocatePool (PrimaryHeader->NumberOfPartitionEntries * sizeof (EFI_PARTITION_ENTRY));
+ if (PartEntry == NULL) {
+ DEBUG ((EFI_D_ERROR, "Allocate pool error\n"));
+ goto Done;
+ }
+
+ Status = DiskIo->ReadDisk (
+ DiskIo,
+ BlockIo->Media->MediaId,
+ MultU64x32(PrimaryHeader->PartitionEntryLBA, BlockSize),
+ PrimaryHeader->NumberOfPartitionEntries * (PrimaryHeader->SizeOfPartitionEntry),
+ PartEntry
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, " Partition Entry ReadBlocks error\n"));
+ goto Done;
+ }
+
+ DEBUG ((EFI_D_INFO, " Partition entries read block success\n"));
+
+ DEBUG ((EFI_D_INFO, " Number of partition entries: %d\n", PrimaryHeader->NumberOfPartitionEntries));
+
+ PEntryStatus = AllocateZeroPool (PrimaryHeader->NumberOfPartitionEntries * sizeof (EFI_PARTITION_ENTRY_STATUS));
+ if (PEntryStatus == NULL) {
+ DEBUG ((EFI_D_ERROR, "Allocate pool error\n"));
+ goto Done;
+ }
+
+ //
+ // Check the integrity of partition entries
+ //
+ PartitionCheckGptEntry (PrimaryHeader, PartEntry, PEntryStatus);
+
+ //
+ // If we got this far the GPT layout of the disk is valid and we should return true
+ //
+ GptValid = TRUE;
+
+ //
+ // Create child device handles
+ //
+ for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) {
+ if (CompareGuid (&PartEntry[Index].PartitionTypeGUID, &gEfiPartTypeUnusedGuid) ||
+ PEntryStatus[Index].OutOfRange ||
+ PEntryStatus[Index].Overlap
+ ) {
+ //
+ // Don't use null EFI Partition Entries or Invalid Partition Entries
+ //
+ continue;
+ }
+
+ ZeroMem (&HdDev, sizeof (HdDev));
+ HdDev.Header.Type = MEDIA_DEVICE_PATH;
+ HdDev.Header.SubType = MEDIA_HARDDRIVE_DP;
+ SetDevicePathNodeLength (&HdDev.Header, sizeof (HdDev));
+
+ HdDev.PartitionNumber = (UINT32) Index + 1;
+ HdDev.MBRType = MBR_TYPE_EFI_PARTITION_TABLE_HEADER;
+ HdDev.SignatureType = SIGNATURE_TYPE_GUID;
+ HdDev.PartitionStart = PartEntry[Index].StartingLBA;
+ HdDev.PartitionSize = PartEntry[Index].EndingLBA - PartEntry[Index].StartingLBA + 1;
+ CopyMem (HdDev.Signature, &PartEntry[Index].UniquePartitionGUID, sizeof (EFI_GUID));
+
+ DEBUG ((EFI_D_INFO, " Index : %d\n", Index));
+ DEBUG ((EFI_D_INFO, " Start LBA : %x\n", HdDev.PartitionStart));
+ DEBUG ((EFI_D_INFO, " End LBA : %x\n", PartEntry[Index].EndingLBA));
+ DEBUG ((EFI_D_INFO, " Partition size: %x\n", HdDev.PartitionSize));
+ DEBUG ((EFI_D_INFO, " Start : %x", MultU64x32 (PartEntry[Index].StartingLBA, BlockSize)));
+ DEBUG ((EFI_D_INFO, " End : %x\n", MultU64x32 (PartEntry[Index].EndingLBA, BlockSize)));
+
+ Status = PartitionInstallChildHandle (
+ This,
+ Handle,
+ DiskIo,
+ BlockIo,
+ DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &HdDev,
+ PartEntry[Index].StartingLBA,
+ PartEntry[Index].EndingLBA,
+ BlockSize,
+ CompareGuid(&PartEntry[Index].PartitionTypeGUID, &gEfiPartTypeSystemPartGuid)
+ );
+ }
+
+ DEBUG ((EFI_D_INFO, "Prepare to Free Pool\n"));
+
+Done:
+ if (ProtectiveMbr != NULL) {
+ gBS->FreePool (ProtectiveMbr);
+ }
+ if (PrimaryHeader != NULL) {
+ gBS->FreePool (PrimaryHeader);
+ }
+ if (BackupHeader != NULL) {
+ gBS->FreePool (BackupHeader);
+ }
+ if (PartEntry != NULL) {
+ gBS->FreePool (PartEntry);
+ }
+ if (PEntryStatus != NULL) {
+ gBS->FreePool (PEntryStatus);
+ }
+
+ return GptValid;
+}
+
+BOOLEAN
+PartitionValidGptTable (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_LBA Lba,
+ OUT EFI_PARTITION_TABLE_HEADER *PartHeader
+ )
+/*++
+
+Routine Description:
+ Check if the GPT partition table is valid
+
+Arguments:
+ BlockIo - Parent BlockIo interface
+ DiskIo - Disk Io protocol.
+ Lba - The starting Lba of the Partition Table
+ PartHeader - Stores the partition table that is read
+
+Returns:
+ TRUE - The partition table is valid
+ FALSE - The partition table is not valid
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 BlockSize;
+ EFI_PARTITION_TABLE_HEADER *PartHdr;
+
+ BlockSize = BlockIo->Media->BlockSize;
+
+ PartHdr = AllocateZeroPool (BlockSize);
+
+ if (PartHdr == NULL) {
+ DEBUG ((EFI_D_ERROR, "Allocate pool error\n"));
+ return FALSE;
+ }
+ //
+ // Read the EFI Partition Table Header
+ //
+ Status = BlockIo->ReadBlocks (
+ BlockIo,
+ BlockIo->Media->MediaId,
+ Lba,
+ BlockSize,
+ PartHdr
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (PartHdr);
+ return FALSE;
+ }
+
+ if (CompareMem (&PartHdr->Header.Signature, EFI_PTAB_HEADER_ID, sizeof (UINT64)) != 0 ||
+ !PartitionCheckCrc (BlockSize, &PartHdr->Header) ||
+ PartHdr->MyLBA != Lba
+ ) {
+ DEBUG ((EFI_D_INFO, " !Valid efi partition table header\n"));
+ gBS->FreePool (PartHdr);
+ return FALSE;
+ }
+
+ CopyMem (PartHeader, PartHdr, sizeof (EFI_PARTITION_TABLE_HEADER));
+ if (!PartitionCheckGptEntryArrayCRC (BlockIo, DiskIo, PartHeader)) {
+ gBS->FreePool (PartHdr);
+ return FALSE;
+ }
+
+ DEBUG ((EFI_D_INFO, " Valid efi partition table header\n"));
+ gBS->FreePool (PartHdr);
+ return TRUE;
+}
+
+BOOLEAN
+PartitionCheckGptEntryArrayCRC (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_PARTITION_TABLE_HEADER *PartHeader
+ )
+/*++
+
+Routine Description:
+
+ Check if the CRC field in the Partition table header is valid
+ for Partition entry array
+
+Arguments:
+
+ BlockIo - parent BlockIo interface
+ DiskIo - Disk Io Protocol.
+ PartHeader - Partition table header structure
+
+Returns:
+
+ TRUE - the CRC is valid
+ FALSE - the CRC is invalid
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT8 *Ptr;
+ UINT32 Crc;
+ UINTN Size;
+
+ //
+ // Read the EFI Partition Entries
+ //
+ Ptr = AllocatePool (PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry);
+ if (Ptr == NULL) {
+ DEBUG ((EFI_D_ERROR, " Allocate pool error\n"));
+ return FALSE;
+ }
+
+ Status = DiskIo->ReadDisk (
+ DiskIo,
+ BlockIo->Media->MediaId,
+ MultU64x32(PartHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),
+ PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,
+ Ptr
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (Ptr);
+ return FALSE;
+ }
+
+ Size = PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry;
+
+ Status = gBS->CalculateCrc32 (Ptr, Size, &Crc);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "CheckPEntryArrayCRC: Crc calculation failed\n"));
+ gBS->FreePool (Ptr);
+ return FALSE;
+ }
+
+ gBS->FreePool (Ptr);
+
+ return (BOOLEAN) (PartHeader->PartitionEntryArrayCRC32 == Crc);
+}
+
+BOOLEAN
+PartitionRestoreGptTable (
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_PARTITION_TABLE_HEADER *PartHeader
+ )
+/*++
+
+Routine Description:
+
+ Restore Partition Table to its alternate place
+ (Primary -> Backup or Backup -> Primary)
+
+Arguments:
+
+ BlockIo - parent BlockIo interface
+ DiskIo - Disk Io Protocol.
+ PartHeader - the source Partition table header structure
+
+Returns:
+
+ TRUE - Restoring succeeds
+ FALSE - Restoring failed
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN BlockSize;
+ EFI_PARTITION_TABLE_HEADER *PartHdr;
+ EFI_LBA PEntryLBA;
+ UINT8 *Ptr;
+
+ PartHdr = NULL;
+ Ptr = NULL;
+
+ BlockSize = BlockIo->Media->BlockSize;
+
+ PartHdr = AllocateZeroPool (BlockSize);
+
+ if (PartHdr == NULL) {
+ DEBUG ((EFI_D_ERROR, "Allocate pool error\n"));
+ return FALSE;
+ }
+
+ PEntryLBA = (PartHeader->MyLBA == PRIMARY_PART_HEADER_LBA) ? \
+ (PartHeader->LastUsableLBA + 1) : \
+ (PRIMARY_PART_HEADER_LBA + 1);
+
+ CopyMem (PartHdr, PartHeader, sizeof (EFI_PARTITION_TABLE_HEADER));
+
+ PartHdr->MyLBA = PartHeader->AlternateLBA;
+ PartHdr->AlternateLBA = PartHeader->MyLBA;
+ PartHdr->PartitionEntryLBA = PEntryLBA;
+ PartitionSetCrc ((EFI_TABLE_HEADER *) PartHdr);
+
+ Status = BlockIo->WriteBlocks (BlockIo, BlockIo->Media->MediaId, PartHdr->MyLBA, BlockSize, PartHdr);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Ptr = AllocatePool (PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry);
+ if (Ptr == NULL) {
+ DEBUG ((EFI_D_ERROR, " Allocate pool effor\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ Status = DiskIo->ReadDisk (
+ DiskIo,
+ BlockIo->Media->MediaId,
+ MultU64x32(PartHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),
+ PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,
+ Ptr
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = DiskIo->WriteDisk (
+ DiskIo,
+ BlockIo->Media->MediaId,
+ MultU64x32(PEntryLBA, BlockIo->Media->BlockSize),
+ PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,
+ Ptr
+ );
+
+Done:
+ gBS->FreePool (PartHdr);
+ gBS->FreePool (Ptr);
+
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+VOID
+PartitionCheckGptEntry (
+ IN EFI_PARTITION_TABLE_HEADER *PartHeader,
+ IN EFI_PARTITION_ENTRY *PartEntry,
+ OUT EFI_PARTITION_ENTRY_STATUS *PEntryStatus
+ )
+/*++
+
+Routine Description:
+
+ Check each partition entry for its range
+
+Arguments:
+
+ PartHeader - the partition table header
+ PartEntry - the partition entry array
+ PEntryStatus - the partition entry status array recording the status of
+ each partition
+
+Returns:
+ VOID
+
+--*/
+{
+ EFI_LBA StartingLBA;
+ EFI_LBA EndingLBA;
+ UINTN Index1;
+ UINTN Index2;
+
+ DEBUG ((EFI_D_INFO, " start check partition entries\n"));
+ for (Index1 = 0; Index1 < PartHeader->NumberOfPartitionEntries; Index1++) {
+ if (CompareGuid (&PartEntry[Index1].PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) {
+ continue;
+ }
+
+ StartingLBA = PartEntry[Index1].StartingLBA;
+ EndingLBA = PartEntry[Index1].EndingLBA;
+ if (StartingLBA > EndingLBA ||
+ StartingLBA < PartHeader->FirstUsableLBA ||
+ StartingLBA > PartHeader->LastUsableLBA ||
+ EndingLBA < PartHeader->FirstUsableLBA ||
+ EndingLBA > PartHeader->LastUsableLBA
+ ) {
+ PEntryStatus[Index1].OutOfRange = TRUE;
+ continue;
+ }
+
+ for (Index2 = Index1 + 1; Index2 < PartHeader->NumberOfPartitionEntries; Index2++) {
+
+ if (CompareGuid (&PartEntry[Index2].PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) {
+ continue;
+ }
+
+ if (PartEntry[Index2].EndingLBA >= StartingLBA && PartEntry[Index2].StartingLBA <= EndingLBA) {
+ //
+ // This region overlaps with the Index1'th region
+ //
+ PEntryStatus[Index1].Overlap = TRUE;
+ PEntryStatus[Index2].Overlap = TRUE;
+ continue;
+
+ }
+ }
+ }
+
+ DEBUG ((EFI_D_INFO, " End check partition entries\n"));
+}
+
+VOID
+PartitionSetCrc (
+ IN OUT EFI_TABLE_HEADER *Hdr
+ )
+/*++
+
+Routine Description:
+
+ Updates the CRC32 value in the table header
+
+Arguments:
+
+ Hdr - The table to update
+
+Returns:
+
+ None
+
+--*/
+{
+ PartitionSetCrcAltSize (Hdr->HeaderSize, Hdr);
+}
+
+VOID
+PartitionSetCrcAltSize (
+ IN UINTN Size,
+ IN OUT EFI_TABLE_HEADER *Hdr
+ )
+/*++
+
+Routine Description:
+
+ Updates the CRC32 value in the table header
+
+Arguments:
+
+ Size - The size of the table
+ Hdr - The table to update
+
+Returns:
+
+ None
+
+--*/
+{
+ UINT32 Crc;
+
+ Hdr->CRC32 = 0;
+ gBS->CalculateCrc32 ((UINT8 *) Hdr, Size, &Crc);
+ Hdr->CRC32 = Crc;
+}
+
+BOOLEAN
+PartitionCheckCrc (
+ IN UINTN MaxSize,
+ IN OUT EFI_TABLE_HEADER *Hdr
+ )
+/*++
+
+Routine Description:
+
+ Checks the CRC32 value in the table header
+
+Arguments:
+
+ MaxSize - Max Size limit
+ Hdr - The table to check
+
+Returns:
+
+ TRUE if the CRC is OK in the table
+
+--*/
+{
+ return PartitionCheckCrcAltSize (MaxSize, Hdr->HeaderSize, Hdr);
+}
+
+BOOLEAN
+PartitionCheckCrcAltSize (
+ IN UINTN MaxSize,
+ IN UINTN Size,
+ IN OUT EFI_TABLE_HEADER *Hdr
+ )
+/*++
+
+Routine Description:
+
+ Checks the CRC32 value in the table header
+
+Arguments:
+
+ MaxSize - Max Size Limit
+ Size - The size of the table
+ Hdr - The table to check
+
+Returns:
+
+ TRUE if the CRC is OK in the table
+
+--*/
+{
+ UINT32 Crc;
+ UINT32 OrgCrc;
+ EFI_STATUS Status;
+
+ Crc = 0;
+
+ if (Size == 0) {
+ //
+ // If header size is 0 CRC will pass so return FALSE here
+ //
+ return FALSE;
+ }
+
+ if (MaxSize && Size > MaxSize) {
+ DEBUG ((EFI_D_ERROR, "CheckCrc32: Size > MaxSize\n"));
+ return FALSE;
+ }
+ //
+ // clear old crc from header
+ //
+ OrgCrc = Hdr->CRC32;
+ Hdr->CRC32 = 0;
+
+ Status = gBS->CalculateCrc32 ((UINT8 *) Hdr, Size, &Crc);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "CheckCrc32: Crc calculation failed\n"));
+ return FALSE;
+ }
+ //
+ // set results
+ //
+ Hdr->CRC32 = Crc;
+
+ //
+ // return status
+ //
+ DEBUG_CODE (
+ if (OrgCrc != Crc) {
+ DEBUG ((EFI_D_ERROR, "CheckCrc32: Crc check failed\n"));
+ }
+ );
+
+ return (BOOLEAN) (OrgCrc == Crc);
+}
diff --git a/EdkModulePkg/Universal/Disk/Partition/Dxe/Gpt.h b/EdkModulePkg/Universal/Disk/Partition/Dxe/Gpt.h
new file mode 100644
index 0000000000..fbcd93db12
--- /dev/null
+++ b/EdkModulePkg/Universal/Disk/Partition/Dxe/Gpt.h
@@ -0,0 +1,76 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Gpt.h
+
+Abstract:
+
+ Data Structures required for detecting GPT Partitions
+
+Revision History
+
+--*/
+
+#ifndef _GPT_H_
+#define _GPT_H_
+
+#pragma pack(1)
+
+#define PRIMARY_PART_HEADER_LBA 1
+
+#define EFI_PTAB_HEADER_ID "EFI PART"
+
+//
+// EFI Partition Attributes
+//
+#define EFI_PART_REQUIRED_TO_FUNCTION 0x0000000000000001
+
+//
+// GPT Partition Table Header
+//
+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 PartitionEntryArrayCRC32;
+} EFI_PARTITION_TABLE_HEADER;
+
+//
+// GPT Partition Entry
+//
+typedef struct {
+ EFI_GUID PartitionTypeGUID;
+ EFI_GUID UniquePartitionGUID;
+ EFI_LBA StartingLBA;
+ EFI_LBA EndingLBA;
+ UINT64 Attributes;
+ CHAR16 PartitionName[36];
+} EFI_PARTITION_ENTRY;
+
+//
+// GPT Partition Entry Status
+//
+typedef struct {
+ BOOLEAN OutOfRange;
+ BOOLEAN Overlap;
+} EFI_PARTITION_ENTRY_STATUS;
+
+#pragma pack()
+
+#endif
diff --git a/EdkModulePkg/Universal/Disk/Partition/Dxe/Mbr.c b/EdkModulePkg/Universal/Disk/Partition/Dxe/Mbr.c
new file mode 100644
index 0000000000..07e3cbe459
--- /dev/null
+++ b/EdkModulePkg/Universal/Disk/Partition/Dxe/Mbr.c
@@ -0,0 +1,317 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Mbr.c
+
+Abstract:
+
+ Decode a hard disk partitioned with the legacy MBR found on most PC's
+
+ MBR - Master Boot Record is in the first sector of a partitioned hard disk.
+ The MBR supports four partitions per disk. The MBR also contains legacy
+ code that is not run on an EFI system. The legacy code reads the
+ first sector of the active partition into memory and
+
+ BPB - Boot(?) Parameter Block is in the first sector of a FAT file system.
+ The BPB contains information about the FAT file system. The BPB is
+ always on the first sector of a media. The first sector also contains
+ the legacy boot strap code.
+
+--*/
+
+#include "Partition.h"
+#include "Mbr.h"
+
+BOOLEAN
+PartitionValidMbr (
+ IN MASTER_BOOT_RECORD *Mbr,
+ IN EFI_LBA LastLba
+ )
+/*++
+
+Routine Description:
+ Test to see if the Mbr buffer is a valid MBR
+
+Arguments:
+ Mbr - Parent Handle
+ LastLba - Last Lba address on the device.
+
+Returns:
+ TRUE - Mbr is a Valid MBR
+ FALSE - Mbr is not a Valid MBR
+
+--*/
+{
+ UINT32 StartingLBA;
+ UINT32 EndingLBA;
+ UINT32 NewEndingLBA;
+ INTN Index1;
+ INTN Index2;
+ BOOLEAN MbrValid;
+
+ if (Mbr->Signature != MBR_SIGNATURE) {
+ return FALSE;
+ }
+ //
+ // The BPB also has this signature, so it can not be used alone.
+ //
+ MbrValid = FALSE;
+ for (Index1 = 0; Index1 < MAX_MBR_PARTITIONS; Index1++) {
+ if (Mbr->Partition[Index1].OSIndicator == 0x00 || UNPACK_UINT32 (Mbr->Partition[Index1].SizeInLBA) == 0) {
+ continue;
+ }
+
+ MbrValid = TRUE;
+ StartingLBA = UNPACK_UINT32 (Mbr->Partition[Index1].StartingLBA);
+ EndingLBA = StartingLBA + UNPACK_UINT32 (Mbr->Partition[Index1].SizeInLBA) - 1;
+ if (EndingLBA > LastLba) {
+ //
+ // Compatibility Errata:
+ // Some systems try to hide drive space with their INT 13h driver
+ // This does not hide space from the OS driver. This means the MBR
+ // that gets created from DOS is smaller than the MBR created from
+ // a real OS (NT & Win98). This leads to BlockIo->LastBlock being
+ // wrong on some systems FDISKed by the OS.
+ //
+ // return FALSE since no block devices on a system are implemented
+ // with INT 13h
+ //
+ return FALSE;
+ }
+
+ for (Index2 = Index1 + 1; Index2 < MAX_MBR_PARTITIONS; Index2++) {
+ if (Mbr->Partition[Index2].OSIndicator == 0x00 || UNPACK_UINT32 (Mbr->Partition[Index2].SizeInLBA) == 0) {
+ continue;
+ }
+
+ NewEndingLBA = UNPACK_UINT32 (Mbr->Partition[Index2].StartingLBA) + UNPACK_UINT32 (Mbr->Partition[Index2].SizeInLBA) - 1;
+ if (NewEndingLBA >= StartingLBA && UNPACK_UINT32 (Mbr->Partition[Index2].StartingLBA) <= EndingLBA) {
+ //
+ // This region overlaps with the Index1'th region
+ //
+ return FALSE;
+ }
+ }
+ }
+ //
+ // Non of the regions overlapped so MBR is O.K.
+ //
+ return MbrValid;
+}
+
+BOOLEAN
+PartitionInstallMbrChildHandles (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Handle,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+/*++
+
+Routine Description:
+ Install child handles if the Handle supports MBR format.
+
+Arguments:
+ This - Calling context.
+ Handle - Parent Handle
+ DiskIo - Parent DiskIo interface
+ BlockIo - Parent BlockIo interface
+ DevicePath - Parent Device Path
+
+Returns:
+ EFI_SUCCESS - If a child handle was added
+ other - A child handle was not added
+
+--*/
+{
+ EFI_STATUS Status;
+ MASTER_BOOT_RECORD *Mbr;
+ UINT32 ExtMbrStartingLba;
+ UINTN Index;
+ HARDDRIVE_DEVICE_PATH HdDev;
+ HARDDRIVE_DEVICE_PATH ParentHdDev;
+ BOOLEAN Found;
+ UINT32 PartitionNumber;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
+ EFI_DEVICE_PATH_PROTOCOL *LastDevicePathNode;
+
+ Mbr = NULL;
+ Found = FALSE;
+
+ Mbr = AllocatePool (BlockIo->Media->BlockSize);
+ if (Mbr == NULL) {
+ goto Done;
+ }
+
+ Status = BlockIo->ReadBlocks (
+ BlockIo,
+ BlockIo->Media->MediaId,
+ 0,
+ BlockIo->Media->BlockSize,
+ Mbr
+ );
+ if (EFI_ERROR (Status) || !PartitionValidMbr (Mbr, BlockIo->Media->LastBlock)) {
+ goto Done;
+ }
+ //
+ // We have a valid mbr - add each partition
+ //
+ //
+ // Get starting and ending LBA of the parent block device.
+ //
+ LastDevicePathNode = NULL;
+ ZeroMem (&ParentHdDev, sizeof (ParentHdDev));
+ DevicePathNode = DevicePath;
+ while (!EfiIsDevicePathEnd (DevicePathNode)) {
+ LastDevicePathNode = DevicePathNode;
+ DevicePathNode = EfiNextDevicePathNode (DevicePathNode);
+ }
+
+ if (LastDevicePathNode != NULL) {
+ if (DevicePathType (LastDevicePathNode) == MEDIA_DEVICE_PATH &&
+ DevicePathSubType (LastDevicePathNode) == MEDIA_HARDDRIVE_DP
+ ) {
+ gBS->CopyMem (&ParentHdDev, LastDevicePathNode, sizeof (ParentHdDev));
+ } else {
+ LastDevicePathNode = NULL;
+ }
+ }
+
+ PartitionNumber = 1;
+
+ ZeroMem (&HdDev, sizeof (HdDev));
+ HdDev.Header.Type = MEDIA_DEVICE_PATH;
+ HdDev.Header.SubType = MEDIA_HARDDRIVE_DP;
+ SetDevicePathNodeLength (&HdDev.Header, sizeof (HdDev));
+ HdDev.MBRType = MBR_TYPE_PCAT;
+ HdDev.SignatureType = SIGNATURE_TYPE_MBR;
+
+ if (LastDevicePathNode == NULL) {
+ //
+ // This is a MBR, add each partition
+ //
+ for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) {
+ if (Mbr->Partition[Index].OSIndicator == 0x00 || UNPACK_UINT32 (Mbr->Partition[Index].SizeInLBA) == 0) {
+ //
+ // Don't use null MBR entries
+ //
+ continue;
+ }
+
+ if (Mbr->Partition[Index].OSIndicator == 0xEE) {
+ //
+ // This is the guard MBR for the GPT. If you ever see a GPT disk with zero partitions you can get here.
+ // We can not produce an MBR BlockIo for this device as the MBR spans the GPT headers. So formating
+ // this BlockIo would corrupt the GPT structures and require a recovery that would corrupt the format
+ // that corrupted the GPT partition.
+ //
+ continue;
+ }
+
+ HdDev.PartitionNumber = PartitionNumber ++;
+ HdDev.PartitionStart = UNPACK_UINT32 (Mbr->Partition[Index].StartingLBA);
+ HdDev.PartitionSize = UNPACK_UINT32 (Mbr->Partition[Index].SizeInLBA);
+ CopyMem (HdDev.Signature, &(Mbr->UniqueMbrSignature[0]), sizeof (UINT32));
+
+ Status = PartitionInstallChildHandle (
+ This,
+ Handle,
+ DiskIo,
+ BlockIo,
+ DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &HdDev,
+ HdDev.PartitionStart,
+ HdDev.PartitionStart + HdDev.PartitionSize - 1,
+ MBR_SIZE,
+ (BOOLEAN) (Mbr->Partition[Index].OSIndicator == EFI_PARTITION)
+ );
+
+ if (!EFI_ERROR (Status)) {
+ Found = TRUE;
+ }
+ }
+ } else {
+ //
+ // It's an extended partition. Follow the extended partition
+ // chain to get all the logical drives
+ //
+ ExtMbrStartingLba = 0;
+
+ do {
+
+ Status = BlockIo->ReadBlocks (
+ BlockIo,
+ BlockIo->Media->MediaId,
+ ExtMbrStartingLba,
+ BlockIo->Media->BlockSize,
+ Mbr
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (Mbr->Partition[0].OSIndicator == 0) {
+ break;
+ }
+
+ HdDev.PartitionNumber = PartitionNumber ++;
+ HdDev.PartitionStart = UNPACK_UINT32 (Mbr->Partition[0].StartingLBA) + ExtMbrStartingLba + ParentHdDev.PartitionStart;
+ HdDev.PartitionSize = UNPACK_UINT32 (Mbr->Partition[0].SizeInLBA);
+ if (HdDev.PartitionStart + HdDev.PartitionSize - 1 >=
+ ParentHdDev.PartitionStart + ParentHdDev.PartitionSize) {
+ break;
+ }
+
+ //
+ // The signature in EBR(Extended Boot Record) should always be 0.
+ //
+ *((UINT32 *) &HdDev.Signature[0]) = 0;
+
+ Status = PartitionInstallChildHandle (
+ This,
+ Handle,
+ DiskIo,
+ BlockIo,
+ DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &HdDev,
+ HdDev.PartitionStart - ParentHdDev.PartitionStart,
+ HdDev.PartitionStart - ParentHdDev.PartitionStart + HdDev.PartitionSize - 1,
+ MBR_SIZE,
+ (BOOLEAN) (Mbr->Partition[0].OSIndicator == EFI_PARTITION)
+ );
+ if (!EFI_ERROR (Status)) {
+ Found = TRUE;
+ }
+
+ if (Mbr->Partition[1].OSIndicator != EXTENDED_DOS_PARTITION &&
+ Mbr->Partition[1].OSIndicator != EXTENDED_WINDOWS_PARTITION
+ ) {
+ break;
+ }
+
+ ExtMbrStartingLba = UNPACK_UINT32 (Mbr->Partition[1].StartingLBA);
+ //
+ // Don't allow partition to be self referencing
+ //
+ if (ExtMbrStartingLba == 0) {
+ break;
+ }
+ } while (ExtMbrStartingLba < ParentHdDev.PartitionSize);
+ }
+
+Done:
+ gBS->FreePool (Mbr);
+
+ return Found;
+}
diff --git a/EdkModulePkg/Universal/Disk/Partition/Dxe/Mbr.h b/EdkModulePkg/Universal/Disk/Partition/Dxe/Mbr.h
new file mode 100644
index 0000000000..c0022c88ad
--- /dev/null
+++ b/EdkModulePkg/Universal/Disk/Partition/Dxe/Mbr.h
@@ -0,0 +1,68 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Mbr.h
+
+Abstract:
+
+ Data Structures required for detecting MBR Partitions
+
+Revision History
+
+--*/
+
+#ifndef _MBR_H_
+#define _MBR_H_
+
+#pragma pack(1)
+
+#define MBR_SIGNATURE 0xaa55
+#define MIN_MBR_DEVICE_SIZE 0x80000
+#define MBR_ERRATA_PAD 0x40000 // 128 MB
+#define EXTENDED_DOS_PARTITION 0x05
+#define EXTENDED_WINDOWS_PARTITION 0x0F
+#define MAX_MBR_PARTITIONS 4
+
+#define EFI_PARTITION 0xef
+#define MBR_SIZE 512
+
+//
+// MBR Partition Entry
+//
+typedef struct {
+ UINT8 BootIndicator;
+ UINT8 StartHead;
+ UINT8 StartSector;
+ UINT8 StartTrack;
+ UINT8 OSIndicator;
+ UINT8 EndHead;
+ UINT8 EndSector;
+ UINT8 EndTrack;
+ UINT8 StartingLBA[4];
+ UINT8 SizeInLBA[4];
+} MBR_PARTITION_RECORD;
+
+//
+// MBR Partition table
+//
+typedef struct {
+ UINT8 BootStrapCode[440];
+ UINT8 UniqueMbrSignature[4];
+ UINT8 Unknown[2];
+ MBR_PARTITION_RECORD Partition[MAX_MBR_PARTITIONS];
+ UINT16 Signature;
+} MASTER_BOOT_RECORD;
+
+#pragma pack()
+
+#endif
diff --git a/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.c b/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.c
new file mode 100644
index 0000000000..59e33b27c1
--- /dev/null
+++ b/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.c
@@ -0,0 +1,735 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Partition.c
+
+Abstract:
+
+ Partition driver that produces logical BlockIo devices from a physical
+ BlockIo device. The logical BlockIo devices are based on the format
+ of the raw block devices media. Currently "El Torito CD-ROM", Legacy
+ MBR, and GPT partition schemes are supported.
+
+--*/
+
+#include "Partition.h"
+
+//
+// Function Prototypes
+//
+EFI_STATUS
+EFIAPI
+PartitionEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+EFI_STATUS
+EFIAPI
+PartitionDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+PartitionDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+PartitionDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+//
+// Partition Driver Global Variables
+//
+EFI_DRIVER_BINDING_PROTOCOL gPartitionDriverBinding = {
+ PartitionDriverBindingSupported,
+ PartitionDriverBindingStart,
+ PartitionDriverBindingStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+EFI_STATUS
+EFIAPI
+PartitionDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+ Test to see if this driver supports ControllerHandle. Any ControllerHandle
+ than contains a BlockIo and DiskIo protocol can be supported.
+
+ Arguments:
+ This - Protocol instance pointer.
+ ControllerHandle - Handle of device to test
+ RemainingDevicePath - Not used
+
+ Returns:
+ EFI_SUCCESS - This driver supports this device
+ EFI_ALREADY_STARTED - This driver is already running on this device
+ EFI_UNSUPPORTED - This driver does not support this device
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_DISK_IO_PROTOCOL *DiskIo;
+ EFI_DEV_PATH *Node;
+
+ if (RemainingDevicePath != NULL) {
+ Node = (EFI_DEV_PATH *) RemainingDevicePath;
+ if (Node->DevPath.Type != MEDIA_DEVICE_PATH ||
+ Node->DevPath.SubType != MEDIA_HARDDRIVE_DP ||
+ DevicePathNodeLength (&Node->DevPath) != sizeof (HARDDRIVE_DEVICE_PATH)
+ ) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ //
+ // Open the IO Abstraction(s) needed to perform the supported test
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (Status == EFI_ALREADY_STARTED) {
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Close the I/O Abstraction(s) used to perform the supported test
+ //
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+
+ //
+ // Open the IO Abstraction(s) needed to perform the supported test
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiDiskIoProtocolGuid,
+ (VOID **) &DiskIo,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (Status == EFI_ALREADY_STARTED) {
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Close the I/O Abstraction(s) used to perform the supported test
+ //
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiDiskIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+
+ //
+ // Open the IO Abstraction(s) needed to perform the supported test
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiBlockIoProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PartitionDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine 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.
+
+ Arguments:
+ This - Protocol instance pointer.
+ ControllerHandle - Handle of device to bind driver to
+ RemainingDevicePath - Not used
+
+ Returns:
+ EFI_SUCCESS - This driver is added to DeviceHandle
+ EFI_ALREADY_STARTED - This driver is already running on DeviceHandle
+ other - This driver does not support this device
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_STATUS OpenStatus;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ EFI_DISK_IO_PROTOCOL *DiskIo;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlockIo,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Get the Device Path Protocol on ControllerHandle's handle
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
+ return Status;
+ }
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiDiskIoProtocolGuid,
+ (VOID **) &DiskIo,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ return Status;
+ }
+
+ OpenStatus = Status;
+
+ //
+ // If no media is present, do nothing here.
+ //
+ Status = EFI_UNSUPPORTED;
+ if (BlockIo->Media->MediaPresent) {
+ //
+ // Try for GPT, then El Torito, and then legacy MBR partition types. If the
+ // media supports a given partition type install child handles to represent
+ // the partitions described by the media.
+ //
+ if (PartitionInstallGptChildHandles (
+ This,
+ ControllerHandle,
+ DiskIo,
+ BlockIo,
+ ParentDevicePath
+ ) ||
+
+ PartitionInstallElToritoChildHandles (
+ This,
+ ControllerHandle,
+ DiskIo,
+ BlockIo,
+ ParentDevicePath
+ ) ||
+
+ PartitionInstallMbrChildHandles (
+ This,
+ ControllerHandle,
+ DiskIo,
+ BlockIo,
+ ParentDevicePath
+ )) {
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+ //
+ // In the case that the driver is already started (OpenStatus == EFI_ALREADY_STARTED),
+ // the DevicePathProtocol and the DiskIoProtocol are not actually opened by the
+ // driver. So don't try to close them. Otherwise, we will break the dependency
+ // between the controller and the driver set up before.
+ //
+ if (EFI_ERROR (Status) && !EFI_ERROR (OpenStatus)) {
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiDiskIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PartitionDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+ Routine Description:
+ Stop this driver on ControllerHandle. Support stoping any child handles
+ created by this driver.
+
+ Arguments:
+ This - Protocol instance pointer.
+ ControllerHandle - 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.
+
+ Returns:
+ EFI_SUCCESS - This driver is removed DeviceHandle
+ EFI_DEVICE_ERROR - This driver was not removed from this device
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ BOOLEAN AllChildrenStopped;
+ PARTITION_PRIVATE_DATA *Private;
+ EFI_DISK_IO_PROTOCOL *DiskIo;
+
+ if (NumberOfChildren == 0) {
+ //
+ // Close the bus driver
+ //
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiDiskIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+
+ return EFI_SUCCESS;
+ }
+
+ AllChildrenStopped = TRUE;
+ for (Index = 0; Index < NumberOfChildren; Index++) {
+ Status = gBS->OpenProtocol (
+ ChildHandleBuffer[Index],
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlockIo,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+
+ Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (BlockIo);
+
+ //
+ // All Software protocols have be freed from the handle so remove it.
+ //
+ BlockIo->FlushBlocks (BlockIo);
+
+ Status = gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiDiskIoProtocolGuid,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index]
+ );
+
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ ChildHandleBuffer[Index],
+ &gEfiDevicePathProtocolGuid,
+ Private->DevicePath,
+ &gEfiBlockIoProtocolGuid,
+ &Private->BlockIo,
+ Private->EspGuid,
+ NULL,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiDiskIoProtocolGuid,
+ (VOID **) &DiskIo,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index],
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ } else {
+ gBS->FreePool (Private->DevicePath);
+ gBS->FreePool (Private);
+ }
+
+ }
+
+ if (EFI_ERROR (Status)) {
+ AllChildrenStopped = FALSE;
+ }
+ }
+
+ if (!AllChildrenStopped) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PartitionReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+/*++
+
+ Routine Description:
+ Reset the parent Block Device.
+
+ Arguments:
+ This - Protocol instance pointer.
+ ExtendedVerification - Driver may perform diagnostics on reset.
+
+ Returns:
+ EFI_SUCCESS - The device was reset.
+ EFI_DEVICE_ERROR - The device is not functioning properly and could
+ not be reset.
+
+--*/
+{
+ PARTITION_PRIVATE_DATA *Private;
+
+ Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
+
+ return Private->ParentBlockIo->Reset (
+ Private->ParentBlockIo,
+ ExtendedVerification
+ );
+}
+
+EFI_STATUS
+EFIAPI
+PartitionReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+ Routine Description:
+ Read by using the Disk IO protocol on the parent device. Lba addresses
+ must be converted to byte offsets.
+
+ Arguments:
+ 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
+
+ Returns:
+ 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 matched 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.
+
+--*/
+{
+ PARTITION_PRIVATE_DATA *Private;
+ UINT64 Offset;
+
+ Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
+
+ if (BufferSize % Private->BlockSize != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
+ if (Offset + BufferSize > Private->End) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Because some kinds of partition have different block size from their parent
+ // device, we call the Disk IO protocol on the parent device, not the Block IO
+ // protocol
+ //
+ return Private->DiskIo->ReadDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);
+}
+
+EFI_STATUS
+EFIAPI
+PartitionWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+ Routine Description:
+ Write by using the Disk IO protocol on the parent device. Lba addresses
+ must be converted to byte offsets.
+
+ Arguments:
+ 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
+
+ Returns:
+ 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_CHNAGED - The MediaId does not matched 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.
+
+--*/
+{
+ PARTITION_PRIVATE_DATA *Private;
+ UINT64 Offset;
+
+ Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
+
+ if (BufferSize % Private->BlockSize != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
+ if (Offset + BufferSize > Private->End) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Because some kinds of partition have different block size from their parent
+ // device, we call the Disk IO protocol on the parent device, not the Block IO
+ // protocol
+ //
+ return Private->DiskIo->WriteDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer);
+}
+
+EFI_STATUS
+EFIAPI
+PartitionFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+/*++
+
+ Routine Description:
+ Flush the parent Block Device.
+
+ Arguments:
+ This - Protocol instance pointer.
+
+ Returns:
+ 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.
+
+--*/
+{
+ PARTITION_PRIVATE_DATA *Private;
+
+ Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This);
+
+ return Private->ParentBlockIo->FlushBlocks (Private->ParentBlockIo);
+}
+
+EFI_STATUS
+PartitionInstallChildHandle (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ParentHandle,
+ IN EFI_DISK_IO_PROTOCOL *ParentDiskIo,
+ IN EFI_BLOCK_IO_PROTOCOL *ParentBlockIo,
+ IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN EFI_LBA Start,
+ IN EFI_LBA End,
+ IN UINT32 BlockSize,
+ IN BOOLEAN InstallEspGuid
+ )
+/*++
+
+Routine Description:
+ Create a child handle for a logical block device that represents the
+ bytes Start to End of the Parent Block IO device.
+
+Arguments:
+ This - Calling context.
+ ParentHandle - Parent Handle for new child
+ ParentDiskIo - Parent DiskIo interface
+ ParentBlockIo - Parent BlockIo interface
+ ParentDevicePath - Parent Device Path
+ DevicePathNode - Child Device Path node
+ Start - Start Block
+ End - End Block
+ BlockSize - Child block size
+ InstallEspGuid - Flag to install EFI System Partition GUID on handle
+
+Returns:
+ EFI_SUCCESS - If a child handle was added
+ EFI_OUT_OF_RESOURCES - A child handle was not added
+
+--*/
+{
+ EFI_STATUS Status;
+ PARTITION_PRIVATE_DATA *Private;
+
+ Private = AllocateZeroPool (sizeof (PARTITION_PRIVATE_DATA));
+ if (Private == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Private->Signature = PARTITION_PRIVATE_DATA_SIGNATURE;
+
+ Private->Start = MultU64x32 (Start, ParentBlockIo->Media->BlockSize);
+ Private->End = MultU64x32 (End + 1, ParentBlockIo->Media->BlockSize);
+
+ Private->BlockSize = BlockSize;
+ Private->ParentBlockIo = ParentBlockIo;
+ Private->DiskIo = ParentDiskIo;
+
+ Private->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;
+
+ Private->BlockIo.Media = &Private->Media;
+ CopyMem (Private->BlockIo.Media, ParentBlockIo->Media, sizeof (EFI_BLOCK_IO_MEDIA));
+ Private->Media.LogicalPartition = TRUE;
+ Private->Media.LastBlock = DivU64x32 (
+ MultU64x32 (
+ End - Start + 1,
+ ParentBlockIo->Media->BlockSize
+ ),
+ BlockSize
+ ) - 1;
+
+ Private->Media.BlockSize = (UINT32) BlockSize;
+
+ Private->BlockIo.Reset = PartitionReset;
+ Private->BlockIo.ReadBlocks = PartitionReadBlocks;
+ Private->BlockIo.WriteBlocks = PartitionWriteBlocks;
+ Private->BlockIo.FlushBlocks = PartitionFlushBlocks;
+
+ Private->DevicePath = AppendDevicePathNode (ParentDevicePath, DevicePathNode);
+
+ if (Private->DevicePath == NULL) {
+ gBS->FreePool (Private);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (InstallEspGuid) {
+ Private->EspGuid = &gEfiPartTypeSystemPartGuid;
+ } else {
+ //
+ // If NULL InstallMultipleProtocolInterfaces will ignore it.
+ //
+ Private->EspGuid = NULL;
+ }
+ //
+ // Create the new handle
+ //
+ Private->Handle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Private->Handle,
+ &gEfiDevicePathProtocolGuid,
+ Private->DevicePath,
+ &gEfiBlockIoProtocolGuid,
+ &Private->BlockIo,
+ Private->EspGuid,
+ NULL,
+ NULL
+ );
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Open the Parent Handle for the child
+ //
+ Status = gBS->OpenProtocol (
+ ParentHandle,
+ &gEfiDiskIoProtocolGuid,
+ (VOID **) &ParentDiskIo,
+ This->DriverBindingHandle,
+ Private->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ } else {
+ gBS->FreePool (Private->DevicePath);
+ gBS->FreePool (Private);
+ }
+
+ return Status;
+}
diff --git a/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.h b/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.h
new file mode 100644
index 0000000000..de6fbf12ef
--- /dev/null
+++ b/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.h
@@ -0,0 +1,123 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Partition.h
+
+Abstract:
+
+ Partition driver that produces logical BlockIo devices from a physical
+ BlockIo device. The logical BlockIo devices are based on the format
+ of the raw block devices media. Currently "El Torito CD-ROM", Legacy
+ MBR, and GPT partition schemes are supported.
+
+Revision History
+
+--*/
+
+#ifndef __PARTITION_H__
+#define __PARTITION_H__
+
+
+
+//
+// Partition private data
+//
+#define PARTITION_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('P', 'a', 'r', 't')
+typedef struct {
+ UINT64 Signature;
+
+ EFI_HANDLE Handle;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_BLOCK_IO_PROTOCOL BlockIo;
+ EFI_BLOCK_IO_MEDIA Media;
+
+ EFI_DISK_IO_PROTOCOL *DiskIo;
+ EFI_BLOCK_IO_PROTOCOL *ParentBlockIo;
+ UINT64 Start;
+ UINT64 End;
+ UINT32 BlockSize;
+
+ EFI_GUID *EspGuid;
+
+} PARTITION_PRIVATE_DATA;
+
+#define PARTITION_DEVICE_FROM_BLOCK_IO_THIS(a) CR (a, PARTITION_PRIVATE_DATA, BlockIo, PARTITION_PRIVATE_DATA_SIGNATURE)
+
+//
+// Global Variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gPartitionDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gPartitionComponentName;
+
+//
+// Extract INT32 from char array
+//
+#define UNPACK_INT32(a) (INT32)( (((UINT8 *) a)[0] << 0) | \
+ (((UINT8 *) a)[1] << 8) | \
+ (((UINT8 *) a)[2] << 16) | \
+ (((UINT8 *) a)[3] << 24) )
+
+//
+// Extract UINT32 from char array
+//
+#define UNPACK_UINT32(a) (UINT32)( (((UINT8 *) a)[0] << 0) | \
+ (((UINT8 *) a)[1] << 8) | \
+ (((UINT8 *) a)[2] << 16) | \
+ (((UINT8 *) a)[3] << 24) )
+
+EFI_STATUS
+PartitionInstallChildHandle (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ParentHandle,
+ IN EFI_DISK_IO_PROTOCOL *ParentDiskIo,
+ IN EFI_BLOCK_IO_PROTOCOL *ParentBlockIo,
+ IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN UINT64 Start,
+ IN UINT64 End,
+ IN UINT32 BlockSize,
+ IN BOOLEAN InstallEspGuid
+ )
+;
+
+BOOLEAN
+PartitionInstallGptChildHandles (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Handle,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+;
+
+BOOLEAN
+PartitionInstallElToritoChildHandles (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Handle,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+;
+
+BOOLEAN
+PartitionInstallMbrChildHandles (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Handle,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+;
+
+#endif
diff --git a/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.mbd b/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.mbd
new file mode 100644
index 0000000000..7be0d52c92
--- /dev/null
+++ b/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.mbd
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<ModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MbdHeader>
+ <BaseName>Partition</BaseName>
+ <Guid>1FA1F39E-FEFF-4aae-BD7B-38A070A3B609</Guid>
+ <Version>0</Version>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Created>2006-03-12 17:09</Created>
+ <Modified>2006-03-19 15:19</Modified>
+ </MbdHeader>
+ <Libraries>
+ <Library>UefiBootServicesTableLib</Library>
+ <Library>BaseLib</Library>
+ <Library>UefiMemoryLib</Library>
+ <Library>UefiLib</Library>
+ <Library>UefiDriverEntryPoint</Library>
+ <Library>UefiDriverModelLib</Library>
+ <Library>DxeMemoryAllocationLib</Library>
+ <Library>DxeReportStatusCodeLib</Library>
+ <Library>BaseDebugLibReportStatusCode</Library>
+ <Library>UefiDevicePathLib</Library>
+ </Libraries>
+</ModuleBuildDescription>
diff --git a/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.msa b/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.msa
new file mode 100644
index 0000000000..a4eed02ef1
--- /dev/null
+++ b/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.msa
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MsaHeader>
+ <BaseName>Partition</BaseName>
+ <ModuleType>UEFI_DRIVER</ModuleType>
+ <ComponentType>BS_DRIVER</ComponentType>
+ <Guid>1FA1F39E-FEFF-4aae-BD7B-38A070A3B609</Guid>
+ <Version>0</Version>
+ <Abstract>Component description file for Partition module.</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Specification>0</Specification>
+ <Created>2006-03-12 17:09</Created>
+ <Updated>2006-03-19 15:19</Updated>
+ </MsaHeader>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverModelLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverEntryPoint</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">MemoryAllocationLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiBootServicesTableLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DevicePathLib</LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>Partition.h</Filename>
+ <Filename>ElTorito.h</Filename>
+ <Filename>Gpt.h</Filename>
+ <Filename>Mbr.h</Filename>
+ <Filename>Partition.c</Filename>
+ <Filename>Eltorito.c</Filename>
+ <Filename>Gpt.c</Filename>
+ <Filename>Mbr.c</Filename>
+ <Filename>ComponentName.c</Filename>
+ </SourceFiles>
+ <Includes>
+ <PackageName>MdePkg</PackageName>
+ </Includes>
+ <Protocols>
+ <Protocol Usage="TO_START">BlockIo</Protocol>
+ <Protocol Usage="TO_START">DiskIo</Protocol>
+ <Protocol Usage="TO_START">DevicePath</Protocol>
+ </Protocols>
+ <Guids>
+ <GuidEntry Usage="SOMETIMES_CONSUMED">
+ <C_Name>PartTypeSystemPart</C_Name>
+ </GuidEntry>
+ <GuidEntry Usage="ALWAYS_CONSUMED">
+ <C_Name>PartTypeUnused</C_Name>
+ </GuidEntry>
+ </Guids>
+ <Externs>
+ <Extern>
+ <ModuleEntryPoint></ModuleEntryPoint>
+ </Extern>
+ <Extern>
+ <DriverBinding>gPartitionDriverBinding</DriverBinding>
+ <ComponentName>gPartitionComponentName</ComponentName>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea>
diff --git a/EdkModulePkg/Universal/Disk/Partition/Dxe/build.xml b/EdkModulePkg/Universal/Disk/Partition/Dxe/build.xml
new file mode 100644
index 0000000000..ea4ea4e1ed
--- /dev/null
+++ b/EdkModulePkg/Universal/Disk/Partition/Dxe/build.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.-->
+<project basedir="." default="Partition"><!--Apply external ANT tasks-->
+ <taskdef resource="GenBuild.tasks"/>
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+ <property environment="env"/>
+ <property name="WORKSPACE_DIR" value="${env.WORKSPACE}"/>
+ <import file="${WORKSPACE_DIR}\Tools\Conf\BuildMacro.xml"/><!--MODULE_RELATIVE PATH is relative to PACKAGE_DIR-->
+ <property name="MODULE_RELATIVE_PATH" value="Universal\Disk\Partition\Dxe"/>
+ <property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
+ <property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
+ <target name="Partition">
+ <GenBuild baseName="Partition" mbdFilename="${MODULE_DIR}\Partition.mbd" msaFilename="${MODULE_DIR}\Partition.msa"/>
+ </target>
+ <target depends="Partition_clean" name="clean"/>
+ <target depends="Partition_cleanall" name="cleanall"/>
+ <target name="Partition_clean">
+ <OutputDirSetup baseName="Partition" mbdFilename="${MODULE_DIR}\Partition.mbd" msaFilename="${MODULE_DIR}\Partition.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\Partition_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\Partition_build.xml" target="clean"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
+ </target>
+ <target name="Partition_cleanall">
+ <OutputDirSetup baseName="Partition" mbdFilename="${MODULE_DIR}\Partition.mbd" msaFilename="${MODULE_DIR}\Partition.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\Partition_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\Partition_build.xml" target="cleanall"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}"/>
+ <delete dir="${DEST_DIR_DEBUG}"/>
+ <delete>
+ <fileset dir="${BIN_DIR}" includes="**Partition*"/>
+ </delete>
+ </target>
+</project> \ No newline at end of file