]> git.proxmox.com Git - mirror_edk2.git/blob - Nt32Pkg/WinNtBlockIoDxe/WinNtBlockIo.c
Patch to remove STATIC modifier. This is on longer recommended by EFI Framework codin...
[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 CHAR16 *
411 GetNextElementPastTerminator (
412 IN CHAR16 *EnvironmentVariable,
413 IN CHAR16 Terminator
414 )
415 /*++
416
417 Routine Description:
418
419 Worker function to parse environment variables.
420
421 Arguments:
422 EnvironmentVariable - Envirnment variable to parse.
423
424 Terminator - Terminator to parse for.
425
426 Returns:
427
428 Pointer to next eliment past the first occurence of Terminator or the '\0'
429 at the end of the string.
430
431 --*/
432 {
433 CHAR16 *Ptr;
434
435 for (Ptr = EnvironmentVariable; *Ptr != '\0'; Ptr++) {
436 if (*Ptr == Terminator) {
437 Ptr++;
438 break;
439 }
440 }
441
442 return Ptr;
443 }
444
445 EFI_STATUS
446 WinNtBlockIoCreateMapping (
447 IN EFI_WIN_NT_IO_PROTOCOL *WinNtIo,
448 IN EFI_HANDLE EfiDeviceHandle,
449 IN CHAR16 *Filename,
450 IN BOOLEAN ReadOnly,
451 IN BOOLEAN RemovableMedia,
452 IN UINTN NumberOfBlocks,
453 IN UINTN BlockSize,
454 IN WIN_NT_RAW_DISK_DEVICE_TYPE DeviceType
455 )
456 /*++
457
458 Routine Description:
459
460 TODO: Add function description
461
462 Arguments:
463
464 WinNtIo - TODO: add argument description
465 EfiDeviceHandle - TODO: add argument description
466 Filename - TODO: add argument description
467 ReadOnly - TODO: add argument description
468 RemovableMedia - TODO: add argument description
469 NumberOfBlocks - TODO: add argument description
470 BlockSize - TODO: add argument description
471 DeviceType - TODO: add argument description
472
473 Returns:
474
475 TODO: add return values
476
477 --*/
478 {
479 EFI_STATUS Status;
480 EFI_BLOCK_IO_PROTOCOL *BlockIo;
481 WIN_NT_BLOCK_IO_PRIVATE *Private;
482 UINTN Index;
483
484 WinNtIo->WinNtThunk->SetErrorMode (SEM_FAILCRITICALERRORS);
485
486 Private = AllocatePool (sizeof (WIN_NT_BLOCK_IO_PRIVATE));
487 ASSERT (Private != NULL);
488
489 EfiInitializeLock (&Private->Lock, TPL_NOTIFY);
490
491 Private->WinNtThunk = WinNtIo->WinNtThunk;
492
493 Private->Signature = WIN_NT_BLOCK_IO_PRIVATE_SIGNATURE;
494 Private->LastBlock = NumberOfBlocks - 1;
495 Private->BlockSize = BlockSize;
496
497 for (Index = 0; Filename[Index] != 0; Index++) {
498 Private->Filename[Index] = Filename[Index];
499 }
500
501 Private->Filename[Index] = 0;
502
503 Private->ReadMode = GENERIC_READ | (ReadOnly ? 0 : GENERIC_WRITE);
504 Private->ShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
505
506 Private->NumberOfBlocks = NumberOfBlocks;
507 Private->DeviceType = DeviceType;
508 Private->NtHandle = INVALID_HANDLE_VALUE;
509
510 Private->ControllerNameTable = NULL;
511
512 AddUnicodeString2 (
513 "eng",
514 gWinNtBlockIoComponentName.SupportedLanguages,
515 &Private->ControllerNameTable,
516 Private->Filename,
517 TRUE
518 );
519 AddUnicodeString2 (
520 "en",
521 gWinNtBlockIoComponentName2.SupportedLanguages,
522 &Private->ControllerNameTable,
523 Private->Filename,
524 FALSE
525 );
526
527
528 BlockIo = &Private->BlockIo;
529 BlockIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;
530 BlockIo->Media = &Private->Media;
531 BlockIo->Media->BlockSize = Private->BlockSize;
532 BlockIo->Media->LastBlock = Private->NumberOfBlocks - 1;
533 BlockIo->Media->MediaId = 0;;
534
535 BlockIo->Reset = WinNtBlockIoResetBlock;
536 BlockIo->ReadBlocks = WinNtBlockIoReadBlocks;
537 BlockIo->WriteBlocks = WinNtBlockIoWriteBlocks;
538 BlockIo->FlushBlocks = WinNtBlockIoFlushBlocks;
539
540 BlockIo->Media->ReadOnly = ReadOnly;
541 BlockIo->Media->RemovableMedia = RemovableMedia;
542 BlockIo->Media->LogicalPartition = FALSE;
543 BlockIo->Media->MediaPresent = TRUE;
544 BlockIo->Media->WriteCaching = FALSE;
545
546 if (DeviceType == EfiWinNtVirtualDisks) {
547 BlockIo->Media->IoAlign = 1;
548
549 //
550 // Create a file to use for a virtual disk even if it does not exist.
551 //
552 Private->OpenMode = OPEN_ALWAYS;
553 } else if (DeviceType == EfiWinNtPhysicalDisks) {
554 //
555 // Physical disk and floppy devices require 4 byte alignment.
556 //
557 BlockIo->Media->IoAlign = 4;
558
559 //
560 // You can only open a physical device if it exists.
561 //
562 Private->OpenMode = OPEN_EXISTING;
563 } else {
564 ASSERT (FALSE);
565 }
566
567 Private->EfiHandle = EfiDeviceHandle;
568 Status = WinNtBlockIoOpenDevice (Private);
569 if (!EFI_ERROR (Status)) {
570
571 Status = gBS->InstallMultipleProtocolInterfaces (
572 &Private->EfiHandle,
573 &gEfiBlockIoProtocolGuid,
574 &Private->BlockIo,
575 NULL
576 );
577 if (EFI_ERROR (Status)) {
578 FreeUnicodeStringTable (Private->ControllerNameTable);
579 FreePool (Private);
580 }
581
582 DEBUG ((EFI_D_INIT, "BlockDevice added: %s\n", Filename));
583 }
584
585 return Status;
586 }
587
588 EFI_STATUS
589 WinNtBlockIoOpenDevice (
590 WIN_NT_BLOCK_IO_PRIVATE *Private
591 )
592 /*++
593
594 Routine Description:
595
596 TODO: Add function description
597
598 Arguments:
599
600 Private - TODO: add argument description
601
602 Returns:
603
604 TODO: add return values
605
606 --*/
607 {
608 EFI_STATUS Status;
609 UINT64 FileSize;
610 UINT64 EndOfFile;
611 EFI_BLOCK_IO_PROTOCOL *BlockIo;
612
613 BlockIo = &Private->BlockIo;
614 EfiAcquireLock (&Private->Lock);
615
616 //
617 // If the device is already opened, close it
618 //
619 if (Private->NtHandle != INVALID_HANDLE_VALUE) {
620 BlockIo->Reset (BlockIo, FALSE);
621 }
622
623 //
624 // Open the device
625 //
626 Private->NtHandle = Private->WinNtThunk->CreateFile (
627 Private->Filename,
628 Private->ReadMode,
629 Private->ShareMode,
630 NULL,
631 Private->OpenMode,
632 0,
633 NULL
634 );
635
636 Status = Private->WinNtThunk->GetLastError ();
637
638 if (Private->NtHandle == INVALID_HANDLE_VALUE) {
639 DEBUG ((EFI_D_INFO, "PlOpenBlock: Could not open %s, %x\n", Private->Filename, Private->WinNtThunk->GetLastError ()));
640 BlockIo->Media->MediaPresent = FALSE;
641 Status = EFI_NO_MEDIA;
642 goto Done;
643 }
644
645 if (!BlockIo->Media->MediaPresent) {
646 //
647 // BugBug: try to emulate if a CD appears - notify drivers to check it out
648 //
649 BlockIo->Media->MediaPresent = TRUE;
650 EfiReleaseLock (&Private->Lock);
651 EfiAcquireLock (&Private->Lock);
652 }
653
654 //
655 // get the size of the file
656 //
657 Status = SetFilePointer64 (Private, 0, &FileSize, FILE_END);
658
659 if (EFI_ERROR (Status)) {
660 FileSize = MultU64x32 (Private->NumberOfBlocks, Private->BlockSize);
661 if (Private->DeviceType == EfiWinNtVirtualDisks) {
662 DEBUG ((EFI_D_ERROR, "PlOpenBlock: Could not get filesize of %s\n", Private->Filename));
663 Status = EFI_UNSUPPORTED;
664 goto Done;
665 }
666 }
667
668 if (Private->NumberOfBlocks == 0) {
669 Private->NumberOfBlocks = DivU64x32 (FileSize, Private->BlockSize);
670 }
671
672 EndOfFile = MultU64x32 (Private->NumberOfBlocks, Private->BlockSize);
673
674 if (FileSize != EndOfFile) {
675 //
676 // file is not the proper size, change it
677 //
678 DEBUG ((EFI_D_INIT, "PlOpenBlock: Initializing block device: %hs\n", Private->Filename));
679
680 //
681 // first set it to 0
682 //
683 SetFilePointer64 (Private, 0, NULL, FILE_BEGIN);
684 Private->WinNtThunk->SetEndOfFile (Private->NtHandle);
685
686 //
687 // then set it to the needed file size (OS will zero fill it)
688 //
689 SetFilePointer64 (Private, EndOfFile, NULL, FILE_BEGIN);
690 Private->WinNtThunk->SetEndOfFile (Private->NtHandle);
691 }
692
693 DEBUG ((EFI_D_INIT, "%HPlOpenBlock: opened %s%N\n", Private->Filename));
694 Status = EFI_SUCCESS;
695
696 Done:
697 if (EFI_ERROR (Status)) {
698 if (Private->NtHandle != INVALID_HANDLE_VALUE) {
699 BlockIo->Reset (BlockIo, FALSE);
700 }
701 }
702
703 EfiReleaseLock (&Private->Lock);
704 return Status;
705 }
706
707 EFI_STATUS
708 WinNtBlockIoError (
709 IN WIN_NT_BLOCK_IO_PRIVATE *Private
710 )
711 /*++
712
713 Routine Description:
714
715 TODO: Add function description
716
717 Arguments:
718
719 Private - TODO: add argument description
720
721 Returns:
722
723 TODO: add return values
724
725 --*/
726 {
727 EFI_BLOCK_IO_PROTOCOL *BlockIo;
728 EFI_STATUS Status;
729 BOOLEAN ReinstallBlockIoFlag;
730
731 BlockIo = &Private->BlockIo;
732
733 switch (Private->WinNtThunk->GetLastError ()) {
734
735 case ERROR_NOT_READY:
736 Status = EFI_NO_MEDIA;
737 BlockIo->Media->ReadOnly = FALSE;
738 BlockIo->Media->MediaPresent = FALSE;
739 ReinstallBlockIoFlag = FALSE;
740 break;
741
742 case ERROR_WRONG_DISK:
743 BlockIo->Media->ReadOnly = FALSE;
744 BlockIo->Media->MediaPresent = TRUE;
745 BlockIo->Media->MediaId += 1;
746 ReinstallBlockIoFlag = TRUE;
747 Status = EFI_MEDIA_CHANGED;
748 break;
749
750 case ERROR_WRITE_PROTECT:
751 BlockIo->Media->ReadOnly = TRUE;
752 ReinstallBlockIoFlag = FALSE;
753 Status = EFI_WRITE_PROTECTED;
754 break;
755
756 default:
757 ReinstallBlockIoFlag = FALSE;
758 Status = EFI_DEVICE_ERROR;
759 break;
760 }
761
762 if (ReinstallBlockIoFlag) {
763 BlockIo->Reset (BlockIo, FALSE);
764
765 gBS->ReinstallProtocolInterface (
766 Private->EfiHandle,
767 &gEfiBlockIoProtocolGuid,
768 BlockIo,
769 BlockIo
770 );
771 }
772
773 return Status;
774 }
775
776 EFI_STATUS
777 WinNtBlockIoReadWriteCommon (
778 IN WIN_NT_BLOCK_IO_PRIVATE *Private,
779 IN UINT32 MediaId,
780 IN EFI_LBA Lba,
781 IN UINTN BufferSize,
782 IN VOID *Buffer,
783 IN CHAR8 *CallerName
784 )
785 /*++
786
787 Routine Description:
788
789 TODO: Add function description
790
791 Arguments:
792
793 Private - TODO: add argument description
794 MediaId - TODO: add argument description
795 Lba - TODO: add argument description
796 BufferSize - TODO: add argument description
797 Buffer - TODO: add argument description
798 CallerName - TODO: add argument description
799
800 Returns:
801
802 EFI_NO_MEDIA - TODO: Add description for return value
803 EFI_MEDIA_CHANGED - TODO: Add description for return value
804 EFI_INVALID_PARAMETER - TODO: Add description for return value
805 EFI_SUCCESS - TODO: Add description for return value
806 EFI_BAD_BUFFER_SIZE - TODO: Add description for return value
807 EFI_INVALID_PARAMETER - TODO: Add description for return value
808 EFI_SUCCESS - TODO: Add description for return value
809
810 --*/
811 {
812 EFI_STATUS Status;
813 UINTN BlockSize;
814 UINT64 LastBlock;
815 INT64 DistanceToMove;
816 UINT64 DistanceMoved;
817
818 if (Private->NtHandle == INVALID_HANDLE_VALUE) {
819 Status = WinNtBlockIoOpenDevice (Private);
820 if (EFI_ERROR (Status)) {
821 return Status;
822 }
823 }
824
825 if (!Private->Media.MediaPresent) {
826 DEBUG ((EFI_D_INIT, "%s: No Media\n", CallerName));
827 return EFI_NO_MEDIA;
828 }
829
830 if (Private->Media.MediaId != MediaId) {
831 return EFI_MEDIA_CHANGED;
832 }
833
834 if ((UINT32) Buffer % Private->Media.IoAlign != 0) {
835 return EFI_INVALID_PARAMETER;
836 }
837
838 //
839 // Verify buffer size
840 //
841 BlockSize = Private->BlockSize;
842 if (BufferSize == 0) {
843 DEBUG ((EFI_D_INIT, "%s: Zero length read\n", CallerName));
844 return EFI_SUCCESS;
845 }
846
847 if ((BufferSize % BlockSize) != 0) {
848 DEBUG ((EFI_D_INIT, "%s: Invalid read size\n", CallerName));
849 return EFI_BAD_BUFFER_SIZE;
850 }
851
852 LastBlock = Lba + (BufferSize / BlockSize) - 1;
853 if (LastBlock > Private->LastBlock) {
854 DEBUG ((EFI_D_INIT, "ReadBlocks: Attempted to read off end of device\n"));
855 return EFI_INVALID_PARAMETER;
856 }
857 //
858 // Seek to End of File
859 //
860 DistanceToMove = MultU64x32 (Lba, BlockSize);
861 Status = SetFilePointer64 (Private, DistanceToMove, &DistanceMoved, FILE_BEGIN);
862
863 if (EFI_ERROR (Status)) {
864 DEBUG ((EFI_D_INIT, "WriteBlocks: SetFilePointer failed\n"));
865 return WinNtBlockIoError (Private);
866 }
867
868 return EFI_SUCCESS;
869 }
870
871 EFI_STATUS
872 EFIAPI
873 WinNtBlockIoReadBlocks (
874 IN EFI_BLOCK_IO_PROTOCOL *This,
875 IN UINT32 MediaId,
876 IN EFI_LBA Lba,
877 IN UINTN BufferSize,
878 OUT VOID *Buffer
879 )
880 /*++
881
882 Routine Description:
883 Read BufferSize bytes from Lba into Buffer.
884
885 Arguments:
886 This - Protocol instance pointer.
887 MediaId - Id of the media, changes every time the media is replaced.
888 Lba - The starting Logical Block Address to read from
889 BufferSize - Size of Buffer, must be a multiple of device block size.
890 Buffer - Buffer containing read data
891
892 Returns:
893 EFI_SUCCESS - The data was read correctly from the device.
894 EFI_DEVICE_ERROR - The device reported an error while performing the read.
895 EFI_NO_MEDIA - There is no media in the device.
896 EFI_MEDIA_CHANGED - The MediaId does not matched the current device.
897 EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the
898 device.
899 EFI_INVALID_PARAMETER - The read request contains device addresses that are not
900 valid for the device.
901
902 --*/
903 {
904 WIN_NT_BLOCK_IO_PRIVATE *Private;
905 BOOL Flag;
906 EFI_STATUS Status;
907 DWORD BytesRead;
908 EFI_TPL OldTpl;
909
910 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
911
912 Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
913
914 Status = WinNtBlockIoReadWriteCommon (Private, MediaId, Lba, BufferSize, Buffer, "WinNtReadBlocks");
915 if (EFI_ERROR (Status)) {
916 goto Done;
917 }
918
919 Flag = Private->WinNtThunk->ReadFile (Private->NtHandle, Buffer, (DWORD) BufferSize, (LPDWORD) &BytesRead, NULL);
920 if (!Flag || (BytesRead != BufferSize)) {
921 DEBUG ((EFI_D_INIT, "ReadBlocks: ReadFile failed. (%d)\n", Private->WinNtThunk->GetLastError ()));
922 Status = WinNtBlockIoError (Private);
923 goto Done;
924 }
925
926 //
927 // If we wrote then media is present.
928 //
929 This->Media->MediaPresent = TRUE;
930 Status = EFI_SUCCESS;
931
932 Done:
933 gBS->RestoreTPL (OldTpl);
934 return Status;
935 }
936
937 EFI_STATUS
938 EFIAPI
939 WinNtBlockIoWriteBlocks (
940 IN EFI_BLOCK_IO_PROTOCOL *This,
941 IN UINT32 MediaId,
942 IN EFI_LBA Lba,
943 IN UINTN BufferSize,
944 IN VOID *Buffer
945 )
946 /*++
947
948 Routine Description:
949 Write BufferSize bytes from Lba into Buffer.
950
951 Arguments:
952 This - Protocol instance pointer.
953 MediaId - Id of the media, changes every time the media is replaced.
954 Lba - The starting Logical Block Address to read from
955 BufferSize - Size of Buffer, must be a multiple of device block size.
956 Buffer - Buffer containing read data
957
958 Returns:
959 EFI_SUCCESS - The data was written correctly to the device.
960 EFI_WRITE_PROTECTED - The device can not be written to.
961 EFI_DEVICE_ERROR - The device reported an error while performing the write.
962 EFI_NO_MEDIA - There is no media in the device.
963 EFI_MEDIA_CHNAGED - The MediaId does not matched the current device.
964 EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the
965 device.
966 EFI_INVALID_PARAMETER - The write request contains a LBA that is not
967 valid for the device.
968
969 --*/
970 {
971 WIN_NT_BLOCK_IO_PRIVATE *Private;
972 UINTN BytesWritten;
973 BOOL Flag;
974 EFI_STATUS Status;
975 EFI_TPL OldTpl;
976
977 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
978
979 Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
980
981 Status = WinNtBlockIoReadWriteCommon (Private, MediaId, Lba, BufferSize, Buffer, "WinNtWriteBlocks");
982 if (EFI_ERROR (Status)) {
983 goto Done;
984 }
985
986 Flag = Private->WinNtThunk->WriteFile (Private->NtHandle, Buffer, (DWORD) BufferSize, (LPDWORD) &BytesWritten, NULL);
987 if (!Flag || (BytesWritten != BufferSize)) {
988 DEBUG ((EFI_D_INIT, "ReadBlocks: WriteFile failed. (%d)\n", Private->WinNtThunk->GetLastError ()));
989 Status = WinNtBlockIoError (Private);
990 goto Done;
991 }
992
993 //
994 // If the write succeeded, we are not write protected and media is present.
995 //
996 This->Media->MediaPresent = TRUE;
997 This->Media->ReadOnly = FALSE;
998 Status = EFI_SUCCESS;
999
1000 Done:
1001 gBS->RestoreTPL (OldTpl);
1002 return Status;
1003
1004 }
1005
1006 EFI_STATUS
1007 EFIAPI
1008 WinNtBlockIoFlushBlocks (
1009 IN EFI_BLOCK_IO_PROTOCOL *This
1010 )
1011 /*++
1012
1013 Routine Description:
1014 Flush the Block Device.
1015
1016 Arguments:
1017 This - Protocol instance pointer.
1018
1019 Returns:
1020 EFI_SUCCESS - All outstanding data was written to the device
1021 EFI_DEVICE_ERROR - The device reported an error while writting back the data
1022 EFI_NO_MEDIA - There is no media in the device.
1023
1024 --*/
1025 {
1026 return EFI_SUCCESS;
1027 }
1028
1029 EFI_STATUS
1030 EFIAPI
1031 WinNtBlockIoResetBlock (
1032 IN EFI_BLOCK_IO_PROTOCOL *This,
1033 IN BOOLEAN ExtendedVerification
1034 )
1035 /*++
1036
1037 Routine Description:
1038 Reset the Block Device.
1039
1040 Arguments:
1041 This - Protocol instance pointer.
1042 ExtendedVerification - Driver may perform diagnostics on reset.
1043
1044 Returns:
1045 EFI_SUCCESS - The device was reset.
1046 EFI_DEVICE_ERROR - The device is not functioning properly and could
1047 not be reset.
1048
1049 --*/
1050 {
1051 WIN_NT_BLOCK_IO_PRIVATE *Private;
1052 EFI_TPL OldTpl;
1053
1054 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1055
1056 Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
1057
1058 if (Private->NtHandle != INVALID_HANDLE_VALUE) {
1059 Private->WinNtThunk->CloseHandle (Private->NtHandle);
1060 Private->NtHandle = INVALID_HANDLE_VALUE;
1061 }
1062
1063 gBS->RestoreTPL (OldTpl);
1064
1065 return EFI_SUCCESS;
1066 }
1067
1068
1069 EFI_STATUS
1070 SetFilePointer64 (
1071 IN WIN_NT_BLOCK_IO_PRIVATE *Private,
1072 IN INT64 DistanceToMove,
1073 OUT UINT64 *NewFilePointer,
1074 IN DWORD MoveMethod
1075 )
1076 /*++
1077
1078 This function extends the capability of SetFilePointer to accept 64 bit parameters
1079
1080 --*/
1081 // TODO: function comment is missing 'Routine Description:'
1082 // TODO: function comment is missing 'Arguments:'
1083 // TODO: function comment is missing 'Returns:'
1084 // TODO: Private - add argument and description to function comment
1085 // TODO: DistanceToMove - add argument and description to function comment
1086 // TODO: NewFilePointer - add argument and description to function comment
1087 // TODO: MoveMethod - add argument and description to function comment
1088 {
1089 EFI_STATUS Status;
1090 LARGE_INTEGER LargeInt;
1091 UINT32 ErrorCode;
1092
1093 LargeInt.QuadPart = DistanceToMove;
1094 Status = EFI_SUCCESS;
1095
1096 LargeInt.LowPart = Private->WinNtThunk->SetFilePointer (
1097 Private->NtHandle,
1098 LargeInt.LowPart,
1099 &LargeInt.HighPart,
1100 MoveMethod
1101 );
1102
1103 if (LargeInt.LowPart == -1 &&
1104 (ErrorCode = Private->WinNtThunk->GetLastError ()) != NO_ERROR) {
1105 Status = EFI_INVALID_PARAMETER;
1106 }
1107
1108 if (NewFilePointer != NULL) {
1109 *NewFilePointer = LargeInt.QuadPart;
1110 }
1111
1112 return Status;
1113 }