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