TianoCore EDK2 master
Loading...
Searching...
No Matches
WinBlockIo.c
Go to the documentation of this file.
1
8#include "WinHost.h"
9
10#define WIN_NT_BLOCK_IO_PRIVATE_SIGNATURE SIGNATURE_32 ('N', 'T', 'b', 'k')
11typedef struct {
12 UINTN Signature;
13
15
16 CHAR16 *FileName;
17 BOOLEAN Removable;
18 BOOLEAN Readonly;
19
20 HANDLE NtHandle;
21 UINT32 BlockSize;
22
23 EFI_BLOCK_IO_MEDIA *Media;
24 EMU_BLOCK_IO_PROTOCOL EmuBlockIo;
26
27#define WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS(a) \
28 CR(a, WIN_NT_BLOCK_IO_PRIVATE, EmuBlockIo, WIN_NT_BLOCK_IO_PRIVATE_SIGNATURE)
29
33 IN BOOLEAN ExtendedVerification
34 );
35
37SetFilePointer64 (
39 IN INT64 DistanceToMove,
40 OUT UINT64 *NewFilePointer,
41 IN DWORD MoveMethod
42 )
43
44/*++
45
46This function extends the capability of SetFilePointer to accept 64 bit parameters
47
48--*/
49{
50 EFI_STATUS Status;
51 LARGE_INTEGER LargeInt;
52
53 LargeInt.QuadPart = DistanceToMove;
54 Status = EFI_SUCCESS;
55
56 LargeInt.LowPart = SetFilePointer (
57 Private->NtHandle,
58 LargeInt.LowPart,
59 &LargeInt.HighPart,
60 MoveMethod
61 );
62
63 if ((LargeInt.LowPart == -1) && (GetLastError () != NO_ERROR)) {
64 Status = EFI_INVALID_PARAMETER;
65 }
66
67 if (NewFilePointer != NULL) {
68 *NewFilePointer = LargeInt.QuadPart;
69 }
70
71 return Status;
72}
73
75WinNtBlockIoOpenDevice (
78 )
79{
80 EFI_STATUS Status;
81 UINT64 FileSize;
82
83 //
84 // If the device is already opened, close it
85 //
86 if (Private->NtHandle != INVALID_HANDLE_VALUE) {
87 WinNtBlockIoReset (&Private->EmuBlockIo, FALSE);
88 }
89
90 //
91 // Open the device
92 //
93 Private->NtHandle = CreateFile (
94 Private->FileName,
95 GENERIC_READ | (Private->Readonly ? 0 : GENERIC_WRITE),
96 FILE_SHARE_READ | FILE_SHARE_WRITE,
97 NULL,
98 OPEN_ALWAYS, // Create if it doesn't exist
99 0,
100 NULL
101 );
102
103 if (Private->NtHandle == INVALID_HANDLE_VALUE) {
104 DEBUG ((DEBUG_INFO, "OpenBlock: Could not open %S, %x\n", Private->FileName, GetLastError ()));
105 Media->MediaPresent = FALSE;
106 Status = EFI_NO_MEDIA;
107 goto Done;
108 }
109
110 //
111 // get the size of the file
112 //
113 Status = SetFilePointer64 (Private, 0, &FileSize, FILE_END);
114
115 if (EFI_ERROR (Status)) {
116 DEBUG ((DEBUG_ERROR, "OpenBlock: Could not get filesize of %s\n", Private->FileName));
117 Status = EFI_UNSUPPORTED;
118 goto Done;
119 }
120
121 Media->LastBlock = DivU64x32 (FileSize, (UINT32)Private->BlockSize) - 1;
122
123 DEBUG ((DEBUG_INIT, "OpenBlock: opened %S\n", Private->FileName));
124 Status = EFI_SUCCESS;
125
126Done:
127 if (EFI_ERROR (Status)) {
128 if (Private->NtHandle != INVALID_HANDLE_VALUE) {
129 WinNtBlockIoReset (&Private->EmuBlockIo, FALSE);
130 }
131 }
132
133 return Status;
134}
135
137EFIAPI
138WinNtBlockIoCreateMapping (
141 )
142{
144
145 Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
146
147 Media->MediaId = 0;
148 Media->RemovableMedia = Private->Removable;
149 Media->MediaPresent = TRUE;
150 Media->LogicalPartition = FALSE;
151 Media->ReadOnly = Private->Readonly;
152 Media->WriteCaching = FALSE;
153 Media->IoAlign = 1;
154 Media->LastBlock = 0; // Filled in by OpenDevice
155 Media->BlockSize = Private->BlockSize;
156
157 // EFI_BLOCK_IO_PROTOCOL_REVISION2
158 Media->LowestAlignedLba = 0;
159 Media->LogicalBlocksPerPhysicalBlock = 0;
160
161 // EFI_BLOCK_IO_PROTOCOL_REVISION3
162 Media->OptimalTransferLengthGranularity = 0;
163
164 //
165 // Remember the Media pointer.
166 //
167 Private->Media = Media;
168 return WinNtBlockIoOpenDevice (Private, Media);
169}
170
172WinNtBlockIoError (
174 )
175
176/*++
177
178Routine Description:
179
180 TODO: Add function description
181
182Arguments:
183
184 Private - TODO: add argument description
185
186Returns:
187
188 TODO: add return values
189
190--*/
191{
192 EFI_BLOCK_IO_MEDIA *Media;
193 EFI_STATUS Status;
194
195 Media = Private->Media;
196
197 switch (GetLastError ()) {
198 case ERROR_NOT_READY:
199 Media->ReadOnly = FALSE;
200 Media->MediaPresent = FALSE;
201 Status = EFI_NO_MEDIA;
202 break;
203
204 case ERROR_WRONG_DISK:
205 Media->ReadOnly = FALSE;
206 Media->MediaPresent = TRUE;
207 Media->MediaId++;
208 Status = EFI_MEDIA_CHANGED;
209 break;
210
211 case ERROR_WRITE_PROTECT:
212 Media->ReadOnly = TRUE;
213 Status = EFI_WRITE_PROTECTED;
214 break;
215
216 default:
217 Status = EFI_DEVICE_ERROR;
218 break;
219 }
220
221 if ((Status == EFI_NO_MEDIA) || (Status == EFI_MEDIA_CHANGED)) {
222 WinNtBlockIoReset (&Private->EmuBlockIo, FALSE);
223 }
224
225 return Status;
226}
227
229WinNtSignalToken (
231 IN EFI_STATUS Status
232 )
233{
234 if (Token != NULL) {
235 if (Token->Event != NULL) {
236 // Caller is responcible for signaling EFI Event
237 Token->TransactionStatus = Status;
238 return EFI_SUCCESS;
239 }
240 }
241
242 return Status;
243}
244
281 IN UINT32 MediaId,
282 IN EFI_LBA Lba,
284 IN UINTN BufferSize,
285 OUT VOID *Buffer
286 )
287{
289 BOOL Flag;
290 EFI_STATUS Status;
291 DWORD BytesRead;
292 UINT64 DistanceToMove;
293 UINT64 DistanceMoved;
294
295 Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
296
297 //
298 // Seek to proper position
299 //
300 DistanceToMove = MultU64x32 (Lba, (UINT32)Private->BlockSize);
301 Status = SetFilePointer64 (Private, DistanceToMove, &DistanceMoved, FILE_BEGIN);
302
303 if (EFI_ERROR (Status) || (DistanceToMove != DistanceMoved)) {
304 DEBUG ((DEBUG_INIT, "ReadBlocks: SetFilePointer failed\n"));
305 return WinNtBlockIoError (Private->Media);
306 }
307
308 Flag = ReadFile (Private->NtHandle, Buffer, (DWORD)BufferSize, (LPDWORD)&BytesRead, NULL);
309 if (!Flag || (BytesRead != BufferSize)) {
310 return WinNtBlockIoError (Private->Media);
311 }
312
313 Private->Media->MediaPresent = TRUE;
314 return WinNtSignalToken (Token, EFI_SUCCESS);
315}
316
351 IN UINT32 MediaId,
352 IN EFI_LBA Lba,
354 IN UINTN BufferSize,
355 IN VOID *Buffer
356 )
357{
359 UINTN BytesWritten;
360 BOOL Success;
361 EFI_STATUS Status;
362 UINT64 DistanceToMove;
363 UINT64 DistanceMoved;
364
365 Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
366
367 //
368 // Seek to proper position
369 //
370 DistanceToMove = MultU64x32 (Lba, (UINT32)Private->BlockSize);
371 Status = SetFilePointer64 (Private, DistanceToMove, &DistanceMoved, FILE_BEGIN);
372
373 if (EFI_ERROR (Status) || (DistanceToMove != DistanceMoved)) {
374 DEBUG ((DEBUG_INIT, "WriteBlocks: SetFilePointer failed\n"));
375 return WinNtBlockIoError (Private->Media);
376 }
377
378 Success = WriteFile (Private->NtHandle, Buffer, (DWORD)BufferSize, (LPDWORD)&BytesWritten, NULL);
379 if (!Success || (BytesWritten != BufferSize)) {
380 return WinNtBlockIoError (Private->Media);
381 }
382
383 //
384 // If the write succeeded, we are not write protected and media is present.
385 //
386 Private->Media->MediaPresent = TRUE;
387 Private->Media->ReadOnly = FALSE;
388 return WinNtSignalToken (Token, EFI_SUCCESS);
389}
390
417 )
418{
419 return WinNtSignalToken (Token, EFI_SUCCESS);
420}
421
438 IN BOOLEAN ExtendedVerification
439 )
440{
442
443 Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
444
445 if (Private->NtHandle != INVALID_HANDLE_VALUE) {
446 CloseHandle (Private->NtHandle);
447 Private->NtHandle = INVALID_HANDLE_VALUE;
448 }
449
450 return EFI_SUCCESS;
451}
452
453EMU_BLOCK_IO_PROTOCOL gEmuBlockIoProtocol = {
458 WinNtBlockIoCreateMapping
459};
460
462EFIAPI
463WinNtBlockIoThunkOpen (
465 )
466{
468 CHAR16 *Str;
469
470 Private = AllocatePool (sizeof (*Private));
471 if (Private == NULL) {
472 return EFI_OUT_OF_RESOURCES;
473 }
474
475 Private->Signature = WIN_NT_BLOCK_IO_PRIVATE_SIGNATURE;
476 Private->Thunk = This;
477 CopyMem (&Private->EmuBlockIo, &gEmuBlockIoProtocol, sizeof (gEmuBlockIoProtocol));
478 Private->BlockSize = 512;
479 Private->NtHandle = INVALID_HANDLE_VALUE;
480
481 Private->FileName = AllocateCopyPool (StrSize (This->ConfigString), This->ConfigString);
482 if (Private->FileName == NULL) {
483 return EFI_OUT_OF_RESOURCES;
484 }
485
486 //
487 // Parse ConfigString
488 // <ConfigString> := <FileName> ':' [RF][OW] ':' <BlockSize>
489 //
490 Str = StrStr (Private->FileName, L":");
491 if (Str == NULL) {
492 Private->Removable = FALSE;
493 Private->Readonly = FALSE;
494 } else {
495 for (*Str++ = L'\0'; *Str != L'\0'; Str++) {
496 if ((*Str == 'R') || (*Str == 'F')) {
497 Private->Removable = (BOOLEAN)(*Str == L'R');
498 }
499
500 if ((*Str == 'O') || (*Str == 'W')) {
501 Private->Readonly = (BOOLEAN)(*Str == L'O');
502 }
503
504 if (*Str == ':') {
505 Private->BlockSize = wcstol (++Str, NULL, 0);
506 break;
507 }
508 }
509 }
510
511 This->Interface = &Private->EmuBlockIo;
512 This->Private = Private;
513 return EFI_SUCCESS;
514}
515
517EFIAPI
518WinNtBlockIoThunkClose (
520 )
521{
523
524 Private = This->Private;
525
526 if (Private != NULL) {
527 if (Private->FileName != NULL) {
528 FreePool (Private->FileName);
529 }
530
531 FreePool (Private);
532 }
533
534 return EFI_SUCCESS;
535}
536
537EMU_IO_THUNK_PROTOCOL mWinNtBlockIoThunkIo = {
538 &gEmuBlockIoProtocolGuid,
539 NULL,
540 NULL,
541 0,
542 WinNtBlockIoThunkOpen,
543 WinNtBlockIoThunkClose,
544 NULL
545};
UINT64 UINTN
UINTN EFIAPI StrSize(IN CONST CHAR16 *String)
Definition: String.c:72
UINT64 EFIAPI DivU64x32(IN UINT64 Dividend, IN UINT32 Divisor)
Definition: DivU64x32.c:29
UINT64 EFIAPI MultU64x32(IN UINT64 Multiplicand, IN UINT32 Multiplier)
Definition: MultU64x32.c:27
CHAR16 *EFIAPI StrStr(IN CONST CHAR16 *String, IN CONST CHAR16 *SearchString)
Definition: String.c:224
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
EFI_STATUS ReadFile(IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN UDF_VOLUME_INFO *Volume, IN UDF_LONG_ALLOCATION_DESCRIPTOR *ParentIcb, IN VOID *FileEntryData, IN OUT UDF_READ_FILE_INFO *ReadFileInfo)
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
UINT64 EFI_LBA
Definition: UefiBaseType.h:45
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_STATUS WinNtBlockIoFlushBlocks(IN EMU_BLOCK_IO_PROTOCOL *This, IN OUT EFI_BLOCK_IO2_TOKEN *Token)
Definition: WinBlockIo.c:414
EFI_STATUS WinNtBlockIoWriteBlocks(IN EMU_BLOCK_IO_PROTOCOL *This, IN UINT32 MediaId, IN EFI_LBA Lba, IN OUT EFI_BLOCK_IO2_TOKEN *Token, IN UINTN BufferSize, IN VOID *Buffer)
Definition: WinBlockIo.c:349
EFI_STATUS WinNtBlockIoReset(IN EMU_BLOCK_IO_PROTOCOL *This, IN BOOLEAN ExtendedVerification)
Definition: WinBlockIo.c:436
EFI_STATUS WinNtBlockIoReadBlocks(IN EMU_BLOCK_IO_PROTOCOL *This, IN UINT32 MediaId, IN EFI_LBA Lba, IN OUT EFI_BLOCK_IO2_TOKEN *Token, IN UINTN BufferSize, OUT VOID *Buffer)
Definition: WinBlockIo.c:279
BOOLEAN MediaPresent
Definition: BlockIo.h:144
BOOLEAN ReadOnly
Definition: BlockIo.h:156