X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FDisk%2FPartitionDxe%2FPartition.c;h=473e0913200ca0a4d1157c76df6c934edae13019;hb=f0f7140150f673f96602a83f16c4015ba2cc4fe1;hp=f6030e0897947c96ae98b0d35046b61d001cb893;hpb=8aafec2c13360f02152b4c19feb376c7c7cfd60d;p=mirror_edk2.git diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c b/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c index f6030e0897..473e091320 100644 --- a/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c +++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c @@ -4,14 +4,9 @@ of the raw block devices media. Currently "El Torito CD-ROM", UDF, Legacy MBR, and GPT partition schemes are supported. -Copyright (c) 2006 - 2017, 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. +Copyright (c) 2018 Qualcomm Datacenter Technologies, Inc. +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -26,8 +21,8 @@ EFI_DRIVER_BINDING_PROTOCOL gPartitionDriverBinding = { PartitionDriverBindingStart, PartitionDriverBindingStop, // - // Grub4Dos copies the BPB of the first partition to the MBR. If the - // DriverBindingStart() of the Fat driver gets run before that of Partition + // Grub4Dos copies the BPB of the first partition to the MBR. If the + // DriverBindingStart() of the Fat driver gets run before that of Partition // driver only the first partition can be recognized. // Let the driver binding version of Partition driver be higher than that of // Fat driver to make sure the DriverBindingStart() of the Partition driver @@ -39,13 +34,20 @@ EFI_DRIVER_BINDING_PROTOCOL gPartitionDriverBinding = { }; // -// Prioritized function list to detect partition table. +// Prioritized function list to detect partition table. +// Refer to UEFI Spec 13.3.2 Partition Discovery, the block device +// should be scanned in below order: +// 1. GPT +// 2. ISO 9660 (El Torito) (or UDF) +// 3. MBR +// 4. no partiton found +// Note: UDF is using a same method as booting from CD-ROM, so put it along +// with CD-ROM check. // PARTITION_DETECT_ROUTINE mPartitionDetectRoutineTable[] = { PartitionInstallGptChildHandles, - PartitionInstallElToritoChildHandles, - PartitionInstallMbrChildHandles, PartitionInstallUdfChildHandles, + PartitionInstallMbrChildHandles, NULL }; @@ -82,7 +84,7 @@ PartitionDriverBindingSupported ( // if (RemainingDevicePath != NULL) { // - // Check if RemainingDevicePath is the End of Device Path Node, + // Check if RemainingDevicePath is the End of Device Path Node, // if yes, go on checking other conditions // if (!IsDevicePathEnd (RemainingDevicePath)) { @@ -205,13 +207,13 @@ PartitionDriverBindingStart ( EFI_TPL OldTpl; BlockIo2 = NULL; - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); // // Check RemainingDevicePath validation // if (RemainingDevicePath != NULL) { // - // Check if RemainingDevicePath is the End of Device Path Node, + // Check if RemainingDevicePath is the End of Device Path Node, // if yes, return EFI_SUCCESS // if (IsDevicePathEnd (RemainingDevicePath)) { @@ -306,9 +308,9 @@ PartitionDriverBindingStart ( if (BlockIo->Media->MediaPresent || (BlockIo->Media->RemovableMedia && !BlockIo->Media->LogicalPartition)) { // - // Try for GPT, then El Torito, then UDF, 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. + // Try for GPT, then legacy MBR partition types, and then UDF and El Torito. + // If the media supports a given partition type install child handles to + // represent the partitions described by the media. // Routine = &mPartitionDetectRoutineTable[0]; while (*Routine != NULL) { @@ -333,12 +335,12 @@ PartitionDriverBindingStart ( // driver. So don't try to close them. Otherwise, we will break the dependency // between the controller and the driver set up before. // - // In the case that when the media changes on a device it will Reinstall the + // In the case that when the media changes on a device it will Reinstall the // BlockIo interaface. This will cause a call to our Stop(), and a subsequent // reentrant call to our Start() successfully. We should leave the device open // when this happen. The "media change" case includes either the status is - // EFI_MEDIA_CHANGED or it is a "media" to "no media" change. - // + // EFI_MEDIA_CHANGED or it is a "media" to "no media" change. + // if (EFI_ERROR (Status) && !EFI_ERROR (OpenStatus) && Status != EFI_MEDIA_CHANGED && @@ -351,7 +353,7 @@ PartitionDriverBindingStart ( ); // // Close Parent DiskIo2 if has. - // + // gBS->CloseProtocol ( ControllerHandle, &gEfiDiskIo2ProtocolGuid, @@ -402,6 +404,7 @@ PartitionDriverBindingStop ( BOOLEAN AllChildrenStopped; PARTITION_PRIVATE_DATA *Private; EFI_DISK_IO_PROTOCOL *DiskIo; + EFI_GUID *TypeGuid; BlockIo = NULL; BlockIo2 = NULL; @@ -429,7 +432,7 @@ PartitionDriverBindingStop ( ); // // Close Parent BlockIO2 if has. - // + // gBS->CloseProtocol ( ControllerHandle, &gEfiDiskIo2ProtocolGuid, @@ -466,7 +469,7 @@ PartitionDriverBindingStop ( This->DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); + ); Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (BlockIo); @@ -494,6 +497,13 @@ PartitionDriverBindingStop ( This->DriverBindingHandle, ChildHandleBuffer[Index] ); + + if (IsZeroGuid (&Private->TypeGuid)) { + TypeGuid = NULL; + } else { + TypeGuid = &Private->TypeGuid; + } + // // All Software protocols have be freed from the handle so remove it. // Remove the BlockIo Protocol if has. @@ -517,7 +527,7 @@ PartitionDriverBindingStop ( &Private->BlockIo2, &gEfiPartitionInfoProtocolGuid, &Private->PartitionInfo, - Private->EspGuid, + TypeGuid, NULL, NULL ); @@ -531,7 +541,7 @@ PartitionDriverBindingStop ( &Private->BlockIo, &gEfiPartitionInfoProtocolGuid, &Private->PartitionInfo, - Private->EspGuid, + TypeGuid, NULL, NULL ); @@ -778,11 +788,15 @@ ProbeMediaStatusEx ( ) { EFI_STATUS Status; + UINT8 Buffer[1]; // - // Read 1 byte from offset 0 but passing NULL as buffer pointer + // Read 1 byte from offset 0 to check if the MediaId is still valid. + // The reading operation is synchronious thus it is not worth it to + // allocate a buffer from the pool. The destination buffer for the + // data is in the stack. // - Status = DiskIo2->ReadDiskEx (DiskIo2, MediaId, 0, NULL, 1, NULL); + Status = DiskIo2->ReadDiskEx (DiskIo2, MediaId, 0, NULL, 1, (VOID*)Buffer); if ((Status == EFI_NO_MEDIA) || (Status == EFI_MEDIA_CHANGED)) { return Status; } @@ -881,7 +895,7 @@ PartitionCreateAccessTask ( /** Read BufferSize bytes from Lba into Buffer. - + This function reads the requested number of blocks from the device. All the blocks are read, or an error is returned. If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_or EFI_MEDIA_CHANGED is returned and @@ -889,13 +903,13 @@ PartitionCreateAccessTask ( not be signaled. @param[in] This Indicates a pointer to the calling context. - @param[in] MediaId Id of the media, changes every time the media is + @param[in] MediaId Id of the media, changes every time the media is replaced. @param[in] Lba The starting Logical Block Address to read from. - @param[in, out] Token A pointer to the token associated with the transaction. - @param[in] BufferSize Size of Buffer, must be a multiple of device block size. - @param[out] Buffer A pointer to the destination buffer for the data. The - caller is responsible for either having implicit or + @param[in, out] Token A pointer to the token associated with the transaction. + @param[in] BufferSize Size of Buffer, must be a multiple of device block size. + @param[out] Buffer A pointer to the destination buffer for the data. The + caller is responsible for either having implicit or explicit ownership of the buffer. @retval EFI_SUCCESS The read request was queued if Token->Event is @@ -907,7 +921,7 @@ PartitionCreateAccessTask ( @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the intrinsic block size of the device. - @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, or the buffer is not on proper alignment. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. @@ -982,7 +996,7 @@ PartitionReadBlocksEx ( @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device. @retval EFI_DEVICE_ERROR The device reported an error while performing the write. @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device. - @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, + @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, or the buffer is not on proper alignment. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. @@ -1014,7 +1028,7 @@ PartitionWriteBlocksEx ( if (Offset + BufferSize > Private->End) { return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_INVALID_PARAMETER); } - + if ((Token != NULL) && (Token->Event != NULL)) { Task = PartitionCreateAccessTask (Token); if (Task == NULL) { @@ -1034,10 +1048,10 @@ PartitionWriteBlocksEx ( /** Flush the Block Device. - + If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED is returned and non-blocking I/O is being used, the Event associated with - this request will not be signaled. + this request will not be signaled. @param[in] This Indicates a pointer to the calling context. @param[in, out] Token A pointer to the token associated with the transaction @@ -1101,6 +1115,7 @@ PartitionFlushBlocksEx ( @param[in] Start Start Block. @param[in] End End Block. @param[in] BlockSize Child block size. + @param[in] TypeGuid Partition GUID Type. @retval EFI_SUCCESS A child handle was added. @retval other A child handle was not added. @@ -1119,7 +1134,8 @@ PartitionInstallChildHandle ( IN EFI_PARTITION_INFO_PROTOCOL *PartitionInfo, IN EFI_LBA Start, IN EFI_LBA End, - IN UINT32 BlockSize + IN UINT32 BlockSize, + IN EFI_GUID *TypeGuid ) { EFI_STATUS Status; @@ -1146,7 +1162,7 @@ PartitionInstallChildHandle ( // Set the BlockIO into Private Data. // Private->BlockIo.Revision = ParentBlockIo->Revision; - + Private->BlockIo.Media = &Private->Media; CopyMem (Private->BlockIo.Media, ParentBlockIo->Media, sizeof (EFI_BLOCK_IO_MEDIA)); @@ -1166,7 +1182,7 @@ PartitionInstallChildHandle ( Private->BlockIo2.Reset = PartitionResetEx; Private->BlockIo2.ReadBlocksEx = PartitionReadBlocksEx; Private->BlockIo2.WriteBlocksEx = PartitionWriteBlocksEx; - Private->BlockIo2.FlushBlocksEx = PartitionFlushBlocksEx; + Private->BlockIo2.FlushBlocksEx = PartitionFlushBlocksEx; } Private->Media.IoAlign = 0; @@ -1213,17 +1229,14 @@ PartitionInstallChildHandle ( // CopyMem (&Private->PartitionInfo, PartitionInfo, sizeof (EFI_PARTITION_INFO_PROTOCOL)); - if ((PartitionInfo->System == 1)) { - Private->EspGuid = &gEfiPartTypeSystemPartGuid; + if (TypeGuid != NULL) { + CopyGuid(&(Private->TypeGuid), TypeGuid); } else { - // - // If NULL InstallMultipleProtocolInterfaces will ignore it. - // - Private->EspGuid = NULL; + ZeroMem ((VOID *)&(Private->TypeGuid), sizeof (EFI_GUID)); } // - // Create the new handle. + // Create the new handle. // Private->Handle = NULL; if (Private->DiskIo2 != NULL) { @@ -1237,11 +1250,11 @@ PartitionInstallChildHandle ( &Private->BlockIo2, &gEfiPartitionInfoProtocolGuid, &Private->PartitionInfo, - Private->EspGuid, + TypeGuid, NULL, NULL ); - } else { + } else { Status = gBS->InstallMultipleProtocolInterfaces ( &Private->Handle, &gEfiDevicePathProtocolGuid, @@ -1250,7 +1263,7 @@ PartitionInstallChildHandle ( &Private->BlockIo, &gEfiPartitionInfoProtocolGuid, &Private->PartitionInfo, - Private->EspGuid, + TypeGuid, NULL, NULL ); @@ -1271,6 +1284,15 @@ PartitionInstallChildHandle ( } else { FreePool (Private->DevicePath); FreePool (Private); + + // + // if the Status == EFI_ALREADY_STARTED, it means the child handles + // are already installed. So return EFI_SUCCESS to avoid do the next + // partition type check. + // + if (Status == EFI_ALREADY_STARTED) { + Status = EFI_SUCCESS; + } } return Status; @@ -1280,9 +1302,9 @@ PartitionInstallChildHandle ( /** The user Entry Point for module Partition. The user code starts with this function. - @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] ImageHandle The firmware allocated handle for the EFI image. @param[in] SystemTable A pointer to the EFI System Table. - + @retval EFI_SUCCESS The entry point is executed successfully. @retval other Some error occurs when executing this entry point.