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