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