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