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