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