• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   The entry point of IScsi driver.
3 
4 Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution.  The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9 
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include "IScsiImpl.h"
16 
17 EFI_DRIVER_BINDING_PROTOCOL gIScsiDriverBinding = {
18   IScsiDriverBindingSupported,
19   IScsiDriverBindingStart,
20   IScsiDriverBindingStop,
21   0xa,
22   NULL,
23   NULL
24 };
25 
26 /**
27   Tests to see if this driver supports the RemainingDevicePath.
28 
29   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
30                                    parameter is ignored by device drivers, and is optional for bus
31                                    drivers. For bus drivers, if this parameter is not NULL, then
32                                    the bus driver must determine if the bus controller specified
33                                    by ControllerHandle and the child controller specified
34                                    by RemainingDevicePath are both supported by this
35                                    bus driver.
36 
37   @retval EFI_SUCCESS              The RemainingDevicePath is supported or NULL.
38   @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
39                                    RemainingDevicePath is not supported by the driver specified by This.
40 **/
41 EFI_STATUS
IScsiIsDevicePathSupported(IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)42 IScsiIsDevicePathSupported (
43   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
44   )
45 {
46   EFI_DEVICE_PATH_PROTOCOL  *CurrentDevicePath;
47 
48   CurrentDevicePath = RemainingDevicePath;
49   if (CurrentDevicePath != NULL) {
50     while (!IsDevicePathEnd (CurrentDevicePath)) {
51       if ((CurrentDevicePath->Type == MESSAGING_DEVICE_PATH) && (CurrentDevicePath->SubType == MSG_ISCSI_DP)) {
52         return EFI_SUCCESS;
53       }
54 
55       CurrentDevicePath = NextDevicePathNode (CurrentDevicePath);
56     }
57 
58     return EFI_UNSUPPORTED;
59   }
60 
61   return EFI_SUCCESS;
62 }
63 
64 /**
65   Tests to see if this driver supports a given controller. If a child device is provided,
66   it further tests to see if this driver supports creating a handle for the specified child device.
67 
68   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
69   @param[in]  ControllerHandle     The handle of the controller to test. This handle
70                                    must support a protocol interface that supplies
71                                    an I/O abstraction to the driver.
72   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.
73                                    This parameter is ignored by device drivers, and is optional for bus drivers.
74 
75 
76   @retval EFI_SUCCESS              The device specified by ControllerHandle and
77                                    RemainingDevicePath is supported by the driver specified by This.
78   @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
79                                    RemainingDevicePath is already being managed by the driver
80                                    specified by This.
81   @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
82                                    RemainingDevicePath is already being managed by a different
83                                    driver or an application that requires exclusive acces.
84                                    Currently not implemented.
85   @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
86                                    RemainingDevicePath is not supported by the driver specified by This.
87 **/
88 EFI_STATUS
89 EFIAPI
IScsiDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)90 IScsiDriverBindingSupported (
91   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
92   IN EFI_HANDLE                   ControllerHandle,
93   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
94   )
95 {
96   EFI_STATUS                Status;
97 
98   Status = gBS->OpenProtocol (
99                   ControllerHandle,
100                   &gEfiCallerIdGuid,
101                   NULL,
102                   This->DriverBindingHandle,
103                   ControllerHandle,
104                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
105                   );
106   if (!EFI_ERROR (Status)) {
107     return EFI_ALREADY_STARTED;
108   }
109 
110   Status = gBS->OpenProtocol (
111                   ControllerHandle,
112                   &gEfiTcp4ServiceBindingProtocolGuid,
113                   NULL,
114                   This->DriverBindingHandle,
115                   ControllerHandle,
116                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
117                   );
118   if (EFI_ERROR (Status)) {
119     return EFI_UNSUPPORTED;
120   }
121 
122   Status = IScsiIsDevicePathSupported (RemainingDevicePath);
123   if (EFI_ERROR (Status)) {
124     return EFI_UNSUPPORTED;
125   }
126 
127   if (IScsiDhcpIsConfigured (ControllerHandle)) {
128     Status = gBS->OpenProtocol (
129                     ControllerHandle,
130                     &gEfiDhcp4ServiceBindingProtocolGuid,
131                     NULL,
132                     This->DriverBindingHandle,
133                     ControllerHandle,
134                     EFI_OPEN_PROTOCOL_TEST_PROTOCOL
135                     );
136     if (EFI_ERROR (Status)) {
137       return EFI_UNSUPPORTED;
138     }
139   }
140 
141   return EFI_SUCCESS;
142 }
143 
144 /**
145   Start this driver on ControllerHandle.
146 
147   The Start() function is designed to be invoked from the EFI boot service ConnectController().
148   As a result, much of the error checking on the parameters to Start() has been moved into this
149   common boot service. It is legal to call Start() from other locations, but the following calling
150   restrictions must be followed or the system behavior will not be deterministic.
151   1. ControllerHandle must be a valid EFI_HANDLE.
152   2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
153      EFI_DEVICE_PATH_PROTOCOL.
154   3. Prior to calling Start(), the Supported() function for the driver specified by This must
155      have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
156 
157   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
158   @param[in]  ControllerHandle     The handle of the controller to start. This handle
159                                    must support a protocol interface that supplies
160                                    an I/O abstraction to the driver.
161   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.
162                                    This parameter is ignored by device drivers, and is optional for bus drivers.
163 
164   @retval EFI_SUCCESS              The device was started.
165   @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.
166                                    Currently not implemented.
167   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
168   @retval Others                   The driver failded to start the device.
169 **/
170 EFI_STATUS
171 EFIAPI
IScsiDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)172 IScsiDriverBindingStart (
173   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
174   IN EFI_HANDLE                   ControllerHandle,
175   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
176   )
177 {
178   EFI_STATUS        Status;
179   ISCSI_DRIVER_DATA *Private;
180   VOID              *Interface;
181 
182   Private = IScsiCreateDriverData (This->DriverBindingHandle, ControllerHandle);
183   if (Private == NULL) {
184     return EFI_OUT_OF_RESOURCES;
185   }
186 
187   //
188   // Create a underlayer child instance, but not need to configure it. Just open ChildHandle
189   // via BY_DRIVER. That is, establishing the relationship between ControllerHandle and ChildHandle.
190   // Therefore, when DisconnectController(), especially VLAN virtual controller handle,
191   // IScsiDriverBindingStop() will be called.
192   //
193   Status = NetLibCreateServiceChild (
194              ControllerHandle,
195              This->DriverBindingHandle,
196              &gEfiTcp4ServiceBindingProtocolGuid,
197              &Private->ChildHandle
198              );
199 
200   if (EFI_ERROR (Status)) {
201     goto ON_ERROR;
202   }
203 
204   Status = gBS->OpenProtocol (
205                   Private->ChildHandle,
206                   &gEfiTcp4ProtocolGuid,
207                   &Interface,
208                   This->DriverBindingHandle,
209                   ControllerHandle,
210                   EFI_OPEN_PROTOCOL_BY_DRIVER
211                   );
212   if (EFI_ERROR (Status)) {
213     goto ON_ERROR;
214   }
215 
216   //
217   // Always install private protocol no matter what happens later. We need to
218   // keep the relationship between ControllerHandle and ChildHandle.
219   //
220   Status = gBS->InstallProtocolInterface (
221                   &ControllerHandle,
222                   &gEfiCallerIdGuid,
223                   EFI_NATIVE_INTERFACE,
224                   &Private->IScsiIdentifier
225                   );
226   if (EFI_ERROR (Status)) {
227     goto ON_ERROR;
228   }
229 
230   //
231   // Try to add a port configuration page for this controller.
232   //
233   IScsiConfigUpdateForm (This->DriverBindingHandle, ControllerHandle, TRUE);
234 
235   //
236   // Get the iSCSI configuration data of this controller.
237   //
238   Status = IScsiGetConfigData (Private);
239   if (EFI_ERROR (Status)) {
240     goto ON_ERROR;
241   }
242   //
243   // Try to login and create an iSCSI session according to the configuration.
244   //
245   Status = IScsiSessionLogin (Private);
246   if (Status == EFI_MEDIA_CHANGED) {
247     //
248     // The specified target is not available and the redirection information is
249     // got, login the session again with the updated target address.
250     //
251     Status = IScsiSessionLogin (Private);
252   }
253 
254   if (EFI_ERROR (Status)) {
255     goto ON_ERROR;
256   }
257   //
258   // Duplicate the Session's tcp connection device path. The source port field
259   // will be set to zero as one iSCSI session is comprised of several iSCSI
260   // connections.
261   //
262   Private->DevicePath = IScsiGetTcpConnDevicePath (Private);
263   if (Private->DevicePath == NULL) {
264     goto ON_ERROR;
265   }
266   //
267   // Install the updated device path onto the ExtScsiPassThruHandle.
268   //
269   Status = gBS->InstallProtocolInterface (
270                   &Private->ExtScsiPassThruHandle,
271                   &gEfiDevicePathProtocolGuid,
272                   EFI_NATIVE_INTERFACE,
273                   Private->DevicePath
274                   );
275   if (EFI_ERROR (Status)) {
276     goto ON_ERROR;
277   }
278 
279   //
280   // ISCSI children should share the default Tcp child, just open the default Tcp child via BY_CHILD_CONTROLLER.
281   //
282   Status = gBS->OpenProtocol (
283                   Private->ChildHandle, /// Default Tcp child
284                   &gEfiTcp4ProtocolGuid,
285                   &Interface,
286                   This->DriverBindingHandle,
287                   Private->ExtScsiPassThruHandle,
288                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
289                   );
290   if (EFI_ERROR (Status)) {
291     gBS->UninstallMultipleProtocolInterfaces (
292            Private->ExtScsiPassThruHandle,
293            &gEfiExtScsiPassThruProtocolGuid,
294            &Private->IScsiExtScsiPassThru,
295            &gEfiDevicePathProtocolGuid,
296            Private->DevicePath,
297            NULL
298            );
299 
300     goto ON_ERROR;
301   }
302 
303   //
304   // Update/Publish the iSCSI Boot Firmware Table.
305   //
306   IScsiPublishIbft ();
307 
308   return EFI_SUCCESS;
309 
310 ON_ERROR:
311 
312   IScsiSessionAbort (&Private->Session);
313 
314   return Status;
315 }
316 
317 /**
318   Stop this driver on ControllerHandle.
319 
320   Release the control of this controller and remove the IScsi functions. The Stop()
321   function is designed to be invoked from the EFI boot service DisconnectController().
322   As a result, much of the error checking on the parameters to Stop() has been moved
323   into this common boot service. It is legal to call Stop() from other locations,
324   but the following calling restrictions must be followed or the system behavior will not be deterministic.
325   1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
326      same driver's Start() function.
327   2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
328      EFI_HANDLE. In addition, all of these handles must have been created in this driver's
329      Start() function, and the Start() function must have called OpenProtocol() on
330      ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
331 
332   @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
333   @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
334                                 support a bus specific I/O protocol for the driver
335                                 to use to stop the device.
336   @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.Not used.
337   @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
338                                 if NumberOfChildren is 0.Not used.
339 
340   @retval EFI_SUCCESS           The device was stopped.
341   @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
342 **/
343 EFI_STATUS
344 EFIAPI
IScsiDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer OPTIONAL)345 IScsiDriverBindingStop (
346   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
347   IN EFI_HANDLE                   ControllerHandle,
348   IN UINTN                        NumberOfChildren,
349   IN EFI_HANDLE                   *ChildHandleBuffer OPTIONAL
350   )
351 {
352   EFI_HANDLE                      IScsiController;
353   EFI_STATUS                      Status;
354   ISCSI_PRIVATE_PROTOCOL          *IScsiIdentifier;
355   ISCSI_DRIVER_DATA               *Private;
356   EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru;
357   ISCSI_CONNECTION                *Conn;
358 
359   if (NumberOfChildren != 0) {
360     //
361     // We should have only one child.
362     //
363     Status = gBS->OpenProtocol (
364                     ChildHandleBuffer[0],
365                     &gEfiExtScsiPassThruProtocolGuid,
366                     (VOID **) &PassThru,
367                     This->DriverBindingHandle,
368                     ControllerHandle,
369                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
370                     );
371     if (EFI_ERROR (Status)) {
372       return EFI_DEVICE_ERROR;
373     }
374 
375     Private = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (PassThru);
376     Conn    = NET_LIST_HEAD (&Private->Session.Conns, ISCSI_CONNECTION, Link);
377 
378     //
379     // Previously the TCP4 protocol is opened BY_CHILD_CONTROLLER. Just close
380     // the protocol here but not uninstall the device path protocol and
381     // EXT SCSI PASS THRU protocol installed on ExtScsiPassThruHandle.
382     //
383     gBS->CloseProtocol (
384            Private->ChildHandle,
385            &gEfiTcp4ProtocolGuid,
386            Private->Image,
387            Private->ExtScsiPassThruHandle
388            );
389 
390     gBS->CloseProtocol (
391           Conn->Tcp4Io.Handle,
392           &gEfiTcp4ProtocolGuid,
393           Private->Image,
394           Private->ExtScsiPassThruHandle
395           );
396 
397     return EFI_SUCCESS;
398   }
399   //
400   // Get the handle of the controller we are controling.
401   //
402   IScsiController = NetLibGetNicHandle (ControllerHandle, &gEfiTcp4ProtocolGuid);
403 
404   Status = gBS->OpenProtocol (
405                   IScsiController,
406                   &gEfiCallerIdGuid,
407                   (VOID **)&IScsiIdentifier,
408                   This->DriverBindingHandle,
409                   ControllerHandle,
410                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
411                   );
412   if (EFI_ERROR (Status)) {
413     return EFI_DEVICE_ERROR;
414   }
415 
416   Private = ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier);
417 
418   if (Private->ChildHandle != NULL) {
419     Status = gBS->CloseProtocol (
420                     Private->ChildHandle,
421                     &gEfiTcp4ProtocolGuid,
422                     This->DriverBindingHandle,
423                     IScsiController
424                     );
425 
426     ASSERT (!EFI_ERROR (Status));
427 
428     Status = NetLibDestroyServiceChild (
429                IScsiController,
430                This->DriverBindingHandle,
431                &gEfiTcp4ServiceBindingProtocolGuid,
432                Private->ChildHandle
433                );
434     ASSERT (!EFI_ERROR (Status));
435   }
436 
437   IScsiConfigUpdateForm (This->DriverBindingHandle, IScsiController, FALSE);
438 
439   //
440   // Uninstall the private protocol.
441   //
442   gBS->UninstallProtocolInterface (
443         IScsiController,
444         &gEfiCallerIdGuid,
445         &Private->IScsiIdentifier
446         );
447 
448   //
449   // Update the iSCSI Boot Firware Table.
450   //
451   IScsiPublishIbft ();
452 
453   IScsiSessionAbort (&Private->Session);
454   IScsiCleanDriverData (Private);
455 
456   return EFI_SUCCESS;
457 }
458 
459 /**
460   Unloads an image(the iSCSI driver).
461 
462   @param[in]  ImageHandle       Handle that identifies the image to be unloaded.
463 
464   @retval EFI_SUCCESS           The image has been unloaded.
465   @retval Others                Other errors as indicated.
466 **/
467 EFI_STATUS
468 EFIAPI
EfiIScsiUnload(IN EFI_HANDLE ImageHandle)469 EfiIScsiUnload (
470   IN EFI_HANDLE  ImageHandle
471   )
472 {
473   EFI_STATUS                        Status;
474   UINTN                             DeviceHandleCount;
475   EFI_HANDLE                        *DeviceHandleBuffer;
476   UINTN                             Index;
477   EFI_COMPONENT_NAME_PROTOCOL       *ComponentName;
478   EFI_COMPONENT_NAME2_PROTOCOL      *ComponentName2;
479 
480   //
481   // Try to disonnect the driver from the devices it's controlling.
482   //
483   Status = gBS->LocateHandleBuffer (
484                   AllHandles,
485                   NULL,
486                   NULL,
487                   &DeviceHandleCount,
488                   &DeviceHandleBuffer
489                   );
490   if (EFI_ERROR (Status)) {
491     return Status;
492   }
493 
494   for (Index = 0; Index < DeviceHandleCount; Index++) {
495     Status = IScsiTestManagedDevice (
496                DeviceHandleBuffer[Index],
497                gIScsiDriverBinding.DriverBindingHandle,
498                &gEfiTcp4ProtocolGuid
499                );
500     if (EFI_ERROR (Status)) {
501       continue;
502     }
503     Status = gBS->DisconnectController (
504                     DeviceHandleBuffer[Index],
505                     gIScsiDriverBinding.DriverBindingHandle,
506                     NULL
507                     );
508     if (EFI_ERROR (Status)) {
509       goto ON_EXIT;
510     }
511   }
512 
513   //
514   // Unload the iSCSI configuration form.
515   //
516   Status = IScsiConfigFormUnload (gIScsiDriverBinding.DriverBindingHandle);
517   if (EFI_ERROR (Status)) {
518     goto ON_EXIT;
519   }
520 
521   //
522   // Uninstall the ComponentName and ComponentName2 protocol from iSCSI4 driver binding handle
523   // if it has been installed.
524   //
525   Status = gBS->HandleProtocol (
526                   gIScsiDriverBinding.DriverBindingHandle,
527                   &gEfiComponentNameProtocolGuid,
528                   (VOID **) &ComponentName
529                   );
530   if (!EFI_ERROR (Status)) {
531     Status = gBS->UninstallMultipleProtocolInterfaces (
532            gIScsiDriverBinding.DriverBindingHandle,
533            &gEfiComponentNameProtocolGuid,
534            ComponentName,
535            NULL
536            );
537     if (EFI_ERROR (Status)) {
538       goto ON_EXIT;
539     }
540   }
541 
542   Status = gBS->HandleProtocol (
543                   gIScsiDriverBinding.DriverBindingHandle,
544                   &gEfiComponentName2ProtocolGuid,
545                   (VOID **) &ComponentName2
546                   );
547   if (!EFI_ERROR (Status)) {
548     gBS->UninstallMultipleProtocolInterfaces (
549            gIScsiDriverBinding.DriverBindingHandle,
550            &gEfiComponentName2ProtocolGuid,
551            ComponentName2,
552            NULL
553            );
554     if (EFI_ERROR (Status)) {
555       goto ON_EXIT;
556     }
557   }
558 
559   Status = gBS->UninstallMultipleProtocolInterfaces (
560                   ImageHandle,
561                   &gEfiDriverBindingProtocolGuid,
562                   &gIScsiDriverBinding,
563                   &gEfiIScsiInitiatorNameProtocolGuid,
564                   &gIScsiInitiatorName,
565                   NULL
566                   );
567 ON_EXIT:
568 
569   if (DeviceHandleBuffer != NULL) {
570     FreePool (DeviceHandleBuffer);
571   }
572 
573   return Status;
574 }
575 
576 /**
577   This is the declaration of an EFI image entry point. This entry point is
578   the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
579   both device drivers and bus drivers. It initialize the global variables and
580   publish the driver binding protocol.
581 
582   @param[in]   ImageHandle      The firmware allocated handle for the UEFI image.
583   @param[in]   SystemTable      A pointer to the EFI System Table.
584 
585   @retval EFI_SUCCESS           The operation completed successfully.
586   @retval EFI_ACCESS_DENIED     EFI_ISCSI_INITIATOR_NAME_PROTOCOL was installed unexpectedly.
587   @retval Others                Other errors as indicated.
588 **/
589 EFI_STATUS
590 EFIAPI
IScsiDriverEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)591 IScsiDriverEntryPoint (
592   IN EFI_HANDLE         ImageHandle,
593   IN EFI_SYSTEM_TABLE   *SystemTable
594   )
595 {
596   EFI_STATUS                         Status;
597   EFI_ISCSI_INITIATOR_NAME_PROTOCOL  *IScsiInitiatorName;
598 
599   //
600   // There should be only one EFI_ISCSI_INITIATOR_NAME_PROTOCOL.
601   //
602   Status = gBS->LocateProtocol (
603                    &gEfiIScsiInitiatorNameProtocolGuid,
604                    NULL,
605                    (VOID**) &IScsiInitiatorName
606                    );
607 
608   if (!EFI_ERROR (Status)) {
609     return EFI_ACCESS_DENIED;
610   }
611 
612   //
613   // Initialize the EFI Driver Library
614   //
615   Status = EfiLibInstallDriverBindingComponentName2 (
616              ImageHandle,
617              SystemTable,
618              &gIScsiDriverBinding,
619              ImageHandle,
620              &gIScsiComponentName,
621              &gIScsiComponentName2
622            );
623 
624   if (!EFI_ERROR (Status)) {
625     //
626     // Install the iSCSI Initiator Name Protocol.
627     //
628     Status = gBS->InstallProtocolInterface (
629                     &ImageHandle,
630                     &gEfiIScsiInitiatorNameProtocolGuid,
631                     EFI_NATIVE_INTERFACE,
632                     &gIScsiInitiatorName
633                     );
634     if (EFI_ERROR (Status)) {
635       gBS->UninstallMultipleProtocolInterfaces (
636             ImageHandle,
637             &gEfiDriverBindingProtocolGuid,
638             &gIScsiDriverBinding,
639             &gEfiComponentName2ProtocolGuid,
640             &gIScsiComponentName2,
641             &gEfiComponentNameProtocolGuid,
642             &gIScsiComponentName,
643             NULL
644             );
645       return Status;
646     }
647 
648     //
649     // Initialize the configuration form of iSCSI.
650     //
651     Status = IScsiConfigFormInit ();
652     if (EFI_ERROR (Status)) {
653       gBS->UninstallMultipleProtocolInterfaces (
654             ImageHandle,
655             &gEfiDriverBindingProtocolGuid,
656             &gIScsiDriverBinding,
657             &gEfiComponentName2ProtocolGuid,
658             &gIScsiComponentName2,
659             &gEfiComponentNameProtocolGuid,
660             &gIScsiComponentName,
661             &gEfiIScsiInitiatorNameProtocolGuid,
662             &gIScsiInitiatorName,
663             NULL
664             );
665     }
666   }
667   return Status;
668 }
669 
670