TianoCore EDK2 master
Loading...
Searching...
No Matches
UsbMassImpl.c
Go to the documentation of this file.
1
9#include "UsbMass.h"
10
11#define USB_MASS_TRANSPORT_COUNT 3
12//
13// Array of USB transport interfaces.
14//
15USB_MASS_TRANSPORT *mUsbMassTransport[USB_MASS_TRANSPORT_COUNT] = {
16 &mUsbCbi0Transport,
17 &mUsbCbi1Transport,
18 &mUsbBotTransport,
19};
20
21EFI_DRIVER_BINDING_PROTOCOL gUSBMassDriverBinding = {
25 0x11,
26 NULL,
27 NULL
28};
29
46EFIAPI
49 IN BOOLEAN ExtendedVerification
50 )
51{
52 USB_MASS_DEVICE *UsbMass;
53 EFI_TPL OldTpl;
54 EFI_STATUS Status;
55
56 //
57 // Raise TPL to TPL_CALLBACK to serialize all its operations
58 // to protect shared data structures.
59 //
60 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
61
62 UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (This);
63 Status = UsbMass->Transport->Reset (UsbMass->Context, ExtendedVerification);
64
65 gBS->RestoreTPL (OldTpl);
66
67 return Status;
68}
69
95EFIAPI
98 IN UINT32 MediaId,
99 IN EFI_LBA Lba,
100 IN UINTN BufferSize,
101 OUT VOID *Buffer
102 )
103{
104 USB_MASS_DEVICE *UsbMass;
105 EFI_BLOCK_IO_MEDIA *Media;
106 EFI_STATUS Status;
107 EFI_TPL OldTpl;
108 UINTN TotalBlock;
109
110 //
111 // Raise TPL to TPL_CALLBACK to serialize all its operations
112 // to protect shared data structures.
113 //
114 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
115 UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (This);
116 Media = &UsbMass->BlockIoMedia;
117
118 //
119 // If it is a removable media, such as CD-Rom or Usb-Floppy,
120 // need to detect the media before each read/write. While some of
121 // Usb-Flash is marked as removable media.
122 //
123 if (Media->RemovableMedia) {
124 Status = UsbBootDetectMedia (UsbMass);
125 if (EFI_ERROR (Status)) {
126 goto ON_EXIT;
127 }
128 }
129
130 if (!(Media->MediaPresent)) {
131 Status = EFI_NO_MEDIA;
132 goto ON_EXIT;
133 }
134
135 if (MediaId != Media->MediaId) {
136 Status = EFI_MEDIA_CHANGED;
137 goto ON_EXIT;
138 }
139
140 if (BufferSize == 0) {
141 Status = EFI_SUCCESS;
142 goto ON_EXIT;
143 }
144
145 if (Buffer == NULL) {
146 Status = EFI_INVALID_PARAMETER;
147 goto ON_EXIT;
148 }
149
150 //
151 // BufferSize must be a multiple of the intrinsic block size of the device.
152 //
153 if ((BufferSize % Media->BlockSize) != 0) {
154 Status = EFI_BAD_BUFFER_SIZE;
155 goto ON_EXIT;
156 }
157
158 TotalBlock = BufferSize / Media->BlockSize;
159
160 //
161 // Make sure the range to read is valid.
162 //
163 if (Lba + TotalBlock - 1 > Media->LastBlock) {
164 Status = EFI_INVALID_PARAMETER;
165 goto ON_EXIT;
166 }
167
168 if (UsbMass->Cdb16Byte) {
169 Status = UsbBootReadWriteBlocks16 (UsbMass, FALSE, Lba, TotalBlock, Buffer);
170 } else {
171 Status = UsbBootReadWriteBlocks (UsbMass, FALSE, (UINT32)Lba, TotalBlock, Buffer);
172 }
173
174 if (EFI_ERROR (Status)) {
175 DEBUG ((DEBUG_ERROR, "UsbMassReadBlocks: UsbBootReadBlocks (%r) -> Reset\n", Status));
176 UsbMassReset (This, TRUE);
177 }
178
179ON_EXIT:
180 gBS->RestoreTPL (OldTpl);
181 return Status;
182}
183
210EFIAPI
213 IN UINT32 MediaId,
214 IN EFI_LBA Lba,
215 IN UINTN BufferSize,
216 IN VOID *Buffer
217 )
218{
219 USB_MASS_DEVICE *UsbMass;
220 EFI_BLOCK_IO_MEDIA *Media;
221 EFI_STATUS Status;
222 EFI_TPL OldTpl;
223 UINTN TotalBlock;
224
225 //
226 // Raise TPL to TPL_CALLBACK to serialize all its operations
227 // to protect shared data structures.
228 //
229 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
230 UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (This);
231 Media = &UsbMass->BlockIoMedia;
232
233 //
234 // If it is a removable media, such as CD-Rom or Usb-Floppy,
235 // need to detect the media before each read/write. Some of
236 // USB Flash is marked as removable media.
237 //
238 if (Media->RemovableMedia) {
239 Status = UsbBootDetectMedia (UsbMass);
240 if (EFI_ERROR (Status)) {
241 goto ON_EXIT;
242 }
243 }
244
245 if (!(Media->MediaPresent)) {
246 Status = EFI_NO_MEDIA;
247 goto ON_EXIT;
248 }
249
250 if (MediaId != Media->MediaId) {
251 Status = EFI_MEDIA_CHANGED;
252 goto ON_EXIT;
253 }
254
255 if (BufferSize == 0) {
256 Status = EFI_SUCCESS;
257 goto ON_EXIT;
258 }
259
260 if (Buffer == NULL) {
261 Status = EFI_INVALID_PARAMETER;
262 goto ON_EXIT;
263 }
264
265 //
266 // BufferSize must be a multiple of the intrinsic block size of the device.
267 //
268 if ((BufferSize % Media->BlockSize) != 0) {
269 Status = EFI_BAD_BUFFER_SIZE;
270 goto ON_EXIT;
271 }
272
273 TotalBlock = BufferSize / Media->BlockSize;
274
275 //
276 // Make sure the range to write is valid.
277 //
278 if (Lba + TotalBlock - 1 > Media->LastBlock) {
279 Status = EFI_INVALID_PARAMETER;
280 goto ON_EXIT;
281 }
282
283 //
284 // Try to write the data even the device is marked as ReadOnly,
285 // and clear the status should the write succeed.
286 //
287 if (UsbMass->Cdb16Byte) {
288 Status = UsbBootReadWriteBlocks16 (UsbMass, TRUE, Lba, TotalBlock, Buffer);
289 } else {
290 Status = UsbBootReadWriteBlocks (UsbMass, TRUE, (UINT32)Lba, TotalBlock, Buffer);
291 }
292
293 if (EFI_ERROR (Status)) {
294 DEBUG ((DEBUG_ERROR, "UsbMassWriteBlocks: UsbBootWriteBlocks (%r) -> Reset\n", Status));
295 UsbMassReset (This, TRUE);
296 }
297
298ON_EXIT:
299 gBS->RestoreTPL (OldTpl);
300 return Status;
301}
302
318EFIAPI
321 )
322{
323 return EFI_SUCCESS;
324}
325
337 IN USB_MASS_DEVICE *UsbMass
338 )
339{
340 EFI_BLOCK_IO_MEDIA *Media;
341 EFI_STATUS Status;
342
343 Media = &UsbMass->BlockIoMedia;
344
345 //
346 // Fields of EFI_BLOCK_IO_MEDIA are defined in UEFI 2.0 spec,
347 // section for Block I/O Protocol.
348 //
349 Media->MediaPresent = FALSE;
350 Media->LogicalPartition = FALSE;
351 Media->ReadOnly = FALSE;
352 Media->WriteCaching = FALSE;
353 Media->IoAlign = 0;
354 Media->MediaId = 1;
355
356 Status = UsbBootGetParams (UsbMass);
357 DEBUG ((DEBUG_INFO, "UsbMassInitMedia: UsbBootGetParams (%r)\n", Status));
358 if (Status == EFI_MEDIA_CHANGED) {
359 //
360 // Some USB storage devices may report MEDIA_CHANGED sense key when hot-plugged.
361 // Treat it as SUCCESS
362 //
363 Status = EFI_SUCCESS;
364 }
365
366 return Status;
367}
368
389 IN EFI_HANDLE Controller,
390 OUT USB_MASS_TRANSPORT **Transport,
391 OUT VOID **Context,
392 OUT UINT8 *MaxLun
393 )
394{
395 EFI_USB_IO_PROTOCOL *UsbIo;
397 UINT8 Index;
398 EFI_STATUS Status;
399
400 Status = gBS->OpenProtocol (
401 Controller,
402 &gEfiUsbIoProtocolGuid,
403 (VOID **)&UsbIo,
404 This->DriverBindingHandle,
405 Controller,
406 EFI_OPEN_PROTOCOL_BY_DRIVER
407 );
408
409 if (EFI_ERROR (Status)) {
410 return Status;
411 }
412
413 Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
414 if (EFI_ERROR (Status)) {
415 goto ON_EXIT;
416 }
417
418 Status = EFI_UNSUPPORTED;
419
420 //
421 // Traverse the USB_MASS_TRANSPORT arrary and try to find the
422 // matching transport protocol.
423 // If not found, return EFI_UNSUPPORTED.
424 // If found, execute USB_MASS_TRANSPORT.Init() to initialize the transport context.
425 //
426 for (Index = 0; Index < USB_MASS_TRANSPORT_COUNT; Index++) {
427 *Transport = mUsbMassTransport[Index];
428
429 if (Interface.InterfaceProtocol == (*Transport)->Protocol) {
430 Status = (*Transport)->Init (UsbIo, Context);
431 break;
432 }
433 }
434
435 if (EFI_ERROR (Status)) {
436 goto ON_EXIT;
437 }
438
439 //
440 // For BOT device, try to get its max LUN.
441 // If max LUN is 0, then it is a non-lun device.
442 // Otherwise, it is a multi-lun device.
443 //
444 if ((*Transport)->Protocol == USB_MASS_STORE_BOT) {
445 (*Transport)->GetMaxLun (*Context, MaxLun);
446 }
447
448ON_EXIT:
449 gBS->CloseProtocol (
450 Controller,
451 &gEfiUsbIoProtocolGuid,
452 This->DriverBindingHandle,
453 Controller
454 );
455 return Status;
456}
457
475 IN EFI_HANDLE Controller,
476 IN USB_MASS_TRANSPORT *Transport,
477 IN VOID *Context,
478 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
479 IN UINT8 MaxLun
480 )
481{
482 USB_MASS_DEVICE *UsbMass;
483 EFI_USB_IO_PROTOCOL *UsbIo;
485 UINT8 Index;
486 EFI_STATUS Status;
487 EFI_STATUS ReturnStatus;
488
489 ASSERT (MaxLun > 0);
490 ReturnStatus = EFI_NOT_FOUND;
491
492 for (Index = 0; Index <= MaxLun; Index++) {
493 DEBUG ((DEBUG_INFO, "UsbMassInitMultiLun: Start to initialize No.%d logic unit\n", Index));
494
495 UsbIo = NULL;
496 UsbMass = AllocateZeroPool (sizeof (USB_MASS_DEVICE));
497 ASSERT (UsbMass != NULL);
498
499 UsbMass->Signature = USB_MASS_SIGNATURE;
500 UsbMass->UsbIo = UsbIo;
501 UsbMass->BlockIo.Media = &UsbMass->BlockIoMedia;
502 UsbMass->BlockIo.Reset = UsbMassReset;
503 UsbMass->BlockIo.ReadBlocks = UsbMassReadBlocks;
504 UsbMass->BlockIo.WriteBlocks = UsbMassWriteBlocks;
505 UsbMass->BlockIo.FlushBlocks = UsbMassFlushBlocks;
506 UsbMass->OpticalStorage = FALSE;
507 UsbMass->Transport = Transport;
508 UsbMass->Context = Context;
509 UsbMass->Lun = Index;
510
511 //
512 // Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol.
513 //
514 Status = UsbMassInitMedia (UsbMass);
515 if ((EFI_ERROR (Status)) && (Status != EFI_NO_MEDIA)) {
516 DEBUG ((DEBUG_ERROR, "UsbMassInitMultiLun: UsbMassInitMedia (%r)\n", Status));
517 FreePool (UsbMass);
518 continue;
519 }
520
521 //
522 // Create a device path node for device logic unit, and append it.
523 //
524 LunNode.Header.Type = MESSAGING_DEVICE_PATH;
525 LunNode.Header.SubType = MSG_DEVICE_LOGICAL_UNIT_DP;
526 LunNode.Lun = UsbMass->Lun;
527
528 SetDevicePathNodeLength (&LunNode.Header, sizeof (LunNode));
529
530 UsbMass->DevicePath = AppendDevicePathNode (DevicePath, &LunNode.Header);
531
532 if (UsbMass->DevicePath == NULL) {
533 DEBUG ((DEBUG_ERROR, "UsbMassInitMultiLun: failed to create device logic unit device path\n"));
534 Status = EFI_OUT_OF_RESOURCES;
535 FreePool (UsbMass);
536 continue;
537 }
538
539 InitializeDiskInfo (UsbMass);
540
541 //
542 // Create a new handle for each LUN, and install Block I/O Protocol and Device Path Protocol.
543 //
544 Status = gBS->InstallMultipleProtocolInterfaces (
545 &UsbMass->Controller,
546 &gEfiDevicePathProtocolGuid,
547 UsbMass->DevicePath,
548 &gEfiBlockIoProtocolGuid,
549 &UsbMass->BlockIo,
550 &gEfiDiskInfoProtocolGuid,
551 &UsbMass->DiskInfo,
552 NULL
553 );
554
555 if (EFI_ERROR (Status)) {
556 DEBUG ((DEBUG_ERROR, "UsbMassInitMultiLun: InstallMultipleProtocolInterfaces (%r)\n", Status));
557 FreePool (UsbMass->DevicePath);
558 FreePool (UsbMass);
559 continue;
560 }
561
562 //
563 // Open USB I/O Protocol by child to setup a parent-child relationship.
564 //
565 Status = gBS->OpenProtocol (
566 Controller,
567 &gEfiUsbIoProtocolGuid,
568 (VOID **)&UsbIo,
569 This->DriverBindingHandle,
570 UsbMass->Controller,
571 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
572 );
573
574 if (EFI_ERROR (Status)) {
575 DEBUG ((DEBUG_ERROR, "UsbMassInitMultiLun: OpenUsbIoProtocol By Child (%r)\n", Status));
576 gBS->UninstallMultipleProtocolInterfaces (
577 UsbMass->Controller,
578 &gEfiDevicePathProtocolGuid,
579 UsbMass->DevicePath,
580 &gEfiBlockIoProtocolGuid,
581 &UsbMass->BlockIo,
582 &gEfiDiskInfoProtocolGuid,
583 &UsbMass->DiskInfo,
584 NULL
585 );
586 FreePool (UsbMass->DevicePath);
587 FreePool (UsbMass);
588 continue;
589 }
590
591 ReturnStatus = EFI_SUCCESS;
592 DEBUG ((DEBUG_INFO, "UsbMassInitMultiLun: Success to initialize No.%d logic unit\n", Index));
593 }
594
595 return ReturnStatus;
596}
597
613 IN EFI_HANDLE Controller,
614 IN USB_MASS_TRANSPORT *Transport,
615 IN VOID *Context
616 )
617{
618 USB_MASS_DEVICE *UsbMass;
619 EFI_USB_IO_PROTOCOL *UsbIo;
620 EFI_STATUS Status;
621
622 UsbIo = NULL;
623 UsbMass = AllocateZeroPool (sizeof (USB_MASS_DEVICE));
624 ASSERT (UsbMass != NULL);
625
626 Status = gBS->OpenProtocol (
627 Controller,
628 &gEfiUsbIoProtocolGuid,
629 (VOID **)&UsbIo,
630 This->DriverBindingHandle,
631 Controller,
632 EFI_OPEN_PROTOCOL_BY_DRIVER
633 );
634
635 if (EFI_ERROR (Status)) {
636 DEBUG ((DEBUG_ERROR, "UsbMassInitNonLun: OpenUsbIoProtocol By Driver (%r)\n", Status));
637 goto ON_ERROR;
638 }
639
640 UsbMass->Signature = USB_MASS_SIGNATURE;
641 UsbMass->Controller = Controller;
642 UsbMass->UsbIo = UsbIo;
643 UsbMass->BlockIo.Media = &UsbMass->BlockIoMedia;
644 UsbMass->BlockIo.Reset = UsbMassReset;
645 UsbMass->BlockIo.ReadBlocks = UsbMassReadBlocks;
646 UsbMass->BlockIo.WriteBlocks = UsbMassWriteBlocks;
647 UsbMass->BlockIo.FlushBlocks = UsbMassFlushBlocks;
648 UsbMass->OpticalStorage = FALSE;
649 UsbMass->Transport = Transport;
650 UsbMass->Context = Context;
651
652 //
653 // Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol.
654 //
655 Status = UsbMassInitMedia (UsbMass);
656 if ((EFI_ERROR (Status)) && (Status != EFI_NO_MEDIA)) {
657 DEBUG ((DEBUG_ERROR, "UsbMassInitNonLun: UsbMassInitMedia (%r)\n", Status));
658 goto ON_ERROR;
659 }
660
661 InitializeDiskInfo (UsbMass);
662
663 Status = gBS->InstallMultipleProtocolInterfaces (
664 &Controller,
665 &gEfiBlockIoProtocolGuid,
666 &UsbMass->BlockIo,
667 &gEfiDiskInfoProtocolGuid,
668 &UsbMass->DiskInfo,
669 NULL
670 );
671 if (EFI_ERROR (Status)) {
672 goto ON_ERROR;
673 }
674
675 return EFI_SUCCESS;
676
677ON_ERROR:
678 if (UsbMass != NULL) {
679 FreePool (UsbMass);
680 }
681
682 if (UsbIo != NULL) {
683 gBS->CloseProtocol (
684 Controller,
685 &gEfiUsbIoProtocolGuid,
686 This->DriverBindingHandle,
687 Controller
688 );
689 }
690
691 return Status;
692}
693
706EFIAPI
709 IN EFI_HANDLE Controller,
710 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
711 )
712{
713 EFI_USB_IO_PROTOCOL *UsbIo;
715 USB_MASS_TRANSPORT *Transport;
716 EFI_STATUS Status;
717 UINTN Index;
718
719 Status = gBS->OpenProtocol (
720 Controller,
721 &gEfiUsbIoProtocolGuid,
722 (VOID **)&UsbIo,
723 This->DriverBindingHandle,
724 Controller,
725 EFI_OPEN_PROTOCOL_BY_DRIVER
726 );
727 if (EFI_ERROR (Status)) {
728 return Status;
729 }
730
731 //
732 // Get the interface descriptor to check the USB class and find a transport
733 // protocol handler.
734 //
735 Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
736 if (EFI_ERROR (Status)) {
737 goto ON_EXIT;
738 }
739
740 Status = EFI_UNSUPPORTED;
741
742 if (Interface.InterfaceClass != USB_MASS_STORE_CLASS) {
743 goto ON_EXIT;
744 }
745
746 //
747 // Traverse the USB_MASS_TRANSPORT arrary and try to find the
748 // matching transport method.
749 // If not found, return EFI_UNSUPPORTED.
750 // If found, execute USB_MASS_TRANSPORT.Init() to initialize the transport context.
751 //
752 for (Index = 0; Index < USB_MASS_TRANSPORT_COUNT; Index++) {
753 Transport = mUsbMassTransport[Index];
754 if (Interface.InterfaceProtocol == Transport->Protocol) {
755 Status = Transport->Init (UsbIo, NULL);
756 break;
757 }
758 }
759
760ON_EXIT:
761 gBS->CloseProtocol (
762 Controller,
763 &gEfiUsbIoProtocolGuid,
764 This->DriverBindingHandle,
765 Controller
766 );
767
768 return Status;
769}
770
790EFIAPI
793 IN EFI_HANDLE Controller,
794 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
795 )
796{
797 USB_MASS_TRANSPORT *Transport;
798 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
799 VOID *Context;
800 UINT8 MaxLun;
801 EFI_STATUS Status;
802 EFI_USB_IO_PROTOCOL *UsbIo;
803 EFI_TPL OldTpl;
804
805 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
806
807 Transport = NULL;
808 Context = NULL;
809 MaxLun = 0;
810
811 Status = UsbMassInitTransport (This, Controller, &Transport, &Context, &MaxLun);
812
813 if (EFI_ERROR (Status)) {
814 DEBUG ((DEBUG_ERROR, "USBMassDriverBindingStart: UsbMassInitTransport (%r)\n", Status));
815 goto Exit;
816 }
817
818 if (MaxLun == 0) {
819 //
820 // Initialize data for device that does not support multiple LUNSs.
821 //
822 Status = UsbMassInitNonLun (This, Controller, Transport, Context);
823 if (EFI_ERROR (Status)) {
824 DEBUG ((DEBUG_ERROR, "USBMassDriverBindingStart: UsbMassInitNonLun (%r)\n", Status));
825 }
826 } else {
827 //
828 // Open device path to prepare for appending Device Logic Unit node.
829 //
830 Status = gBS->OpenProtocol (
831 Controller,
832 &gEfiDevicePathProtocolGuid,
833 (VOID **)&DevicePath,
834 This->DriverBindingHandle,
835 Controller,
836 EFI_OPEN_PROTOCOL_BY_DRIVER
837 );
838
839 if (EFI_ERROR (Status)) {
840 DEBUG ((DEBUG_ERROR, "USBMassDriverBindingStart: OpenDevicePathProtocol By Driver (%r)\n", Status));
841 goto Exit;
842 }
843
844 Status = gBS->OpenProtocol (
845 Controller,
846 &gEfiUsbIoProtocolGuid,
847 (VOID **)&UsbIo,
848 This->DriverBindingHandle,
849 Controller,
850 EFI_OPEN_PROTOCOL_BY_DRIVER
851 );
852
853 if (EFI_ERROR (Status)) {
854 DEBUG ((DEBUG_ERROR, "USBMassDriverBindingStart: OpenUsbIoProtocol By Driver (%r)\n", Status));
855 gBS->CloseProtocol (
856 Controller,
857 &gEfiDevicePathProtocolGuid,
858 This->DriverBindingHandle,
859 Controller
860 );
861 goto Exit;
862 }
863
864 //
865 // Initialize data for device that supports multiple LUNs.
866 // EFI_SUCCESS is returned if at least 1 LUN is initialized successfully.
867 //
868 Status = UsbMassInitMultiLun (This, Controller, Transport, Context, DevicePath, MaxLun);
869 if (EFI_ERROR (Status)) {
870 gBS->CloseProtocol (
871 Controller,
872 &gEfiDevicePathProtocolGuid,
873 This->DriverBindingHandle,
874 Controller
875 );
876 gBS->CloseProtocol (
877 Controller,
878 &gEfiUsbIoProtocolGuid,
879 This->DriverBindingHandle,
880 Controller
881 );
882 DEBUG ((DEBUG_ERROR, "USBMassDriverBindingStart: UsbMassInitMultiLun (%r) with Maxlun=%d\n", Status, MaxLun));
883 }
884 }
885
886Exit:
887 gBS->RestoreTPL (OldTpl);
888 return Status;
889}
890
906EFIAPI
909 IN EFI_HANDLE Controller,
910 IN UINTN NumberOfChildren,
911 IN EFI_HANDLE *ChildHandleBuffer
912 )
913{
914 EFI_STATUS Status;
915 USB_MASS_DEVICE *UsbMass;
916 EFI_USB_IO_PROTOCOL *UsbIo;
917 EFI_BLOCK_IO_PROTOCOL *BlockIo;
918 UINTN Index;
919 BOOLEAN AllChildrenStopped;
920
921 //
922 // This is a bus driver stop function since multi-lun is supported.
923 // There are three kinds of device handles that might be passed:
924 // 1st is a handle with USB I/O & Block I/O installed (non-multi-lun)
925 // 2nd is a handle with Device Path & USB I/O installed (multi-lun root)
926 // 3rd is a handle with Device Path & USB I/O & Block I/O installed (multi-lun).
927 //
928 if (NumberOfChildren == 0) {
929 //
930 // A handle without any children, might be 1st and 2nd type.
931 //
932 Status = gBS->OpenProtocol (
933 Controller,
934 &gEfiBlockIoProtocolGuid,
935 (VOID **)&BlockIo,
936 This->DriverBindingHandle,
937 Controller,
938 EFI_OPEN_PROTOCOL_GET_PROTOCOL
939 );
940
941 if (EFI_ERROR (Status)) {
942 //
943 // This is a 2nd type handle(multi-lun root), it needs to close devicepath
944 // and usbio protocol.
945 //
946 gBS->CloseProtocol (
947 Controller,
948 &gEfiDevicePathProtocolGuid,
949 This->DriverBindingHandle,
950 Controller
951 );
952 gBS->CloseProtocol (
953 Controller,
954 &gEfiUsbIoProtocolGuid,
955 This->DriverBindingHandle,
956 Controller
957 );
958 DEBUG ((DEBUG_INFO, "Success to stop multi-lun root handle\n"));
959 return EFI_SUCCESS;
960 }
961
962 //
963 // This is a 1st type handle(non-multi-lun), which only needs to uninstall
964 // Block I/O Protocol, close USB I/O Protocol and free mass device.
965 //
966 UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (BlockIo);
967
968 //
969 // Uninstall Block I/O protocol from the device handle,
970 // then call the transport protocol to stop itself.
971 //
972 Status = gBS->UninstallMultipleProtocolInterfaces (
973 Controller,
974 &gEfiBlockIoProtocolGuid,
975 &UsbMass->BlockIo,
976 &gEfiDiskInfoProtocolGuid,
977 &UsbMass->DiskInfo,
978 NULL
979 );
980 if (EFI_ERROR (Status)) {
981 return Status;
982 }
983
984 gBS->CloseProtocol (
985 Controller,
986 &gEfiUsbIoProtocolGuid,
987 This->DriverBindingHandle,
988 Controller
989 );
990
991 UsbMass->Transport->CleanUp (UsbMass->Context);
992 FreePool (UsbMass);
993
994 DEBUG ((DEBUG_INFO, "Success to stop non-multi-lun root handle\n"));
995 return EFI_SUCCESS;
996 }
997
998 //
999 // This is a 3rd type handle(multi-lun), which needs uninstall
1000 // Block I/O Protocol and Device Path Protocol, close USB I/O Protocol and
1001 // free mass device for all children.
1002 //
1003 AllChildrenStopped = TRUE;
1004
1005 for (Index = 0; Index < NumberOfChildren; Index++) {
1006 Status = gBS->OpenProtocol (
1007 ChildHandleBuffer[Index],
1008 &gEfiBlockIoProtocolGuid,
1009 (VOID **)&BlockIo,
1010 This->DriverBindingHandle,
1011 Controller,
1012 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1013 );
1014 if (EFI_ERROR (Status)) {
1015 AllChildrenStopped = FALSE;
1016 DEBUG ((DEBUG_ERROR, "Fail to stop No.%d multi-lun child handle when opening blockio\n", (UINT32)Index));
1017 continue;
1018 }
1019
1020 UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (BlockIo);
1021
1022 gBS->CloseProtocol (
1023 Controller,
1024 &gEfiUsbIoProtocolGuid,
1025 This->DriverBindingHandle,
1026 ChildHandleBuffer[Index]
1027 );
1028
1029 Status = gBS->UninstallMultipleProtocolInterfaces (
1030 ChildHandleBuffer[Index],
1031 &gEfiDevicePathProtocolGuid,
1032 UsbMass->DevicePath,
1033 &gEfiBlockIoProtocolGuid,
1034 &UsbMass->BlockIo,
1035 &gEfiDiskInfoProtocolGuid,
1036 &UsbMass->DiskInfo,
1037 NULL
1038 );
1039
1040 if (EFI_ERROR (Status)) {
1041 //
1042 // Fail to uninstall Block I/O Protocol and Device Path Protocol, so re-open USB I/O Protocol by child.
1043 //
1044 AllChildrenStopped = FALSE;
1045 DEBUG ((DEBUG_ERROR, "Fail to stop No.%d multi-lun child handle when uninstalling blockio and devicepath\n", (UINT32)Index));
1046
1047 gBS->OpenProtocol (
1048 Controller,
1049 &gEfiUsbIoProtocolGuid,
1050 (VOID **)&UsbIo,
1051 This->DriverBindingHandle,
1052 ChildHandleBuffer[Index],
1053 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1054 );
1055 } else {
1056 //
1057 // Succeed to stop this multi-lun handle, so go on with next child.
1058 //
1059 if (((Index + 1) == NumberOfChildren) && AllChildrenStopped) {
1060 UsbMass->Transport->CleanUp (UsbMass->Context);
1061 }
1062
1063 FreePool (UsbMass);
1064 }
1065 }
1066
1067 if (!AllChildrenStopped) {
1068 return EFI_DEVICE_ERROR;
1069 }
1070
1071 DEBUG ((DEBUG_INFO, "Success to stop all %d multi-lun children handles\n", (UINT32)NumberOfChildren));
1072 return EFI_SUCCESS;
1073}
1074
1088EFIAPI
1090 IN EFI_HANDLE ImageHandle,
1091 IN EFI_SYSTEM_TABLE *SystemTable
1092 )
1093{
1094 EFI_STATUS Status;
1095
1096 //
1097 // Install driver binding protocol
1098 //
1100 ImageHandle,
1101 SystemTable,
1102 &gUSBMassDriverBinding,
1103 ImageHandle,
1104 &gUsbMassStorageComponentName,
1105 &gUsbMassStorageComponentName2
1106 );
1107 ASSERT_EFI_ERROR (Status);
1108
1109 return EFI_SUCCESS;
1110}
UINT64 UINTN
#define MSG_DEVICE_LOGICAL_UNIT_DP
Definition: DevicePath.h:498
#define MESSAGING_DEVICE_PATH
Definition: DevicePath.h:321
UINT16 EFIAPI SetDevicePathNodeLength(IN OUT VOID *Node, IN UINTN Length)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI AppendDevicePathNode(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL, IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode OPTIONAL)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
VOID InitializeDiskInfo(IN NVME_DEVICE_PRIVATE_DATA *Device)
VOID EFIAPI Exit(IN EFI_STATUS Status)
UINT64 EFI_LBA
Definition: UefiBaseType.h:45
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
UINTN EFI_TPL
Definition: UefiBaseType.h:41
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_STATUS EFIAPI EfiLibInstallDriverBindingComponentName2(IN CONST EFI_HANDLE ImageHandle, IN CONST EFI_SYSTEM_TABLE *SystemTable, IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, IN EFI_HANDLE DriverBindingHandle, IN CONST EFI_COMPONENT_NAME_PROTOCOL *ComponentName OPTIONAL, IN CONST EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2 OPTIONAL)
#define USB_MASS_STORE_BOT
Bulk-Only Transport.
Definition: Usb.h:38
EFI_STATUS UsbBootGetParams(IN USB_MASS_DEVICE *UsbMass)
Definition: UsbMassBoot.c:624
EFI_STATUS UsbBootReadWriteBlocks(IN USB_MASS_DEVICE *UsbMass, IN BOOLEAN Write, IN UINT32 Lba, IN UINTN TotalBlock, IN OUT UINT8 *Buffer)
Definition: UsbMassBoot.c:810
EFI_STATUS UsbBootReadWriteBlocks16(IN USB_MASS_DEVICE *UsbMass, IN BOOLEAN Write, IN UINT64 Lba, IN UINTN TotalBlock, IN OUT UINT8 *Buffer)
Definition: UsbMassBoot.c:896
EFI_STATUS UsbBootDetectMedia(IN USB_MASS_DEVICE *UsbMass)
Definition: UsbMassBoot.c:682
EFI_STATUS UsbMassInitMedia(IN USB_MASS_DEVICE *UsbMass)
Definition: UsbMassImpl.c:336
EFI_STATUS EFIAPI UsbMassReset(IN EFI_BLOCK_IO_PROTOCOL *This, IN BOOLEAN ExtendedVerification)
Definition: UsbMassImpl.c:47
EFI_STATUS EFIAPI USBMassDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath)
Definition: UsbMassImpl.c:707
EFI_STATUS EFIAPI USBMassStorageEntryPoint(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: UsbMassImpl.c:1089
EFI_STATUS UsbMassInitTransport(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, OUT USB_MASS_TRANSPORT **Transport, OUT VOID **Context, OUT UINT8 *MaxLun)
Definition: UsbMassImpl.c:387
EFI_STATUS EFIAPI UsbMassReadBlocks(IN EFI_BLOCK_IO_PROTOCOL *This, IN UINT32 MediaId, IN EFI_LBA Lba, IN UINTN BufferSize, OUT VOID *Buffer)
Definition: UsbMassImpl.c:96
EFI_STATUS EFIAPI USBMassDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath)
Definition: UsbMassImpl.c:791
EFI_STATUS UsbMassInitMultiLun(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN USB_MASS_TRANSPORT *Transport, IN VOID *Context, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN UINT8 MaxLun)
Definition: UsbMassImpl.c:473
EFI_STATUS EFIAPI UsbMassFlushBlocks(IN EFI_BLOCK_IO_PROTOCOL *This)
Definition: UsbMassImpl.c:319
EFI_STATUS UsbMassInitNonLun(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN USB_MASS_TRANSPORT *Transport, IN VOID *Context)
Definition: UsbMassImpl.c:611
EFI_STATUS EFIAPI UsbMassWriteBlocks(IN EFI_BLOCK_IO_PROTOCOL *This, IN UINT32 MediaId, IN EFI_LBA Lba, IN UINTN BufferSize, IN VOID *Buffer)
Definition: UsbMassImpl.c:211
EFI_STATUS EFIAPI USBMassDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer)
Definition: UsbMassImpl.c:907
EFI_BLOCK_IO_MEDIA * Media
Definition: BlockIo.h:224
UINT8 Lun
Logical Unit Number.
Definition: UsbMass.h:177
USB_MASS_TRANSPORT * Transport
USB mass storage transport protocol.
Definition: UsbMass.h:179
USB_MASS_INIT_TRANSPORT Init
Initialize the mass storage transport protocol.
Definition: UsbMass.h:162
USB_MASS_RESET Reset
Reset the device.
Definition: UsbMass.h:164
USB_MASS_CLEAN_UP CleanUp
Clean up the resources.
Definition: UsbMass.h:166
BOOLEAN RemovableMedia
Definition: BlockIo.h:137
BOOLEAN LogicalPartition
Definition: BlockIo.h:150
UINT32 BlockSize
Definition: BlockIo.h:167
EFI_LBA LastBlock
Definition: BlockIo.h:178
BOOLEAN WriteCaching
Definition: BlockIo.h:161
BOOLEAN MediaPresent
Definition: BlockIo.h:144
BOOLEAN ReadOnly
Definition: BlockIo.h:156