/** Initialize data for device that does not support multiple LUNSs. @param This The Driver Binding Protocol instance. @param Controller The device to initialize. @param Transport Pointer to USB_MASS_TRANSPORT. @param Context Parameter for USB_MASS_DEVICE.Context. @retval EFI_SUCCESS Initialization succeeds. @retval Other Initialization fails. **/ EFI_STATUS UsbMassInitNonLun ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN USB_MASS_TRANSPORT *Transport, IN VOID *Context ) { USB_MASS_DEVICE *UsbMass; EFI_USB_IO_PROTOCOL *UsbIo; EFI_STATUS Status; UsbIo = NULL; UsbMass = AllocateZeroPool (sizeof (USB_MASS_DEVICE)); ASSERT (UsbMass != NULL); Status = gBS->OpenProtocol ( Controller, &gEfiUsbIoProtocolGuid, (VOID **) &UsbIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "UsbMassInitNonLun: OpenUsbIoProtocol By Driver (%r)\n", Status)); goto ON_ERROR; } UsbMass->Signature = USB_MASS_SIGNATURE; UsbMass->Controller = Controller; UsbMass->UsbIo = UsbIo; UsbMass->BlockIo.Media = &UsbMass->BlockIoMedia; UsbMass->BlockIo.Reset = UsbMassReset; UsbMass->BlockIo.ReadBlocks = UsbMassReadBlocks; UsbMass->BlockIo.WriteBlocks = UsbMassWriteBlocks; UsbMass->BlockIo.FlushBlocks = UsbMassFlushBlocks; UsbMass->OpticalStorage = FALSE; UsbMass->Transport = Transport; UsbMass->Context = Context; // // Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol. // Status = UsbMassInitMedia (UsbMass); if ((EFI_ERROR (Status)) && (Status != EFI_NO_MEDIA)) { DEBUG ((EFI_D_ERROR, "UsbMassInitNonLun: UsbMassInitMedia (%r)\n", Status)); goto ON_ERROR; } InitializeDiskInfo (UsbMass); Status = gBS->InstallMultipleProtocolInterfaces ( &Controller, &gEfiBlockIoProtocolGuid, &UsbMass->BlockIo, &gEfiDiskInfoProtocolGuid, &UsbMass->DiskInfo, NULL ); if (EFI_ERROR (Status)) { goto ON_ERROR; } return EFI_SUCCESS; ON_ERROR: if (UsbMass != NULL) { FreePool (UsbMass); } if (UsbIo != NULL) { gBS->CloseProtocol ( Controller, &gEfiUsbIoProtocolGuid, This->DriverBindingHandle, Controller ); } return Status; }
/** Initialize data for device that does not support multiple LUNSs. @param This The Driver Binding Protocol instance. @param Controller The device to initialize. @param Transport Pointer to USB_MASS_TRANSPORT. @param Context Parameter for USB_MASS_DEVICE.Context. @retval EFI_SUCCESS Initialization succeeds. @retval Other Initialization fails. **/ EFI_STATUS UsbMassInitNonLun ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN USB_MASS_TRANSPORT *Transport, IN VOID *Context ) { USB_MASS_DEVICE *UsbMass; EFI_USB_IO_PROTOCOL *UsbIo; EFI_STATUS Status; UsbIo = NULL; UsbMass = AllocateZeroPool (sizeof (USB_MASS_DEVICE)); ASSERT (UsbMass != NULL); Status = gBS->OpenProtocol ( Controller, &gEfiUsbIoProtocolGuid, (VOID **) &UsbIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "UsbMassInitNonLun: OpenUsbIoProtocol By Driver (%r)\n", Status)); goto ON_ERROR; } UsbMass->Signature = USB_MASS_SIGNATURE; UsbMass->Controller = Controller; UsbMass->UsbIo = UsbIo; UsbMass->BlockIo.Media = &UsbMass->BlockIoMedia; UsbMass->BlockIo.Reset = UsbMassReset; UsbMass->BlockIo.ReadBlocks = UsbMassReadBlocks; UsbMass->BlockIo.WriteBlocks = UsbMassWriteBlocks; UsbMass->BlockIo.FlushBlocks = UsbMassFlushBlocks; UsbMass->OpticalStorage = FALSE; UsbMass->Transport = Transport; UsbMass->Context = Context; // // Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol. // Status = UsbMassInitMedia (UsbMass); if (!EFI_ERROR (Status)) { // // According to USB Mass Storage Specification for Bootability, only following // 4 Peripheral Device Types are in spec. // if ((UsbMass->Pdt != USB_PDT_DIRECT_ACCESS) && (UsbMass->Pdt != USB_PDT_CDROM) && (UsbMass->Pdt != USB_PDT_OPTICAL) && (UsbMass->Pdt != USB_PDT_SIMPLE_DIRECT)) { DEBUG ((EFI_D_ERROR, "UsbMassInitNonLun: Found an unsupported peripheral type[%d]\n", UsbMass->Pdt)); goto ON_ERROR; } } else if (Status != EFI_NO_MEDIA){ DEBUG ((EFI_D_ERROR, "UsbMassInitNonLun: UsbMassInitMedia (%r)\n", Status)); goto ON_ERROR; } InitializeDiskInfo (UsbMass); Status = gBS->InstallMultipleProtocolInterfaces ( &Controller, &gEfiBlockIoProtocolGuid, &UsbMass->BlockIo, &gEfiDiskInfoProtocolGuid, &UsbMass->DiskInfo, NULL ); if (EFI_ERROR (Status)) { goto ON_ERROR; } return EFI_SUCCESS; ON_ERROR: if (UsbMass != NULL) { FreePool (UsbMass); } if (UsbIo != NULL) { gBS->CloseProtocol ( Controller, &gEfiUsbIoProtocolGuid, This->DriverBindingHandle, Controller ); } return Status; }
/** Initialize data for device that supports multiple LUNSs. @param This The Driver Binding Protocol instance. @param Controller The device to initialize. @param Transport Pointer to USB_MASS_TRANSPORT. @param Context Parameter for USB_MASS_DEVICE.Context. @param DevicePath The remaining device path. @param MaxLun The max LUN number. @retval EFI_SUCCESS At least one LUN is initialized successfully. @retval EFI_NOT_FOUND Fail to initialize any of multiple LUNs. **/ EFI_STATUS UsbMassInitMultiLun ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN USB_MASS_TRANSPORT *Transport, IN VOID *Context, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN UINT8 MaxLun ) { USB_MASS_DEVICE *UsbMass; EFI_USB_IO_PROTOCOL *UsbIo; DEVICE_LOGICAL_UNIT_DEVICE_PATH LunNode; UINT8 Index; EFI_STATUS Status; EFI_STATUS ReturnStatus; ASSERT (MaxLun > 0); ReturnStatus = EFI_NOT_FOUND; for (Index = 0; Index <= MaxLun; Index++) { DEBUG ((EFI_D_INFO, "UsbMassInitMultiLun: Start to initialize No.%d logic unit\n", Index)); UsbIo = NULL; UsbMass = AllocateZeroPool (sizeof (USB_MASS_DEVICE)); ASSERT (UsbMass != NULL); UsbMass->Signature = USB_MASS_SIGNATURE; UsbMass->UsbIo = UsbIo; UsbMass->BlockIo.Media = &UsbMass->BlockIoMedia; UsbMass->BlockIo.Reset = UsbMassReset; UsbMass->BlockIo.ReadBlocks = UsbMassReadBlocks; UsbMass->BlockIo.WriteBlocks = UsbMassWriteBlocks; UsbMass->BlockIo.FlushBlocks = UsbMassFlushBlocks; UsbMass->OpticalStorage = FALSE; UsbMass->Transport = Transport; UsbMass->Context = Context; UsbMass->Lun = Index; // // Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol. // Status = UsbMassInitMedia (UsbMass); if ((EFI_ERROR (Status)) && (Status != EFI_NO_MEDIA)) { DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: UsbMassInitMedia (%r)\n", Status)); FreePool (UsbMass); continue; } // // Create a device path node for device logic unit, and append it. // LunNode.Header.Type = MESSAGING_DEVICE_PATH; LunNode.Header.SubType = MSG_DEVICE_LOGICAL_UNIT_DP; LunNode.Lun = UsbMass->Lun; SetDevicePathNodeLength (&LunNode.Header, sizeof (LunNode)); UsbMass->DevicePath = AppendDevicePathNode (DevicePath, &LunNode.Header); if (UsbMass->DevicePath == NULL) { DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: failed to create device logic unit device path\n")); Status = EFI_OUT_OF_RESOURCES; FreePool (UsbMass); continue; } InitializeDiskInfo (UsbMass); // // Create a new handle for each LUN, and install Block I/O Protocol and Device Path Protocol. // Status = gBS->InstallMultipleProtocolInterfaces ( &UsbMass->Controller, &gEfiDevicePathProtocolGuid, UsbMass->DevicePath, &gEfiBlockIoProtocolGuid, &UsbMass->BlockIo, &gEfiDiskInfoProtocolGuid, &UsbMass->DiskInfo, NULL ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: InstallMultipleProtocolInterfaces (%r)\n", Status)); FreePool (UsbMass->DevicePath); FreePool (UsbMass); continue; } // // Open USB I/O Protocol by child to setup a parent-child relationship. // Status = gBS->OpenProtocol ( Controller, &gEfiUsbIoProtocolGuid, (VOID **) &UsbIo, This->DriverBindingHandle, UsbMass->Controller, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: OpenUsbIoProtocol By Child (%r)\n", Status)); gBS->UninstallMultipleProtocolInterfaces ( &UsbMass->Controller, &gEfiDevicePathProtocolGuid, UsbMass->DevicePath, &gEfiBlockIoProtocolGuid, &UsbMass->BlockIo, &gEfiDiskInfoProtocolGuid, &UsbMass->DiskInfo, NULL ); FreePool (UsbMass->DevicePath); FreePool (UsbMass); continue; } ReturnStatus = EFI_SUCCESS; DEBUG ((EFI_D_INFO, "UsbMassInitMultiLun: Success to initialize No.%d logic unit\n", Index)); } return ReturnStatus; }
/** Initialize data for device that supports multiple LUNSs. @param This The Driver Binding Protocol instance. @param Controller The device to initialize. @param Transport Pointer to USB_MASS_TRANSPORT. @param Context Parameter for USB_MASS_DEVICE.Context. @param DevicePath The remaining device path. @param MaxLun The max LUN number. @retval EFI_SUCCESS At least one LUN is initialized successfully. @retval EFI_OUT_OF_RESOURCES Out of resource while creating device path node. @retval Other Initialization fails. **/ EFI_STATUS UsbMassInitMultiLun ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN USB_MASS_TRANSPORT *Transport, IN VOID *Context, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN UINT8 MaxLun ) { USB_MASS_DEVICE *UsbMass; EFI_USB_IO_PROTOCOL *UsbIo; DEVICE_LOGICAL_UNIT_DEVICE_PATH LunNode; UINT8 Index; EFI_STATUS Status; ASSERT (MaxLun > 0); for (Index = 0; Index <= MaxLun; Index++) { DEBUG ((EFI_D_INFO, "UsbMassInitMultiLun: Start to initialize No.%d logic unit\n", Index)); UsbIo = NULL; UsbMass = AllocateZeroPool (sizeof (USB_MASS_DEVICE)); ASSERT (UsbMass != NULL); UsbMass->Signature = USB_MASS_SIGNATURE; UsbMass->UsbIo = UsbIo; UsbMass->BlockIo.Media = &UsbMass->BlockIoMedia; UsbMass->BlockIo.Reset = UsbMassReset; UsbMass->BlockIo.ReadBlocks = UsbMassReadBlocks; UsbMass->BlockIo.WriteBlocks = UsbMassWriteBlocks; UsbMass->BlockIo.FlushBlocks = UsbMassFlushBlocks; UsbMass->OpticalStorage = FALSE; UsbMass->Transport = Transport; UsbMass->Context = Context; UsbMass->Lun = Index; // // Initialize the media parameter data for EFI_BLOCK_IO_MEDIA of Block I/O Protocol. // Status = UsbMassInitMedia (UsbMass); if (!EFI_ERROR (Status)) { // // According to USB Mass Storage Specification for Bootability, only following // 4 Peripheral Device Types are in spec. // if ((UsbMass->Pdt != USB_PDT_DIRECT_ACCESS) && (UsbMass->Pdt != USB_PDT_CDROM) && (UsbMass->Pdt != USB_PDT_OPTICAL) && (UsbMass->Pdt != USB_PDT_SIMPLE_DIRECT)) { DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: Found an unsupported peripheral type[%d]\n", UsbMass->Pdt)); goto ON_ERROR; } } else if (Status != EFI_NO_MEDIA){ DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: UsbMassInitMedia (%r)\n", Status)); goto ON_ERROR; } // // Create a device path node for device logic unit, and append it. // LunNode.Header.Type = MESSAGING_DEVICE_PATH; LunNode.Header.SubType = MSG_DEVICE_LOGICAL_UNIT_DP; LunNode.Lun = UsbMass->Lun; SetDevicePathNodeLength (&LunNode.Header, sizeof (LunNode)); UsbMass->DevicePath = AppendDevicePathNode (DevicePath, &LunNode.Header); if (UsbMass->DevicePath == NULL) { DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: failed to create device logic unit device path\n")); Status = EFI_OUT_OF_RESOURCES; goto ON_ERROR; } InitializeDiskInfo (UsbMass); // // Create a new handle for each LUN, and install Block I/O Protocol and Device Path Protocol. // Status = gBS->InstallMultipleProtocolInterfaces ( &UsbMass->Controller, &gEfiDevicePathProtocolGuid, UsbMass->DevicePath, &gEfiBlockIoProtocolGuid, &UsbMass->BlockIo, &gEfiDiskInfoProtocolGuid, &UsbMass->DiskInfo, NULL ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: InstallMultipleProtocolInterfaces (%r)\n", Status)); goto ON_ERROR; } // // Open USB I/O Protocol by child to setup a parent-child relationship. // Status = gBS->OpenProtocol ( Controller, &gEfiUsbIoProtocolGuid, (VOID **) &UsbIo, This->DriverBindingHandle, UsbMass->Controller, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "UsbMassInitMultiLun: OpenUsbIoProtocol By Child (%r)\n", Status)); gBS->UninstallMultipleProtocolInterfaces ( &UsbMass->Controller, &gEfiDevicePathProtocolGuid, UsbMass->DevicePath, &gEfiBlockIoProtocolGuid, &UsbMass->BlockIo, &gEfiDiskInfoProtocolGuid, &UsbMass->DiskInfo, NULL ); goto ON_ERROR; } DEBUG ((EFI_D_INFO, "UsbMassInitMultiLun: Success to initialize No.%d logic unit\n", Index)); } return EFI_SUCCESS; ON_ERROR: if (UsbMass != NULL) { if (UsbMass->DevicePath != NULL) { FreePool (UsbMass->DevicePath); } FreePool (UsbMass); } if (UsbIo != NULL) { gBS->CloseProtocol ( Controller, &gEfiUsbIoProtocolGuid, This->DriverBindingHandle, UsbMass->Controller ); } // // Return EFI_SUCCESS if at least one LUN is initialized successfully. // if (Index > 0) { return EFI_SUCCESS; } else { return Status; } }