]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/IScsiDxe/IScsiDriver.c
MdePkg, NetworkPkg: Refine the coding style.
[mirror_edk2.git] / NetworkPkg / IScsiDxe / IScsiDriver.c
CommitLineData
4c5a5e0c 1/** @file\r
2 The entry point of IScsi driver.\r
3\r
e590d29f 4Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>\r
4c5a5e0c 5This program and the accompanying materials\r
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
13**/\r
14\r
15#include "IScsiImpl.h"\r
16\r
6879581d 17EFI_DRIVER_BINDING_PROTOCOL gIScsiIp4DriverBinding = {\r
18 IScsiIp4DriverBindingSupported,\r
19 IScsiIp4DriverBindingStart,\r
20 IScsiIp4DriverBindingStop,\r
21 0xa,\r
22 NULL,\r
23 NULL\r
24};\r
25\r
26EFI_DRIVER_BINDING_PROTOCOL gIScsiIp6DriverBinding = {\r
27 IScsiIp6DriverBindingSupported,\r
28 IScsiIp6DriverBindingStart,\r
29 IScsiIp6DriverBindingStop,\r
4c5a5e0c 30 0xa,\r
31 NULL,\r
32 NULL\r
33};\r
34\r
216f7970 35EFI_GUID gIScsiV4PrivateGuid = ISCSI_V4_PRIVATE_GUID;\r
36EFI_GUID gIScsiV6PrivateGuid = ISCSI_V6_PRIVATE_GUID;\r
4c5a5e0c 37ISCSI_PRIVATE_DATA *mPrivate = NULL;\r
38\r
39/**\r
6879581d 40 Tests to see if this driver supports the RemainingDevicePath. \r
4c5a5e0c 41\r
42 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
43 parameter is ignored by device drivers, and is optional for bus \r
44 drivers. For bus drivers, if this parameter is not NULL, then \r
45 the bus driver must determine if the bus controller specified \r
46 by ControllerHandle and the child controller specified \r
47 by RemainingDevicePath are both supported by this \r
48 bus driver.\r
49\r
50 @retval EFI_SUCCESS The RemainingDevicePath is supported or NULL.\r
51 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
52 RemainingDevicePath is not supported by the driver specified by This.\r
53**/\r
54EFI_STATUS\r
55IScsiIsDevicePathSupported (\r
56 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
57 )\r
58{\r
59 EFI_DEVICE_PATH_PROTOCOL *CurrentDevicePath;\r
60\r
61 CurrentDevicePath = RemainingDevicePath;\r
62 if (CurrentDevicePath != NULL) {\r
63 while (!IsDevicePathEnd (CurrentDevicePath)) {\r
64 if ((CurrentDevicePath->Type == MESSAGING_DEVICE_PATH) && (CurrentDevicePath->SubType == MSG_ISCSI_DP)) {\r
65 return EFI_SUCCESS;\r
66 }\r
67\r
68 CurrentDevicePath = NextDevicePathNode (CurrentDevicePath);\r
69 }\r
70\r
71 return EFI_UNSUPPORTED;\r
72 }\r
73\r
74 return EFI_SUCCESS;\r
75}\r
76\r
8873b174
YT
77/**\r
78 Check whether an iSCSI HBA adapter already installs an AIP instance with\r
79 network boot policy matching the value specified in PcdIScsiAIPNetworkBootPolicy.\r
80 If yes, return EFI_SUCCESS.\r
81\r
82 @retval EFI_SUCCESS Found an AIP with matching network boot policy.\r
83 @retval EFI_NOT_FOUND AIP is unavailable or the network boot policy\r
84 not matched.\r
85**/\r
86EFI_STATUS\r
87IScsiCheckAip (\r
88 )\r
89{\r
90 UINTN AipHandleCount;\r
91 EFI_HANDLE *AipHandleBuffer;\r
92 UINTN AipIndex;\r
93 EFI_ADAPTER_INFORMATION_PROTOCOL *Aip;\r
94 EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtScsiPassThru;\r
95 EFI_GUID *InfoTypesBuffer;\r
96 UINTN InfoTypeBufferCount;\r
97 UINTN TypeIndex;\r
98 VOID *InfoBlock;\r
99 UINTN InfoBlockSize;\r
100 BOOLEAN Supported;\r
101 EFI_ADAPTER_INFO_NETWORK_BOOT *NetworkBoot;\r
102 EFI_STATUS Status;\r
103 UINT8 NetworkBootPolicy;\r
104\r
105 //\r
106 // Check any AIP instances exist in system.\r
107 //\r
5346adbb
JW
108 AipHandleCount = 0;\r
109 AipHandleBuffer = NULL;\r
8873b174
YT
110 Status = gBS->LocateHandleBuffer (\r
111 ByProtocol,\r
112 &gEfiAdapterInformationProtocolGuid,\r
113 NULL,\r
114 &AipHandleCount,\r
115 &AipHandleBuffer\r
116 );\r
117 if (EFI_ERROR (Status) || AipHandleCount == 0) {\r
118 return EFI_NOT_FOUND;\r
119 }\r
120\r
5346adbb
JW
121 ASSERT (AipHandleBuffer != NULL);\r
122\r
8873b174
YT
123 InfoBlock = NULL;\r
124\r
125 for (AipIndex = 0; AipIndex < AipHandleCount; AipIndex++) {\r
126 Status = gBS->HandleProtocol (\r
127 AipHandleBuffer[AipIndex],\r
128 &gEfiAdapterInformationProtocolGuid,\r
129 (VOID *) &Aip\r
130 );\r
131 ASSERT_EFI_ERROR (Status);\r
132 ASSERT (Aip != NULL);\r
133\r
134 Status = gBS->HandleProtocol (\r
135 AipHandleBuffer[AipIndex],\r
136 &gEfiExtScsiPassThruProtocolGuid,\r
137 (VOID *) &ExtScsiPassThru\r
138 );\r
139 if (EFI_ERROR (Status) || ExtScsiPassThru == NULL) {\r
140 continue;\r
141 }\r
142\r
143 InfoTypesBuffer = NULL;\r
144 InfoTypeBufferCount = 0;\r
145 Status = Aip->GetSupportedTypes (Aip, &InfoTypesBuffer, &InfoTypeBufferCount);\r
146 if (EFI_ERROR (Status) || InfoTypesBuffer == NULL) {\r
147 continue;\r
148 }\r
149 //\r
150 // Check whether the AIP instance has Network boot information block.\r
151 //\r
152 Supported = FALSE;\r
153 for (TypeIndex = 0; TypeIndex < InfoTypeBufferCount; TypeIndex++) {\r
154 if (CompareGuid (&InfoTypesBuffer[TypeIndex], &gEfiAdapterInfoNetworkBootGuid)) {\r
155 Supported = TRUE;\r
156 break;\r
157 }\r
158 }\r
159\r
160 FreePool (InfoTypesBuffer);\r
161 if (!Supported) {\r
162 continue;\r
163 }\r
164\r
165 //\r
166 // We now have network boot information block.\r
167 //\r
168 InfoBlock = NULL;\r
169 InfoBlockSize = 0;\r
170 Status = Aip->GetInformation (Aip, &gEfiAdapterInfoNetworkBootGuid, &InfoBlock, &InfoBlockSize);\r
171 if (EFI_ERROR (Status) || InfoBlock == NULL) {\r
172 continue;\r
173 }\r
174\r
175 //\r
176 // Check whether the network boot policy matches.\r
177 //\r
178 NetworkBoot = (EFI_ADAPTER_INFO_NETWORK_BOOT *) InfoBlock;\r
179 NetworkBootPolicy = PcdGet8 (PcdIScsiAIPNetworkBootPolicy);\r
180\r
181 if (NetworkBootPolicy == STOP_UEFI_ISCSI_IF_HBA_INSTALL_AIP) {\r
182 Status = EFI_SUCCESS;\r
183 goto Exit;\r
184 }\r
185 if (((NetworkBootPolicy & STOP_UEFI_ISCSI_IF_AIP_SUPPORT_IP4) != 0 &&\r
186 !NetworkBoot->iScsiIpv4BootCapablity) ||\r
187 ((NetworkBootPolicy & STOP_UEFI_ISCSI_IF_AIP_SUPPORT_IP6) != 0 &&\r
188 !NetworkBoot->iScsiIpv6BootCapablity) ||\r
189 ((NetworkBootPolicy & STOP_UEFI_ISCSI_IF_AIP_SUPPORT_OFFLOAD) != 0 &&\r
190 !NetworkBoot->OffloadCapability) ||\r
191 ((NetworkBootPolicy & STOP_UEFI_ISCSI_IF_AIP_SUPPORT_MPIO) != 0 &&\r
192 !NetworkBoot->iScsiMpioCapability) ||\r
193 ((NetworkBootPolicy & STOP_UEFI_ISCSI_IF_AIP_CONFIGURED_IP4) != 0 &&\r
194 !NetworkBoot->iScsiIpv4Boot) ||\r
195 ((NetworkBootPolicy & STOP_UEFI_ISCSI_IF_AIP_CONFIGURED_IP6) != 0 &&\r
196 !NetworkBoot->iScsiIpv6Boot)) {\r
197 FreePool (InfoBlock);\r
198 continue;\r
199 }\r
200\r
201 Status = EFI_SUCCESS;\r
202 goto Exit;\r
203 }\r
204\r
205 Status = EFI_NOT_FOUND;\r
206\r
207Exit:\r
208 if (InfoBlock != NULL) {\r
209 FreePool (InfoBlock);\r
210 }\r
211 if (AipHandleBuffer != NULL) {\r
212 FreePool (AipHandleBuffer);\r
213 }\r
214 return Status;\r
215}\r
4c5a5e0c 216\r
217/**\r
6879581d 218 Tests to see if this driver supports a given controller. This is the worker function for\r
219 IScsiIp4(6)DriverBindingSupported.\r
4c5a5e0c 220\r
221 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
222 @param[in] ControllerHandle The handle of the controller to test. This handle \r
223 must support a protocol interface that supplies \r
224 an I/O abstraction to the driver.\r
225 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
226 parameter is ignored by device drivers, and is optional for bus \r
227 drivers. For bus drivers, if this parameter is not NULL, then \r
228 the bus driver must determine if the bus controller specified \r
229 by ControllerHandle and the child controller specified \r
230 by RemainingDevicePath are both supported by this \r
231 bus driver.\r
6879581d 232 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.\r
4c5a5e0c 233\r
234 @retval EFI_SUCCESS The device specified by ControllerHandle and\r
235 RemainingDevicePath is supported by the driver specified by This.\r
236 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
237 RemainingDevicePath is already being managed by the driver\r
238 specified by This.\r
4c5a5e0c 239 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
240 RemainingDevicePath is not supported by the driver specified by This.\r
241**/\r
242EFI_STATUS\r
243EFIAPI\r
6879581d 244IScsiSupported (\r
4c5a5e0c 245 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
246 IN EFI_HANDLE ControllerHandle,\r
6879581d 247 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL,\r
248 IN UINT8 IpVersion\r
4c5a5e0c 249 )\r
250{\r
251 EFI_STATUS Status;\r
6879581d 252 EFI_GUID *IScsiServiceBindingGuid;\r
253 EFI_GUID *TcpServiceBindingGuid;\r
b7cc5bf1 254 EFI_GUID *DhcpServiceBindingGuid;\r
4c5a5e0c 255\r
6879581d 256 if (IpVersion == IP_VERSION_4) {\r
257 IScsiServiceBindingGuid = &gIScsiV4PrivateGuid;\r
258 TcpServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;\r
b7cc5bf1 259 DhcpServiceBindingGuid = &gEfiDhcp4ServiceBindingProtocolGuid;\r
4c5a5e0c 260 } else {\r
6879581d 261 IScsiServiceBindingGuid = &gIScsiV6PrivateGuid;\r
262 TcpServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;\r
b7cc5bf1 263 DhcpServiceBindingGuid = &gEfiDhcp6ServiceBindingProtocolGuid;\r
4c5a5e0c 264 }\r
265\r
266 Status = gBS->OpenProtocol (\r
267 ControllerHandle,\r
6879581d 268 IScsiServiceBindingGuid,\r
4c5a5e0c 269 NULL,\r
270 This->DriverBindingHandle,\r
271 ControllerHandle,\r
272 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
273 );\r
274 if (!EFI_ERROR (Status)) {\r
6879581d 275 return EFI_ALREADY_STARTED;\r
b7cc5bf1
WJ
276 }\r
277\r
278 Status = gBS->OpenProtocol (\r
279 ControllerHandle,\r
280 TcpServiceBindingGuid,\r
281 NULL,\r
282 This->DriverBindingHandle,\r
283 ControllerHandle,\r
284 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
285 );\r
286 if (EFI_ERROR (Status)) {\r
287 return EFI_UNSUPPORTED;\r
288 }\r
289\r
290 Status = IScsiIsDevicePathSupported (RemainingDevicePath);\r
291 if (EFI_ERROR (Status)) {\r
292 return EFI_UNSUPPORTED;\r
293 }\r
294\r
295 if (IScsiDhcpIsConfigured (ControllerHandle, IpVersion)) {\r
4c5a5e0c 296 Status = gBS->OpenProtocol (\r
297 ControllerHandle,\r
b7cc5bf1 298 DhcpServiceBindingGuid,\r
4c5a5e0c 299 NULL,\r
300 This->DriverBindingHandle,\r
301 ControllerHandle,\r
302 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
303 );\r
b7cc5bf1
WJ
304 if (EFI_ERROR (Status)) {\r
305 return EFI_UNSUPPORTED;\r
4c5a5e0c 306 }\r
307 }\r
b7cc5bf1
WJ
308 \r
309 return EFI_SUCCESS;\r
4c5a5e0c 310}\r
311\r
312\r
313/**\r
314 Start to manage the controller. This is the worker function for\r
6879581d 315 IScsiIp4(6)DriverBindingStart.\r
4c5a5e0c 316\r
317 @param[in] Image Handle of the image.\r
318 @param[in] ControllerHandle Handle of the controller.\r
6879581d 319 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.\r
4c5a5e0c 320\r
6879581d 321 @retval EFI_SUCCES This driver was started.\r
4c5a5e0c 322 @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
323 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
324 @retval EFI_NOT_FOUND There is no sufficient information to establish\r
325 the iScsi session.\r
7c275b3c 326 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
e590d29f
ZL
327 @retval EFI_DEVICE_ERROR Failed to get TCP connection device path.\r
328 @retval EFI_ACCESS_DENIED The protocol could not be removed from the Handle\r
329 because its interfaces are being used.\r
4c5a5e0c 330\r
331**/\r
332EFI_STATUS\r
333IScsiStart (\r
334 IN EFI_HANDLE Image,\r
335 IN EFI_HANDLE ControllerHandle,\r
336 IN UINT8 IpVersion\r
337 )\r
338{\r
339 EFI_STATUS Status;\r
340 ISCSI_DRIVER_DATA *Private;\r
341 LIST_ENTRY *Entry;\r
342 LIST_ENTRY *NextEntry;\r
343 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
344 ISCSI_SESSION *Session;\r
345 UINT8 Index;\r
346 EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExistIScsiExtScsiPassThru;\r
347 ISCSI_DRIVER_DATA *ExistPrivate;\r
348 UINT8 *AttemptConfigOrder;\r
349 UINTN AttemptConfigOrderSize;\r
350 UINT8 BootSelected;\r
351 EFI_HANDLE *HandleBuffer;\r
352 UINTN NumberOfHandles;\r
353 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
354 EFI_GUID *IScsiPrivateGuid;\r
355 EFI_GUID *TcpServiceBindingGuid;\r
356 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];\r
357 BOOLEAN NeedUpdate;\r
358 VOID *Interface;\r
359 EFI_GUID *ProtocolGuid;\r
8873b174 360 UINT8 NetworkBootPolicy;\r
a2d59ef2 361 ISCSI_SESSION_CONFIG_NVDATA *NvData;\r
4c5a5e0c 362\r
363 //\r
364 // Test to see if iSCSI driver supports the given controller.\r
365 //\r
366\r
367 if (IpVersion == IP_VERSION_4) {\r
216f7970 368 IScsiPrivateGuid = &gIScsiV4PrivateGuid;\r
4c5a5e0c 369 TcpServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;\r
370 ProtocolGuid = &gEfiTcp4ProtocolGuid;\r
371 } else if (IpVersion == IP_VERSION_6) {\r
216f7970 372 IScsiPrivateGuid = &gIScsiV6PrivateGuid;\r
4c5a5e0c 373 TcpServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;\r
374 ProtocolGuid = &gEfiTcp6ProtocolGuid;\r
375 } else {\r
376 return EFI_INVALID_PARAMETER;\r
377 }\r
378\r
379 Status = gBS->OpenProtocol (\r
380 ControllerHandle,\r
381 IScsiPrivateGuid,\r
382 NULL,\r
383 Image,\r
384 ControllerHandle,\r
385 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
386 );\r
387 if (!EFI_ERROR (Status)) {\r
388 return EFI_ALREADY_STARTED;\r
389 }\r
390\r
391 Status = gBS->OpenProtocol (\r
392 ControllerHandle,\r
393 TcpServiceBindingGuid,\r
394 NULL,\r
395 Image,\r
396 ControllerHandle,\r
397 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
398 );\r
399 if (EFI_ERROR (Status)) {\r
400 return EFI_UNSUPPORTED;\r
401 }\r
402\r
8873b174
YT
403 NetworkBootPolicy = PcdGet8 (PcdIScsiAIPNetworkBootPolicy);\r
404 if (NetworkBootPolicy != ALWAYS_USE_UEFI_ISCSI_AND_IGNORE_AIP) {\r
405 //\r
406 // Check existing iSCSI AIP.\r
407 //\r
408 Status = IScsiCheckAip ();\r
409 if (!EFI_ERROR (Status)) {\r
410 //\r
411 // Find iSCSI AIP with specified network boot policy. return EFI_ABORTED.\r
412 //\r
413 return EFI_ABORTED;\r
414 }\r
415 }\r
416 \r
4c5a5e0c 417 //\r
418 // Record the incoming NIC info.\r
419 //\r
420 Status = IScsiAddNic (ControllerHandle);\r
421 if (EFI_ERROR (Status)) {\r
422 return Status;\r
423 }\r
424\r
425 //\r
426 // Create the instance private data.\r
427 //\r
428 Private = IScsiCreateDriverData (Image, ControllerHandle);\r
429 if (Private == NULL) {\r
430 return EFI_OUT_OF_RESOURCES;\r
431 }\r
432\r
433 //\r
434 // Create a underlayer child instance, but not need to configure it. Just open ChildHandle\r
435 // via BY_DRIVER. That is, establishing the relationship between ControllerHandle and ChildHandle.\r
436 // Therefore, when DisconnectController(), especially VLAN virtual controller handle,\r
437 // IScsiDriverBindingStop() will be called.\r
438 //\r
439 Status = NetLibCreateServiceChild (\r
440 ControllerHandle,\r
441 Image,\r
442 TcpServiceBindingGuid,\r
443 &Private->ChildHandle\r
444 );\r
445\r
446 if (EFI_ERROR (Status)) {\r
447 goto ON_ERROR;\r
448 }\r
449\r
450 Status = gBS->OpenProtocol (\r
d63a52eb 451 Private->ChildHandle, /// Default Tcp child\r
4c5a5e0c 452 ProtocolGuid,\r
453 &Interface,\r
454 Image,\r
455 ControllerHandle,\r
456 EFI_OPEN_PROTOCOL_BY_DRIVER\r
457 );\r
458 \r
459 if (EFI_ERROR (Status)) {\r
460 goto ON_ERROR;\r
461 }\r
462\r
463 //\r
464 // Always install private protocol no matter what happens later. We need to \r
465 // keep the relationship between ControllerHandle and ChildHandle.\r
466 //\r
467 Status = gBS->InstallProtocolInterface (\r
468 &ControllerHandle,\r
469 IScsiPrivateGuid,\r
470 EFI_NATIVE_INTERFACE,\r
471 &Private->IScsiIdentifier\r
472 );\r
473 if (EFI_ERROR (Status)) {\r
474 goto ON_ERROR;\r
475 }\r
476 \r
477 if (IpVersion == IP_VERSION_4) {\r
478 mPrivate->Ipv6Flag = FALSE;\r
479 } else {\r
480 mPrivate->Ipv6Flag = TRUE;\r
481 }\r
482\r
483 //\r
484 // Get the current iSCSI configuration data.\r
485 //\r
486 Status = IScsiGetConfigData (Private);\r
487 if (EFI_ERROR (Status)) {\r
488 goto ON_ERROR;\r
489 }\r
490\r
491 //\r
492 // If there is already a successul attempt, check whether this attempt is the\r
493 // first "enabled for MPIO" attempt. If not, still try the first attempt.\r
494 // In single path mode, try all attempts.\r
495 //\r
496 ExistPrivate = NULL;\r
497 Status = EFI_NOT_FOUND;\r
498\r
499 if (mPrivate->OneSessionEstablished && mPrivate->EnableMpio) {\r
500 AttemptConfigData = NULL;\r
501 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {\r
502 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
503 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {\r
504 break;\r
505 }\r
506 }\r
507\r
508 if (AttemptConfigData == NULL) {\r
509 goto ON_ERROR;\r
510 }\r
511\r
512 if (AttemptConfigData->AttemptConfigIndex == mPrivate->BootSelectedIndex) {\r
513 goto ON_EXIT;\r
514 }\r
515\r
516 //\r
517 // Uninstall the original ExtScsiPassThru first.\r
518 //\r
519\r
520 //\r
521 // Locate all ExtScsiPassThru protocol instances.\r
522 //\r
523 Status = gBS->LocateHandleBuffer (\r
524 ByProtocol,\r
525 &gEfiExtScsiPassThruProtocolGuid,\r
526 NULL,\r
527 &NumberOfHandles,\r
528 &HandleBuffer\r
529 );\r
530 if (EFI_ERROR (Status)) {\r
531 goto ON_ERROR;\r
532 }\r
533\r
534 //\r
535 // Find ExtScsiPassThru protocol instance produced by this driver.\r
536 //\r
537 ExistIScsiExtScsiPassThru = NULL;\r
538 for (Index = 0; Index < NumberOfHandles && ExistIScsiExtScsiPassThru == NULL; Index++) {\r
539 Status = gBS->HandleProtocol (\r
540 HandleBuffer[Index],\r
541 &gEfiDevicePathProtocolGuid,\r
542 (VOID **) &DevicePath\r
543 );\r
544 if (EFI_ERROR (Status)) {\r
545 continue;\r
546 }\r
547\r
548 while (!IsDevicePathEnd (DevicePath)) {\r
549 if ((DevicePath->Type == MESSAGING_DEVICE_PATH) && (DevicePath->SubType == MSG_MAC_ADDR_DP)) {\r
550 //\r
551 // Get the ExtScsiPassThru protocol instance.\r
552 //\r
553 Status = gBS->HandleProtocol (\r
554 HandleBuffer[Index],\r
555 &gEfiExtScsiPassThruProtocolGuid,\r
556 (VOID **) &ExistIScsiExtScsiPassThru\r
557 );\r
558 ASSERT_EFI_ERROR (Status);\r
559 break;\r
560 }\r
561\r
562 DevicePath = NextDevicePathNode (DevicePath);\r
563 }\r
564 }\r
565\r
566 FreePool (HandleBuffer);\r
567\r
568 if (ExistIScsiExtScsiPassThru == NULL) {\r
569 Status = EFI_NOT_FOUND;\r
570 goto ON_ERROR;\r
571 }\r
572\r
573 ExistPrivate = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (ExistIScsiExtScsiPassThru);\r
574\r
575 Status = gBS->UninstallProtocolInterface (\r
576 ExistPrivate->ExtScsiPassThruHandle,\r
577 &gEfiExtScsiPassThruProtocolGuid,\r
578 &ExistPrivate->IScsiExtScsiPassThru\r
579 );\r
580 if (EFI_ERROR (Status)) {\r
581 goto ON_ERROR;\r
582 }\r
583 }\r
584\r
585 //\r
586 // Install the Ext SCSI PASS THRU protocol.\r
587 //\r
588 Status = gBS->InstallProtocolInterface (\r
589 &Private->ExtScsiPassThruHandle,\r
590 &gEfiExtScsiPassThruProtocolGuid,\r
591 EFI_NATIVE_INTERFACE,\r
592 &Private->IScsiExtScsiPassThru\r
593 );\r
594 if (EFI_ERROR (Status)) {\r
595 goto ON_ERROR;\r
596 }\r
597\r
598 BootSelected = 0;\r
599\r
600 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mPrivate->AttemptConfigs) {\r
601 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
602 //\r
603 // Don't process the attempt that does not associate with the current NIC or\r
604 // this attempt is disabled or established.\r
605 //\r
606 if (AttemptConfigData->NicIndex != mPrivate->CurrentNic ||\r
607 AttemptConfigData->SessionConfigData.Enabled == ISCSI_DISABLED ||\r
608 AttemptConfigData->ValidPath) {\r
609 continue;\r
610 }\r
611\r
612 //\r
613 // In multipath mode, don't process attempts configured for single path.\r
614 // In default single path mode, don't process attempts configured for multipath.\r
615 //\r
616 if ((mPrivate->EnableMpio &&\r
617 AttemptConfigData->SessionConfigData.Enabled != ISCSI_ENABLED_FOR_MPIO) ||\r
618 (!mPrivate->EnableMpio &&\r
619 AttemptConfigData->SessionConfigData.Enabled != ISCSI_ENABLED)) {\r
620 continue;\r
621 }\r
622\r
623 //\r
624 // Don't process the attempt that fails to get the init/target information from DHCP.\r
625 //\r
626 if (AttemptConfigData->SessionConfigData.InitiatorInfoFromDhcp &&\r
627 !AttemptConfigData->DhcpSuccess) {\r
628 if (!mPrivate->EnableMpio && mPrivate->ValidSinglePathCount > 0) {\r
629 mPrivate->ValidSinglePathCount--;\r
630 }\r
631 continue;\r
632 }\r
633\r
634 //\r
635 // Don't process the autoconfigure path if it is already established.\r
636 //\r
637 if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG &&\r
87ce4210 638 AttemptConfigData->AutoConfigureSuccess) {\r
4c5a5e0c 639 continue;\r
640 }\r
641\r
642 //\r
643 // Don't process the attempt if its IP mode is not in the current IP version.\r
644 //\r
645 if (!mPrivate->Ipv6Flag) {\r
646 if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP6) {\r
647 continue;\r
648 }\r
649 if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG &&\r
650 AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6) {\r
651 continue;\r
652 }\r
653 } else {\r
654 if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP4) {\r
655 continue;\r
656 }\r
657 if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG &&\r
658 AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP4) {\r
659 continue;\r
660 }\r
661 }\r
662\r
663 //\r
664 // Fill in the Session and init it.\r
665 //\r
666 Session = (ISCSI_SESSION *) AllocateZeroPool (sizeof (ISCSI_SESSION));\r
667 if (Session == NULL) {\r
668 Status = EFI_OUT_OF_RESOURCES;\r
669 goto ON_ERROR;\r
670 }\r
671\r
672 Session->Private = Private;\r
673 Session->ConfigData = AttemptConfigData;\r
674 Session->AuthType = AttemptConfigData->AuthenticationType;\r
675\r
f256ab43 676 AsciiStrToUnicodeStrS (AttemptConfigData->MacString, MacString, ARRAY_SIZE (MacString));\r
4c5a5e0c 677 UnicodeSPrint (\r
678 mPrivate->PortString,\r
679 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
680 L"%s%d",\r
681 MacString,\r
682 (UINTN) AttemptConfigData->AttemptConfigIndex\r
683 );\r
684\r
685 if (Session->AuthType == ISCSI_AUTH_TYPE_CHAP) {\r
686 Session->AuthData.CHAP.AuthConfig = &AttemptConfigData->AuthConfigData.CHAP;\r
687 }\r
688\r
689 IScsiSessionInit (Session, FALSE);\r
690\r
691 //\r
692 // Try to login and create an iSCSI session according to the configuration.\r
693 //\r
694 Status = IScsiSessionLogin (Session);\r
695 if (Status == EFI_MEDIA_CHANGED) {\r
696 //\r
697 // The specified target is not available, and the redirection information is\r
698 // received. Login the session again with the updated target address.\r
699 //\r
700 Status = IScsiSessionLogin (Session);\r
701 } else if (Status == EFI_NOT_READY) {\r
702 Status = IScsiSessionReLogin (Session);\r
703 }\r
704\r
a2d59ef2
YT
705 //\r
706 // Restore the origial user setting which specifies the proxy/virtual iSCSI target to NV region.\r
707 //\r
708 NvData = &AttemptConfigData->SessionConfigData;\r
709 if (NvData->RedirectFlag) {\r
710 NvData->TargetPort = NvData->OriginalTargetPort;\r
711 CopyMem (&NvData->TargetIp, &NvData->OriginalTargetIp, sizeof (EFI_IP_ADDRESS));\r
712 NvData->RedirectFlag = FALSE;\r
713\r
714 gRT->SetVariable (\r
715 mPrivate->PortString,\r
716 &gEfiIScsiInitiatorNameProtocolGuid,\r
717 ISCSI_CONFIG_VAR_ATTR,\r
718 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),\r
719 AttemptConfigData\r
720 );\r
721 }\r
722\r
4c5a5e0c 723 if (EFI_ERROR (Status)) {\r
724 //\r
725 // In Single path mode, only the successful attempt will be recorded in iBFT;\r
726 // in multi-path mode, all the attempt entries in MPIO will be recorded in iBFT.\r
727 //\r
728 if (!mPrivate->EnableMpio && mPrivate->ValidSinglePathCount > 0) {\r
729 mPrivate->ValidSinglePathCount--;\r
730 }\r
731\r
732 FreePool (Session);\r
733\r
734 } else {\r
735 AttemptConfigData->ValidPath = TRUE;\r
736\r
737 //\r
738 // Do not record the attempt in iBFT if it login with KRB5.\r
739 // TODO: record KRB5 attempt information in the iSCSI device path.\r
740 //\r
741 if (Session->AuthType == ISCSI_AUTH_TYPE_KRB) {\r
742 if (!mPrivate->EnableMpio && mPrivate->ValidSinglePathCount > 0) {\r
743 mPrivate->ValidSinglePathCount--;\r
744 }\r
745\r
746 AttemptConfigData->ValidiBFTPath = FALSE;\r
747 } else {\r
748 AttemptConfigData->ValidiBFTPath = TRUE;\r
749 }\r
750\r
751 //\r
752 // IScsi session success. Update the attempt state to NVR.\r
753 //\r
754 if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) {\r
87ce4210 755 AttemptConfigData->AutoConfigureSuccess = TRUE;\r
4c5a5e0c 756 }\r
757\r
758 gRT->SetVariable (\r
759 mPrivate->PortString,\r
760 &gEfiIScsiInitiatorNameProtocolGuid,\r
761 ISCSI_CONFIG_VAR_ATTR,\r
762 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),\r
763 AttemptConfigData\r
764 );\r
765\r
766 //\r
767 // Select the first login session. Abort others.\r
768 //\r
769 if (Private->Session == NULL) {\r
770 Private->Session = Session;\r
771 BootSelected = AttemptConfigData->AttemptConfigIndex;\r
772 //\r
773 // Don't validate other attempt in multipath mode if one is success.\r
774 //\r
775 if (mPrivate->EnableMpio) {\r
776 break;\r
777 }\r
778 } else {\r
779 IScsiSessionAbort (Session);\r
780 FreePool (Session);\r
781 }\r
782 }\r
783 }\r
784\r
785 //\r
786 // All attempts configured for this driver instance are not valid.\r
787 //\r
788 if (Private->Session == NULL) {\r
789 Status = gBS->UninstallProtocolInterface (\r
790 Private->ExtScsiPassThruHandle,\r
791 &gEfiExtScsiPassThruProtocolGuid,\r
792 &Private->IScsiExtScsiPassThru\r
793 );\r
794 ASSERT_EFI_ERROR (Status);\r
795 Private->ExtScsiPassThruHandle = NULL;\r
796\r
797 //\r
798 // Reinstall the original ExtScsiPassThru back.\r
799 //\r
800 if (mPrivate->OneSessionEstablished && ExistPrivate != NULL) {\r
801 Status = gBS->InstallProtocolInterface (\r
802 &ExistPrivate->ExtScsiPassThruHandle,\r
803 &gEfiExtScsiPassThruProtocolGuid,\r
804 EFI_NATIVE_INTERFACE,\r
805 &ExistPrivate->IScsiExtScsiPassThru\r
806 );\r
807 if (EFI_ERROR (Status)) {\r
808 goto ON_ERROR;\r
809 }\r
810\r
811 goto ON_EXIT;\r
812 }\r
813\r
814 Status = EFI_NOT_FOUND;\r
815\r
816 goto ON_ERROR;\r
817 }\r
818\r
819 NeedUpdate = TRUE;\r
820 //\r
821 // More than one attempt successes.\r
822 //\r
823 if (Private->Session != NULL && mPrivate->OneSessionEstablished) {\r
824\r
825 AttemptConfigOrder = IScsiGetVariableAndSize (\r
826 L"AttemptOrder",\r
9bdc6592 827 &gIScsiConfigGuid,\r
4c5a5e0c 828 &AttemptConfigOrderSize\r
829 );\r
9c12f2d7
FS
830 if (AttemptConfigOrder == NULL) {\r
831 goto ON_ERROR;\r
832 }\r
4c5a5e0c 833 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {\r
834 if (AttemptConfigOrder[Index] == mPrivate->BootSelectedIndex ||\r
835 AttemptConfigOrder[Index] == BootSelected) {\r
836 break;\r
837 }\r
838 }\r
839\r
840 if (mPrivate->EnableMpio) {\r
841 //\r
842 // Use the attempt in earlier order. Abort the later one in MPIO.\r
843 //\r
844 if (AttemptConfigOrder[Index] == mPrivate->BootSelectedIndex) {\r
845 IScsiSessionAbort (Private->Session);\r
846 FreePool (Private->Session);\r
847 Private->Session = NULL;\r
848 gBS->UninstallProtocolInterface (\r
849 Private->ExtScsiPassThruHandle,\r
850 &gEfiExtScsiPassThruProtocolGuid,\r
851 &Private->IScsiExtScsiPassThru\r
852 );\r
853 Private->ExtScsiPassThruHandle = NULL;\r
854\r
855 //\r
856 // Reinstall the original ExtScsiPassThru back.\r
857 //\r
858 Status = gBS->InstallProtocolInterface (\r
859 &ExistPrivate->ExtScsiPassThruHandle,\r
860 &gEfiExtScsiPassThruProtocolGuid,\r
861 EFI_NATIVE_INTERFACE,\r
862 &ExistPrivate->IScsiExtScsiPassThru\r
863 );\r
864 if (EFI_ERROR (Status)) {\r
865 goto ON_ERROR;\r
866 }\r
867\r
868 goto ON_EXIT;\r
869 } else {\r
9c12f2d7
FS
870 if (AttemptConfigOrder[Index] != BootSelected) {\r
871 goto ON_ERROR;\r
872 }\r
4c5a5e0c 873 mPrivate->BootSelectedIndex = BootSelected;\r
874 //\r
875 // Clear the resource in ExistPrivate.\r
876 //\r
877 gBS->UninstallProtocolInterface (\r
878 ExistPrivate->Controller,\r
879 IScsiPrivateGuid,\r
880 &ExistPrivate->IScsiIdentifier\r
881 ); \r
882 \r
883 IScsiRemoveNic (ExistPrivate->Controller);\r
884 if (ExistPrivate->Session != NULL) {\r
885 IScsiSessionAbort (ExistPrivate->Session);\r
886 }\r
887\r
89446d89
ZL
888 if (ExistPrivate->DevicePath != NULL) {\r
889 Status = gBS->UninstallProtocolInterface (\r
890 ExistPrivate->ExtScsiPassThruHandle,\r
891 &gEfiDevicePathProtocolGuid,\r
892 ExistPrivate->DevicePath\r
893 );\r
894 if (EFI_ERROR (Status)) {\r
895 goto ON_ERROR;\r
896 }\r
897\r
898 FreePool (ExistPrivate->DevicePath);\r
e590d29f 899 }\r
89446d89
ZL
900\r
901 gBS->CloseEvent (ExistPrivate->ExitBootServiceEvent);\r
902 FreePool (ExistPrivate);\r
903\r
4c5a5e0c 904 }\r
905 } else {\r
906 //\r
907 // Use the attempt in earlier order as boot selected in single path mode.\r
908 //\r
909 if (AttemptConfigOrder[Index] == mPrivate->BootSelectedIndex) {\r
910 NeedUpdate = FALSE;\r
911 }\r
912 }\r
913\r
914 }\r
915\r
916 if (NeedUpdate) {\r
917 mPrivate->OneSessionEstablished = TRUE;\r
918 mPrivate->BootSelectedIndex = BootSelected;\r
919 }\r
920\r
921 //\r
922 // Duplicate the Session's tcp connection device path. The source port field\r
923 // will be set to zero as one iSCSI session is comprised of several iSCSI\r
924 // connections.\r
925 //\r
926 Private->DevicePath = IScsiGetTcpConnDevicePath (Private->Session);\r
927 if (Private->DevicePath == NULL) {\r
928 Status = EFI_DEVICE_ERROR;\r
929 goto ON_ERROR;\r
930 }\r
931 //\r
932 // Install the updated device path onto the ExtScsiPassThruHandle.\r
933 //\r
934 Status = gBS->InstallProtocolInterface (\r
935 &Private->ExtScsiPassThruHandle,\r
936 &gEfiDevicePathProtocolGuid,\r
937 EFI_NATIVE_INTERFACE,\r
938 Private->DevicePath\r
939 );\r
940 if (EFI_ERROR (Status)) {\r
941 goto ON_ERROR;\r
942 }\r
943\r
d63a52eb
WJ
944 //\r
945 // ISCSI children should share the default Tcp child, just open the default Tcp child via BY_CHILD_CONTROLLER.\r
946 //\r
947 Status = gBS->OpenProtocol (\r
948 Private->ChildHandle, /// Default Tcp child\r
949 ProtocolGuid,\r
950 &Interface,\r
951 Image,\r
952 Private->ExtScsiPassThruHandle,\r
953 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
954 ); \r
955 if (EFI_ERROR (Status)) {\r
956 gBS->UninstallMultipleProtocolInterfaces (\r
957 Private->ExtScsiPassThruHandle,\r
958 &gEfiExtScsiPassThruProtocolGuid,\r
959 &Private->IScsiExtScsiPassThru,\r
960 &gEfiDevicePathProtocolGuid,\r
961 Private->DevicePath,\r
962 NULL\r
963 );\r
964 \r
965 goto ON_ERROR;\r
966 }\r
967\r
4c5a5e0c 968ON_EXIT:\r
969\r
970 //\r
971 // Update/Publish the iSCSI Boot Firmware Table.\r
972 //\r
973 if (mPrivate->BootSelectedIndex != 0) {\r
974 IScsiPublishIbft ();\r
975 }\r
976\r
977 return EFI_SUCCESS;\r
978\r
979ON_ERROR:\r
980\r
981 if (Private->Session != NULL) {\r
982 IScsiSessionAbort (Private->Session);\r
983 }\r
984\r
985 return Status;\r
986}\r
987\r
988/**\r
6879581d 989 Stops a device controller or a bus controller. This is the worker function for\r
990 IScsiIp4(6)DriverBindingStop.\r
4c5a5e0c 991 \r
992 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
993 @param[in] ControllerHandle A handle to the device being stopped. The handle must \r
994 support a bus specific I/O protocol for the driver \r
995 to use to stop the device.\r
996 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
997 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL \r
998 if NumberOfChildren is 0.\r
6879581d 999 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.\r
1000 \r
4c5a5e0c 1001 @retval EFI_SUCCESS The device was stopped.\r
1002 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
e590d29f
ZL
1003 @retval EFI_INVALID_PARAMETER Child handle is NULL.\r
1004 @retval EFI_ACCESS_DENIED The protocol could not be removed from the Handle\r
1005 because its interfaces are being used.\r
4c5a5e0c 1006\r
1007**/\r
1008EFI_STATUS\r
1009EFIAPI\r
6879581d 1010IScsiStop (\r
4c5a5e0c 1011 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1012 IN EFI_HANDLE ControllerHandle,\r
1013 IN UINTN NumberOfChildren,\r
6879581d 1014 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL,\r
1015 IN UINT8 IpVersion\r
4c5a5e0c 1016 )\r
1017{\r
1018 EFI_HANDLE IScsiController;\r
1019 EFI_STATUS Status;\r
1020 ISCSI_PRIVATE_PROTOCOL *IScsiIdentifier;\r
1021 ISCSI_DRIVER_DATA *Private;\r
1022 EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru;\r
1023 ISCSI_CONNECTION *Conn;\r
1024 EFI_GUID *ProtocolGuid;\r
1025 EFI_GUID *TcpServiceBindingGuid;\r
1026 EFI_GUID *TcpProtocolGuid;\r
1027\r
1028\r
1029 if (NumberOfChildren != 0) {\r
1030 //\r
1031 // We should have only one child.\r
1032 //\r
1033 Status = gBS->OpenProtocol (\r
1034 ChildHandleBuffer[0],\r
1035 &gEfiExtScsiPassThruProtocolGuid,\r
1036 (VOID **) &PassThru,\r
1037 This->DriverBindingHandle,\r
1038 ControllerHandle,\r
1039 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1040 );\r
1041 if (EFI_ERROR (Status)) {\r
1042 return EFI_DEVICE_ERROR;\r
1043 }\r
1044\r
1045 Private = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (PassThru);\r
1046 Conn = NET_LIST_HEAD (&Private->Session->Conns, ISCSI_CONNECTION, Link);\r
1047\r
1048 //\r
1049 // Previously the TCP protocol is opened BY_CHILD_CONTROLLER. Just close\r
1050 // the protocol here, but do not uninstall the device path protocol and\r
1051 // EXT SCSI PASS THRU protocol installed on ExtScsiPassThruHandle.\r
1052 //\r
6879581d 1053 if (IpVersion == IP_VERSION_4) {\r
4c5a5e0c 1054 ProtocolGuid = &gEfiTcp4ProtocolGuid;\r
1055 } else {\r
1056 ProtocolGuid = &gEfiTcp6ProtocolGuid;\r
1057 }\r
1058\r
d63a52eb
WJ
1059 gBS->CloseProtocol (\r
1060 Private->ChildHandle,\r
1061 ProtocolGuid,\r
1062 Private->Image,\r
1063 Private->ExtScsiPassThruHandle\r
1064 );\r
1065 \r
4c5a5e0c 1066 gBS->CloseProtocol (\r
1067 Conn->TcpIo.Handle,\r
1068 ProtocolGuid,\r
1069 Private->Image,\r
1070 Private->ExtScsiPassThruHandle\r
1071 );\r
1072\r
1073 return EFI_SUCCESS;\r
1074 }\r
d63a52eb 1075 \r
4c5a5e0c 1076 //\r
1077 // Get the handle of the controller we are controling.\r
1078 //\r
6879581d 1079 if (IpVersion == IP_VERSION_4) {\r
216f7970 1080 ProtocolGuid = &gIScsiV4PrivateGuid;\r
4c5a5e0c 1081 TcpProtocolGuid = &gEfiTcp4ProtocolGuid;\r
1082 TcpServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;\r
1083 } else {\r
216f7970 1084 ProtocolGuid = &gIScsiV6PrivateGuid;\r
4c5a5e0c 1085 TcpProtocolGuid = &gEfiTcp6ProtocolGuid;\r
1086 TcpServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;\r
1087 }\r
6879581d 1088 IScsiController = NetLibGetNicHandle (ControllerHandle, TcpProtocolGuid);\r
1089 if (IScsiController == NULL) {\r
1090 return EFI_SUCCESS;\r
1091 }\r
4c5a5e0c 1092\r
1093 Status = gBS->OpenProtocol (\r
1094 IScsiController,\r
1095 ProtocolGuid,\r
1096 (VOID **) &IScsiIdentifier,\r
1097 This->DriverBindingHandle,\r
1098 ControllerHandle,\r
1099 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1100 );\r
1101 if (EFI_ERROR (Status)) {\r
1102 return EFI_DEVICE_ERROR;\r
1103 }\r
1104\r
1105 Private = ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier);\r
1106 ASSERT (Private != NULL);\r
1107\r
1108 if (Private->ChildHandle != NULL) {\r
1109 Status = gBS->CloseProtocol (\r
1110 Private->ChildHandle,\r
1111 TcpProtocolGuid,\r
1112 This->DriverBindingHandle,\r
1113 IScsiController\r
1114 );\r
1115 \r
1116 ASSERT (!EFI_ERROR (Status));\r
1117\r
1118 Status = NetLibDestroyServiceChild (\r
1119 IScsiController,\r
1120 This->DriverBindingHandle,\r
1121 TcpServiceBindingGuid,\r
1122 Private->ChildHandle\r
1123 );\r
1124\r
1125 ASSERT (!EFI_ERROR (Status));\r
1126 }\r
1127\r
1128 gBS->UninstallProtocolInterface (\r
1129 IScsiController,\r
1130 ProtocolGuid,\r
1131 &Private->IScsiIdentifier\r
1132 ); \r
1133\r
1134 //\r
1135 // Remove this NIC.\r
1136 //\r
1137 IScsiRemoveNic (IScsiController);\r
1138\r
1139 //\r
1140 // Update the iSCSI Boot Firware Table.\r
1141 //\r
1142 IScsiPublishIbft ();\r
1143\r
1144 if (Private->Session != NULL) {\r
1145 IScsiSessionAbort (Private->Session);\r
1146 }\r
1147\r
e590d29f
ZL
1148 Status = IScsiCleanDriverData (Private);\r
1149\r
1150 if (EFI_ERROR (Status)) {\r
1151 return Status;\r
1152 }\r
4c5a5e0c 1153\r
1154 return EFI_SUCCESS;\r
1155}\r
1156\r
6879581d 1157/**\r
1158 Tests to see if this driver supports a given controller. If a child device is provided, \r
1159 it tests to see if this driver supports creating a handle for the specified child device.\r
1160\r
1161 This function checks to see if the driver specified by This supports the device specified by \r
1162 ControllerHandle. Drivers typically use the device path attached to \r
1163 ControllerHandle and/or the services from the bus I/O abstraction attached to \r
1164 ControllerHandle to determine if the driver supports ControllerHandle. This function \r
1165 may be called many times during platform initialization. In order to reduce boot times, the tests \r
1166 performed by this function must be very small and take as little time as possible to execute. This \r
1167 function must not change the state of any hardware devices, and this function must be aware that the \r
1168 device specified by ControllerHandle may already be managed by the same driver or a \r
1169 different driver. This function must match its calls to AllocatePages() with FreePages(), \r
1170 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). \r
1171 Since ControllerHandle may have been previously started by the same driver, if a protocol is \r
1172 already in the opened state, then it must not be closed with CloseProtocol(). This is required \r
1173 to guarantee the state of ControllerHandle is not modified by this function.\r
1174\r
1175 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
1176 @param[in] ControllerHandle The handle of the controller to test. This handle \r
1177 must support a protocol interface that supplies \r
1178 an I/O abstraction to the driver.\r
1179 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
1180 parameter is ignored by device drivers, and is optional for bus \r
1181 drivers. For bus drivers, if this parameter is not NULL, then \r
1182 the bus driver must determine if the bus controller specified \r
1183 by ControllerHandle and the child controller specified \r
1184 by RemainingDevicePath are both supported by this \r
1185 bus driver.\r
1186\r
1187 @retval EFI_SUCCESS The device specified by ControllerHandle and\r
1188 RemainingDevicePath is supported by the driver specified by This.\r
1189 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
1190 RemainingDevicePath is already managed by the driver\r
1191 specified by This.\r
1192 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
1193 RemainingDevicePath is already managed by a different\r
1194 driver or an application that requires exclusive access.\r
1195 Currently not implemented.\r
1196 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
1197 RemainingDevicePath is not supported by the driver specified by This.\r
1198**/\r
1199EFI_STATUS\r
1200EFIAPI\r
1201IScsiIp4DriverBindingSupported (\r
1202 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1203 IN EFI_HANDLE ControllerHandle,\r
1204 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
1205 )\r
1206{\r
1207 return IScsiSupported (\r
1208 This,\r
1209 ControllerHandle,\r
1210 RemainingDevicePath,\r
1211 IP_VERSION_4\r
1212 );\r
1213}\r
1214\r
1215/**\r
1216 Starts a device controller or a bus controller.\r
1217\r
1218 The Start() function is designed to be invoked from the EFI boot service ConnectController().\r
1219 As a result, much of the error checking on the parameters to Start() has been moved into this \r
1220 common boot service. It is legal to call Start() from other locations, \r
1221 but the following calling restrictions must be followed or the system behavior will not be deterministic.\r
1222 1. ControllerHandle must be a valid EFI_HANDLE.\r
1223 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
1224 EFI_DEVICE_PATH_PROTOCOL.\r
1225 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
1226 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. \r
1227\r
1228 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
1229 @param[in] ControllerHandle The handle of the controller to start. This handle \r
1230 must support a protocol interface that supplies \r
1231 an I/O abstraction to the driver.\r
1232 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
1233 parameter is ignored by device drivers, and is optional for bus \r
1234 drivers. For a bus driver, if this parameter is NULL, then handles \r
1235 for all the children of Controller are created by this driver. \r
1236 If this parameter is not NULL and the first Device Path Node is \r
1237 not the End of Device Path Node, then only the handle for the \r
1238 child device specified by the first Device Path Node of \r
1239 RemainingDevicePath is created by this driver.\r
1240 If the first Device Path Node of RemainingDevicePath is \r
1241 the End of Device Path Node, no child handle is created by this\r
1242 driver.\r
1243\r
1244 @retval EFI_SUCCESS The device was started.\r
1245 @retval EFI_DEVICE_ERROR The device could not be started due to a device error. Currently not implemented.\r
1246 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
1247 @retval Others The driver failed to start the device.\r
1248\r
1249**/\r
1250EFI_STATUS\r
1251EFIAPI\r
1252IScsiIp4DriverBindingStart (\r
1253 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1254 IN EFI_HANDLE ControllerHandle,\r
1255 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
1256 )\r
1257{\r
1258 EFI_STATUS Status;\r
1259\r
1260 Status = IScsiStart (This->DriverBindingHandle, ControllerHandle, IP_VERSION_4);\r
1261 if (Status == EFI_ALREADY_STARTED) {\r
1262 Status = EFI_SUCCESS;\r
1263 }\r
1264\r
1265 return Status;\r
1266}\r
1267\r
1268/**\r
1269 Stops a device controller or a bus controller.\r
1270 \r
1271 The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). \r
1272 As a result, much of the error checking on the parameters to Stop() has been moved \r
1273 into this common boot service. It is legal to call Stop() from other locations, \r
1274 but the following calling restrictions must be followed or the system behavior will not be deterministic.\r
1275 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
1276 same driver's Start() function.\r
1277 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
1278 EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
1279 Start() function, and the Start() function must have called OpenProtocol() on\r
1280 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
1281 \r
1282 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
1283 @param[in] ControllerHandle A handle to the device being stopped. The handle must \r
1284 support a bus specific I/O protocol for the driver \r
1285 to use to stop the device.\r
1286 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
1287 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL \r
1288 if NumberOfChildren is 0.\r
1289\r
1290 @retval EFI_SUCCESS The device was stopped.\r
1291 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
1292\r
1293**/\r
1294EFI_STATUS\r
1295EFIAPI\r
1296IScsiIp4DriverBindingStop (\r
1297 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1298 IN EFI_HANDLE ControllerHandle,\r
1299 IN UINTN NumberOfChildren,\r
1300 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
1301 )\r
1302{\r
1303 return IScsiStop (\r
1304 This,\r
1305 ControllerHandle,\r
1306 NumberOfChildren,\r
1307 ChildHandleBuffer,\r
1308 IP_VERSION_4\r
1309 );\r
1310}\r
1311\r
1312/**\r
1313 Tests to see if this driver supports a given controller. If a child device is provided, \r
1314 it tests to see if this driver supports creating a handle for the specified child device.\r
1315\r
1316 This function checks to see if the driver specified by This supports the device specified by \r
1317 ControllerHandle. Drivers typically use the device path attached to \r
1318 ControllerHandle and/or the services from the bus I/O abstraction attached to \r
1319 ControllerHandle to determine if the driver supports ControllerHandle. This function \r
1320 may be called many times during platform initialization. In order to reduce boot times, the tests \r
1321 performed by this function must be very small and take as little time as possible to execute. This \r
1322 function must not change the state of any hardware devices, and this function must be aware that the \r
1323 device specified by ControllerHandle may already be managed by the same driver or a \r
1324 different driver. This function must match its calls to AllocatePages() with FreePages(), \r
1325 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). \r
1326 Since ControllerHandle may have been previously started by the same driver, if a protocol is \r
1327 already in the opened state, then it must not be closed with CloseProtocol(). This is required \r
1328 to guarantee the state of ControllerHandle is not modified by this function.\r
1329\r
1330 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
1331 @param[in] ControllerHandle The handle of the controller to test. This handle \r
1332 must support a protocol interface that supplies \r
1333 an I/O abstraction to the driver.\r
1334 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
1335 parameter is ignored by device drivers, and is optional for bus \r
1336 drivers. For bus drivers, if this parameter is not NULL, then \r
1337 the bus driver must determine if the bus controller specified \r
1338 by ControllerHandle and the child controller specified \r
1339 by RemainingDevicePath are both supported by this \r
1340 bus driver.\r
1341\r
1342 @retval EFI_SUCCESS The device specified by ControllerHandle and\r
1343 RemainingDevicePath is supported by the driver specified by This.\r
1344 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
1345 RemainingDevicePath is already managed by the driver\r
1346 specified by This.\r
1347 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
1348 RemainingDevicePath is already managed by a different\r
1349 driver or an application that requires exclusive access.\r
1350 Currently not implemented.\r
1351 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
1352 RemainingDevicePath is not supported by the driver specified by This.\r
1353**/\r
1354EFI_STATUS\r
1355EFIAPI\r
1356IScsiIp6DriverBindingSupported (\r
1357 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1358 IN EFI_HANDLE ControllerHandle,\r
1359 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
1360 )\r
1361{\r
1362 return IScsiSupported (\r
1363 This,\r
1364 ControllerHandle,\r
1365 RemainingDevicePath,\r
1366 IP_VERSION_6\r
1367 );\r
1368}\r
1369\r
1370/**\r
1371 Starts a device controller or a bus controller.\r
1372\r
1373 The Start() function is designed to be invoked from the EFI boot service ConnectController().\r
1374 As a result, much of the error checking on the parameters to Start() has been moved into this \r
1375 common boot service. It is legal to call Start() from other locations, \r
1376 but the following calling restrictions must be followed or the system behavior will not be deterministic.\r
1377 1. ControllerHandle must be a valid EFI_HANDLE.\r
1378 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
1379 EFI_DEVICE_PATH_PROTOCOL.\r
1380 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
1381 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. \r
1382\r
1383 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
1384 @param[in] ControllerHandle The handle of the controller to start. This handle \r
1385 must support a protocol interface that supplies \r
1386 an I/O abstraction to the driver.\r
1387 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
1388 parameter is ignored by device drivers, and is optional for bus \r
1389 drivers. For a bus driver, if this parameter is NULL, then handles \r
1390 for all the children of Controller are created by this driver. \r
1391 If this parameter is not NULL and the first Device Path Node is \r
1392 not the End of Device Path Node, then only the handle for the \r
1393 child device specified by the first Device Path Node of \r
1394 RemainingDevicePath is created by this driver.\r
1395 If the first Device Path Node of RemainingDevicePath is \r
1396 the End of Device Path Node, no child handle is created by this\r
1397 driver.\r
1398\r
1399 @retval EFI_SUCCESS The device was started.\r
1400 @retval EFI_DEVICE_ERROR The device could not be started due to a device error. Currently not implemented.\r
1401 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
1402 @retval Others The driver failed to start the device.\r
1403\r
1404**/\r
1405EFI_STATUS\r
1406EFIAPI\r
1407IScsiIp6DriverBindingStart (\r
1408 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1409 IN EFI_HANDLE ControllerHandle,\r
1410 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
1411 )\r
1412{\r
1413 EFI_STATUS Status;\r
1414\r
1415 Status = IScsiStart (This->DriverBindingHandle, ControllerHandle, IP_VERSION_6);\r
1416 if (Status == EFI_ALREADY_STARTED) {\r
1417 Status = EFI_SUCCESS;\r
1418 }\r
1419\r
1420 return Status;\r
1421}\r
1422\r
1423/**\r
1424 Stops a device controller or a bus controller.\r
1425 \r
1426 The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). \r
1427 As a result, much of the error checking on the parameters to Stop() has been moved \r
1428 into this common boot service. It is legal to call Stop() from other locations, \r
1429 but the following calling restrictions must be followed or the system behavior will not be deterministic.\r
1430 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
1431 same driver's Start() function.\r
1432 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
1433 EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
1434 Start() function, and the Start() function must have called OpenProtocol() on\r
1435 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
1436 \r
1437 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
1438 @param[in] ControllerHandle A handle to the device being stopped. The handle must \r
1439 support a bus specific I/O protocol for the driver \r
1440 to use to stop the device.\r
1441 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
1442 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL \r
1443 if NumberOfChildren is 0.\r
1444\r
1445 @retval EFI_SUCCESS The device was stopped.\r
1446 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
1447\r
1448**/\r
1449EFI_STATUS\r
1450EFIAPI\r
1451IScsiIp6DriverBindingStop (\r
1452 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1453 IN EFI_HANDLE ControllerHandle,\r
1454 IN UINTN NumberOfChildren,\r
1455 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
1456 )\r
1457{\r
1458 return IScsiStop (\r
1459 This,\r
1460 ControllerHandle,\r
1461 NumberOfChildren,\r
1462 ChildHandleBuffer,\r
1463 IP_VERSION_6\r
1464 );\r
1465}\r
4c5a5e0c 1466\r
1467/**\r
1468 Unload the iSCSI driver.\r
1469\r
1470 @param[in] ImageHandle The handle of the driver image.\r
1471\r
1472 @retval EFI_SUCCESS The driver is unloaded.\r
1473 @retval EFI_DEVICE_ERROR An unexpected error occurred.\r
1474\r
1475**/\r
1476EFI_STATUS\r
1477EFIAPI\r
1478IScsiUnload (\r
1479 IN EFI_HANDLE ImageHandle\r
1480 )\r
1481{\r
18b24f92
FS
1482 EFI_STATUS Status;\r
1483 UINTN DeviceHandleCount;\r
1484 EFI_HANDLE *DeviceHandleBuffer;\r
1485 UINTN Index;\r
1486 EFI_COMPONENT_NAME_PROTOCOL *ComponentName;\r
1487 EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;\r
4c5a5e0c 1488\r
1489 //\r
1490 // Try to disonnect the driver from the devices it's controlling.\r
1491 //\r
1492 Status = gBS->LocateHandleBuffer (\r
1493 AllHandles,\r
1494 NULL,\r
1495 NULL,\r
1496 &DeviceHandleCount,\r
1497 &DeviceHandleBuffer\r
1498 );\r
6879581d 1499 if (EFI_ERROR (Status)) {\r
1500 return Status;\r
1501 }\r
4c5a5e0c 1502\r
18b24f92
FS
1503 //\r
1504 // Disconnect the iSCSI4 driver from the controlled device.\r
1505 //\r
1506 for (Index = 0; Index < DeviceHandleCount; Index++) {\r
1507 Status = IScsiTestManagedDevice (\r
1508 DeviceHandleBuffer[Index],\r
1509 gIScsiIp4DriverBinding.DriverBindingHandle,\r
1510 &gEfiTcp4ProtocolGuid)\r
1511 ;\r
1512 if (EFI_ERROR (Status)) {\r
1513 continue;\r
1514 }\r
1515 Status = gBS->DisconnectController (\r
1516 DeviceHandleBuffer[Index],\r
1517 gIScsiIp4DriverBinding.DriverBindingHandle,\r
1518 NULL\r
1519 );\r
1520 if (EFI_ERROR (Status)) {\r
1521 goto ON_EXIT;\r
1522 }\r
1523 }\r
1524\r
1525 //\r
1526 // Disconnect the iSCSI6 driver from the controlled device.\r
1527 //\r
6879581d 1528 for (Index = 0; Index < DeviceHandleCount; Index++) {\r
18b24f92
FS
1529 Status = IScsiTestManagedDevice (\r
1530 DeviceHandleBuffer[Index],\r
1531 gIScsiIp6DriverBinding.DriverBindingHandle,\r
1532 &gEfiTcp6ProtocolGuid\r
1533 );\r
1534 if (EFI_ERROR (Status)) {\r
1535 continue;\r
1536 }\r
1537 Status = gBS->DisconnectController (\r
1538 DeviceHandleBuffer[Index],\r
1539 gIScsiIp6DriverBinding.DriverBindingHandle,\r
1540 NULL\r
1541 );\r
1542 if (EFI_ERROR (Status)) {\r
1543 goto ON_EXIT;\r
1544 }\r
1545 }\r
1546\r
1547 //\r
1548 // Unload the iSCSI configuration form.\r
1549 //\r
1550 Status = IScsiConfigFormUnload (gIScsiIp4DriverBinding.DriverBindingHandle);\r
1551 if (EFI_ERROR (Status)) {\r
1552 goto ON_EXIT;\r
1553 }\r
1554 \r
1555 //\r
1556 // Uninstall the protocols installed by iSCSI driver.\r
1557 //\r
1558 Status = gBS->UninstallMultipleProtocolInterfaces (\r
1559 ImageHandle,\r
1560 &gEfiAuthenticationInfoProtocolGuid,\r
1561 &gIScsiAuthenticationInfo,\r
1562 NULL\r
1563 );\r
1564 if (EFI_ERROR (Status)) {\r
1565 goto ON_EXIT;\r
1566 }\r
1567 \r
1568 if (gIScsiControllerNameTable!= NULL) {\r
1569 Status = FreeUnicodeStringTable (gIScsiControllerNameTable);\r
1570 if (EFI_ERROR (Status)) {\r
1571 goto ON_EXIT;\r
1572 }\r
1573 gIScsiControllerNameTable = NULL;\r
1574 }\r
1575\r
1576 //\r
1577 // Uninstall the ComponentName and ComponentName2 protocol from iSCSI4 driver binding handle\r
1578 // if it has been installed.\r
1579 //\r
1580 Status = gBS->HandleProtocol (\r
1581 gIScsiIp4DriverBinding.DriverBindingHandle,\r
1582 &gEfiComponentNameProtocolGuid,\r
1583 (VOID **) &ComponentName\r
1584 );\r
1585 if (!EFI_ERROR (Status)) {\r
1586 Status = gBS->UninstallMultipleProtocolInterfaces (\r
6879581d 1587 gIScsiIp4DriverBinding.DriverBindingHandle,\r
18b24f92
FS
1588 &gEfiComponentNameProtocolGuid,\r
1589 ComponentName,\r
6879581d 1590 NULL\r
1591 );\r
18b24f92
FS
1592 if (EFI_ERROR (Status)) {\r
1593 goto ON_EXIT;\r
1594 }\r
1595 }\r
1596 \r
1597 Status = gBS->HandleProtocol (\r
1598 gIScsiIp4DriverBinding.DriverBindingHandle,\r
1599 &gEfiComponentName2ProtocolGuid,\r
1600 (VOID **) &ComponentName2\r
1601 );\r
1602 if (!EFI_ERROR (Status)) {\r
1603 gBS->UninstallMultipleProtocolInterfaces (\r
1604 gIScsiIp4DriverBinding.DriverBindingHandle,\r
1605 &gEfiComponentName2ProtocolGuid,\r
1606 ComponentName2,\r
6879581d 1607 NULL\r
1608 );\r
18b24f92
FS
1609 if (EFI_ERROR (Status)) {\r
1610 goto ON_EXIT;\r
1611 }\r
4c5a5e0c 1612 }\r
6879581d 1613\r
4c5a5e0c 1614 //\r
18b24f92
FS
1615 // Uninstall the ComponentName and ComponentName2 protocol from iSCSI6 driver binding handle\r
1616 // if it has been installed.\r
4c5a5e0c 1617 //\r
18b24f92
FS
1618 Status = gBS->HandleProtocol (\r
1619 gIScsiIp6DriverBinding.DriverBindingHandle,\r
1620 &gEfiComponentNameProtocolGuid,\r
1621 (VOID **) &ComponentName\r
1622 );\r
1623 if (!EFI_ERROR (Status)) {\r
1624 Status = gBS->UninstallMultipleProtocolInterfaces (\r
1625 gIScsiIp6DriverBinding.DriverBindingHandle,\r
1626 &gEfiComponentNameProtocolGuid,\r
1627 ComponentName,\r
1628 NULL\r
1629 );\r
1630 if (EFI_ERROR (Status)) {\r
1631 goto ON_EXIT;\r
1632 }\r
1633 }\r
1634 \r
1635 Status = gBS->HandleProtocol (\r
1636 gIScsiIp6DriverBinding.DriverBindingHandle,\r
1637 &gEfiComponentName2ProtocolGuid,\r
1638 (VOID **) &ComponentName2\r
1639 );\r
1640 if (!EFI_ERROR (Status)) {\r
1641 gBS->UninstallMultipleProtocolInterfaces (\r
1642 gIScsiIp6DriverBinding.DriverBindingHandle,\r
1643 &gEfiComponentName2ProtocolGuid,\r
1644 ComponentName2,\r
1645 NULL\r
1646 );\r
1647 if (EFI_ERROR (Status)) {\r
1648 goto ON_EXIT;\r
1649 }\r
1650 }\r
4c5a5e0c 1651\r
1652 //\r
18b24f92 1653 // Uninstall the IScsiInitiatorNameProtocol and all the driver binding protocols.\r
4c5a5e0c 1654 //\r
18b24f92
FS
1655 Status = gBS->UninstallMultipleProtocolInterfaces (\r
1656 gIScsiIp4DriverBinding.DriverBindingHandle,\r
1657 &gEfiDriverBindingProtocolGuid,\r
1658 &gIScsiIp4DriverBinding,\r
1659 &gEfiIScsiInitiatorNameProtocolGuid,\r
1660 &gIScsiInitiatorName,\r
1661 NULL\r
1662 );\r
1663 if (EFI_ERROR (Status)) {\r
1664 goto ON_EXIT;\r
1665 }\r
216f7970 1666\r
18b24f92
FS
1667 Status = gBS->UninstallMultipleProtocolInterfaces (\r
1668 gIScsiIp6DriverBinding.DriverBindingHandle,\r
1669 &gEfiDriverBindingProtocolGuid,\r
1670 &gIScsiIp6DriverBinding,\r
1671 NULL\r
1672 );\r
1673\r
1674ON_EXIT:\r
1675\r
1676 if (DeviceHandleBuffer != NULL) {\r
1677 FreePool (DeviceHandleBuffer);\r
216f7970 1678 }\r
4c5a5e0c 1679 \r
18b24f92 1680 return Status;\r
4c5a5e0c 1681}\r
1682\r
1683/**\r
1684 This is the declaration of an EFI image entry point. This entry point is\r
1685 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including\r
1686 both device drivers and bus drivers.\r
1687 \r
1688 The entry point for iSCSI driver which initializes the global variables and\r
1689 installs the driver binding, component name protocol, iSCSI initiator name\r
1690 protocol and Authentication Info protocol on its image.\r
1691 \r
1692 @param[in] ImageHandle The firmware allocated handle for the UEFI image.\r
1693 @param[in] SystemTable A pointer to the EFI System Table.\r
1694\r
1695 @retval EFI_SUCCESS The operation completed successfully.\r
1696 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
1697\r
1698**/\r
1699EFI_STATUS\r
1700EFIAPI\r
1701IScsiDriverEntryPoint (\r
1702 IN EFI_HANDLE ImageHandle,\r
1703 IN EFI_SYSTEM_TABLE *SystemTable\r
1704 )\r
1705{\r
1706 EFI_STATUS Status;\r
1707 EFI_ISCSI_INITIATOR_NAME_PROTOCOL *IScsiInitiatorName;\r
1708 EFI_AUTHENTICATION_INFO_PROTOCOL *AuthenticationInfo;\r
1709\r
1710 //\r
1711 // There should be only one EFI_ISCSI_INITIATOR_NAME_PROTOCOL.\r
1712 //\r
1713 Status = gBS->LocateProtocol (\r
1714 &gEfiIScsiInitiatorNameProtocolGuid,\r
1715 NULL,\r
1716 (VOID **) &IScsiInitiatorName\r
1717 );\r
1718 if (!EFI_ERROR (Status)) {\r
1719 return EFI_ACCESS_DENIED;\r
1720 }\r
1721\r
1722 //\r
1723 // Initialize the EFI Driver Library.\r
1724 //\r
1725 Status = EfiLibInstallDriverBindingComponentName2 (\r
1726 ImageHandle,\r
1727 SystemTable,\r
6879581d 1728 &gIScsiIp4DriverBinding,\r
4c5a5e0c 1729 ImageHandle,\r
1730 &gIScsiComponentName,\r
1731 &gIScsiComponentName2\r
1732 );\r
1733 if (EFI_ERROR (Status)) {\r
1734 return Status;\r
1735 }\r
1736\r
6879581d 1737 Status = EfiLibInstallDriverBindingComponentName2 (\r
1738 ImageHandle,\r
1739 SystemTable,\r
1740 &gIScsiIp6DriverBinding,\r
1741 NULL,\r
1742 &gIScsiComponentName,\r
1743 &gIScsiComponentName2\r
1744 );\r
1745 if (EFI_ERROR (Status)) {\r
1746 goto Error1;\r
1747 }\r
1748 \r
4c5a5e0c 1749 //\r
1750 // Install the iSCSI Initiator Name Protocol.\r
1751 //\r
1752 Status = gBS->InstallProtocolInterface (\r
1753 &ImageHandle,\r
1754 &gEfiIScsiInitiatorNameProtocolGuid,\r
1755 EFI_NATIVE_INTERFACE,\r
1756 &gIScsiInitiatorName\r
1757 );\r
1758 if (EFI_ERROR (Status)) {\r
6879581d 1759 goto Error2;\r
4c5a5e0c 1760 } \r
1761\r
1762 //\r
1763 // Create the private data structures.\r
1764 //\r
1765 mPrivate = AllocateZeroPool (sizeof (ISCSI_PRIVATE_DATA));\r
1766 if (mPrivate == NULL) {\r
1767 Status = EFI_OUT_OF_RESOURCES;\r
6879581d 1768 goto Error3;\r
4c5a5e0c 1769 }\r
1770\r
1771 InitializeListHead (&mPrivate->NicInfoList);\r
1772 InitializeListHead (&mPrivate->AttemptConfigs);\r
1773\r
1774 //\r
1775 // Initialize the configuration form of iSCSI.\r
1776 //\r
6879581d 1777 Status = IScsiConfigFormInit (gIScsiIp4DriverBinding.DriverBindingHandle);\r
4c5a5e0c 1778 if (EFI_ERROR (Status)) {\r
6879581d 1779 goto Error4;\r
4c5a5e0c 1780 }\r
1781\r
1782 //\r
1783 // There should be only one EFI_AUTHENTICATION_INFO_PROTOCOL. If already exists,\r
1784 // do not produce the protocol instance.\r
1785 //\r
1786 Status = gBS->LocateProtocol (\r
1787 &gEfiAuthenticationInfoProtocolGuid,\r
1788 NULL,\r
1789 (VOID **) &AuthenticationInfo\r
1790 );\r
1791 if (Status == EFI_NOT_FOUND) {\r
1792 Status = gBS->InstallProtocolInterface (\r
1793 &ImageHandle,\r
1794 &gEfiAuthenticationInfoProtocolGuid,\r
1795 EFI_NATIVE_INTERFACE,\r
1796 &gIScsiAuthenticationInfo\r
1797 );\r
1798 if (EFI_ERROR (Status)) {\r
6879581d 1799 goto Error5;\r
4c5a5e0c 1800 } \r
1801 }\r
1802\r
1803 return EFI_SUCCESS;\r
1804\r
6879581d 1805Error5:\r
1806 IScsiConfigFormUnload (gIScsiIp4DriverBinding.DriverBindingHandle);\r
4c5a5e0c 1807\r
6879581d 1808Error4:\r
4c5a5e0c 1809 FreePool (mPrivate);\r
1810\r
6879581d 1811Error3:\r
4c5a5e0c 1812 gBS->UninstallMultipleProtocolInterfaces (\r
1813 ImageHandle,\r
1814 &gEfiIScsiInitiatorNameProtocolGuid,\r
1815 &gIScsiInitiatorName,\r
1816 NULL\r
1817 );\r
1818\r
6879581d 1819Error2:\r
1820 gBS->UninstallMultipleProtocolInterfaces (\r
1821 gIScsiIp6DriverBinding.DriverBindingHandle,\r
1822 &gEfiDriverBindingProtocolGuid,\r
1823 &gIScsiIp6DriverBinding,\r
1824 &gEfiComponentName2ProtocolGuid,\r
1825 &gIScsiComponentName2,\r
1826 &gEfiComponentNameProtocolGuid,\r
1827 &gIScsiComponentName,\r
1828 NULL\r
1829 );\r
1830\r
4c5a5e0c 1831Error1:\r
1832 gBS->UninstallMultipleProtocolInterfaces (\r
1833 ImageHandle,\r
1834 &gEfiDriverBindingProtocolGuid,\r
6879581d 1835 &gIScsiIp4DriverBinding,\r
4c5a5e0c 1836 &gEfiComponentName2ProtocolGuid,\r
1837 &gIScsiComponentName2,\r
1838 &gEfiComponentNameProtocolGuid,\r
1839 &gIScsiComponentName,\r
1840 NULL\r
1841 );\r
1842\r
1843 return Status;\r
1844}\r
1845\r