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