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