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