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