]> git.proxmox.com Git - mirror_edk2.git/blame - InOsEmuPkg/Unix/Sec/BlockIo.c
Clarify the requirements for the Destination parameter of UnicodeStrToAsciiStr.
[mirror_edk2.git] / InOsEmuPkg / Unix / Sec / BlockIo.c
CommitLineData
d59326d3 1/**@file\r
2\r
3Copyright (c) 2004 - 2009, Intel Corporation. All rights reserved.<BR>\r
4This 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
d59326d3 12**/\r
13\r
033d0e5f 14#include "SecMain.h"\r
d59326d3 15\r
033d0e5f 16#define EMU_BLOCK_IO_PRIVATE_SIGNATURE SIGNATURE_32 ('E', 'M', 'b', 'k')\r
17typedef struct {\r
18 UINTN Signature;\r
d59326d3 19\r
033d0e5f 20 EMU_IO_THUNK_PROTOCOL *Thunk;\r
d59326d3 21\r
033d0e5f 22 char *Filename;\r
23 UINTN ReadMode;\r
24 UINTN Mode;\r
d59326d3 25\r
033d0e5f 26 int fd;\r
d59326d3 27\r
d59326d3 28 BOOLEAN RemovableMedia;\r
29 BOOLEAN WriteProtected;\r
d59326d3 30\r
033d0e5f 31 UINT64 NumberOfBlocks;\r
5dcda296 32 UINT32 BlockSize;\r
d59326d3 33\r
033d0e5f 34 EMU_BLOCK_IO_PROTOCOL EmuBlockIo;\r
35 EFI_BLOCK_IO_MEDIA *Media;\r
d59326d3 36\r
033d0e5f 37} EMU_BLOCK_IO_PRIVATE;\r
d59326d3 38\r
033d0e5f 39#define EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS(a) \\r
40 CR(a, EMU_BLOCK_IO_PRIVATE, EmuBlockIo, EMU_BLOCK_IO_PRIVATE_SIGNATURE)\r
d59326d3 41\r
d59326d3 42\r
d59326d3 43\r
44EFI_STATUS\r
033d0e5f 45EmuBlockIoReset (\r
46 IN EMU_BLOCK_IO_PROTOCOL *This,\r
47 IN BOOLEAN ExtendedVerification\r
48 );\r
d59326d3 49\r
d59326d3 50\r
d59326d3 51/*++\r
52\r
033d0e5f 53This function extends the capability of SetFilePointer to accept 64 bit parameters\r
d59326d3 54\r
55**/\r
d59326d3 56EFI_STATUS\r
033d0e5f 57SetFilePointer64 (\r
58 IN EMU_BLOCK_IO_PRIVATE *Private,\r
59 IN INT64 DistanceToMove,\r
60 OUT UINT64 *NewFilePointer,\r
61 IN INT32 MoveMethod\r
d59326d3 62 )\r
63{\r
033d0e5f 64 EFI_STATUS Status;\r
65 off_t res;\r
63947cc4 66 off_t offset = DistanceToMove;\r
d59326d3 67\r
033d0e5f 68 Status = EFI_SUCCESS;\r
63947cc4 69 res = lseek (Private->fd, offset, (int)MoveMethod);\r
033d0e5f 70 if (res == -1) {\r
71 Status = EFI_INVALID_PARAMETER;\r
63947cc4 72 } \r
d59326d3 73\r
033d0e5f 74 if (NewFilePointer != NULL) {\r
75 *NewFilePointer = res;\r
d59326d3 76 }\r
77\r
78 return Status;\r
79}\r
80\r
033d0e5f 81\r
d59326d3 82EFI_STATUS\r
033d0e5f 83EmuBlockIoOpenDevice (\r
84 IN EMU_BLOCK_IO_PRIVATE *Private\r
d59326d3 85 )\r
86{\r
87 EFI_STATUS Status;\r
88 UINT64 FileSize;\r
63947cc4 89 struct statfs buf;\r
d59326d3 90\r
d59326d3 91\r
92 //\r
93 // If the device is already opened, close it\r
94 //\r
95 if (Private->fd >= 0) {\r
033d0e5f 96 EmuBlockIoReset (&Private->EmuBlockIo, FALSE);\r
d59326d3 97 }\r
98\r
99 //\r
100 // Open the device\r
101 //\r
033d0e5f 102 Private->fd = open (Private->Filename, Private->Mode, 0644);\r
d59326d3 103 if (Private->fd < 0) {\r
63947cc4 104 printf ("EmuOpenBlock: Could not open %s: %s\n", Private->Filename, strerror(errno));\r
033d0e5f 105 Private->Media->MediaPresent = FALSE;\r
63947cc4 106 Status = EFI_NO_MEDIA;\r
d59326d3 107 goto Done;\r
108 }\r
109\r
033d0e5f 110 if (!Private->Media->MediaPresent) {\r
d59326d3 111 //\r
112 // BugBug: try to emulate if a CD appears - notify drivers to check it out\r
113 //\r
033d0e5f 114 Private->Media->MediaPresent = TRUE;\r
d59326d3 115 }\r
116\r
117 //\r
118 // get the size of the file\r
119 //\r
120 Status = SetFilePointer64 (Private, 0, &FileSize, SEEK_END);\r
121 if (EFI_ERROR (Status)) {\r
63947cc4 122 printf ("EmuOpenBlock: Could not get filesize of %s\n", Private->Filename);\r
d59326d3 123 Status = EFI_UNSUPPORTED;\r
124 goto Done;\r
125 }\r
63947cc4 126 \r
127 if (FileSize == 0) {\r
128 // lseek fails on a real device. ioctl calls are OS specific\r
129#if __APPLE__\r
130 {\r
131 UINT32 BlockSize;\r
132 \r
133 if (ioctl (Private->fd, DKIOCGETBLOCKSIZE, &BlockSize) == 0) {\r
134 Private->Media->BlockSize = BlockSize;\r
135 }\r
136 if (ioctl (Private->fd, DKIOCGETBLOCKCOUNT, &Private->NumberOfBlocks) == 0) {\r
137 if ((Private->NumberOfBlocks == 0) && (BlockSize == 0x800)) {\r
138 // A DVD is ~ 4.37 GB so make up a number\r
139 Private->Media->LastBlock = (0x100000000ULL/0x800) - 1;\r
140 } else {\r
141 Private->Media->LastBlock = Private->NumberOfBlocks - 1;\r
142 }\r
143 }\r
144 ioctl (Private->fd, DKIOCGETMAXBLOCKCOUNTWRITE, &Private->Media->OptimalTransferLengthGranularity); \r
145 }\r
146#else \r
147 {\r
148 size_t BlockSize;\r
149 UINT64 DiskSize;\r
150 \r
151 if (ioctl (Private->fd, BLKSSZGET, &BlockSize) == 0) {\r
152 Private->Media->BlockSize = BlockSize;\r
153 }\r
154 if (ioctl (Private->fd, BLKGETSIZE64, &DiskSize) == 0) {\r
155 Private->NumberOfBlocks = DivU64x32 (DiskSize, (UINT32)BlockSize);\r
156 Private->Media->LastBlock = Private->NumberOfBlocks - 1;\r
157 }\r
158 }\r
159#endif\r
160 \r
5dcda296 161 } else {\r
162 Private->Media->BlockSize = Private->BlockSize;\r
63947cc4 163 Private->NumberOfBlocks = DivU64x32 (FileSize, Private->Media->BlockSize);\r
164 Private->Media->LastBlock = Private->NumberOfBlocks - 1;\r
5dcda296 165 \r
166 if (fstatfs (Private->fd, &buf) == 0) {\r
0bc26da2 167#if __APPLE__\r
5dcda296 168 Private->Media->OptimalTransferLengthGranularity = buf.f_iosize/buf.f_bsize;\r
0bc26da2 169#else\r
170 Private->Media->OptimalTransferLengthGranularity = buf.f_bsize/buf.f_bsize;\r
171#endif\r
5dcda296 172 }\r
63947cc4 173 } \r
d59326d3 174\r
033d0e5f 175 DEBUG ((EFI_D_INIT, "%HEmuOpenBlock: opened %a%N\n", Private->Filename));\r
d59326d3 176 Status = EFI_SUCCESS;\r
177\r
178Done:\r
179 if (EFI_ERROR (Status)) {\r
180 if (Private->fd >= 0) {\r
033d0e5f 181 EmuBlockIoReset (&Private->EmuBlockIo, FALSE);\r
d59326d3 182 }\r
183 }\r
184\r
d59326d3 185 return Status;\r
186}\r
187\r
033d0e5f 188\r
d59326d3 189EFI_STATUS\r
033d0e5f 190EmuBlockIoCreateMapping (\r
191 IN EMU_BLOCK_IO_PROTOCOL *This,\r
192 IN EFI_BLOCK_IO_MEDIA *Media\r
d59326d3 193 )\r
194{\r
033d0e5f 195 EFI_STATUS Status;\r
196 EMU_BLOCK_IO_PRIVATE *Private;\r
197\r
198 Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);\r
199\r
200 Private->Media = Media;\r
201 \r
202 Media->MediaId = 0;\r
203 Media->RemovableMedia = Private->RemovableMedia;\r
204 Media->MediaPresent = TRUE;\r
205 Media->LogicalPartition = FALSE;\r
206 Media->ReadOnly = Private->WriteProtected;\r
207 Media->WriteCaching = FALSE;\r
033d0e5f 208 Media->IoAlign = 1;\r
209 Media->LastBlock = 0; // Filled in by OpenDevice\r
210 \r
211 // EFI_BLOCK_IO_PROTOCOL_REVISION2\r
212 Media->LowestAlignedLba = 0;\r
213 Media->LogicalBlocksPerPhysicalBlock = 0; \r
63947cc4 214 \r
215\r
033d0e5f 216 // EFI_BLOCK_IO_PROTOCOL_REVISION3\r
217 Media->OptimalTransferLengthGranularity = 0;\r
63947cc4 218 \r
033d0e5f 219 Status = EmuBlockIoOpenDevice (Private);\r
220\r
63947cc4 221 \r
033d0e5f 222 return Status;\r
223}\r
224\r
d59326d3 225\r
033d0e5f 226EFI_STATUS\r
227EmuBlockIoError (\r
228 IN EMU_BLOCK_IO_PRIVATE *Private\r
229 )\r
230{\r
d59326d3 231 EFI_STATUS Status;\r
232 BOOLEAN ReinstallBlockIoFlag;\r
233\r
234\r
033d0e5f 235 switch (errno) {\r
d59326d3 236\r
033d0e5f 237 case EAGAIN:\r
d59326d3 238 Status = EFI_NO_MEDIA;\r
033d0e5f 239 Private->Media->ReadOnly = FALSE;\r
240 Private->Media->MediaPresent = FALSE;\r
d59326d3 241 ReinstallBlockIoFlag = FALSE;\r
242 break;\r
243\r
033d0e5f 244 case EACCES:\r
245 Private->Media->ReadOnly = FALSE;\r
246 Private->Media->MediaPresent = TRUE;\r
247 Private->Media->MediaId += 1;\r
d59326d3 248 ReinstallBlockIoFlag = TRUE;\r
249 Status = EFI_MEDIA_CHANGED;\r
250 break;\r
251\r
033d0e5f 252 case EROFS:\r
253 Private->Media->ReadOnly = TRUE;\r
d59326d3 254 ReinstallBlockIoFlag = FALSE;\r
255 Status = EFI_WRITE_PROTECTED;\r
256 break;\r
257\r
258 default:\r
259 ReinstallBlockIoFlag = FALSE;\r
260 Status = EFI_DEVICE_ERROR;\r
261 break;\r
262 }\r
d59326d3 263 return Status;\r
d59326d3 264}\r
265\r
bfa084fa 266\r
d59326d3 267EFI_STATUS\r
033d0e5f 268EmuBlockIoReadWriteCommon (\r
269 IN EMU_BLOCK_IO_PRIVATE *Private,\r
d59326d3 270 IN UINT32 MediaId,\r
271 IN EFI_LBA Lba,\r
272 IN UINTN BufferSize,\r
273 IN VOID *Buffer,\r
274 IN CHAR8 *CallerName\r
275 )\r
276{\r
277 EFI_STATUS Status;\r
278 UINTN BlockSize;\r
279 UINT64 LastBlock;\r
280 INT64 DistanceToMove;\r
281 UINT64 DistanceMoved;\r
282\r
283 if (Private->fd < 0) {\r
033d0e5f 284 Status = EmuBlockIoOpenDevice (Private);\r
d59326d3 285 if (EFI_ERROR (Status)) {\r
286 return Status;\r
287 }\r
288 }\r
289\r
033d0e5f 290 if (!Private->Media->MediaPresent) {\r
d59326d3 291 DEBUG ((EFI_D_INIT, "%s: No Media\n", CallerName));\r
292 return EFI_NO_MEDIA;\r
293 }\r
294\r
033d0e5f 295 if (Private->Media->MediaId != MediaId) {\r
d59326d3 296 return EFI_MEDIA_CHANGED;\r
297 }\r
298\r
033d0e5f 299 if ((UINTN) Buffer % Private->Media->IoAlign != 0) {\r
d59326d3 300 return EFI_INVALID_PARAMETER;\r
301 }\r
302 \r
303 //\r
304 // Verify buffer size\r
305 //\r
63947cc4 306 BlockSize = Private->Media->BlockSize;\r
d59326d3 307 if (BufferSize == 0) {\r
308 DEBUG ((EFI_D_INIT, "%s: Zero length read\n", CallerName));\r
309 return EFI_SUCCESS;\r
310 }\r
311\r
312 if ((BufferSize % BlockSize) != 0) {\r
313 DEBUG ((EFI_D_INIT, "%s: Invalid read size\n", CallerName));\r
314 return EFI_BAD_BUFFER_SIZE;\r
315 }\r
316\r
317 LastBlock = Lba + (BufferSize / BlockSize) - 1;\r
63947cc4 318 if (LastBlock > Private->Media->LastBlock) {\r
d59326d3 319 DEBUG ((EFI_D_INIT, "ReadBlocks: Attempted to read off end of device\n"));\r
320 return EFI_INVALID_PARAMETER;\r
321 }\r
322 //\r
323 // Seek to End of File\r
324 //\r
325 DistanceToMove = MultU64x32 (Lba, BlockSize);\r
326 Status = SetFilePointer64 (Private, DistanceToMove, &DistanceMoved, SEEK_SET);\r
327\r
328 if (EFI_ERROR (Status)) {\r
329 DEBUG ((EFI_D_INIT, "WriteBlocks: SetFilePointer failed\n"));\r
033d0e5f 330 return EmuBlockIoError (Private);\r
d59326d3 331 }\r
332\r
333 return EFI_SUCCESS;\r
334}\r
335\r
d59326d3 336\r
033d0e5f 337/**\r
338 Read BufferSize bytes from Lba into Buffer.\r
339 \r
340 This function reads the requested number of blocks from the device. All the\r
341 blocks are read, or an error is returned.\r
342 If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_or EFI_MEDIA_CHANGED is returned and\r
343 non-blocking I/O is being used, the Event associated with this request will\r
344 not be signaled.\r
345\r
346 @param[in] This Indicates a pointer to the calling context.\r
347 @param[in] MediaId Id of the media, changes every time the media is \r
348 replaced.\r
349 @param[in] Lba The starting Logical Block Address to read from.\r
350 @param[in, out] Token A pointer to the token associated with the transaction.\r
351 @param[in] BufferSize Size of Buffer, must be a multiple of device block size. \r
352 @param[out] Buffer A pointer to the destination buffer for the data. The \r
353 caller is responsible for either having implicit or \r
354 explicit ownership of the buffer.\r
355\r
356 @retval EFI_SUCCESS The read request was queued if Token->Event is\r
357 not NULL.The data was read correctly from the\r
358 device if the Token->Event is NULL.\r
359 @retval EFI_DEVICE_ERROR The device reported an error while performing\r
360 the read.\r
361 @retval EFI_NO_MEDIA There is no media in the device.\r
362 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
363 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the\r
364 intrinsic block size of the device.\r
365 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, \r
366 or the buffer is not on proper alignment.\r
367 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack\r
368 of resources.\r
d59326d3 369**/\r
033d0e5f 370EFI_STATUS\r
371EmuBlockIoReadBlocks (\r
372 IN EMU_BLOCK_IO_PROTOCOL *This,\r
373 IN UINT32 MediaId,\r
374 IN EFI_LBA LBA,\r
375 IN OUT EFI_BLOCK_IO2_TOKEN *Token,\r
376 IN UINTN BufferSize,\r
377 OUT VOID *Buffer\r
378 )\r
d59326d3 379{\r
d59326d3 380 EFI_STATUS Status;\r
033d0e5f 381 EMU_BLOCK_IO_PRIVATE *Private;\r
382 ssize_t len;\r
d59326d3 383\r
384 Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);\r
385\r
033d0e5f 386 Status = EmuBlockIoReadWriteCommon (Private, MediaId, LBA, BufferSize, Buffer, "UnixReadBlocks");\r
d59326d3 387 if (EFI_ERROR (Status)) {\r
388 goto Done;\r
389 }\r
390\r
033d0e5f 391 len = read (Private->fd, Buffer, BufferSize);\r
d59326d3 392 if (len != BufferSize) {\r
393 DEBUG ((EFI_D_INIT, "ReadBlocks: ReadFile failed.\n"));\r
033d0e5f 394 Status = EmuBlockIoError (Private);\r
d59326d3 395 goto Done;\r
396 }\r
397\r
398 //\r
033d0e5f 399 // If we read then media is present.\r
d59326d3 400 //\r
033d0e5f 401 Private->Media->MediaPresent = TRUE;\r
d59326d3 402 Status = EFI_SUCCESS;\r
403\r
404Done:\r
033d0e5f 405 if (Token != NULL) {\r
406 if (Token->Event != NULL) {\r
407 // Caller is responcible for signaling EFI Event\r
408 Token->TransactionStatus = Status;\r
409 return EFI_SUCCESS;\r
410 }\r
411 }\r
d59326d3 412 return Status;\r
413}\r
414\r
d59326d3 415\r
033d0e5f 416/**\r
417 Write BufferSize bytes from Lba into Buffer.\r
418\r
419 This function writes the requested number of blocks to the device. All blocks\r
420 are written, or an error is returned.If EFI_DEVICE_ERROR, EFI_NO_MEDIA,\r
421 EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED is returned and non-blocking I/O is\r
422 being used, the Event associated with this request will not be signaled.\r
423\r
424 @param[in] This Indicates a pointer to the calling context.\r
425 @param[in] MediaId The media ID that the write request is for.\r
426 @param[in] Lba The starting logical block address to be written. The\r
427 caller is responsible for writing to only legitimate\r
428 locations.\r
429 @param[in, out] Token A pointer to the token associated with the transaction.\r
430 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.\r
431 @param[in] Buffer A pointer to the source buffer for the data.\r
432\r
433 @retval EFI_SUCCESS The write request was queued if Event is not NULL.\r
434 The data was written correctly to the device if\r
435 the Event is NULL.\r
436 @retval EFI_WRITE_PROTECTED The device can not be written to.\r
437 @retval EFI_NO_MEDIA There is no media in the device.\r
438 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
439 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.\r
440 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
441 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, \r
442 or the buffer is not on proper alignment.\r
443 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack\r
444 of resources.\r
d59326d3 445\r
446**/\r
033d0e5f 447EFI_STATUS\r
448EmuBlockIoWriteBlocks (\r
449 IN EMU_BLOCK_IO_PROTOCOL *This,\r
450 IN UINT32 MediaId,\r
451 IN EFI_LBA LBA,\r
452 IN OUT EFI_BLOCK_IO2_TOKEN *Token,\r
453 IN UINTN BufferSize,\r
454 IN VOID *Buffer\r
455 )\r
d59326d3 456{\r
033d0e5f 457 EMU_BLOCK_IO_PRIVATE *Private;\r
d59326d3 458 ssize_t len;\r
459 EFI_STATUS Status;\r
d59326d3 460\r
d59326d3 461\r
462 Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);\r
463\r
033d0e5f 464 Status = EmuBlockIoReadWriteCommon (Private, MediaId, LBA, BufferSize, Buffer, "UnixWriteBlocks");\r
d59326d3 465 if (EFI_ERROR (Status)) {\r
466 goto Done;\r
467 }\r
468\r
033d0e5f 469 len = write (Private->fd, Buffer, BufferSize);\r
d59326d3 470 if (len != BufferSize) {\r
471 DEBUG ((EFI_D_INIT, "ReadBlocks: WriteFile failed.\n"));\r
033d0e5f 472 Status = EmuBlockIoError (Private);\r
d59326d3 473 goto Done;\r
474 }\r
475\r
476 //\r
477 // If the write succeeded, we are not write protected and media is present.\r
478 //\r
033d0e5f 479 Private->Media->MediaPresent = TRUE;\r
480 Private->Media->ReadOnly = FALSE;\r
d59326d3 481 Status = EFI_SUCCESS;\r
482\r
483Done:\r
033d0e5f 484 if (Token != NULL) {\r
485 if (Token->Event != NULL) {\r
486 // Caller is responcible for signaling EFI Event\r
487 Token->TransactionStatus = Status;\r
488 return EFI_SUCCESS;\r
489 }\r
490 }\r
491\r
d59326d3 492 return Status;\r
493}\r
494\r
d59326d3 495\r
033d0e5f 496/**\r
497 Flush the Block Device.\r
498 \r
499 If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED\r
500 is returned and non-blocking I/O is being used, the Event associated with\r
501 this request will not be signaled. \r
502\r
503 @param[in] This Indicates a pointer to the calling context.\r
504 @param[in,out] Token A pointer to the token associated with the transaction\r
505\r
506 @retval EFI_SUCCESS The flush request was queued if Event is not NULL.\r
507 All outstanding data was written correctly to the\r
508 device if the Event is NULL.\r
509 @retval EFI_DEVICE_ERROR The device reported an error while writting back\r
510 the data.\r
511 @retval EFI_WRITE_PROTECTED The device cannot be written to.\r
512 @retval EFI_NO_MEDIA There is no media in the device.\r
513 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
514 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack\r
515 of resources.\r
d59326d3 516\r
517**/\r
033d0e5f 518EFI_STATUS\r
519EmuBlockIoFlushBlocks (\r
520 IN EMU_BLOCK_IO_PROTOCOL *This,\r
521 IN OUT EFI_BLOCK_IO2_TOKEN *Token\r
522 )\r
d59326d3 523{\r
033d0e5f 524 EMU_BLOCK_IO_PRIVATE *Private;\r
525\r
526 Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);\r
527\r
528 if (Private->fd >= 0) {\r
0bc26da2 529 fsync (Private->fd);\r
530#if __APPLE__\r
531 fcntl (Private->fd, F_FULLFSYNC);\r
532#endif\r
033d0e5f 533 }\r
534 \r
63947cc4 535 \r
033d0e5f 536 if (Token != NULL) {\r
537 if (Token->Event != NULL) {\r
538 // Caller is responcible for signaling EFI Event\r
539 Token->TransactionStatus = EFI_SUCCESS;\r
540 return EFI_SUCCESS;\r
541 }\r
542 }\r
543 \r
d59326d3 544 return EFI_SUCCESS;\r
545}\r
546\r
033d0e5f 547\r
548/**\r
549 Reset the block device hardware.\r
550\r
551 @param[in] This Indicates a pointer to the calling context.\r
552 @param[in] ExtendedVerification Indicates that the driver may perform a more\r
553 exhausive verfication operation of the device\r
554 during reset.\r
555\r
556 @retval EFI_SUCCESS The device was reset.\r
557 @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
558 not be reset.\r
559\r
560**/\r
d59326d3 561EFI_STATUS\r
033d0e5f 562EmuBlockIoReset (\r
563 IN EMU_BLOCK_IO_PROTOCOL *This,\r
564 IN BOOLEAN ExtendedVerification\r
d59326d3 565 )\r
d59326d3 566{\r
567 EMU_BLOCK_IO_PRIVATE *Private;\r
d59326d3 568\r
d59326d3 569 Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);\r
570\r
571 if (Private->fd >= 0) {\r
033d0e5f 572 close (Private->fd);\r
d59326d3 573 Private->fd = -1;\r
574 }\r
575\r
d59326d3 576 return EFI_SUCCESS;\r
577}\r
578\r
d59326d3 579\r
033d0e5f 580char *\r
581StdDupUnicodeToAscii (\r
582 IN CHAR16 *Str\r
583 )\r
584{\r
585 UINTN Size;\r
586 char *Ascii;\r
587 char *Ptr;\r
588 \r
589 Size = StrLen (Str) + 1;\r
590 Ascii = malloc (Size);\r
591 if (Ascii == NULL) {\r
592 return NULL;\r
593 }\r
594 \r
595 for (Ptr = Ascii; *Str != '\0'; Ptr++, Str++) {\r
596 *Ptr = *Str;\r
597 }\r
598 *Ptr = 0;\r
599 \r
600 return Ascii;\r
601}\r
d59326d3 602\r
d59326d3 603\r
033d0e5f 604EMU_BLOCK_IO_PROTOCOL gEmuBlockIoProtocol = {\r
605 GasketEmuBlockIoReset,\r
606 GasketEmuBlockIoReadBlocks,\r
607 GasketEmuBlockIoWriteBlocks,\r
608 GasketEmuBlockIoFlushBlocks,\r
609 GasketEmuBlockIoCreateMapping\r
610};\r
d59326d3 611\r
033d0e5f 612EFI_STATUS\r
613EmuBlockIoThunkOpen (\r
614 IN EMU_IO_THUNK_PROTOCOL *This\r
615 )\r
d59326d3 616{\r
033d0e5f 617 EMU_BLOCK_IO_PRIVATE *Private;\r
618 char *Str;\r
619 \r
620 if (This->Private != NULL) {\r
621 return EFI_ALREADY_STARTED;\r
d59326d3 622 }\r
033d0e5f 623 \r
624 if (!CompareGuid (This->Protocol, &gEmuBlockIoProtocolGuid)) {\r
625 return EFI_UNSUPPORTED;\r
626 }\r
627 \r
628 Private = malloc (sizeof (EMU_BLOCK_IO_PRIVATE));\r
629 if (Private == NULL) {\r
630 return EFI_OUT_OF_RESOURCES;\r
d59326d3 631 }\r
632\r
033d0e5f 633 \r
634 Private->Signature = EMU_BLOCK_IO_PRIVATE_SIGNATURE;\r
635 Private->Thunk = This;\r
636 CopyMem (&Private->EmuBlockIo, &gEmuBlockIoProtocol, sizeof (gEmuBlockIoProtocol));\r
5dcda296 637 Private->fd = -1;\r
638 Private->BlockSize = 512;\r
033d0e5f 639 \r
640 Private->Filename = StdDupUnicodeToAscii (This->ConfigString);\r
641 if (Private->Filename == NULL) {\r
642 return EFI_OUT_OF_RESOURCES;\r
643 }\r
644 \r
645 Str = strstr (Private->Filename, ":");\r
646 if (Str == NULL) {\r
647 Private->RemovableMedia = FALSE;\r
648 Private->WriteProtected = FALSE;\r
649 } else {\r
650 for (*Str++ = '\0'; *Str != 0; Str++) {\r
651 if (*Str == 'R' || *Str == 'F') {\r
652 Private->RemovableMedia = (BOOLEAN) (*Str == 'R');\r
653 }\r
654 if (*Str == 'O' || *Str == 'W') {\r
655 Private->WriteProtected = (BOOLEAN) (*Str == 'O');\r
656 }\r
5dcda296 657 if (*Str == ':') {\r
658 Private->BlockSize = strtol (++Str, NULL, 0);\r
659 break;\r
660 }\r
033d0e5f 661 }\r
662 }\r
663 \r
033d0e5f 664 This->Interface = &Private->EmuBlockIo;\r
665 This->Private = Private;\r
666 return EFI_SUCCESS;\r
d59326d3 667}\r
668\r
669\r
d59326d3 670EFI_STATUS\r
033d0e5f 671EmuBlockIoThunkClose (\r
672 IN EMU_IO_THUNK_PROTOCOL *This\r
d59326d3 673 )\r
674{\r
033d0e5f 675 EMU_BLOCK_IO_PRIVATE *Private;\r
d59326d3 676\r
033d0e5f 677 if (!CompareGuid (This->Protocol, &gEmuBlockIoProtocolGuid)) {\r
678 return EFI_UNSUPPORTED;\r
d59326d3 679 }\r
033d0e5f 680 \r
681 Private = This->Private;\r
682 \r
683 if (This->Private != NULL) {\r
684 if (Private->Filename != NULL) {\r
685 free (Private->Filename);\r
686 } \r
687 free (This->Private);\r
21ce7a41 688 This->Private = NULL;\r
d59326d3 689 }\r
033d0e5f 690 \r
691 return EFI_SUCCESS;\r
d59326d3 692}\r
033d0e5f 693\r
694\r
695\r
696EMU_IO_THUNK_PROTOCOL gBlockIoThunkIo = {\r
697 &gEmuBlockIoProtocolGuid,\r
698 NULL,\r
699 NULL,\r
700 0,\r
701 GasketBlockIoThunkOpen,\r
702 GasketBlockIoThunkClose,\r
703 NULL\r
704};\r
705\r
706\r