]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbMassStorageDxe / UsbMassImpl.c
CommitLineData
e237e7ae 1/** @file\r
d80ed2a7 2 USB Mass Storage Driver that manages USB Mass Storage Device and produces Block I/O Protocol.\r
cc5166ff 3\r
06e24096 4Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
9d510e61 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
e237e7ae 6\r
e237e7ae 7**/\r
8\r
39840c50 9#include "UsbMass.h"\r
e237e7ae 10\r
db0bd81c 11#define USB_MASS_TRANSPORT_COUNT 3\r
d80ed2a7 12//\r
d1102dba 13// Array of USB transport interfaces.\r
d80ed2a7 14//\r
db0bd81c 15USB_MASS_TRANSPORT *mUsbMassTransport[USB_MASS_TRANSPORT_COUNT] = {\r
e237e7ae 16 &mUsbCbi0Transport,\r
17 &mUsbCbi1Transport,\r
18 &mUsbBotTransport,\r
e237e7ae 19};\r
20\r
d80ed2a7 21EFI_DRIVER_BINDING_PROTOCOL gUSBMassDriverBinding = {\r
22 USBMassDriverBindingSupported,\r
23 USBMassDriverBindingStart,\r
24 USBMassDriverBindingStop,\r
25 0x11,\r
26 NULL,\r
27 NULL\r
28};\r
29\r
e237e7ae 30/**\r
d80ed2a7 31 Reset the block device.\r
32\r
d1102dba 33 This function implements EFI_BLOCK_IO_PROTOCOL.Reset().\r
d80ed2a7 34 It resets the block device hardware.\r
35 ExtendedVerification is ignored in this implementation.\r
e237e7ae 36\r
d80ed2a7 37 @param This Indicates a pointer to the calling context.\r
38 @param ExtendedVerification Indicates that the driver may perform a more exhaustive\r
39 verification operation of the device during reset.\r
e237e7ae 40\r
d80ed2a7 41 @retval EFI_SUCCESS The block device was reset.\r
42 @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be reset.\r
e237e7ae 43\r
44**/\r
45EFI_STATUS\r
1c619535 46EFIAPI\r
e237e7ae 47UsbMassReset (\r
48 IN EFI_BLOCK_IO_PROTOCOL *This,\r
49 IN BOOLEAN ExtendedVerification\r
50 )\r
51{\r
52 USB_MASS_DEVICE *UsbMass;\r
41e8ff27 53 EFI_TPL OldTpl;\r
54 EFI_STATUS Status;\r
55\r
d80ed2a7 56 //\r
b77e1a24 57 // Raise TPL to TPL_CALLBACK to serialize all its operations\r
d80ed2a7 58 // to protect shared data structures.\r
59 //\r
3cf6450e 60 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
e237e7ae 61\r
d80ed2a7 62 UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (This);\r
41e8ff27 63 Status = UsbMass->Transport->Reset (UsbMass->Context, ExtendedVerification);\r
64\r
65 gBS->RestoreTPL (OldTpl);\r
66\r
67 return Status;\r
e237e7ae 68}\r
69\r
e237e7ae 70/**\r
d80ed2a7 71 Reads the requested number of blocks from the device.\r
72\r
d1102dba 73 This function implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks().\r
d80ed2a7 74 It reads the requested number of blocks from the device.\r
75 All the blocks are read, or an error is returned.\r
76\r
77 @param This Indicates a pointer to the calling context.\r
78 @param MediaId The media ID that the read request is for.\r
79 @param Lba The starting logical block address to read from on the device.\r
80 @param BufferSize The size of the Buffer in bytes.\r
81 This must be a multiple of the intrinsic block size of the device.\r
82 @param Buffer A pointer to the destination buffer for the data. The caller is\r
83 responsible for either having implicit or explicit ownership of the buffer.\r
84\r
85 @retval EFI_SUCCESS The data was read correctly from the device.\r
86 @retval EFI_DEVICE_ERROR The device reported an error while attempting to perform the read operation.\r
87 @retval EFI_NO_MEDIA There is no media in the device.\r
88 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
89 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the intrinsic block size of the device.\r
90 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,\r
91 or the buffer is not on proper alignment.\r
e237e7ae 92\r
93**/\r
94EFI_STATUS\r
1c619535 95EFIAPI\r
e237e7ae 96UsbMassReadBlocks (\r
97 IN EFI_BLOCK_IO_PROTOCOL *This,\r
98 IN UINT32 MediaId,\r
99 IN EFI_LBA Lba,\r
100 IN UINTN BufferSize,\r
101 OUT VOID *Buffer\r
102 )\r
103{\r
104 USB_MASS_DEVICE *UsbMass;\r
105 EFI_BLOCK_IO_MEDIA *Media;\r
106 EFI_STATUS Status;\r
41e8ff27 107 EFI_TPL OldTpl;\r
e237e7ae 108 UINTN TotalBlock;\r
1c619535 109\r
d80ed2a7 110 //\r
b77e1a24 111 // Raise TPL to TPL_CALLBACK to serialize all its operations\r
d80ed2a7 112 // to protect shared data structures.\r
113 //\r
3cf6450e 114 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
d80ed2a7 115 UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (This);\r
116 Media = &UsbMass->BlockIoMedia;\r
117\r
e237e7ae 118 //\r
41e8ff27 119 // If it is a removable media, such as CD-Rom or Usb-Floppy,\r
d80ed2a7 120 // need to detect the media before each read/write. While some of\r
41e8ff27 121 // Usb-Flash is marked as removable media.\r
1c619535 122 //\r
d80ed2a7 123 if (Media->RemovableMedia) {\r
41e8ff27 124 Status = UsbBootDetectMedia (UsbMass);\r
125 if (EFI_ERROR (Status)) {\r
41e8ff27 126 goto ON_EXIT;\r
1c619535 127 }\r
e237e7ae 128 }\r
1c619535 129\r
fcf5e49d
RN
130 if (!(Media->MediaPresent)) {\r
131 Status = EFI_NO_MEDIA;\r
132 goto ON_EXIT;\r
133 }\r
134\r
135 if (MediaId != Media->MediaId) {\r
136 Status = EFI_MEDIA_CHANGED;\r
137 goto ON_EXIT;\r
138 }\r
139\r
140 if (BufferSize == 0) {\r
141 Status = EFI_SUCCESS;\r
142 goto ON_EXIT;\r
143 }\r
144\r
145 if (Buffer == NULL) {\r
146 Status = EFI_INVALID_PARAMETER;\r
147 goto ON_EXIT;\r
148 }\r
149\r
e237e7ae 150 //\r
d80ed2a7 151 // BufferSize must be a multiple of the intrinsic block size of the device.\r
e237e7ae 152 //\r
153 if ((BufferSize % Media->BlockSize) != 0) {\r
41e8ff27 154 Status = EFI_BAD_BUFFER_SIZE;\r
155 goto ON_EXIT;\r
e237e7ae 156 }\r
157\r
158 TotalBlock = BufferSize / Media->BlockSize;\r
159\r
d80ed2a7 160 //\r
161 // Make sure the range to read is valid.\r
162 //\r
e237e7ae 163 if (Lba + TotalBlock - 1 > Media->LastBlock) {\r
1c619535 164 Status = EFI_INVALID_PARAMETER;\r
165 goto ON_EXIT;\r
166 }\r
167\r
99c1725e 168 if (UsbMass->Cdb16Byte) {\r
e59db6a7 169 Status = UsbBootReadWriteBlocks16 (UsbMass, FALSE, Lba, TotalBlock, Buffer);\r
99c1725e 170 } else {\r
e59db6a7 171 Status = UsbBootReadWriteBlocks (UsbMass, FALSE, (UINT32) Lba, TotalBlock, Buffer);\r
99c1725e 172 }\r
173\r
e237e7ae 174 if (EFI_ERROR (Status)) {\r
1c619535 175 DEBUG ((EFI_D_ERROR, "UsbMassReadBlocks: UsbBootReadBlocks (%r) -> Reset\n", Status));\r
e237e7ae 176 UsbMassReset (This, TRUE);\r
177 }\r
178\r
41e8ff27 179ON_EXIT:\r
180 gBS->RestoreTPL (OldTpl);\r
e237e7ae 181 return Status;\r
182}\r
183\r
184\r
185/**\r
d80ed2a7 186 Writes a specified number of blocks to the device.\r
187\r
d1102dba 188 This function implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks().\r
d80ed2a7 189 It writes a specified number of blocks to the device.\r
190 All blocks are written, or an error is returned.\r
191\r
192 @param This Indicates a pointer to the calling context.\r
193 @param MediaId The media ID that the write request is for.\r
194 @param Lba The starting logical block address to be written.\r
195 @param BufferSize The size of the Buffer in bytes.\r
196 This must be a multiple of the intrinsic block size of the device.\r
197 @param Buffer Pointer to the source buffer for the data.\r
198\r
199 @retval EFI_SUCCESS The data were written correctly to the device.\r
200 @retval EFI_WRITE_PROTECTED The device cannot be written to.\r
201 @retval EFI_NO_MEDIA There is no media in the device.\r
202 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
203 @retval EFI_DEVICE_ERROR The device reported an error while attempting to perform the write operation.\r
204 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the intrinsic\r
205 block size of the device.\r
206 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,\r
207 or the buffer is not on proper alignment.\r
e237e7ae 208\r
209**/\r
210EFI_STATUS\r
1c619535 211EFIAPI\r
e237e7ae 212UsbMassWriteBlocks (\r
213 IN EFI_BLOCK_IO_PROTOCOL *This,\r
214 IN UINT32 MediaId,\r
215 IN EFI_LBA Lba,\r
216 IN UINTN BufferSize,\r
217 IN VOID *Buffer\r
218 )\r
219{\r
220 USB_MASS_DEVICE *UsbMass;\r
221 EFI_BLOCK_IO_MEDIA *Media;\r
222 EFI_STATUS Status;\r
41e8ff27 223 EFI_TPL OldTpl;\r
e237e7ae 224 UINTN TotalBlock;\r
225\r
e237e7ae 226 //\r
b77e1a24 227 // Raise TPL to TPL_CALLBACK to serialize all its operations\r
d80ed2a7 228 // to protect shared data structures.\r
1c619535 229 //\r
3cf6450e 230 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
d80ed2a7 231 UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (This);\r
232 Media = &UsbMass->BlockIoMedia;\r
233\r
234 //\r
235 // If it is a removable media, such as CD-Rom or Usb-Floppy,\r
236 // need to detect the media before each read/write. Some of\r
237 // USB Flash is marked as removable media.\r
1c619535 238 //\r
d80ed2a7 239 if (Media->RemovableMedia) {\r
41e8ff27 240 Status = UsbBootDetectMedia (UsbMass);\r
241 if (EFI_ERROR (Status)) {\r
41e8ff27 242 goto ON_EXIT;\r
1c619535 243 }\r
e237e7ae 244 }\r
1c619535 245\r
fcf5e49d
RN
246 if (!(Media->MediaPresent)) {\r
247 Status = EFI_NO_MEDIA;\r
248 goto ON_EXIT;\r
249 }\r
250\r
251 if (MediaId != Media->MediaId) {\r
252 Status = EFI_MEDIA_CHANGED;\r
253 goto ON_EXIT;\r
254 }\r
255\r
256 if (BufferSize == 0) {\r
257 Status = EFI_SUCCESS;\r
258 goto ON_EXIT;\r
259 }\r
260\r
261 if (Buffer == NULL) {\r
262 Status = EFI_INVALID_PARAMETER;\r
263 goto ON_EXIT;\r
264 }\r
265\r
e237e7ae 266 //\r
d80ed2a7 267 // BufferSize must be a multiple of the intrinsic block size of the device.\r
e237e7ae 268 //\r
269 if ((BufferSize % Media->BlockSize) != 0) {\r
41e8ff27 270 Status = EFI_BAD_BUFFER_SIZE;\r
271 goto ON_EXIT;\r
e237e7ae 272 }\r
273\r
274 TotalBlock = BufferSize / Media->BlockSize;\r
275\r
d80ed2a7 276 //\r
277 // Make sure the range to write is valid.\r
278 //\r
e237e7ae 279 if (Lba + TotalBlock - 1 > Media->LastBlock) {\r
1c619535 280 Status = EFI_INVALID_PARAMETER;\r
41e8ff27 281 goto ON_EXIT;\r
e237e7ae 282 }\r
1c619535 283\r
e237e7ae 284 //\r
285 // Try to write the data even the device is marked as ReadOnly,\r
286 // and clear the status should the write succeed.\r
287 //\r
99c1725e 288 if (UsbMass->Cdb16Byte) {\r
e59db6a7 289 Status = UsbBootReadWriteBlocks16 (UsbMass, TRUE, Lba, TotalBlock, Buffer);\r
99c1725e 290 } else {\r
e59db6a7 291 Status = UsbBootReadWriteBlocks (UsbMass, TRUE, (UINT32) Lba, TotalBlock, Buffer);\r
d1102dba 292 }\r
99c1725e 293\r
e237e7ae 294 if (EFI_ERROR (Status)) {\r
1c619535 295 DEBUG ((EFI_D_ERROR, "UsbMassWriteBlocks: UsbBootWriteBlocks (%r) -> Reset\n", Status));\r
e237e7ae 296 UsbMassReset (This, TRUE);\r
297 }\r
1c619535 298\r
41e8ff27 299ON_EXIT:\r
300 gBS->RestoreTPL (OldTpl);\r
e237e7ae 301 return Status;\r
302}\r
303\r
e237e7ae 304/**\r
d80ed2a7 305 Flushes all modified data to a physical block device.\r
306\r
307 This function implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks().\r
308 USB mass storage device doesn't support write cache,\r
309 so return EFI_SUCCESS directly.\r
e237e7ae 310\r
d80ed2a7 311 @param This Indicates a pointer to the calling context.\r
e237e7ae 312\r
d80ed2a7 313 @retval EFI_SUCCESS All outstanding data were written correctly to the device.\r
314 @retval EFI_DEVICE_ERROR The device reported an error while attempting to write data.\r
315 @retval EFI_NO_MEDIA There is no media in the device.\r
e237e7ae 316\r
317**/\r
318EFI_STATUS\r
1c619535 319EFIAPI\r
e237e7ae 320UsbMassFlushBlocks (\r
321 IN EFI_BLOCK_IO_PROTOCOL *This\r
322 )\r
323{\r
324 return EFI_SUCCESS;\r
325}\r
326\r
c7e39923 327/**\r
d80ed2a7 328 Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol.\r
c7e39923 329\r
330 @param UsbMass The USB mass storage device\r
331\r
d80ed2a7 332 @retval EFI_SUCCESS The media parameters are updated successfully.\r
c7e39923 333 @retval Others Failed to get the media parameters.\r
334\r
335**/\r
336EFI_STATUS\r
337UsbMassInitMedia (\r
338 IN USB_MASS_DEVICE *UsbMass\r
339 )\r
340{\r
341 EFI_BLOCK_IO_MEDIA *Media;\r
342 EFI_STATUS Status;\r
c7e39923 343\r
344 Media = &UsbMass->BlockIoMedia;\r
345\r
346 //\r
d80ed2a7 347 // Fields of EFI_BLOCK_IO_MEDIA are defined in UEFI 2.0 spec,\r
348 // section for Block I/O Protocol.\r
c7e39923 349 //\r
350 Media->MediaPresent = FALSE;\r
351 Media->LogicalPartition = FALSE;\r
352 Media->ReadOnly = FALSE;\r
353 Media->WriteCaching = FALSE;\r
354 Media->IoAlign = 0;\r
355 Media->MediaId = 1;\r
356\r
19bc8527 357 Status = UsbBootGetParams (UsbMass);\r
06e24096
RN
358 DEBUG ((DEBUG_INFO, "UsbMassInitMedia: UsbBootGetParams (%r)\n", Status));\r
359 if (Status == EFI_MEDIA_CHANGED) {\r
360 //\r
361 // Some USB storage devices may report MEDIA_CHANGED sense key when hot-plugged.\r
362 // Treat it as SUCCESS\r
363 //\r
364 Status = EFI_SUCCESS;\r
365 }\r
c7e39923 366 return Status;\r
367}\r
368\r
cc5166ff 369/**\r
d80ed2a7 370 Initilize the USB Mass Storage transport.\r
371\r
372 This function tries to find the matching USB Mass Storage transport\r
373 protocol for USB device. If found, initializes the matching transport.\r
cc5166ff 374\r
375 @param This The USB mass driver's driver binding.\r
376 @param Controller The device to test.\r
377 @param Transport The pointer to pointer to USB_MASS_TRANSPORT.\r
3e03cb4d 378 @param Context The parameter for USB_MASS_DEVICE.Context.\r
cc5166ff 379 @param MaxLun Get the MaxLun if is BOT dev.\r
380\r
d7db0902 381 @retval EFI_SUCCESS The initialization is successful.\r
d80ed2a7 382 @retval EFI_UNSUPPORTED No matching transport protocol is found.\r
d7db0902 383 @retval Others Failed to initialize dev.\r
cc5166ff 384\r
385**/\r
c7e39923 386EFI_STATUS\r
387UsbMassInitTransport (\r
388 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
389 IN EFI_HANDLE Controller,\r
390 OUT USB_MASS_TRANSPORT **Transport,\r
391 OUT VOID **Context,\r
392 OUT UINT8 *MaxLun\r
393 )\r
394{\r
395 EFI_USB_IO_PROTOCOL *UsbIo;\r
396 EFI_USB_INTERFACE_DESCRIPTOR Interface;\r
397 UINT8 Index;\r
398 EFI_STATUS Status;\r
d1102dba 399\r
c7e39923 400 Status = gBS->OpenProtocol (\r
401 Controller,\r
402 &gEfiUsbIoProtocolGuid,\r
b16b8bf9 403 (VOID **) &UsbIo,\r
c7e39923 404 This->DriverBindingHandle,\r
405 Controller,\r
406 EFI_OPEN_PROTOCOL_BY_DRIVER\r
407 );\r
408\r
409 if (EFI_ERROR (Status)) {\r
c7e39923 410 return Status;\r
411 }\r
d1102dba 412\r
c7e39923 413 Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);\r
414 if (EFI_ERROR (Status)) {\r
c7e39923 415 goto ON_EXIT;\r
416 }\r
d1102dba 417\r
c7e39923 418 Status = EFI_UNSUPPORTED;\r
419\r
d80ed2a7 420 //\r
421 // Traverse the USB_MASS_TRANSPORT arrary and try to find the\r
422 // matching transport protocol.\r
423 // If not found, return EFI_UNSUPPORTED.\r
424 // If found, execute USB_MASS_TRANSPORT.Init() to initialize the transport context.\r
425 //\r
db0bd81c 426 for (Index = 0; Index < USB_MASS_TRANSPORT_COUNT; Index++) {\r
c7e39923 427 *Transport = mUsbMassTransport[Index];\r
428\r
429 if (Interface.InterfaceProtocol == (*Transport)->Protocol) {\r
430 Status = (*Transport)->Init (UsbIo, Context);\r
431 break;\r
432 }\r
433 }\r
434\r
435 if (EFI_ERROR (Status)) {\r
c7e39923 436 goto ON_EXIT;\r
437 }\r
438\r
439 //\r
d1102dba 440 // For BOT device, try to get its max LUN.\r
d80ed2a7 441 // If max LUN is 0, then it is a non-lun device.\r
442 // Otherwise, it is a multi-lun device.\r
c7e39923 443 //\r
444 if ((*Transport)->Protocol == USB_MASS_STORE_BOT) {\r
445 (*Transport)->GetMaxLun (*Context, MaxLun);\r
c7e39923 446 }\r
447\r
448ON_EXIT:\r
449 gBS->CloseProtocol (\r
450 Controller,\r
451 &gEfiUsbIoProtocolGuid,\r
452 This->DriverBindingHandle,\r
453 Controller\r
454 );\r
d1102dba 455 return Status;\r
c7e39923 456}\r
457\r
cc5166ff 458/**\r
3e03cb4d 459 Initialize data for device that supports multiple LUNSs.\r
cc5166ff 460\r
3e03cb4d 461 @param This The Driver Binding Protocol instance.\r
462 @param Controller The device to initialize.\r
463 @param Transport Pointer to USB_MASS_TRANSPORT.\r
464 @param Context Parameter for USB_MASS_DEVICE.Context.\r
465 @param DevicePath The remaining device path.\r
466 @param MaxLun The max LUN number.\r
cc5166ff 467\r
3e03cb4d 468 @retval EFI_SUCCESS At least one LUN is initialized successfully.\r
66a5771e 469 @retval EFI_NOT_FOUND Fail to initialize any of multiple LUNs.\r
cc5166ff 470\r
471**/\r
c7e39923 472EFI_STATUS\r
473UsbMassInitMultiLun (\r
3e03cb4d 474 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
c7e39923 475 IN EFI_HANDLE Controller,\r
476 IN USB_MASS_TRANSPORT *Transport,\r
477 IN VOID *Context,\r
478 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
479 IN UINT8 MaxLun\r
480 )\r
481{\r
482 USB_MASS_DEVICE *UsbMass;\r
483 EFI_USB_IO_PROTOCOL *UsbIo;\r
484 DEVICE_LOGICAL_UNIT_DEVICE_PATH LunNode;\r
485 UINT8 Index;\r
486 EFI_STATUS Status;\r
66a5771e 487 EFI_STATUS ReturnStatus;\r
c7e39923 488\r
489 ASSERT (MaxLun > 0);\r
66a5771e 490 ReturnStatus = EFI_NOT_FOUND;\r
c7e39923 491\r
d1102dba 492 for (Index = 0; Index <= MaxLun; Index++) {\r
c7e39923 493\r
494 DEBUG ((EFI_D_INFO, "UsbMassInitMultiLun: Start to initialize No.%d logic unit\n", Index));\r
d1102dba 495\r
c7e39923 496 UsbIo = NULL;\r
497 UsbMass = AllocateZeroPool (sizeof (USB_MASS_DEVICE));\r
3e03cb4d 498 ASSERT (UsbMass != NULL);\r
d1102dba 499\r
c7e39923 500 UsbMass->Signature = USB_MASS_SIGNATURE;\r
501 UsbMass->UsbIo = UsbIo;\r
502 UsbMass->BlockIo.Media = &UsbMass->BlockIoMedia;\r
503 UsbMass->BlockIo.Reset = UsbMassReset;\r
504 UsbMass->BlockIo.ReadBlocks = UsbMassReadBlocks;\r
505 UsbMass->BlockIo.WriteBlocks = UsbMassWriteBlocks;\r
506 UsbMass->BlockIo.FlushBlocks = UsbMassFlushBlocks;\r
507 UsbMass->OpticalStorage = FALSE;\r
508 UsbMass->Transport = Transport;\r
509 UsbMass->Context = Context;\r
510 UsbMass->Lun = Index;\r
d1102dba 511\r
c7e39923 512 //\r
3e03cb4d 513 // Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol.\r
c7e39923 514 //\r
515 Status = UsbMassInitMedia (UsbMass);\r
66a5771e 516 if ((EFI_ERROR (Status)) && (Status != EFI_NO_MEDIA)) {\r
c7e39923 517 DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: UsbMassInitMedia (%r)\n", Status));\r
66a5771e
TF
518 FreePool (UsbMass);\r
519 continue;\r
c7e39923 520 }\r
521\r
522 //\r
3e03cb4d 523 // Create a device path node for device logic unit, and append it.\r
c7e39923 524 //\r
525 LunNode.Header.Type = MESSAGING_DEVICE_PATH;\r
526 LunNode.Header.SubType = MSG_DEVICE_LOGICAL_UNIT_DP;\r
527 LunNode.Lun = UsbMass->Lun;\r
d1102dba 528\r
c7e39923 529 SetDevicePathNodeLength (&LunNode.Header, sizeof (LunNode));\r
d1102dba 530\r
c7e39923 531 UsbMass->DevicePath = AppendDevicePathNode (DevicePath, &LunNode.Header);\r
d1102dba 532\r
c7e39923 533 if (UsbMass->DevicePath == NULL) {\r
534 DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: failed to create device logic unit device path\n"));\r
c7e39923 535 Status = EFI_OUT_OF_RESOURCES;\r
66a5771e
TF
536 FreePool (UsbMass);\r
537 continue;\r
c7e39923 538 }\r
539\r
39840c50 540 InitializeDiskInfo (UsbMass);\r
541\r
c7e39923 542 //\r
3e03cb4d 543 // Create a new handle for each LUN, and install Block I/O Protocol and Device Path Protocol.\r
c7e39923 544 //\r
545 Status = gBS->InstallMultipleProtocolInterfaces (\r
546 &UsbMass->Controller,\r
547 &gEfiDevicePathProtocolGuid,\r
548 UsbMass->DevicePath,\r
549 &gEfiBlockIoProtocolGuid,\r
550 &UsbMass->BlockIo,\r
39840c50 551 &gEfiDiskInfoProtocolGuid,\r
552 &UsbMass->DiskInfo,\r
c7e39923 553 NULL\r
554 );\r
d1102dba 555\r
c7e39923 556 if (EFI_ERROR (Status)) {\r
557 DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: InstallMultipleProtocolInterfaces (%r)\n", Status));\r
66a5771e
TF
558 FreePool (UsbMass->DevicePath);\r
559 FreePool (UsbMass);\r
560 continue;\r
c7e39923 561 }\r
562\r
563 //\r
3e03cb4d 564 // Open USB I/O Protocol by child to setup a parent-child relationship.\r
c7e39923 565 //\r
566 Status = gBS->OpenProtocol (\r
567 Controller,\r
568 &gEfiUsbIoProtocolGuid,\r
b16b8bf9 569 (VOID **) &UsbIo,\r
c7e39923 570 This->DriverBindingHandle,\r
571 UsbMass->Controller,\r
572 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
573 );\r
574\r
575 if (EFI_ERROR (Status)) {\r
576 DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: OpenUsbIoProtocol By Child (%r)\n", Status));\r
577 gBS->UninstallMultipleProtocolInterfaces (\r
578 &UsbMass->Controller,\r
579 &gEfiDevicePathProtocolGuid,\r
580 UsbMass->DevicePath,\r
581 &gEfiBlockIoProtocolGuid,\r
582 &UsbMass->BlockIo,\r
39840c50 583 &gEfiDiskInfoProtocolGuid,\r
584 &UsbMass->DiskInfo,\r
c7e39923 585 NULL\r
586 );\r
66a5771e
TF
587 FreePool (UsbMass->DevicePath);\r
588 FreePool (UsbMass);\r
589 continue;\r
c7e39923 590 }\r
66a5771e 591 ReturnStatus = EFI_SUCCESS;\r
c7e39923 592 DEBUG ((EFI_D_INFO, "UsbMassInitMultiLun: Success to initialize No.%d logic unit\n", Index));\r
593 }\r
d1102dba 594\r
66a5771e 595 return ReturnStatus;\r
c7e39923 596}\r
597\r
cc5166ff 598/**\r
3e03cb4d 599 Initialize data for device that does not support multiple LUNSs.\r
cc5166ff 600\r
3e03cb4d 601 @param This The Driver Binding Protocol instance.\r
602 @param Controller The device to initialize.\r
603 @param Transport Pointer to USB_MASS_TRANSPORT.\r
604 @param Context Parameter for USB_MASS_DEVICE.Context.\r
cc5166ff 605\r
3e03cb4d 606 @retval EFI_SUCCESS Initialization succeeds.\r
cc5166ff 607 @retval Other Initialization fails.\r
608\r
609**/\r
c7e39923 610EFI_STATUS\r
611UsbMassInitNonLun (\r
612 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
613 IN EFI_HANDLE Controller,\r
614 IN USB_MASS_TRANSPORT *Transport,\r
615 IN VOID *Context\r
616 )\r
617{\r
618 USB_MASS_DEVICE *UsbMass;\r
619 EFI_USB_IO_PROTOCOL *UsbIo;\r
620 EFI_STATUS Status;\r
621\r
622 UsbIo = NULL;\r
623 UsbMass = AllocateZeroPool (sizeof (USB_MASS_DEVICE));\r
3e03cb4d 624 ASSERT (UsbMass != NULL);\r
625\r
c7e39923 626 Status = gBS->OpenProtocol (\r
627 Controller,\r
628 &gEfiUsbIoProtocolGuid,\r
b16b8bf9 629 (VOID **) &UsbIo,\r
c7e39923 630 This->DriverBindingHandle,\r
631 Controller,\r
632 EFI_OPEN_PROTOCOL_BY_DRIVER\r
633 );\r
634\r
635 if (EFI_ERROR (Status)) {\r
636 DEBUG ((EFI_D_ERROR, "UsbMassInitNonLun: OpenUsbIoProtocol By Driver (%r)\n", Status));\r
637 goto ON_ERROR;\r
638 }\r
d1102dba 639\r
c7e39923 640 UsbMass->Signature = USB_MASS_SIGNATURE;\r
641 UsbMass->Controller = Controller;\r
642 UsbMass->UsbIo = UsbIo;\r
643 UsbMass->BlockIo.Media = &UsbMass->BlockIoMedia;\r
644 UsbMass->BlockIo.Reset = UsbMassReset;\r
645 UsbMass->BlockIo.ReadBlocks = UsbMassReadBlocks;\r
646 UsbMass->BlockIo.WriteBlocks = UsbMassWriteBlocks;\r
647 UsbMass->BlockIo.FlushBlocks = UsbMassFlushBlocks;\r
648 UsbMass->OpticalStorage = FALSE;\r
649 UsbMass->Transport = Transport;\r
650 UsbMass->Context = Context;\r
d1102dba 651\r
c7e39923 652 //\r
3e03cb4d 653 // Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol.\r
c7e39923 654 //\r
655 Status = UsbMassInitMedia (UsbMass);\r
66a5771e 656 if ((EFI_ERROR (Status)) && (Status != EFI_NO_MEDIA)) {\r
c7e39923 657 DEBUG ((EFI_D_ERROR, "UsbMassInitNonLun: UsbMassInitMedia (%r)\n", Status));\r
658 goto ON_ERROR;\r
659 }\r
d1102dba 660\r
39840c50 661 InitializeDiskInfo (UsbMass);\r
662\r
663 Status = gBS->InstallMultipleProtocolInterfaces (\r
c7e39923 664 &Controller,\r
665 &gEfiBlockIoProtocolGuid,\r
39840c50 666 &UsbMass->BlockIo,\r
667 &gEfiDiskInfoProtocolGuid,\r
668 &UsbMass->DiskInfo,\r
669 NULL\r
c7e39923 670 );\r
671 if (EFI_ERROR (Status)) {\r
672 goto ON_ERROR;\r
673 }\r
674\r
675 return EFI_SUCCESS;\r
676\r
677ON_ERROR:\r
678 if (UsbMass != NULL) {\r
3e03cb4d 679 FreePool (UsbMass);\r
c7e39923 680 }\r
73f8ef8c 681 if (UsbIo != NULL) {\r
682 gBS->CloseProtocol (\r
683 Controller,\r
684 &gEfiUsbIoProtocolGuid,\r
685 This->DriverBindingHandle,\r
686 Controller\r
687 );\r
688 }\r
d1102dba 689 return Status;\r
c7e39923 690}\r
691\r
e237e7ae 692\r
693/**\r
694 Check whether the controller is a supported USB mass storage.\r
695\r
d80ed2a7 696 @param This The USB mass storage driver binding protocol.\r
697 @param Controller The controller handle to check.\r
698 @param RemainingDevicePath The remaining device path.\r
e237e7ae 699\r
d80ed2a7 700 @retval EFI_SUCCESS The driver supports this controller.\r
701 @retval other This device isn't supported.\r
e237e7ae 702\r
703**/\r
704EFI_STATUS\r
705EFIAPI\r
706USBMassDriverBindingSupported (\r
707 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
708 IN EFI_HANDLE Controller,\r
709 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
710 )\r
711{\r
712 EFI_USB_IO_PROTOCOL *UsbIo;\r
713 EFI_USB_INTERFACE_DESCRIPTOR Interface;\r
714 USB_MASS_TRANSPORT *Transport;\r
715 EFI_STATUS Status;\r
d80ed2a7 716 UINTN Index;\r
e237e7ae 717\r
e237e7ae 718 Status = gBS->OpenProtocol (\r
719 Controller,\r
720 &gEfiUsbIoProtocolGuid,\r
c52fa98c 721 (VOID **) &UsbIo,\r
e237e7ae 722 This->DriverBindingHandle,\r
723 Controller,\r
724 EFI_OPEN_PROTOCOL_BY_DRIVER\r
725 );\r
726 if (EFI_ERROR (Status)) {\r
727 return Status;\r
728 }\r
729\r
730 //\r
d80ed2a7 731 // Get the interface descriptor to check the USB class and find a transport\r
e237e7ae 732 // protocol handler.\r
733 //\r
734 Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);\r
735 if (EFI_ERROR (Status)) {\r
736 goto ON_EXIT;\r
737 }\r
738\r
739 Status = EFI_UNSUPPORTED;\r
740\r
741 if (Interface.InterfaceClass != USB_MASS_STORE_CLASS) {\r
742 goto ON_EXIT;\r
743 }\r
744\r
d80ed2a7 745 //\r
746 // Traverse the USB_MASS_TRANSPORT arrary and try to find the\r
747 // matching transport method.\r
748 // If not found, return EFI_UNSUPPORTED.\r
749 // If found, execute USB_MASS_TRANSPORT.Init() to initialize the transport context.\r
750 //\r
db0bd81c 751 for (Index = 0; Index < USB_MASS_TRANSPORT_COUNT; Index++) {\r
e237e7ae 752 Transport = mUsbMassTransport[Index];\r
753 if (Interface.InterfaceProtocol == Transport->Protocol) {\r
c7e39923 754 Status = Transport->Init (UsbIo, NULL);\r
e237e7ae 755 break;\r
756 }\r
757 }\r
758\r
e237e7ae 759ON_EXIT:\r
760 gBS->CloseProtocol (\r
d80ed2a7 761 Controller,\r
762 &gEfiUsbIoProtocolGuid,\r
763 This->DriverBindingHandle,\r
764 Controller\r
765 );\r
e237e7ae 766\r
767 return Status;\r
768}\r
769\r
e237e7ae 770/**\r
d80ed2a7 771 Starts the USB mass storage device with this driver.\r
e237e7ae 772\r
d80ed2a7 773 This function consumes USB I/O Portocol, intializes USB mass storage device,\r
774 installs Block I/O Protocol, and submits Asynchronous Interrupt\r
775 Transfer to manage the USB mass storage device.\r
776\r
3e03cb4d 777 @param This The USB mass storage driver binding protocol.\r
778 @param Controller The USB mass storage device to start on\r
779 @param RemainingDevicePath The remaining device path.\r
e237e7ae 780\r
d80ed2a7 781 @retval EFI_SUCCESS This driver supports this device.\r
782 @retval EFI_UNSUPPORTED This driver does not support this device.\r
783 @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.\r
784 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.\r
785 @retval EFI_ALREADY_STARTED This driver has been started.\r
e237e7ae 786\r
787**/\r
788EFI_STATUS\r
789EFIAPI\r
790USBMassDriverBindingStart (\r
791 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
792 IN EFI_HANDLE Controller,\r
793 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
794 )\r
795{\r
e237e7ae 796 USB_MASS_TRANSPORT *Transport;\r
c7e39923 797 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
798 VOID *Context;\r
799 UINT8 MaxLun;\r
e237e7ae 800 EFI_STATUS Status;\r
d1102dba 801 EFI_USB_IO_PROTOCOL *UsbIo;\r
15cc67e6 802 EFI_TPL OldTpl;\r
803\r
804 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
805\r
c7e39923 806 Transport = NULL;\r
807 Context = NULL;\r
808 MaxLun = 0;\r
e237e7ae 809\r
c7e39923 810 Status = UsbMassInitTransport (This, Controller, &Transport, &Context, &MaxLun);\r
e237e7ae 811\r
812 if (EFI_ERROR (Status)) {\r
c7e39923 813 DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: UsbMassInitTransport (%r)\n", Status));\r
15cc67e6 814 goto Exit;\r
e237e7ae 815 }\r
c7e39923 816 if (MaxLun == 0) {\r
817 //\r
3e03cb4d 818 // Initialize data for device that does not support multiple LUNSs.\r
c7e39923 819 //\r
3e03cb4d 820 Status = UsbMassInitNonLun (This, Controller, Transport, Context);\r
d1102dba 821 if (EFI_ERROR (Status)) {\r
c7e39923 822 DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: UsbMassInitNonLun (%r)\n", Status));\r
823 }\r
824 } else {\r
825 //\r
3e03cb4d 826 // Open device path to prepare for appending Device Logic Unit node.\r
c7e39923 827 //\r
828 Status = gBS->OpenProtocol (\r
829 Controller,\r
830 &gEfiDevicePathProtocolGuid,\r
831 (VOID **) &DevicePath,\r
832 This->DriverBindingHandle,\r
833 Controller,\r
834 EFI_OPEN_PROTOCOL_BY_DRIVER\r
835 );\r
d1102dba 836\r
c7e39923 837 if (EFI_ERROR (Status)) {\r
838 DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: OpenDevicePathProtocol By Driver (%r)\n", Status));\r
15cc67e6 839 goto Exit;\r
e237e7ae 840 }\r
e237e7ae 841\r
73f8ef8c 842 Status = gBS->OpenProtocol (\r
843 Controller,\r
844 &gEfiUsbIoProtocolGuid,\r
845 (VOID **) &UsbIo,\r
846 This->DriverBindingHandle,\r
847 Controller,\r
848 EFI_OPEN_PROTOCOL_BY_DRIVER\r
849 );\r
d1102dba 850\r
73f8ef8c 851 if (EFI_ERROR (Status)) {\r
852 DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: OpenUsbIoProtocol By Driver (%r)\n", Status));\r
853 gBS->CloseProtocol (\r
854 Controller,\r
855 &gEfiDevicePathProtocolGuid,\r
856 This->DriverBindingHandle,\r
857 Controller\r
858 );\r
15cc67e6 859 goto Exit;\r
73f8ef8c 860 }\r
861\r
c7e39923 862 //\r
66a5771e 863 // Initialize data for device that supports multiple LUNs.\r
3e03cb4d 864 // EFI_SUCCESS is returned if at least 1 LUN is initialized successfully.\r
c7e39923 865 //\r
d80ed2a7 866 Status = UsbMassInitMultiLun (This, Controller, Transport, Context, DevicePath, MaxLun);\r
c7e39923 867 if (EFI_ERROR (Status)) {\r
73f8ef8c 868 gBS->CloseProtocol (\r
869 Controller,\r
870 &gEfiDevicePathProtocolGuid,\r
871 This->DriverBindingHandle,\r
872 Controller\r
873 );\r
874 gBS->CloseProtocol (\r
875 Controller,\r
876 &gEfiUsbIoProtocolGuid,\r
877 This->DriverBindingHandle,\r
878 Controller\r
879 );\r
c7e39923 880 DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: UsbMassInitMultiLun (%r) with Maxlun=%d\n", Status, MaxLun));\r
881 }\r
e237e7ae 882 }\r
15cc67e6 883Exit:\r
884 gBS->RestoreTPL (OldTpl);\r
e237e7ae 885 return Status;\r
886}\r
887\r
888\r
889/**\r
890 Stop controlling the device.\r
891\r
892 @param This The USB mass storage driver binding\r
893 @param Controller The device controller controlled by the driver.\r
894 @param NumberOfChildren The number of children of this device\r
895 @param ChildHandleBuffer The buffer of children handle.\r
896\r
897 @retval EFI_SUCCESS The driver stopped from controlling the device.\r
3e03cb4d 898 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
899 @retval EFI_UNSUPPORTED Block I/O Protocol is not installed on Controller.\r
e237e7ae 900 @retval Others Failed to stop the driver\r
901\r
902**/\r
903EFI_STATUS\r
904EFIAPI\r
905USBMassDriverBindingStop (\r
906 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
907 IN EFI_HANDLE Controller,\r
908 IN UINTN NumberOfChildren,\r
909 IN EFI_HANDLE *ChildHandleBuffer\r
910 )\r
911{\r
912 EFI_STATUS Status;\r
913 USB_MASS_DEVICE *UsbMass;\r
3e03cb4d 914 EFI_USB_IO_PROTOCOL *UsbIo;\r
e237e7ae 915 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
3e03cb4d 916 UINTN Index;\r
917 BOOLEAN AllChildrenStopped;\r
c7e39923 918\r
919 //\r
3e03cb4d 920 // This is a bus driver stop function since multi-lun is supported.\r
921 // There are three kinds of device handles that might be passed:\r
73f8ef8c 922 // 1st is a handle with USB I/O & Block I/O installed (non-multi-lun)\r
3e03cb4d 923 // 2nd is a handle with Device Path & USB I/O installed (multi-lun root)\r
73f8ef8c 924 // 3rd is a handle with Device Path & USB I/O & Block I/O installed (multi-lun).\r
c7e39923 925 //\r
926 if (NumberOfChildren == 0) {\r
927 //\r
928 // A handle without any children, might be 1st and 2nd type.\r
929 //\r
930 Status = gBS->OpenProtocol (\r
931 Controller,\r
932 &gEfiBlockIoProtocolGuid,\r
b16b8bf9 933 (VOID **) &BlockIo,\r
c7e39923 934 This->DriverBindingHandle,\r
935 Controller,\r
936 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
937 );\r
d1102dba 938\r
c7e39923 939 if (EFI_ERROR(Status)) {\r
940 //\r
73f8ef8c 941 // This is a 2nd type handle(multi-lun root), it needs to close devicepath\r
942 // and usbio protocol.\r
c7e39923 943 //\r
944 gBS->CloseProtocol (\r
945 Controller,\r
946 &gEfiDevicePathProtocolGuid,\r
947 This->DriverBindingHandle,\r
948 Controller\r
949 );\r
73f8ef8c 950 gBS->CloseProtocol (\r
951 Controller,\r
952 &gEfiUsbIoProtocolGuid,\r
953 This->DriverBindingHandle,\r
954 Controller\r
955 );\r
c7e39923 956 DEBUG ((EFI_D_INFO, "Success to stop multi-lun root handle\n"));\r
957 return EFI_SUCCESS;\r
958 }\r
d1102dba 959\r
c7e39923 960 //\r
3e03cb4d 961 // This is a 1st type handle(non-multi-lun), which only needs to uninstall\r
962 // Block I/O Protocol, close USB I/O Protocol and free mass device.\r
c7e39923 963 //\r
d80ed2a7 964 UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (BlockIo);\r
d1102dba 965\r
c7e39923 966 //\r
967 // Uninstall Block I/O protocol from the device handle,\r
968 // then call the transport protocol to stop itself.\r
969 //\r
39840c50 970 Status = gBS->UninstallMultipleProtocolInterfaces (\r
c7e39923 971 Controller,\r
972 &gEfiBlockIoProtocolGuid,\r
39840c50 973 &UsbMass->BlockIo,\r
974 &gEfiDiskInfoProtocolGuid,\r
975 &UsbMass->DiskInfo,\r
976 NULL\r
c7e39923 977 );\r
978 if (EFI_ERROR (Status)) {\r
979 return Status;\r
980 }\r
d1102dba 981\r
c7e39923 982 gBS->CloseProtocol (\r
983 Controller,\r
984 &gEfiUsbIoProtocolGuid,\r
985 This->DriverBindingHandle,\r
986 Controller\r
987 );\r
d1102dba 988\r
d80ed2a7 989 UsbMass->Transport->CleanUp (UsbMass->Context);\r
3e03cb4d 990 FreePool (UsbMass);\r
d1102dba 991\r
c7e39923 992 DEBUG ((EFI_D_INFO, "Success to stop non-multi-lun root handle\n"));\r
993 return EFI_SUCCESS;\r
d1102dba 994 }\r
c7e39923 995\r
996 //\r
997 // This is a 3rd type handle(multi-lun), which needs uninstall\r
d1102dba 998 // Block I/O Protocol and Device Path Protocol, close USB I/O Protocol and\r
3e03cb4d 999 // free mass device for all children.\r
c7e39923 1000 //\r
1001 AllChildrenStopped = TRUE;\r
1002\r
1003 for (Index = 0; Index < NumberOfChildren; Index++) {\r
1004\r
1005 Status = gBS->OpenProtocol (\r
1006 ChildHandleBuffer[Index],\r
1007 &gEfiBlockIoProtocolGuid,\r
1008 (VOID **) &BlockIo,\r
1009 This->DriverBindingHandle,\r
1010 Controller,\r
1011 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1012 );\r
1013 if (EFI_ERROR (Status)) {\r
1014 AllChildrenStopped = FALSE;\r
7df7393f 1015 DEBUG ((EFI_D_ERROR, "Fail to stop No.%d multi-lun child handle when opening blockio\n", (UINT32)Index));\r
c7e39923 1016 continue;\r
1017 }\r
e237e7ae 1018\r
d80ed2a7 1019 UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (BlockIo);\r
c7e39923 1020\r
1021 gBS->CloseProtocol (\r
3e03cb4d 1022 Controller,\r
1023 &gEfiUsbIoProtocolGuid,\r
1024 This->DriverBindingHandle,\r
1025 ChildHandleBuffer[Index]\r
1026 );\r
d1102dba 1027\r
c7e39923 1028 Status = gBS->UninstallMultipleProtocolInterfaces (\r
1029 ChildHandleBuffer[Index],\r
1030 &gEfiDevicePathProtocolGuid,\r
1031 UsbMass->DevicePath,\r
1032 &gEfiBlockIoProtocolGuid,\r
1033 &UsbMass->BlockIo,\r
39840c50 1034 &gEfiDiskInfoProtocolGuid,\r
1035 &UsbMass->DiskInfo,\r
c7e39923 1036 NULL\r
1037 );\r
d1102dba 1038\r
c7e39923 1039 if (EFI_ERROR (Status)) {\r
1040 //\r
3e03cb4d 1041 // Fail to uninstall Block I/O Protocol and Device Path Protocol, so re-open USB I/O Protocol by child.\r
c7e39923 1042 //\r
1043 AllChildrenStopped = FALSE;\r
7df7393f 1044 DEBUG ((EFI_D_ERROR, "Fail to stop No.%d multi-lun child handle when uninstalling blockio and devicepath\n", (UINT32)Index));\r
d1102dba 1045\r
c7e39923 1046 gBS->OpenProtocol (\r
1047 Controller,\r
1048 &gEfiUsbIoProtocolGuid,\r
b16b8bf9 1049 (VOID **) &UsbIo,\r
c7e39923 1050 This->DriverBindingHandle,\r
1051 ChildHandleBuffer[Index],\r
1052 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
1053 );\r
1054 } else {\r
1055 //\r
3e03cb4d 1056 // Succeed to stop this multi-lun handle, so go on with next child.\r
c7e39923 1057 //\r
1058 if (((Index + 1) == NumberOfChildren) && AllChildrenStopped) {\r
d80ed2a7 1059 UsbMass->Transport->CleanUp (UsbMass->Context);\r
c7e39923 1060 }\r
3e03cb4d 1061 FreePool (UsbMass);\r
c7e39923 1062 }\r
e237e7ae 1063 }\r
1064\r
c7e39923 1065 if (!AllChildrenStopped) {\r
1066 return EFI_DEVICE_ERROR;\r
e237e7ae 1067 }\r
d1102dba 1068\r
3e03cb4d 1069 DEBUG ((EFI_D_INFO, "Success to stop all %d multi-lun children handles\n", (UINT32) NumberOfChildren));\r
e237e7ae 1070 return EFI_SUCCESS;\r
1071}\r
1072\r
cc5166ff 1073/**\r
3e03cb4d 1074 Entrypoint of USB Mass Storage Driver.\r
1075\r
1076 This function is the entrypoint of USB Mass Storage Driver. It installs Driver Binding\r
1077 Protocol together with Component Name Protocols.\r
cc5166ff 1078\r
3e03cb4d 1079 @param ImageHandle The firmware allocated handle for the EFI image.\r
1080 @param SystemTable A pointer to the EFI System Table.\r
cc5166ff 1081\r
3e03cb4d 1082 @retval EFI_SUCCESS The entry point is executed successfully.\r
cc5166ff 1083\r
1084**/\r
e237e7ae 1085EFI_STATUS\r
1086EFIAPI\r
1087USBMassStorageEntryPoint (\r
1088 IN EFI_HANDLE ImageHandle,\r
1089 IN EFI_SYSTEM_TABLE *SystemTable\r
1090 )\r
e237e7ae 1091{\r
1092 EFI_STATUS Status;\r
1093\r
1094 //\r
1095 // Install driver binding protocol\r
1096 //\r
62b9bb55 1097 Status = EfiLibInstallDriverBindingComponentName2 (\r
e237e7ae 1098 ImageHandle,\r
1099 SystemTable,\r
1100 &gUSBMassDriverBinding,\r
1101 ImageHandle,\r
1102 &gUsbMassStorageComponentName,\r
62b9bb55 1103 &gUsbMassStorageComponentName2\r
e237e7ae 1104 );\r
d80ed2a7 1105 ASSERT_EFI_ERROR (Status);\r
e237e7ae 1106\r
d80ed2a7 1107 return EFI_SUCCESS;\r
e237e7ae 1108}\r