]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.c
Update auth-variable and secure boot UI driver to support only time-based PK, KEK...
[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
c7e39923 339\r
340 Media = &UsbMass->BlockIoMedia;\r
341\r
342 //\r
d80ed2a7 343 // Fields of EFI_BLOCK_IO_MEDIA are defined in UEFI 2.0 spec,\r
344 // section for Block I/O Protocol.\r
c7e39923 345 //\r
346 Media->MediaPresent = FALSE;\r
347 Media->LogicalPartition = FALSE;\r
348 Media->ReadOnly = FALSE;\r
349 Media->WriteCaching = FALSE;\r
350 Media->IoAlign = 0;\r
351 Media->MediaId = 1;\r
352\r
19bc8527 353 Status = UsbBootGetParams (UsbMass);\r
c7e39923 354 return Status;\r
355}\r
356\r
cc5166ff 357/**\r
d80ed2a7 358 Initilize the USB Mass Storage transport.\r
359\r
360 This function tries to find the matching USB Mass Storage transport\r
361 protocol for USB device. If found, initializes the matching transport.\r
cc5166ff 362\r
363 @param This The USB mass driver's driver binding.\r
364 @param Controller The device to test.\r
365 @param Transport The pointer to pointer to USB_MASS_TRANSPORT.\r
3e03cb4d 366 @param Context The parameter for USB_MASS_DEVICE.Context.\r
cc5166ff 367 @param MaxLun Get the MaxLun if is BOT dev.\r
368\r
d7db0902 369 @retval EFI_SUCCESS The initialization is successful.\r
d80ed2a7 370 @retval EFI_UNSUPPORTED No matching transport protocol is found.\r
d7db0902 371 @retval Others Failed to initialize dev.\r
cc5166ff 372\r
373**/\r
c7e39923 374EFI_STATUS\r
375UsbMassInitTransport (\r
376 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
377 IN EFI_HANDLE Controller,\r
378 OUT USB_MASS_TRANSPORT **Transport,\r
379 OUT VOID **Context,\r
380 OUT UINT8 *MaxLun\r
381 )\r
382{\r
383 EFI_USB_IO_PROTOCOL *UsbIo;\r
384 EFI_USB_INTERFACE_DESCRIPTOR Interface;\r
385 UINT8 Index;\r
386 EFI_STATUS Status;\r
387 \r
388 Status = gBS->OpenProtocol (\r
389 Controller,\r
390 &gEfiUsbIoProtocolGuid,\r
b16b8bf9 391 (VOID **) &UsbIo,\r
c7e39923 392 This->DriverBindingHandle,\r
393 Controller,\r
394 EFI_OPEN_PROTOCOL_BY_DRIVER\r
395 );\r
396\r
397 if (EFI_ERROR (Status)) {\r
c7e39923 398 return Status;\r
399 }\r
400 \r
401 Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);\r
402 if (EFI_ERROR (Status)) {\r
c7e39923 403 goto ON_EXIT;\r
404 }\r
405 \r
406 Status = EFI_UNSUPPORTED;\r
407\r
d80ed2a7 408 //\r
409 // Traverse the USB_MASS_TRANSPORT arrary and try to find the\r
410 // matching transport protocol.\r
411 // If not found, return EFI_UNSUPPORTED.\r
412 // If found, execute USB_MASS_TRANSPORT.Init() to initialize the transport context.\r
413 //\r
db0bd81c 414 for (Index = 0; Index < USB_MASS_TRANSPORT_COUNT; Index++) {\r
c7e39923 415 *Transport = mUsbMassTransport[Index];\r
416\r
417 if (Interface.InterfaceProtocol == (*Transport)->Protocol) {\r
418 Status = (*Transport)->Init (UsbIo, Context);\r
419 break;\r
420 }\r
421 }\r
422\r
423 if (EFI_ERROR (Status)) {\r
c7e39923 424 goto ON_EXIT;\r
425 }\r
426\r
427 //\r
d80ed2a7 428 // For BOT device, try to get its max LUN. \r
429 // If max LUN is 0, then it is a non-lun device.\r
430 // Otherwise, it is a multi-lun device.\r
c7e39923 431 //\r
432 if ((*Transport)->Protocol == USB_MASS_STORE_BOT) {\r
433 (*Transport)->GetMaxLun (*Context, MaxLun);\r
c7e39923 434 }\r
435\r
436ON_EXIT:\r
437 gBS->CloseProtocol (\r
438 Controller,\r
439 &gEfiUsbIoProtocolGuid,\r
440 This->DriverBindingHandle,\r
441 Controller\r
442 );\r
443 return Status; \r
444}\r
445\r
cc5166ff 446/**\r
3e03cb4d 447 Initialize data for device that supports multiple LUNSs.\r
cc5166ff 448\r
3e03cb4d 449 @param This The Driver Binding Protocol instance.\r
450 @param Controller The device to initialize.\r
451 @param Transport Pointer to USB_MASS_TRANSPORT.\r
452 @param Context Parameter for USB_MASS_DEVICE.Context.\r
453 @param DevicePath The remaining device path.\r
454 @param MaxLun The max LUN number.\r
cc5166ff 455\r
3e03cb4d 456 @retval EFI_SUCCESS At least one LUN is initialized successfully.\r
457 @retval EFI_OUT_OF_RESOURCES Out of resource while creating device path node.\r
458 @retval Other Initialization fails.\r
cc5166ff 459\r
460**/\r
c7e39923 461EFI_STATUS\r
462UsbMassInitMultiLun (\r
3e03cb4d 463 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
c7e39923 464 IN EFI_HANDLE Controller,\r
465 IN USB_MASS_TRANSPORT *Transport,\r
466 IN VOID *Context,\r
467 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
468 IN UINT8 MaxLun\r
469 )\r
470{\r
471 USB_MASS_DEVICE *UsbMass;\r
472 EFI_USB_IO_PROTOCOL *UsbIo;\r
473 DEVICE_LOGICAL_UNIT_DEVICE_PATH LunNode;\r
474 UINT8 Index;\r
475 EFI_STATUS Status;\r
476\r
477 ASSERT (MaxLun > 0);\r
478\r
479 for (Index = 0; Index <= MaxLun; Index++) { \r
480\r
481 DEBUG ((EFI_D_INFO, "UsbMassInitMultiLun: Start to initialize No.%d logic unit\n", Index));\r
482 \r
483 UsbIo = NULL;\r
484 UsbMass = AllocateZeroPool (sizeof (USB_MASS_DEVICE));\r
3e03cb4d 485 ASSERT (UsbMass != NULL);\r
c7e39923 486 \r
487 UsbMass->Signature = USB_MASS_SIGNATURE;\r
488 UsbMass->UsbIo = UsbIo;\r
489 UsbMass->BlockIo.Media = &UsbMass->BlockIoMedia;\r
490 UsbMass->BlockIo.Reset = UsbMassReset;\r
491 UsbMass->BlockIo.ReadBlocks = UsbMassReadBlocks;\r
492 UsbMass->BlockIo.WriteBlocks = UsbMassWriteBlocks;\r
493 UsbMass->BlockIo.FlushBlocks = UsbMassFlushBlocks;\r
494 UsbMass->OpticalStorage = FALSE;\r
495 UsbMass->Transport = Transport;\r
496 UsbMass->Context = Context;\r
497 UsbMass->Lun = Index;\r
498 \r
499 //\r
3e03cb4d 500 // Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol.\r
c7e39923 501 //\r
502 Status = UsbMassInitMedia (UsbMass);\r
503 if (!EFI_ERROR (Status)) {\r
3e03cb4d 504 //\r
505 // According to USB Mass Storage Specification for Bootability, only following\r
506 // 4 Peripheral Device Types are in spec.\r
507 //\r
c7e39923 508 if ((UsbMass->Pdt != USB_PDT_DIRECT_ACCESS) && \r
509 (UsbMass->Pdt != USB_PDT_CDROM) &&\r
510 (UsbMass->Pdt != USB_PDT_OPTICAL) && \r
511 (UsbMass->Pdt != USB_PDT_SIMPLE_DIRECT)) {\r
512 DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: Found an unsupported peripheral type[%d]\n", UsbMass->Pdt));\r
513 goto ON_ERROR;\r
514 }\r
515 } else if (Status != EFI_NO_MEDIA){\r
516 DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: UsbMassInitMedia (%r)\n", Status));\r
517 goto ON_ERROR;\r
518 }\r
519\r
520 //\r
3e03cb4d 521 // Create a device path node for device logic unit, and append it.\r
c7e39923 522 //\r
523 LunNode.Header.Type = MESSAGING_DEVICE_PATH;\r
524 LunNode.Header.SubType = MSG_DEVICE_LOGICAL_UNIT_DP;\r
525 LunNode.Lun = UsbMass->Lun;\r
526 \r
527 SetDevicePathNodeLength (&LunNode.Header, sizeof (LunNode));\r
528 \r
529 UsbMass->DevicePath = AppendDevicePathNode (DevicePath, &LunNode.Header);\r
530 \r
531 if (UsbMass->DevicePath == NULL) {\r
532 DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: failed to create device logic unit device path\n"));\r
533 \r
534 Status = EFI_OUT_OF_RESOURCES;\r
535 goto ON_ERROR;\r
536 }\r
537\r
39840c50 538 InitializeDiskInfo (UsbMass);\r
539\r
c7e39923 540 //\r
3e03cb4d 541 // Create a new handle for each LUN, and install Block I/O Protocol and Device Path Protocol.\r
c7e39923 542 //\r
543 Status = gBS->InstallMultipleProtocolInterfaces (\r
544 &UsbMass->Controller,\r
545 &gEfiDevicePathProtocolGuid,\r
546 UsbMass->DevicePath,\r
547 &gEfiBlockIoProtocolGuid,\r
548 &UsbMass->BlockIo,\r
39840c50 549 &gEfiDiskInfoProtocolGuid,\r
550 &UsbMass->DiskInfo,\r
c7e39923 551 NULL\r
552 );\r
553 \r
554 if (EFI_ERROR (Status)) {\r
555 DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: InstallMultipleProtocolInterfaces (%r)\n", Status));\r
556 goto ON_ERROR;\r
557 }\r
558\r
559 //\r
3e03cb4d 560 // Open USB I/O Protocol by child to setup a parent-child relationship.\r
c7e39923 561 //\r
562 Status = gBS->OpenProtocol (\r
563 Controller,\r
564 &gEfiUsbIoProtocolGuid,\r
b16b8bf9 565 (VOID **) &UsbIo,\r
c7e39923 566 This->DriverBindingHandle,\r
567 UsbMass->Controller,\r
568 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
569 );\r
570\r
571 if (EFI_ERROR (Status)) {\r
572 DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: OpenUsbIoProtocol By Child (%r)\n", Status));\r
573 gBS->UninstallMultipleProtocolInterfaces (\r
574 &UsbMass->Controller,\r
575 &gEfiDevicePathProtocolGuid,\r
576 UsbMass->DevicePath,\r
577 &gEfiBlockIoProtocolGuid,\r
578 &UsbMass->BlockIo,\r
39840c50 579 &gEfiDiskInfoProtocolGuid,\r
580 &UsbMass->DiskInfo,\r
c7e39923 581 NULL\r
582 );\r
583 goto ON_ERROR;\r
584 }\r
585 \r
586 DEBUG ((EFI_D_INFO, "UsbMassInitMultiLun: Success to initialize No.%d logic unit\n", Index));\r
587 }\r
588 \r
589 return EFI_SUCCESS;\r
590\r
591ON_ERROR:\r
c7e39923 592 if (UsbMass != NULL) {\r
81464cf1 593 if (UsbMass->DevicePath != NULL) {\r
594 FreePool (UsbMass->DevicePath);\r
595 }\r
3e03cb4d 596 FreePool (UsbMass);\r
c7e39923 597 }\r
598 if (UsbIo != NULL) {\r
599 gBS->CloseProtocol (\r
600 Controller,\r
601 &gEfiUsbIoProtocolGuid,\r
602 This->DriverBindingHandle,\r
603 UsbMass->Controller\r
604 );\r
605 }\r
606\r
607 //\r
3e03cb4d 608 // Return EFI_SUCCESS if at least one LUN is initialized successfully.\r
c7e39923 609 //\r
610 if (Index > 0) {\r
611 return EFI_SUCCESS; \r
612 } else {\r
613 return Status;\r
614 } \r
615}\r
616\r
cc5166ff 617/**\r
3e03cb4d 618 Initialize data for device that does not support multiple LUNSs.\r
cc5166ff 619\r
3e03cb4d 620 @param This The Driver Binding Protocol instance.\r
621 @param Controller The device to initialize.\r
622 @param Transport Pointer to USB_MASS_TRANSPORT.\r
623 @param Context Parameter for USB_MASS_DEVICE.Context.\r
cc5166ff 624\r
3e03cb4d 625 @retval EFI_SUCCESS Initialization succeeds.\r
cc5166ff 626 @retval Other Initialization fails.\r
627\r
628**/\r
c7e39923 629EFI_STATUS\r
630UsbMassInitNonLun (\r
631 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
632 IN EFI_HANDLE Controller,\r
633 IN USB_MASS_TRANSPORT *Transport,\r
634 IN VOID *Context\r
635 )\r
636{\r
637 USB_MASS_DEVICE *UsbMass;\r
638 EFI_USB_IO_PROTOCOL *UsbIo;\r
639 EFI_STATUS Status;\r
640\r
641 UsbIo = NULL;\r
642 UsbMass = AllocateZeroPool (sizeof (USB_MASS_DEVICE));\r
3e03cb4d 643 ASSERT (UsbMass != NULL);\r
644\r
c7e39923 645 Status = gBS->OpenProtocol (\r
646 Controller,\r
647 &gEfiUsbIoProtocolGuid,\r
b16b8bf9 648 (VOID **) &UsbIo,\r
c7e39923 649 This->DriverBindingHandle,\r
650 Controller,\r
651 EFI_OPEN_PROTOCOL_BY_DRIVER\r
652 );\r
653\r
654 if (EFI_ERROR (Status)) {\r
655 DEBUG ((EFI_D_ERROR, "UsbMassInitNonLun: OpenUsbIoProtocol By Driver (%r)\n", Status));\r
656 goto ON_ERROR;\r
657 }\r
658 \r
659 UsbMass->Signature = USB_MASS_SIGNATURE;\r
660 UsbMass->Controller = Controller;\r
661 UsbMass->UsbIo = UsbIo;\r
662 UsbMass->BlockIo.Media = &UsbMass->BlockIoMedia;\r
663 UsbMass->BlockIo.Reset = UsbMassReset;\r
664 UsbMass->BlockIo.ReadBlocks = UsbMassReadBlocks;\r
665 UsbMass->BlockIo.WriteBlocks = UsbMassWriteBlocks;\r
666 UsbMass->BlockIo.FlushBlocks = UsbMassFlushBlocks;\r
667 UsbMass->OpticalStorage = FALSE;\r
668 UsbMass->Transport = Transport;\r
669 UsbMass->Context = Context;\r
670 \r
671 //\r
3e03cb4d 672 // Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol.\r
c7e39923 673 //\r
674 Status = UsbMassInitMedia (UsbMass);\r
675 if (!EFI_ERROR (Status)) {\r
3e03cb4d 676 //\r
677 // According to USB Mass Storage Specification for Bootability, only following\r
678 // 4 Peripheral Device Types are in spec.\r
679 //\r
c7e39923 680 if ((UsbMass->Pdt != USB_PDT_DIRECT_ACCESS) && \r
681 (UsbMass->Pdt != USB_PDT_CDROM) &&\r
682 (UsbMass->Pdt != USB_PDT_OPTICAL) && \r
683 (UsbMass->Pdt != USB_PDT_SIMPLE_DIRECT)) {\r
684 DEBUG ((EFI_D_ERROR, "UsbMassInitNonLun: Found an unsupported peripheral type[%d]\n", UsbMass->Pdt));\r
685 goto ON_ERROR;\r
686 }\r
687 } else if (Status != EFI_NO_MEDIA){\r
688 DEBUG ((EFI_D_ERROR, "UsbMassInitNonLun: UsbMassInitMedia (%r)\n", Status));\r
689 goto ON_ERROR;\r
690 }\r
691 \r
39840c50 692 InitializeDiskInfo (UsbMass);\r
693\r
694 Status = gBS->InstallMultipleProtocolInterfaces (\r
c7e39923 695 &Controller,\r
696 &gEfiBlockIoProtocolGuid,\r
39840c50 697 &UsbMass->BlockIo,\r
698 &gEfiDiskInfoProtocolGuid,\r
699 &UsbMass->DiskInfo,\r
700 NULL\r
c7e39923 701 );\r
702 if (EFI_ERROR (Status)) {\r
703 goto ON_ERROR;\r
704 }\r
705\r
706 return EFI_SUCCESS;\r
707\r
708ON_ERROR:\r
709 if (UsbMass != NULL) {\r
3e03cb4d 710 FreePool (UsbMass);\r
c7e39923 711 }\r
73f8ef8c 712 if (UsbIo != NULL) {\r
713 gBS->CloseProtocol (\r
714 Controller,\r
715 &gEfiUsbIoProtocolGuid,\r
716 This->DriverBindingHandle,\r
717 Controller\r
718 );\r
719 }\r
c7e39923 720 return Status; \r
721}\r
722\r
e237e7ae 723\r
724/**\r
725 Check whether the controller is a supported USB mass storage.\r
726\r
d80ed2a7 727 @param This The USB mass storage driver binding protocol.\r
728 @param Controller The controller handle to check.\r
729 @param RemainingDevicePath The remaining device path.\r
e237e7ae 730\r
d80ed2a7 731 @retval EFI_SUCCESS The driver supports this controller.\r
732 @retval other This device isn't supported.\r
e237e7ae 733\r
734**/\r
735EFI_STATUS\r
736EFIAPI\r
737USBMassDriverBindingSupported (\r
738 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
739 IN EFI_HANDLE Controller,\r
740 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
741 )\r
742{\r
743 EFI_USB_IO_PROTOCOL *UsbIo;\r
744 EFI_USB_INTERFACE_DESCRIPTOR Interface;\r
745 USB_MASS_TRANSPORT *Transport;\r
746 EFI_STATUS Status;\r
d80ed2a7 747 UINTN Index;\r
e237e7ae 748\r
e237e7ae 749 Status = gBS->OpenProtocol (\r
750 Controller,\r
751 &gEfiUsbIoProtocolGuid,\r
c52fa98c 752 (VOID **) &UsbIo,\r
e237e7ae 753 This->DriverBindingHandle,\r
754 Controller,\r
755 EFI_OPEN_PROTOCOL_BY_DRIVER\r
756 );\r
757 if (EFI_ERROR (Status)) {\r
758 return Status;\r
759 }\r
760\r
761 //\r
d80ed2a7 762 // Get the interface descriptor to check the USB class and find a transport\r
e237e7ae 763 // protocol handler.\r
764 //\r
765 Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);\r
766 if (EFI_ERROR (Status)) {\r
767 goto ON_EXIT;\r
768 }\r
769\r
770 Status = EFI_UNSUPPORTED;\r
771\r
772 if (Interface.InterfaceClass != USB_MASS_STORE_CLASS) {\r
773 goto ON_EXIT;\r
774 }\r
775\r
d80ed2a7 776 //\r
777 // Traverse the USB_MASS_TRANSPORT arrary and try to find the\r
778 // matching transport method.\r
779 // If not found, return EFI_UNSUPPORTED.\r
780 // If found, execute USB_MASS_TRANSPORT.Init() to initialize the transport context.\r
781 //\r
db0bd81c 782 for (Index = 0; Index < USB_MASS_TRANSPORT_COUNT; Index++) {\r
e237e7ae 783 Transport = mUsbMassTransport[Index];\r
784 if (Interface.InterfaceProtocol == Transport->Protocol) {\r
c7e39923 785 Status = Transport->Init (UsbIo, NULL);\r
e237e7ae 786 break;\r
787 }\r
788 }\r
789\r
e237e7ae 790ON_EXIT:\r
791 gBS->CloseProtocol (\r
d80ed2a7 792 Controller,\r
793 &gEfiUsbIoProtocolGuid,\r
794 This->DriverBindingHandle,\r
795 Controller\r
796 );\r
e237e7ae 797\r
798 return Status;\r
799}\r
800\r
e237e7ae 801/**\r
d80ed2a7 802 Starts the USB mass storage device with this driver.\r
e237e7ae 803\r
d80ed2a7 804 This function consumes USB I/O Portocol, intializes USB mass storage device,\r
805 installs Block I/O Protocol, and submits Asynchronous Interrupt\r
806 Transfer to manage the USB mass storage device.\r
807\r
3e03cb4d 808 @param This The USB mass storage driver binding protocol.\r
809 @param Controller The USB mass storage device to start on\r
810 @param RemainingDevicePath The remaining device path.\r
e237e7ae 811\r
d80ed2a7 812 @retval EFI_SUCCESS This driver supports this device.\r
813 @retval EFI_UNSUPPORTED This driver does not support this device.\r
814 @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.\r
815 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.\r
816 @retval EFI_ALREADY_STARTED This driver has been started.\r
e237e7ae 817\r
818**/\r
819EFI_STATUS\r
820EFIAPI\r
821USBMassDriverBindingStart (\r
822 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
823 IN EFI_HANDLE Controller,\r
824 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
825 )\r
826{\r
e237e7ae 827 USB_MASS_TRANSPORT *Transport;\r
c7e39923 828 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
829 VOID *Context;\r
830 UINT8 MaxLun;\r
e237e7ae 831 EFI_STATUS Status;\r
73f8ef8c 832 EFI_USB_IO_PROTOCOL *UsbIo; \r
15cc67e6 833 EFI_TPL OldTpl;\r
834\r
835 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
836\r
c7e39923 837 Transport = NULL;\r
838 Context = NULL;\r
839 MaxLun = 0;\r
e237e7ae 840\r
c7e39923 841 Status = UsbMassInitTransport (This, Controller, &Transport, &Context, &MaxLun);\r
e237e7ae 842\r
843 if (EFI_ERROR (Status)) {\r
c7e39923 844 DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: UsbMassInitTransport (%r)\n", Status));\r
15cc67e6 845 goto Exit;\r
e237e7ae 846 }\r
c7e39923 847 if (MaxLun == 0) {\r
848 //\r
3e03cb4d 849 // Initialize data for device that does not support multiple LUNSs.\r
c7e39923 850 //\r
3e03cb4d 851 Status = UsbMassInitNonLun (This, Controller, Transport, Context);\r
c7e39923 852 if (EFI_ERROR (Status)) { \r
853 DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: UsbMassInitNonLun (%r)\n", Status));\r
854 }\r
855 } else {\r
856 //\r
3e03cb4d 857 // Open device path to prepare for appending Device Logic Unit node.\r
c7e39923 858 //\r
859 Status = gBS->OpenProtocol (\r
860 Controller,\r
861 &gEfiDevicePathProtocolGuid,\r
862 (VOID **) &DevicePath,\r
863 This->DriverBindingHandle,\r
864 Controller,\r
865 EFI_OPEN_PROTOCOL_BY_DRIVER\r
866 );\r
867 \r
868 if (EFI_ERROR (Status)) {\r
869 DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: OpenDevicePathProtocol By Driver (%r)\n", Status));\r
15cc67e6 870 goto Exit;\r
e237e7ae 871 }\r
e237e7ae 872\r
73f8ef8c 873 Status = gBS->OpenProtocol (\r
874 Controller,\r
875 &gEfiUsbIoProtocolGuid,\r
876 (VOID **) &UsbIo,\r
877 This->DriverBindingHandle,\r
878 Controller,\r
879 EFI_OPEN_PROTOCOL_BY_DRIVER\r
880 );\r
881 \r
882 if (EFI_ERROR (Status)) {\r
883 DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: OpenUsbIoProtocol By Driver (%r)\n", Status));\r
884 gBS->CloseProtocol (\r
885 Controller,\r
886 &gEfiDevicePathProtocolGuid,\r
887 This->DriverBindingHandle,\r
888 Controller\r
889 );\r
15cc67e6 890 goto Exit;\r
73f8ef8c 891 }\r
892\r
c7e39923 893 //\r
3e03cb4d 894 // Initialize data for device that supports multiple LUNSs.\r
895 // EFI_SUCCESS is returned if at least 1 LUN is initialized successfully.\r
c7e39923 896 //\r
d80ed2a7 897 Status = UsbMassInitMultiLun (This, Controller, Transport, Context, DevicePath, MaxLun);\r
c7e39923 898 if (EFI_ERROR (Status)) {\r
73f8ef8c 899 gBS->CloseProtocol (\r
900 Controller,\r
901 &gEfiDevicePathProtocolGuid,\r
902 This->DriverBindingHandle,\r
903 Controller\r
904 );\r
905 gBS->CloseProtocol (\r
906 Controller,\r
907 &gEfiUsbIoProtocolGuid,\r
908 This->DriverBindingHandle,\r
909 Controller\r
910 );\r
c7e39923 911 DEBUG ((EFI_D_ERROR, "USBMassDriverBindingStart: UsbMassInitMultiLun (%r) with Maxlun=%d\n", Status, MaxLun));\r
912 }\r
e237e7ae 913 }\r
15cc67e6 914Exit:\r
915 gBS->RestoreTPL (OldTpl);\r
e237e7ae 916 return Status;\r
917}\r
918\r
919\r
920/**\r
921 Stop controlling the device.\r
922\r
923 @param This The USB mass storage driver binding\r
924 @param Controller The device controller controlled by the driver.\r
925 @param NumberOfChildren The number of children of this device\r
926 @param ChildHandleBuffer The buffer of children handle.\r
927\r
928 @retval EFI_SUCCESS The driver stopped from controlling the device.\r
3e03cb4d 929 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
930 @retval EFI_UNSUPPORTED Block I/O Protocol is not installed on Controller.\r
e237e7ae 931 @retval Others Failed to stop the driver\r
932\r
933**/\r
934EFI_STATUS\r
935EFIAPI\r
936USBMassDriverBindingStop (\r
937 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
938 IN EFI_HANDLE Controller,\r
939 IN UINTN NumberOfChildren,\r
940 IN EFI_HANDLE *ChildHandleBuffer\r
941 )\r
942{\r
943 EFI_STATUS Status;\r
944 USB_MASS_DEVICE *UsbMass;\r
3e03cb4d 945 EFI_USB_IO_PROTOCOL *UsbIo;\r
e237e7ae 946 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
3e03cb4d 947 UINTN Index;\r
948 BOOLEAN AllChildrenStopped;\r
c7e39923 949\r
950 //\r
3e03cb4d 951 // This is a bus driver stop function since multi-lun is supported.\r
952 // There are three kinds of device handles that might be passed:\r
73f8ef8c 953 // 1st is a handle with USB I/O & Block I/O installed (non-multi-lun)\r
3e03cb4d 954 // 2nd is a handle with Device Path & USB I/O installed (multi-lun root)\r
73f8ef8c 955 // 3rd is a handle with Device Path & USB I/O & Block I/O installed (multi-lun).\r
c7e39923 956 //\r
957 if (NumberOfChildren == 0) {\r
958 //\r
959 // A handle without any children, might be 1st and 2nd type.\r
960 //\r
961 Status = gBS->OpenProtocol (\r
962 Controller,\r
963 &gEfiBlockIoProtocolGuid,\r
b16b8bf9 964 (VOID **) &BlockIo,\r
c7e39923 965 This->DriverBindingHandle,\r
966 Controller,\r
967 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
968 );\r
969 \r
970 if (EFI_ERROR(Status)) {\r
971 //\r
73f8ef8c 972 // This is a 2nd type handle(multi-lun root), it needs to close devicepath\r
973 // and usbio protocol.\r
c7e39923 974 //\r
975 gBS->CloseProtocol (\r
976 Controller,\r
977 &gEfiDevicePathProtocolGuid,\r
978 This->DriverBindingHandle,\r
979 Controller\r
980 );\r
73f8ef8c 981 gBS->CloseProtocol (\r
982 Controller,\r
983 &gEfiUsbIoProtocolGuid,\r
984 This->DriverBindingHandle,\r
985 Controller\r
986 );\r
c7e39923 987 DEBUG ((EFI_D_INFO, "Success to stop multi-lun root handle\n"));\r
988 return EFI_SUCCESS;\r
989 }\r
990 \r
991 //\r
3e03cb4d 992 // This is a 1st type handle(non-multi-lun), which only needs to uninstall\r
993 // Block I/O Protocol, close USB I/O Protocol and free mass device.\r
c7e39923 994 //\r
d80ed2a7 995 UsbMass = USB_MASS_DEVICE_FROM_BLOCK_IO (BlockIo);\r
c7e39923 996 \r
997 //\r
998 // Uninstall Block I/O protocol from the device handle,\r
999 // then call the transport protocol to stop itself.\r
1000 //\r
39840c50 1001 Status = gBS->UninstallMultipleProtocolInterfaces (\r
c7e39923 1002 Controller,\r
1003 &gEfiBlockIoProtocolGuid,\r
39840c50 1004 &UsbMass->BlockIo,\r
1005 &gEfiDiskInfoProtocolGuid,\r
1006 &UsbMass->DiskInfo,\r
1007 NULL\r
c7e39923 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
39840c50 1065 &gEfiDiskInfoProtocolGuid,\r
1066 &UsbMass->DiskInfo,\r
c7e39923 1067 NULL\r
1068 );\r
1069 \r
1070 if (EFI_ERROR (Status)) {\r
1071 //\r
3e03cb4d 1072 // Fail to uninstall Block I/O Protocol and Device Path Protocol, so re-open USB I/O Protocol by child.\r
c7e39923 1073 //\r
1074 AllChildrenStopped = FALSE;\r
7df7393f 1075 DEBUG ((EFI_D_ERROR, "Fail to stop No.%d multi-lun child handle when uninstalling blockio and devicepath\n", (UINT32)Index));\r
c7e39923 1076 \r
1077 gBS->OpenProtocol (\r
1078 Controller,\r
1079 &gEfiUsbIoProtocolGuid,\r
b16b8bf9 1080 (VOID **) &UsbIo,\r
c7e39923 1081 This->DriverBindingHandle,\r
1082 ChildHandleBuffer[Index],\r
1083 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
1084 );\r
1085 } else {\r
1086 //\r
3e03cb4d 1087 // Succeed to stop this multi-lun handle, so go on with next child.\r
c7e39923 1088 //\r
1089 if (((Index + 1) == NumberOfChildren) && AllChildrenStopped) {\r
d80ed2a7 1090 UsbMass->Transport->CleanUp (UsbMass->Context);\r
c7e39923 1091 }\r
3e03cb4d 1092 FreePool (UsbMass);\r
c7e39923 1093 }\r
e237e7ae 1094 }\r
1095\r
c7e39923 1096 if (!AllChildrenStopped) {\r
1097 return EFI_DEVICE_ERROR;\r
e237e7ae 1098 }\r
c7e39923 1099 \r
3e03cb4d 1100 DEBUG ((EFI_D_INFO, "Success to stop all %d multi-lun children handles\n", (UINT32) NumberOfChildren));\r
e237e7ae 1101 return EFI_SUCCESS;\r
1102}\r
1103\r
cc5166ff 1104/**\r
3e03cb4d 1105 Entrypoint of USB Mass Storage Driver.\r
1106\r
1107 This function is the entrypoint of USB Mass Storage Driver. It installs Driver Binding\r
1108 Protocol together with Component Name Protocols.\r
cc5166ff 1109\r
3e03cb4d 1110 @param ImageHandle The firmware allocated handle for the EFI image.\r
1111 @param SystemTable A pointer to the EFI System Table.\r
cc5166ff 1112\r
3e03cb4d 1113 @retval EFI_SUCCESS The entry point is executed successfully.\r
cc5166ff 1114\r
1115**/\r
e237e7ae 1116EFI_STATUS\r
1117EFIAPI\r
1118USBMassStorageEntryPoint (\r
1119 IN EFI_HANDLE ImageHandle,\r
1120 IN EFI_SYSTEM_TABLE *SystemTable\r
1121 )\r
e237e7ae 1122{\r
1123 EFI_STATUS Status;\r
1124\r
1125 //\r
1126 // Install driver binding protocol\r
1127 //\r
62b9bb55 1128 Status = EfiLibInstallDriverBindingComponentName2 (\r
e237e7ae 1129 ImageHandle,\r
1130 SystemTable,\r
1131 &gUSBMassDriverBinding,\r
1132 ImageHandle,\r
1133 &gUsbMassStorageComponentName,\r
62b9bb55 1134 &gUsbMassStorageComponentName2\r
e237e7ae 1135 );\r
d80ed2a7 1136 ASSERT_EFI_ERROR (Status);\r
e237e7ae 1137\r
d80ed2a7 1138 return EFI_SUCCESS;\r
e237e7ae 1139}\r