]> git.proxmox.com Git - mirror_edk2.git/blob - Nt32Pkg/WinNtBlockIoDxe/WinNtBlockIo.c
Modify all file header to follow doxygen format
[mirror_edk2.git] / Nt32Pkg / WinNtBlockIoDxe / WinNtBlockIo.c
1 /**@file
2
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
8
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.
11
12 Module Name:
13
14 WinNtBlockIo.c
15
16 Abstract:
17
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.
22
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.
29
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.
34
35 EFI_WIN_NT_VIRTUAL_DISKS =
36 <F | R><O | W>;<block count>;<block size>[!...]
37
38 EFI_WIN_NT_PHYSICAL_DISKS =
39 <drive letter>:<F | R><O | W>;<block count>;<block size>[!...]
40
41 Virtual Disks: These devices use a file to emulate a hard disk or removable
42 media device.
43
44 Thus a 20 MB emulated hard drive would look like:
45 EFI_WIN_NT_VIRTUAL_DISKS=FW;40960;512
46
47 A 1.44MB emulated floppy with a block size of 1024 would look like:
48 EFI_WIN_NT_VIRTUAL_DISKS=RW;1440;1024
49
50 Physical Disks: These devices use NT to open a real device in your system
51
52 Thus a 120 MB floppy would look like:
53 EFI_WIN_NT_PHYSICAL_DISKS=B:RW;245760;512
54
55 Thus a standard CD-ROM floppy would look like:
56 EFI_WIN_NT_PHYSICAL_DISKS=Z:RO;307200;2048
57
58
59 * Other names and brands may be claimed as the property of others.
60
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>
69 //
70 // The Library classes this module consumes
71 //
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>
79
80 #include "WinNtBlockIo.h"
81
82 EFI_DRIVER_BINDING_PROTOCOL gWinNtBlockIoDriverBinding = {
83 WinNtBlockIoDriverBindingSupported,
84 WinNtBlockIoDriverBindingStart,
85 WinNtBlockIoDriverBindingStop,
86 0xa,
87 NULL,
88 NULL
89 };
90
91 /**
92 The user Entry Point for module WinNtBlockIo. The user code starts with this function.
93
94 @param[in] ImageHandle The firmware allocated handle for the EFI image.
95 @param[in] SystemTable A pointer to the EFI System Table.
96
97 @retval EFI_SUCCESS The entry point is executed successfully.
98 @retval other Some error occurs when executing this entry point.
99
100 **/
101 EFI_STATUS
102 EFIAPI
103 InitializeWinNtBlockIo(
104 IN EFI_HANDLE ImageHandle,
105 IN EFI_SYSTEM_TABLE *SystemTable
106 )
107 {
108 EFI_STATUS Status;
109
110 //
111 // Install driver model protocol(s).
112 //
113 Status = EfiLibInstallAllDriverProtocols2 (
114 ImageHandle,
115 SystemTable,
116 &gWinNtBlockIoDriverBinding,
117 ImageHandle,
118 &gWinNtBlockIoComponentName,
119 &gWinNtBlockIoComponentName2,
120 NULL,
121 &gWinNtBlockIoDriverDiagnostics,
122 &gWinNtBlockIoDriverDiagnostics2
123 );
124 ASSERT_EFI_ERROR (Status);
125
126
127 return Status;
128 }
129
130 EFI_STATUS
131 EFIAPI
132 WinNtBlockIoDriverBindingSupported (
133 IN EFI_DRIVER_BINDING_PROTOCOL *This,
134 IN EFI_HANDLE Handle,
135 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
136 )
137 /*++
138
139 Routine Description:
140
141 Arguments:
142
143 Returns:
144
145 None
146
147 --*/
148 // TODO: This - add argument and description to function comment
149 // TODO: Handle - add argument and description to function comment
150 // TODO: RemainingDevicePath - add argument and description to function comment
151 {
152 EFI_STATUS Status;
153 EFI_WIN_NT_IO_PROTOCOL *WinNtIo;
154
155 //
156 // Open the IO Abstraction(s) needed to perform the supported test
157 //
158 Status = gBS->OpenProtocol (
159 Handle,
160 &gEfiWinNtIoProtocolGuid,
161 &WinNtIo,
162 This->DriverBindingHandle,
163 Handle,
164 EFI_OPEN_PROTOCOL_BY_DRIVER
165 );
166 if (EFI_ERROR (Status)) {
167 return Status;
168 }
169
170 //
171 // Make sure the WinNtThunkProtocol is valid
172 //
173 Status = EFI_UNSUPPORTED;
174 if (WinNtIo->WinNtThunk->Signature == EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE) {
175
176 //
177 // Check the GUID to see if this is a handle type the driver supports
178 //
179 if (CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtVirtualDisksGuid) ||
180 CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtPhysicalDisksGuid) ) {
181 Status = EFI_SUCCESS;
182 }
183 }
184
185 //
186 // Close the I/O Abstraction(s) used to perform the supported test
187 //
188 gBS->CloseProtocol (
189 Handle,
190 &gEfiWinNtIoProtocolGuid,
191 This->DriverBindingHandle,
192 Handle
193 );
194
195 return Status;
196 }
197
198 EFI_STATUS
199 EFIAPI
200 WinNtBlockIoDriverBindingStart (
201 IN EFI_DRIVER_BINDING_PROTOCOL *This,
202 IN EFI_HANDLE Handle,
203 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
204 )
205 /*++
206
207 Routine Description:
208
209 Arguments:
210
211 Returns:
212
213 None
214
215 --*/
216 // TODO: This - add argument and description to function comment
217 // TODO: Handle - add argument and description to function comment
218 // TODO: RemainingDevicePath - add argument and description to function comment
219 {
220 EFI_STATUS Status;
221 EFI_WIN_NT_IO_PROTOCOL *WinNtIo;
222 WIN_NT_RAW_DISK_DEVICE_TYPE DiskType;
223 UINT16 Buffer[FILENAME_BUFFER_SIZE];
224 CHAR16 *Str;
225 BOOLEAN RemovableMedia;
226 BOOLEAN WriteProtected;
227 UINTN NumberOfBlocks;
228 UINTN BlockSize;
229
230 //
231 // Grab the protocols we need
232 //
233 Status = gBS->OpenProtocol (
234 Handle,
235 &gEfiWinNtIoProtocolGuid,
236 &WinNtIo,
237 This->DriverBindingHandle,
238 Handle,
239 EFI_OPEN_PROTOCOL_BY_DRIVER
240 );
241 if (EFI_ERROR (Status)) {
242 return Status;
243 }
244
245 //
246 // Set DiskType
247 //
248 if (CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtVirtualDisksGuid)) {
249 DiskType = EfiWinNtVirtualDisks;
250 } else if (CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtPhysicalDisksGuid)) {
251 DiskType = EfiWinNtPhysicalDisks;
252 } else {
253 Status = EFI_UNSUPPORTED;
254 goto Done;
255 }
256
257 Status = EFI_NOT_FOUND;
258 Str = WinNtIo->EnvString;
259 if (DiskType == EfiWinNtVirtualDisks) {
260 WinNtIo->WinNtThunk->SPrintf (
261 Buffer,
262 sizeof (Buffer),
263 L"Diskfile%d",
264 WinNtIo->InstanceNumber
265 );
266 } else {
267 if (*Str >= 'A' && *Str <= 'Z' || *Str >= 'a' && *Str <= 'z') {
268 WinNtIo->WinNtThunk->SPrintf (Buffer, sizeof (Buffer), L"\\\\.\\%c:", *Str);
269 } else {
270 WinNtIo->WinNtThunk->SPrintf (Buffer, sizeof (Buffer), L"\\\\.\\PHYSICALDRIVE%c", *Str);
271 }
272
273 Str++;
274 if (*Str != ':') {
275 Status = EFI_NOT_FOUND;
276 goto Done;
277 }
278
279 Str++;
280 }
281
282 if (*Str == 'R' || *Str == 'F') {
283 RemovableMedia = (BOOLEAN) (*Str == 'R');
284 Str++;
285 if (*Str == 'O' || *Str == 'W') {
286 WriteProtected = (BOOLEAN) (*Str == 'O');
287 Str = GetNextElementPastTerminator (Str, ';');
288
289 NumberOfBlocks = StrDecimalToUintn (Str);
290 if (NumberOfBlocks != 0) {
291 Str = GetNextElementPastTerminator (Str, ';');
292 BlockSize = StrDecimalToUintn (Str);
293 if (BlockSize != 0) {
294 //
295 // If we get here the variable is valid so do the work.
296 //
297 Status = WinNtBlockIoCreateMapping (
298 WinNtIo,
299 Handle,
300 Buffer,
301 WriteProtected,
302 RemovableMedia,
303 NumberOfBlocks,
304 BlockSize,
305 DiskType
306 );
307
308 }
309 }
310 }
311 }
312
313 Done:
314 if (EFI_ERROR (Status)) {
315 gBS->CloseProtocol (
316 Handle,
317 &gEfiWinNtIoProtocolGuid,
318 This->DriverBindingHandle,
319 Handle
320 );
321 }
322
323 return Status;
324 }
325
326 EFI_STATUS
327 EFIAPI
328 WinNtBlockIoDriverBindingStop (
329 IN EFI_DRIVER_BINDING_PROTOCOL *This,
330 IN EFI_HANDLE Handle,
331 IN UINTN NumberOfChildren,
332 IN EFI_HANDLE *ChildHandleBuffer
333 )
334 /*++
335
336 Routine Description:
337
338 TODO: Add function description
339
340 Arguments:
341
342 This - TODO: add argument description
343 Handle - TODO: add argument description
344 NumberOfChildren - TODO: add argument description
345 ChildHandleBuffer - TODO: add argument description
346
347 Returns:
348
349 EFI_UNSUPPORTED - TODO: Add description for return value
350
351 --*/
352 {
353 EFI_BLOCK_IO_PROTOCOL *BlockIo;
354 EFI_STATUS Status;
355 WIN_NT_BLOCK_IO_PRIVATE *Private;
356
357 //
358 // Get our context back
359 //
360 Status = gBS->OpenProtocol (
361 Handle,
362 &gEfiBlockIoProtocolGuid,
363 &BlockIo,
364 This->DriverBindingHandle,
365 Handle,
366 EFI_OPEN_PROTOCOL_GET_PROTOCOL
367 );
368 if (EFI_ERROR (Status)) {
369 return EFI_UNSUPPORTED;
370 }
371
372 Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (BlockIo);
373
374 //
375 // BugBug: If we need to kick people off, we need to make Uninstall Close the handles.
376 // We could pass in our image handle or FLAG our open to be closed via
377 // Unistall (== to saying any CloseProtocol will close our open)
378 //
379 Status = gBS->UninstallMultipleProtocolInterfaces (
380 Private->EfiHandle,
381 &gEfiBlockIoProtocolGuid,
382 &Private->BlockIo,
383 NULL
384 );
385 if (!EFI_ERROR (Status)) {
386
387 Status = gBS->CloseProtocol (
388 Handle,
389 &gEfiWinNtIoProtocolGuid,
390 This->DriverBindingHandle,
391 Handle
392 );
393
394 //
395 // Shut down our device
396 //
397 Private->WinNtThunk->CloseHandle (Private->NtHandle);
398
399 //
400 // Free our instance data
401 //
402 FreeUnicodeStringTable (Private->ControllerNameTable);
403
404 FreePool (Private);
405 }
406
407 return Status;
408 }
409
410 STATIC
411 CHAR16 *
412 GetNextElementPastTerminator (
413 IN CHAR16 *EnvironmentVariable,
414 IN CHAR16 Terminator
415 )
416 /*++
417
418 Routine Description:
419
420 Worker function to parse environment variables.
421
422 Arguments:
423 EnvironmentVariable - Envirnment variable to parse.
424
425 Terminator - Terminator to parse for.
426
427 Returns:
428
429 Pointer to next eliment past the first occurence of Terminator or the '\0'
430 at the end of the string.
431
432 --*/
433 {
434 CHAR16 *Ptr;
435
436 for (Ptr = EnvironmentVariable; *Ptr != '\0'; Ptr++) {
437 if (*Ptr == Terminator) {
438 Ptr++;
439 break;
440 }
441 }
442
443 return Ptr;
444 }
445
446 STATIC
447 EFI_STATUS
448 WinNtBlockIoCreateMapping (
449 IN EFI_WIN_NT_IO_PROTOCOL *WinNtIo,
450 IN EFI_HANDLE EfiDeviceHandle,
451 IN CHAR16 *Filename,
452 IN BOOLEAN ReadOnly,
453 IN BOOLEAN RemovableMedia,
454 IN UINTN NumberOfBlocks,
455 IN UINTN BlockSize,
456 IN WIN_NT_RAW_DISK_DEVICE_TYPE DeviceType
457 )
458 /*++
459
460 Routine Description:
461
462 TODO: Add function description
463
464 Arguments:
465
466 WinNtIo - TODO: add argument description
467 EfiDeviceHandle - TODO: add argument description
468 Filename - TODO: add argument description
469 ReadOnly - TODO: add argument description
470 RemovableMedia - TODO: add argument description
471 NumberOfBlocks - TODO: add argument description
472 BlockSize - TODO: add argument description
473 DeviceType - TODO: add argument description
474
475 Returns:
476
477 TODO: add return values
478
479 --*/
480 {
481 EFI_STATUS Status;
482 EFI_BLOCK_IO_PROTOCOL *BlockIo;
483 WIN_NT_BLOCK_IO_PRIVATE *Private;
484 UINTN Index;
485
486 WinNtIo->WinNtThunk->SetErrorMode (SEM_FAILCRITICALERRORS);
487
488 Private = AllocatePool (sizeof (WIN_NT_BLOCK_IO_PRIVATE));
489 ASSERT (Private != NULL);
490
491 EfiInitializeLock (&Private->Lock, TPL_NOTIFY);
492
493 Private->WinNtThunk = WinNtIo->WinNtThunk;
494
495 Private->Signature = WIN_NT_BLOCK_IO_PRIVATE_SIGNATURE;
496 Private->LastBlock = NumberOfBlocks - 1;
497 Private->BlockSize = BlockSize;
498
499 for (Index = 0; Filename[Index] != 0; Index++) {
500 Private->Filename[Index] = Filename[Index];
501 }
502
503 Private->Filename[Index] = 0;
504
505 Private->ReadMode = GENERIC_READ | (ReadOnly ? 0 : GENERIC_WRITE);
506 Private->ShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
507
508 Private->NumberOfBlocks = NumberOfBlocks;
509 Private->DeviceType = DeviceType;
510 Private->NtHandle = INVALID_HANDLE_VALUE;
511
512 Private->ControllerNameTable = NULL;
513
514 AddUnicodeString2 (
515 "eng",
516 gWinNtBlockIoComponentName.SupportedLanguages,
517 &Private->ControllerNameTable,
518 Private->Filename,
519 TRUE
520 );
521 AddUnicodeString2 (
522 "en",
523 gWinNtBlockIoComponentName2.SupportedLanguages,
524 &Private->ControllerNameTable,
525 Private->Filename,
526 FALSE
527 );
528
529
530 BlockIo = &Private->BlockIo;
531 BlockIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;
532 BlockIo->Media = &Private->Media;
533 BlockIo->Media->BlockSize = Private->BlockSize;
534 BlockIo->Media->LastBlock = Private->NumberOfBlocks - 1;
535 BlockIo->Media->MediaId = 0;;
536
537 BlockIo->Reset = WinNtBlockIoResetBlock;
538 BlockIo->ReadBlocks = WinNtBlockIoReadBlocks;
539 BlockIo->WriteBlocks = WinNtBlockIoWriteBlocks;
540 BlockIo->FlushBlocks = WinNtBlockIoFlushBlocks;
541
542 BlockIo->Media->ReadOnly = ReadOnly;
543 BlockIo->Media->RemovableMedia = RemovableMedia;
544 BlockIo->Media->LogicalPartition = FALSE;
545 BlockIo->Media->MediaPresent = TRUE;
546 BlockIo->Media->WriteCaching = FALSE;
547
548 if (DeviceType == EfiWinNtVirtualDisks) {
549 BlockIo->Media->IoAlign = 1;
550
551 //
552 // Create a file to use for a virtual disk even if it does not exist.
553 //
554 Private->OpenMode = OPEN_ALWAYS;
555 } else if (DeviceType == EfiWinNtPhysicalDisks) {
556 //
557 // Physical disk and floppy devices require 4 byte alignment.
558 //
559 BlockIo->Media->IoAlign = 4;
560
561 //
562 // You can only open a physical device if it exists.
563 //
564 Private->OpenMode = OPEN_EXISTING;
565 } else {
566 ASSERT (FALSE);
567 }
568
569 Private->EfiHandle = EfiDeviceHandle;
570 Status = WinNtBlockIoOpenDevice (Private);
571 if (!EFI_ERROR (Status)) {
572
573 Status = gBS->InstallMultipleProtocolInterfaces (
574 &Private->EfiHandle,
575 &gEfiBlockIoProtocolGuid,
576 &Private->BlockIo,
577 NULL
578 );
579 if (EFI_ERROR (Status)) {
580 FreeUnicodeStringTable (Private->ControllerNameTable);
581 FreePool (Private);
582 }
583
584 DEBUG ((EFI_D_INIT, "BlockDevice added: %s\n", Filename));
585 }
586
587 return Status;
588 }
589
590 STATIC
591 EFI_STATUS
592 WinNtBlockIoOpenDevice (
593 WIN_NT_BLOCK_IO_PRIVATE *Private
594 )
595 /*++
596
597 Routine Description:
598
599 TODO: Add function description
600
601 Arguments:
602
603 Private - TODO: add argument description
604
605 Returns:
606
607 TODO: add return values
608
609 --*/
610 {
611 EFI_STATUS Status;
612 UINT64 FileSize;
613 UINT64 EndOfFile;
614 EFI_BLOCK_IO_PROTOCOL *BlockIo;
615
616 BlockIo = &Private->BlockIo;
617 EfiAcquireLock (&Private->Lock);
618
619 //
620 // If the device is already opened, close it
621 //
622 if (Private->NtHandle != INVALID_HANDLE_VALUE) {
623 BlockIo->Reset (BlockIo, FALSE);
624 }
625
626 //
627 // Open the device
628 //
629 Private->NtHandle = Private->WinNtThunk->CreateFile (
630 Private->Filename,
631 Private->ReadMode,
632 Private->ShareMode,
633 NULL,
634 Private->OpenMode,
635 0,
636 NULL
637 );
638
639 Status = Private->WinNtThunk->GetLastError ();
640
641 if (Private->NtHandle == INVALID_HANDLE_VALUE) {
642 DEBUG ((EFI_D_INFO, "PlOpenBlock: Could not open %s, %x\n", Private->Filename, Private->WinNtThunk->GetLastError ()));
643 BlockIo->Media->MediaPresent = FALSE;
644 Status = EFI_NO_MEDIA;
645 goto Done;
646 }
647
648 if (!BlockIo->Media->MediaPresent) {
649 //
650 // BugBug: try to emulate if a CD appears - notify drivers to check it out
651 //
652 BlockIo->Media->MediaPresent = TRUE;
653 EfiReleaseLock (&Private->Lock);
654 EfiAcquireLock (&Private->Lock);
655 }
656
657 //
658 // get the size of the file
659 //
660 Status = SetFilePointer64 (Private, 0, &FileSize, FILE_END);
661
662 if (EFI_ERROR (Status)) {
663 FileSize = MultU64x32 (Private->NumberOfBlocks, Private->BlockSize);
664 if (Private->DeviceType == EfiWinNtVirtualDisks) {
665 DEBUG ((EFI_D_ERROR, "PlOpenBlock: Could not get filesize of %s\n", Private->Filename));
666 Status = EFI_UNSUPPORTED;
667 goto Done;
668 }
669 }
670
671 if (Private->NumberOfBlocks == 0) {
672 Private->NumberOfBlocks = DivU64x32 (FileSize, Private->BlockSize);
673 }
674
675 EndOfFile = MultU64x32 (Private->NumberOfBlocks, Private->BlockSize);
676
677 if (FileSize != EndOfFile) {
678 //
679 // file is not the proper size, change it
680 //
681 DEBUG ((EFI_D_INIT, "PlOpenBlock: Initializing block device: %hs\n", Private->Filename));
682
683 //
684 // first set it to 0
685 //
686 SetFilePointer64 (Private, 0, NULL, FILE_BEGIN);
687 Private->WinNtThunk->SetEndOfFile (Private->NtHandle);
688
689 //
690 // then set it to the needed file size (OS will zero fill it)
691 //
692 SetFilePointer64 (Private, EndOfFile, NULL, FILE_BEGIN);
693 Private->WinNtThunk->SetEndOfFile (Private->NtHandle);
694 }
695
696 DEBUG ((EFI_D_INIT, "%HPlOpenBlock: opened %s%N\n", Private->Filename));
697 Status = EFI_SUCCESS;
698
699 Done:
700 if (EFI_ERROR (Status)) {
701 if (Private->NtHandle != INVALID_HANDLE_VALUE) {
702 BlockIo->Reset (BlockIo, FALSE);
703 }
704 }
705
706 EfiReleaseLock (&Private->Lock);
707 return Status;
708 }
709
710 STATIC
711 EFI_STATUS
712 WinNtBlockIoError (
713 IN WIN_NT_BLOCK_IO_PRIVATE *Private
714 )
715 /*++
716
717 Routine Description:
718
719 TODO: Add function description
720
721 Arguments:
722
723 Private - TODO: add argument description
724
725 Returns:
726
727 TODO: add return values
728
729 --*/
730 {
731 EFI_BLOCK_IO_PROTOCOL *BlockIo;
732 EFI_STATUS Status;
733 BOOLEAN ReinstallBlockIoFlag;
734
735 BlockIo = &Private->BlockIo;
736
737 switch (Private->WinNtThunk->GetLastError ()) {
738
739 case ERROR_NOT_READY:
740 Status = EFI_NO_MEDIA;
741 BlockIo->Media->ReadOnly = FALSE;
742 BlockIo->Media->MediaPresent = FALSE;
743 ReinstallBlockIoFlag = FALSE;
744 break;
745
746 case ERROR_WRONG_DISK:
747 BlockIo->Media->ReadOnly = FALSE;
748 BlockIo->Media->MediaPresent = TRUE;
749 BlockIo->Media->MediaId += 1;
750 ReinstallBlockIoFlag = TRUE;
751 Status = EFI_MEDIA_CHANGED;
752 break;
753
754 case ERROR_WRITE_PROTECT:
755 BlockIo->Media->ReadOnly = TRUE;
756 ReinstallBlockIoFlag = FALSE;
757 Status = EFI_WRITE_PROTECTED;
758 break;
759
760 default:
761 ReinstallBlockIoFlag = FALSE;
762 Status = EFI_DEVICE_ERROR;
763 break;
764 }
765
766 if (ReinstallBlockIoFlag) {
767 BlockIo->Reset (BlockIo, FALSE);
768
769 gBS->ReinstallProtocolInterface (
770 Private->EfiHandle,
771 &gEfiBlockIoProtocolGuid,
772 BlockIo,
773 BlockIo
774 );
775 }
776
777 return Status;
778 }
779
780 STATIC
781 EFI_STATUS
782 WinNtBlockIoReadWriteCommon (
783 IN WIN_NT_BLOCK_IO_PRIVATE *Private,
784 IN UINT32 MediaId,
785 IN EFI_LBA Lba,
786 IN UINTN BufferSize,
787 IN VOID *Buffer,
788 IN CHAR8 *CallerName
789 )
790 /*++
791
792 Routine Description:
793
794 TODO: Add function description
795
796 Arguments:
797
798 Private - TODO: add argument description
799 MediaId - TODO: add argument description
800 Lba - TODO: add argument description
801 BufferSize - TODO: add argument description
802 Buffer - TODO: add argument description
803 CallerName - TODO: add argument description
804
805 Returns:
806
807 EFI_NO_MEDIA - TODO: Add description for return value
808 EFI_MEDIA_CHANGED - TODO: Add description for return value
809 EFI_INVALID_PARAMETER - TODO: Add description for return value
810 EFI_SUCCESS - TODO: Add description for return value
811 EFI_BAD_BUFFER_SIZE - TODO: Add description for return value
812 EFI_INVALID_PARAMETER - TODO: Add description for return value
813 EFI_SUCCESS - TODO: Add description for return value
814
815 --*/
816 {
817 EFI_STATUS Status;
818 UINTN BlockSize;
819 UINT64 LastBlock;
820 INT64 DistanceToMove;
821 UINT64 DistanceMoved;
822
823 if (Private->NtHandle == INVALID_HANDLE_VALUE) {
824 Status = WinNtBlockIoOpenDevice (Private);
825 if (EFI_ERROR (Status)) {
826 return Status;
827 }
828 }
829
830 if (!Private->Media.MediaPresent) {
831 DEBUG ((EFI_D_INIT, "%s: No Media\n", CallerName));
832 return EFI_NO_MEDIA;
833 }
834
835 if (Private->Media.MediaId != MediaId) {
836 return EFI_MEDIA_CHANGED;
837 }
838
839 if ((UINT32) Buffer % Private->Media.IoAlign != 0) {
840 return EFI_INVALID_PARAMETER;
841 }
842
843 //
844 // Verify buffer size
845 //
846 BlockSize = Private->BlockSize;
847 if (BufferSize == 0) {
848 DEBUG ((EFI_D_INIT, "%s: Zero length read\n", CallerName));
849 return EFI_SUCCESS;
850 }
851
852 if ((BufferSize % BlockSize) != 0) {
853 DEBUG ((EFI_D_INIT, "%s: Invalid read size\n", CallerName));
854 return EFI_BAD_BUFFER_SIZE;
855 }
856
857 LastBlock = Lba + (BufferSize / BlockSize) - 1;
858 if (LastBlock > Private->LastBlock) {
859 DEBUG ((EFI_D_INIT, "ReadBlocks: Attempted to read off end of device\n"));
860 return EFI_INVALID_PARAMETER;
861 }
862 //
863 // Seek to End of File
864 //
865 DistanceToMove = MultU64x32 (Lba, BlockSize);
866 Status = SetFilePointer64 (Private, DistanceToMove, &DistanceMoved, FILE_BEGIN);
867
868 if (EFI_ERROR (Status)) {
869 DEBUG ((EFI_D_INIT, "WriteBlocks: SetFilePointer failed\n"));
870 return WinNtBlockIoError (Private);
871 }
872
873 return EFI_SUCCESS;
874 }
875
876 STATIC
877 EFI_STATUS
878 EFIAPI
879 WinNtBlockIoReadBlocks (
880 IN EFI_BLOCK_IO_PROTOCOL *This,
881 IN UINT32 MediaId,
882 IN EFI_LBA Lba,
883 IN UINTN BufferSize,
884 OUT VOID *Buffer
885 )
886 /*++
887
888 Routine Description:
889 Read BufferSize bytes from Lba into Buffer.
890
891 Arguments:
892 This - Protocol instance pointer.
893 MediaId - Id of the media, changes every time the media is replaced.
894 Lba - The starting Logical Block Address to read from
895 BufferSize - Size of Buffer, must be a multiple of device block size.
896 Buffer - Buffer containing read data
897
898 Returns:
899 EFI_SUCCESS - The data was read correctly from the device.
900 EFI_DEVICE_ERROR - The device reported an error while performing the read.
901 EFI_NO_MEDIA - There is no media in the device.
902 EFI_MEDIA_CHANGED - The MediaId does not matched the current device.
903 EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the
904 device.
905 EFI_INVALID_PARAMETER - The read request contains device addresses that are not
906 valid for the device.
907
908 --*/
909 {
910 WIN_NT_BLOCK_IO_PRIVATE *Private;
911 BOOL Flag;
912 EFI_STATUS Status;
913 DWORD BytesRead;
914 EFI_TPL OldTpl;
915
916 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
917
918 Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
919
920 Status = WinNtBlockIoReadWriteCommon (Private, MediaId, Lba, BufferSize, Buffer, "WinNtReadBlocks");
921 if (EFI_ERROR (Status)) {
922 goto Done;
923 }
924
925 Flag = Private->WinNtThunk->ReadFile (Private->NtHandle, Buffer, (DWORD) BufferSize, (LPDWORD) &BytesRead, NULL);
926 if (!Flag || (BytesRead != BufferSize)) {
927 DEBUG ((EFI_D_INIT, "ReadBlocks: ReadFile failed. (%d)\n", Private->WinNtThunk->GetLastError ()));
928 Status = WinNtBlockIoError (Private);
929 goto Done;
930 }
931
932 //
933 // If we wrote then media is present.
934 //
935 This->Media->MediaPresent = TRUE;
936 Status = EFI_SUCCESS;
937
938 Done:
939 gBS->RestoreTPL (OldTpl);
940 return Status;
941 }
942
943 STATIC
944 EFI_STATUS
945 EFIAPI
946 WinNtBlockIoWriteBlocks (
947 IN EFI_BLOCK_IO_PROTOCOL *This,
948 IN UINT32 MediaId,
949 IN EFI_LBA Lba,
950 IN UINTN BufferSize,
951 IN VOID *Buffer
952 )
953 /*++
954
955 Routine Description:
956 Write BufferSize bytes from Lba into Buffer.
957
958 Arguments:
959 This - Protocol instance pointer.
960 MediaId - Id of the media, changes every time the media is replaced.
961 Lba - The starting Logical Block Address to read from
962 BufferSize - Size of Buffer, must be a multiple of device block size.
963 Buffer - Buffer containing read data
964
965 Returns:
966 EFI_SUCCESS - The data was written correctly to the device.
967 EFI_WRITE_PROTECTED - The device can not be written to.
968 EFI_DEVICE_ERROR - The device reported an error while performing the write.
969 EFI_NO_MEDIA - There is no media in the device.
970 EFI_MEDIA_CHNAGED - The MediaId does not matched the current device.
971 EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the
972 device.
973 EFI_INVALID_PARAMETER - The write request contains a LBA that is not
974 valid for the device.
975
976 --*/
977 {
978 WIN_NT_BLOCK_IO_PRIVATE *Private;
979 UINTN BytesWritten;
980 BOOL Flag;
981 EFI_STATUS Status;
982 EFI_TPL OldTpl;
983
984 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
985
986 Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
987
988 Status = WinNtBlockIoReadWriteCommon (Private, MediaId, Lba, BufferSize, Buffer, "WinNtWriteBlocks");
989 if (EFI_ERROR (Status)) {
990 goto Done;
991 }
992
993 Flag = Private->WinNtThunk->WriteFile (Private->NtHandle, Buffer, (DWORD) BufferSize, (LPDWORD) &BytesWritten, NULL);
994 if (!Flag || (BytesWritten != BufferSize)) {
995 DEBUG ((EFI_D_INIT, "ReadBlocks: WriteFile failed. (%d)\n", Private->WinNtThunk->GetLastError ()));
996 Status = WinNtBlockIoError (Private);
997 goto Done;
998 }
999
1000 //
1001 // If the write succeeded, we are not write protected and media is present.
1002 //
1003 This->Media->MediaPresent = TRUE;
1004 This->Media->ReadOnly = FALSE;
1005 Status = EFI_SUCCESS;
1006
1007 Done:
1008 gBS->RestoreTPL (OldTpl);
1009 return Status;
1010
1011 }
1012
1013 STATIC
1014 EFI_STATUS
1015 EFIAPI
1016 WinNtBlockIoFlushBlocks (
1017 IN EFI_BLOCK_IO_PROTOCOL *This
1018 )
1019 /*++
1020
1021 Routine Description:
1022 Flush the Block Device.
1023
1024 Arguments:
1025 This - Protocol instance pointer.
1026
1027 Returns:
1028 EFI_SUCCESS - All outstanding data was written to the device
1029 EFI_DEVICE_ERROR - The device reported an error while writting back the data
1030 EFI_NO_MEDIA - There is no media in the device.
1031
1032 --*/
1033 {
1034 return EFI_SUCCESS;
1035 }
1036
1037 STATIC
1038 EFI_STATUS
1039 EFIAPI
1040 WinNtBlockIoResetBlock (
1041 IN EFI_BLOCK_IO_PROTOCOL *This,
1042 IN BOOLEAN ExtendedVerification
1043 )
1044 /*++
1045
1046 Routine Description:
1047 Reset the Block Device.
1048
1049 Arguments:
1050 This - Protocol instance pointer.
1051 ExtendedVerification - Driver may perform diagnostics on reset.
1052
1053 Returns:
1054 EFI_SUCCESS - The device was reset.
1055 EFI_DEVICE_ERROR - The device is not functioning properly and could
1056 not be reset.
1057
1058 --*/
1059 {
1060 WIN_NT_BLOCK_IO_PRIVATE *Private;
1061 EFI_TPL OldTpl;
1062
1063 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1064
1065 Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
1066
1067 if (Private->NtHandle != INVALID_HANDLE_VALUE) {
1068 Private->WinNtThunk->CloseHandle (Private->NtHandle);
1069 Private->NtHandle = INVALID_HANDLE_VALUE;
1070 }
1071
1072 gBS->RestoreTPL (OldTpl);
1073
1074 return EFI_SUCCESS;
1075 }
1076
1077
1078 EFI_STATUS
1079 SetFilePointer64 (
1080 IN WIN_NT_BLOCK_IO_PRIVATE *Private,
1081 IN INT64 DistanceToMove,
1082 OUT UINT64 *NewFilePointer,
1083 IN DWORD MoveMethod
1084 )
1085 /*++
1086
1087 This function extends the capability of SetFilePointer to accept 64 bit parameters
1088
1089 --*/
1090 // TODO: function comment is missing 'Routine Description:'
1091 // TODO: function comment is missing 'Arguments:'
1092 // TODO: function comment is missing 'Returns:'
1093 // TODO: Private - add argument and description to function comment
1094 // TODO: DistanceToMove - add argument and description to function comment
1095 // TODO: NewFilePointer - add argument and description to function comment
1096 // TODO: MoveMethod - add argument and description to function comment
1097 {
1098 EFI_STATUS Status;
1099 LARGE_INTEGER LargeInt;
1100 UINT32 ErrorCode;
1101
1102 LargeInt.QuadPart = DistanceToMove;
1103 Status = EFI_SUCCESS;
1104
1105 LargeInt.LowPart = Private->WinNtThunk->SetFilePointer (
1106 Private->NtHandle,
1107 LargeInt.LowPart,
1108 &LargeInt.HighPart,
1109 MoveMethod
1110 );
1111
1112 if (LargeInt.LowPart == -1 &&
1113 (ErrorCode = Private->WinNtThunk->GetLastError ()) != NO_ERROR) {
1114 Status = EFI_INVALID_PARAMETER;
1115 }
1116
1117 if (NewFilePointer != NULL) {
1118 *NewFilePointer = LargeInt.QuadPart;
1119 }
1120
1121 return Status;
1122 }