]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.c
MdeModulePkg: Apply uncrustify changes
[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
1436aea4 11#define USB_MASS_TRANSPORT_COUNT 3\r
d80ed2a7 12//\r
d1102dba 13// Array of USB transport interfaces.\r
d80ed2a7 14//\r
1436aea4 15USB_MASS_TRANSPORT *mUsbMassTransport[USB_MASS_TRANSPORT_COUNT] = {\r
e237e7ae 16 &mUsbCbi0Transport,\r
17 &mUsbCbi1Transport,\r
18 &mUsbBotTransport,\r
e237e7ae 19};\r
20\r
1436aea4 21EFI_DRIVER_BINDING_PROTOCOL gUSBMassDriverBinding = {\r
d80ed2a7 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
1436aea4
MK
48 IN EFI_BLOCK_IO_PROTOCOL *This,\r
49 IN BOOLEAN ExtendedVerification\r
e237e7ae 50 )\r
51{\r
1436aea4
MK
52 USB_MASS_DEVICE *UsbMass;\r
53 EFI_TPL OldTpl;\r
54 EFI_STATUS Status;\r
41e8ff27 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
1436aea4 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
1436aea4
MK
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
e237e7ae 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
1436aea4 171 Status = UsbBootReadWriteBlocks (UsbMass, FALSE, (UINT32)Lba, TotalBlock, Buffer);\r
99c1725e 172 }\r
173\r
e237e7ae 174 if (EFI_ERROR (Status)) {\r
87000d77 175 DEBUG ((DEBUG_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
e237e7ae 184/**\r
d80ed2a7 185 Writes a specified number of blocks to the device.\r
186\r
d1102dba 187 This function implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks().\r
d80ed2a7 188 It writes a specified number of blocks to the device.\r
189 All blocks are written, or an error is returned.\r
190\r
191 @param This Indicates a pointer to the calling context.\r
192 @param MediaId The media ID that the write request is for.\r
193 @param Lba The starting logical block address to be written.\r
194 @param BufferSize The size of the Buffer in bytes.\r
195 This must be a multiple of the intrinsic block size of the device.\r
196 @param Buffer Pointer to the source buffer for the data.\r
197\r
198 @retval EFI_SUCCESS The data were written correctly to the device.\r
199 @retval EFI_WRITE_PROTECTED The device cannot be written to.\r
200 @retval EFI_NO_MEDIA There is no media in the device.\r
201 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
202 @retval EFI_DEVICE_ERROR The device reported an error while attempting to perform the write operation.\r
203 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the intrinsic\r
204 block size of the device.\r
205 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,\r
206 or the buffer is not on proper alignment.\r
e237e7ae 207\r
208**/\r
209EFI_STATUS\r
1c619535 210EFIAPI\r
e237e7ae 211UsbMassWriteBlocks (\r
1436aea4
MK
212 IN EFI_BLOCK_IO_PROTOCOL *This,\r
213 IN UINT32 MediaId,\r
214 IN EFI_LBA Lba,\r
215 IN UINTN BufferSize,\r
216 IN VOID *Buffer\r
e237e7ae 217 )\r
218{\r
219 USB_MASS_DEVICE *UsbMass;\r
220 EFI_BLOCK_IO_MEDIA *Media;\r
221 EFI_STATUS Status;\r
41e8ff27 222 EFI_TPL OldTpl;\r
e237e7ae 223 UINTN TotalBlock;\r
224\r
e237e7ae 225 //\r
b77e1a24 226 // Raise TPL to TPL_CALLBACK to serialize all its operations\r
d80ed2a7 227 // to protect shared data structures.\r
1c619535 228 //\r
3cf6450e 229 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
d80ed2a7 230 UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (This);\r
231 Media = &UsbMass->BlockIoMedia;\r
232\r
233 //\r
234 // If it is a removable media, such as CD-Rom or Usb-Floppy,\r
235 // need to detect the media before each read/write. Some of\r
236 // USB Flash is marked as removable media.\r
1c619535 237 //\r
d80ed2a7 238 if (Media->RemovableMedia) {\r
41e8ff27 239 Status = UsbBootDetectMedia (UsbMass);\r
240 if (EFI_ERROR (Status)) {\r
41e8ff27 241 goto ON_EXIT;\r
1c619535 242 }\r
e237e7ae 243 }\r
1c619535 244\r
fcf5e49d
RN
245 if (!(Media->MediaPresent)) {\r
246 Status = EFI_NO_MEDIA;\r
247 goto ON_EXIT;\r
248 }\r
249\r
250 if (MediaId != Media->MediaId) {\r
251 Status = EFI_MEDIA_CHANGED;\r
252 goto ON_EXIT;\r
253 }\r
254\r
255 if (BufferSize == 0) {\r
256 Status = EFI_SUCCESS;\r
257 goto ON_EXIT;\r
258 }\r
259\r
260 if (Buffer == NULL) {\r
261 Status = EFI_INVALID_PARAMETER;\r
262 goto ON_EXIT;\r
263 }\r
264\r
e237e7ae 265 //\r
d80ed2a7 266 // BufferSize must be a multiple of the intrinsic block size of the device.\r
e237e7ae 267 //\r
268 if ((BufferSize % Media->BlockSize) != 0) {\r
41e8ff27 269 Status = EFI_BAD_BUFFER_SIZE;\r
270 goto ON_EXIT;\r
e237e7ae 271 }\r
272\r
273 TotalBlock = BufferSize / Media->BlockSize;\r
274\r
d80ed2a7 275 //\r
276 // Make sure the range to write is valid.\r
277 //\r
e237e7ae 278 if (Lba + TotalBlock - 1 > Media->LastBlock) {\r
1c619535 279 Status = EFI_INVALID_PARAMETER;\r
41e8ff27 280 goto ON_EXIT;\r
e237e7ae 281 }\r
1c619535 282\r
e237e7ae 283 //\r
284 // Try to write the data even the device is marked as ReadOnly,\r
285 // and clear the status should the write succeed.\r
286 //\r
99c1725e 287 if (UsbMass->Cdb16Byte) {\r
e59db6a7 288 Status = UsbBootReadWriteBlocks16 (UsbMass, TRUE, Lba, TotalBlock, Buffer);\r
99c1725e 289 } else {\r
1436aea4 290 Status = UsbBootReadWriteBlocks (UsbMass, TRUE, (UINT32)Lba, TotalBlock, Buffer);\r
d1102dba 291 }\r
99c1725e 292\r
e237e7ae 293 if (EFI_ERROR (Status)) {\r
87000d77 294 DEBUG ((DEBUG_ERROR, "UsbMassWriteBlocks: UsbBootWriteBlocks (%r) -> Reset\n", Status));\r
e237e7ae 295 UsbMassReset (This, TRUE);\r
296 }\r
1c619535 297\r
41e8ff27 298ON_EXIT:\r
299 gBS->RestoreTPL (OldTpl);\r
e237e7ae 300 return Status;\r
301}\r
302\r
e237e7ae 303/**\r
d80ed2a7 304 Flushes all modified data to a physical block device.\r
305\r
306 This function implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks().\r
307 USB mass storage device doesn't support write cache,\r
308 so return EFI_SUCCESS directly.\r
e237e7ae 309\r
d80ed2a7 310 @param This Indicates a pointer to the calling context.\r
e237e7ae 311\r
d80ed2a7 312 @retval EFI_SUCCESS All outstanding data were written correctly to the device.\r
313 @retval EFI_DEVICE_ERROR The device reported an error while attempting to write data.\r
314 @retval EFI_NO_MEDIA There is no media in the device.\r
e237e7ae 315\r
316**/\r
317EFI_STATUS\r
1c619535 318EFIAPI\r
e237e7ae 319UsbMassFlushBlocks (\r
320 IN EFI_BLOCK_IO_PROTOCOL *This\r
321 )\r
322{\r
323 return EFI_SUCCESS;\r
324}\r
325\r
c7e39923 326/**\r
d80ed2a7 327 Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol.\r
c7e39923 328\r
329 @param UsbMass The USB mass storage device\r
330\r
d80ed2a7 331 @retval EFI_SUCCESS The media parameters are updated successfully.\r
c7e39923 332 @retval Others Failed to get the media parameters.\r
333\r
334**/\r
335EFI_STATUS\r
336UsbMassInitMedia (\r
1436aea4 337 IN USB_MASS_DEVICE *UsbMass\r
c7e39923 338 )\r
339{\r
1436aea4
MK
340 EFI_BLOCK_IO_MEDIA *Media;\r
341 EFI_STATUS Status;\r
c7e39923 342\r
343 Media = &UsbMass->BlockIoMedia;\r
344\r
345 //\r
d80ed2a7 346 // Fields of EFI_BLOCK_IO_MEDIA are defined in UEFI 2.0 spec,\r
347 // section for Block I/O Protocol.\r
c7e39923 348 //\r
349 Media->MediaPresent = FALSE;\r
350 Media->LogicalPartition = FALSE;\r
351 Media->ReadOnly = FALSE;\r
352 Media->WriteCaching = FALSE;\r
353 Media->IoAlign = 0;\r
354 Media->MediaId = 1;\r
355\r
19bc8527 356 Status = UsbBootGetParams (UsbMass);\r
06e24096
RN
357 DEBUG ((DEBUG_INFO, "UsbMassInitMedia: UsbBootGetParams (%r)\n", Status));\r
358 if (Status == EFI_MEDIA_CHANGED) {\r
359 //\r
360 // Some USB storage devices may report MEDIA_CHANGED sense key when hot-plugged.\r
361 // Treat it as SUCCESS\r
362 //\r
363 Status = EFI_SUCCESS;\r
364 }\r
1436aea4 365\r
c7e39923 366 return Status;\r
367}\r
368\r
cc5166ff 369/**\r
957ca631 370 Initialize the USB Mass Storage transport.\r
d80ed2a7 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
1436aea4 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
1436aea4 430 Status = (*Transport)->Init (UsbIo, Context);\r
c7e39923 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
1436aea4
MK
474 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
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
c7e39923 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
87000d77 493 DEBUG ((DEBUG_INFO, "UsbMassInitMultiLun: Start to initialize No.%d logic unit\n", Index));\r
d1102dba 494\r
c7e39923 495 UsbIo = NULL;\r
496 UsbMass = AllocateZeroPool (sizeof (USB_MASS_DEVICE));\r
3e03cb4d 497 ASSERT (UsbMass != NULL);\r
d1102dba 498\r
1436aea4
MK
499 UsbMass->Signature = USB_MASS_SIGNATURE;\r
500 UsbMass->UsbIo = UsbIo;\r
501 UsbMass->BlockIo.Media = &UsbMass->BlockIoMedia;\r
502 UsbMass->BlockIo.Reset = UsbMassReset;\r
503 UsbMass->BlockIo.ReadBlocks = UsbMassReadBlocks;\r
504 UsbMass->BlockIo.WriteBlocks = UsbMassWriteBlocks;\r
505 UsbMass->BlockIo.FlushBlocks = UsbMassFlushBlocks;\r
506 UsbMass->OpticalStorage = FALSE;\r
507 UsbMass->Transport = Transport;\r
508 UsbMass->Context = Context;\r
509 UsbMass->Lun = Index;\r
d1102dba 510\r
c7e39923 511 //\r
3e03cb4d 512 // Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol.\r
c7e39923 513 //\r
514 Status = UsbMassInitMedia (UsbMass);\r
66a5771e 515 if ((EFI_ERROR (Status)) && (Status != EFI_NO_MEDIA)) {\r
87000d77 516 DEBUG ((DEBUG_ERROR, "UsbMassInitMultiLun: UsbMassInitMedia (%r)\n", Status));\r
66a5771e
TF
517 FreePool (UsbMass);\r
518 continue;\r
c7e39923 519 }\r
520\r
521 //\r
3e03cb4d 522 // Create a device path node for device logic unit, and append it.\r
c7e39923 523 //\r
524 LunNode.Header.Type = MESSAGING_DEVICE_PATH;\r
525 LunNode.Header.SubType = MSG_DEVICE_LOGICAL_UNIT_DP;\r
526 LunNode.Lun = UsbMass->Lun;\r
d1102dba 527\r
c7e39923 528 SetDevicePathNodeLength (&LunNode.Header, sizeof (LunNode));\r
d1102dba 529\r
c7e39923 530 UsbMass->DevicePath = AppendDevicePathNode (DevicePath, &LunNode.Header);\r
d1102dba 531\r
c7e39923 532 if (UsbMass->DevicePath == NULL) {\r
87000d77 533 DEBUG ((DEBUG_ERROR, "UsbMassInitMultiLun: failed to create device logic unit device path\n"));\r
c7e39923 534 Status = EFI_OUT_OF_RESOURCES;\r
66a5771e
TF
535 FreePool (UsbMass);\r
536 continue;\r
c7e39923 537 }\r
538\r
39840c50 539 InitializeDiskInfo (UsbMass);\r
540\r
c7e39923 541 //\r
3e03cb4d 542 // Create a new handle for each LUN, and install Block I/O Protocol and Device Path Protocol.\r
c7e39923 543 //\r
544 Status = gBS->InstallMultipleProtocolInterfaces (\r
545 &UsbMass->Controller,\r
546 &gEfiDevicePathProtocolGuid,\r
547 UsbMass->DevicePath,\r
548 &gEfiBlockIoProtocolGuid,\r
549 &UsbMass->BlockIo,\r
39840c50 550 &gEfiDiskInfoProtocolGuid,\r
551 &UsbMass->DiskInfo,\r
c7e39923 552 NULL\r
553 );\r
d1102dba 554\r
c7e39923 555 if (EFI_ERROR (Status)) {\r
87000d77 556 DEBUG ((DEBUG_ERROR, "UsbMassInitMultiLun: InstallMultipleProtocolInterfaces (%r)\n", Status));\r
66a5771e
TF
557 FreePool (UsbMass->DevicePath);\r
558 FreePool (UsbMass);\r
559 continue;\r
c7e39923 560 }\r
561\r
562 //\r
3e03cb4d 563 // Open USB I/O Protocol by child to setup a parent-child relationship.\r
c7e39923 564 //\r
565 Status = gBS->OpenProtocol (\r
566 Controller,\r
567 &gEfiUsbIoProtocolGuid,\r
1436aea4 568 (VOID **)&UsbIo,\r
c7e39923 569 This->DriverBindingHandle,\r
570 UsbMass->Controller,\r
571 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
572 );\r
573\r
574 if (EFI_ERROR (Status)) {\r
87000d77 575 DEBUG ((DEBUG_ERROR, "UsbMassInitMultiLun: OpenUsbIoProtocol By Child (%r)\n", Status));\r
c7e39923 576 gBS->UninstallMultipleProtocolInterfaces (\r
9388c6b1 577 UsbMass->Controller,\r
c7e39923 578 &gEfiDevicePathProtocolGuid,\r
579 UsbMass->DevicePath,\r
580 &gEfiBlockIoProtocolGuid,\r
581 &UsbMass->BlockIo,\r
39840c50 582 &gEfiDiskInfoProtocolGuid,\r
583 &UsbMass->DiskInfo,\r
c7e39923 584 NULL\r
585 );\r
66a5771e
TF
586 FreePool (UsbMass->DevicePath);\r
587 FreePool (UsbMass);\r
588 continue;\r
c7e39923 589 }\r
1436aea4 590\r
66a5771e 591 ReturnStatus = EFI_SUCCESS;\r
87000d77 592 DEBUG ((DEBUG_INFO, "UsbMassInitMultiLun: Success to initialize No.%d logic unit\n", Index));\r
c7e39923 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
1436aea4
MK
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
c7e39923 616 )\r
617{\r
1436aea4
MK
618 USB_MASS_DEVICE *UsbMass;\r
619 EFI_USB_IO_PROTOCOL *UsbIo;\r
620 EFI_STATUS Status;\r
c7e39923 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
1436aea4 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
87000d77 636 DEBUG ((DEBUG_ERROR, "UsbMassInitNonLun: OpenUsbIoProtocol By Driver (%r)\n", Status));\r
c7e39923 637 goto ON_ERROR;\r
638 }\r
d1102dba 639\r
1436aea4
MK
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
87000d77 657 DEBUG ((DEBUG_ERROR, "UsbMassInitNonLun: UsbMassInitMedia (%r)\n", Status));\r
c7e39923 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
1436aea4 681\r
73f8ef8c 682 if (UsbIo != NULL) {\r
683 gBS->CloseProtocol (\r
684 Controller,\r
685 &gEfiUsbIoProtocolGuid,\r
686 This->DriverBindingHandle,\r
687 Controller\r
688 );\r
689 }\r
1436aea4 690\r
d1102dba 691 return Status;\r
c7e39923 692}\r
693\r
e237e7ae 694/**\r
695 Check whether the controller is a supported USB mass storage.\r
696\r
d80ed2a7 697 @param This The USB mass storage driver binding protocol.\r
698 @param Controller The controller handle to check.\r
699 @param RemainingDevicePath The remaining device path.\r
e237e7ae 700\r
d80ed2a7 701 @retval EFI_SUCCESS The driver supports this controller.\r
702 @retval other This device isn't supported.\r
e237e7ae 703\r
704**/\r
705EFI_STATUS\r
706EFIAPI\r
707USBMassDriverBindingSupported (\r
708 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
709 IN EFI_HANDLE Controller,\r
710 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
711 )\r
712{\r
713 EFI_USB_IO_PROTOCOL *UsbIo;\r
714 EFI_USB_INTERFACE_DESCRIPTOR Interface;\r
715 USB_MASS_TRANSPORT *Transport;\r
716 EFI_STATUS Status;\r
d80ed2a7 717 UINTN Index;\r
e237e7ae 718\r
e237e7ae 719 Status = gBS->OpenProtocol (\r
720 Controller,\r
721 &gEfiUsbIoProtocolGuid,\r
1436aea4 722 (VOID **)&UsbIo,\r
e237e7ae 723 This->DriverBindingHandle,\r
724 Controller,\r
725 EFI_OPEN_PROTOCOL_BY_DRIVER\r
726 );\r
727 if (EFI_ERROR (Status)) {\r
728 return Status;\r
729 }\r
730\r
731 //\r
d80ed2a7 732 // Get the interface descriptor to check the USB class and find a transport\r
e237e7ae 733 // protocol handler.\r
734 //\r
735 Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);\r
736 if (EFI_ERROR (Status)) {\r
737 goto ON_EXIT;\r
738 }\r
739\r
740 Status = EFI_UNSUPPORTED;\r
741\r
742 if (Interface.InterfaceClass != USB_MASS_STORE_CLASS) {\r
743 goto ON_EXIT;\r
744 }\r
745\r
d80ed2a7 746 //\r
747 // Traverse the USB_MASS_TRANSPORT arrary and try to find the\r
748 // matching transport method.\r
749 // If not found, return EFI_UNSUPPORTED.\r
750 // If found, execute USB_MASS_TRANSPORT.Init() to initialize the transport context.\r
751 //\r
db0bd81c 752 for (Index = 0; Index < USB_MASS_TRANSPORT_COUNT; Index++) {\r
e237e7ae 753 Transport = mUsbMassTransport[Index];\r
754 if (Interface.InterfaceProtocol == Transport->Protocol) {\r
c7e39923 755 Status = Transport->Init (UsbIo, NULL);\r
e237e7ae 756 break;\r
757 }\r
758 }\r
759\r
e237e7ae 760ON_EXIT:\r
761 gBS->CloseProtocol (\r
d80ed2a7 762 Controller,\r
763 &gEfiUsbIoProtocolGuid,\r
764 This->DriverBindingHandle,\r
765 Controller\r
766 );\r
e237e7ae 767\r
768 return Status;\r
769}\r
770\r
e237e7ae 771/**\r
d80ed2a7 772 Starts the USB mass storage device with this driver.\r
e237e7ae 773\r
957ca631 774 This function consumes USB I/O Protocol, initializes USB mass storage device,\r
d80ed2a7 775 installs Block I/O Protocol, and submits Asynchronous Interrupt\r
776 Transfer to manage the USB mass storage device.\r
777\r
3e03cb4d 778 @param This The USB mass storage driver binding protocol.\r
779 @param Controller The USB mass storage device to start on\r
780 @param RemainingDevicePath The remaining device path.\r
e237e7ae 781\r
d80ed2a7 782 @retval EFI_SUCCESS This driver supports this device.\r
783 @retval EFI_UNSUPPORTED This driver does not support this device.\r
784 @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.\r
785 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.\r
786 @retval EFI_ALREADY_STARTED This driver has been started.\r
e237e7ae 787\r
788**/\r
789EFI_STATUS\r
790EFIAPI\r
791USBMassDriverBindingStart (\r
792 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
793 IN EFI_HANDLE Controller,\r
794 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
795 )\r
796{\r
1436aea4
MK
797 USB_MASS_TRANSPORT *Transport;\r
798 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
799 VOID *Context;\r
800 UINT8 MaxLun;\r
801 EFI_STATUS Status;\r
802 EFI_USB_IO_PROTOCOL *UsbIo;\r
803 EFI_TPL OldTpl;\r
15cc67e6 804\r
805 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
806\r
c7e39923 807 Transport = NULL;\r
808 Context = NULL;\r
809 MaxLun = 0;\r
e237e7ae 810\r
c7e39923 811 Status = UsbMassInitTransport (This, Controller, &Transport, &Context, &MaxLun);\r
e237e7ae 812\r
813 if (EFI_ERROR (Status)) {\r
87000d77 814 DEBUG ((DEBUG_ERROR, "USBMassDriverBindingStart: UsbMassInitTransport (%r)\n", Status));\r
15cc67e6 815 goto Exit;\r
e237e7ae 816 }\r
1436aea4 817\r
c7e39923 818 if (MaxLun == 0) {\r
819 //\r
3e03cb4d 820 // Initialize data for device that does not support multiple LUNSs.\r
c7e39923 821 //\r
3e03cb4d 822 Status = UsbMassInitNonLun (This, Controller, Transport, Context);\r
d1102dba 823 if (EFI_ERROR (Status)) {\r
87000d77 824 DEBUG ((DEBUG_ERROR, "USBMassDriverBindingStart: UsbMassInitNonLun (%r)\n", Status));\r
c7e39923 825 }\r
826 } else {\r
827 //\r
3e03cb4d 828 // Open device path to prepare for appending Device Logic Unit node.\r
c7e39923 829 //\r
830 Status = gBS->OpenProtocol (\r
831 Controller,\r
832 &gEfiDevicePathProtocolGuid,\r
1436aea4 833 (VOID **)&DevicePath,\r
c7e39923 834 This->DriverBindingHandle,\r
835 Controller,\r
836 EFI_OPEN_PROTOCOL_BY_DRIVER\r
837 );\r
d1102dba 838\r
c7e39923 839 if (EFI_ERROR (Status)) {\r
87000d77 840 DEBUG ((DEBUG_ERROR, "USBMassDriverBindingStart: OpenDevicePathProtocol By Driver (%r)\n", Status));\r
15cc67e6 841 goto Exit;\r
e237e7ae 842 }\r
e237e7ae 843\r
73f8ef8c 844 Status = gBS->OpenProtocol (\r
845 Controller,\r
846 &gEfiUsbIoProtocolGuid,\r
1436aea4 847 (VOID **)&UsbIo,\r
73f8ef8c 848 This->DriverBindingHandle,\r
849 Controller,\r
850 EFI_OPEN_PROTOCOL_BY_DRIVER\r
851 );\r
d1102dba 852\r
73f8ef8c 853 if (EFI_ERROR (Status)) {\r
87000d77 854 DEBUG ((DEBUG_ERROR, "USBMassDriverBindingStart: OpenUsbIoProtocol By Driver (%r)\n", Status));\r
73f8ef8c 855 gBS->CloseProtocol (\r
856 Controller,\r
857 &gEfiDevicePathProtocolGuid,\r
858 This->DriverBindingHandle,\r
859 Controller\r
860 );\r
15cc67e6 861 goto Exit;\r
73f8ef8c 862 }\r
863\r
c7e39923 864 //\r
66a5771e 865 // Initialize data for device that supports multiple LUNs.\r
3e03cb4d 866 // EFI_SUCCESS is returned if at least 1 LUN is initialized successfully.\r
c7e39923 867 //\r
d80ed2a7 868 Status = UsbMassInitMultiLun (This, Controller, Transport, Context, DevicePath, MaxLun);\r
c7e39923 869 if (EFI_ERROR (Status)) {\r
73f8ef8c 870 gBS->CloseProtocol (\r
1436aea4
MK
871 Controller,\r
872 &gEfiDevicePathProtocolGuid,\r
873 This->DriverBindingHandle,\r
874 Controller\r
875 );\r
73f8ef8c 876 gBS->CloseProtocol (\r
1436aea4
MK
877 Controller,\r
878 &gEfiUsbIoProtocolGuid,\r
879 This->DriverBindingHandle,\r
880 Controller\r
881 );\r
87000d77 882 DEBUG ((DEBUG_ERROR, "USBMassDriverBindingStart: UsbMassInitMultiLun (%r) with Maxlun=%d\n", Status, MaxLun));\r
c7e39923 883 }\r
e237e7ae 884 }\r
1436aea4 885\r
15cc67e6 886Exit:\r
887 gBS->RestoreTPL (OldTpl);\r
e237e7ae 888 return Status;\r
889}\r
890\r
e237e7ae 891/**\r
892 Stop controlling the device.\r
893\r
894 @param This The USB mass storage driver binding\r
895 @param Controller The device controller controlled by the driver.\r
896 @param NumberOfChildren The number of children of this device\r
897 @param ChildHandleBuffer The buffer of children handle.\r
898\r
899 @retval EFI_SUCCESS The driver stopped from controlling the device.\r
3e03cb4d 900 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
901 @retval EFI_UNSUPPORTED Block I/O Protocol is not installed on Controller.\r
e237e7ae 902 @retval Others Failed to stop the driver\r
903\r
904**/\r
905EFI_STATUS\r
906EFIAPI\r
907USBMassDriverBindingStop (\r
1436aea4
MK
908 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
909 IN EFI_HANDLE Controller,\r
910 IN UINTN NumberOfChildren,\r
911 IN EFI_HANDLE *ChildHandleBuffer\r
e237e7ae 912 )\r
913{\r
1436aea4
MK
914 EFI_STATUS Status;\r
915 USB_MASS_DEVICE *UsbMass;\r
916 EFI_USB_IO_PROTOCOL *UsbIo;\r
917 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
918 UINTN Index;\r
919 BOOLEAN AllChildrenStopped;\r
c7e39923 920\r
921 //\r
3e03cb4d 922 // This is a bus driver stop function since multi-lun is supported.\r
923 // There are three kinds of device handles that might be passed:\r
73f8ef8c 924 // 1st is a handle with USB I/O & Block I/O installed (non-multi-lun)\r
3e03cb4d 925 // 2nd is a handle with Device Path & USB I/O installed (multi-lun root)\r
73f8ef8c 926 // 3rd is a handle with Device Path & USB I/O & Block I/O installed (multi-lun).\r
c7e39923 927 //\r
928 if (NumberOfChildren == 0) {\r
929 //\r
930 // A handle without any children, might be 1st and 2nd type.\r
931 //\r
932 Status = gBS->OpenProtocol (\r
933 Controller,\r
934 &gEfiBlockIoProtocolGuid,\r
1436aea4 935 (VOID **)&BlockIo,\r
c7e39923 936 This->DriverBindingHandle,\r
937 Controller,\r
938 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
939 );\r
d1102dba 940\r
1436aea4 941 if (EFI_ERROR (Status)) {\r
c7e39923 942 //\r
73f8ef8c 943 // This is a 2nd type handle(multi-lun root), it needs to close devicepath\r
944 // and usbio protocol.\r
c7e39923 945 //\r
946 gBS->CloseProtocol (\r
1436aea4
MK
947 Controller,\r
948 &gEfiDevicePathProtocolGuid,\r
949 This->DriverBindingHandle,\r
950 Controller\r
951 );\r
73f8ef8c 952 gBS->CloseProtocol (\r
1436aea4
MK
953 Controller,\r
954 &gEfiUsbIoProtocolGuid,\r
955 This->DriverBindingHandle,\r
956 Controller\r
957 );\r
87000d77 958 DEBUG ((DEBUG_INFO, "Success to stop multi-lun root handle\n"));\r
c7e39923 959 return EFI_SUCCESS;\r
960 }\r
d1102dba 961\r
c7e39923 962 //\r
3e03cb4d 963 // This is a 1st type handle(non-multi-lun), which only needs to uninstall\r
964 // Block I/O Protocol, close USB I/O Protocol and free mass device.\r
c7e39923 965 //\r
d80ed2a7 966 UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (BlockIo);\r
d1102dba 967\r
c7e39923 968 //\r
969 // Uninstall Block I/O protocol from the device handle,\r
970 // then call the transport protocol to stop itself.\r
971 //\r
39840c50 972 Status = gBS->UninstallMultipleProtocolInterfaces (\r
c7e39923 973 Controller,\r
974 &gEfiBlockIoProtocolGuid,\r
39840c50 975 &UsbMass->BlockIo,\r
976 &gEfiDiskInfoProtocolGuid,\r
977 &UsbMass->DiskInfo,\r
978 NULL\r
c7e39923 979 );\r
980 if (EFI_ERROR (Status)) {\r
981 return Status;\r
982 }\r
d1102dba 983\r
c7e39923 984 gBS->CloseProtocol (\r
1436aea4
MK
985 Controller,\r
986 &gEfiUsbIoProtocolGuid,\r
987 This->DriverBindingHandle,\r
988 Controller\r
989 );\r
d1102dba 990\r
d80ed2a7 991 UsbMass->Transport->CleanUp (UsbMass->Context);\r
3e03cb4d 992 FreePool (UsbMass);\r
d1102dba 993\r
87000d77 994 DEBUG ((DEBUG_INFO, "Success to stop non-multi-lun root handle\n"));\r
c7e39923 995 return EFI_SUCCESS;\r
d1102dba 996 }\r
c7e39923 997\r
998 //\r
999 // This is a 3rd type handle(multi-lun), which needs uninstall\r
d1102dba 1000 // Block I/O Protocol and Device Path Protocol, close USB I/O Protocol and\r
3e03cb4d 1001 // free mass device for all children.\r
c7e39923 1002 //\r
1003 AllChildrenStopped = TRUE;\r
1004\r
1005 for (Index = 0; Index < NumberOfChildren; Index++) {\r
c7e39923 1006 Status = gBS->OpenProtocol (\r
1007 ChildHandleBuffer[Index],\r
1008 &gEfiBlockIoProtocolGuid,\r
1436aea4 1009 (VOID **)&BlockIo,\r
c7e39923 1010 This->DriverBindingHandle,\r
1011 Controller,\r
1012 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1013 );\r
1014 if (EFI_ERROR (Status)) {\r
1015 AllChildrenStopped = FALSE;\r
87000d77 1016 DEBUG ((DEBUG_ERROR, "Fail to stop No.%d multi-lun child handle when opening blockio\n", (UINT32)Index));\r
c7e39923 1017 continue;\r
1018 }\r
e237e7ae 1019\r
d80ed2a7 1020 UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (BlockIo);\r
c7e39923 1021\r
1022 gBS->CloseProtocol (\r
3e03cb4d 1023 Controller,\r
1024 &gEfiUsbIoProtocolGuid,\r
1025 This->DriverBindingHandle,\r
1026 ChildHandleBuffer[Index]\r
1027 );\r
d1102dba 1028\r
c7e39923 1029 Status = gBS->UninstallMultipleProtocolInterfaces (\r
1030 ChildHandleBuffer[Index],\r
1031 &gEfiDevicePathProtocolGuid,\r
1032 UsbMass->DevicePath,\r
1033 &gEfiBlockIoProtocolGuid,\r
1034 &UsbMass->BlockIo,\r
39840c50 1035 &gEfiDiskInfoProtocolGuid,\r
1036 &UsbMass->DiskInfo,\r
c7e39923 1037 NULL\r
1038 );\r
d1102dba 1039\r
c7e39923 1040 if (EFI_ERROR (Status)) {\r
1041 //\r
3e03cb4d 1042 // Fail to uninstall Block I/O Protocol and Device Path Protocol, so re-open USB I/O Protocol by child.\r
c7e39923 1043 //\r
1044 AllChildrenStopped = FALSE;\r
87000d77 1045 DEBUG ((DEBUG_ERROR, "Fail to stop No.%d multi-lun child handle when uninstalling blockio and devicepath\n", (UINT32)Index));\r
d1102dba 1046\r
c7e39923 1047 gBS->OpenProtocol (\r
1048 Controller,\r
1049 &gEfiUsbIoProtocolGuid,\r
1436aea4 1050 (VOID **)&UsbIo,\r
c7e39923 1051 This->DriverBindingHandle,\r
1052 ChildHandleBuffer[Index],\r
1053 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
1054 );\r
1055 } else {\r
1056 //\r
3e03cb4d 1057 // Succeed to stop this multi-lun handle, so go on with next child.\r
c7e39923 1058 //\r
1059 if (((Index + 1) == NumberOfChildren) && AllChildrenStopped) {\r
d80ed2a7 1060 UsbMass->Transport->CleanUp (UsbMass->Context);\r
c7e39923 1061 }\r
1436aea4 1062\r
3e03cb4d 1063 FreePool (UsbMass);\r
c7e39923 1064 }\r
e237e7ae 1065 }\r
1066\r
c7e39923 1067 if (!AllChildrenStopped) {\r
1068 return EFI_DEVICE_ERROR;\r
e237e7ae 1069 }\r
d1102dba 1070\r
1436aea4 1071 DEBUG ((DEBUG_INFO, "Success to stop all %d multi-lun children handles\n", (UINT32)NumberOfChildren));\r
e237e7ae 1072 return EFI_SUCCESS;\r
1073}\r
1074\r
cc5166ff 1075/**\r
3e03cb4d 1076 Entrypoint of USB Mass Storage Driver.\r
1077\r
1078 This function is the entrypoint of USB Mass Storage Driver. It installs Driver Binding\r
1079 Protocol together with Component Name Protocols.\r
cc5166ff 1080\r
3e03cb4d 1081 @param ImageHandle The firmware allocated handle for the EFI image.\r
1082 @param SystemTable A pointer to the EFI System Table.\r
cc5166ff 1083\r
3e03cb4d 1084 @retval EFI_SUCCESS The entry point is executed successfully.\r
cc5166ff 1085\r
1086**/\r
e237e7ae 1087EFI_STATUS\r
1088EFIAPI\r
1089USBMassStorageEntryPoint (\r
1436aea4
MK
1090 IN EFI_HANDLE ImageHandle,\r
1091 IN EFI_SYSTEM_TABLE *SystemTable\r
e237e7ae 1092 )\r
e237e7ae 1093{\r
1094 EFI_STATUS Status;\r
1095\r
1096 //\r
1097 // Install driver binding protocol\r
1098 //\r
62b9bb55 1099 Status = EfiLibInstallDriverBindingComponentName2 (\r
e237e7ae 1100 ImageHandle,\r
1101 SystemTable,\r
1102 &gUSBMassDriverBinding,\r
1103 ImageHandle,\r
1104 &gUsbMassStorageComponentName,\r
62b9bb55 1105 &gUsbMassStorageComponentName2\r
e237e7ae 1106 );\r
d80ed2a7 1107 ASSERT_EFI_ERROR (Status);\r
e237e7ae 1108\r
d80ed2a7 1109 return EFI_SUCCESS;\r
e237e7ae 1110}\r