]> git.proxmox.com Git - mirror_edk2.git/blame - EmulatorPkg/EmuBlockIoDxe/EmuBlockIo.c
EmulatorPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / EmulatorPkg / EmuBlockIoDxe / EmuBlockIo.c
CommitLineData
d59326d3 1/**@file\r
2\r
1e571882 3Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
e3ba31da 4SPDX-License-Identifier: BSD-2-Clause-Patent\r
d59326d3 5bbe\r
6**/\r
7\r
8#include "EmuBlockIo.h"\r
9\r
10\r
11/**\r
12 Reset the block device hardware.\r
13\r
14 @param[in] This Indicates a pointer to the calling context.\r
15 @param[in] ExtendedVerification Indicates that the driver may perform a more\r
16 exhausive verfication operation of the device\r
17 during reset.\r
18\r
19 @retval EFI_SUCCESS The device was reset.\r
20 @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
21 not be reset.\r
22\r
23**/\r
24EFI_STATUS\r
25EFIAPI\r
26EmuBlockIo2Reset (\r
27 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
28 IN BOOLEAN ExtendedVerification\r
29 )\r
30{\r
31 EFI_STATUS Status;\r
32 EMU_BLOCK_IO_PRIVATE *Private;\r
33 EFI_TPL OldTpl;\r
34\r
35 Private = EMU_BLOCK_IO2_PRIVATE_DATA_FROM_THIS (This);\r
36\r
37 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
38\r
39 Status = Private->Io->Reset (Private->Io, ExtendedVerification);\r
40\r
41 gBS->RestoreTPL (OldTpl);\r
42 return Status;\r
43}\r
44\r
45/**\r
46 Read BufferSize bytes from Lba into Buffer.\r
d18d8a1d 47\r
d59326d3 48 This function reads the requested number of blocks from the device. All the\r
49 blocks are read, or an error is returned.\r
50 If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_or EFI_MEDIA_CHANGED is returned and\r
51 non-blocking I/O is being used, the Event associated with this request will\r
52 not be signaled.\r
53\r
54 @param[in] This Indicates a pointer to the calling context.\r
d18d8a1d 55 @param[in] MediaId Id of the media, changes every time the media is\r
d59326d3 56 replaced.\r
57 @param[in] Lba The starting Logical Block Address to read from.\r
79e4f2a5 58 @param[in, out] Token A pointer to the token associated with the transaction.\r
d18d8a1d 59 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.\r
60 @param[out] Buffer A pointer to the destination buffer for the data. The\r
61 caller is responsible for either having implicit or\r
d59326d3 62 explicit ownership of the buffer.\r
63\r
64 @retval EFI_SUCCESS The read request was queued if Token->Event is\r
65 not NULL.The data was read correctly from the\r
66 device if the Token->Event is NULL.\r
67 @retval EFI_DEVICE_ERROR The device reported an error while performing\r
68 the read.\r
69 @retval EFI_NO_MEDIA There is no media in the device.\r
70 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
71 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the\r
72 intrinsic block size of the device.\r
d18d8a1d 73 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,\r
d59326d3 74 or the buffer is not on proper alignment.\r
75 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack\r
76 of resources.\r
77**/\r
78EFI_STATUS\r
79EFIAPI\r
80EmuBlockIo2ReadBlocksEx (\r
81 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
82 IN UINT32 MediaId,\r
83 IN EFI_LBA LBA,\r
84 IN OUT EFI_BLOCK_IO2_TOKEN *Token,\r
85 IN UINTN BufferSize,\r
86 OUT VOID *Buffer\r
87 )\r
88{\r
89 EFI_STATUS Status;\r
90 EMU_BLOCK_IO_PRIVATE *Private;\r
91 EFI_TPL OldTpl;\r
92\r
93 Private = EMU_BLOCK_IO2_PRIVATE_DATA_FROM_THIS (This);\r
94\r
95 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
96\r
97 Status = Private->Io->ReadBlocks (Private->Io, MediaId, LBA, Token, BufferSize, Buffer);\r
98\r
99 gBS->RestoreTPL (OldTpl);\r
100 return Status;\r
101}\r
102\r
103\r
104/**\r
105 Write BufferSize bytes from Lba into Buffer.\r
106\r
107 This function writes the requested number of blocks to the device. All blocks\r
108 are written, or an error is returned.If EFI_DEVICE_ERROR, EFI_NO_MEDIA,\r
109 EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED is returned and non-blocking I/O is\r
110 being used, the Event associated with this request will not be signaled.\r
111\r
112 @param[in] This Indicates a pointer to the calling context.\r
113 @param[in] MediaId The media ID that the write request is for.\r
114 @param[in] Lba The starting logical block address to be written. The\r
115 caller is responsible for writing to only legitimate\r
116 locations.\r
117 @param[in, out] Token A pointer to the token associated with the transaction.\r
118 @param[in] BufferSize Size of Buffer, must be a multiple of device block size.\r
119 @param[in] Buffer A pointer to the source buffer for the data.\r
120\r
121 @retval EFI_SUCCESS The write request was queued if Event is not NULL.\r
122 The data was written correctly to the device if\r
123 the Event is NULL.\r
124 @retval EFI_WRITE_PROTECTED The device can not be written to.\r
125 @retval EFI_NO_MEDIA There is no media in the device.\r
126 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
127 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.\r
128 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
d18d8a1d 129 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,\r
d59326d3 130 or the buffer is not on proper alignment.\r
131 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack\r
132 of resources.\r
133\r
134**/\r
135EFI_STATUS\r
d18d8a1d 136EFIAPI\r
d59326d3 137EmuBlockIo2WriteBlocksEx (\r
138 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
139 IN UINT32 MediaId,\r
140 IN EFI_LBA LBA,\r
141 IN OUT EFI_BLOCK_IO2_TOKEN *Token,\r
142 IN UINTN BufferSize,\r
143 IN VOID *Buffer\r
144 )\r
145{\r
146 EFI_STATUS Status;\r
147 EMU_BLOCK_IO_PRIVATE *Private;\r
148 EFI_TPL OldTpl;\r
149\r
150 Private = EMU_BLOCK_IO2_PRIVATE_DATA_FROM_THIS (This);\r
151\r
152 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
153\r
154 Status = Private->Io->WriteBlocks (Private->Io, MediaId, LBA, Token, BufferSize, Buffer);\r
155\r
156 gBS->RestoreTPL (OldTpl);\r
157 return Status;\r
158}\r
159\r
160\r
161\r
162/**\r
163 Flush the Block Device.\r
d18d8a1d 164\r
d59326d3 165 If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED\r
166 is returned and non-blocking I/O is being used, the Event associated with\r
d18d8a1d 167 this request will not be signaled.\r
d59326d3 168\r
169 @param[in] This Indicates a pointer to the calling context.\r
170 @param[in,out] Token A pointer to the token associated with the transaction\r
171\r
172 @retval EFI_SUCCESS The flush request was queued if Event is not NULL.\r
173 All outstanding data was written correctly to the\r
174 device if the Event is NULL.\r
175 @retval EFI_DEVICE_ERROR The device reported an error while writting back\r
176 the data.\r
177 @retval EFI_WRITE_PROTECTED The device cannot be written to.\r
178 @retval EFI_NO_MEDIA There is no media in the device.\r
179 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
180 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack\r
181 of resources.\r
182\r
183**/\r
184EFI_STATUS\r
185EFIAPI\r
186EmuBlockIo2Flush (\r
187 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
188 IN OUT EFI_BLOCK_IO2_TOKEN *Token\r
189 )\r
190{\r
191 EFI_STATUS Status;\r
192 EMU_BLOCK_IO_PRIVATE *Private;\r
193 EFI_TPL OldTpl;\r
194\r
195 Private = EMU_BLOCK_IO2_PRIVATE_DATA_FROM_THIS (This);\r
196\r
197 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
198\r
199 Status = Private->Io->FlushBlocks (Private->Io, Token);\r
200\r
201 gBS->RestoreTPL (OldTpl);\r
202 return Status;\r
203}\r
204\r
205\r
206\r
207/**\r
208 Reset the Block Device.\r
209\r
210 @param This Indicates a pointer to the calling context.\r
211 @param ExtendedVerification Driver may perform diagnostics on reset.\r
212\r
213 @retval EFI_SUCCESS The device was reset.\r
214 @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
215 not be reset.\r
216\r
217**/\r
218EFI_STATUS\r
219EFIAPI\r
220EmuBlockIoReset (\r
221 IN EFI_BLOCK_IO_PROTOCOL *This,\r
222 IN BOOLEAN ExtendedVerification\r
223 )\r
224{\r
225 EFI_STATUS Status;\r
226 EMU_BLOCK_IO_PRIVATE *Private;\r
227 EFI_TPL OldTpl;\r
228\r
033d0e5f 229 Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);\r
d59326d3 230\r
231 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
232\r
233 Status = Private->Io->Reset (Private->Io, ExtendedVerification);\r
234\r
235 gBS->RestoreTPL (OldTpl);\r
236 return Status;\r
237}\r
238\r
239\r
240/**\r
241 Read BufferSize bytes from Lba into Buffer.\r
242\r
243 @param This Indicates a pointer to the calling context.\r
244 @param MediaId Id of the media, changes every time the media is replaced.\r
245 @param Lba The starting Logical Block Address to read from\r
246 @param BufferSize Size of Buffer, must be a multiple of device block size.\r
247 @param Buffer A pointer to the destination buffer for the data. The caller is\r
248 responsible for either having implicit or explicit ownership of the buffer.\r
249\r
250 @retval EFI_SUCCESS The data was read correctly from the device.\r
251 @retval EFI_DEVICE_ERROR The device reported an error while performing the read.\r
252 @retval EFI_NO_MEDIA There is no media in the device.\r
253 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.\r
254 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
d18d8a1d 255 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,\r
d59326d3 256 or the buffer is not on proper alignment.\r
257\r
258**/\r
259EFI_STATUS\r
260EFIAPI\r
033d0e5f 261EmuBlockIoReadBlocks (\r
d59326d3 262 IN EFI_BLOCK_IO_PROTOCOL *This,\r
263 IN UINT32 MediaId,\r
264 IN EFI_LBA Lba,\r
265 IN UINTN BufferSize,\r
266 OUT VOID *Buffer\r
267 )\r
268{\r
269 EFI_STATUS Status;\r
270 EMU_BLOCK_IO_PRIVATE *Private;\r
271 EFI_TPL OldTpl;\r
272 EFI_BLOCK_IO2_TOKEN Token;\r
273\r
033d0e5f 274 Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);\r
d59326d3 275\r
276 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
277\r
278 Token.Event = NULL;\r
279 Status = Private->Io->ReadBlocks (Private->Io, MediaId, Lba, &Token, BufferSize, Buffer);\r
280\r
281 gBS->RestoreTPL (OldTpl);\r
282 return Status;\r
283}\r
284\r
285\r
286/**\r
287 Write BufferSize bytes from Lba into Buffer.\r
288\r
289 @param This Indicates a pointer to the calling context.\r
290 @param MediaId The media ID that the write request is for.\r
291 @param Lba The starting logical block address to be written. The caller is\r
292 responsible for writing to only legitimate locations.\r
293 @param BufferSize Size of Buffer, must be a multiple of device block size.\r
294 @param Buffer A pointer to the source buffer for the data.\r
295\r
296 @retval EFI_SUCCESS The data was written correctly to the device.\r
297 @retval EFI_WRITE_PROTECTED The device can not be written to.\r
298 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.\r
299 @retval EFI_NO_MEDIA There is no media in the device.\r
300 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
301 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
d18d8a1d 302 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,\r
d59326d3 303 or the buffer is not on proper alignment.\r
304\r
305**/\r
306EFI_STATUS\r
307EFIAPI\r
308EmuBlockIoWriteBlocks (\r
309 IN EFI_BLOCK_IO_PROTOCOL *This,\r
310 IN UINT32 MediaId,\r
311 IN EFI_LBA Lba,\r
312 IN UINTN BufferSize,\r
313 IN VOID *Buffer\r
314 )\r
315{\r
316 EFI_STATUS Status;\r
317 EMU_BLOCK_IO_PRIVATE *Private;\r
318 EFI_TPL OldTpl;\r
319 EFI_BLOCK_IO2_TOKEN Token;\r
320\r
033d0e5f 321 Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);\r
d59326d3 322\r
323 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
324\r
325 Token.Event = NULL;\r
326 Status = Private->Io->WriteBlocks (Private->Io, MediaId, Lba, &Token, BufferSize, Buffer);\r
327\r
328 gBS->RestoreTPL (OldTpl);\r
329 return Status;\r
330}\r
331\r
332/**\r
333 Flush the Block Device.\r
334\r
335 @param This Indicates a pointer to the calling context.\r
336\r
337 @retval EFI_SUCCESS All outstanding data was written to the device\r
338 @retval EFI_DEVICE_ERROR The device reported an error while writting back the data\r
339 @retval EFI_NO_MEDIA There is no media in the device.\r
340\r
341**/\r
342EFI_STATUS\r
343EFIAPI\r
344EmuBlockIoFlushBlocks (\r
345 IN EFI_BLOCK_IO_PROTOCOL *This\r
346 )\r
347{\r
348 EFI_STATUS Status;\r
349 EMU_BLOCK_IO_PRIVATE *Private;\r
350 EFI_TPL OldTpl;\r
351 EFI_BLOCK_IO2_TOKEN Token;\r
352\r
033d0e5f 353 Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);\r
d59326d3 354\r
355 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
356\r
357 Token.Event = NULL;\r
358 Status = Private->Io->FlushBlocks (Private->Io, &Token);\r
359\r
360 gBS->RestoreTPL (OldTpl);\r
361 return Status;\r
362}\r
363\r
364\r
365\r
366/**\r
d18d8a1d 367 Tests to see if this driver supports a given controller. If a child device is provided,\r
d59326d3 368 it further tests to see if this driver supports creating a handle for the specified child device.\r
369\r
d18d8a1d 370 This function checks to see if the driver specified by This supports the device specified by\r
371 ControllerHandle. Drivers will typically use the device path attached to\r
372 ControllerHandle and/or the services from the bus I/O abstraction attached to\r
373 ControllerHandle to determine if the driver supports ControllerHandle. This function\r
374 may be called many times during platform initialization. In order to reduce boot times, the tests\r
375 performed by this function must be very small, and take as little time as possible to execute. This\r
376 function must not change the state of any hardware devices, and this function must be aware that the\r
377 device specified by ControllerHandle may already be managed by the same driver or a\r
378 different driver. This function must match its calls to AllocatePages() with FreePages(),\r
379 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().\r
380 Because ControllerHandle may have been previously started by the same driver, if a protocol is\r
381 already in the opened state, then it must not be closed with CloseProtocol(). This is required\r
d59326d3 382 to guarantee the state of ControllerHandle is not modified by this function.\r
383\r
384 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
d18d8a1d 385 @param[in] ControllerHandle The handle of the controller to test. This handle\r
386 must support a protocol interface that supplies\r
d59326d3 387 an I/O abstraction to the driver.\r
d18d8a1d 388 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
389 parameter is ignored by device drivers, and is optional for bus\r
390 drivers. For bus drivers, if this parameter is not NULL, then\r
391 the bus driver must determine if the bus controller specified\r
392 by ControllerHandle and the child controller specified\r
393 by RemainingDevicePath are both supported by this\r
d59326d3 394 bus driver.\r
395\r
396 @retval EFI_SUCCESS The device specified by ControllerHandle and\r
397 RemainingDevicePath is supported by the driver specified by This.\r
398 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
399 RemainingDevicePath is already being managed by the driver\r
400 specified by This.\r
401 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
402 RemainingDevicePath is already being managed by a different\r
403 driver or an application that requires exclusive access.\r
404 Currently not implemented.\r
405 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
406 RemainingDevicePath is not supported by the driver specified by This.\r
407**/\r
408EFI_STATUS\r
409EFIAPI\r
410EmuBlockIoDriverBindingSupported (\r
411 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
412 IN EFI_HANDLE Handle,\r
413 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
414 )\r
415{\r
416 EFI_STATUS Status;\r
572287f8 417 EMU_IO_THUNK_PROTOCOL *EmuIoThunk;\r
d59326d3 418\r
419 //\r
420 // Open the IO Abstraction(s) needed to perform the supported test\r
421 //\r
422 Status = gBS->OpenProtocol (\r
423 Handle,\r
424 &gEmuIoThunkProtocolGuid,\r
425 (VOID **)&EmuIoThunk,\r
426 This->DriverBindingHandle,\r
427 Handle,\r
428 EFI_OPEN_PROTOCOL_BY_DRIVER\r
429 );\r
430 if (EFI_ERROR (Status)) {\r
431 return Status;\r
432 }\r
433\r
434 //\r
435 // Make sure GUID is for a File System handle.\r
436 //\r
437 Status = EFI_UNSUPPORTED;\r
033d0e5f 438 if (CompareGuid (EmuIoThunk->Protocol, &gEmuBlockIoProtocolGuid)) {\r
d59326d3 439 Status = EFI_SUCCESS;\r
440 }\r
441\r
442 //\r
443 // Close the I/O Abstraction(s) used to perform the supported test\r
444 //\r
445 gBS->CloseProtocol (\r
446 Handle,\r
447 &gEmuIoThunkProtocolGuid,\r
448 This->DriverBindingHandle,\r
449 Handle\r
450 );\r
451 return Status;\r
452}\r
453\r
454\r
455/**\r
456 Starts a device controller or a bus controller.\r
457\r
458 The Start() function is designed to be invoked from the EFI boot service ConnectController().\r
d18d8a1d 459 As a result, much of the error checking on the parameters to Start() has been moved into this\r
460 common boot service. It is legal to call Start() from other locations,\r
d59326d3 461 but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
462 1. ControllerHandle must be a valid EFI_HANDLE.\r
463 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
464 EFI_DEVICE_PATH_PROTOCOL.\r
465 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
d18d8a1d 466 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.\r
d59326d3 467\r
468 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
d18d8a1d 469 @param[in] ControllerHandle The handle of the controller to start. This handle\r
470 must support a protocol interface that supplies\r
d59326d3 471 an I/O abstraction to the driver.\r
d18d8a1d 472 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
473 parameter is ignored by device drivers, and is optional for bus\r
474 drivers. For a bus driver, if this parameter is NULL, then handles\r
475 for all the children of Controller are created by this driver.\r
476 If this parameter is not NULL and the first Device Path Node is\r
477 not the End of Device Path Node, then only the handle for the\r
478 child device specified by the first Device Path Node of\r
d59326d3 479 RemainingDevicePath is created by this driver.\r
d18d8a1d 480 If the first Device Path Node of RemainingDevicePath is\r
d59326d3 481 the End of Device Path Node, no child handle is created by this\r
482 driver.\r
483\r
484 @retval EFI_SUCCESS The device was started.\r
485 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.\r
486 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
487 @retval Others The driver failded to start the device.\r
488\r
489**/\r
490EFI_STATUS\r
491EFIAPI\r
492EmuBlockIoDriverBindingStart (\r
493 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
494 IN EFI_HANDLE Handle,\r
495 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
496 )\r
497{\r
498 EFI_STATUS Status;\r
499 EMU_IO_THUNK_PROTOCOL *EmuIoThunk;\r
7e284acb 500 EMU_BLOCK_IO_PRIVATE *Private = NULL;\r
d59326d3 501\r
502 //\r
503 // Grab the protocols we need\r
504 //\r
d18d8a1d 505\r
d59326d3 506 Status = gBS->OpenProtocol (\r
507 Handle,\r
508 &gEmuIoThunkProtocolGuid,\r
509 (void *)&EmuIoThunk,\r
510 This->DriverBindingHandle,\r
511 Handle,\r
512 EFI_OPEN_PROTOCOL_BY_DRIVER\r
513 );\r
514 if (EFI_ERROR (Status)) {\r
515 return Status;\r
516 }\r
d18d8a1d 517\r
033d0e5f 518 if (!CompareGuid (EmuIoThunk->Protocol, &gEmuBlockIoProtocolGuid)) {\r
d59326d3 519 Status = EFI_UNSUPPORTED;\r
520 goto Done;\r
521 }\r
522\r
523 Status = EmuIoThunk->Open (EmuIoThunk);\r
524 if (EFI_ERROR (Status)) {\r
525 goto Done;\r
526 }\r
527\r
528 Private = AllocatePool (sizeof (EMU_BLOCK_IO_PRIVATE));\r
529 if (Private == NULL) {\r
530 goto Done;\r
531 }\r
532\r
533 Private->Signature = EMU_BLOCK_IO_PRIVATE_SIGNATURE;\r
534 Private->IoThunk = EmuIoThunk;\r
535 Private->Io = EmuIoThunk->Interface;\r
033d0e5f 536 Private->EfiHandle = Handle;\r
d18d8a1d 537\r
d59326d3 538 Private->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION2;\r
539 Private->BlockIo.Media = &Private->Media;\r
540 Private->BlockIo.Reset = EmuBlockIoReset;\r
541 Private->BlockIo.ReadBlocks = EmuBlockIoReadBlocks;\r
542 Private->BlockIo.WriteBlocks = EmuBlockIoWriteBlocks;\r
543 Private->BlockIo.FlushBlocks = EmuBlockIoFlushBlocks;\r
544\r
545 Private->BlockIo2.Media = &Private->Media;\r
546 Private->BlockIo2.Reset = EmuBlockIo2Reset;\r
547 Private->BlockIo2.ReadBlocksEx = EmuBlockIo2ReadBlocksEx;\r
548 Private->BlockIo2.WriteBlocksEx = EmuBlockIo2WriteBlocksEx;\r
63947cc4 549 Private->BlockIo2.FlushBlocksEx = EmuBlockIo2Flush;\r
d59326d3 550\r
551 Private->ControllerNameTable = NULL;\r
552\r
553 Status = Private->Io->CreateMapping (Private->Io, &Private->Media);\r
554 if (EFI_ERROR (Status)) {\r
555 goto Done;\r
556 }\r
557\r
558 AddUnicodeString2 (\r
559 "eng",\r
560 gEmuBlockIoComponentName.SupportedLanguages,\r
561 &Private->ControllerNameTable,\r
562 EmuIoThunk->ConfigString,\r
563 TRUE\r
564 );\r
d18d8a1d 565\r
d59326d3 566 AddUnicodeString2 (\r
567 "en",\r
568 gEmuBlockIoComponentName2.SupportedLanguages,\r
569 &Private->ControllerNameTable,\r
570 EmuIoThunk->ConfigString,\r
571 FALSE\r
572 );\r
573\r
574 Status = gBS->InstallMultipleProtocolInterfaces (\r
575 &Handle,\r
576 &gEfiBlockIoProtocolGuid, &Private->BlockIo,\r
577 &gEfiBlockIo2ProtocolGuid, &Private->BlockIo2,\r
578 NULL\r
579 );\r
580\r
581Done:\r
582 if (EFI_ERROR (Status)) {\r
583 if (Private != NULL) {\r
584 if (Private->ControllerNameTable != NULL) {\r
585 FreeUnicodeStringTable (Private->ControllerNameTable);\r
586 }\r
d18d8a1d 587\r
d59326d3 588 gBS->FreePool (Private);\r
d18d8a1d 589\r
d59326d3 590 }\r
d18d8a1d 591\r
d59326d3 592 gBS->CloseProtocol (\r
593 Handle,\r
594 &gEmuIoThunkProtocolGuid,\r
595 This->DriverBindingHandle,\r
596 Handle\r
597 );\r
598 }\r
599\r
600 return Status;\r
601}\r
602\r
603\r
604/**\r
605 Stops a device controller or a bus controller.\r
d18d8a1d 606\r
607 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().\r
608 As a result, much of the error checking on the parameters to Stop() has been moved\r
609 into this common boot service. It is legal to call Stop() from other locations,\r
d59326d3 610 but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
611 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
612 same driver's Start() function.\r
613 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
614 EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
615 Start() function, and the Start() function must have called OpenProtocol() on\r
616 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
d18d8a1d 617\r
d59326d3 618 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
d18d8a1d 619 @param[in] ControllerHandle A handle to the device being stopped. The handle must\r
620 support a bus specific I/O protocol for the driver\r
d59326d3 621 to use to stop the device.\r
622 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
d18d8a1d 623 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL\r
d59326d3 624 if NumberOfChildren is 0.\r
625\r
626 @retval EFI_SUCCESS The device was stopped.\r
627 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
628\r
629**/\r
630EFI_STATUS\r
631EFIAPI\r
632EmuBlockIoDriverBindingStop (\r
633 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
634 IN EFI_HANDLE Handle,\r
635 IN UINTN NumberOfChildren,\r
636 IN EFI_HANDLE *ChildHandleBuffer\r
637 )\r
638{\r
639 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
640 EFI_STATUS Status;\r
641 EMU_BLOCK_IO_PRIVATE *Private;\r
642\r
643 //\r
644 // Get our context back\r
645 //\r
646 Status = gBS->OpenProtocol (\r
647 Handle,\r
648 &gEfiBlockIoProtocolGuid,\r
649 (void *)&BlockIo,\r
650 This->DriverBindingHandle,\r
651 Handle,\r
652 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
653 );\r
654 if (EFI_ERROR (Status)) {\r
655 return EFI_UNSUPPORTED;\r
656 }\r
657\r
658 Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (BlockIo);\r
d59326d3 659\r
660 Status = gBS->UninstallMultipleProtocolInterfaces (\r
661 Private->EfiHandle,\r
662 &gEfiBlockIoProtocolGuid, &Private->BlockIo,\r
663 &gEfiBlockIo2ProtocolGuid, &Private->BlockIo2,\r
664 NULL\r
665 );\r
666 if (!EFI_ERROR (Status)) {\r
667 Status = gBS->CloseProtocol (\r
668 Handle,\r
669 &gEmuIoThunkProtocolGuid,\r
670 This->DriverBindingHandle,\r
671 Handle\r
672 );\r
1e571882
RN
673 ASSERT_EFI_ERROR (Status);\r
674 //\r
675 // Destroy the IO interface.\r
676 //\r
677 Status = Private->IoThunk->Close (Private->IoThunk);\r
678 ASSERT_EFI_ERROR (Status);\r
d59326d3 679 //\r
680 // Free our instance data\r
681 //\r
682 FreeUnicodeStringTable (Private->ControllerNameTable);\r
1e571882 683 FreePool (Private);\r
d59326d3 684 }\r
685\r
686 return Status;\r
687}\r
688\r
689\r
690\r
691\r
692\r
693EFI_DRIVER_BINDING_PROTOCOL gEmuBlockIoDriverBinding = {\r
694 EmuBlockIoDriverBindingSupported,\r
695 EmuBlockIoDriverBindingStart,\r
696 EmuBlockIoDriverBindingStop,\r
697 0xa,\r
698 NULL,\r
699 NULL\r
700};\r
701\r
702\r
703\r
704\r
705/**\r
706 The user Entry Point for module EmuBlockIo . The user code starts with this function.\r
707\r
d18d8a1d 708 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
d59326d3 709 @param[in] SystemTable A pointer to the EFI System Table.\r
d18d8a1d 710\r
d59326d3 711 @retval EFI_SUCCESS The entry point is executed successfully.\r
712 @retval other Some error occurs when executing this entry point.\r
713\r
714**/\r
715EFI_STATUS\r
716EFIAPI\r
717InitializeEmuBlockIo (\r
718 IN EFI_HANDLE ImageHandle,\r
719 IN EFI_SYSTEM_TABLE *SystemTable\r
720 )\r
721{\r
722 EFI_STATUS Status;\r
723\r
724 Status = EfiLibInstallAllDriverProtocols2 (\r
725 ImageHandle,\r
726 SystemTable,\r
727 &gEmuBlockIoDriverBinding,\r
728 ImageHandle,\r
729 &gEmuBlockIoComponentName,\r
730 &gEmuBlockIoComponentName2,\r
731 NULL,\r
732 NULL,\r
733 &gEmuBlockIoDriverDiagnostics,\r
734 &gEmuBlockIoDriverDiagnostics2\r
735 );\r
736 ASSERT_EFI_ERROR (Status);\r
737\r
738\r
739 return Status;\r
740}\r
741\r
742\r
743\r