]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/IScsiDxe/IScsiMisc.c
MdePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / NetworkPkg / IScsiDxe / IScsiMisc.c
CommitLineData
4c5a5e0c 1/** @file\r
2 Miscellaneous routines for iSCSI driver.\r
3\r
a37c60b6 4Copyright (c) 2004 - 2018, 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
17GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 IScsiHexString[] = "0123456789ABCDEFabcdef";\r
18\r
19/**\r
20 Removes (trims) specified leading and trailing characters from a string.\r
21\r
22 @param[in, out] Str Pointer to the null-terminated string to be trimmed.\r
f75a7f56 23 On return, Str will hold the trimmed string.\r
4c5a5e0c 24\r
25 @param[in] CharC Character will be trimmed from str.\r
26\r
27**/\r
28VOID\r
29IScsiStrTrim (\r
30 IN OUT CHAR16 *Str,\r
31 IN CHAR16 CharC\r
32 )\r
33{\r
34 CHAR16 *Pointer1;\r
35 CHAR16 *Pointer2;\r
f75a7f56 36\r
4c5a5e0c 37 if (*Str == 0) {\r
38 return ;\r
39 }\r
f75a7f56 40\r
4c5a5e0c 41 //\r
42 // Trim off the leading and trailing characters c\r
43 //\r
44 for (Pointer1 = Str; (*Pointer1 != 0) && (*Pointer1 == CharC); Pointer1++) {\r
45 ;\r
46 }\r
f75a7f56 47\r
4c5a5e0c 48 Pointer2 = Str;\r
49 if (Pointer2 == Pointer1) {\r
50 while (*Pointer1 != 0) {\r
51 Pointer2++;\r
52 Pointer1++;\r
53 }\r
54 } else {\r
f75a7f56
LG
55 while (*Pointer1 != 0) {\r
56 *Pointer2 = *Pointer1;\r
4c5a5e0c 57 Pointer1++;\r
58 Pointer2++;\r
59 }\r
60 *Pointer2 = 0;\r
61 }\r
f75a7f56
LG
62\r
63\r
4c5a5e0c 64 for (Pointer1 = Str + StrLen(Str) - 1; Pointer1 >= Str && *Pointer1 == CharC; Pointer1--) {\r
65 ;\r
66 }\r
f75a7f56 67 if (Pointer1 != Str + StrLen(Str) - 1) {\r
4c5a5e0c 68 *(Pointer1 + 1) = 0;\r
69 }\r
70}\r
71\r
72/**\r
73 Calculate the prefix length of the IPv4 subnet mask.\r
74\r
75 @param[in] SubnetMask The IPv4 subnet mask.\r
76\r
77 @return The prefix length of the subnet mask.\r
78 @retval 0 Other errors as indicated.\r
79\r
80**/\r
81UINT8\r
82IScsiGetSubnetMaskPrefixLength (\r
83 IN EFI_IPv4_ADDRESS *SubnetMask\r
84 )\r
85{\r
86 UINT8 Len;\r
87 UINT32 ReverseMask;\r
88\r
89 //\r
90 // The SubnetMask is in network byte order.\r
91 //\r
92 ReverseMask = (SubnetMask->Addr[0] << 24) | (SubnetMask->Addr[1] << 16) | (SubnetMask->Addr[2] << 8) | (SubnetMask->Addr[3]);\r
93\r
94 //\r
95 // Reverse it.\r
96 //\r
97 ReverseMask = ~ReverseMask;\r
98\r
99 if ((ReverseMask & (ReverseMask + 1)) != 0) {\r
100 return 0;\r
101 }\r
102\r
103 Len = 0;\r
104\r
105 while (ReverseMask != 0) {\r
106 ReverseMask = ReverseMask >> 1;\r
107 Len++;\r
108 }\r
109\r
110 return (UINT8) (32 - Len);\r
111}\r
112\r
113\r
114/**\r
115 Convert the hexadecimal encoded LUN string into the 64-bit LUN.\r
116\r
117 @param[in] Str The hexadecimal encoded LUN string.\r
118 @param[out] Lun Storage to return the 64-bit LUN.\r
119\r
120 @retval EFI_SUCCESS The 64-bit LUN is stored in Lun.\r
121 @retval EFI_INVALID_PARAMETER The string is malformatted.\r
122\r
123**/\r
124EFI_STATUS\r
125IScsiAsciiStrToLun (\r
126 IN CHAR8 *Str,\r
127 OUT UINT8 *Lun\r
128 )\r
129{\r
130 UINTN Index, IndexValue, IndexNum, SizeStr;\r
131 CHAR8 TemStr[2];\r
132 UINT8 TemValue;\r
133 UINT16 Value[4];\r
f75a7f56 134\r
4c5a5e0c 135 ZeroMem (Lun, 8);\r
136 ZeroMem (TemStr, 2);\r
137 ZeroMem ((UINT8 *) Value, sizeof (Value));\r
f75a7f56 138 SizeStr = AsciiStrLen (Str);\r
4c5a5e0c 139 IndexValue = 0;\r
140 IndexNum = 0;\r
141\r
142 for (Index = 0; Index < SizeStr; Index ++) {\r
143 TemStr[0] = Str[Index];\r
144 TemValue = (UINT8) AsciiStrHexToUint64 (TemStr);\r
145 if (TemValue == 0 && TemStr[0] != '0') {\r
146 if ((TemStr[0] != '-') || (IndexNum == 0)) {\r
147 //\r
148 // Invalid Lun Char.\r
149 //\r
150 return EFI_INVALID_PARAMETER;\r
151 }\r
152 }\r
f75a7f56 153\r
4c5a5e0c 154 if ((TemValue == 0) && (TemStr[0] == '-')) {\r
155 //\r
156 // Next Lun value.\r
157 //\r
158 if (++IndexValue >= 4) {\r
159 //\r
160 // Max 4 Lun value.\r
161 //\r
162 return EFI_INVALID_PARAMETER;\r
163 }\r
164 //\r
165 // Restart str index for the next lun value.\r
166 //\r
167 IndexNum = 0;\r
168 continue;\r
169 }\r
f75a7f56 170\r
4c5a5e0c 171 if (++IndexNum > 4) {\r
f75a7f56 172 //\r
4c5a5e0c 173 // Each Lun Str can't exceed size 4, because it will be as UINT16 value.\r
174 //\r
175 return EFI_INVALID_PARAMETER;\r
176 }\r
f75a7f56 177\r
4c5a5e0c 178 //\r
179 // Combine UINT16 value.\r
180 //\r
181 Value[IndexValue] = (UINT16) ((Value[IndexValue] << 4) + TemValue);\r
182 }\r
f75a7f56 183\r
4c5a5e0c 184 for (Index = 0; Index <= IndexValue; Index ++) {\r
185 *((UINT16 *) &Lun[Index * 2]) = HTONS (Value[Index]);\r
186 }\r
f75a7f56 187\r
4c5a5e0c 188 return EFI_SUCCESS;\r
189}\r
190\r
191/**\r
192 Convert the 64-bit LUN into the hexadecimal encoded LUN string.\r
193\r
194 @param[in] Lun The 64-bit LUN.\r
195 @param[out] Str The storage to return the hexadecimal encoded LUN string.\r
196\r
197**/\r
198VOID\r
199IScsiLunToUnicodeStr (\r
200 IN UINT8 *Lun,\r
201 OUT CHAR16 *Str\r
202 )\r
203{\r
204 UINTN Index;\r
205 CHAR16 *TempStr;\r
206\r
207 TempStr = Str;\r
208\r
209 for (Index = 0; Index < 4; Index++) {\r
210\r
211 if ((Lun[2 * Index] | Lun[2 * Index + 1]) == 0) {\r
a4faf336 212 CopyMem (TempStr, L"0-", sizeof (L"0-"));\r
4c5a5e0c 213 } else {\r
214 TempStr[0] = (CHAR16) IScsiHexString[Lun[2 * Index] >> 4];\r
215 TempStr[1] = (CHAR16) IScsiHexString[Lun[2 * Index] & 0x0F];\r
216 TempStr[2] = (CHAR16) IScsiHexString[Lun[2 * Index + 1] >> 4];\r
217 TempStr[3] = (CHAR16) IScsiHexString[Lun[2 * Index + 1] & 0x0F];\r
218 TempStr[4] = L'-';\r
219 TempStr[5] = 0;\r
220\r
221 IScsiStrTrim (TempStr, L'0');\r
222 }\r
223\r
224 TempStr += StrLen (TempStr);\r
225 }\r
a4faf336
FS
226 //\r
227 // Remove the last '-'\r
228 //\r
35320304 229 ASSERT (StrLen(Str) >= 1);\r
4c5a5e0c 230 Str[StrLen (Str) - 1] = 0;\r
231\r
232 for (Index = StrLen (Str) - 1; Index > 1; Index = Index - 2) {\r
233 if ((Str[Index] == L'0') && (Str[Index - 1] == L'-')) {\r
234 Str[Index - 1] = 0;\r
235 } else {\r
236 break;\r
237 }\r
238 }\r
239}\r
240\r
241/**\r
242 Convert the formatted IP address into the binary IP address.\r
243\r
244 @param[in] Str The UNICODE string.\r
245 @param[in] IpMode Indicates whether the IP address is v4 or v6.\r
246 @param[out] Ip The storage to return the ASCII string.\r
247\r
248 @retval EFI_SUCCESS The binary IP address is returned in Ip.\r
249 @retval EFI_INVALID_PARAMETER The IP string is malformatted or IpMode is\r
250 invalid.\r
251\r
252**/\r
253EFI_STATUS\r
254IScsiAsciiStrToIp (\r
255 IN CHAR8 *Str,\r
256 IN UINT8 IpMode,\r
257 OUT EFI_IP_ADDRESS *Ip\r
258 )\r
259{\r
260 EFI_STATUS Status;\r
261\r
262 if (IpMode == IP_MODE_IP4 || IpMode == IP_MODE_AUTOCONFIG_IP4) {\r
263 return NetLibAsciiStrToIp4 (Str, &Ip->v4);\r
264\r
265 } else if (IpMode == IP_MODE_IP6 || IpMode == IP_MODE_AUTOCONFIG_IP6) {\r
266 return NetLibAsciiStrToIp6 (Str, &Ip->v6);\r
267\r
268 } else if (IpMode == IP_MODE_AUTOCONFIG) {\r
269 Status = NetLibAsciiStrToIp4 (Str, &Ip->v4);\r
270 if (!EFI_ERROR (Status)) {\r
271 return Status;\r
272 }\r
273 return NetLibAsciiStrToIp6 (Str, &Ip->v6);\r
274\r
275 }\r
276\r
277 return EFI_INVALID_PARAMETER;\r
278}\r
279\r
280/**\r
281 Convert the mac address into a hexadecimal encoded "-" seperated string.\r
282\r
283 @param[in] Mac The mac address.\r
284 @param[in] Len Length in bytes of the mac address.\r
285 @param[in] VlanId VLAN ID of the network device.\r
286 @param[out] Str The storage to return the mac string.\r
287\r
288**/\r
289VOID\r
290IScsiMacAddrToStr (\r
291 IN EFI_MAC_ADDRESS *Mac,\r
292 IN UINT32 Len,\r
293 IN UINT16 VlanId,\r
294 OUT CHAR16 *Str\r
295 )\r
296{\r
297 UINT32 Index;\r
298 CHAR16 *String;\r
299\r
300 for (Index = 0; Index < Len; Index++) {\r
301 Str[3 * Index] = (CHAR16) IScsiHexString[(Mac->Addr[Index] >> 4) & 0x0F];\r
302 Str[3 * Index + 1] = (CHAR16) IScsiHexString[Mac->Addr[Index] & 0x0F];\r
c0d494b5 303 Str[3 * Index + 2] = L':';\r
4c5a5e0c 304 }\r
305\r
306 String = &Str[3 * Index - 1] ;\r
307 if (VlanId != 0) {\r
308 String += UnicodeSPrint (String, 6 * sizeof (CHAR16), L"\\%04x", (UINTN) VlanId);\r
309 }\r
310\r
311 *String = L'\0';\r
312}\r
313\r
314/**\r
315 Convert the binary encoded buffer into a hexadecimal encoded string.\r
316\r
317 @param[in] BinBuffer The buffer containing the binary data.\r
318 @param[in] BinLength Length of the binary buffer.\r
319 @param[in, out] HexStr Pointer to the string.\r
320 @param[in, out] HexLength The length of the string.\r
321\r
f75a7f56 322 @retval EFI_SUCCESS The binary data is converted to the hexadecimal string\r
4c5a5e0c 323 and the length of the string is updated.\r
324 @retval EFI_BUFFER_TOO_SMALL The string is too small.\r
325 @retval EFI_INVALID_PARAMETER The IP string is malformatted.\r
326\r
327**/\r
328EFI_STATUS\r
329IScsiBinToHex (\r
330 IN UINT8 *BinBuffer,\r
331 IN UINT32 BinLength,\r
332 IN OUT CHAR8 *HexStr,\r
333 IN OUT UINT32 *HexLength\r
334 )\r
335{\r
336 UINTN Index;\r
337\r
338 if ((HexStr == NULL) || (BinBuffer == NULL) || (BinLength == 0)) {\r
339 return EFI_INVALID_PARAMETER;\r
340 }\r
341\r
342 if (((*HexLength) - 3) < BinLength * 2) {\r
343 *HexLength = BinLength * 2 + 3;\r
344 return EFI_BUFFER_TOO_SMALL;\r
345 }\r
346\r
347 *HexLength = BinLength * 2 + 3;\r
348 //\r
349 // Prefix for Hex String.\r
350 //\r
351 HexStr[0] = '0';\r
352 HexStr[1] = 'x';\r
353\r
354 for (Index = 0; Index < BinLength; Index++) {\r
355 HexStr[Index * 2 + 2] = IScsiHexString[BinBuffer[Index] >> 4];\r
356 HexStr[Index * 2 + 3] = IScsiHexString[BinBuffer[Index] & 0xf];\r
357 }\r
358\r
359 HexStr[Index * 2 + 2] = '\0';\r
360\r
361 return EFI_SUCCESS;\r
362}\r
363\r
364\r
365/**\r
366 Convert the hexadecimal string into a binary encoded buffer.\r
367\r
368 @param[in, out] BinBuffer The binary buffer.\r
369 @param[in, out] BinLength Length of the binary buffer.\r
370 @param[in] HexStr The hexadecimal string.\r
371\r
372 @retval EFI_SUCCESS The hexadecimal string is converted into a binary\r
373 encoded buffer.\r
374 @retval EFI_BUFFER_TOO_SMALL The binary buffer is too small to hold the converted data.\r
375\r
376**/\r
377EFI_STATUS\r
378IScsiHexToBin (\r
379 IN OUT UINT8 *BinBuffer,\r
380 IN OUT UINT32 *BinLength,\r
381 IN CHAR8 *HexStr\r
382 )\r
383{\r
384 UINTN Index;\r
385 UINTN Length;\r
386 UINT8 Digit;\r
387 CHAR8 TemStr[2];\r
f75a7f56 388\r
4c5a5e0c 389 ZeroMem (TemStr, sizeof (TemStr));\r
390\r
391 //\r
392 // Find out how many hex characters the string has.\r
393 //\r
394 if ((HexStr[0] == '0') && ((HexStr[1] == 'x') || (HexStr[1] == 'X'))) {\r
395 HexStr += 2;\r
396 }\r
f75a7f56 397\r
4c5a5e0c 398 Length = AsciiStrLen (HexStr);\r
399\r
400 for (Index = 0; Index < Length; Index ++) {\r
401 TemStr[0] = HexStr[Index];\r
402 Digit = (UINT8) AsciiStrHexToUint64 (TemStr);\r
403 if (Digit == 0 && TemStr[0] != '0') {\r
404 //\r
405 // Invalid Lun Char.\r
406 //\r
407 break;\r
408 }\r
409 if ((Index & 1) == 0) {\r
410 BinBuffer [Index/2] = Digit;\r
411 } else {\r
412 BinBuffer [Index/2] = (UINT8) ((BinBuffer [Index/2] << 4) + Digit);\r
413 }\r
414 }\r
f75a7f56 415\r
4c5a5e0c 416 *BinLength = (UINT32) ((Index + 1)/2);\r
417\r
418 return EFI_SUCCESS;\r
419}\r
420\r
421\r
422/**\r
423 Convert the decimal-constant string or hex-constant string into a numerical value.\r
424\r
425 @param[in] Str String in decimal or hex.\r
426\r
427 @return The numerical value.\r
428\r
429**/\r
430UINTN\r
431IScsiNetNtoi (\r
432 IN CHAR8 *Str\r
433 )\r
434{\r
435 if ((Str[0] == '0') && ((Str[1] == 'x') || (Str[1] == 'X'))) {\r
436 Str += 2;\r
437\r
438 return AsciiStrHexToUintn (Str);\r
439 }\r
440\r
441 return AsciiStrDecimalToUintn (Str);\r
442}\r
443\r
444\r
445/**\r
446 Generate random numbers.\r
447\r
448 @param[in, out] Rand The buffer to contain random numbers.\r
449 @param[in] RandLength The length of the Rand buffer.\r
450\r
451**/\r
452VOID\r
453IScsiGenRandom (\r
454 IN OUT UINT8 *Rand,\r
455 IN UINTN RandLength\r
456 )\r
457{\r
458 UINT32 Random;\r
459\r
460 while (RandLength > 0) {\r
461 Random = NET_RANDOM (NetRandomInitSeed ());\r
462 *Rand++ = (UINT8) (Random);\r
463 RandLength--;\r
464 }\r
465}\r
466\r
467\r
6b08dd6e
JW
468/**\r
469 Check whether UNDI protocol supports IPv6.\r
470\r
471 @param[in] ControllerHandle Controller handle.\r
472 @param[in] Image Handle of the image.\r
473 @param[out] Ipv6Support TRUE if UNDI supports IPv6.\r
474\r
475 @retval EFI_SUCCESS Get the result whether UNDI supports IPv6 by NII or AIP protocol successfully.\r
476 @retval EFI_NOT_FOUND Don't know whether UNDI supports IPv6 since NII or AIP is not available.\r
477\r
478**/\r
479EFI_STATUS\r
480IScsiCheckIpv6Support (\r
481 IN EFI_HANDLE ControllerHandle,\r
482 IN EFI_HANDLE Image,\r
483 OUT BOOLEAN *Ipv6Support\r
484 )\r
485{\r
486 EFI_HANDLE Handle;\r
487 EFI_ADAPTER_INFORMATION_PROTOCOL *Aip;\r
488 EFI_STATUS Status;\r
489 EFI_GUID *InfoTypesBuffer;\r
490 UINTN InfoTypeBufferCount;\r
491 UINTN TypeIndex;\r
492 BOOLEAN Supported;\r
493 VOID *InfoBlock;\r
494 UINTN InfoBlockSize;\r
f75a7f56 495\r
6b08dd6e
JW
496 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *Nii;\r
497\r
498 ASSERT (Ipv6Support != NULL);\r
499\r
500 //\r
501 // Check whether the UNDI supports IPv6 by NII protocol.\r
502 //\r
503 Status = gBS->OpenProtocol (\r
504 ControllerHandle,\r
505 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
506 (VOID **) &Nii,\r
507 Image,\r
508 ControllerHandle,\r
509 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
510 );\r
511 if (Status == EFI_SUCCESS) {\r
512 *Ipv6Support = Nii->Ipv6Supported;\r
513 return EFI_SUCCESS;\r
514 }\r
515\r
516 //\r
517 // Get the NIC handle by SNP protocol.\r
f75a7f56 518 //\r
6b08dd6e
JW
519 Handle = NetLibGetSnpHandle (ControllerHandle, NULL);\r
520 if (Handle == NULL) {\r
521 return EFI_NOT_FOUND;\r
522 }\r
523\r
524 Aip = NULL;\r
525 Status = gBS->HandleProtocol (\r
526 Handle,\r
527 &gEfiAdapterInformationProtocolGuid,\r
528 (VOID *) &Aip\r
529 );\r
530 if (EFI_ERROR (Status) || Aip == NULL) {\r
531 return EFI_NOT_FOUND;\r
532 }\r
533\r
534 InfoTypesBuffer = NULL;\r
535 InfoTypeBufferCount = 0;\r
536 Status = Aip->GetSupportedTypes (Aip, &InfoTypesBuffer, &InfoTypeBufferCount);\r
537 if (EFI_ERROR (Status) || InfoTypesBuffer == NULL) {\r
538 FreePool (InfoTypesBuffer);\r
539 return EFI_NOT_FOUND;\r
540 }\r
541\r
542 Supported = FALSE;\r
543 for (TypeIndex = 0; TypeIndex < InfoTypeBufferCount; TypeIndex++) {\r
544 if (CompareGuid (&InfoTypesBuffer[TypeIndex], &gEfiAdapterInfoUndiIpv6SupportGuid)) {\r
545 Supported = TRUE;\r
546 break;\r
547 }\r
548 }\r
549\r
550 FreePool (InfoTypesBuffer);\r
551 if (!Supported) {\r
552 return EFI_NOT_FOUND;\r
553 }\r
554\r
555 //\r
556 // We now have adapter information block.\r
557 //\r
558 InfoBlock = NULL;\r
559 InfoBlockSize = 0;\r
560 Status = Aip->GetInformation (Aip, &gEfiAdapterInfoUndiIpv6SupportGuid, &InfoBlock, &InfoBlockSize);\r
561 if (EFI_ERROR (Status) || InfoBlock == NULL) {\r
562 FreePool (InfoBlock);\r
563 return EFI_NOT_FOUND;\r
f75a7f56 564 }\r
6b08dd6e
JW
565\r
566 *Ipv6Support = ((EFI_ADAPTER_INFO_UNDI_IPV6_SUPPORT *) InfoBlock)->Ipv6Support;\r
567 FreePool (InfoBlock);\r
f75a7f56 568\r
6b08dd6e
JW
569 return EFI_SUCCESS;\r
570}\r
571\r
4c5a5e0c 572/**\r
573 Record the NIC info in global structure.\r
574\r
575 @param[in] Controller The handle of the controller.\r
6b08dd6e 576 @param[in] Image Handle of the image.\r
4c5a5e0c 577\r
578 @retval EFI_SUCCESS The operation is completed.\r
579 @retval EFI_OUT_OF_RESOURCES Do not have sufficient resources to finish this\r
580 operation.\r
581\r
582**/\r
583EFI_STATUS\r
584IScsiAddNic (\r
6b08dd6e
JW
585 IN EFI_HANDLE Controller,\r
586 IN EFI_HANDLE Image\r
4c5a5e0c 587 )\r
588{\r
589 EFI_STATUS Status;\r
590 ISCSI_NIC_INFO *NicInfo;\r
591 LIST_ENTRY *Entry;\r
592 EFI_MAC_ADDRESS MacAddr;\r
593 UINTN HwAddressSize;\r
594 UINT16 VlanId;\r
595\r
596 //\r
597 // Get MAC address of this network device.\r
598 //\r
599 Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);\r
600 if (EFI_ERROR (Status)) {\r
601 return Status;\r
602 }\r
603\r
604 //\r
605 // Get VLAN ID of this network device.\r
606 //\r
607 VlanId = NetLibGetVlanId (Controller);\r
608\r
609 //\r
610 // Check whether the NIC info already exists. Return directly if so.\r
611 //\r
612 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {\r
613 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);\r
614 if (NicInfo->HwAddressSize == HwAddressSize &&\r
615 CompareMem (&NicInfo->PermanentAddress, MacAddr.Addr, HwAddressSize) == 0 &&\r
616 NicInfo->VlanId == VlanId) {\r
617 mPrivate->CurrentNic = NicInfo->NicIndex;\r
f75a7f56
LG
618\r
619 //\r
6b08dd6e 620 // Set IPv6 available flag.\r
f75a7f56 621 //\r
6b08dd6e
JW
622 Status = IScsiCheckIpv6Support (Controller, Image, &NicInfo->Ipv6Available);\r
623 if (EFI_ERROR (Status)) {\r
624 //\r
f75a7f56 625 // Fail to get the data whether UNDI supports IPv6.\r
6b08dd6e
JW
626 // Set default value to TRUE.\r
627 //\r
628 NicInfo->Ipv6Available = TRUE;\r
629 }\r
f75a7f56 630\r
4c5a5e0c 631 return EFI_SUCCESS;\r
632 }\r
633\r
634 if (mPrivate->MaxNic < NicInfo->NicIndex) {\r
635 mPrivate->MaxNic = NicInfo->NicIndex;\r
636 }\r
637 }\r
638\r
639 //\r
640 // Record the NIC info in private structure.\r
641 //\r
642 NicInfo = AllocateZeroPool (sizeof (ISCSI_NIC_INFO));\r
643 if (NicInfo == NULL) {\r
644 return EFI_OUT_OF_RESOURCES;\r
645 }\r
646\r
647 CopyMem (&NicInfo->PermanentAddress, MacAddr.Addr, HwAddressSize);\r
648 NicInfo->HwAddressSize = (UINT32) HwAddressSize;\r
649 NicInfo->VlanId = VlanId;\r
650 NicInfo->NicIndex = (UINT8) (mPrivate->MaxNic + 1);\r
651 mPrivate->MaxNic = NicInfo->NicIndex;\r
f75a7f56 652\r
6b08dd6e
JW
653 //\r
654 // Set IPv6 available flag.\r
f75a7f56 655 //\r
6b08dd6e
JW
656 Status = IScsiCheckIpv6Support (Controller, Image, &NicInfo->Ipv6Available);\r
657 if (EFI_ERROR (Status)) {\r
658 //\r
f75a7f56 659 // Fail to get the data whether UNDI supports IPv6.\r
6b08dd6e
JW
660 // Set default value to TRUE.\r
661 //\r
662 NicInfo->Ipv6Available = TRUE;\r
663 }\r
f75a7f56 664\r
4c5a5e0c 665 //\r
666 // Get the PCI location.\r
667 //\r
668 IScsiGetNICPciLocation (\r
669 Controller,\r
670 &NicInfo->BusNumber,\r
671 &NicInfo->DeviceNumber,\r
672 &NicInfo->FunctionNumber\r
673 );\r
674\r
675 InsertTailList (&mPrivate->NicInfoList, &NicInfo->Link);\r
676 mPrivate->NicCount++;\r
677\r
678 mPrivate->CurrentNic = NicInfo->NicIndex;\r
679 return EFI_SUCCESS;\r
680}\r
681\r
682\r
683/**\r
684 Delete the recorded NIC info from global structure. Also delete corresponding\r
685 attempts.\r
686\r
687 @param[in] Controller The handle of the controller.\r
688\r
689 @retval EFI_SUCCESS The operation is completed.\r
690 @retval EFI_NOT_FOUND The NIC info to be deleted is not recorded.\r
691\r
692**/\r
693EFI_STATUS\r
694IScsiRemoveNic (\r
695 IN EFI_HANDLE Controller\r
696 )\r
697{\r
698 EFI_STATUS Status;\r
699 ISCSI_NIC_INFO *NicInfo;\r
700 LIST_ENTRY *Entry;\r
701 LIST_ENTRY *NextEntry;\r
702 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
703 ISCSI_NIC_INFO *ThisNic;\r
704 EFI_MAC_ADDRESS MacAddr;\r
705 UINTN HwAddressSize;\r
706 UINT16 VlanId;\r
707\r
708 //\r
709 // Get MAC address of this network device.\r
710 //\r
711 Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);\r
712 if (EFI_ERROR (Status)) {\r
713 return Status;\r
714 }\r
715\r
716 //\r
717 // Get VLAN ID of this network device.\r
718 //\r
719 VlanId = NetLibGetVlanId (Controller);\r
720\r
721 //\r
722 // Check whether the NIC information exists.\r
723 //\r
724 ThisNic = NULL;\r
725\r
726 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {\r
727 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);\r
728 if (NicInfo->HwAddressSize == HwAddressSize &&\r
729 CompareMem (&NicInfo->PermanentAddress, MacAddr.Addr, HwAddressSize) == 0 &&\r
730 NicInfo->VlanId == VlanId) {\r
731\r
732 ThisNic = NicInfo;\r
733 break;\r
734 }\r
735 }\r
736\r
737 if (ThisNic == NULL) {\r
738 return EFI_NOT_FOUND;\r
739 }\r
740\r
741 mPrivate->CurrentNic = ThisNic->NicIndex;\r
742\r
743 RemoveEntryList (&ThisNic->Link);\r
744 FreePool (ThisNic);\r
745 mPrivate->NicCount--;\r
746\r
747 //\r
748 // Remove all attempts related to this NIC.\r
749 //\r
750 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mPrivate->AttemptConfigs) {\r
751 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
752 if (AttemptConfigData->NicIndex == mPrivate->CurrentNic) {\r
753 RemoveEntryList (&AttemptConfigData->Link);\r
754 mPrivate->AttemptCount--;\r
755\r
756 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO && mPrivate->MpioCount > 0) {\r
757 if (--mPrivate->MpioCount == 0) {\r
758 mPrivate->EnableMpio = FALSE;\r
759 }\r
760\r
761 if (AttemptConfigData->AuthenticationType == ISCSI_AUTH_TYPE_KRB && mPrivate->Krb5MpioCount > 0) {\r
762 mPrivate->Krb5MpioCount--;\r
763 }\r
764\r
765 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED && mPrivate->SinglePathCount > 0) {\r
766 mPrivate->SinglePathCount--;\r
767\r
768 if (mPrivate->ValidSinglePathCount > 0) {\r
769 mPrivate->ValidSinglePathCount--;\r
770 }\r
771 }\r
772\r
773 FreePool (AttemptConfigData);\r
774 }\r
775 }\r
776\r
8d1f5e04
ZL
777 return EFI_SUCCESS;\r
778}\r
779\r
780/**\r
781 Create and initialize the Attempts.\r
782\r
783 @param[in] AttemptNum The number of Attempts will be created.\r
784\r
785 @retval EFI_SUCCESS The Attempts have been created successfully.\r
786 @retval Others Failed to create the Attempt.\r
787\r
788**/\r
789EFI_STATUS\r
790IScsiCreateAttempts (\r
791 IN UINTN AttemptNum\r
792)\r
793{\r
794 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
795 ISCSI_SESSION_CONFIG_NVDATA *ConfigData;\r
796 UINT8 *AttemptConfigOrder;\r
797 UINTN AttemptConfigOrderSize;\r
798 UINT8 *AttemptOrderTmp;\r
799 UINTN TotalNumber;\r
800 UINT8 Index;\r
801 EFI_STATUS Status;\r
802\r
803 for (Index = 1; Index <= AttemptNum; Index ++) {\r
804 //\r
805 // Get the initialized attempt order. This is used to essure creating attempts by order.\r
806 //\r
807 AttemptConfigOrder = IScsiGetVariableAndSize (\r
808 L"InitialAttemptOrder",\r
809 &gIScsiConfigGuid,\r
810 &AttemptConfigOrderSize\r
811 );\r
812 TotalNumber = AttemptConfigOrderSize / sizeof (UINT8);\r
813 if (TotalNumber == AttemptNum) {\r
814 Status = EFI_SUCCESS;\r
815 break;\r
816 }\r
817 TotalNumber++;\r
818\r
819 //\r
820 // Append the new created attempt to the end.\r
821 //\r
822 AttemptOrderTmp = AllocateZeroPool (TotalNumber * sizeof (UINT8));\r
823 if (AttemptOrderTmp == NULL) {\r
824 if (AttemptConfigOrder != NULL) {\r
825 FreePool (AttemptConfigOrder);\r
826 }\r
827 return EFI_OUT_OF_RESOURCES;\r
828 }\r
829\r
830 if (AttemptConfigOrder != NULL) {\r
831 CopyMem (AttemptOrderTmp, AttemptConfigOrder, AttemptConfigOrderSize);\r
832 FreePool (AttemptConfigOrder);\r
833 }\r
834\r
835 AttemptOrderTmp[TotalNumber - 1] = Index;\r
836 AttemptConfigOrder = AttemptOrderTmp;\r
837 AttemptConfigOrderSize = TotalNumber * sizeof (UINT8);\r
838\r
839 Status = gRT->SetVariable (\r
840 L"InitialAttemptOrder",\r
841 &gIScsiConfigGuid,\r
842 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
843 AttemptConfigOrderSize,\r
844 AttemptConfigOrder\r
845 );\r
846 FreePool (AttemptConfigOrder);\r
847 if (EFI_ERROR (Status)) {\r
a2481def
VS
848 DEBUG ((DEBUG_ERROR,\r
849 "%a: Failed to set 'InitialAttemptOrder' with Guid (%g): "\r
850 "%r\n",\r
851 __FUNCTION__, &gIScsiConfigGuid, Status));\r
8d1f5e04
ZL
852 return Status;\r
853 }\r
854\r
855 //\r
856 // Create new Attempt\r
857 //\r
858 AttemptConfigData = AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA));\r
859 if (AttemptConfigData == NULL) {\r
860 return EFI_OUT_OF_RESOURCES;\r
861 }\r
862 ConfigData = &AttemptConfigData->SessionConfigData;\r
863 ConfigData->TargetPort = ISCSI_WELL_KNOWN_PORT;\r
864 ConfigData->ConnectTimeout = CONNECT_DEFAULT_TIMEOUT;\r
865 ConfigData->ConnectRetryCount = CONNECT_MIN_RETRY;\r
866\r
867 AttemptConfigData->AuthenticationType = ISCSI_AUTH_TYPE_CHAP;\r
868 AttemptConfigData->AuthConfigData.CHAP.CHAPType = ISCSI_CHAP_UNI;\r
869 //\r
870 // Configure the Attempt index and set variable.\r
871 //\r
872 AttemptConfigData->AttemptConfigIndex = Index;\r
873\r
874 //\r
875 // Set the attempt name according to the order.\r
876 //\r
877 UnicodeSPrint (\r
878 mPrivate->PortString,\r
879 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
880 L"Attempt %d",\r
881 (UINTN) AttemptConfigData->AttemptConfigIndex\r
882 );\r
883 UnicodeStrToAsciiStrS (mPrivate->PortString, AttemptConfigData->AttemptName, ATTEMPT_NAME_SIZE);\r
884\r
885 Status = gRT->SetVariable (\r
886 mPrivate->PortString,\r
887 &gEfiIScsiInitiatorNameProtocolGuid,\r
888 ISCSI_CONFIG_VAR_ATTR,\r
889 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),\r
890 AttemptConfigData\r
891 );\r
892 FreePool (AttemptConfigData);\r
893 if (EFI_ERROR (Status)) {\r
a2481def
VS
894 DEBUG ((DEBUG_ERROR,\r
895 "%a: Failed to set variable (mPrivate->PortString) with Guid (%g): "\r
896 "%r\n",\r
897 __FUNCTION__, &gEfiIScsiInitiatorNameProtocolGuid, Status));\r
8d1f5e04
ZL
898 return Status;\r
899 }\r
c0d494b5 900 }\r
901\r
4c5a5e0c 902 return EFI_SUCCESS;\r
903}\r
904\r
8d1f5e04
ZL
905/**\r
906 Create the iSCSI configuration Keywords for each attempt. You can find the keywords\r
907 defined in the "x-UEFI-ns" namespace (http://www.uefi.org/confignamespace).\r
908\r
909 @param[in] KeywordNum The number Sets of Keywords will be created.\r
910\r
911 @retval EFI_SUCCESS The operation is completed.\r
912 @retval Others Failed to create the Keywords.\r
913\r
914**/\r
915EFI_STATUS\r
916IScsiCreateKeywords (\r
917 IN UINTN KeywordNum\r
918)\r
919{\r
920 VOID *StartOpCodeHandle;\r
921 EFI_IFR_GUID_LABEL *StartLabel;\r
922 VOID *EndOpCodeHandle;\r
923 EFI_IFR_GUID_LABEL *EndLabel;\r
924 UINTN Index;\r
925 EFI_STRING_ID StringToken;\r
926 CHAR16 StringId[64];\r
927 CHAR16 KeywordId[32];\r
928 EFI_STATUS Status;\r
929\r
930 Status = IScsiCreateOpCode (\r
931 KEYWORD_ENTRY_LABEL,\r
932 &StartOpCodeHandle,\r
933 &StartLabel,\r
934 &EndOpCodeHandle,\r
935 &EndLabel\r
936 );\r
937 if (EFI_ERROR (Status)) {\r
938 return EFI_OUT_OF_RESOURCES;\r
939 }\r
940\r
941 for (Index = 1; Index <= KeywordNum; Index ++) {\r
942 //\r
943 // Create iSCSIAttemptName Keyword.\r
944 //\r
945 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_ATTEMPTT_NAME_PROMPT%d", Index);\r
946 StringToken = HiiSetString (\r
947 mCallbackInfo->RegisteredHandle,\r
948 0,\r
949 StringId,\r
950 NULL\r
951 );\r
952 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIAttemptName:%d", Index);\r
953 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
954 HiiCreateStringOpCode (\r
955 StartOpCodeHandle,\r
956 (EFI_QUESTION_ID) (ATTEMPT_ATTEMPT_NAME_QUESTION_ID + (Index - 1)),\r
957 CONFIGURATION_VARSTORE_ID,\r
958 (UINT16) (ATTEMPT_ATTEMPT_NAME_VAR_OFFSET + ATTEMPT_NAME_SIZE * (Index - 1) * sizeof (CHAR16)),\r
959 StringToken,\r
960 StringToken,\r
961 EFI_IFR_FLAG_READ_ONLY,\r
962 0,\r
963 0,\r
964 ATTEMPT_NAME_SIZE,\r
965 NULL\r
966 );\r
967\r
968 //\r
969 // Create iSCSIBootEnable Keyword.\r
970 //\r
971 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_MODE_PROMPT%d", Index);\r
972 StringToken = HiiSetString (\r
973 mCallbackInfo->RegisteredHandle,\r
974 0,\r
975 StringId,\r
976 NULL\r
977 );\r
978 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIBootEnable:%d", Index);\r
979 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
980 HiiCreateNumericOpCode (\r
981 StartOpCodeHandle,\r
982 (EFI_QUESTION_ID) (ATTEMPT_BOOTENABLE_QUESTION_ID + (Index - 1)),\r
983 CONFIGURATION_VARSTORE_ID,\r
984 (UINT16) (ATTEMPT_BOOTENABLE_VAR_OFFSET + (Index - 1)),\r
985 StringToken,\r
986 StringToken,\r
987 0,\r
988 EFI_IFR_NUMERIC_SIZE_1,\r
989 0,\r
990 2,\r
991 0,\r
992 NULL\r
993 );\r
994\r
995 //\r
996 // Create iSCSIIpAddressType Keyword.\r
997 //\r
998 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_IP_MODE_PROMPT%d", Index);\r
999 StringToken = HiiSetString (\r
1000 mCallbackInfo->RegisteredHandle,\r
1001 0,\r
1002 StringId,\r
1003 NULL\r
1004 );\r
1005 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIIpAddressType:%d", Index);\r
1006 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
1007 HiiCreateNumericOpCode (\r
1008 StartOpCodeHandle,\r
1009 (EFI_QUESTION_ID) (ATTEMPT_ADDRESS_TYPE_QUESTION_ID + (Index - 1)),\r
1010 CONFIGURATION_VARSTORE_ID,\r
1011 (UINT16) (ATTEMPT_ADDRESS_TYPE_VAR_OFFSET + (Index - 1)),\r
1012 StringToken,\r
1013 StringToken,\r
1014 0,\r
1015 EFI_IFR_NUMERIC_SIZE_1,\r
1016 0,\r
1017 2,\r
1018 0,\r
1019 NULL\r
1020 );\r
1021\r
1022 //\r
1023 // Create iSCSIConnectRetry Keyword.\r
1024 //\r
1025 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CONNECT_RETRY_PROMPT%d", Index);\r
1026 StringToken = HiiSetString (\r
1027 mCallbackInfo->RegisteredHandle,\r
1028 0,\r
1029 StringId,\r
1030 NULL\r
1031 );\r
1032 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIConnectRetry:%d", Index);\r
1033 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
1034 HiiCreateNumericOpCode (\r
1035 StartOpCodeHandle,\r
1036 (EFI_QUESTION_ID) (ATTEMPT_CONNECT_RETRY_QUESTION_ID + (Index - 1)),\r
1037 CONFIGURATION_VARSTORE_ID,\r
1038 (UINT16) (ATTEMPT_CONNECT_RETRY_VAR_OFFSET + (Index - 1)),\r
1039 StringToken,\r
1040 StringToken,\r
1041 0,\r
1042 EFI_IFR_NUMERIC_SIZE_1,\r
1043 0,\r
1044 16,\r
1045 0,\r
1046 NULL\r
1047 );\r
1048\r
1049 //\r
1050 // Create iSCSIConnectTimeout Keyword.\r
1051 //\r
1052 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CONNECT_TIMEOUT_PROMPT%d", Index);\r
1053 StringToken = HiiSetString (\r
1054 mCallbackInfo->RegisteredHandle,\r
1055 0,\r
1056 StringId,\r
1057 NULL\r
1058 );\r
1059 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIConnectTimeout:%d", Index);\r
1060 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
1061 HiiCreateNumericOpCode (\r
1062 StartOpCodeHandle,\r
1063 (EFI_QUESTION_ID) (ATTEMPT_CONNECT_TIMEOUT_QUESTION_ID + (Index - 1)),\r
1064 CONFIGURATION_VARSTORE_ID,\r
1065 (UINT16) (ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET + 2 * (Index - 1)),\r
1066 StringToken,\r
1067 StringToken,\r
1068 0,\r
1069 EFI_IFR_NUMERIC_SIZE_2,\r
1070 CONNECT_MIN_TIMEOUT,\r
1071 CONNECT_MAX_TIMEOUT,\r
1072 0,\r
1073 NULL\r
1074 );\r
1075\r
1076 //\r
1077 // Create ISID Keyword.\r
1078 //\r
1079 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_ISID_PROMPT%d", Index);\r
1080 StringToken = HiiSetString (\r
1081 mCallbackInfo->RegisteredHandle,\r
1082 0,\r
1083 StringId,\r
1084 NULL\r
1085 );\r
1086 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIISID:%d", Index);\r
1087 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
1088 HiiCreateStringOpCode (\r
1089 StartOpCodeHandle,\r
1090 (EFI_QUESTION_ID) (ATTEMPT_ISID_QUESTION_ID + (Index - 1)),\r
1091 CONFIGURATION_VARSTORE_ID,\r
1092 (UINT16) (ATTEMPT_ISID_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),\r
1093 StringToken,\r
41c9011c 1094 STRING_TOKEN (STR_ISCSI_ISID_HELP),\r
8d1f5e04
ZL
1095 0,\r
1096 0,\r
1097 ISID_CONFIGURABLE_MIN_LEN,\r
1098 ISID_CONFIGURABLE_STORAGE,\r
1099 NULL\r
1100 );\r
1101\r
1102 //\r
1103 // Create iSCSIInitiatorInfoViaDHCP Keyword.\r
1104 //\r
1105 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_INITIATOR_VIA_DHCP_PROMPT%d", Index);\r
1106 StringToken = HiiSetString (\r
1107 mCallbackInfo->RegisteredHandle,\r
1108 0,\r
1109 StringId,\r
1110 NULL\r
1111 );\r
1112 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIInitiatorInfoViaDHCP:%d", Index);\r
1113 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
1114 HiiCreateNumericOpCode (\r
1115 StartOpCodeHandle,\r
1116 (EFI_QUESTION_ID) (ATTEMPT_INITIATOR_VIA_DHCP_QUESTION_ID + (Index - 1)),\r
1117 CONFIGURATION_VARSTORE_ID,\r
1118 (UINT16) (ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET + (Index - 1)),\r
1119 StringToken,\r
1120 StringToken,\r
1121 0,\r
1122 0,\r
1123 0,\r
1124 1,\r
1125 0,\r
1126 NULL\r
1127 );\r
1128\r
1129 //\r
1130 // Create iSCSIInitiatorIpAddress Keyword.\r
1131 //\r
1132 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_INITIATOR_IP_ADDRESS_PROMPT%d", Index);\r
1133 StringToken = HiiSetString (\r
1134 mCallbackInfo->RegisteredHandle,\r
1135 0,\r
1136 StringId,\r
1137 NULL\r
1138 );\r
1139 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIInitiatorIpAddress:%d", Index);\r
1140 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
1141 HiiCreateStringOpCode (\r
1142 StartOpCodeHandle,\r
1143 (EFI_QUESTION_ID) (ATTEMPT_INITIATOR_IP_ADDRESS_QUESTION_ID + (Index - 1)),\r
1144 CONFIGURATION_VARSTORE_ID,\r
1145 (UINT16) (ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),\r
1146 StringToken,\r
1147 StringToken,\r
1148 0,\r
1149 0,\r
1150 IP4_MIN_SIZE,\r
8b134dfd 1151 IP4_STR_MAX_SIZE,\r
8d1f5e04
ZL
1152 NULL\r
1153 );\r
1154\r
1155 //\r
1156 // Create iSCSIInitiatorNetmask Keyword.\r
1157 //\r
1158 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_INITIATOR_NET_MASK_PROMPT%d", Index);\r
1159 StringToken = HiiSetString (\r
1160 mCallbackInfo->RegisteredHandle,\r
1161 0,\r
1162 StringId,\r
1163 NULL\r
1164 );\r
1165 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIInitiatorNetmask:%d", Index);\r
1166 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
1167 HiiCreateStringOpCode (\r
1168 StartOpCodeHandle,\r
1169 (EFI_QUESTION_ID) (ATTEMPT_INITIATOR_NET_MASK_QUESTION_ID + (Index - 1)),\r
1170 CONFIGURATION_VARSTORE_ID,\r
1171 (UINT16) (ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),\r
1172 StringToken,\r
1173 StringToken,\r
1174 0,\r
1175 0,\r
1176 IP4_MIN_SIZE,\r
8b134dfd 1177 IP4_STR_MAX_SIZE,\r
8d1f5e04
ZL
1178 NULL\r
1179 );\r
1180\r
1181 //\r
1182 // Create iSCSIInitiatorGateway Keyword.\r
1183 //\r
1184 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_INITIATOR_GATE_PROMPT%d", Index);\r
1185 StringToken = HiiSetString (\r
1186 mCallbackInfo->RegisteredHandle,\r
1187 0,\r
1188 StringId,\r
1189 NULL\r
1190 );\r
1191 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIInitiatorGateway:%d", Index);\r
1192 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
1193 HiiCreateStringOpCode (\r
1194 StartOpCodeHandle,\r
1195 (EFI_QUESTION_ID) (ATTEMPT_INITIATOR_GATE_WAY_QUESTION_ID + (Index - 1)),\r
1196 CONFIGURATION_VARSTORE_ID,\r
1197 (UINT16) (ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),\r
1198 StringToken,\r
1199 StringToken,\r
1200 0,\r
1201 0,\r
1202 IP4_MIN_SIZE,\r
8b134dfd 1203 IP4_STR_MAX_SIZE,\r
8d1f5e04
ZL
1204 NULL\r
1205 );\r
1206\r
1207 //\r
1208 // Create iSCSITargetInfoViaDHCP Keyword.\r
1209 //\r
1210 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_TARGET_VIA_DHCP_PROMPT%d", Index);\r
1211 StringToken = HiiSetString (\r
1212 mCallbackInfo->RegisteredHandle,\r
1213 0,\r
1214 StringId,\r
1215 NULL\r
1216 );\r
1217 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSITargetInfoViaDHCP:%d", Index);\r
1218 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
1219 HiiCreateNumericOpCode (\r
1220 StartOpCodeHandle,\r
1221 (EFI_QUESTION_ID) (ATTEMPT_TARGET_VIA_DHCP_QUESTION_ID + (Index - 1)),\r
1222 CONFIGURATION_VARSTORE_ID,\r
1223 (UINT16) (ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET + (Index - 1)),\r
1224 StringToken,\r
1225 StringToken,\r
1226 0,\r
1227 0,\r
1228 0,\r
1229 1,\r
1230 0,\r
1231 NULL\r
1232 );\r
1233\r
1234 //\r
1235 // Create iSCSITargetTcpPort Keyword.\r
1236 //\r
1237 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_TARGET_TCP_PORT_PROMPT%d", Index);\r
1238 StringToken = HiiSetString (\r
1239 mCallbackInfo->RegisteredHandle,\r
1240 0,\r
1241 StringId,\r
1242 NULL\r
1243 );\r
1244 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSITargetTcpPort:%d", Index);\r
1245 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
1246 HiiCreateNumericOpCode (\r
1247 StartOpCodeHandle,\r
1248 (EFI_QUESTION_ID) (ATTEMPT_TARGET_TCP_PORT_QUESTION_ID + (Index - 1)),\r
1249 CONFIGURATION_VARSTORE_ID,\r
1250 (UINT16) (ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET + 2 * (Index - 1)),\r
1251 StringToken,\r
1252 StringToken,\r
1253 0,\r
1254 EFI_IFR_NUMERIC_SIZE_2,\r
1255 TARGET_PORT_MIN_NUM,\r
1256 TARGET_PORT_MAX_NUM,\r
1257 0,\r
1258 NULL\r
1259 );\r
1260\r
1261 //\r
1262 // Create iSCSITargetName Keyword.\r
1263 //\r
1264 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_TARGET_NAME_PROMPT%d", Index);\r
1265 StringToken = HiiSetString (\r
1266 mCallbackInfo->RegisteredHandle,\r
1267 0,\r
1268 StringId,\r
1269 NULL\r
1270 );\r
1271 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSITargetName:%d", Index);\r
1272 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
1273 HiiCreateStringOpCode (\r
1274 StartOpCodeHandle,\r
1275 (EFI_QUESTION_ID) (ATTEMPT_TARGET_NAME_QUESTION_ID + (Index - 1)),\r
1276 CONFIGURATION_VARSTORE_ID,\r
1277 (UINT16) (ATTEMPT_TARGET_NAME_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),\r
1278 StringToken,\r
1279 StringToken,\r
1280 0,\r
1281 0,\r
1282 ISCSI_NAME_IFR_MIN_SIZE,\r
1283 ISCSI_NAME_IFR_MAX_SIZE,\r
1284 NULL\r
1285 );\r
1286\r
1287 //\r
1288 // Create iSCSITargetIpAddress Keyword.\r
1289 //\r
1290 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_TARGET_IP_ADDRESS_PROMPT%d", Index);\r
1291 StringToken = HiiSetString (\r
1292 mCallbackInfo->RegisteredHandle,\r
1293 0,\r
1294 StringId,\r
1295 NULL\r
1296 );\r
1297 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSITargetIpAddress:%d", Index);\r
1298 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
1299 HiiCreateStringOpCode (\r
1300 StartOpCodeHandle,\r
1301 (EFI_QUESTION_ID) (ATTEMPT_TARGET_IP_ADDRESS_QUESTION_ID + (Index - 1)),\r
1302 CONFIGURATION_VARSTORE_ID,\r
1303 (UINT16) (ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),\r
1304 StringToken,\r
1305 StringToken,\r
1306 0,\r
1307 0,\r
1308 IP_MIN_SIZE,\r
8b134dfd 1309 IP_STR_MAX_SIZE,\r
8d1f5e04
ZL
1310 NULL\r
1311 );\r
1312\r
1313 //\r
1314 // Create iSCSILUN Keyword.\r
1315 //\r
1316 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_LUN_PROMPT%d", Index);\r
1317 StringToken = HiiSetString (\r
1318 mCallbackInfo->RegisteredHandle,\r
1319 0,\r
1320 StringId,\r
1321 NULL\r
1322 );\r
1323 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSILUN:%d", Index);\r
1324 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
1325 HiiCreateStringOpCode (\r
1326 StartOpCodeHandle,\r
1327 (EFI_QUESTION_ID) (ATTEMPT_LUN_QUESTION_ID + (Index - 1)),\r
1328 CONFIGURATION_VARSTORE_ID,\r
1329 (UINT16) (ATTEMPT_LUN_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),\r
1330 StringToken,\r
1331 StringToken,\r
1332 0,\r
1333 0,\r
1334 LUN_MIN_SIZE,\r
1335 LUN_MAX_SIZE,\r
1336 NULL\r
1337 );\r
1338\r
1339 //\r
1340 // Create iSCSIAuthenticationMethod Keyword.\r
1341 //\r
1342 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_AUTHENTICATION_METHOD_PROMPT%d", Index);\r
1343 StringToken = HiiSetString (\r
1344 mCallbackInfo->RegisteredHandle,\r
1345 0,\r
1346 StringId,\r
1347 NULL\r
1348 );\r
1349 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIAuthenticationMethod:%d", Index);\r
1350 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
1351 HiiCreateNumericOpCode (\r
1352 StartOpCodeHandle,\r
1353 (EFI_QUESTION_ID) (ATTEMPT_AUTHENTICATION_METHOD_QUESTION_ID + (Index - 1)),\r
1354 CONFIGURATION_VARSTORE_ID,\r
1355 (UINT16) (ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET + (Index - 1)),\r
1356 StringToken,\r
1357 StringToken,\r
1358 0,\r
1359 0,\r
1360 0,\r
1361 1,\r
1362 0,\r
1363 NULL\r
1364 );\r
1365\r
1366 //\r
1367 // Create iSCSIChapType Keyword.\r
1368 //\r
1369 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHARTYPE_PROMPT%d", Index);\r
1370 StringToken = HiiSetString (\r
1371 mCallbackInfo->RegisteredHandle,\r
1372 0,\r
1373 StringId,\r
1374 NULL\r
1375 );\r
1376 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIChapType:%d", Index);\r
1377 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
1378 HiiCreateNumericOpCode (\r
1379 StartOpCodeHandle,\r
1380 (EFI_QUESTION_ID) (ATTEMPT_CHARTYPE_QUESTION_ID + (Index - 1)),\r
1381 CONFIGURATION_VARSTORE_ID,\r
1382 (UINT16) (ATTEMPT_CHARTYPE_VAR_OFFSET + (Index - 1)),\r
1383 StringToken,\r
1384 StringToken,\r
1385 0,\r
1386 0,\r
1387 0,\r
1388 1,\r
1389 0,\r
1390 NULL\r
1391 );\r
1392\r
1393 //\r
1394 // Create iSCSIChapUsername Keyword.\r
1395 //\r
1396 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHAR_USER_NAME_PROMPT%d", Index);\r
1397 StringToken = HiiSetString (\r
1398 mCallbackInfo->RegisteredHandle,\r
1399 0,\r
1400 StringId,\r
1401 NULL\r
1402 );\r
1403 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIChapUsername:%d", Index);\r
1404 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
1405 HiiCreateStringOpCode (\r
1406 StartOpCodeHandle,\r
1407 (EFI_QUESTION_ID) (ATTEMPT_CHAR_USER_NAME_QUESTION_ID + (Index - 1)),\r
1408 CONFIGURATION_VARSTORE_ID,\r
1409 (UINT16) (ATTEMPT_CHAR_USER_NAME_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),\r
1410 StringToken,\r
1411 StringToken,\r
1412 0,\r
1413 0,\r
1414 0,\r
1415 ISCSI_CHAP_NAME_MAX_LEN,\r
1416 NULL\r
1417 );\r
1418\r
1419 //\r
1420 // Create iSCSIChapSecret Keyword.\r
1421 //\r
1422 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHAR_SECRET_PROMPT%d", Index);\r
1423 StringToken = HiiSetString (\r
1424 mCallbackInfo->RegisteredHandle,\r
1425 0,\r
1426 StringId,\r
1427 NULL\r
1428 );\r
1429 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIChapSecret:%d", Index);\r
1430 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
1431 HiiCreateStringOpCode (\r
1432 StartOpCodeHandle,\r
1433 (EFI_QUESTION_ID) (ATTEMPT_CHAR_SECRET_QUESTION_ID + (Index - 1)),\r
1434 CONFIGURATION_VARSTORE_ID,\r
1435 (UINT16) (ATTEMPT_CHAR_SECRET_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),\r
1436 StringToken,\r
1437 StringToken,\r
1438 0,\r
1439 0,\r
1440 ISCSI_CHAP_SECRET_MIN_LEN,\r
1441 ISCSI_CHAP_SECRET_MAX_LEN,\r
1442 NULL\r
1443 );\r
1444\r
1445 //\r
1446 // Create iSCSIReverseChapUsername Keyword.\r
1447 //\r
1448 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHAR_REVERSE_USER_NAME_PROMPT%d", Index);\r
1449 StringToken = HiiSetString (\r
1450 mCallbackInfo->RegisteredHandle,\r
1451 0,\r
1452 StringId,\r
1453 NULL\r
1454 );\r
1455 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIReverseChapUsername:%d", Index);\r
1456 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
1457 HiiCreateStringOpCode (\r
1458 StartOpCodeHandle,\r
1459 (EFI_QUESTION_ID) (ATTEMPT_CHAR_REVERSE_USER_NAME_QUESTION_ID + (Index - 1)),\r
1460 CONFIGURATION_VARSTORE_ID,\r
1461 (UINT16) (ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),\r
1462 StringToken,\r
1463 StringToken,\r
1464 0,\r
1465 0,\r
1466 0,\r
1467 ISCSI_CHAP_NAME_MAX_LEN,\r
1468 NULL\r
1469 );\r
1470\r
1471 //\r
1472 // Create iSCSIReverseChapSecret Keyword.\r
1473 //\r
1474 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHAR_REVERSE_SECRET_PROMPT%d", Index);\r
1475 StringToken = HiiSetString (\r
1476 mCallbackInfo->RegisteredHandle,\r
1477 0,\r
1478 StringId,\r
1479 NULL\r
1480 );\r
1481 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIReverseChapSecret:%d", Index);\r
1482 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
1483 HiiCreateStringOpCode (\r
1484 StartOpCodeHandle,\r
1485 (EFI_QUESTION_ID) (ATTEMPT_CHAR_REVERSE_SECRET_QUESTION_ID + (Index - 1)),\r
1486 CONFIGURATION_VARSTORE_ID,\r
1487 (UINT16) (ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),\r
1488 StringToken,\r
1489 StringToken,\r
1490 0,\r
1491 0,\r
1492 ISCSI_CHAP_SECRET_MIN_LEN,\r
1493 ISCSI_CHAP_SECRET_MAX_LEN,\r
1494 NULL\r
1495 );\r
1496 }\r
1497\r
1498 Status = HiiUpdateForm (\r
1499 mCallbackInfo->RegisteredHandle, // HII handle\r
1500 &gIScsiConfigGuid, // Formset GUID\r
1501 FORMID_ATTEMPT_FORM, // Form ID\r
1502 StartOpCodeHandle, // Label for where to insert opcodes\r
1503 EndOpCodeHandle // Replace data\r
1504 );\r
1505\r
1506 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
1507 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
1508\r
1509 return Status;\r
1510}\r
1511\r
1512/**\r
1513\r
1514 Free the attempt configure data variable.\r
1515\r
1516**/\r
1517VOID\r
1518IScsiCleanAttemptVariable (\r
1519 IN VOID\r
1520)\r
1521{\r
1522 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
1523 UINT8 *AttemptConfigOrder;\r
1524 UINTN AttemptConfigOrderSize;\r
1525 UINTN Index;\r
1526\r
1527 //\r
1528 // Get the initialized attempt order.\r
1529 //\r
1530 AttemptConfigOrder = IScsiGetVariableAndSize (\r
1531 L"InitialAttemptOrder",\r
1532 &gIScsiConfigGuid,\r
1533 &AttemptConfigOrderSize\r
1534 );\r
1535 if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {\r
1536 return;\r
1537 }\r
1538\r
1539 for (Index = 1; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {\r
1540 UnicodeSPrint (\r
1541 mPrivate->PortString,\r
1542 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
1543 L"Attempt %d",\r
1544 Index\r
1545 );\r
1546\r
1547 GetVariable2 (\r
1548 mPrivate->PortString,\r
1549 &gEfiIScsiInitiatorNameProtocolGuid,\r
1550 (VOID**)&AttemptConfigData,\r
1551 NULL\r
1552 );\r
1553\r
1554 if (AttemptConfigData != NULL) {\r
1555 gRT->SetVariable (\r
1556 mPrivate->PortString,\r
1557 &gEfiIScsiInitiatorNameProtocolGuid,\r
1558 0,\r
1559 0,\r
1560 NULL\r
1561 );\r
1562 }\r
1563 }\r
1564 return;\r
1565}\r
4c5a5e0c 1566\r
1567/**\r
1568 Get the recorded NIC info from global structure by the Index.\r
1569\r
1570 @param[in] NicIndex The index indicates the position of NIC info.\r
1571\r
1572 @return Pointer to the NIC info, or NULL if not found.\r
1573\r
1574**/\r
1575ISCSI_NIC_INFO *\r
1576IScsiGetNicInfoByIndex (\r
1577 IN UINT8 NicIndex\r
1578 )\r
1579{\r
1580 LIST_ENTRY *Entry;\r
1581 ISCSI_NIC_INFO *NicInfo;\r
1582\r
1583 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {\r
1584 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);\r
1585 if (NicInfo->NicIndex == NicIndex) {\r
1586 return NicInfo;\r
1587 }\r
1588 }\r
1589\r
1590 return NULL;\r
1591}\r
1592\r
1593\r
1594/**\r
59c0c1cb 1595 Get the NIC's PCI location and return it according to the composited\r
4c5a5e0c 1596 format defined in iSCSI Boot Firmware Table.\r
1597\r
1598 @param[in] Controller The handle of the controller.\r
1599 @param[out] Bus The bus number.\r
1600 @param[out] Device The device number.\r
1601 @param[out] Function The function number.\r
1602\r
1603 @return The composited representation of the NIC PCI location.\r
1604\r
1605**/\r
1606UINT16\r
1607IScsiGetNICPciLocation (\r
1608 IN EFI_HANDLE Controller,\r
1609 OUT UINTN *Bus,\r
1610 OUT UINTN *Device,\r
1611 OUT UINTN *Function\r
1612 )\r
1613{\r
1614 EFI_STATUS Status;\r
1615 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
1616 EFI_HANDLE PciIoHandle;\r
1617 EFI_PCI_IO_PROTOCOL *PciIo;\r
1618 UINTN Segment;\r
1619\r
1620 Status = gBS->HandleProtocol (\r
1621 Controller,\r
1622 &gEfiDevicePathProtocolGuid,\r
1623 (VOID **) &DevicePath\r
1624 );\r
1625 if (EFI_ERROR (Status)) {\r
1626 return 0;\r
1627 }\r
1628\r
1629 Status = gBS->LocateDevicePath (\r
1630 &gEfiPciIoProtocolGuid,\r
1631 &DevicePath,\r
1632 &PciIoHandle\r
1633 );\r
1634 if (EFI_ERROR (Status)) {\r
1635 return 0;\r
1636 }\r
1637\r
1638 Status = gBS->HandleProtocol (PciIoHandle, &gEfiPciIoProtocolGuid, (VOID **) &PciIo);\r
1639 if (EFI_ERROR (Status)) {\r
1640 return 0;\r
1641 }\r
1642\r
1643 Status = PciIo->GetLocation (PciIo, &Segment, Bus, Device, Function);\r
1644 if (EFI_ERROR (Status)) {\r
1645 return 0;\r
1646 }\r
1647\r
1648 return (UINT16) ((*Bus << 8) | (*Device << 3) | *Function);\r
1649}\r
1650\r
1651\r
1652/**\r
1653 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated\r
1654 buffer, and the size of the buffer. If failure, return NULL.\r
1655\r
1656 @param[in] Name String part of EFI variable name.\r
1657 @param[in] VendorGuid GUID part of EFI variable name.\r
1658 @param[out] VariableSize Returns the size of the EFI variable that was read.\r
1659\r
1660 @return Dynamically allocated memory that contains a copy of the EFI variable.\r
1661 @return Caller is responsible freeing the buffer.\r
1662 @retval NULL Variable was not read.\r
1663\r
1664**/\r
1665VOID *\r
1666IScsiGetVariableAndSize (\r
1667 IN CHAR16 *Name,\r
1668 IN EFI_GUID *VendorGuid,\r
1669 OUT UINTN *VariableSize\r
1670 )\r
1671{\r
1672 EFI_STATUS Status;\r
1673 UINTN BufferSize;\r
1674 VOID *Buffer;\r
1675\r
1676 Buffer = NULL;\r
1677\r
1678 //\r
1679 // Pass in a zero size buffer to find the required buffer size.\r
1680 //\r
1681 BufferSize = 0;\r
1682 Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
1683 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1684 //\r
1685 // Allocate the buffer to return\r
1686 //\r
1687 Buffer = AllocateZeroPool (BufferSize);\r
1688 if (Buffer == NULL) {\r
1689 return NULL;\r
1690 }\r
1691 //\r
1692 // Read variable into the allocated buffer.\r
1693 //\r
1694 Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
1695 if (EFI_ERROR (Status)) {\r
1696 BufferSize = 0;\r
1697 }\r
1698 }\r
1699\r
1700 *VariableSize = BufferSize;\r
1701 return Buffer;\r
1702}\r
1703\r
1704\r
1705/**\r
1706 Create the iSCSI driver data.\r
1707\r
1708 @param[in] Image The handle of the driver image.\r
1709 @param[in] Controller The handle of the controller.\r
1710\r
1711 @return The iSCSI driver data created.\r
1712 @retval NULL Other errors as indicated.\r
1713\r
1714**/\r
1715ISCSI_DRIVER_DATA *\r
1716IScsiCreateDriverData (\r
1717 IN EFI_HANDLE Image,\r
1718 IN EFI_HANDLE Controller\r
1719 )\r
1720{\r
1721 ISCSI_DRIVER_DATA *Private;\r
1722 EFI_STATUS Status;\r
1723\r
1724 Private = AllocateZeroPool (sizeof (ISCSI_DRIVER_DATA));\r
1725 if (Private == NULL) {\r
1726 return NULL;\r
1727 }\r
1728\r
1729 Private->Signature = ISCSI_DRIVER_DATA_SIGNATURE;\r
1730 Private->Image = Image;\r
1731 Private->Controller = Controller;\r
1732 Private->Session = NULL;\r
1733\r
1734 //\r
1735 // Create an event to be signaled when the BS to RT transition is triggerd so\r
1736 // as to abort the iSCSI session.\r
1737 //\r
1738 Status = gBS->CreateEventEx (\r
1739 EVT_NOTIFY_SIGNAL,\r
1740 TPL_CALLBACK,\r
1741 IScsiOnExitBootService,\r
1742 Private,\r
1743 &gEfiEventExitBootServicesGuid,\r
1744 &Private->ExitBootServiceEvent\r
1745 );\r
1746 if (EFI_ERROR (Status)) {\r
1747 FreePool (Private);\r
1748 return NULL;\r
1749 }\r
1750\r
1751 Private->ExtScsiPassThruHandle = NULL;\r
1752 CopyMem(&Private->IScsiExtScsiPassThru, &gIScsiExtScsiPassThruProtocolTemplate, sizeof(EFI_EXT_SCSI_PASS_THRU_PROTOCOL));\r
1753\r
1754 //\r
1755 // 0 is designated to the TargetId, so use another value for the AdapterId.\r
1756 //\r
1757 Private->ExtScsiPassThruMode.AdapterId = 2;\r
1758 Private->ExtScsiPassThruMode.Attributes = EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;\r
1759 Private->ExtScsiPassThruMode.IoAlign = 4;\r
1760 Private->IScsiExtScsiPassThru.Mode = &Private->ExtScsiPassThruMode;\r
1761\r
1762 return Private;\r
1763}\r
1764\r
1765\r
1766/**\r
1767 Clean the iSCSI driver data.\r
1768\r
e590d29f
ZL
1769 @param[in] Private The iSCSI driver data.\r
1770\r
6d0bab0e 1771 @retval EFI_SUCCESS The clean operation is successful.\r
e590d29f 1772 @retval Others Other errors as indicated.\r
4c5a5e0c 1773\r
1774**/\r
e590d29f 1775EFI_STATUS\r
4c5a5e0c 1776IScsiCleanDriverData (\r
1777 IN ISCSI_DRIVER_DATA *Private\r
1778 )\r
1779{\r
1780 EFI_STATUS Status;\r
6d0bab0e
ZL
1781\r
1782 Status = EFI_SUCCESS;\r
4c5a5e0c 1783\r
1784 if (Private->DevicePath != NULL) {\r
e590d29f
ZL
1785 Status = gBS->UninstallProtocolInterface (\r
1786 Private->ExtScsiPassThruHandle,\r
1787 &gEfiDevicePathProtocolGuid,\r
1788 Private->DevicePath\r
1789 );\r
1790 if (EFI_ERROR (Status)) {\r
1791 goto EXIT;\r
1792 }\r
4c5a5e0c 1793\r
1794 FreePool (Private->DevicePath);\r
1795 }\r
1796\r
1797 if (Private->ExtScsiPassThruHandle != NULL) {\r
1798 Status = gBS->UninstallProtocolInterface (\r
1799 Private->ExtScsiPassThruHandle,\r
1800 &gEfiExtScsiPassThruProtocolGuid,\r
1801 &Private->IScsiExtScsiPassThru\r
1802 );\r
1803 if (!EFI_ERROR (Status)) {\r
1804 mPrivate->OneSessionEstablished = FALSE;\r
1805 }\r
1806 }\r
1807\r
e590d29f 1808EXIT:\r
a37c60b6 1809 if (Private->ExitBootServiceEvent != NULL) {\r
f75a7f56 1810 gBS->CloseEvent (Private->ExitBootServiceEvent);\r
a37c60b6 1811 }\r
4c5a5e0c 1812\r
3cb5b997
ZL
1813 mCallbackInfo->Current = NULL;\r
1814\r
4c5a5e0c 1815 FreePool (Private);\r
e590d29f 1816 return Status;\r
4c5a5e0c 1817}\r
1818\r
b7cc5bf1
WJ
1819/**\r
1820 Check wheather the Controller handle is configured to use DHCP protocol.\r
1821\r
1822 @param[in] Controller The handle of the controller.\r
1823 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.\r
f75a7f56 1824\r
b7cc5bf1
WJ
1825 @retval TRUE The handle of the controller need the Dhcp protocol.\r
1826 @retval FALSE The handle of the controller does not need the Dhcp protocol.\r
f75a7f56 1827\r
b7cc5bf1
WJ
1828**/\r
1829BOOLEAN\r
1830IScsiDhcpIsConfigured (\r
1831 IN EFI_HANDLE Controller,\r
1832 IN UINT8 IpVersion\r
1833 )\r
1834{\r
1835 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptTmp;\r
1836 UINT8 *AttemptConfigOrder;\r
1837 UINTN AttemptConfigOrderSize;\r
1838 UINTN Index;\r
1839 EFI_STATUS Status;\r
1840 EFI_MAC_ADDRESS MacAddr;\r
1841 UINTN HwAddressSize;\r
1842 UINT16 VlanId;\r
1843 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];\r
8d1f5e04 1844 CHAR16 AttemptMacString[ISCSI_MAX_MAC_STRING_LEN];\r
b7cc5bf1 1845 CHAR16 AttemptName[ISCSI_NAME_IFR_MAX_SIZE];\r
f75a7f56 1846\r
b7cc5bf1
WJ
1847 AttemptConfigOrder = IScsiGetVariableAndSize (\r
1848 L"AttemptOrder",\r
1849 &gIScsiConfigGuid,\r
1850 &AttemptConfigOrderSize\r
1851 );\r
1852 if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {\r
1853 return FALSE;\r
1854 }\r
f75a7f56 1855\r
b7cc5bf1
WJ
1856 //\r
1857 // Get MAC address of this network device.\r
1858 //\r
1859 Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);\r
1860 if(EFI_ERROR (Status)) {\r
1861 return FALSE;\r
1862 }\r
1863 //\r
1864 // Get VLAN ID of this network device.\r
1865 //\r
1866 VlanId = NetLibGetVlanId (Controller);\r
1867 IScsiMacAddrToStr (&MacAddr, (UINT32) HwAddressSize, VlanId, MacString);\r
f75a7f56 1868\r
b7cc5bf1
WJ
1869 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {\r
1870 UnicodeSPrint (\r
1871 AttemptName,\r
1872 (UINTN) 128,\r
8d1f5e04 1873 L"Attempt %d",\r
b7cc5bf1
WJ
1874 (UINTN) AttemptConfigOrder[Index]\r
1875 );\r
1876 Status = GetVariable2 (\r
1877 AttemptName,\r
1878 &gEfiIScsiInitiatorNameProtocolGuid,\r
1879 (VOID**)&AttemptTmp,\r
1880 NULL\r
1881 );\r
107e3d7a 1882 if(AttemptTmp == NULL || EFI_ERROR (Status)) {\r
b7cc5bf1
WJ
1883 continue;\r
1884 }\r
f75a7f56 1885\r
b7cc5bf1
WJ
1886 ASSERT (AttemptConfigOrder[Index] == AttemptTmp->AttemptConfigIndex);\r
1887\r
1888 if (AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED) {\r
1889 FreePool (AttemptTmp);\r
1890 continue;\r
1891 }\r
1892\r
f75a7f56 1893 if (AttemptTmp->SessionConfigData.IpMode != IP_MODE_AUTOCONFIG &&\r
b7cc5bf1
WJ
1894 AttemptTmp->SessionConfigData.IpMode != ((IpVersion == IP_VERSION_4) ? IP_MODE_IP4 : IP_MODE_IP6)) {\r
1895 FreePool (AttemptTmp);\r
1896 continue;\r
1897 }\r
8d1f5e04
ZL
1898\r
1899 AsciiStrToUnicodeStrS (AttemptTmp->MacString, AttemptMacString, sizeof (AttemptMacString) / sizeof (AttemptMacString[0]));\r
1900\r
1901 if (AttemptTmp->Actived == ISCSI_ACTIVE_DISABLED || StrCmp (MacString, AttemptMacString)) {\r
1902 continue;\r
1903 }\r
1904\r
b7cc5bf1
WJ
1905 if(AttemptTmp->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG ||\r
1906 AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp == TRUE ||\r
f75a7f56 1907 AttemptTmp->SessionConfigData.TargetInfoFromDhcp == TRUE) {\r
b7cc5bf1
WJ
1908 FreePool (AttemptTmp);\r
1909 FreePool (AttemptConfigOrder);\r
1910 return TRUE;\r
1911 }\r
1912\r
1913 FreePool (AttemptTmp);\r
1914 }\r
f75a7f56 1915\r
b7cc5bf1
WJ
1916 FreePool (AttemptConfigOrder);\r
1917 return FALSE;\r
1918}\r
4c5a5e0c 1919\r
eabc6e59 1920/**\r
df077b3e 1921 Check whether the Controller handle is configured to use DNS protocol.\r
eabc6e59
ZL
1922\r
1923 @param[in] Controller The handle of the controller.\r
f75a7f56 1924\r
eabc6e59
ZL
1925 @retval TRUE The handle of the controller need the Dns protocol.\r
1926 @retval FALSE The handle of the controller does not need the Dns protocol.\r
f75a7f56 1927\r
eabc6e59
ZL
1928**/\r
1929BOOLEAN\r
1930IScsiDnsIsConfigured (\r
1931 IN EFI_HANDLE Controller\r
1932 )\r
1933{\r
1934 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptTmp;\r
1935 UINT8 *AttemptConfigOrder;\r
1936 UINTN AttemptConfigOrderSize;\r
1937 UINTN Index;\r
1938 EFI_STATUS Status;\r
1939 EFI_MAC_ADDRESS MacAddr;\r
1940 UINTN HwAddressSize;\r
1941 UINT16 VlanId;\r
df077b3e 1942 CHAR16 AttemptMacString[ISCSI_MAX_MAC_STRING_LEN];\r
eabc6e59
ZL
1943 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];\r
1944 CHAR16 AttemptName[ISCSI_NAME_IFR_MAX_SIZE];\r
f75a7f56 1945\r
eabc6e59
ZL
1946 AttemptConfigOrder = IScsiGetVariableAndSize (\r
1947 L"AttemptOrder",\r
1948 &gIScsiConfigGuid,\r
1949 &AttemptConfigOrderSize\r
1950 );\r
1951 if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {\r
1952 return FALSE;\r
1953 }\r
f75a7f56 1954\r
eabc6e59
ZL
1955 //\r
1956 // Get MAC address of this network device.\r
1957 //\r
1958 Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);\r
1959 if(EFI_ERROR (Status)) {\r
1960 return FALSE;\r
1961 }\r
1962 //\r
1963 // Get VLAN ID of this network device.\r
1964 //\r
1965 VlanId = NetLibGetVlanId (Controller);\r
1966 IScsiMacAddrToStr (&MacAddr, (UINT32) HwAddressSize, VlanId, MacString);\r
f75a7f56 1967\r
eabc6e59
ZL
1968 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {\r
1969 UnicodeSPrint (\r
1970 AttemptName,\r
1971 (UINTN) 128,\r
df077b3e 1972 L"Attempt %d",\r
eabc6e59
ZL
1973 (UINTN) AttemptConfigOrder[Index]\r
1974 );\r
df077b3e 1975\r
eabc6e59
ZL
1976 Status = GetVariable2 (\r
1977 AttemptName,\r
1978 &gEfiIScsiInitiatorNameProtocolGuid,\r
1979 (VOID**)&AttemptTmp,\r
1980 NULL\r
1981 );\r
1982 if(AttemptTmp == NULL || EFI_ERROR (Status)) {\r
1983 continue;\r
1984 }\r
f75a7f56 1985\r
eabc6e59
ZL
1986 ASSERT (AttemptConfigOrder[Index] == AttemptTmp->AttemptConfigIndex);\r
1987\r
df077b3e
ZL
1988 AsciiStrToUnicodeStrS (AttemptTmp->MacString, AttemptMacString, sizeof (AttemptMacString) / sizeof (AttemptMacString[0]));\r
1989\r
1990 if (AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED || StrCmp (MacString, AttemptMacString)) {\r
eabc6e59
ZL
1991 FreePool (AttemptTmp);\r
1992 continue;\r
1993 }\r
f75a7f56 1994\r
841d8698 1995 if (AttemptTmp->SessionConfigData.DnsMode || AttemptTmp->SessionConfigData.TargetInfoFromDhcp) {\r
eabc6e59
ZL
1996 FreePool (AttemptTmp);\r
1997 FreePool (AttemptConfigOrder);\r
1998 return TRUE;\r
1999 } else {\r
2000 FreePool (AttemptTmp);\r
2001 continue;\r
2002 }\r
2003\r
2004 }\r
2005\r
2006 FreePool (AttemptConfigOrder);\r
2007 return FALSE;\r
2008\r
2009}\r
2010\r
4c5a5e0c 2011/**\r
2012 Get the various configuration data.\r
2013\r
2014 @param[in] Private The iSCSI driver data.\r
2015\r
2016 @retval EFI_SUCCESS The configuration data is retrieved.\r
2017 @retval EFI_NOT_FOUND This iSCSI driver is not configured yet.\r
7c275b3c 2018 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
4c5a5e0c 2019\r
2020**/\r
2021EFI_STATUS\r
2022IScsiGetConfigData (\r
2023 IN ISCSI_DRIVER_DATA *Private\r
2024 )\r
2025{\r
2026 EFI_STATUS Status;\r
2027 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];\r
8d1f5e04 2028 CHAR16 AttemptMacString[ISCSI_MAX_MAC_STRING_LEN];\r
4c5a5e0c 2029 UINTN Index;\r
2030 ISCSI_NIC_INFO *NicInfo;\r
2031 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
2032 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptTmp;\r
2033 UINT8 *AttemptConfigOrder;\r
2034 UINTN AttemptConfigOrderSize;\r
2035 CHAR16 IScsiMode[64];\r
2036 CHAR16 IpMode[64];\r
2037\r
2038 //\r
2039 // There should be at least one attempt configured.\r
2040 //\r
2041 AttemptConfigOrder = IScsiGetVariableAndSize (\r
2042 L"AttemptOrder",\r
9bdc6592 2043 &gIScsiConfigGuid,\r
4c5a5e0c 2044 &AttemptConfigOrderSize\r
2045 );\r
2046 if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {\r
2047 return EFI_NOT_FOUND;\r
2048 }\r
2049\r
2050 //\r
2051 // Get the iSCSI Initiator Name.\r
2052 //\r
2053 mPrivate->InitiatorNameLength = ISCSI_NAME_MAX_SIZE;\r
2054 Status = gIScsiInitiatorName.Get (\r
2055 &gIScsiInitiatorName,\r
2056 &mPrivate->InitiatorNameLength,\r
2057 mPrivate->InitiatorName\r
2058 );\r
2059 if (EFI_ERROR (Status)) {\r
2060 return Status;\r
2061 }\r
2062\r
2063 //\r
2064 // Get the normal configuration.\r
2065 //\r
2066 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {\r
2067\r
2068 //\r
2069 // Check whether the attempt exists in AttemptConfig.\r
2070 //\r
f75a7f56 2071 AttemptTmp = IScsiConfigGetAttemptByConfigIndex (AttemptConfigOrder[Index]);\r
4c5a5e0c 2072 if (AttemptTmp != NULL && AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED) {\r
2073 continue;\r
2074 } else if (AttemptTmp != NULL && AttemptTmp->SessionConfigData.Enabled != ISCSI_DISABLED) {\r
2075 //\r
2076 // Check the autoconfig path to see whether it should be retried.\r
2077 //\r
2078 if (AttemptTmp->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG &&\r
87ce4210 2079 !AttemptTmp->AutoConfigureSuccess) {\r
4c5a5e0c 2080 if (mPrivate->Ipv6Flag &&\r
2081 AttemptTmp->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6) {\r
2082 //\r
2083 // Autoconfigure for IP6 already attempted but failed. Do not try again.\r
2084 //\r
2085 continue;\r
2086 } else if (!mPrivate->Ipv6Flag &&\r
2087 AttemptTmp->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP4) {\r
2088 //\r
2089 // Autoconfigure for IP4 already attempted but failed. Do not try again.\r
2090 //\r
2091 continue;\r
2092 } else {\r
2093 //\r
2094 // Try another approach for this autoconfigure path.\r
2095 //\r
2096 AttemptTmp->AutoConfigureMode =\r
2097 (UINT8) (mPrivate->Ipv6Flag ? IP_MODE_AUTOCONFIG_IP6 : IP_MODE_AUTOCONFIG_IP4);\r
2098 AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp = TRUE;\r
2099 AttemptTmp->SessionConfigData.TargetInfoFromDhcp = TRUE;\r
2100 AttemptTmp->DhcpSuccess = FALSE;\r
2101\r
2102 //\r
2103 // Get some information from the dhcp server.\r
2104 //\r
2105 if (!mPrivate->Ipv6Flag) {\r
2106 Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptTmp);\r
2107 if (!EFI_ERROR (Status)) {\r
2108 AttemptTmp->DhcpSuccess = TRUE;\r
2109 }\r
2110 } else {\r
2111 Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptTmp);\r
2112 if (!EFI_ERROR (Status)) {\r
2113 AttemptTmp->DhcpSuccess = TRUE;\r
2114 }\r
2115 }\r
2116\r
2117 //\r
2118 // Refresh the state of this attempt to NVR.\r
2119 //\r
4c5a5e0c 2120 UnicodeSPrint (\r
2121 mPrivate->PortString,\r
2122 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
8d1f5e04 2123 L"Attempt %d",\r
4c5a5e0c 2124 (UINTN) AttemptTmp->AttemptConfigIndex\r
2125 );\r
2126\r
2127 gRT->SetVariable (\r
2128 mPrivate->PortString,\r
2129 &gEfiIScsiInitiatorNameProtocolGuid,\r
2130 ISCSI_CONFIG_VAR_ATTR,\r
2131 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),\r
2132 AttemptTmp\r
2133 );\r
2134\r
2135 continue;\r
2136 }\r
f75a7f56
LG
2137 } else if (AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp &&\r
2138 !AttemptTmp->ValidPath &&\r
067ca838 2139 AttemptTmp->NicIndex == mPrivate->CurrentNic) {\r
4c5a5e0c 2140 //\r
f75a7f56 2141 // If the attempt associates with the current NIC, we can\r
067ca838 2142 // get DHCP information for already added, but failed, attempt.\r
4c5a5e0c 2143 //\r
2144 AttemptTmp->DhcpSuccess = FALSE;\r
2145 if (!mPrivate->Ipv6Flag && (AttemptTmp->SessionConfigData.IpMode == IP_MODE_IP4)) {\r
2146 Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptTmp);\r
2147 if (!EFI_ERROR (Status)) {\r
2148 AttemptTmp->DhcpSuccess = TRUE;\r
2149 }\r
2150 } else if (mPrivate->Ipv6Flag && (AttemptTmp->SessionConfigData.IpMode == IP_MODE_IP6)) {\r
2151 Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptTmp);\r
2152 if (!EFI_ERROR (Status)) {\r
2153 AttemptTmp->DhcpSuccess = TRUE;\r
2154 }\r
2155 }\r
2156\r
2157 //\r
2158 // Refresh the state of this attempt to NVR.\r
2159 //\r
4c5a5e0c 2160 UnicodeSPrint (\r
2161 mPrivate->PortString,\r
2162 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
8d1f5e04 2163 L"Attempt %d",\r
4c5a5e0c 2164 (UINTN) AttemptTmp->AttemptConfigIndex\r
2165 );\r
2166\r
2167 gRT->SetVariable (\r
2168 mPrivate->PortString,\r
2169 &gEfiIScsiInitiatorNameProtocolGuid,\r
2170 ISCSI_CONFIG_VAR_ATTR,\r
2171 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),\r
2172 AttemptTmp\r
2173 );\r
2174\r
2175 continue;\r
2176\r
2177 } else {\r
2178 continue;\r
2179 }\r
2180 }\r
2181\r
2182 //\r
2183 // This attempt does not exist in AttemptConfig. Try to add a new one.\r
2184 //\r
2185\r
2186 NicInfo = IScsiGetNicInfoByIndex (mPrivate->CurrentNic);\r
2187 ASSERT (NicInfo != NULL);\r
2188 IScsiMacAddrToStr (&NicInfo->PermanentAddress, NicInfo->HwAddressSize, NicInfo->VlanId, MacString);\r
2189 UnicodeSPrint (\r
2190 mPrivate->PortString,\r
8d1f5e04
ZL
2191 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
2192 L"Attempt %d",\r
4c5a5e0c 2193 (UINTN) AttemptConfigOrder[Index]\r
2194 );\r
2195\r
bf4a3dbd 2196 GetVariable2 (\r
a2d59ef2
YT
2197 mPrivate->PortString,\r
2198 &gEfiIScsiInitiatorNameProtocolGuid,\r
2199 (VOID**)&AttemptConfigData,\r
2200 NULL\r
2201 );\r
8d1f5e04 2202 AsciiStrToUnicodeStrS (AttemptConfigData->MacString, AttemptMacString, sizeof (AttemptMacString) / sizeof (AttemptMacString[0]));\r
4c5a5e0c 2203\r
8d1f5e04
ZL
2204 if (AttemptConfigData == NULL || AttemptConfigData->Actived == ISCSI_ACTIVE_DISABLED ||\r
2205 StrCmp (MacString, AttemptMacString)) {\r
4c5a5e0c 2206 continue;\r
2207 }\r
2208\r
2209 ASSERT (AttemptConfigOrder[Index] == AttemptConfigData->AttemptConfigIndex);\r
2210\r
2211 AttemptConfigData->NicIndex = NicInfo->NicIndex;\r
2212 AttemptConfigData->DhcpSuccess = FALSE;\r
2213 AttemptConfigData->ValidiBFTPath = (BOOLEAN) (mPrivate->EnableMpio ? TRUE : FALSE);\r
2214 AttemptConfigData->ValidPath = FALSE;\r
2215\r
2216 if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) {\r
2217 AttemptConfigData->SessionConfigData.InitiatorInfoFromDhcp = TRUE;\r
2218 AttemptConfigData->SessionConfigData.TargetInfoFromDhcp = TRUE;\r
2219\r
2220 AttemptConfigData->AutoConfigureMode =\r
2221 (UINT8) (mPrivate->Ipv6Flag ? IP_MODE_AUTOCONFIG_IP6 : IP_MODE_AUTOCONFIG_IP4);\r
87ce4210 2222 AttemptConfigData->AutoConfigureSuccess = FALSE;\r
4c5a5e0c 2223 }\r
f75a7f56 2224\r
4c5a5e0c 2225 //\r
2226 // Get some information from dhcp server.\r
2227 //\r
2228 if (AttemptConfigData->SessionConfigData.Enabled != ISCSI_DISABLED &&\r
2229 AttemptConfigData->SessionConfigData.InitiatorInfoFromDhcp) {\r
2230\r
2231 if (!mPrivate->Ipv6Flag &&\r
2232 (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP4 ||\r
2233 AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP4)) {\r
2234 Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptConfigData);\r
2235 if (!EFI_ERROR (Status)) {\r
2236 AttemptConfigData->DhcpSuccess = TRUE;\r
2237 }\r
2238 } else if (mPrivate->Ipv6Flag &&\r
2239 (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP6 ||\r
2240 AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6)) {\r
2241 Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptConfigData);\r
2242 if (!EFI_ERROR (Status)) {\r
2243 AttemptConfigData->DhcpSuccess = TRUE;\r
2244 }\r
2245 }\r
2246\r
2247 //\r
2248 // Refresh the state of this attempt to NVR.\r
2249 //\r
4c5a5e0c 2250 UnicodeSPrint (\r
2251 mPrivate->PortString,\r
2252 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
8d1f5e04 2253 L"Attempt %d",\r
4c5a5e0c 2254 (UINTN) AttemptConfigData->AttemptConfigIndex\r
2255 );\r
2256\r
2257 gRT->SetVariable (\r
2258 mPrivate->PortString,\r
2259 &gEfiIScsiInitiatorNameProtocolGuid,\r
2260 ISCSI_CONFIG_VAR_ATTR,\r
2261 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),\r
2262 AttemptConfigData\r
2263 );\r
2264 }\r
2265\r
2266 //\r
2267 // Update Attempt Help Info.\r
2268 //\r
2269\r
2270 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_DISABLED) {\r
2271 UnicodeSPrint (IScsiMode, 64, L"Disabled");\r
2272 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED) {\r
2273 UnicodeSPrint (IScsiMode, 64, L"Enabled");\r
2274 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {\r
2275 UnicodeSPrint (IScsiMode, 64, L"Enabled for MPIO");\r
2276 }\r
2277\r
2278 if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP4) {\r
2279 UnicodeSPrint (IpMode, 64, L"IP4");\r
2280 } else if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP6) {\r
2281 UnicodeSPrint (IpMode, 64, L"IP6");\r
2282 } else if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) {\r
2283 UnicodeSPrint (IpMode, 64, L"Autoconfigure");\r
2284 }\r
2285\r
2286 UnicodeSPrint (\r
2287 mPrivate->PortString,\r
2288 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
2289 L"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",\r
2290 MacString,\r
2291 NicInfo->BusNumber,\r
2292 NicInfo->DeviceNumber,\r
2293 NicInfo->FunctionNumber,\r
2294 IScsiMode,\r
2295 IpMode\r
2296 );\r
2297\r
2298 AttemptConfigData->AttemptTitleHelpToken = HiiSetString (\r
2299 mCallbackInfo->RegisteredHandle,\r
2300 0,\r
2301 mPrivate->PortString,\r
2302 NULL\r
2303 );\r
7c275b3c
ZL
2304 if (AttemptConfigData->AttemptTitleHelpToken == 0) {\r
2305 return EFI_OUT_OF_RESOURCES;\r
2306 }\r
4c5a5e0c 2307\r
2308 //\r
2309 // Record the attempt in global link list.\r
2310 //\r
2311 InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link);\r
2312 mPrivate->AttemptCount++;\r
2313\r
2314 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {\r
2315 mPrivate->MpioCount++;\r
2316 mPrivate->EnableMpio = TRUE;\r
2317\r
2318 if (AttemptConfigData->AuthenticationType == ISCSI_AUTH_TYPE_KRB) {\r
2319 mPrivate->Krb5MpioCount++;\r
2320 }\r
2321 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED) {\r
2322 mPrivate->SinglePathCount++;\r
2323 }\r
2324 }\r
2325\r
2326 //\r
2327 // Reorder the AttemptConfig by the configured order.\r
2328 //\r
2329 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {\r
2330 AttemptConfigData = IScsiConfigGetAttemptByConfigIndex (AttemptConfigOrder[Index]);\r
2331 if (AttemptConfigData == NULL) {\r
2332 continue;\r
2333 }\r
2334\r
2335 RemoveEntryList (&AttemptConfigData->Link);\r
2336 InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link);\r
2337 }\r
2338\r
2339 //\r
2340 // Update the Main Form.\r
2341 //\r
2342 IScsiConfigUpdateAttempt ();\r
2343\r
2344 FreePool (AttemptConfigOrder);\r
2345\r
2346 //\r
2347 // There should be at least one attempt configuration.\r
2348 //\r
2349 if (!mPrivate->EnableMpio) {\r
2350 if (mPrivate->SinglePathCount == 0) {\r
2351 return EFI_NOT_FOUND;\r
2352 }\r
2353 mPrivate->ValidSinglePathCount = mPrivate->SinglePathCount;\r
2354 }\r
2355\r
2356 return EFI_SUCCESS;\r
2357}\r
2358\r
2359\r
2360/**\r
2361 Get the device path of the iSCSI tcp connection and update it.\r
2362\r
2363 @param Session The iSCSI session.\r
2364\r
2365 @return The updated device path.\r
2366 @retval NULL Other errors as indicated.\r
2367\r
2368**/\r
2369EFI_DEVICE_PATH_PROTOCOL *\r
2370IScsiGetTcpConnDevicePath (\r
2371 IN ISCSI_SESSION *Session\r
2372 )\r
2373{\r
2374 ISCSI_CONNECTION *Conn;\r
2375 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
2376 EFI_STATUS Status;\r
2377 EFI_DEV_PATH *DPathNode;\r
42f0586d 2378 UINTN PathLen;\r
4c5a5e0c 2379\r
2380 if (Session->State != SESSION_STATE_LOGGED_IN) {\r
2381 return NULL;\r
2382 }\r
2383\r
2384 Conn = NET_LIST_USER_STRUCT_S (\r
2385 Session->Conns.ForwardLink,\r
2386 ISCSI_CONNECTION,\r
2387 Link,\r
2388 ISCSI_CONNECTION_SIGNATURE\r
2389 );\r
2390\r
2391 Status = gBS->HandleProtocol (\r
2392 Conn->TcpIo.Handle,\r
2393 &gEfiDevicePathProtocolGuid,\r
2394 (VOID **) &DevicePath\r
f75a7f56 2395 );\r
4c5a5e0c 2396 if (EFI_ERROR (Status)) {\r
2397 return NULL;\r
2398 }\r
2399 //\r
2400 // Duplicate it.\r
2401 //\r
2402 DevicePath = DuplicateDevicePath (DevicePath);\r
2403 if (DevicePath == NULL) {\r
2404 return NULL;\r
2405 }\r
2406\r
2407 DPathNode = (EFI_DEV_PATH *) DevicePath;\r
2408\r
2409 while (!IsDevicePathEnd (&DPathNode->DevPath)) {\r
2410 if (DevicePathType (&DPathNode->DevPath) == MESSAGING_DEVICE_PATH) {\r
2411 if (!Conn->Ipv6Flag && DevicePathSubType (&DPathNode->DevPath) == MSG_IPv4_DP) {\r
2412 DPathNode->Ipv4.LocalPort = 0;\r
501793fa 2413\r
f75a7f56 2414 DPathNode->Ipv4.StaticIpAddress =\r
501793fa
RN
2415 (BOOLEAN) (!Session->ConfigData->SessionConfigData.InitiatorInfoFromDhcp);\r
2416\r
42f0586d 2417 //\r
2418 // Add a judgement here to support previous versions of IPv4_DEVICE_PATH.\r
2419 // In previous versions of IPv4_DEVICE_PATH, GatewayIpAddress and SubnetMask\r
2420 // do not exist.\r
2421 // In new version of IPv4_DEVICE_PATH, structcure length is 27.\r
2422 //\r
501793fa 2423\r
42f0586d 2424 PathLen = DevicePathNodeLength (&DPathNode->Ipv4);\r
f75a7f56
LG
2425\r
2426 if (PathLen == IP4_NODE_LEN_NEW_VERSIONS) {\r
2427\r
42f0586d 2428 IP4_COPY_ADDRESS (\r
2429 &DPathNode->Ipv4.GatewayIpAddress,\r
2430 &Session->ConfigData->SessionConfigData.Gateway\r
2431 );\r
2432\r
2433 IP4_COPY_ADDRESS (\r
2434 &DPathNode->Ipv4.SubnetMask,\r
2435 &Session->ConfigData->SessionConfigData.SubnetMask\r
2436 );\r
2437 }\r
f75a7f56 2438\r
4c5a5e0c 2439 break;\r
2440 } else if (Conn->Ipv6Flag && DevicePathSubType (&DPathNode->DevPath) == MSG_IPv6_DP) {\r
2441 DPathNode->Ipv6.LocalPort = 0;\r
42f0586d 2442\r
2443 //\r
2444 // Add a judgement here to support previous versions of IPv6_DEVICE_PATH.\r
2445 // In previous versions of IPv6_DEVICE_PATH, IpAddressOrigin, PrefixLength\r
2446 // and GatewayIpAddress do not exist.\r
f75a7f56 2447 // In new version of IPv6_DEVICE_PATH, structure length is 60, while in\r
42f0586d 2448 // old versions, the length is 43.\r
2449 //\r
2450\r
2451 PathLen = DevicePathNodeLength (&DPathNode->Ipv6);\r
f75a7f56
LG
2452\r
2453 if (PathLen == IP6_NODE_LEN_NEW_VERSIONS ) {\r
42f0586d 2454\r
2455 DPathNode->Ipv6.IpAddressOrigin = 0;\r
2456 DPathNode->Ipv6.PrefixLength = IP6_PREFIX_LENGTH;\r
2457 ZeroMem (&DPathNode->Ipv6.GatewayIpAddress, sizeof (EFI_IPv6_ADDRESS));\r
2458 }\r
f75a7f56 2459 else if (PathLen == IP6_NODE_LEN_OLD_VERSIONS) {\r
42f0586d 2460\r
2461 //\r
f75a7f56 2462 // StaticIPAddress is a field in old versions of IPv6_DEVICE_PATH, while ignored in new\r
42f0586d 2463 // version. Set StaticIPAddress through its' offset in old IPv6_DEVICE_PATH.\r
2464 //\r
f75a7f56 2465 *((UINT8 *)(&DPathNode->Ipv6) + IP6_OLD_IPADDRESS_OFFSET) =\r
42f0586d 2466 (BOOLEAN) (!Session->ConfigData->SessionConfigData.InitiatorInfoFromDhcp);\r
2467 }\r
f75a7f56 2468\r
4c5a5e0c 2469 break;\r
2470 }\r
2471 }\r
2472\r
2473 DPathNode = (EFI_DEV_PATH *) NextDevicePathNode (&DPathNode->DevPath);\r
2474 }\r
2475\r
2476 return DevicePath;\r
2477}\r
2478\r
2479\r
2480/**\r
2481 Abort the session when the transition from BS to RT is initiated.\r
2482\r
2483 @param[in] Event The event signaled.\r
2484 @param[in] Context The iSCSI driver data.\r
2485\r
2486**/\r
2487VOID\r
2488EFIAPI\r
2489IScsiOnExitBootService (\r
2490 IN EFI_EVENT Event,\r
2491 IN VOID *Context\r
2492 )\r
2493{\r
2494 ISCSI_DRIVER_DATA *Private;\r
2495\r
2496 Private = (ISCSI_DRIVER_DATA *) Context;\r
f75a7f56 2497\r
4c5a5e0c 2498 gBS->CloseEvent (Private->ExitBootServiceEvent);\r
a37c60b6 2499 Private->ExitBootServiceEvent = NULL;\r
f75a7f56 2500\r
4c5a5e0c 2501 if (Private->Session != NULL) {\r
2502 IScsiSessionAbort (Private->Session);\r
2503 }\r
2504}\r
18b24f92
FS
2505\r
2506/**\r
2507 Tests whether a controller handle is being managed by IScsi driver.\r
2508\r
2509 This function tests whether the driver specified by DriverBindingHandle is\r
2510 currently managing the controller specified by ControllerHandle. This test\r
2511 is performed by evaluating if the the protocol specified by ProtocolGuid is\r
2512 present on ControllerHandle and is was opened by DriverBindingHandle and Nic\r
f75a7f56 2513 Device handle with an attribute of EFI_OPEN_PROTOCOL_BY_DRIVER.\r
18b24f92
FS
2514 If ProtocolGuid is NULL, then ASSERT().\r
2515\r
2516 @param ControllerHandle A handle for a controller to test.\r
2517 @param DriverBindingHandle Specifies the driver binding handle for the\r
2518 driver.\r
2519 @param ProtocolGuid Specifies the protocol that the driver specified\r
2520 by DriverBindingHandle opens in its Start()\r
2521 function.\r
2522\r
2523 @retval EFI_SUCCESS ControllerHandle is managed by the driver\r
2524 specified by DriverBindingHandle.\r
2525 @retval EFI_UNSUPPORTED ControllerHandle is not managed by the driver\r
2526 specified by DriverBindingHandle.\r
2527\r
2528**/\r
2529EFI_STATUS\r
2530EFIAPI\r
2531IScsiTestManagedDevice (\r
2532 IN EFI_HANDLE ControllerHandle,\r
2533 IN EFI_HANDLE DriverBindingHandle,\r
2534 IN EFI_GUID *ProtocolGuid\r
2535 )\r
2536{\r
2537 EFI_STATUS Status;\r
2538 VOID *ManagedInterface;\r
2539 EFI_HANDLE NicControllerHandle;\r
2540\r
2541 ASSERT (ProtocolGuid != NULL);\r
2542\r
2543 NicControllerHandle = NetLibGetNicHandle (ControllerHandle, ProtocolGuid);\r
2544 if (NicControllerHandle == NULL) {\r
2545 return EFI_UNSUPPORTED;\r
2546 }\r
2547\r
2548 Status = gBS->OpenProtocol (\r
2549 ControllerHandle,\r
2550 (EFI_GUID *) ProtocolGuid,\r
2551 &ManagedInterface,\r
2552 DriverBindingHandle,\r
2553 NicControllerHandle,\r
2554 EFI_OPEN_PROTOCOL_BY_DRIVER\r
2555 );\r
2556 if (!EFI_ERROR (Status)) {\r
2557 gBS->CloseProtocol (\r
2558 ControllerHandle,\r
2559 (EFI_GUID *) ProtocolGuid,\r
2560 DriverBindingHandle,\r
2561 NicControllerHandle\r
2562 );\r
2563 return EFI_UNSUPPORTED;\r
2564 }\r
2565\r
2566 if (Status != EFI_ALREADY_STARTED) {\r
2567 return EFI_UNSUPPORTED;\r
2568 }\r
2569\r
2570 return EFI_SUCCESS;\r
2571}\r