From 878ddf1fc3540a715f63594ed22b6929e881afb4 Mon Sep 17 00:00:00 2001 From: bbahnsen Date: Fri, 21 Apr 2006 22:54:32 +0000 Subject: Initial import. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Universal/Disk/DiskIo/Dxe/ComponentName.c | 160 ++++ EdkModulePkg/Universal/Disk/DiskIo/Dxe/DiskIo.mbd | 41 + EdkModulePkg/Universal/Disk/DiskIo/Dxe/DiskIo.msa | 65 ++ EdkModulePkg/Universal/Disk/DiskIo/Dxe/build.xml | 47 ++ EdkModulePkg/Universal/Disk/DiskIo/Dxe/diskio.c | 876 +++++++++++++++++++++ EdkModulePkg/Universal/Disk/DiskIo/Dxe/diskio.h | 44 ++ .../Disk/DiskIoPartition/dxe/DiskIoPartition.mbd | 42 + .../Disk/DiskIoPartition/dxe/DiskIoPartition.msa | 88 +++ .../Universal/Disk/DiskIoPartition/dxe/build.xml | 47 ++ .../Universal/Disk/Partition/Dxe/ComponentName.c | 160 ++++ .../Universal/Disk/Partition/Dxe/ElTorito.c | 277 +++++++ .../Universal/Disk/Partition/Dxe/ElTorito.h | 130 +++ EdkModulePkg/Universal/Disk/Partition/Dxe/Gpt.c | 768 ++++++++++++++++++ EdkModulePkg/Universal/Disk/Partition/Dxe/Gpt.h | 76 ++ EdkModulePkg/Universal/Disk/Partition/Dxe/Mbr.c | 317 ++++++++ EdkModulePkg/Universal/Disk/Partition/Dxe/Mbr.h | 68 ++ .../Universal/Disk/Partition/Dxe/Partition.c | 735 +++++++++++++++++ .../Universal/Disk/Partition/Dxe/Partition.h | 123 +++ .../Universal/Disk/Partition/Dxe/Partition.mbd | 42 + .../Universal/Disk/Partition/Dxe/Partition.msa | 81 ++ .../Universal/Disk/Partition/Dxe/build.xml | 47 ++ .../Disk/UnicodeCollation/English/Dxe/English.mbd | 38 + .../Disk/UnicodeCollation/English/Dxe/English.msa | 53 ++ .../English/Dxe/UnicodeCollationEng.c | 478 +++++++++++ .../English/Dxe/UnicodeCollationEng.h | 102 +++ .../Disk/UnicodeCollation/English/Dxe/build.xml | 47 ++ 26 files changed, 4952 insertions(+) create mode 100644 EdkModulePkg/Universal/Disk/DiskIo/Dxe/ComponentName.c create mode 100644 EdkModulePkg/Universal/Disk/DiskIo/Dxe/DiskIo.mbd create mode 100644 EdkModulePkg/Universal/Disk/DiskIo/Dxe/DiskIo.msa create mode 100644 EdkModulePkg/Universal/Disk/DiskIo/Dxe/build.xml create mode 100644 EdkModulePkg/Universal/Disk/DiskIo/Dxe/diskio.c create mode 100644 EdkModulePkg/Universal/Disk/DiskIo/Dxe/diskio.h create mode 100644 EdkModulePkg/Universal/Disk/DiskIoPartition/dxe/DiskIoPartition.mbd create mode 100644 EdkModulePkg/Universal/Disk/DiskIoPartition/dxe/DiskIoPartition.msa create mode 100644 EdkModulePkg/Universal/Disk/DiskIoPartition/dxe/build.xml create mode 100644 EdkModulePkg/Universal/Disk/Partition/Dxe/ComponentName.c create mode 100644 EdkModulePkg/Universal/Disk/Partition/Dxe/ElTorito.c create mode 100644 EdkModulePkg/Universal/Disk/Partition/Dxe/ElTorito.h create mode 100644 EdkModulePkg/Universal/Disk/Partition/Dxe/Gpt.c create mode 100644 EdkModulePkg/Universal/Disk/Partition/Dxe/Gpt.h create mode 100644 EdkModulePkg/Universal/Disk/Partition/Dxe/Mbr.c create mode 100644 EdkModulePkg/Universal/Disk/Partition/Dxe/Mbr.h create mode 100644 EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.c create mode 100644 EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.h create mode 100644 EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.mbd create mode 100644 EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.msa create mode 100644 EdkModulePkg/Universal/Disk/Partition/Dxe/build.xml create mode 100644 EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/English.mbd create mode 100644 EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/English.msa create mode 100644 EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/UnicodeCollationEng.c create mode 100644 EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/UnicodeCollationEng.h create mode 100644 EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/build.xml (limited to 'EdkModulePkg/Universal/Disk') diff --git a/EdkModulePkg/Universal/Disk/DiskIo/Dxe/ComponentName.c b/EdkModulePkg/Universal/Disk/DiskIo/Dxe/ComponentName.c new file mode 100644 index 0000000..35ca70d --- /dev/null +++ b/EdkModulePkg/Universal/Disk/DiskIo/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 "DiskIo.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +DiskIoComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +DiskIoComponentNameGetControllerName ( + 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 gDiskIoComponentName = { + DiskIoComponentNameGetDriverName, + DiskIoComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mDiskIoDriverNameTable[] = { + { + "eng", + (CHAR16 *)L"Generic Disk I/O Driver" + }, + { + NULL, + NULL + } +}; + +EFI_STATUS +EFIAPI +DiskIoComponentNameGetDriverName ( + 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, + gDiskIoComponentName.SupportedLanguages, + mDiskIoDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +DiskIoComponentNameGetControllerName ( + 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/DiskIo/Dxe/DiskIo.mbd b/EdkModulePkg/Universal/Disk/DiskIo/Dxe/DiskIo.mbd new file mode 100644 index 0000000..087bedf --- /dev/null +++ b/EdkModulePkg/Universal/Disk/DiskIo/Dxe/DiskIo.mbd @@ -0,0 +1,41 @@ + + + + + DiskIo + 6B38F7B4-AD98-40e9-9093-ACA2B5A253C4 + 0 + FIX ME! + Copyright (c) 2004-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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + BaseLib + DxeMemoryAllocationLib + + diff --git a/EdkModulePkg/Universal/Disk/DiskIo/Dxe/DiskIo.msa b/EdkModulePkg/Universal/Disk/DiskIo/Dxe/DiskIo.msa new file mode 100644 index 0000000..2ddc523 --- /dev/null +++ b/EdkModulePkg/Universal/Disk/DiskIo/Dxe/DiskIo.msa @@ -0,0 +1,65 @@ + + + + + DiskIo + UEFI_DRIVER + BS_DRIVER + 6B38F7B4-AD98-40e9-9093-ACA2B5A253C4 + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + UefiLib + BaseLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + + + diskio.c + diskio.h + ComponentName.c + + + MdePkg + + + BlockIo + DiskIo + + + + + + + gDiskIoDriverBinding + gDiskIoComponentName + + + diff --git a/EdkModulePkg/Universal/Disk/DiskIo/Dxe/build.xml b/EdkModulePkg/Universal/Disk/DiskIo/Dxe/build.xml new file mode 100644 index 0000000..8a6ff7b --- /dev/null +++ b/EdkModulePkg/Universal/Disk/DiskIo/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/Disk/DiskIo/Dxe/diskio.c b/EdkModulePkg/Universal/Disk/DiskIo/Dxe/diskio.c new file mode 100644 index 0000000..4998c9b --- /dev/null +++ b/EdkModulePkg/Universal/Disk/DiskIo/Dxe/diskio.c @@ -0,0 +1,876 @@ +/*++ + +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: + + DiskIo.c + +Abstract: + + DiskIo driver that layers it's self on every Block IO protocol in the system. + DiskIo converts a block oriented device to a byte oriented device. + + ReadDisk may have to do reads that are not aligned on sector boundaries. + There are three cases: + + UnderRun - The first byte is not on a sector boundary or the read request is + less than a sector in length. + + Aligned - A read of N contiguous sectors. + + OverRun - The last byte is not on a sector boundary. + +--*/ + +#include "DiskIo.h" + +// +// Prototypes +// Driver model protocol interface +// +EFI_STATUS +EFIAPI +DiskIoDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +DiskIoDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +DiskIoDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +// +// Disk I/O Protocol Interface +// +EFI_STATUS +EFIAPI +DiskIoReadDisk ( + IN EFI_DISK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN UINT64 Offset, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +EFI_STATUS +EFIAPI +DiskIoWriteDisk ( + IN EFI_DISK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN UINT64 Offset, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +EFI_DRIVER_BINDING_PROTOCOL gDiskIoDriverBinding = { + DiskIoDriverBindingSupported, + DiskIoDriverBindingStart, + DiskIoDriverBindingStop, + 0x10, + NULL, + NULL +}; + +DISK_IO_PRIVATE_DATA gDiskIoPrivateDataTemplate = { + DISK_IO_PRIVATE_DATA_SIGNATURE, + { + EFI_DISK_IO_PROTOCOL_REVISION, + DiskIoReadDisk, + DiskIoWriteDisk + }, + NULL +}; + +EFI_STATUS +EFIAPI +DiskIoDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +/*++ + + Routine Description: + Test to see if this driver supports ControllerHandle. Any ControllerHandle + than contains a BlockIo 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. + other - This driver does not support this device. + +--*/ +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlockIo; +/* + DEBUG_CODE_BEGIN + UINT32 Bar; + UINT32 Foo; + UINT32 HotPlug; + + // + // Get TYPE 0 + // + Bar = PcdGet32 (PciExpressBaseVersion); + DEBUG ((EFI_D_ERROR, "PciExpressBaseVersion = %08x\n", Bar)); + + // + // Get TYPE 1 + // + Foo = PcdGet32 (PciExpressBaseAddress); + DEBUG ((EFI_D_ERROR, "PciExpressBaseAddress = %08x\n", Foo)); + + // + // Set TYPE 1 + // + PcdSet32 (PciExpressBaseAddress, Foo + 1); + + // + // Get TYPE 1 + // + Foo = PcdGet32 (PciExpressBaseAddress); + DEBUG ((EFI_D_ERROR, "PciExpressBaseAddress = %08x\n", Foo)); + + // + // Get TYPE 2 + // + HotPlug = PcdGet32 (PciExpressBaseHotPlug); + DEBUG ((EFI_D_ERROR, "PciExpressHotPlug = %08x\n", HotPlug)); + + // + // Set TYPE 1 + // + PcdSet32 (PciExpressBaseHotPlug, HotPlug + 1); + + // + // Get TYPE 1 + // + HotPlug = PcdGet32 (PciExpressBaseHotPlug); + DEBUG ((EFI_D_ERROR, "PciExpressHotPlug = %08x\n", HotPlug)); + + DEBUG_CODE_END + + DEBUG_CODE_BEGIN + UINT32 MyVariable; + + if (ControllerHandle == NULL) { + MyVariable = 32 * (UINTN)This; + ControllerHandle = (EFI_HANDLE)MyVariable; + DEBUG ((EFI_D_ERROR, "DiskIoSupported-DebugCode. MyVariable = %08x\n", MyVariable)); + ASSERT (MyVariable != 32); + } + DEBUG_CODE_END +*/ + DEBUG ((EFI_D_ERROR, "DiskIoSupported\n")); + +// Io8Or (0x400, 1); +// Io8And (0x400, 1); +// Io8AndThenOr (0x400, 1, 2); + +// Mmio8Or (0xa0000000, 1); +// Mmio8And (0xa0000000, 1); +// Mmio8AndThenOr (0xa0000000, 1, 2); + +/* + PciRead8 (PCI_LIB_ADDRESS (1,2,3,4)); + PciRead16 (PCI_LIB_ADDRESS (1,2,3,4)); + PciRead32 (PCI_LIB_ADDRESS (1,2,3,4)); + + PciWrite8 (PCI_LIB_ADDRESS (1,2,3,4), 0xAA); + PciWrite16 (PCI_LIB_ADDRESS (1,2,3,4), 0xAA55); + PciWrite32 (PCI_LIB_ADDRESS (1,2,3,4), 0xAA55A55A); + + Pci8Or (PCI_LIB_ADDRESS (1,2,3,4), 0xAA); + Pci8And (PCI_LIB_ADDRESS (1,2,3,4), 0x55); + Pci8AndThenOr (PCI_LIB_ADDRESS (1,2,3,4), 0xAA, 0x55); + + Pci16Or (PCI_LIB_ADDRESS (1,2,3,4), 0xAA55); + Pci16And (PCI_LIB_ADDRESS (1,2,3,4), 0x55AA); + Pci16AndThenOr (PCI_LIB_ADDRESS (1,2,3,4), 0xAA55, 0x55AA); + + Pci32Or (PCI_LIB_ADDRESS (1,2,3,4), 0xAA55A55A); + Pci32And (PCI_LIB_ADDRESS (1,2,3,4), 0x55AA5AA5); + Pci32AndThenOr (PCI_LIB_ADDRESS (1,2,3,4), 0xAA555AA5, 0x55AAA55A); +*/ + // + // Open the IO Abstraction(s) needed to perform the supported test. + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlockIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Close the I/O Abstraction(s) used to perform the supported test. + // + gBS->CloseProtocol ( + ControllerHandle, + &gEfiBlockIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +DiskIoDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +/*++ + + Routine Description: + Start this driver on ControllerHandle by opening a Block IO protocol and + installing a Disk IO protocol on ControllerHandle. + + Arguments: + This - Protocol instance pointer. + ControllerHandle - Handle of device to bind driver to. + RemainingDevicePath - Not used, always produce all possible children. + + Returns: + EFI_SUCCESS - This driver is added to ControllerHandle. + EFI_ALREADY_STARTED - This driver is already running on ControllerHandle. + other - This driver does not support this device. + +--*/ +{ + EFI_STATUS Status; + DISK_IO_PRIVATE_DATA *Private; + + Private = NULL; + + DEBUG ((EFI_D_ERROR, "DiskIoStart\n")); + // + // Connect to the Block IO interface on ControllerHandle. + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiBlockIoProtocolGuid, + (VOID **) &gDiskIoPrivateDataTemplate.BlockIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Initialize the Disk IO device instance. + // + Private = AllocateCopyPool (sizeof (DISK_IO_PRIVATE_DATA), &gDiskIoPrivateDataTemplate); + if (Private == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + // + // Install protocol interfaces for the Disk IO device. + // + Status = gBS->InstallProtocolInterface ( + &ControllerHandle, + &gEfiDiskIoProtocolGuid, + EFI_NATIVE_INTERFACE, + &Private->DiskIo + ); + +ErrorExit: + if (EFI_ERROR (Status)) { + + if (Private != NULL) { + gBS->FreePool (Private); + } + + gBS->CloseProtocol ( + ControllerHandle, + &gEfiBlockIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + } + + return Status; +} + +EFI_STATUS +EFIAPI +DiskIoDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + + Routine Description: + Stop this driver on ControllerHandle by removing Disk IO protocol and closing + the Block IO protocol on ControllerHandle. + + Arguments: + This - Protocol instance pointer. + ControllerHandle - Handle of device to stop driver on. + NumberOfChildren - Not used. + ChildHandleBuffer - Not used. + + Returns: + EFI_SUCCESS - This driver is removed ControllerHandle. + other - This driver was not removed from this device. + EFI_UNSUPPORTED + +--*/ +{ + EFI_STATUS Status; + EFI_DISK_IO_PROTOCOL *DiskIo; + DISK_IO_PRIVATE_DATA *Private; + + DEBUG ((EFI_D_ERROR, "DiskIoStop\n")); + // + // Get our context back. + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDiskIoProtocolGuid, + (VOID **) &DiskIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Private = DISK_IO_PRIVATE_DATA_FROM_THIS (DiskIo); + + Status = gBS->UninstallProtocolInterface ( + ControllerHandle, + &gEfiDiskIoProtocolGuid, + &Private->DiskIo + ); + if (!EFI_ERROR (Status)) { + + Status = gBS->CloseProtocol ( + ControllerHandle, + &gEfiBlockIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + } + + if (!EFI_ERROR (Status)) { + gBS->FreePool (Private); + } + + return Status; +} + +EFI_STATUS +EFIAPI +DiskIoReadDisk ( + IN EFI_DISK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN UINT64 Offset, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +/*++ + + Routine Description: + Read BufferSize bytes from Offset into Buffer. + + Reads may support reads that are not aligned on + sector boundaries. There are three cases: + + UnderRun - The first byte is not on a sector boundary or the read request is + less than a sector in length. + + Aligned - A read of N contiguous sectors. + + OverRun - The last byte is not on a sector boundary. + + + Arguments: + This - Protocol instance pointer. + MediaId - Id of the media, changes every time the media is replaced. + Offset - The starting byte offset to read from. + BufferSize - Size of Buffer. + 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_CHNAGED - The MediaId does not matched the current device. + EFI_INVALID_PARAMETER - The read request contains device addresses that are not + valid for the device. + EFI_OUT_OF_RESOURCES + +--*/ +{ + EFI_STATUS Status; + DISK_IO_PRIVATE_DATA *Private; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_BLOCK_IO_MEDIA *Media; + UINT32 BlockSize; + UINT64 Lba; + UINT64 OverRunLba; + UINT32 UnderRun; + UINT32 OverRun; + BOOLEAN TransactionComplete; + UINTN WorkingBufferSize; + UINT8 *WorkingBuffer; + UINTN Length; + UINT8 *Data; + UINT8 *PreData; + UINTN IsBufferAligned; + UINTN DataBufferSize; + BOOLEAN LastRead; + + DEBUG ((EFI_D_ERROR, "DiskIoReadDisk\n")); + + Private = DISK_IO_PRIVATE_DATA_FROM_THIS (This); + + BlockIo = Private->BlockIo; + Media = BlockIo->Media; + BlockSize = Media->BlockSize; + + if (Media->MediaId != MediaId) { + return EFI_MEDIA_CHANGED; + } + + WorkingBuffer = Buffer; + WorkingBufferSize = BufferSize; + + // + // Allocate a temporary buffer for operation + // + DataBufferSize = BlockSize * DATA_BUFFER_BLOCK_NUM; + + if (Media->IoAlign > 1) { + PreData = AllocatePool (DataBufferSize + Media->IoAlign); + Data = PreData - ((UINTN) PreData & (Media->IoAlign - 1)) + Media->IoAlign; + } else { + PreData = AllocatePool (DataBufferSize); + Data = PreData; + } + + if (PreData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Lba = DivU64x32Remainder (Offset, BlockSize, &UnderRun); + + Length = BlockSize - UnderRun; + TransactionComplete = FALSE; + + Status = EFI_SUCCESS; + if (UnderRun != 0) { + // + // Offset starts in the middle of an Lba, so read the entire block. + // + Status = BlockIo->ReadBlocks ( + BlockIo, + MediaId, + Lba, + BlockSize, + Data + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + if (Length > BufferSize) { + Length = BufferSize; + TransactionComplete = TRUE; + } + + CopyMem (WorkingBuffer, Data + UnderRun, Length); + + WorkingBuffer += Length; + + WorkingBufferSize -= Length; + if (WorkingBufferSize == 0) { + goto Done; + } + + Lba += 1; + } + + OverRunLba = Lba + DivU64x32Remainder (WorkingBufferSize, BlockSize, &OverRun); + + if (!TransactionComplete && WorkingBufferSize >= BlockSize) { + // + // If the DiskIo maps directly to a BlockIo device do the read. + // + if (OverRun != 0) { + WorkingBufferSize -= OverRun; + } + // + // Check buffer alignment + // + IsBufferAligned = (UINTN) WorkingBuffer & (UINTN) (Media->IoAlign - 1); + + if (Media->IoAlign <= 1 || IsBufferAligned == 0) { + // + // Alignment is satisfied, so read them together + // + Status = BlockIo->ReadBlocks ( + BlockIo, + MediaId, + Lba, + WorkingBufferSize, + WorkingBuffer + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + WorkingBuffer += WorkingBufferSize; + + } else { + // + // Use the allocated buffer instead of the original buffer + // to avoid alignment issue. + // Here, the allocated buffer (8-byte align) can satisfy the alignment + // + LastRead = FALSE; + do { + if (WorkingBufferSize <= DataBufferSize) { + // + // It is the last calling to readblocks in this loop + // + DataBufferSize = WorkingBufferSize; + LastRead = TRUE; + } + + Status = BlockIo->ReadBlocks ( + BlockIo, + MediaId, + Lba, + DataBufferSize, + Data + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + CopyMem (WorkingBuffer, Data, DataBufferSize); + WorkingBufferSize -= DataBufferSize; + WorkingBuffer += DataBufferSize; + Lba += DATA_BUFFER_BLOCK_NUM; + } while (!LastRead); + } + } + + if (!TransactionComplete && OverRun != 0) { + // + // Last read is not a complete block. + // + Status = BlockIo->ReadBlocks ( + BlockIo, + MediaId, + OverRunLba, + BlockSize, + Data + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + CopyMem (WorkingBuffer, Data, OverRun); + } + +Done: + if (PreData != NULL) { + gBS->FreePool (PreData); + } + + return Status; +} + +EFI_STATUS +EFIAPI +DiskIoWriteDisk ( + IN EFI_DISK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN UINT64 Offset, + IN UINTN BufferSize, + IN VOID *Buffer + ) +/*++ + + Routine Description: + Read BufferSize bytes from Offset into Buffer. + + Writes may require a read modify write to support writes that are not + aligned on sector boundaries. There are three cases: + + UnderRun - The first byte is not on a sector boundary or the write request + is less than a sector in length. Read modify write is required. + + Aligned - A write of N contiguous sectors. + + OverRun - The last byte is not on a sector boundary. Read modified write + required. + + Arguments: + This - Protocol instance pointer. + MediaId - Id of the media, changes every time the media is replaced. + Offset - The starting byte offset to read from. + BufferSize - Size of Buffer. + 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_INVALID_PARAMETER - The write request contains device addresses that are not + valid for the device. + EFI_OUT_OF_RESOURCES + +--*/ +{ + EFI_STATUS Status; + DISK_IO_PRIVATE_DATA *Private; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_BLOCK_IO_MEDIA *Media; + UINT32 BlockSize; + UINT64 Lba; + UINT64 OverRunLba; + UINT32 UnderRun; + UINT32 OverRun; + BOOLEAN TransactionComplete; + UINTN WorkingBufferSize; + UINT8 *WorkingBuffer; + UINTN Length; + UINT8 *Data; + UINT8 *PreData; + UINTN IsBufferAligned; + UINTN DataBufferSize; + BOOLEAN LastWrite; + + DEBUG ((EFI_D_ERROR, "DiskIoWriteDisk\n")); + + Private = DISK_IO_PRIVATE_DATA_FROM_THIS (This); + + BlockIo = Private->BlockIo; + Media = BlockIo->Media; + BlockSize = Media->BlockSize; + + if (Media->ReadOnly) { + return EFI_WRITE_PROTECTED; + } + + if (Media->MediaId != MediaId) { + return EFI_MEDIA_CHANGED; + } + + DataBufferSize = BlockSize * DATA_BUFFER_BLOCK_NUM; + + if (Media->IoAlign > 1) { + PreData = AllocatePool (DataBufferSize + Media->IoAlign); + Data = PreData - ((UINTN) PreData & (Media->IoAlign - 1)) + Media->IoAlign; + } else { + PreData = AllocatePool (DataBufferSize); + Data = PreData; + } + + if (PreData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + WorkingBuffer = Buffer; + WorkingBufferSize = BufferSize; + + Lba = DivU64x32Remainder (Offset, BlockSize, &UnderRun); + + Length = BlockSize - UnderRun; + TransactionComplete = FALSE; + + Status = EFI_SUCCESS; + if (UnderRun != 0) { + // + // Offset starts in the middle of an Lba, so do read modify write. + // + Status = BlockIo->ReadBlocks ( + BlockIo, + MediaId, + Lba, + BlockSize, + Data + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + if (Length > BufferSize) { + Length = BufferSize; + TransactionComplete = TRUE; + } + + CopyMem (Data + UnderRun, WorkingBuffer, Length); + + Status = BlockIo->WriteBlocks ( + BlockIo, + MediaId, + Lba, + BlockSize, + Data + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + WorkingBuffer += Length; + WorkingBufferSize -= Length; + if (WorkingBufferSize == 0) { + goto Done; + } + + Lba += 1; + } + + OverRunLba = Lba + DivU64x32Remainder (WorkingBufferSize, BlockSize, &OverRun); + + if (!TransactionComplete && WorkingBufferSize >= BlockSize) { + // + // If the DiskIo maps directly to a BlockIo device do the write. + // + if (OverRun != 0) { + WorkingBufferSize -= OverRun; + } + // + // Check buffer alignment + // + IsBufferAligned = (UINTN) WorkingBuffer & (UINTN) (Media->IoAlign - 1); + + if (Media->IoAlign <= 1 || IsBufferAligned == 0) { + // + // Alignment is satisfied, so write them together + // + Status = BlockIo->WriteBlocks ( + BlockIo, + MediaId, + Lba, + WorkingBufferSize, + WorkingBuffer + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + WorkingBuffer += WorkingBufferSize; + + } else { + // + // The buffer parameter is not aligned with the request + // So use the allocated instead. + // It can fit almost all the cases. + // + LastWrite = FALSE; + do { + if (WorkingBufferSize <= DataBufferSize) { + // + // It is the last calling to writeblocks in this loop + // + DataBufferSize = WorkingBufferSize; + LastWrite = TRUE; + } + + CopyMem (Data, WorkingBuffer, DataBufferSize); + Status = BlockIo->WriteBlocks ( + BlockIo, + MediaId, + Lba, + DataBufferSize, + Data + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + WorkingBufferSize -= DataBufferSize; + WorkingBuffer += DataBufferSize; + Lba += DATA_BUFFER_BLOCK_NUM; + } while (!LastWrite); + } + } + + if (!TransactionComplete && OverRun != 0) { + // + // Last bit is not a complete block, so do a read modify write. + // + Status = BlockIo->ReadBlocks ( + BlockIo, + MediaId, + OverRunLba, + BlockSize, + Data + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + CopyMem (Data, WorkingBuffer, OverRun); + + Status = BlockIo->WriteBlocks ( + BlockIo, + MediaId, + OverRunLba, + BlockSize, + Data + ); + if (EFI_ERROR (Status)) { + goto Done; + } + } + +Done: + if (PreData != NULL) { + gBS->FreePool (PreData); + } + + return Status; +} diff --git a/EdkModulePkg/Universal/Disk/DiskIo/Dxe/diskio.h b/EdkModulePkg/Universal/Disk/DiskIo/Dxe/diskio.h new file mode 100644 index 0000000..39d8766 --- /dev/null +++ b/EdkModulePkg/Universal/Disk/DiskIo/Dxe/diskio.h @@ -0,0 +1,44 @@ +/*++ + +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: + + DiskIo.h + +Abstract: + Private Data definition for Disk IO driver + +--*/ + +#ifndef _DISK_IO_H +#define _DISK_IO_H + + + +#define DISK_IO_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('d', 's', 'k', 'I') + +#define DATA_BUFFER_BLOCK_NUM (64) + +typedef struct { + UINTN Signature; + EFI_DISK_IO_PROTOCOL DiskIo; + EFI_BLOCK_IO_PROTOCOL *BlockIo; +} DISK_IO_PRIVATE_DATA; + +#define DISK_IO_PRIVATE_DATA_FROM_THIS(a) CR (a, DISK_IO_PRIVATE_DATA, DiskIo, DISK_IO_PRIVATE_DATA_SIGNATURE) + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gDiskIoDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gDiskIoComponentName; + +#endif diff --git a/EdkModulePkg/Universal/Disk/DiskIoPartition/dxe/DiskIoPartition.mbd b/EdkModulePkg/Universal/Disk/DiskIoPartition/dxe/DiskIoPartition.mbd new file mode 100644 index 0000000..ed89f07 --- /dev/null +++ b/EdkModulePkg/Universal/Disk/DiskIoPartition/dxe/DiskIoPartition.mbd @@ -0,0 +1,42 @@ + + + + + DiskIoPartition + 854E153A-8AC8-40f4-A5A9-4C51F18CFB1B + 0 + FIX ME! + Copyright (c) 2004-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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + BaseLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + DxeMemoryAllocationLib + UefiDevicePathLib + + diff --git a/EdkModulePkg/Universal/Disk/DiskIoPartition/dxe/DiskIoPartition.msa b/EdkModulePkg/Universal/Disk/DiskIoPartition/dxe/DiskIoPartition.msa new file mode 100644 index 0000000..930f57b --- /dev/null +++ b/EdkModulePkg/Universal/Disk/DiskIoPartition/dxe/DiskIoPartition.msa @@ -0,0 +1,88 @@ + + + + + DiskIoPartition + UEFI_DRIVER + BS_DRIVER + 854E153A-8AC8-40f4-A5A9-4C51F18CFB1B + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + BaseLib + UefiLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + DevicePathLib + + + ..\..\DiskIo\Dxe\diskio.c + ..\..\DiskIo\Dxe\diskio.h + ..\..\DiskIo\Dxe\ComponentName.c + ..\..\Partition\Dxe\Partition.h + ..\..\Partition\Dxe\ElTorito.h + ..\..\Partition\Dxe\Gpt.h + ..\..\Partition\Dxe\Mbr.h + ..\..\Partition\Dxe\Partition.c + ..\..\Partition\Dxe\Eltorito.c + ..\..\Partition\Dxe\Gpt.c + ..\..\Partition\Dxe\Mbr.c + ..\..\Partition\Dxe\ComponentName.c + + + MdePkg + + + BlockIo + DiskIo + DevicePath + + + + PartTypeSystemPart + + + PartTypeUnused + + + + + + + + gPartitionDriverBinding + gPartitionComponentName + + + gDiskIoDriverBinding + gDiskIoComponentName + + + diff --git a/EdkModulePkg/Universal/Disk/DiskIoPartition/dxe/build.xml b/EdkModulePkg/Universal/Disk/DiskIoPartition/dxe/build.xml new file mode 100644 index 0000000..4b1c1f8 --- /dev/null +++ b/EdkModulePkg/Universal/Disk/DiskIoPartition/dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/Disk/Partition/Dxe/ComponentName.c b/EdkModulePkg/Universal/Disk/Partition/Dxe/ComponentName.c new file mode 100644 index 0000000..3821690 --- /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 0000000..27beba1 --- /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 0000000..f085315 --- /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 0000000..35ff1a8 --- /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 0000000..fbcd93d --- /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 0000000..07e3cbe --- /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 0000000..c0022c8 --- /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 0000000..59e33b2 --- /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 0000000..de6fbf1 --- /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 0000000..7be0d52 --- /dev/null +++ b/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.mbd @@ -0,0 +1,42 @@ + + + + + Partition + 1FA1F39E-FEFF-4aae-BD7B-38A070A3B609 + 0 + FIX ME! + Copyright (c) 2004-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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + BaseLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeMemoryAllocationLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + UefiDevicePathLib + + diff --git a/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.msa b/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.msa new file mode 100644 index 0000000..a4eed02 --- /dev/null +++ b/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.msa @@ -0,0 +1,81 @@ + + + + + Partition + UEFI_DRIVER + BS_DRIVER + 1FA1F39E-FEFF-4aae-BD7B-38A070A3B609 + 0 + Component description file for Partition module. + FIX ME! + Copyright (c) 2004-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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + BaseLib + UefiLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + DevicePathLib + + + Partition.h + ElTorito.h + Gpt.h + Mbr.h + Partition.c + Eltorito.c + Gpt.c + Mbr.c + ComponentName.c + + + MdePkg + + + BlockIo + DiskIo + DevicePath + + + + PartTypeSystemPart + + + PartTypeUnused + + + + + + + + gPartitionDriverBinding + gPartitionComponentName + + + diff --git a/EdkModulePkg/Universal/Disk/Partition/Dxe/build.xml b/EdkModulePkg/Universal/Disk/Partition/Dxe/build.xml new file mode 100644 index 0000000..ea4ea4e --- /dev/null +++ b/EdkModulePkg/Universal/Disk/Partition/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/English.mbd b/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/English.mbd new file mode 100644 index 0000000..46b51cf --- /dev/null +++ b/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/English.mbd @@ -0,0 +1,38 @@ + + + + + English + CD3BAFB6-50FB-4fe8-8E4E-AB74D2C1A600 + 0 + FIX ME! + Copyright (c) 2004-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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + BaseLib + UefiMemoryLib + UefiDriverEntryPoint + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + + diff --git a/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/English.msa b/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/English.msa new file mode 100644 index 0000000..9abe328 --- /dev/null +++ b/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/English.msa @@ -0,0 +1,53 @@ + + + + + English + UEFI_DRIVER + BS_DRIVER + CD3BAFB6-50FB-4fe8-8E4E-AB74D2C1A600 + 0 + Component description file for English module for unicode collation. + FIX ME! + Copyright (c) 2004-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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + DebugLib + UefiDriverEntryPoint + UefiBootServicesTableLib + + + UnicodeCollationEng.c + + + MdePkg + + + UnicodeCollation + + + + InitializeUnicodeCollationEng + + + diff --git a/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/UnicodeCollationEng.c b/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/UnicodeCollationEng.c new file mode 100644 index 0000000..f043f37 --- /dev/null +++ b/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/UnicodeCollationEng.c @@ -0,0 +1,478 @@ +/*++ + +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: + + UnicodeCollationEng.c + +Abstract: + + Unicode Collation Protocol (English) + +Revision History + +--*/ + +#include "UnicodeCollationEng.h" + +CHAR8 mEngUpperMap[0x100]; +CHAR8 mEngLowerMap[0x100]; +CHAR8 mEngInfoMap[0x100]; + +CHAR8 mOtherChars[] = { + '0', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '\\', + '.', + '_', + '^', + '$', + '~', + '!', + '#', + '%', + '&', + '-', + '{', + '}', + '(', + ')', + '@', + '`', + '\'', + '\0' +}; + +EFI_HANDLE mHandle = NULL; + +EFI_UNICODE_COLLATION_PROTOCOL UnicodeEng = { + EngStriColl, + EngMetaiMatch, + EngStrLwr, + EngStrUpr, + EngFatToStr, + EngStrToFat, + "eng" +}; + +// +// +// +EFI_STATUS +InitializeUnicodeCollationEng ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + Initializes the Unicode Collation Driver + +Arguments: + + ImageHandle - + + SystemTable - + +Returns: + + EFI_SUCCESS + EFI_OUT_OF_RESOURCES + +--*/ +{ + UINTN Index; + UINTN Index2; + + // + // Initialize mapping tables for the supported languages + // + for (Index = 0; Index < 0x100; Index++) { + mEngUpperMap[Index] = (CHAR8) Index; + mEngLowerMap[Index] = (CHAR8) Index; + mEngInfoMap[Index] = 0; + + if ((Index >= 'a' && Index <= 'z') || (Index >= 0xe0 && Index <= 0xf6) || (Index >= 0xf8 && Index <= 0xfe)) { + + Index2 = Index - 0x20; + mEngUpperMap[Index] = (CHAR8) Index2; + mEngLowerMap[Index2] = (CHAR8) Index; + + mEngInfoMap[Index] |= CHAR_FAT_VALID; + mEngInfoMap[Index2] |= CHAR_FAT_VALID; + } + } + + for (Index = 0; mOtherChars[Index]; Index++) { + Index2 = mOtherChars[Index]; + mEngInfoMap[Index2] |= CHAR_FAT_VALID; + } + // + // Create a handle for the device + // + return gBS->InstallProtocolInterface ( + &mHandle, + &gEfiUnicodeCollationProtocolGuid, + EFI_NATIVE_INTERFACE, + &UnicodeEng + ); +} + +INTN +EFIAPI +EngStriColl ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN CHAR16 *s1, + IN CHAR16 *s2 + ) +/*++ + +Routine Description: + + Performs a case-insensitive comparison of two Null-terminated Unicode strings. + +Arguments: + + This + s1 + s2 + +Returns: + +--*/ +{ + while (*s1) { + if (ToUpper (*s1) != ToUpper (*s2)) { + break; + } + + s1 += 1; + s2 += 1; + } + + return ToUpper (*s1) - ToUpper (*s2); +} + +VOID +EFIAPI +EngStrLwr ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN OUT CHAR16 *Str + ) +/*++ + +Routine Description: + + Converts all the Unicode characters in a Null-terminated Unicode string + to lower case Unicode characters. + +Arguments: + + This - A pointer to the EFI_UNICODE_COLLATION_PROTOCOL instance. + Str1 - A pointer to a Null-terminated Unicode string. + Str2 - A pointer to a Null-terminated Unicode string. + +Returns: + + 0 - s1 is equivalent to s2. + > 0 - s1 is lexically greater than s2. + < 0 - s1 is lexically less than s2. + +--*/ +{ + while (*Str) { + *Str = ToLower (*Str); + Str += 1; + } +} + +VOID +EFIAPI +EngStrUpr ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN OUT CHAR16 *Str + ) +/*++ + +Routine Description: + + Converts all the Unicode characters in a Null-terminated + Unicode string to upper case Unicode characters. + +Arguments: + This + Str + +Returns: + None + +--*/ +{ + while (*Str) { + *Str = ToUpper (*Str); + Str += 1; + } +} + +BOOLEAN +EFIAPI +EngMetaiMatch ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN CHAR16 *String, + IN CHAR16 *Pattern + ) +/*++ + +Routine Description: + + Performs a case-insensitive comparison between a Null-terminated + Unicode pattern string and a Null-terminated Unicode string. + + The pattern string can use the '?' wildcard to match any character, + and the '*' wildcard to match any sub-string. + +Arguments: + + This - A pointer to the EFI_UNICODE_COLLATION_PROTOCOL instance. + String - A pointer to a Null-terminated Unicode string. + Pattern - A pointer to a Null-terminated Unicode pattern string. + +Returns: + + TRUE - Pattern was found in String. + FALSE - Pattern was not found in String. + +--*/ +{ + CHAR16 CharC; + CHAR16 CharP; + CHAR16 Index3; + + for (;;) { + CharP = *Pattern; + Pattern += 1; + + switch (CharP) { + case 0: + // + // End of pattern. If end of string, TRUE match + // + if (*String) { + return FALSE; + } else { + return TRUE; + } + + case '*': + // + // Match zero or more chars + // + while (*String) { + if (EngMetaiMatch (This, String, Pattern)) { + return TRUE; + } + + String += 1; + } + + return EngMetaiMatch (This, String, Pattern); + + case '?': + // + // Match any one char + // + if (!*String) { + return FALSE; + } + + String += 1; + break; + + case '[': + // + // Match char set + // + CharC = *String; + if (!CharC) { + // + // syntax problem + // + return FALSE; + } + + Index3 = 0; + CharP = *Pattern++; + while (CharP) { + if (CharP == ']') { + return FALSE; + } + + if (CharP == '-') { + // + // if range of chars, get high range + // + CharP = *Pattern; + if (CharP == 0 || CharP == ']') { + // + // syntax problem + // + return FALSE; + } + + if (ToUpper (CharC) >= ToUpper (Index3) && ToUpper (CharC) <= ToUpper (CharP)) { + // + // if in range, it's a match + // + break; + } + } + + Index3 = CharP; + if (ToUpper (CharC) == ToUpper (CharP)) { + // + // if char matches + // + break; + } + + CharP = *Pattern++; + } + // + // skip to end of match char set + // + while (CharP && CharP != ']') { + CharP = *Pattern; + Pattern += 1; + } + + String += 1; + break; + + default: + CharC = *String; + if (ToUpper (CharC) != ToUpper (CharP)) { + return FALSE; + } + + String += 1; + break; + } + } +} + +VOID +EFIAPI +EngFatToStr ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN UINTN FatSize, + IN CHAR8 *Fat, + OUT CHAR16 *String + ) +/*++ + +Routine Description: + + Converts an 8.3 FAT file name using an OEM character set + to a Null-terminated Unicode string. + + BUGBUG: Function has to expand DBCS FAT chars, currently not. + +Arguments: + This + FatSize + Fat + String + +Returns: + +--*/ +{ + // + // No DBCS issues, just expand and add null terminate to end of string + // + while (*Fat && FatSize) { + *String = *Fat; + String += 1; + Fat += 1; + FatSize -= 1; + } + + *String = 0; +} + +BOOLEAN +EFIAPI +EngStrToFat ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN CHAR16 *String, + IN UINTN FatSize, + OUT CHAR8 *Fat + ) +/*++ + +Routine Description: + + Converts a Null-terminated Unicode string to legal characters + in a FAT filename using an OEM character set. + + Functions has to crunch string to a fat string. Replacing + any chars that can't be represented in the fat name. + +Arguments: + This + String + FatSize + Fat + +Returns: + TRUE + FALSE +--*/ +{ + BOOLEAN SpecialCharExist; + + SpecialCharExist = FALSE; + while (*String && FatSize) { + // + // Skip '.' or ' ' when making a fat name + // + if (*String != '.' && *String != ' ') { + // + // If this is a valid fat char, move it. + // Otherwise, move a '_' and flag the fact that the name needs an Lfn + // + if (*String < 0x100 && (mEngInfoMap[*String] & CHAR_FAT_VALID)) { + *Fat = mEngUpperMap[*String]; + } else { + *Fat = '_'; + SpecialCharExist = TRUE; + } + + Fat += 1; + FatSize -= 1; + } + + String += 1; + } + // + // Do not terminate that fat string + // + return SpecialCharExist; +} diff --git a/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/UnicodeCollationEng.h b/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/UnicodeCollationEng.h new file mode 100644 index 0000000..6bd5479 --- /dev/null +++ b/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/UnicodeCollationEng.h @@ -0,0 +1,102 @@ +/*++ + +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: + + UnicodeCollationEng.h + +Abstract: + + Head file for Unicode Collation Protocol (English) + +Revision History + +--*/ + +#ifndef _UNICODE_COLLATION_ENG_H +#define _UNICODE_COLLATION_ENG_H + + + +// +// Defines +// +#define CHAR_FAT_VALID 0x01 + +#define ToUpper(a) (CHAR16) (a <= 0xFF ? mEngUpperMap[a] : a) +#define ToLower(a) (CHAR16) (a <= 0xFF ? mEngLowerMap[a] : a) + +// +// Prototypes +// +INTN +EFIAPI +EngStriColl ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN CHAR16 *s1, + IN CHAR16 *s2 + ) +; + +BOOLEAN +EFIAPI +EngMetaiMatch ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN CHAR16 *String, + IN CHAR16 *Pattern + ) +; + +VOID +EFIAPI +EngStrLwr ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN OUT CHAR16 *Str + ) +; + +VOID +EFIAPI +EngStrUpr ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN OUT CHAR16 *Str + ) +; + +VOID +EFIAPI +EngFatToStr ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN UINTN FatSize, + IN CHAR8 *Fat, + OUT CHAR16 *String + ) +; + +BOOLEAN +EFIAPI +EngStrToFat ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN CHAR16 *String, + IN UINTN FatSize, + OUT CHAR8 *Fat + ) +; + +EFI_STATUS +EFIAPI +InitializeUnicodeCollationEng ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +; + +#endif diff --git a/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/build.xml b/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/build.xml new file mode 100644 index 0000000..81fd524 --- /dev/null +++ b/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.1