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