--- /dev/null
+/**@file\r
+\r
+Copyright (c) 2004 - 2009, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php \r
+ \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+bbe\r
+**/\r
+\r
+#include "EmuBlockIo.h"\r
+\r
+\r
+/**\r
+ Reset the block device hardware.\r
+\r
+ @param[in] This Indicates a pointer to the calling context.\r
+ @param[in] ExtendedVerification Indicates that the driver may perform a more\r
+ exhausive verfication operation of the device\r
+ during reset.\r
+\r
+ @retval EFI_SUCCESS The device was reset.\r
+ @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
+ not be reset.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EmuBlockIo2Reset (\r
+ IN EFI_BLOCK_IO2_PROTOCOL *This,\r
+ IN BOOLEAN ExtendedVerification\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EMU_BLOCK_IO_PRIVATE *Private;\r
+ EFI_TPL OldTpl;\r
+\r
+ Private = EMU_BLOCK_IO2_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+ Status = Private->Io->Reset (Private->Io, ExtendedVerification);\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Read BufferSize bytes from Lba into Buffer.\r
+ \r
+ This function reads the requested number of blocks from the device. All the\r
+ blocks are read, or an error is returned.\r
+ If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_or EFI_MEDIA_CHANGED is returned and\r
+ non-blocking I/O is being used, the Event associated with this request will\r
+ not be signaled.\r
+\r
+ @param[in] This Indicates a pointer to the calling context.\r
+ @param[in] MediaId Id of the media, changes every time the media is \r
+ replaced.\r
+ @param[in] Lba The starting Logical Block Address to read from.\r
+ @param[in, out] Token A pointer to the token associated with the transaction.\r
+ @param[in] BufferSize Size of Buffer, must be a multiple of device block size. \r
+ @param[out] Buffer A pointer to the destination buffer for the data. The \r
+ caller is responsible for either having implicit or \r
+ explicit ownership of the buffer.\r
+\r
+ @retval EFI_SUCCESS The read request was queued if Token->Event is\r
+ not NULL.The data was read correctly from the\r
+ device if the Token->Event is NULL.\r
+ @retval EFI_DEVICE_ERROR The device reported an error while performing\r
+ the read.\r
+ @retval EFI_NO_MEDIA There is no media in the device.\r
+ @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
+ @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the\r
+ intrinsic block size of the device.\r
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, \r
+ or the buffer is not on proper alignment.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack\r
+ of resources.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EmuBlockIo2ReadBlocksEx (\r
+ IN EFI_BLOCK_IO2_PROTOCOL *This,\r
+ IN UINT32 MediaId,\r
+ IN EFI_LBA LBA,\r
+ IN OUT EFI_BLOCK_IO2_TOKEN *Token,\r
+ IN UINTN BufferSize,\r
+ OUT VOID *Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EMU_BLOCK_IO_PRIVATE *Private;\r
+ EFI_TPL OldTpl;\r
+\r
+ Private = EMU_BLOCK_IO2_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+ Status = Private->Io->ReadBlocks (Private->Io, MediaId, LBA, Token, BufferSize, Buffer);\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Write BufferSize bytes from Lba into Buffer.\r
+\r
+ This function writes the requested number of blocks to the device. All blocks\r
+ are written, or an error is returned.If EFI_DEVICE_ERROR, EFI_NO_MEDIA,\r
+ EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED is returned and non-blocking I/O is\r
+ being used, the Event associated with this request will not be signaled.\r
+\r
+ @param[in] This Indicates a pointer to the calling context.\r
+ @param[in] MediaId The media ID that the write request is for.\r
+ @param[in] Lba The starting logical block address to be written. The\r
+ caller is responsible for writing to only legitimate\r
+ locations.\r
+ @param[in, out] Token A pointer to the token associated with the transaction.\r
+ @param[in] BufferSize Size of Buffer, must be a multiple of device block size.\r
+ @param[in] Buffer A pointer to the source buffer for the data.\r
+\r
+ @retval EFI_SUCCESS The write request was queued if Event is not NULL.\r
+ The data was written correctly to the device if\r
+ the Event is NULL.\r
+ @retval EFI_WRITE_PROTECTED The device can not be written to.\r
+ @retval EFI_NO_MEDIA There is no media in the device.\r
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.\r
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, \r
+ or the buffer is not on proper alignment.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack\r
+ of resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI \r
+EmuBlockIo2WriteBlocksEx (\r
+ IN EFI_BLOCK_IO2_PROTOCOL *This,\r
+ IN UINT32 MediaId,\r
+ IN EFI_LBA LBA,\r
+ IN OUT EFI_BLOCK_IO2_TOKEN *Token,\r
+ IN UINTN BufferSize,\r
+ IN VOID *Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EMU_BLOCK_IO_PRIVATE *Private;\r
+ EFI_TPL OldTpl;\r
+\r
+ Private = EMU_BLOCK_IO2_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+ Status = Private->Io->WriteBlocks (Private->Io, MediaId, LBA, Token, BufferSize, Buffer);\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
+}\r
+\r
+\r
+\r
+/**\r
+ Flush the Block Device.\r
+ \r
+ If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED\r
+ is returned and non-blocking I/O is being used, the Event associated with\r
+ this request will not be signaled. \r
+\r
+ @param[in] This Indicates a pointer to the calling context.\r
+ @param[in,out] Token A pointer to the token associated with the transaction\r
+\r
+ @retval EFI_SUCCESS The flush request was queued if Event is not NULL.\r
+ All outstanding data was written correctly to the\r
+ device if the Event is NULL.\r
+ @retval EFI_DEVICE_ERROR The device reported an error while writting back\r
+ the data.\r
+ @retval EFI_WRITE_PROTECTED The device cannot be written to.\r
+ @retval EFI_NO_MEDIA There is no media in the device.\r
+ @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack\r
+ of resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EmuBlockIo2Flush (\r
+ IN EFI_BLOCK_IO2_PROTOCOL *This,\r
+ IN OUT EFI_BLOCK_IO2_TOKEN *Token\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EMU_BLOCK_IO_PRIVATE *Private;\r
+ EFI_TPL OldTpl;\r
+\r
+ Private = EMU_BLOCK_IO2_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+ Status = Private->Io->FlushBlocks (Private->Io, Token);\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
+}\r
+\r
+\r
+\r
+/**\r
+ Reset the Block Device.\r
+\r
+ @param This Indicates a pointer to the calling context.\r
+ @param ExtendedVerification Driver may perform diagnostics on reset.\r
+\r
+ @retval EFI_SUCCESS The device was reset.\r
+ @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
+ not be reset.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EmuBlockIoReset (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN BOOLEAN ExtendedVerification\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EMU_BLOCK_IO_PRIVATE *Private;\r
+ EFI_TPL OldTpl;\r
+\r
+ Private = EMU_BLOCK_IO2_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+ Status = Private->Io->Reset (Private->Io, ExtendedVerification);\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Read BufferSize bytes from Lba into Buffer.\r
+\r
+ @param This Indicates a pointer to the calling context.\r
+ @param MediaId Id of the media, changes every time the media is replaced.\r
+ @param Lba The starting Logical Block Address to read from\r
+ @param BufferSize Size of Buffer, must be a multiple of device block size.\r
+ @param Buffer A pointer to the destination buffer for the data. The caller is\r
+ responsible for either having implicit or explicit ownership of the buffer.\r
+\r
+ @retval EFI_SUCCESS The data was read correctly from the device.\r
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.\r
+ @retval EFI_NO_MEDIA There is no media in the device.\r
+ @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.\r
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, \r
+ or the buffer is not on proper alignment.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EmuBlockIoReadBlocks\r
+(\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN UINT32 MediaId,\r
+ IN EFI_LBA Lba,\r
+ IN UINTN BufferSize,\r
+ OUT VOID *Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EMU_BLOCK_IO_PRIVATE *Private;\r
+ EFI_TPL OldTpl;\r
+ EFI_BLOCK_IO2_TOKEN Token;\r
+\r
+ Private = EMU_BLOCK_IO2_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+ Token.Event = NULL;\r
+ Status = Private->Io->ReadBlocks (Private->Io, MediaId, Lba, &Token, BufferSize, Buffer);\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Write BufferSize bytes from Lba into Buffer.\r
+\r
+ @param This Indicates a pointer to the calling context.\r
+ @param MediaId The media ID that the write request is for.\r
+ @param Lba The starting logical block address to be written. The caller is\r
+ responsible for writing to only legitimate locations.\r
+ @param BufferSize Size of Buffer, must be a multiple of device block size.\r
+ @param Buffer A pointer to the source buffer for the data.\r
+\r
+ @retval EFI_SUCCESS The data was written correctly to the device.\r
+ @retval EFI_WRITE_PROTECTED The device can not be written to.\r
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.\r
+ @retval EFI_NO_MEDIA There is no media in the device.\r
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, \r
+ or the buffer is not on proper alignment.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EmuBlockIoWriteBlocks (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN UINT32 MediaId,\r
+ IN EFI_LBA Lba,\r
+ IN UINTN BufferSize,\r
+ IN VOID *Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EMU_BLOCK_IO_PRIVATE *Private;\r
+ EFI_TPL OldTpl;\r
+ EFI_BLOCK_IO2_TOKEN Token;\r
+\r
+ Private = EMU_BLOCK_IO2_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+ Token.Event = NULL;\r
+ Status = Private->Io->WriteBlocks (Private->Io, MediaId, Lba, &Token, BufferSize, Buffer);\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Flush the Block Device.\r
+\r
+ @param This Indicates a pointer to the calling context.\r
+\r
+ @retval EFI_SUCCESS All outstanding data was written to the device\r
+ @retval EFI_DEVICE_ERROR The device reported an error while writting back the data\r
+ @retval EFI_NO_MEDIA There is no media in the device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EmuBlockIoFlushBlocks (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EMU_BLOCK_IO_PRIVATE *Private;\r
+ EFI_TPL OldTpl;\r
+ EFI_BLOCK_IO2_TOKEN Token;\r
+\r
+ Private = EMU_BLOCK_IO2_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+ Token.Event = NULL;\r
+ Status = Private->Io->FlushBlocks (Private->Io, &Token);\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
+}\r
+\r
+\r
+\r
+/**\r
+ Tests to see if this driver supports a given controller. If a child device is provided, \r
+ it further tests to see if this driver supports creating a handle for the specified child device.\r
+\r
+ This function checks to see if the driver specified by This supports the device specified by \r
+ ControllerHandle. Drivers will typically use the device path attached to \r
+ ControllerHandle and/or the services from the bus I/O abstraction attached to \r
+ ControllerHandle to determine if the driver supports ControllerHandle. This function \r
+ may be called many times during platform initialization. In order to reduce boot times, the tests \r
+ performed by this function must be very small, and take as little time as possible to execute. This \r
+ function must not change the state of any hardware devices, and this function must be aware that the \r
+ device specified by ControllerHandle may already be managed by the same driver or a \r
+ different driver. This function must match its calls to AllocatePages() with FreePages(), \r
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). \r
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is \r
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required \r
+ to guarantee the state of ControllerHandle is not modified by this function.\r
+\r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle The handle of the controller to test. This handle \r
+ must support a protocol interface that supplies \r
+ an I/O abstraction to the driver.\r
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
+ parameter is ignored by device drivers, and is optional for bus \r
+ drivers. For bus drivers, if this parameter is not NULL, then \r
+ the bus driver must determine if the bus controller specified \r
+ by ControllerHandle and the child controller specified \r
+ by RemainingDevicePath are both supported by this \r
+ bus driver.\r
+\r
+ @retval EFI_SUCCESS The device specified by ControllerHandle and\r
+ RemainingDevicePath is supported by the driver specified by This.\r
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
+ RemainingDevicePath is already being managed by the driver\r
+ specified by This.\r
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
+ RemainingDevicePath is already being managed by a different\r
+ driver or an application that requires exclusive access.\r
+ Currently not implemented.\r
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
+ RemainingDevicePath is not supported by the driver specified by This.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EmuBlockIoDriverBindingSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Handle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EMU_IO_THUNK_PROTOCOL *EmuIoThunk;\r
+\r
+ //\r
+ // Open the IO Abstraction(s) needed to perform the supported test\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Handle,\r
+ &gEmuIoThunkProtocolGuid,\r
+ (VOID **)&EmuIoThunk,\r
+ This->DriverBindingHandle,\r
+ Handle,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Make sure GUID is for a File System handle.\r
+ //\r
+ Status = EFI_UNSUPPORTED;\r
+ if (CompareGuid (EmuIoThunk->Protocol, &gEmuVirtualDisksGuid)) {\r
+ Status = EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Close the I/O Abstraction(s) used to perform the supported test\r
+ //\r
+ gBS->CloseProtocol (\r
+ Handle,\r
+ &gEmuIoThunkProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Handle\r
+ );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Starts a device controller or a bus controller.\r
+\r
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().\r
+ As a result, much of the error checking on the parameters to Start() has been moved into this \r
+ common boot service. It is legal to call Start() from other locations, \r
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
+ 1. ControllerHandle must be a valid EFI_HANDLE.\r
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
+ EFI_DEVICE_PATH_PROTOCOL.\r
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. \r
+\r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle The handle of the controller to start. This handle \r
+ must support a protocol interface that supplies \r
+ an I/O abstraction to the driver.\r
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
+ parameter is ignored by device drivers, and is optional for bus \r
+ drivers. For a bus driver, if this parameter is NULL, then handles \r
+ for all the children of Controller are created by this driver. \r
+ If this parameter is not NULL and the first Device Path Node is \r
+ not the End of Device Path Node, then only the handle for the \r
+ child device specified by the first Device Path Node of \r
+ RemainingDevicePath is created by this driver.\r
+ If the first Device Path Node of RemainingDevicePath is \r
+ the End of Device Path Node, no child handle is created by this\r
+ driver.\r
+\r
+ @retval EFI_SUCCESS The device was started.\r
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ @retval Others The driver failded to start the device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EmuBlockIoDriverBindingStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Handle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EMU_IO_THUNK_PROTOCOL *EmuIoThunk;\r
+ EMU_BLOCK_IO_PRIVATE *Private;\r
+\r
+ //\r
+ // Grab the protocols we need\r
+ //\r
+ \r
+ Status = gBS->OpenProtocol (\r
+ Handle,\r
+ &gEmuIoThunkProtocolGuid,\r
+ (void *)&EmuIoThunk,\r
+ This->DriverBindingHandle,\r
+ Handle,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Set DiskType\r
+ //\r
+ if (!CompareGuid (EmuIoThunk->Protocol, &gEmuVirtualDisksGuid)) {\r
+ Status = EFI_UNSUPPORTED;\r
+ goto Done;\r
+ }\r
+\r
+ Status = EmuIoThunk->Open (EmuIoThunk);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Private = AllocatePool (sizeof (EMU_BLOCK_IO_PRIVATE));\r
+ if (Private == NULL) {\r
+ goto Done;\r
+ }\r
+\r
+ Private->Signature = EMU_BLOCK_IO_PRIVATE_SIGNATURE;\r
+ Private->IoThunk = EmuIoThunk;\r
+ Private->Io = EmuIoThunk->Interface;\r
+ \r
+ Private->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION2;\r
+ Private->BlockIo.Media = &Private->Media;\r
+ Private->BlockIo.Reset = EmuBlockIoReset;\r
+ Private->BlockIo.ReadBlocks = EmuBlockIoReadBlocks;\r
+ Private->BlockIo.WriteBlocks = EmuBlockIoWriteBlocks;\r
+ Private->BlockIo.FlushBlocks = EmuBlockIoFlushBlocks;\r
+\r
+ Private->BlockIo2.Media = &Private->Media;\r
+ Private->BlockIo2.Reset = EmuBlockIo2Reset;\r
+ Private->BlockIo2.ReadBlocksEx = EmuBlockIo2ReadBlocksEx;\r
+ Private->BlockIo2.WriteBlocksEx = EmuBlockIo2WriteBlocksEx;\r
+ Private->BlockIo2.FlushBlocksEx = (EFI_BLOCK_FLUSH_EX)EmuBlockIoFlushBlocks;\r
+\r
+ Private->ControllerNameTable = NULL;\r
+\r
+ Status = Private->Io->CreateMapping (Private->Io, &Private->Media);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ AddUnicodeString2 (\r
+ "eng",\r
+ gEmuBlockIoComponentName.SupportedLanguages,\r
+ &Private->ControllerNameTable,\r
+ EmuIoThunk->ConfigString,\r
+ TRUE\r
+ );\r
+ \r
+ AddUnicodeString2 (\r
+ "en",\r
+ gEmuBlockIoComponentName2.SupportedLanguages,\r
+ &Private->ControllerNameTable,\r
+ EmuIoThunk->ConfigString,\r
+ FALSE\r
+ );\r
+\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &Handle,\r
+ &gEfiBlockIoProtocolGuid, &Private->BlockIo,\r
+ &gEfiBlockIo2ProtocolGuid, &Private->BlockIo2,\r
+ NULL\r
+ );\r
+\r
+Done:\r
+ if (EFI_ERROR (Status)) {\r
+ if (Private != NULL) {\r
+ if (Private->ControllerNameTable != NULL) {\r
+ FreeUnicodeStringTable (Private->ControllerNameTable);\r
+ }\r
+ \r
+ gBS->FreePool (Private);\r
+ \r
+ }\r
+ \r
+ gBS->CloseProtocol (\r
+ Handle,\r
+ &gEmuIoThunkProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Handle\r
+ );\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Stops a device controller or a bus controller.\r
+ \r
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). \r
+ As a result, much of the error checking on the parameters to Stop() has been moved \r
+ into this common boot service. It is legal to call Stop() from other locations, \r
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
+ same driver's Start() function.\r
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
+ Start() function, and the Start() function must have called OpenProtocol() on\r
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
+ \r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must \r
+ support a bus specific I/O protocol for the driver \r
+ to use to stop the device.\r
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL \r
+ if NumberOfChildren is 0.\r
+\r
+ @retval EFI_SUCCESS The device was stopped.\r
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EmuBlockIoDriverBindingStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Handle,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer\r
+ )\r
+{\r
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
+ EFI_STATUS Status;\r
+ EMU_BLOCK_IO_PRIVATE *Private;\r
+\r
+ //\r
+ // Get our context back\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Handle,\r
+ &gEfiBlockIoProtocolGuid,\r
+ (void *)&BlockIo,\r
+ This->DriverBindingHandle,\r
+ Handle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (BlockIo);\r
+ Status = Private->IoThunk->Close (Private->IoThunk);\r
+\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ Private->EfiHandle,\r
+ &gEfiBlockIoProtocolGuid, &Private->BlockIo,\r
+ &gEfiBlockIo2ProtocolGuid, &Private->BlockIo2,\r
+ NULL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gBS->CloseProtocol (\r
+ Handle,\r
+ &gEmuIoThunkProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Handle\r
+ );\r
+ }\r
+ \r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Free our instance data\r
+ //\r
+ FreeUnicodeStringTable (Private->ControllerNameTable);\r
+ gBS->FreePool (Private);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+\r
+\r
+\r
+EFI_DRIVER_BINDING_PROTOCOL gEmuBlockIoDriverBinding = {\r
+ EmuBlockIoDriverBindingSupported,\r
+ EmuBlockIoDriverBindingStart,\r
+ EmuBlockIoDriverBindingStop,\r
+ 0xa,\r
+ NULL,\r
+ NULL\r
+};\r
+\r
+\r
+\r
+\r
+/**\r
+ The user Entry Point for module EmuBlockIo . The user code starts with this function.\r
+\r
+ @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
+ @param[in] SystemTable A pointer to the EFI System Table.\r
+ \r
+ @retval EFI_SUCCESS The entry point is executed successfully.\r
+ @retval other Some error occurs when executing this entry point.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeEmuBlockIo (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = EfiLibInstallAllDriverProtocols2 (\r
+ ImageHandle,\r
+ SystemTable,\r
+ &gEmuBlockIoDriverBinding,\r
+ ImageHandle,\r
+ &gEmuBlockIoComponentName,\r
+ &gEmuBlockIoComponentName2,\r
+ NULL,\r
+ NULL,\r
+ &gEmuBlockIoDriverDiagnostics,\r
+ &gEmuBlockIoDriverDiagnostics2\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+\r