+++ /dev/null
-/**@file\r
-\r
-Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\r
-SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-Module Name:\r
-\r
- WinNtBlockIo.c\r
-\r
-Abstract:\r
-\r
- Produce block IO abstractions for real devices on your PC using Win32 APIs.\r
- The configuration of what devices to mount or emulate comes from NT\r
- environment variables. The variables must be visible to the Microsoft*\r
- Developer Studio for them to work.\r
-\r
- <F>ixed - Fixed disk like a hard drive.\r
- <R>emovable - Removable media like a floppy or CD-ROM.\r
- Read <O>nly - Write protected device.\r
- Read <W>rite - Read write device.\r
- <block count> - Decimal number of blocks a device supports.\r
- <block size> - Decimal number of bytes per block.\r
-\r
- NT envirnonment variable contents. '<' and '>' are not part of the variable,\r
- they are just used to make this help more readable. There should be no\r
- spaces between the ';'. Extra spaces will break the variable. A '!' is\r
- used to seperate multiple devices in a variable.\r
-\r
- EFI_WIN_NT_VIRTUAL_DISKS =\r
- <F | R><O | W>;<block count>;<block size>[!...]\r
-\r
- EFI_WIN_NT_PHYSICAL_DISKS =\r
- <drive letter>:<F | R><O | W>;<block count>;<block size>[!...]\r
-\r
- Virtual Disks: These devices use a file to emulate a hard disk or removable\r
- media device.\r
-\r
- Thus a 20 MB emulated hard drive would look like:\r
- EFI_WIN_NT_VIRTUAL_DISKS=FW;40960;512\r
-\r
- A 1.44MB emulated floppy with a block size of 1024 would look like:\r
- EFI_WIN_NT_VIRTUAL_DISKS=RW;1440;1024\r
-\r
- Physical Disks: These devices use NT to open a real device in your system\r
-\r
- Thus a 120 MB floppy would look like:\r
- EFI_WIN_NT_PHYSICAL_DISKS=B:RW;245760;512\r
-\r
- Thus a standard CD-ROM floppy would look like:\r
- EFI_WIN_NT_PHYSICAL_DISKS=Z:RO;307200;2048\r
-\r
-\r
- * Other names and brands may be claimed as the property of others.\r
-\r
-**/\r
-#include <Uefi.h>\r
-#include <WinNtDxe.h>\r
-#include <Protocol/WinNtThunk.h>\r
-#include <Protocol/WinNtIo.h>\r
-#include <Protocol/BlockIo.h>\r
-#include <Protocol/ComponentName.h>\r
-#include <Protocol/DriverBinding.h>\r
-//\r
-// The Library classes this module consumes\r
-//\r
-#include <Library/DebugLib.h>\r
-#include <Library/BaseLib.h>\r
-#include <Library/UefiDriverEntryPoint.h>\r
-#include <Library/UefiLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-\r
-#include "WinNtBlockIo.h"\r
-\r
-EFI_DRIVER_BINDING_PROTOCOL gWinNtBlockIoDriverBinding = {\r
- WinNtBlockIoDriverBindingSupported,\r
- WinNtBlockIoDriverBindingStart,\r
- WinNtBlockIoDriverBindingStop,\r
- 0xa,\r
- NULL,\r
- NULL\r
-};\r
-\r
-/**\r
- The user Entry Point for module WinNtBlockIo. 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
-InitializeWinNtBlockIo(\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- //\r
- // Install driver model protocol(s).\r
- //\r
- Status = EfiLibInstallAllDriverProtocols2 (\r
- ImageHandle,\r
- SystemTable,\r
- &gWinNtBlockIoDriverBinding,\r
- ImageHandle,\r
- &gWinNtBlockIoComponentName,\r
- &gWinNtBlockIoComponentName2,\r
- NULL,\r
- NULL,\r
- &gWinNtBlockIoDriverDiagnostics,\r
- &gWinNtBlockIoDriverDiagnostics2\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-WinNtBlockIoDriverBindingSupported (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Handle,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-Arguments:\r
-\r
-Returns:\r
-\r
- None\r
-\r
---*/\r
-// TODO: This - add argument and description to function comment\r
-// TODO: Handle - add argument and description to function comment\r
-// TODO: RemainingDevicePath - add argument and description to function comment\r
-{\r
- EFI_STATUS Status;\r
- EFI_WIN_NT_IO_PROTOCOL *WinNtIo;\r
-\r
- //\r
- // Open the IO Abstraction(s) needed to perform the supported test\r
- //\r
- Status = gBS->OpenProtocol (\r
- Handle,\r
- &gEfiWinNtIoProtocolGuid,\r
- (VOID **) &WinNtIo,\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 the WinNtThunkProtocol is valid\r
- //\r
- Status = EFI_UNSUPPORTED;\r
- if (WinNtIo->WinNtThunk->Signature == EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE) {\r
-\r
- //\r
- // Check the GUID to see if this is a handle type the driver supports\r
- //\r
- if (CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtVirtualDisksGuid) ||\r
- CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtPhysicalDisksGuid) ) {\r
- Status = EFI_SUCCESS;\r
- }\r
- }\r
-\r
- //\r
- // Close the I/O Abstraction(s) used to perform the supported test\r
- //\r
- gBS->CloseProtocol (\r
- Handle,\r
- &gEfiWinNtIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Handle\r
- );\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-WinNtBlockIoDriverBindingStart (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Handle,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-Arguments:\r
-\r
-Returns:\r
-\r
- None\r
-\r
---*/\r
-// TODO: This - add argument and description to function comment\r
-// TODO: Handle - add argument and description to function comment\r
-// TODO: RemainingDevicePath - add argument and description to function comment\r
-{\r
- EFI_STATUS Status;\r
- EFI_WIN_NT_IO_PROTOCOL *WinNtIo;\r
- WIN_NT_RAW_DISK_DEVICE_TYPE DiskType;\r
- UINT16 Buffer[FILENAME_BUFFER_SIZE];\r
- CHAR16 *Str;\r
- BOOLEAN RemovableMedia;\r
- BOOLEAN WriteProtected;\r
- UINTN NumberOfBlocks;\r
- UINTN BlockSize;\r
-\r
- //\r
- // Grab the protocols we need\r
- //\r
- Status = gBS->OpenProtocol (\r
- Handle,\r
- &gEfiWinNtIoProtocolGuid,\r
- (VOID **) &WinNtIo,\r
- This->DriverBindingHandle,\r
- Handle,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Set DiskType\r
- //\r
- if (CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtVirtualDisksGuid)) {\r
- DiskType = EfiWinNtVirtualDisks;\r
- } else if (CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtPhysicalDisksGuid)) {\r
- DiskType = EfiWinNtPhysicalDisks;\r
- } else {\r
- Status = EFI_UNSUPPORTED;\r
- goto Done;\r
- }\r
-\r
- Status = EFI_NOT_FOUND;\r
- Str = WinNtIo->EnvString;\r
- if (DiskType == EfiWinNtVirtualDisks) {\r
- WinNtIo->WinNtThunk->SPrintf (\r
- Buffer,\r
- sizeof (Buffer),\r
- L"Diskfile%d",\r
- WinNtIo->InstanceNumber\r
- );\r
- } else {\r
- if (*Str >= 'A' && *Str <= 'Z' || *Str >= 'a' && *Str <= 'z') {\r
- WinNtIo->WinNtThunk->SPrintf (Buffer, sizeof (Buffer), L"\\\\.\\%c:", *Str);\r
- } else {\r
- WinNtIo->WinNtThunk->SPrintf (Buffer, sizeof (Buffer), L"\\\\.\\PHYSICALDRIVE%c", *Str);\r
- }\r
-\r
- Str++;\r
- if (*Str != ':') {\r
- Status = EFI_NOT_FOUND;\r
- goto Done;\r
- }\r
-\r
- Str++;\r
- }\r
-\r
- if (*Str == 'R' || *Str == 'F') {\r
- RemovableMedia = (BOOLEAN) (*Str == 'R');\r
- Str++;\r
- if (*Str == 'O' || *Str == 'W') {\r
- WriteProtected = (BOOLEAN) (*Str == 'O');\r
- Str = GetNextElementPastTerminator (Str, ';');\r
-\r
- NumberOfBlocks = StrDecimalToUintn (Str);\r
- if (NumberOfBlocks != 0) {\r
- Str = GetNextElementPastTerminator (Str, ';');\r
- BlockSize = StrDecimalToUintn (Str);\r
- if (BlockSize != 0) {\r
- //\r
- // If we get here the variable is valid so do the work.\r
- //\r
- Status = WinNtBlockIoCreateMapping (\r
- WinNtIo,\r
- Handle,\r
- Buffer,\r
- WriteProtected,\r
- RemovableMedia,\r
- NumberOfBlocks,\r
- BlockSize,\r
- DiskType\r
- );\r
-\r
- }\r
- }\r
- }\r
- }\r
-\r
-Done:\r
- if (EFI_ERROR (Status)) {\r
- gBS->CloseProtocol (\r
- Handle,\r
- &gEfiWinNtIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Handle\r
- );\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-WinNtBlockIoDriverBindingStop (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Handle,\r
- IN UINTN NumberOfChildren,\r
- IN EFI_HANDLE *ChildHandleBuffer\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- TODO: Add function description\r
-\r
-Arguments:\r
-\r
- This - TODO: add argument description\r
- Handle - TODO: add argument description\r
- NumberOfChildren - TODO: add argument description\r
- ChildHandleBuffer - TODO: add argument description\r
-\r
-Returns:\r
-\r
- EFI_UNSUPPORTED - TODO: Add description for return value\r
-\r
---*/\r
-{\r
- EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
- EFI_STATUS Status;\r
- WIN_NT_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 = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (BlockIo);\r
-\r
- //\r
- // BugBug: If we need to kick people off, we need to make Uninstall Close the handles.\r
- // We could pass in our image handle or FLAG our open to be closed via\r
- // Unistall (== to saying any CloseProtocol will close our open)\r
- //\r
- Status = gBS->UninstallMultipleProtocolInterfaces (\r
- Private->EfiHandle,\r
- &gEfiBlockIoProtocolGuid,\r
- &Private->BlockIo,\r
- NULL\r
- );\r
- if (!EFI_ERROR (Status)) {\r
-\r
- Status = gBS->CloseProtocol (\r
- Handle,\r
- &gEfiWinNtIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Handle\r
- );\r
-\r
- //\r
- // Shut down our device\r
- //\r
- Private->WinNtThunk->CloseHandle (Private->NtHandle);\r
-\r
- //\r
- // Free our instance data\r
- //\r
- FreeUnicodeStringTable (Private->ControllerNameTable);\r
-\r
- FreePool (Private);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-CHAR16 *\r
-GetNextElementPastTerminator (\r
- IN CHAR16 *EnvironmentVariable,\r
- IN CHAR16 Terminator\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Worker function to parse environment variables.\r
-\r
-Arguments:\r
- EnvironmentVariable - Envirnment variable to parse.\r
-\r
- Terminator - Terminator to parse for.\r
-\r
-Returns:\r
-\r
- Pointer to next eliment past the first occurence of Terminator or the '\0'\r
- at the end of the string.\r
-\r
---*/\r
-{\r
- CHAR16 *Ptr;\r
-\r
- for (Ptr = EnvironmentVariable; *Ptr != '\0'; Ptr++) {\r
- if (*Ptr == Terminator) {\r
- Ptr++;\r
- break;\r
- }\r
- }\r
-\r
- return Ptr;\r
-}\r
-\r
-EFI_STATUS\r
-WinNtBlockIoCreateMapping (\r
- IN EFI_WIN_NT_IO_PROTOCOL *WinNtIo,\r
- IN EFI_HANDLE EfiDeviceHandle,\r
- IN CHAR16 *Filename,\r
- IN BOOLEAN ReadOnly,\r
- IN BOOLEAN RemovableMedia,\r
- IN UINTN NumberOfBlocks,\r
- IN UINTN BlockSize,\r
- IN WIN_NT_RAW_DISK_DEVICE_TYPE DeviceType\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- TODO: Add function description\r
-\r
-Arguments:\r
-\r
- WinNtIo - TODO: add argument description\r
- EfiDeviceHandle - TODO: add argument description\r
- Filename - TODO: add argument description\r
- ReadOnly - TODO: add argument description\r
- RemovableMedia - TODO: add argument description\r
- NumberOfBlocks - TODO: add argument description\r
- BlockSize - TODO: add argument description\r
- DeviceType - TODO: add argument description\r
-\r
-Returns:\r
-\r
- TODO: add return values\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
- WIN_NT_BLOCK_IO_PRIVATE *Private;\r
- UINTN Index;\r
-\r
- WinNtIo->WinNtThunk->SetErrorMode (SEM_FAILCRITICALERRORS);\r
-\r
- Private = AllocatePool (sizeof (WIN_NT_BLOCK_IO_PRIVATE));\r
- ASSERT (Private != NULL);\r
-\r
- EfiInitializeLock (&Private->Lock, TPL_NOTIFY);\r
-\r
- Private->WinNtThunk = WinNtIo->WinNtThunk;\r
-\r
- Private->Signature = WIN_NT_BLOCK_IO_PRIVATE_SIGNATURE;\r
- Private->LastBlock = NumberOfBlocks - 1;\r
- Private->BlockSize = BlockSize;\r
-\r
- for (Index = 0; Filename[Index] != 0; Index++) {\r
- Private->Filename[Index] = Filename[Index];\r
- }\r
-\r
- Private->Filename[Index] = 0;\r
-\r
- Private->ReadMode = GENERIC_READ | (ReadOnly ? 0 : GENERIC_WRITE);\r
- Private->ShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;\r
-\r
- Private->NumberOfBlocks = NumberOfBlocks;\r
- Private->DeviceType = DeviceType;\r
- Private->NtHandle = INVALID_HANDLE_VALUE;\r
-\r
- Private->ControllerNameTable = NULL;\r
-\r
- AddUnicodeString2 (\r
- "eng",\r
- gWinNtBlockIoComponentName.SupportedLanguages,\r
- &Private->ControllerNameTable,\r
- Private->Filename,\r
- TRUE\r
- );\r
- AddUnicodeString2 (\r
- "en",\r
- gWinNtBlockIoComponentName2.SupportedLanguages,\r
- &Private->ControllerNameTable,\r
- Private->Filename,\r
- FALSE\r
- );\r
-\r
-\r
- BlockIo = &Private->BlockIo;\r
- BlockIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;\r
- BlockIo->Media = &Private->Media;\r
- BlockIo->Media->BlockSize = (UINT32)Private->BlockSize;\r
- BlockIo->Media->LastBlock = Private->NumberOfBlocks - 1;\r
- BlockIo->Media->MediaId = 0;;\r
-\r
- BlockIo->Reset = WinNtBlockIoResetBlock;\r
- BlockIo->ReadBlocks = WinNtBlockIoReadBlocks;\r
- BlockIo->WriteBlocks = WinNtBlockIoWriteBlocks;\r
- BlockIo->FlushBlocks = WinNtBlockIoFlushBlocks;\r
-\r
- BlockIo->Media->ReadOnly = ReadOnly;\r
- BlockIo->Media->RemovableMedia = RemovableMedia;\r
- BlockIo->Media->LogicalPartition = FALSE;\r
- BlockIo->Media->MediaPresent = TRUE;\r
- BlockIo->Media->WriteCaching = FALSE;\r
-\r
- if (DeviceType == EfiWinNtVirtualDisks) {\r
- BlockIo->Media->IoAlign = 1;\r
-\r
- //\r
- // Create a file to use for a virtual disk even if it does not exist.\r
- //\r
- Private->OpenMode = OPEN_ALWAYS;\r
- } else if (DeviceType == EfiWinNtPhysicalDisks) {\r
- //\r
- // Physical disk and floppy devices require 4 byte alignment.\r
- //\r
- BlockIo->Media->IoAlign = 4;\r
-\r
- //\r
- // You can only open a physical device if it exists.\r
- //\r
- Private->OpenMode = OPEN_EXISTING;\r
- } else {\r
- ASSERT (FALSE);\r
- }\r
-\r
- Private->EfiHandle = EfiDeviceHandle;\r
- Status = WinNtBlockIoOpenDevice (Private);\r
- if (!EFI_ERROR (Status)) {\r
-\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &Private->EfiHandle,\r
- &gEfiBlockIoProtocolGuid,\r
- &Private->BlockIo,\r
- NULL\r
- );\r
- if (EFI_ERROR (Status)) {\r
- FreeUnicodeStringTable (Private->ControllerNameTable);\r
- FreePool (Private);\r
- }\r
-\r
- DEBUG ((EFI_D_INIT, "BlockDevice added: %s\n", Filename));\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-WinNtBlockIoOpenDevice (\r
- WIN_NT_BLOCK_IO_PRIVATE *Private\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- TODO: Add function description\r
-\r
-Arguments:\r
-\r
- Private - TODO: add argument description\r
-\r
-Returns:\r
-\r
- TODO: add return values\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- UINT64 FileSize;\r
- UINT64 EndOfFile;\r
- EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
-\r
- BlockIo = &Private->BlockIo;\r
- EfiAcquireLock (&Private->Lock);\r
-\r
- //\r
- // If the device is already opened, close it\r
- //\r
- if (Private->NtHandle != INVALID_HANDLE_VALUE) {\r
- BlockIo->Reset (BlockIo, FALSE);\r
- }\r
-\r
- //\r
- // Open the device\r
- //\r
- Private->NtHandle = Private->WinNtThunk->CreateFile (\r
- Private->Filename,\r
- (DWORD)Private->ReadMode,\r
- (DWORD)Private->ShareMode,\r
- NULL,\r
- (DWORD)Private->OpenMode,\r
- 0,\r
- NULL\r
- );\r
-\r
- Status = Private->WinNtThunk->GetLastError ();\r
-\r
- if (Private->NtHandle == INVALID_HANDLE_VALUE) {\r
- DEBUG ((EFI_D_INFO, "PlOpenBlock: Could not open %s, %x\n", Private->Filename, Private->WinNtThunk->GetLastError ()));\r
- BlockIo->Media->MediaPresent = FALSE;\r
- Status = EFI_NO_MEDIA;\r
- goto Done;\r
- }\r
-\r
- if (!BlockIo->Media->MediaPresent) {\r
- //\r
- // BugBug: try to emulate if a CD appears - notify drivers to check it out\r
- //\r
- BlockIo->Media->MediaPresent = TRUE;\r
- EfiReleaseLock (&Private->Lock);\r
- EfiAcquireLock (&Private->Lock);\r
- }\r
-\r
- //\r
- // get the size of the file\r
- //\r
- Status = SetFilePointer64 (Private, 0, &FileSize, FILE_END);\r
-\r
- if (EFI_ERROR (Status)) {\r
- FileSize = MultU64x32 (Private->NumberOfBlocks, (UINT32)Private->BlockSize);\r
- if (Private->DeviceType == EfiWinNtVirtualDisks) {\r
- DEBUG ((EFI_D_ERROR, "PlOpenBlock: Could not get filesize of %s\n", Private->Filename));\r
- Status = EFI_UNSUPPORTED;\r
- goto Done;\r
- }\r
- }\r
-\r
- if (Private->NumberOfBlocks == 0) {\r
- Private->NumberOfBlocks = DivU64x32 (FileSize, (UINT32)Private->BlockSize);\r
- }\r
-\r
- EndOfFile = MultU64x32 (Private->NumberOfBlocks, (UINT32)Private->BlockSize);\r
-\r
- if (FileSize != EndOfFile) {\r
- //\r
- // file is not the proper size, change it\r
- //\r
- DEBUG ((EFI_D_INIT, "PlOpenBlock: Initializing block device: %hs\n", Private->Filename));\r
-\r
- //\r
- // first set it to 0\r
- //\r
- SetFilePointer64 (Private, 0, NULL, FILE_BEGIN);\r
- Private->WinNtThunk->SetEndOfFile (Private->NtHandle);\r
-\r
- //\r
- // then set it to the needed file size (OS will zero fill it)\r
- //\r
- SetFilePointer64 (Private, EndOfFile, NULL, FILE_BEGIN);\r
- Private->WinNtThunk->SetEndOfFile (Private->NtHandle);\r
- }\r
-\r
- DEBUG ((EFI_D_INIT, "%HPlOpenBlock: opened %s%N\n", Private->Filename));\r
- Status = EFI_SUCCESS;\r
-\r
-Done:\r
- if (EFI_ERROR (Status)) {\r
- if (Private->NtHandle != INVALID_HANDLE_VALUE) {\r
- BlockIo->Reset (BlockIo, FALSE);\r
- }\r
- }\r
-\r
- EfiReleaseLock (&Private->Lock);\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-WinNtBlockIoError (\r
- IN WIN_NT_BLOCK_IO_PRIVATE *Private\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- TODO: Add function description\r
-\r
-Arguments:\r
-\r
- Private - TODO: add argument description\r
-\r
-Returns:\r
-\r
- TODO: add return values\r
-\r
---*/\r
-{\r
- EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
- EFI_STATUS Status;\r
- BOOLEAN ReinstallBlockIoFlag;\r
-\r
- BlockIo = &Private->BlockIo;\r
-\r
- switch (Private->WinNtThunk->GetLastError ()) {\r
-\r
- case ERROR_NOT_READY:\r
- Status = EFI_NO_MEDIA;\r
- BlockIo->Media->ReadOnly = FALSE;\r
- BlockIo->Media->MediaPresent = FALSE;\r
- ReinstallBlockIoFlag = FALSE;\r
- break;\r
-\r
- case ERROR_WRONG_DISK:\r
- BlockIo->Media->ReadOnly = FALSE;\r
- BlockIo->Media->MediaPresent = TRUE;\r
- BlockIo->Media->MediaId += 1;\r
- ReinstallBlockIoFlag = TRUE;\r
- Status = EFI_MEDIA_CHANGED;\r
- break;\r
-\r
- case ERROR_WRITE_PROTECT:\r
- BlockIo->Media->ReadOnly = TRUE;\r
- ReinstallBlockIoFlag = FALSE;\r
- Status = EFI_WRITE_PROTECTED;\r
- break;\r
-\r
- default:\r
- ReinstallBlockIoFlag = FALSE;\r
- Status = EFI_DEVICE_ERROR;\r
- break;\r
- }\r
-\r
- if (ReinstallBlockIoFlag) {\r
- BlockIo->Reset (BlockIo, FALSE);\r
-\r
- gBS->ReinstallProtocolInterface (\r
- Private->EfiHandle,\r
- &gEfiBlockIoProtocolGuid,\r
- BlockIo,\r
- BlockIo\r
- );\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-WinNtBlockIoReadWriteCommon (\r
- IN WIN_NT_BLOCK_IO_PRIVATE *Private,\r
- IN UINT32 MediaId,\r
- IN EFI_LBA Lba,\r
- IN UINTN BufferSize,\r
- IN VOID *Buffer,\r
- IN CHAR8 *CallerName\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- TODO: Add function description\r
-\r
-Arguments:\r
-\r
- Private - TODO: add argument description\r
- MediaId - TODO: add argument description\r
- Lba - TODO: add argument description\r
- BufferSize - TODO: add argument description\r
- Buffer - TODO: add argument description\r
- CallerName - TODO: add argument description\r
-\r
-Returns:\r
-\r
- EFI_NO_MEDIA - TODO: Add description for return value\r
- EFI_MEDIA_CHANGED - TODO: Add description for return value\r
- EFI_INVALID_PARAMETER - TODO: Add description for return value\r
- EFI_SUCCESS - TODO: Add description for return value\r
- EFI_BAD_BUFFER_SIZE - TODO: Add description for return value\r
- EFI_INVALID_PARAMETER - TODO: Add description for return value\r
- EFI_SUCCESS - TODO: Add description for return value\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- UINTN BlockSize;\r
- UINT64 LastBlock;\r
- INT64 DistanceToMove;\r
- UINT64 DistanceMoved;\r
-\r
- if (Private->NtHandle == INVALID_HANDLE_VALUE) {\r
- Status = WinNtBlockIoOpenDevice (Private);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- }\r
-\r
- if (!Private->Media.MediaPresent) {\r
- DEBUG ((EFI_D_INIT, "%s: No Media\n", CallerName));\r
- return EFI_NO_MEDIA;\r
- }\r
-\r
- if (Private->Media.MediaId != MediaId) {\r
- return EFI_MEDIA_CHANGED;\r
- }\r
-\r
- if ((UINTN) Buffer % Private->Media.IoAlign != 0) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // Verify buffer size\r
- //\r
- BlockSize = Private->BlockSize;\r
- if (BufferSize == 0) {\r
- DEBUG ((EFI_D_INIT, "%s: Zero length read\n", CallerName));\r
- return EFI_SUCCESS;\r
- }\r
-\r
- if ((BufferSize % BlockSize) != 0) {\r
- DEBUG ((EFI_D_INIT, "%s: Invalid read size\n", CallerName));\r
- return EFI_BAD_BUFFER_SIZE;\r
- }\r
-\r
- LastBlock = Lba + (BufferSize / BlockSize) - 1;\r
- if (LastBlock > Private->LastBlock) {\r
- DEBUG ((EFI_D_INIT, "ReadBlocks: Attempted to read off end of device\n"));\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- //\r
- // Seek to End of File\r
- //\r
- DistanceToMove = MultU64x32 (Lba, (UINT32)BlockSize);\r
- Status = SetFilePointer64 (Private, DistanceToMove, &DistanceMoved, FILE_BEGIN);\r
-\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_INIT, "WriteBlocks: SetFilePointer failed\n"));\r
- return WinNtBlockIoError (Private);\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-WinNtBlockIoReadBlocks (\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
-\r
- Routine Description:\r
- Read BufferSize bytes from Lba into Buffer.\r
-\r
- Arguments:\r
- This - Protocol instance pointer.\r
- MediaId - Id of the media, changes every time the media is replaced.\r
- Lba - The starting Logical Block Address to read from\r
- BufferSize - Size of Buffer, must be a multiple of device block size.\r
- Buffer - Buffer containing read data\r
-\r
- Returns:\r
- EFI_SUCCESS - The data was read correctly from the device.\r
- EFI_DEVICE_ERROR - The device reported an error while performing the read.\r
- EFI_NO_MEDIA - There is no media in the device.\r
- EFI_MEDIA_CHANGED - The MediaId does not matched the current device.\r
- EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the\r
- device.\r
- EFI_INVALID_PARAMETER - The read request contains device addresses that are not\r
- valid for the device.\r
-\r
---*/\r
-{\r
- WIN_NT_BLOCK_IO_PRIVATE *Private;\r
- BOOL Flag;\r
- EFI_STATUS Status;\r
- DWORD BytesRead;\r
- EFI_TPL OldTpl;\r
-\r
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
- Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);\r
-\r
- Status = WinNtBlockIoReadWriteCommon (Private, MediaId, Lba, BufferSize, Buffer, "WinNtReadBlocks");\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- Flag = Private->WinNtThunk->ReadFile (Private->NtHandle, Buffer, (DWORD) BufferSize, (LPDWORD) &BytesRead, NULL);\r
- if (!Flag || (BytesRead != BufferSize)) {\r
- DEBUG ((EFI_D_INIT, "ReadBlocks: ReadFile failed. (%d)\n", Private->WinNtThunk->GetLastError ()));\r
- Status = WinNtBlockIoError (Private);\r
- goto Done;\r
- }\r
-\r
- //\r
- // If we wrote then media is present.\r
- //\r
- This->Media->MediaPresent = TRUE;\r
- Status = EFI_SUCCESS;\r
-\r
-Done:\r
- gBS->RestoreTPL (OldTpl);\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-WinNtBlockIoWriteBlocks (\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
-\r
- Routine Description:\r
- Write BufferSize bytes from Lba into Buffer.\r
-\r
- Arguments:\r
- This - Protocol instance pointer.\r
- MediaId - Id of the media, changes every time the media is replaced.\r
- Lba - The starting Logical Block Address to read from\r
- BufferSize - Size of Buffer, must be a multiple of device block size.\r
- Buffer - Buffer containing read data\r
-\r
- Returns:\r
- EFI_SUCCESS - The data was written correctly to the device.\r
- EFI_WRITE_PROTECTED - The device can not be written to.\r
- EFI_DEVICE_ERROR - The device reported an error while performing the write.\r
- EFI_NO_MEDIA - There is no media in the device.\r
- EFI_MEDIA_CHNAGED - The MediaId does not matched the current device.\r
- EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the\r
- device.\r
- EFI_INVALID_PARAMETER - The write request contains a LBA that is not\r
- valid for the device.\r
-\r
---*/\r
-{\r
- WIN_NT_BLOCK_IO_PRIVATE *Private;\r
- UINTN BytesWritten;\r
- BOOL Flag;\r
- BOOL Locked;\r
- EFI_STATUS Status;\r
- EFI_TPL OldTpl;\r
- UINTN BytesReturned;\r
-\r
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
- Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);\r
-\r
- Status = WinNtBlockIoReadWriteCommon (Private, MediaId, Lba, BufferSize, Buffer, "WinNtWriteBlocks");\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- //\r
- // According the Windows requirement, first need to lock the volume before \r
- // write to it.\r
- //\r
- if (Private->DeviceType == EfiWinNtPhysicalDisks) {\r
- Locked = Private->WinNtThunk->DeviceIoControl (Private->NtHandle, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &BytesReturned, NULL);\r
- if (Locked == 0) {\r
- DEBUG ((EFI_D_INIT, "ReadBlocks: Lock volume failed. (%d)\n", Private->WinNtThunk->GetLastError ()));\r
- Status = WinNtBlockIoError (Private);\r
- goto Done;\r
- }\r
- } else {\r
- Locked = 0;\r
- }\r
- Flag = Private->WinNtThunk->WriteFile (Private->NtHandle, Buffer, (DWORD) BufferSize, (LPDWORD) &BytesWritten, NULL);\r
- if (Locked != 0) {\r
- Private->WinNtThunk->DeviceIoControl (Private->NtHandle, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &BytesReturned, NULL);\r
- }\r
- if (!Flag || (BytesWritten != BufferSize)) {\r
- DEBUG ((EFI_D_INIT, "ReadBlocks: WriteFile failed. (%d)\n", Private->WinNtThunk->GetLastError ()));\r
- Status = WinNtBlockIoError (Private);\r
- goto Done;\r
- }\r
-\r
- //\r
- // If the write succeeded, we are not write protected and media is present.\r
- //\r
- This->Media->MediaPresent = TRUE;\r
- This->Media->ReadOnly = FALSE;\r
- Status = EFI_SUCCESS;\r
-\r
-Done:\r
- gBS->RestoreTPL (OldTpl);\r
- return Status;\r
-\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-WinNtBlockIoFlushBlocks (\r
- IN EFI_BLOCK_IO_PROTOCOL *This\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Flush the Block Device.\r
-\r
- Arguments:\r
- This - Protocol instance pointer.\r
-\r
- Returns:\r
- EFI_SUCCESS - All outstanding data was written to the device\r
- EFI_DEVICE_ERROR - The device reported an error while writting back the data\r
- EFI_NO_MEDIA - There is no media in the device.\r
-\r
---*/\r
-{\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-WinNtBlockIoResetBlock (\r
- IN EFI_BLOCK_IO_PROTOCOL *This,\r
- IN BOOLEAN ExtendedVerification\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Reset the Block Device.\r
-\r
- Arguments:\r
- This - Protocol instance pointer.\r
- ExtendedVerification - Driver may perform diagnostics on reset.\r
-\r
- Returns:\r
- EFI_SUCCESS - The device was reset.\r
- EFI_DEVICE_ERROR - The device is not functioning properly and could\r
- not be reset.\r
-\r
---*/\r
-{\r
- WIN_NT_BLOCK_IO_PRIVATE *Private;\r
- EFI_TPL OldTpl;\r
-\r
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
- Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);\r
-\r
- if (Private->NtHandle != INVALID_HANDLE_VALUE) {\r
- Private->WinNtThunk->CloseHandle (Private->NtHandle);\r
- Private->NtHandle = INVALID_HANDLE_VALUE;\r
- }\r
-\r
- gBS->RestoreTPL (OldTpl);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-EFI_STATUS\r
-SetFilePointer64 (\r
- IN WIN_NT_BLOCK_IO_PRIVATE *Private,\r
- IN INT64 DistanceToMove,\r
- OUT UINT64 *NewFilePointer,\r
- IN DWORD MoveMethod\r
- )\r
-/*++\r
-\r
-This function extends the capability of SetFilePointer to accept 64 bit parameters\r
-\r
---*/\r
-// TODO: function comment is missing 'Routine Description:'\r
-// TODO: function comment is missing 'Arguments:'\r
-// TODO: function comment is missing 'Returns:'\r
-// TODO: Private - add argument and description to function comment\r
-// TODO: DistanceToMove - add argument and description to function comment\r
-// TODO: NewFilePointer - add argument and description to function comment\r
-// TODO: MoveMethod - add argument and description to function comment\r
-{\r
- EFI_STATUS Status;\r
- LARGE_INTEGER LargeInt;\r
-\r
- LargeInt.QuadPart = DistanceToMove;\r
- Status = EFI_SUCCESS;\r
-\r
- LargeInt.LowPart = Private->WinNtThunk->SetFilePointer (\r
- Private->NtHandle,\r
- LargeInt.LowPart,\r
- &LargeInt.HighPart,\r
- MoveMethod\r
- );\r
-\r
- if (LargeInt.LowPart == -1 && Private->WinNtThunk->GetLastError () != NO_ERROR) {\r
- Status = EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (NewFilePointer != NULL) {\r
- *NewFilePointer = LargeInt.QuadPart;\r
- }\r
-\r
- return Status;\r
-}\r