Add IncompatiblePciDeviceSupportDxe module in IntelFrameworkModulePkg.
[edk2.git] / Nt32Pkg / WinNtBlockIoDxe / WinNtBlockIo.c
blob291f7a08e2ec582160192cfe7ee1012246075651
1 /**@file
3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 Module Name:
14 WinNtBlockIo.c
16 Abstract:
18 Produce block IO abstractions for real devices on your PC using Win32 APIs.
19 The configuration of what devices to mount or emulate comes from NT
20 environment variables. The variables must be visible to the Microsoft*
21 Developer Studio for them to work.
23 <F>ixed - Fixed disk like a hard drive.
24 <R>emovable - Removable media like a floppy or CD-ROM.
25 Read <O>nly - Write protected device.
26 Read <W>rite - Read write device.
27 <block count> - Decimal number of blocks a device supports.
28 <block size> - Decimal number of bytes per block.
30 NT envirnonment variable contents. '<' and '>' are not part of the variable,
31 they are just used to make this help more readable. There should be no
32 spaces between the ';'. Extra spaces will break the variable. A '!' is
33 used to seperate multiple devices in a variable.
35 EFI_WIN_NT_VIRTUAL_DISKS =
36 <F | R><O | W>;<block count>;<block size>[!...]
38 EFI_WIN_NT_PHYSICAL_DISKS =
39 <drive letter>:<F | R><O | W>;<block count>;<block size>[!...]
41 Virtual Disks: These devices use a file to emulate a hard disk or removable
42 media device.
44 Thus a 20 MB emulated hard drive would look like:
45 EFI_WIN_NT_VIRTUAL_DISKS=FW;40960;512
47 A 1.44MB emulated floppy with a block size of 1024 would look like:
48 EFI_WIN_NT_VIRTUAL_DISKS=RW;1440;1024
50 Physical Disks: These devices use NT to open a real device in your system
52 Thus a 120 MB floppy would look like:
53 EFI_WIN_NT_PHYSICAL_DISKS=B:RW;245760;512
55 Thus a standard CD-ROM floppy would look like:
56 EFI_WIN_NT_PHYSICAL_DISKS=Z:RO;307200;2048
59 * Other names and brands may be claimed as the property of others.
61 **/
62 #include <Uefi.h>
63 #include <WinNtDxe.h>
64 #include <Protocol/WinNtThunk.h>
65 #include <Protocol/WinNtIo.h>
66 #include <Protocol/BlockIo.h>
67 #include <Protocol/ComponentName.h>
68 #include <Protocol/DriverBinding.h>
70 // The Library classes this module consumes
72 #include <Library/DebugLib.h>
73 #include <Library/BaseLib.h>
74 #include <Library/UefiDriverEntryPoint.h>
75 #include <Library/UefiLib.h>
76 #include <Library/BaseMemoryLib.h>
77 #include <Library/UefiBootServicesTableLib.h>
78 #include <Library/MemoryAllocationLib.h>
80 #include "WinNtBlockIo.h"
82 EFI_DRIVER_BINDING_PROTOCOL gWinNtBlockIoDriverBinding = {
83 WinNtBlockIoDriverBindingSupported,
84 WinNtBlockIoDriverBindingStart,
85 WinNtBlockIoDriverBindingStop,
86 0xa,
87 NULL,
88 NULL
91 /**
92 The user Entry Point for module WinNtBlockIo. The user code starts with this function.
94 @param[in] ImageHandle The firmware allocated handle for the EFI image.
95 @param[in] SystemTable A pointer to the EFI System Table.
97 @retval EFI_SUCCESS The entry point is executed successfully.
98 @retval other Some error occurs when executing this entry point.
101 EFI_STATUS
102 EFIAPI
103 InitializeWinNtBlockIo(
104 IN EFI_HANDLE ImageHandle,
105 IN EFI_SYSTEM_TABLE *SystemTable
108 EFI_STATUS Status;
111 // Install driver model protocol(s).
113 Status = EfiLibInstallAllDriverProtocols2 (
114 ImageHandle,
115 SystemTable,
116 &gWinNtBlockIoDriverBinding,
117 ImageHandle,
118 &gWinNtBlockIoComponentName,
119 &gWinNtBlockIoComponentName2,
120 NULL,
121 NULL,
122 &gWinNtBlockIoDriverDiagnostics,
123 &gWinNtBlockIoDriverDiagnostics2
125 ASSERT_EFI_ERROR (Status);
128 return Status;
131 EFI_STATUS
132 EFIAPI
133 WinNtBlockIoDriverBindingSupported (
134 IN EFI_DRIVER_BINDING_PROTOCOL *This,
135 IN EFI_HANDLE Handle,
136 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
138 /*++
140 Routine Description:
142 Arguments:
144 Returns:
146 None
148 --*/
149 // TODO: This - add argument and description to function comment
150 // TODO: Handle - add argument and description to function comment
151 // TODO: RemainingDevicePath - add argument and description to function comment
153 EFI_STATUS Status;
154 EFI_WIN_NT_IO_PROTOCOL *WinNtIo;
157 // Open the IO Abstraction(s) needed to perform the supported test
159 Status = gBS->OpenProtocol (
160 Handle,
161 &gEfiWinNtIoProtocolGuid,
162 (VOID **) &WinNtIo,
163 This->DriverBindingHandle,
164 Handle,
165 EFI_OPEN_PROTOCOL_BY_DRIVER
167 if (EFI_ERROR (Status)) {
168 return Status;
172 // Make sure the WinNtThunkProtocol is valid
174 Status = EFI_UNSUPPORTED;
175 if (WinNtIo->WinNtThunk->Signature == EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE) {
178 // Check the GUID to see if this is a handle type the driver supports
180 if (CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtVirtualDisksGuid) ||
181 CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtPhysicalDisksGuid) ) {
182 Status = EFI_SUCCESS;
187 // Close the I/O Abstraction(s) used to perform the supported test
189 gBS->CloseProtocol (
190 Handle,
191 &gEfiWinNtIoProtocolGuid,
192 This->DriverBindingHandle,
193 Handle
196 return Status;
199 EFI_STATUS
200 EFIAPI
201 WinNtBlockIoDriverBindingStart (
202 IN EFI_DRIVER_BINDING_PROTOCOL *This,
203 IN EFI_HANDLE Handle,
204 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
206 /*++
208 Routine Description:
210 Arguments:
212 Returns:
214 None
216 --*/
217 // TODO: This - add argument and description to function comment
218 // TODO: Handle - add argument and description to function comment
219 // TODO: RemainingDevicePath - add argument and description to function comment
221 EFI_STATUS Status;
222 EFI_WIN_NT_IO_PROTOCOL *WinNtIo;
223 WIN_NT_RAW_DISK_DEVICE_TYPE DiskType;
224 UINT16 Buffer[FILENAME_BUFFER_SIZE];
225 CHAR16 *Str;
226 BOOLEAN RemovableMedia;
227 BOOLEAN WriteProtected;
228 UINTN NumberOfBlocks;
229 UINTN BlockSize;
232 // Grab the protocols we need
234 Status = gBS->OpenProtocol (
235 Handle,
236 &gEfiWinNtIoProtocolGuid,
237 (VOID **) &WinNtIo,
238 This->DriverBindingHandle,
239 Handle,
240 EFI_OPEN_PROTOCOL_BY_DRIVER
242 if (EFI_ERROR (Status)) {
243 return Status;
247 // Set DiskType
249 if (CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtVirtualDisksGuid)) {
250 DiskType = EfiWinNtVirtualDisks;
251 } else if (CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtPhysicalDisksGuid)) {
252 DiskType = EfiWinNtPhysicalDisks;
253 } else {
254 Status = EFI_UNSUPPORTED;
255 goto Done;
258 Status = EFI_NOT_FOUND;
259 Str = WinNtIo->EnvString;
260 if (DiskType == EfiWinNtVirtualDisks) {
261 WinNtIo->WinNtThunk->SPrintf (
262 Buffer,
263 sizeof (Buffer),
264 L"Diskfile%d",
265 WinNtIo->InstanceNumber
267 } else {
268 if (*Str >= 'A' && *Str <= 'Z' || *Str >= 'a' && *Str <= 'z') {
269 WinNtIo->WinNtThunk->SPrintf (Buffer, sizeof (Buffer), L"\\\\.\\%c:", *Str);
270 } else {
271 WinNtIo->WinNtThunk->SPrintf (Buffer, sizeof (Buffer), L"\\\\.\\PHYSICALDRIVE%c", *Str);
274 Str++;
275 if (*Str != ':') {
276 Status = EFI_NOT_FOUND;
277 goto Done;
280 Str++;
283 if (*Str == 'R' || *Str == 'F') {
284 RemovableMedia = (BOOLEAN) (*Str == 'R');
285 Str++;
286 if (*Str == 'O' || *Str == 'W') {
287 WriteProtected = (BOOLEAN) (*Str == 'O');
288 Str = GetNextElementPastTerminator (Str, ';');
290 NumberOfBlocks = StrDecimalToUintn (Str);
291 if (NumberOfBlocks != 0) {
292 Str = GetNextElementPastTerminator (Str, ';');
293 BlockSize = StrDecimalToUintn (Str);
294 if (BlockSize != 0) {
296 // If we get here the variable is valid so do the work.
298 Status = WinNtBlockIoCreateMapping (
299 WinNtIo,
300 Handle,
301 Buffer,
302 WriteProtected,
303 RemovableMedia,
304 NumberOfBlocks,
305 BlockSize,
306 DiskType
314 Done:
315 if (EFI_ERROR (Status)) {
316 gBS->CloseProtocol (
317 Handle,
318 &gEfiWinNtIoProtocolGuid,
319 This->DriverBindingHandle,
320 Handle
324 return Status;
327 EFI_STATUS
328 EFIAPI
329 WinNtBlockIoDriverBindingStop (
330 IN EFI_DRIVER_BINDING_PROTOCOL *This,
331 IN EFI_HANDLE Handle,
332 IN UINTN NumberOfChildren,
333 IN EFI_HANDLE *ChildHandleBuffer
335 /*++
337 Routine Description:
339 TODO: Add function description
341 Arguments:
343 This - TODO: add argument description
344 Handle - TODO: add argument description
345 NumberOfChildren - TODO: add argument description
346 ChildHandleBuffer - TODO: add argument description
348 Returns:
350 EFI_UNSUPPORTED - TODO: Add description for return value
352 --*/
354 EFI_BLOCK_IO_PROTOCOL *BlockIo;
355 EFI_STATUS Status;
356 WIN_NT_BLOCK_IO_PRIVATE *Private;
359 // Get our context back
361 Status = gBS->OpenProtocol (
362 Handle,
363 &gEfiBlockIoProtocolGuid,
364 (VOID **) &BlockIo,
365 This->DriverBindingHandle,
366 Handle,
367 EFI_OPEN_PROTOCOL_GET_PROTOCOL
369 if (EFI_ERROR (Status)) {
370 return EFI_UNSUPPORTED;
373 Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (BlockIo);
376 // BugBug: If we need to kick people off, we need to make Uninstall Close the handles.
377 // We could pass in our image handle or FLAG our open to be closed via
378 // Unistall (== to saying any CloseProtocol will close our open)
380 Status = gBS->UninstallMultipleProtocolInterfaces (
381 Private->EfiHandle,
382 &gEfiBlockIoProtocolGuid,
383 &Private->BlockIo,
384 NULL
386 if (!EFI_ERROR (Status)) {
388 Status = gBS->CloseProtocol (
389 Handle,
390 &gEfiWinNtIoProtocolGuid,
391 This->DriverBindingHandle,
392 Handle
396 // Shut down our device
398 Private->WinNtThunk->CloseHandle (Private->NtHandle);
401 // Free our instance data
403 FreeUnicodeStringTable (Private->ControllerNameTable);
405 FreePool (Private);
408 return Status;
411 CHAR16 *
412 GetNextElementPastTerminator (
413 IN CHAR16 *EnvironmentVariable,
414 IN CHAR16 Terminator
416 /*++
418 Routine Description:
420 Worker function to parse environment variables.
422 Arguments:
423 EnvironmentVariable - Envirnment variable to parse.
425 Terminator - Terminator to parse for.
427 Returns:
429 Pointer to next eliment past the first occurence of Terminator or the '\0'
430 at the end of the string.
432 --*/
434 CHAR16 *Ptr;
436 for (Ptr = EnvironmentVariable; *Ptr != '\0'; Ptr++) {
437 if (*Ptr == Terminator) {
438 Ptr++;
439 break;
443 return Ptr;
446 EFI_STATUS
447 WinNtBlockIoCreateMapping (
448 IN EFI_WIN_NT_IO_PROTOCOL *WinNtIo,
449 IN EFI_HANDLE EfiDeviceHandle,
450 IN CHAR16 *Filename,
451 IN BOOLEAN ReadOnly,
452 IN BOOLEAN RemovableMedia,
453 IN UINTN NumberOfBlocks,
454 IN UINTN BlockSize,
455 IN WIN_NT_RAW_DISK_DEVICE_TYPE DeviceType
457 /*++
459 Routine Description:
461 TODO: Add function description
463 Arguments:
465 WinNtIo - TODO: add argument description
466 EfiDeviceHandle - TODO: add argument description
467 Filename - TODO: add argument description
468 ReadOnly - TODO: add argument description
469 RemovableMedia - TODO: add argument description
470 NumberOfBlocks - TODO: add argument description
471 BlockSize - TODO: add argument description
472 DeviceType - TODO: add argument description
474 Returns:
476 TODO: add return values
478 --*/
480 EFI_STATUS Status;
481 EFI_BLOCK_IO_PROTOCOL *BlockIo;
482 WIN_NT_BLOCK_IO_PRIVATE *Private;
483 UINTN Index;
485 WinNtIo->WinNtThunk->SetErrorMode (SEM_FAILCRITICALERRORS);
487 Private = AllocatePool (sizeof (WIN_NT_BLOCK_IO_PRIVATE));
488 ASSERT (Private != NULL);
490 EfiInitializeLock (&Private->Lock, TPL_NOTIFY);
492 Private->WinNtThunk = WinNtIo->WinNtThunk;
494 Private->Signature = WIN_NT_BLOCK_IO_PRIVATE_SIGNATURE;
495 Private->LastBlock = NumberOfBlocks - 1;
496 Private->BlockSize = BlockSize;
498 for (Index = 0; Filename[Index] != 0; Index++) {
499 Private->Filename[Index] = Filename[Index];
502 Private->Filename[Index] = 0;
504 Private->ReadMode = GENERIC_READ | (ReadOnly ? 0 : GENERIC_WRITE);
505 Private->ShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
507 Private->NumberOfBlocks = NumberOfBlocks;
508 Private->DeviceType = DeviceType;
509 Private->NtHandle = INVALID_HANDLE_VALUE;
511 Private->ControllerNameTable = NULL;
513 AddUnicodeString2 (
514 "eng",
515 gWinNtBlockIoComponentName.SupportedLanguages,
516 &Private->ControllerNameTable,
517 Private->Filename,
518 TRUE
520 AddUnicodeString2 (
521 "en",
522 gWinNtBlockIoComponentName2.SupportedLanguages,
523 &Private->ControllerNameTable,
524 Private->Filename,
525 FALSE
529 BlockIo = &Private->BlockIo;
530 BlockIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;
531 BlockIo->Media = &Private->Media;
532 BlockIo->Media->BlockSize = Private->BlockSize;
533 BlockIo->Media->LastBlock = Private->NumberOfBlocks - 1;
534 BlockIo->Media->MediaId = 0;;
536 BlockIo->Reset = WinNtBlockIoResetBlock;
537 BlockIo->ReadBlocks = WinNtBlockIoReadBlocks;
538 BlockIo->WriteBlocks = WinNtBlockIoWriteBlocks;
539 BlockIo->FlushBlocks = WinNtBlockIoFlushBlocks;
541 BlockIo->Media->ReadOnly = ReadOnly;
542 BlockIo->Media->RemovableMedia = RemovableMedia;
543 BlockIo->Media->LogicalPartition = FALSE;
544 BlockIo->Media->MediaPresent = TRUE;
545 BlockIo->Media->WriteCaching = FALSE;
547 if (DeviceType == EfiWinNtVirtualDisks) {
548 BlockIo->Media->IoAlign = 1;
551 // Create a file to use for a virtual disk even if it does not exist.
553 Private->OpenMode = OPEN_ALWAYS;
554 } else if (DeviceType == EfiWinNtPhysicalDisks) {
556 // Physical disk and floppy devices require 4 byte alignment.
558 BlockIo->Media->IoAlign = 4;
561 // You can only open a physical device if it exists.
563 Private->OpenMode = OPEN_EXISTING;
564 } else {
565 ASSERT (FALSE);
568 Private->EfiHandle = EfiDeviceHandle;
569 Status = WinNtBlockIoOpenDevice (Private);
570 if (!EFI_ERROR (Status)) {
572 Status = gBS->InstallMultipleProtocolInterfaces (
573 &Private->EfiHandle,
574 &gEfiBlockIoProtocolGuid,
575 &Private->BlockIo,
576 NULL
578 if (EFI_ERROR (Status)) {
579 FreeUnicodeStringTable (Private->ControllerNameTable);
580 FreePool (Private);
583 DEBUG ((EFI_D_INIT, "BlockDevice added: %s\n", Filename));
586 return Status;
589 EFI_STATUS
590 WinNtBlockIoOpenDevice (
591 WIN_NT_BLOCK_IO_PRIVATE *Private
593 /*++
595 Routine Description:
597 TODO: Add function description
599 Arguments:
601 Private - TODO: add argument description
603 Returns:
605 TODO: add return values
607 --*/
609 EFI_STATUS Status;
610 UINT64 FileSize;
611 UINT64 EndOfFile;
612 EFI_BLOCK_IO_PROTOCOL *BlockIo;
614 BlockIo = &Private->BlockIo;
615 EfiAcquireLock (&Private->Lock);
618 // If the device is already opened, close it
620 if (Private->NtHandle != INVALID_HANDLE_VALUE) {
621 BlockIo->Reset (BlockIo, FALSE);
625 // Open the device
627 Private->NtHandle = Private->WinNtThunk->CreateFile (
628 Private->Filename,
629 Private->ReadMode,
630 Private->ShareMode,
631 NULL,
632 Private->OpenMode,
634 NULL
637 Status = Private->WinNtThunk->GetLastError ();
639 if (Private->NtHandle == INVALID_HANDLE_VALUE) {
640 DEBUG ((EFI_D_INFO, "PlOpenBlock: Could not open %s, %x\n", Private->Filename, Private->WinNtThunk->GetLastError ()));
641 BlockIo->Media->MediaPresent = FALSE;
642 Status = EFI_NO_MEDIA;
643 goto Done;
646 if (!BlockIo->Media->MediaPresent) {
648 // BugBug: try to emulate if a CD appears - notify drivers to check it out
650 BlockIo->Media->MediaPresent = TRUE;
651 EfiReleaseLock (&Private->Lock);
652 EfiAcquireLock (&Private->Lock);
656 // get the size of the file
658 Status = SetFilePointer64 (Private, 0, &FileSize, FILE_END);
660 if (EFI_ERROR (Status)) {
661 FileSize = MultU64x32 (Private->NumberOfBlocks, Private->BlockSize);
662 if (Private->DeviceType == EfiWinNtVirtualDisks) {
663 DEBUG ((EFI_D_ERROR, "PlOpenBlock: Could not get filesize of %s\n", Private->Filename));
664 Status = EFI_UNSUPPORTED;
665 goto Done;
669 if (Private->NumberOfBlocks == 0) {
670 Private->NumberOfBlocks = DivU64x32 (FileSize, Private->BlockSize);
673 EndOfFile = MultU64x32 (Private->NumberOfBlocks, Private->BlockSize);
675 if (FileSize != EndOfFile) {
677 // file is not the proper size, change it
679 DEBUG ((EFI_D_INIT, "PlOpenBlock: Initializing block device: %hs\n", Private->Filename));
682 // first set it to 0
684 SetFilePointer64 (Private, 0, NULL, FILE_BEGIN);
685 Private->WinNtThunk->SetEndOfFile (Private->NtHandle);
688 // then set it to the needed file size (OS will zero fill it)
690 SetFilePointer64 (Private, EndOfFile, NULL, FILE_BEGIN);
691 Private->WinNtThunk->SetEndOfFile (Private->NtHandle);
694 DEBUG ((EFI_D_INIT, "%HPlOpenBlock: opened %s%N\n", Private->Filename));
695 Status = EFI_SUCCESS;
697 Done:
698 if (EFI_ERROR (Status)) {
699 if (Private->NtHandle != INVALID_HANDLE_VALUE) {
700 BlockIo->Reset (BlockIo, FALSE);
704 EfiReleaseLock (&Private->Lock);
705 return Status;
708 EFI_STATUS
709 WinNtBlockIoError (
710 IN WIN_NT_BLOCK_IO_PRIVATE *Private
712 /*++
714 Routine Description:
716 TODO: Add function description
718 Arguments:
720 Private - TODO: add argument description
722 Returns:
724 TODO: add return values
726 --*/
728 EFI_BLOCK_IO_PROTOCOL *BlockIo;
729 EFI_STATUS Status;
730 BOOLEAN ReinstallBlockIoFlag;
732 BlockIo = &Private->BlockIo;
734 switch (Private->WinNtThunk->GetLastError ()) {
736 case ERROR_NOT_READY:
737 Status = EFI_NO_MEDIA;
738 BlockIo->Media->ReadOnly = FALSE;
739 BlockIo->Media->MediaPresent = FALSE;
740 ReinstallBlockIoFlag = FALSE;
741 break;
743 case ERROR_WRONG_DISK:
744 BlockIo->Media->ReadOnly = FALSE;
745 BlockIo->Media->MediaPresent = TRUE;
746 BlockIo->Media->MediaId += 1;
747 ReinstallBlockIoFlag = TRUE;
748 Status = EFI_MEDIA_CHANGED;
749 break;
751 case ERROR_WRITE_PROTECT:
752 BlockIo->Media->ReadOnly = TRUE;
753 ReinstallBlockIoFlag = FALSE;
754 Status = EFI_WRITE_PROTECTED;
755 break;
757 default:
758 ReinstallBlockIoFlag = FALSE;
759 Status = EFI_DEVICE_ERROR;
760 break;
763 if (ReinstallBlockIoFlag) {
764 BlockIo->Reset (BlockIo, FALSE);
766 gBS->ReinstallProtocolInterface (
767 Private->EfiHandle,
768 &gEfiBlockIoProtocolGuid,
769 BlockIo,
770 BlockIo
774 return Status;
777 EFI_STATUS
778 WinNtBlockIoReadWriteCommon (
779 IN WIN_NT_BLOCK_IO_PRIVATE *Private,
780 IN UINT32 MediaId,
781 IN EFI_LBA Lba,
782 IN UINTN BufferSize,
783 IN VOID *Buffer,
784 IN CHAR8 *CallerName
786 /*++
788 Routine Description:
790 TODO: Add function description
792 Arguments:
794 Private - TODO: add argument description
795 MediaId - TODO: add argument description
796 Lba - TODO: add argument description
797 BufferSize - TODO: add argument description
798 Buffer - TODO: add argument description
799 CallerName - TODO: add argument description
801 Returns:
803 EFI_NO_MEDIA - TODO: Add description for return value
804 EFI_MEDIA_CHANGED - TODO: Add description for return value
805 EFI_INVALID_PARAMETER - TODO: Add description for return value
806 EFI_SUCCESS - TODO: Add description for return value
807 EFI_BAD_BUFFER_SIZE - TODO: Add description for return value
808 EFI_INVALID_PARAMETER - TODO: Add description for return value
809 EFI_SUCCESS - TODO: Add description for return value
811 --*/
813 EFI_STATUS Status;
814 UINTN BlockSize;
815 UINT64 LastBlock;
816 INT64 DistanceToMove;
817 UINT64 DistanceMoved;
819 if (Private->NtHandle == INVALID_HANDLE_VALUE) {
820 Status = WinNtBlockIoOpenDevice (Private);
821 if (EFI_ERROR (Status)) {
822 return Status;
826 if (!Private->Media.MediaPresent) {
827 DEBUG ((EFI_D_INIT, "%s: No Media\n", CallerName));
828 return EFI_NO_MEDIA;
831 if (Private->Media.MediaId != MediaId) {
832 return EFI_MEDIA_CHANGED;
835 if ((UINT32) Buffer % Private->Media.IoAlign != 0) {
836 return EFI_INVALID_PARAMETER;
840 // Verify buffer size
842 BlockSize = Private->BlockSize;
843 if (BufferSize == 0) {
844 DEBUG ((EFI_D_INIT, "%s: Zero length read\n", CallerName));
845 return EFI_SUCCESS;
848 if ((BufferSize % BlockSize) != 0) {
849 DEBUG ((EFI_D_INIT, "%s: Invalid read size\n", CallerName));
850 return EFI_BAD_BUFFER_SIZE;
853 LastBlock = Lba + (BufferSize / BlockSize) - 1;
854 if (LastBlock > Private->LastBlock) {
855 DEBUG ((EFI_D_INIT, "ReadBlocks: Attempted to read off end of device\n"));
856 return EFI_INVALID_PARAMETER;
859 // Seek to End of File
861 DistanceToMove = MultU64x32 (Lba, BlockSize);
862 Status = SetFilePointer64 (Private, DistanceToMove, &DistanceMoved, FILE_BEGIN);
864 if (EFI_ERROR (Status)) {
865 DEBUG ((EFI_D_INIT, "WriteBlocks: SetFilePointer failed\n"));
866 return WinNtBlockIoError (Private);
869 return EFI_SUCCESS;
872 EFI_STATUS
873 EFIAPI
874 WinNtBlockIoReadBlocks (
875 IN EFI_BLOCK_IO_PROTOCOL *This,
876 IN UINT32 MediaId,
877 IN EFI_LBA Lba,
878 IN UINTN BufferSize,
879 OUT VOID *Buffer
881 /*++
883 Routine Description:
884 Read BufferSize bytes from Lba into Buffer.
886 Arguments:
887 This - Protocol instance pointer.
888 MediaId - Id of the media, changes every time the media is replaced.
889 Lba - The starting Logical Block Address to read from
890 BufferSize - Size of Buffer, must be a multiple of device block size.
891 Buffer - Buffer containing read data
893 Returns:
894 EFI_SUCCESS - The data was read correctly from the device.
895 EFI_DEVICE_ERROR - The device reported an error while performing the read.
896 EFI_NO_MEDIA - There is no media in the device.
897 EFI_MEDIA_CHANGED - The MediaId does not matched the current device.
898 EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the
899 device.
900 EFI_INVALID_PARAMETER - The read request contains device addresses that are not
901 valid for the device.
903 --*/
905 WIN_NT_BLOCK_IO_PRIVATE *Private;
906 BOOL Flag;
907 EFI_STATUS Status;
908 DWORD BytesRead;
909 EFI_TPL OldTpl;
911 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
913 Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
915 Status = WinNtBlockIoReadWriteCommon (Private, MediaId, Lba, BufferSize, Buffer, "WinNtReadBlocks");
916 if (EFI_ERROR (Status)) {
917 goto Done;
920 Flag = Private->WinNtThunk->ReadFile (Private->NtHandle, Buffer, (DWORD) BufferSize, (LPDWORD) &BytesRead, NULL);
921 if (!Flag || (BytesRead != BufferSize)) {
922 DEBUG ((EFI_D_INIT, "ReadBlocks: ReadFile failed. (%d)\n", Private->WinNtThunk->GetLastError ()));
923 Status = WinNtBlockIoError (Private);
924 goto Done;
928 // If we wrote then media is present.
930 This->Media->MediaPresent = TRUE;
931 Status = EFI_SUCCESS;
933 Done:
934 gBS->RestoreTPL (OldTpl);
935 return Status;
938 EFI_STATUS
939 EFIAPI
940 WinNtBlockIoWriteBlocks (
941 IN EFI_BLOCK_IO_PROTOCOL *This,
942 IN UINT32 MediaId,
943 IN EFI_LBA Lba,
944 IN UINTN BufferSize,
945 IN VOID *Buffer
947 /*++
949 Routine Description:
950 Write BufferSize bytes from Lba into Buffer.
952 Arguments:
953 This - Protocol instance pointer.
954 MediaId - Id of the media, changes every time the media is replaced.
955 Lba - The starting Logical Block Address to read from
956 BufferSize - Size of Buffer, must be a multiple of device block size.
957 Buffer - Buffer containing read data
959 Returns:
960 EFI_SUCCESS - The data was written correctly to the device.
961 EFI_WRITE_PROTECTED - The device can not be written to.
962 EFI_DEVICE_ERROR - The device reported an error while performing the write.
963 EFI_NO_MEDIA - There is no media in the device.
964 EFI_MEDIA_CHNAGED - The MediaId does not matched the current device.
965 EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the
966 device.
967 EFI_INVALID_PARAMETER - The write request contains a LBA that is not
968 valid for the device.
970 --*/
972 WIN_NT_BLOCK_IO_PRIVATE *Private;
973 UINTN BytesWritten;
974 BOOL Flag;
975 EFI_STATUS Status;
976 EFI_TPL OldTpl;
978 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
980 Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
982 Status = WinNtBlockIoReadWriteCommon (Private, MediaId, Lba, BufferSize, Buffer, "WinNtWriteBlocks");
983 if (EFI_ERROR (Status)) {
984 goto Done;
987 Flag = Private->WinNtThunk->WriteFile (Private->NtHandle, Buffer, (DWORD) BufferSize, (LPDWORD) &BytesWritten, NULL);
988 if (!Flag || (BytesWritten != BufferSize)) {
989 DEBUG ((EFI_D_INIT, "ReadBlocks: WriteFile failed. (%d)\n", Private->WinNtThunk->GetLastError ()));
990 Status = WinNtBlockIoError (Private);
991 goto Done;
995 // If the write succeeded, we are not write protected and media is present.
997 This->Media->MediaPresent = TRUE;
998 This->Media->ReadOnly = FALSE;
999 Status = EFI_SUCCESS;
1001 Done:
1002 gBS->RestoreTPL (OldTpl);
1003 return Status;
1007 EFI_STATUS
1008 EFIAPI
1009 WinNtBlockIoFlushBlocks (
1010 IN EFI_BLOCK_IO_PROTOCOL *This
1012 /*++
1014 Routine Description:
1015 Flush the Block Device.
1017 Arguments:
1018 This - Protocol instance pointer.
1020 Returns:
1021 EFI_SUCCESS - All outstanding data was written to the device
1022 EFI_DEVICE_ERROR - The device reported an error while writting back the data
1023 EFI_NO_MEDIA - There is no media in the device.
1025 --*/
1027 return EFI_SUCCESS;
1030 EFI_STATUS
1031 EFIAPI
1032 WinNtBlockIoResetBlock (
1033 IN EFI_BLOCK_IO_PROTOCOL *This,
1034 IN BOOLEAN ExtendedVerification
1036 /*++
1038 Routine Description:
1039 Reset the Block Device.
1041 Arguments:
1042 This - Protocol instance pointer.
1043 ExtendedVerification - Driver may perform diagnostics on reset.
1045 Returns:
1046 EFI_SUCCESS - The device was reset.
1047 EFI_DEVICE_ERROR - The device is not functioning properly and could
1048 not be reset.
1050 --*/
1052 WIN_NT_BLOCK_IO_PRIVATE *Private;
1053 EFI_TPL OldTpl;
1055 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1057 Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
1059 if (Private->NtHandle != INVALID_HANDLE_VALUE) {
1060 Private->WinNtThunk->CloseHandle (Private->NtHandle);
1061 Private->NtHandle = INVALID_HANDLE_VALUE;
1064 gBS->RestoreTPL (OldTpl);
1066 return EFI_SUCCESS;
1070 EFI_STATUS
1071 SetFilePointer64 (
1072 IN WIN_NT_BLOCK_IO_PRIVATE *Private,
1073 IN INT64 DistanceToMove,
1074 OUT UINT64 *NewFilePointer,
1075 IN DWORD MoveMethod
1077 /*++
1079 This function extends the capability of SetFilePointer to accept 64 bit parameters
1081 --*/
1082 // TODO: function comment is missing 'Routine Description:'
1083 // TODO: function comment is missing 'Arguments:'
1084 // TODO: function comment is missing 'Returns:'
1085 // TODO: Private - add argument and description to function comment
1086 // TODO: DistanceToMove - add argument and description to function comment
1087 // TODO: NewFilePointer - add argument and description to function comment
1088 // TODO: MoveMethod - add argument and description to function comment
1090 EFI_STATUS Status;
1091 LARGE_INTEGER LargeInt;
1093 LargeInt.QuadPart = DistanceToMove;
1094 Status = EFI_SUCCESS;
1096 LargeInt.LowPart = Private->WinNtThunk->SetFilePointer (
1097 Private->NtHandle,
1098 LargeInt.LowPart,
1099 &LargeInt.HighPart,
1100 MoveMethod
1103 if (LargeInt.LowPart == -1 && Private->WinNtThunk->GetLastError () != NO_ERROR) {
1104 Status = EFI_INVALID_PARAMETER;
1107 if (NewFilePointer != NULL) {
1108 *NewFilePointer = LargeInt.QuadPart;
1111 return Status;