]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.c
Correct inconsistent information in IpsecConfig.efi help report.
[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
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
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
39840c50 557 InitializeDiskInfo (UsbMass);\r
558\r
c7e39923 559 //\r
3e03cb4d 560 // Create a new handle for each LUN, and install Block I/O Protocol and Device Path Protocol.\r
c7e39923 561 //\r
562 Status = gBS->InstallMultipleProtocolInterfaces (\r
563 &UsbMass->Controller,\r
564 &gEfiDevicePathProtocolGuid,\r
565 UsbMass->DevicePath,\r
566 &gEfiBlockIoProtocolGuid,\r
567 &UsbMass->BlockIo,\r
39840c50 568 &gEfiDiskInfoProtocolGuid,\r
569 &UsbMass->DiskInfo,\r
c7e39923 570 NULL\r
571 );\r
572 \r
573 if (EFI_ERROR (Status)) {\r
574 DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: InstallMultipleProtocolInterfaces (%r)\n", Status));\r
575 goto ON_ERROR;\r
576 }\r
577\r
578 //\r
3e03cb4d 579 // Open USB I/O Protocol by child to setup a parent-child relationship.\r
c7e39923 580 //\r
581 Status = gBS->OpenProtocol (\r
582 Controller,\r
583 &gEfiUsbIoProtocolGuid,\r
b16b8bf9 584 (VOID **) &UsbIo,\r
c7e39923 585 This->DriverBindingHandle,\r
586 UsbMass->Controller,\r
587 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
588 );\r
589\r
590 if (EFI_ERROR (Status)) {\r
591 DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: OpenUsbIoProtocol By Child (%r)\n", Status));\r
592 gBS->UninstallMultipleProtocolInterfaces (\r
593 &UsbMass->Controller,\r
594 &gEfiDevicePathProtocolGuid,\r
595 UsbMass->DevicePath,\r
596 &gEfiBlockIoProtocolGuid,\r
597 &UsbMass->BlockIo,\r
39840c50 598 &gEfiDiskInfoProtocolGuid,\r
599 &UsbMass->DiskInfo,\r
c7e39923 600 NULL\r
601 );\r
602 goto ON_ERROR;\r
603 }\r
604 \r
605 DEBUG ((EFI_D_INFO, "UsbMassInitMultiLun: Success to initialize No.%d logic unit\n", Index));\r
606 }\r
607 \r
608 return EFI_SUCCESS;\r
609\r
610ON_ERROR:\r
c7e39923 611 if (UsbMass != NULL) {\r
81464cf1 612 if (UsbMass->DevicePath != NULL) {\r
613 FreePool (UsbMass->DevicePath);\r
614 }\r
3e03cb4d 615 FreePool (UsbMass);\r
c7e39923 616 }\r
617 if (UsbIo != NULL) {\r
618 gBS->CloseProtocol (\r
619 Controller,\r
620 &gEfiUsbIoProtocolGuid,\r
621 This->DriverBindingHandle,\r
622 UsbMass->Controller\r
623 );\r
624 }\r
625\r
626 //\r
3e03cb4d 627 // Return EFI_SUCCESS if at least one LUN is initialized successfully.\r
c7e39923 628 //\r
629 if (Index > 0) {\r
630 return EFI_SUCCESS; \r
631 } else {\r
632 return Status;\r
633 } \r
634}\r
635\r
cc5166ff 636/**\r
3e03cb4d 637 Initialize data for device that does not support multiple LUNSs.\r
cc5166ff 638\r
3e03cb4d 639 @param This The Driver Binding Protocol instance.\r
640 @param Controller The device to initialize.\r
641 @param Transport Pointer to USB_MASS_TRANSPORT.\r
642 @param Context Parameter for USB_MASS_DEVICE.Context.\r
cc5166ff 643\r
3e03cb4d 644 @retval EFI_SUCCESS Initialization succeeds.\r
cc5166ff 645 @retval Other Initialization fails.\r
646\r
647**/\r
c7e39923 648EFI_STATUS\r
649UsbMassInitNonLun (\r
650 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
651 IN EFI_HANDLE Controller,\r
652 IN USB_MASS_TRANSPORT *Transport,\r
653 IN VOID *Context\r
654 )\r
655{\r
656 USB_MASS_DEVICE *UsbMass;\r
657 EFI_USB_IO_PROTOCOL *UsbIo;\r
658 EFI_STATUS Status;\r
659\r
660 UsbIo = NULL;\r
661 UsbMass = AllocateZeroPool (sizeof (USB_MASS_DEVICE));\r
3e03cb4d 662 ASSERT (UsbMass != NULL);\r
663\r
c7e39923 664 Status = gBS->OpenProtocol (\r
665 Controller,\r
666 &gEfiUsbIoProtocolGuid,\r
b16b8bf9 667 (VOID **) &UsbIo,\r
c7e39923 668 This->DriverBindingHandle,\r
669 Controller,\r
670 EFI_OPEN_PROTOCOL_BY_DRIVER\r
671 );\r
672\r
673 if (EFI_ERROR (Status)) {\r
674 DEBUG ((EFI_D_ERROR, "UsbMassInitNonLun: OpenUsbIoProtocol By Driver (%r)\n", Status));\r
675 goto ON_ERROR;\r
676 }\r
677 \r
678 UsbMass->Signature = USB_MASS_SIGNATURE;\r
679 UsbMass->Controller = Controller;\r
680 UsbMass->UsbIo = UsbIo;\r
681 UsbMass->BlockIo.Media = &UsbMass->BlockIoMedia;\r
682 UsbMass->BlockIo.Reset = UsbMassReset;\r
683 UsbMass->BlockIo.ReadBlocks = UsbMassReadBlocks;\r
684 UsbMass->BlockIo.WriteBlocks = UsbMassWriteBlocks;\r
685 UsbMass->BlockIo.FlushBlocks = UsbMassFlushBlocks;\r
686 UsbMass->OpticalStorage = FALSE;\r
687 UsbMass->Transport = Transport;\r
688 UsbMass->Context = Context;\r
689 \r
690 //\r
3e03cb4d 691 // Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol.\r
c7e39923 692 //\r
693 Status = UsbMassInitMedia (UsbMass);\r
694 if (!EFI_ERROR (Status)) {\r
3e03cb4d 695 //\r
696 // According to USB Mass Storage Specification for Bootability, only following\r
697 // 4 Peripheral Device Types are in spec.\r
698 //\r
c7e39923 699 if ((UsbMass->Pdt != USB_PDT_DIRECT_ACCESS) && \r
700 (UsbMass->Pdt != USB_PDT_CDROM) &&\r
701 (UsbMass->Pdt != USB_PDT_OPTICAL) && \r
702 (UsbMass->Pdt != USB_PDT_SIMPLE_DIRECT)) {\r
703 DEBUG ((EFI_D_ERROR, "UsbMassInitNonLun: Found an unsupported peripheral type[%d]\n", UsbMass->Pdt));\r
704 goto ON_ERROR;\r
705 }\r
706 } else if (Status != EFI_NO_MEDIA){\r
707 DEBUG ((EFI_D_ERROR, "UsbMassInitNonLun: UsbMassInitMedia (%r)\n", Status));\r
708 goto ON_ERROR;\r
709 }\r
710 \r
39840c50 711 InitializeDiskInfo (UsbMass);\r
712\r
713 Status = gBS->InstallMultipleProtocolInterfaces (\r
c7e39923 714 &Controller,\r
715 &gEfiBlockIoProtocolGuid,\r
39840c50 716 &UsbMass->BlockIo,\r
717 &gEfiDiskInfoProtocolGuid,\r
718 &UsbMass->DiskInfo,\r
719 NULL\r
c7e39923 720 );\r
721 if (EFI_ERROR (Status)) {\r
722 goto ON_ERROR;\r
723 }\r
724\r
725 return EFI_SUCCESS;\r
726\r
727ON_ERROR:\r
728 if (UsbMass != NULL) {\r
3e03cb4d 729 FreePool (UsbMass);\r
c7e39923 730 }\r
73f8ef8c 731 if (UsbIo != NULL) {\r
732 gBS->CloseProtocol (\r
733 Controller,\r
734 &gEfiUsbIoProtocolGuid,\r
735 This->DriverBindingHandle,\r
736 Controller\r
737 );\r
738 }\r
c7e39923 739 return Status; \r
740}\r
741\r
e237e7ae 742\r
743/**\r
744 Check whether the controller is a supported USB mass storage.\r
745\r
d80ed2a7 746 @param This The USB mass storage driver binding protocol.\r
747 @param Controller The controller handle to check.\r
748 @param RemainingDevicePath The remaining device path.\r
e237e7ae 749\r
d80ed2a7 750 @retval EFI_SUCCESS The driver supports this controller.\r
751 @retval other This device isn't supported.\r
e237e7ae 752\r
753**/\r
754EFI_STATUS\r
755EFIAPI\r
756USBMassDriverBindingSupported (\r
757 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
758 IN EFI_HANDLE Controller,\r
759 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
760 )\r
761{\r
762 EFI_USB_IO_PROTOCOL *UsbIo;\r
763 EFI_USB_INTERFACE_DESCRIPTOR Interface;\r
764 USB_MASS_TRANSPORT *Transport;\r
765 EFI_STATUS Status;\r
d80ed2a7 766 UINTN Index;\r
e237e7ae 767\r
e237e7ae 768 Status = gBS->OpenProtocol (\r
769 Controller,\r
770 &gEfiUsbIoProtocolGuid,\r
c52fa98c 771 (VOID **) &UsbIo,\r
e237e7ae 772 This->DriverBindingHandle,\r
773 Controller,\r
774 EFI_OPEN_PROTOCOL_BY_DRIVER\r
775 );\r
776 if (EFI_ERROR (Status)) {\r
777 return Status;\r
778 }\r
779\r
780 //\r
d80ed2a7 781 // Get the interface descriptor to check the USB class and find a transport\r
e237e7ae 782 // protocol handler.\r
783 //\r
784 Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);\r
785 if (EFI_ERROR (Status)) {\r
786 goto ON_EXIT;\r
787 }\r
788\r
789 Status = EFI_UNSUPPORTED;\r
790\r
791 if (Interface.InterfaceClass != USB_MASS_STORE_CLASS) {\r
792 goto ON_EXIT;\r
793 }\r
794\r
d80ed2a7 795 //\r
796 // Traverse the USB_MASS_TRANSPORT arrary and try to find the\r
797 // matching transport method.\r
798 // If not found, return EFI_UNSUPPORTED.\r
799 // If found, execute USB_MASS_TRANSPORT.Init() to initialize the transport context.\r
800 //\r
db0bd81c 801 for (Index = 0; Index < USB_MASS_TRANSPORT_COUNT; Index++) {\r
e237e7ae 802 Transport = mUsbMassTransport[Index];\r
803 if (Interface.InterfaceProtocol == Transport->Protocol) {\r
c7e39923 804 Status = Transport->Init (UsbIo, NULL);\r
e237e7ae 805 break;\r
806 }\r
807 }\r
808\r
e237e7ae 809ON_EXIT:\r
810 gBS->CloseProtocol (\r
d80ed2a7 811 Controller,\r
812 &gEfiUsbIoProtocolGuid,\r
813 This->DriverBindingHandle,\r
814 Controller\r
815 );\r
e237e7ae 816\r
817 return Status;\r
818}\r
819\r
e237e7ae 820/**\r
d80ed2a7 821 Starts the USB mass storage device with this driver.\r
e237e7ae 822\r
d80ed2a7 823 This function consumes USB I/O Portocol, intializes USB mass storage device,\r
824 installs Block I/O Protocol, and submits Asynchronous Interrupt\r
825 Transfer to manage the USB mass storage device.\r
826\r
3e03cb4d 827 @param This The USB mass storage driver binding protocol.\r
828 @param Controller The USB mass storage device to start on\r
829 @param RemainingDevicePath The remaining device path.\r
e237e7ae 830\r
d80ed2a7 831 @retval EFI_SUCCESS This driver supports this device.\r
832 @retval EFI_UNSUPPORTED This driver does not support this device.\r
833 @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.\r
834 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.\r
835 @retval EFI_ALREADY_STARTED This driver has been started.\r
e237e7ae 836\r
837**/\r
838EFI_STATUS\r
839EFIAPI\r
840USBMassDriverBindingStart (\r
841 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
842 IN EFI_HANDLE Controller,\r
843 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
844 )\r
845{\r
e237e7ae 846 USB_MASS_TRANSPORT *Transport;\r
c7e39923 847 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
848 VOID *Context;\r
849 UINT8 MaxLun;\r
e237e7ae 850 EFI_STATUS Status;\r
73f8ef8c 851 EFI_USB_IO_PROTOCOL *UsbIo; \r
15cc67e6 852 EFI_TPL OldTpl;\r
853\r
854 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
855\r
c7e39923 856 Transport = NULL;\r
857 Context = NULL;\r
858 MaxLun = 0;\r
e237e7ae 859\r
c7e39923 860 Status = UsbMassInitTransport (This, Controller, &Transport, &Context, &MaxLun);\r
e237e7ae 861\r
862 if (EFI_ERROR (Status)) {\r
c7e39923 863 DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: UsbMassInitTransport (%r)\n", Status));\r
15cc67e6 864 goto Exit;\r
e237e7ae 865 }\r
c7e39923 866 if (MaxLun == 0) {\r
867 //\r
3e03cb4d 868 // Initialize data for device that does not support multiple LUNSs.\r
c7e39923 869 //\r
3e03cb4d 870 Status = UsbMassInitNonLun (This, Controller, Transport, Context);\r
c7e39923 871 if (EFI_ERROR (Status)) { \r
872 DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: UsbMassInitNonLun (%r)\n", Status));\r
873 }\r
874 } else {\r
875 //\r
3e03cb4d 876 // Open device path to prepare for appending Device Logic Unit node.\r
c7e39923 877 //\r
878 Status = gBS->OpenProtocol (\r
879 Controller,\r
880 &gEfiDevicePathProtocolGuid,\r
881 (VOID **) &DevicePath,\r
882 This->DriverBindingHandle,\r
883 Controller,\r
884 EFI_OPEN_PROTOCOL_BY_DRIVER\r
885 );\r
886 \r
887 if (EFI_ERROR (Status)) {\r
888 DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: OpenDevicePathProtocol By Driver (%r)\n", Status));\r
15cc67e6 889 goto Exit;\r
e237e7ae 890 }\r
e237e7ae 891\r
73f8ef8c 892 Status = gBS->OpenProtocol (\r
893 Controller,\r
894 &gEfiUsbIoProtocolGuid,\r
895 (VOID **) &UsbIo,\r
896 This->DriverBindingHandle,\r
897 Controller,\r
898 EFI_OPEN_PROTOCOL_BY_DRIVER\r
899 );\r
900 \r
901 if (EFI_ERROR (Status)) {\r
902 DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: OpenUsbIoProtocol By Driver (%r)\n", Status));\r
903 gBS->CloseProtocol (\r
904 Controller,\r
905 &gEfiDevicePathProtocolGuid,\r
906 This->DriverBindingHandle,\r
907 Controller\r
908 );\r
15cc67e6 909 goto Exit;\r
73f8ef8c 910 }\r
911\r
c7e39923 912 //\r
3e03cb4d 913 // Initialize data for device that supports multiple LUNSs.\r
914 // EFI_SUCCESS is returned if at least 1 LUN is initialized successfully.\r
c7e39923 915 //\r
d80ed2a7 916 Status = UsbMassInitMultiLun (This, Controller, Transport, Context, DevicePath, MaxLun);\r
c7e39923 917 if (EFI_ERROR (Status)) {\r
73f8ef8c 918 gBS->CloseProtocol (\r
919 Controller,\r
920 &gEfiDevicePathProtocolGuid,\r
921 This->DriverBindingHandle,\r
922 Controller\r
923 );\r
924 gBS->CloseProtocol (\r
925 Controller,\r
926 &gEfiUsbIoProtocolGuid,\r
927 This->DriverBindingHandle,\r
928 Controller\r
929 );\r
c7e39923 930 DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: UsbMassInitMultiLun (%r) with Maxlun=%d\n", Status, MaxLun));\r
931 }\r
e237e7ae 932 }\r
15cc67e6 933Exit:\r
934 gBS->RestoreTPL (OldTpl);\r
e237e7ae 935 return Status;\r
936}\r
937\r
938\r
939/**\r
940 Stop controlling the device.\r
941\r
942 @param This The USB mass storage driver binding\r
943 @param Controller The device controller controlled by the driver.\r
944 @param NumberOfChildren The number of children of this device\r
945 @param ChildHandleBuffer The buffer of children handle.\r
946\r
947 @retval EFI_SUCCESS The driver stopped from controlling the device.\r
3e03cb4d 948 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
949 @retval EFI_UNSUPPORTED Block I/O Protocol is not installed on Controller.\r
e237e7ae 950 @retval Others Failed to stop the driver\r
951\r
952**/\r
953EFI_STATUS\r
954EFIAPI\r
955USBMassDriverBindingStop (\r
956 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
957 IN EFI_HANDLE Controller,\r
958 IN UINTN NumberOfChildren,\r
959 IN EFI_HANDLE *ChildHandleBuffer\r
960 )\r
961{\r
962 EFI_STATUS Status;\r
963 USB_MASS_DEVICE *UsbMass;\r
3e03cb4d 964 EFI_USB_IO_PROTOCOL *UsbIo;\r
e237e7ae 965 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
3e03cb4d 966 UINTN Index;\r
967 BOOLEAN AllChildrenStopped;\r
c7e39923 968\r
969 //\r
3e03cb4d 970 // This is a bus driver stop function since multi-lun is supported.\r
971 // There are three kinds of device handles that might be passed:\r
73f8ef8c 972 // 1st is a handle with USB I/O & Block I/O installed (non-multi-lun)\r
3e03cb4d 973 // 2nd is a handle with Device Path & USB I/O installed (multi-lun root)\r
73f8ef8c 974 // 3rd is a handle with Device Path & USB I/O & Block I/O installed (multi-lun).\r
c7e39923 975 //\r
976 if (NumberOfChildren == 0) {\r
977 //\r
978 // A handle without any children, might be 1st and 2nd type.\r
979 //\r
980 Status = gBS->OpenProtocol (\r
981 Controller,\r
982 &gEfiBlockIoProtocolGuid,\r
b16b8bf9 983 (VOID **) &BlockIo,\r
c7e39923 984 This->DriverBindingHandle,\r
985 Controller,\r
986 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
987 );\r
988 \r
989 if (EFI_ERROR(Status)) {\r
990 //\r
73f8ef8c 991 // This is a 2nd type handle(multi-lun root), it needs to close devicepath\r
992 // and usbio protocol.\r
c7e39923 993 //\r
994 gBS->CloseProtocol (\r
995 Controller,\r
996 &gEfiDevicePathProtocolGuid,\r
997 This->DriverBindingHandle,\r
998 Controller\r
999 );\r
73f8ef8c 1000 gBS->CloseProtocol (\r
1001 Controller,\r
1002 &gEfiUsbIoProtocolGuid,\r
1003 This->DriverBindingHandle,\r
1004 Controller\r
1005 );\r
c7e39923 1006 DEBUG ((EFI_D_INFO, "Success to stop multi-lun root handle\n"));\r
1007 return EFI_SUCCESS;\r
1008 }\r
1009 \r
1010 //\r
3e03cb4d 1011 // This is a 1st type handle(non-multi-lun), which only needs to uninstall\r
1012 // Block I/O Protocol, close USB I/O Protocol and free mass device.\r
c7e39923 1013 //\r
d80ed2a7 1014 UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (BlockIo);\r
c7e39923 1015 \r
1016 //\r
1017 // Uninstall Block I/O protocol from the device handle,\r
1018 // then call the transport protocol to stop itself.\r
1019 //\r
39840c50 1020 Status = gBS->UninstallMultipleProtocolInterfaces (\r
c7e39923 1021 Controller,\r
1022 &gEfiBlockIoProtocolGuid,\r
39840c50 1023 &UsbMass->BlockIo,\r
1024 &gEfiDiskInfoProtocolGuid,\r
1025 &UsbMass->DiskInfo,\r
1026 NULL\r
c7e39923 1027 );\r
1028 if (EFI_ERROR (Status)) {\r
1029 return Status;\r
1030 }\r
1031 \r
1032 gBS->CloseProtocol (\r
1033 Controller,\r
1034 &gEfiUsbIoProtocolGuid,\r
1035 This->DriverBindingHandle,\r
1036 Controller\r
1037 );\r
1038 \r
d80ed2a7 1039 UsbMass->Transport->CleanUp (UsbMass->Context);\r
3e03cb4d 1040 FreePool (UsbMass);\r
c7e39923 1041 \r
1042 DEBUG ((EFI_D_INFO, "Success to stop non-multi-lun root handle\n"));\r
1043 return EFI_SUCCESS;\r
1044 } \r
1045\r
1046 //\r
1047 // This is a 3rd type handle(multi-lun), which needs uninstall\r
3e03cb4d 1048 // Block I/O Protocol and Device Path Protocol, close USB I/O Protocol and \r
1049 // free mass device for all children.\r
c7e39923 1050 //\r
1051 AllChildrenStopped = TRUE;\r
1052\r
1053 for (Index = 0; Index < NumberOfChildren; Index++) {\r
1054\r
1055 Status = gBS->OpenProtocol (\r
1056 ChildHandleBuffer[Index],\r
1057 &gEfiBlockIoProtocolGuid,\r
1058 (VOID **) &BlockIo,\r
1059 This->DriverBindingHandle,\r
1060 Controller,\r
1061 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1062 );\r
1063 if (EFI_ERROR (Status)) {\r
1064 AllChildrenStopped = FALSE;\r
7df7393f 1065 DEBUG ((EFI_D_ERROR, "Fail to stop No.%d multi-lun child handle when opening blockio\n", (UINT32)Index));\r
c7e39923 1066 continue;\r
1067 }\r
e237e7ae 1068\r
d80ed2a7 1069 UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (BlockIo);\r
c7e39923 1070\r
1071 gBS->CloseProtocol (\r
3e03cb4d 1072 Controller,\r
1073 &gEfiUsbIoProtocolGuid,\r
1074 This->DriverBindingHandle,\r
1075 ChildHandleBuffer[Index]\r
1076 );\r
c7e39923 1077 \r
1078 Status = gBS->UninstallMultipleProtocolInterfaces (\r
1079 ChildHandleBuffer[Index],\r
1080 &gEfiDevicePathProtocolGuid,\r
1081 UsbMass->DevicePath,\r
1082 &gEfiBlockIoProtocolGuid,\r
1083 &UsbMass->BlockIo,\r
39840c50 1084 &gEfiDiskInfoProtocolGuid,\r
1085 &UsbMass->DiskInfo,\r
c7e39923 1086 NULL\r
1087 );\r
1088 \r
1089 if (EFI_ERROR (Status)) {\r
1090 //\r
3e03cb4d 1091 // Fail to uninstall Block I/O Protocol and Device Path Protocol, so re-open USB I/O Protocol by child.\r
c7e39923 1092 //\r
1093 AllChildrenStopped = FALSE;\r
7df7393f 1094 DEBUG ((EFI_D_ERROR, "Fail to stop No.%d multi-lun child handle when uninstalling blockio and devicepath\n", (UINT32)Index));\r
c7e39923 1095 \r
1096 gBS->OpenProtocol (\r
1097 Controller,\r
1098 &gEfiUsbIoProtocolGuid,\r
b16b8bf9 1099 (VOID **) &UsbIo,\r
c7e39923 1100 This->DriverBindingHandle,\r
1101 ChildHandleBuffer[Index],\r
1102 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
1103 );\r
1104 } else {\r
1105 //\r
3e03cb4d 1106 // Succeed to stop this multi-lun handle, so go on with next child.\r
c7e39923 1107 //\r
1108 if (((Index + 1) == NumberOfChildren) && AllChildrenStopped) {\r
d80ed2a7 1109 UsbMass->Transport->CleanUp (UsbMass->Context);\r
c7e39923 1110 }\r
3e03cb4d 1111 FreePool (UsbMass);\r
c7e39923 1112 }\r
e237e7ae 1113 }\r
1114\r
c7e39923 1115 if (!AllChildrenStopped) {\r
1116 return EFI_DEVICE_ERROR;\r
e237e7ae 1117 }\r
c7e39923 1118 \r
3e03cb4d 1119 DEBUG ((EFI_D_INFO, "Success to stop all %d multi-lun children handles\n", (UINT32) NumberOfChildren));\r
e237e7ae 1120 return EFI_SUCCESS;\r
1121}\r
1122\r
cc5166ff 1123/**\r
3e03cb4d 1124 Entrypoint of USB Mass Storage Driver.\r
1125\r
1126 This function is the entrypoint of USB Mass Storage Driver. It installs Driver Binding\r
1127 Protocol together with Component Name Protocols.\r
cc5166ff 1128\r
3e03cb4d 1129 @param ImageHandle The firmware allocated handle for the EFI image.\r
1130 @param SystemTable A pointer to the EFI System Table.\r
cc5166ff 1131\r
3e03cb4d 1132 @retval EFI_SUCCESS The entry point is executed successfully.\r
cc5166ff 1133\r
1134**/\r
e237e7ae 1135EFI_STATUS\r
1136EFIAPI\r
1137USBMassStorageEntryPoint (\r
1138 IN EFI_HANDLE ImageHandle,\r
1139 IN EFI_SYSTEM_TABLE *SystemTable\r
1140 )\r
e237e7ae 1141{\r
1142 EFI_STATUS Status;\r
1143\r
1144 //\r
1145 // Install driver binding protocol\r
1146 //\r
62b9bb55 1147 Status = EfiLibInstallDriverBindingComponentName2 (\r
e237e7ae 1148 ImageHandle,\r
1149 SystemTable,\r
1150 &gUSBMassDriverBinding,\r
1151 ImageHandle,\r
1152 &gUsbMassStorageComponentName,\r
62b9bb55 1153 &gUsbMassStorageComponentName2\r
e237e7ae 1154 );\r
d80ed2a7 1155 ASSERT_EFI_ERROR (Status);\r
e237e7ae 1156\r
d80ed2a7 1157 return EFI_SUCCESS;\r
e237e7ae 1158}\r