]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/IScsiDxe/IScsiMisc.c
BaseTools: Fix the regression issue caused by commit dc4c77
[mirror_edk2.git] / NetworkPkg / IScsiDxe / IScsiMisc.c
CommitLineData
4c5a5e0c 1/** @file\r
2 Miscellaneous routines for iSCSI driver.\r
3\r
eabc6e59 4Copyright (c) 2004 - 2017, 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
23 On return, Str will hold the trimmed string. \r
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
36 \r
37 if (*Str == 0) {\r
38 return ;\r
39 }\r
40 \r
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
47 \r
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
55 while (*Pointer1 != 0) { \r
56 *Pointer2 = *Pointer1; \r
57 Pointer1++;\r
58 Pointer2++;\r
59 }\r
60 *Pointer2 = 0;\r
61 }\r
62 \r
63 \r
64 for (Pointer1 = Str + StrLen(Str) - 1; Pointer1 >= Str && *Pointer1 == CharC; Pointer1--) {\r
65 ;\r
66 }\r
67 if (Pointer1 != Str + StrLen(Str) - 1) { \r
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
134 \r
135 ZeroMem (Lun, 8);\r
136 ZeroMem (TemStr, 2);\r
137 ZeroMem ((UINT8 *) Value, sizeof (Value));\r
138 SizeStr = AsciiStrLen (Str); \r
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
153 \r
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
170 \r
171 if (++IndexNum > 4) {\r
172 // \r
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
177 \r
178 //\r
179 // Combine UINT16 value.\r
180 //\r
181 Value[IndexValue] = (UINT16) ((Value[IndexValue] << 4) + TemValue);\r
182 }\r
183 \r
184 for (Index = 0; Index <= IndexValue; Index ++) {\r
185 *((UINT16 *) &Lun[Index * 2]) = HTONS (Value[Index]);\r
186 }\r
187 \r
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
322 @retval EFI_SUCCESS The binary data is converted to the hexadecimal string \r
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
388 \r
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
397 \r
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
415 \r
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
468/**\r
469 Record the NIC info in global structure.\r
470\r
471 @param[in] Controller The handle of the controller.\r
472\r
473 @retval EFI_SUCCESS The operation is completed.\r
474 @retval EFI_OUT_OF_RESOURCES Do not have sufficient resources to finish this\r
475 operation.\r
476\r
477**/\r
478EFI_STATUS\r
479IScsiAddNic (\r
480 IN EFI_HANDLE Controller\r
481 )\r
482{\r
483 EFI_STATUS Status;\r
484 ISCSI_NIC_INFO *NicInfo;\r
485 LIST_ENTRY *Entry;\r
486 EFI_MAC_ADDRESS MacAddr;\r
487 UINTN HwAddressSize;\r
488 UINT16 VlanId;\r
489\r
490 //\r
491 // Get MAC address of this network device.\r
492 //\r
493 Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);\r
494 if (EFI_ERROR (Status)) {\r
495 return Status;\r
496 }\r
497\r
498 //\r
499 // Get VLAN ID of this network device.\r
500 //\r
501 VlanId = NetLibGetVlanId (Controller);\r
502\r
503 //\r
504 // Check whether the NIC info already exists. Return directly if so.\r
505 //\r
506 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {\r
507 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);\r
508 if (NicInfo->HwAddressSize == HwAddressSize &&\r
509 CompareMem (&NicInfo->PermanentAddress, MacAddr.Addr, HwAddressSize) == 0 &&\r
510 NicInfo->VlanId == VlanId) {\r
511 mPrivate->CurrentNic = NicInfo->NicIndex;\r
512 return EFI_SUCCESS;\r
513 }\r
514\r
515 if (mPrivate->MaxNic < NicInfo->NicIndex) {\r
516 mPrivate->MaxNic = NicInfo->NicIndex;\r
517 }\r
518 }\r
519\r
520 //\r
521 // Record the NIC info in private structure.\r
522 //\r
523 NicInfo = AllocateZeroPool (sizeof (ISCSI_NIC_INFO));\r
524 if (NicInfo == NULL) {\r
525 return EFI_OUT_OF_RESOURCES;\r
526 }\r
527\r
528 CopyMem (&NicInfo->PermanentAddress, MacAddr.Addr, HwAddressSize);\r
529 NicInfo->HwAddressSize = (UINT32) HwAddressSize;\r
530 NicInfo->VlanId = VlanId;\r
531 NicInfo->NicIndex = (UINT8) (mPrivate->MaxNic + 1);\r
532 mPrivate->MaxNic = NicInfo->NicIndex;\r
533\r
534 //\r
535 // Get the PCI location.\r
536 //\r
537 IScsiGetNICPciLocation (\r
538 Controller,\r
539 &NicInfo->BusNumber,\r
540 &NicInfo->DeviceNumber,\r
541 &NicInfo->FunctionNumber\r
542 );\r
543\r
544 InsertTailList (&mPrivate->NicInfoList, &NicInfo->Link);\r
545 mPrivate->NicCount++;\r
546\r
547 mPrivate->CurrentNic = NicInfo->NicIndex;\r
548 return EFI_SUCCESS;\r
549}\r
550\r
551\r
552/**\r
553 Delete the recorded NIC info from global structure. Also delete corresponding\r
554 attempts.\r
555\r
556 @param[in] Controller The handle of the controller.\r
557\r
558 @retval EFI_SUCCESS The operation is completed.\r
559 @retval EFI_NOT_FOUND The NIC info to be deleted is not recorded.\r
560\r
561**/\r
562EFI_STATUS\r
563IScsiRemoveNic (\r
564 IN EFI_HANDLE Controller\r
565 )\r
566{\r
567 EFI_STATUS Status;\r
568 ISCSI_NIC_INFO *NicInfo;\r
569 LIST_ENTRY *Entry;\r
570 LIST_ENTRY *NextEntry;\r
571 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
572 ISCSI_NIC_INFO *ThisNic;\r
573 EFI_MAC_ADDRESS MacAddr;\r
574 UINTN HwAddressSize;\r
575 UINT16 VlanId;\r
576\r
577 //\r
578 // Get MAC address of this network device.\r
579 //\r
580 Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);\r
581 if (EFI_ERROR (Status)) {\r
582 return Status;\r
583 }\r
584\r
585 //\r
586 // Get VLAN ID of this network device.\r
587 //\r
588 VlanId = NetLibGetVlanId (Controller);\r
589\r
590 //\r
591 // Check whether the NIC information exists.\r
592 //\r
593 ThisNic = NULL;\r
594\r
595 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {\r
596 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);\r
597 if (NicInfo->HwAddressSize == HwAddressSize &&\r
598 CompareMem (&NicInfo->PermanentAddress, MacAddr.Addr, HwAddressSize) == 0 &&\r
599 NicInfo->VlanId == VlanId) {\r
600\r
601 ThisNic = NicInfo;\r
602 break;\r
603 }\r
604 }\r
605\r
606 if (ThisNic == NULL) {\r
607 return EFI_NOT_FOUND;\r
608 }\r
609\r
610 mPrivate->CurrentNic = ThisNic->NicIndex;\r
611\r
612 RemoveEntryList (&ThisNic->Link);\r
613 FreePool (ThisNic);\r
614 mPrivate->NicCount--;\r
615\r
616 //\r
617 // Remove all attempts related to this NIC.\r
618 //\r
619 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mPrivate->AttemptConfigs) {\r
620 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
621 if (AttemptConfigData->NicIndex == mPrivate->CurrentNic) {\r
622 RemoveEntryList (&AttemptConfigData->Link);\r
623 mPrivate->AttemptCount--;\r
624\r
625 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO && mPrivate->MpioCount > 0) {\r
626 if (--mPrivate->MpioCount == 0) {\r
627 mPrivate->EnableMpio = FALSE;\r
628 }\r
629\r
630 if (AttemptConfigData->AuthenticationType == ISCSI_AUTH_TYPE_KRB && mPrivate->Krb5MpioCount > 0) {\r
631 mPrivate->Krb5MpioCount--;\r
632 }\r
633\r
634 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED && mPrivate->SinglePathCount > 0) {\r
635 mPrivate->SinglePathCount--;\r
636\r
637 if (mPrivate->ValidSinglePathCount > 0) {\r
638 mPrivate->ValidSinglePathCount--;\r
639 }\r
640 }\r
641\r
642 FreePool (AttemptConfigData);\r
643 }\r
644 }\r
645\r
c0d494b5 646 //\r
647 // Free attempt is created but not saved to system.\r
648 //\r
649 if (mPrivate->NewAttempt != NULL) {\r
650 FreePool (mPrivate->NewAttempt);\r
651 mPrivate->NewAttempt = NULL;\r
652 }\r
653\r
4c5a5e0c 654 return EFI_SUCCESS;\r
655}\r
656\r
657\r
658/**\r
659 Get the recorded NIC info from global structure by the Index.\r
660\r
661 @param[in] NicIndex The index indicates the position of NIC info.\r
662\r
663 @return Pointer to the NIC info, or NULL if not found.\r
664\r
665**/\r
666ISCSI_NIC_INFO *\r
667IScsiGetNicInfoByIndex (\r
668 IN UINT8 NicIndex\r
669 )\r
670{\r
671 LIST_ENTRY *Entry;\r
672 ISCSI_NIC_INFO *NicInfo;\r
673\r
674 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {\r
675 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);\r
676 if (NicInfo->NicIndex == NicIndex) {\r
677 return NicInfo;\r
678 }\r
679 }\r
680\r
681 return NULL;\r
682}\r
683\r
684\r
685/**\r
59c0c1cb 686 Get the NIC's PCI location and return it according to the composited\r
4c5a5e0c 687 format defined in iSCSI Boot Firmware Table.\r
688\r
689 @param[in] Controller The handle of the controller.\r
690 @param[out] Bus The bus number.\r
691 @param[out] Device The device number.\r
692 @param[out] Function The function number.\r
693\r
694 @return The composited representation of the NIC PCI location.\r
695\r
696**/\r
697UINT16\r
698IScsiGetNICPciLocation (\r
699 IN EFI_HANDLE Controller,\r
700 OUT UINTN *Bus,\r
701 OUT UINTN *Device,\r
702 OUT UINTN *Function\r
703 )\r
704{\r
705 EFI_STATUS Status;\r
706 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
707 EFI_HANDLE PciIoHandle;\r
708 EFI_PCI_IO_PROTOCOL *PciIo;\r
709 UINTN Segment;\r
710\r
711 Status = gBS->HandleProtocol (\r
712 Controller,\r
713 &gEfiDevicePathProtocolGuid,\r
714 (VOID **) &DevicePath\r
715 );\r
716 if (EFI_ERROR (Status)) {\r
717 return 0;\r
718 }\r
719\r
720 Status = gBS->LocateDevicePath (\r
721 &gEfiPciIoProtocolGuid,\r
722 &DevicePath,\r
723 &PciIoHandle\r
724 );\r
725 if (EFI_ERROR (Status)) {\r
726 return 0;\r
727 }\r
728\r
729 Status = gBS->HandleProtocol (PciIoHandle, &gEfiPciIoProtocolGuid, (VOID **) &PciIo);\r
730 if (EFI_ERROR (Status)) {\r
731 return 0;\r
732 }\r
733\r
734 Status = PciIo->GetLocation (PciIo, &Segment, Bus, Device, Function);\r
735 if (EFI_ERROR (Status)) {\r
736 return 0;\r
737 }\r
738\r
739 return (UINT16) ((*Bus << 8) | (*Device << 3) | *Function);\r
740}\r
741\r
742\r
743/**\r
744 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated\r
745 buffer, and the size of the buffer. If failure, return NULL.\r
746\r
747 @param[in] Name String part of EFI variable name.\r
748 @param[in] VendorGuid GUID part of EFI variable name.\r
749 @param[out] VariableSize Returns the size of the EFI variable that was read.\r
750\r
751 @return Dynamically allocated memory that contains a copy of the EFI variable.\r
752 @return Caller is responsible freeing the buffer.\r
753 @retval NULL Variable was not read.\r
754\r
755**/\r
756VOID *\r
757IScsiGetVariableAndSize (\r
758 IN CHAR16 *Name,\r
759 IN EFI_GUID *VendorGuid,\r
760 OUT UINTN *VariableSize\r
761 )\r
762{\r
763 EFI_STATUS Status;\r
764 UINTN BufferSize;\r
765 VOID *Buffer;\r
766\r
767 Buffer = NULL;\r
768\r
769 //\r
770 // Pass in a zero size buffer to find the required buffer size.\r
771 //\r
772 BufferSize = 0;\r
773 Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
774 if (Status == EFI_BUFFER_TOO_SMALL) {\r
775 //\r
776 // Allocate the buffer to return\r
777 //\r
778 Buffer = AllocateZeroPool (BufferSize);\r
779 if (Buffer == NULL) {\r
780 return NULL;\r
781 }\r
782 //\r
783 // Read variable into the allocated buffer.\r
784 //\r
785 Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
786 if (EFI_ERROR (Status)) {\r
787 BufferSize = 0;\r
788 }\r
789 }\r
790\r
791 *VariableSize = BufferSize;\r
792 return Buffer;\r
793}\r
794\r
795\r
796/**\r
797 Create the iSCSI driver data.\r
798\r
799 @param[in] Image The handle of the driver image.\r
800 @param[in] Controller The handle of the controller.\r
801\r
802 @return The iSCSI driver data created.\r
803 @retval NULL Other errors as indicated.\r
804\r
805**/\r
806ISCSI_DRIVER_DATA *\r
807IScsiCreateDriverData (\r
808 IN EFI_HANDLE Image,\r
809 IN EFI_HANDLE Controller\r
810 )\r
811{\r
812 ISCSI_DRIVER_DATA *Private;\r
813 EFI_STATUS Status;\r
814\r
815 Private = AllocateZeroPool (sizeof (ISCSI_DRIVER_DATA));\r
816 if (Private == NULL) {\r
817 return NULL;\r
818 }\r
819\r
820 Private->Signature = ISCSI_DRIVER_DATA_SIGNATURE;\r
821 Private->Image = Image;\r
822 Private->Controller = Controller;\r
823 Private->Session = NULL;\r
824\r
825 //\r
826 // Create an event to be signaled when the BS to RT transition is triggerd so\r
827 // as to abort the iSCSI session.\r
828 //\r
829 Status = gBS->CreateEventEx (\r
830 EVT_NOTIFY_SIGNAL,\r
831 TPL_CALLBACK,\r
832 IScsiOnExitBootService,\r
833 Private,\r
834 &gEfiEventExitBootServicesGuid,\r
835 &Private->ExitBootServiceEvent\r
836 );\r
837 if (EFI_ERROR (Status)) {\r
838 FreePool (Private);\r
839 return NULL;\r
840 }\r
841\r
842 Private->ExtScsiPassThruHandle = NULL;\r
843 CopyMem(&Private->IScsiExtScsiPassThru, &gIScsiExtScsiPassThruProtocolTemplate, sizeof(EFI_EXT_SCSI_PASS_THRU_PROTOCOL));\r
844\r
845 //\r
846 // 0 is designated to the TargetId, so use another value for the AdapterId.\r
847 //\r
848 Private->ExtScsiPassThruMode.AdapterId = 2;\r
849 Private->ExtScsiPassThruMode.Attributes = EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;\r
850 Private->ExtScsiPassThruMode.IoAlign = 4;\r
851 Private->IScsiExtScsiPassThru.Mode = &Private->ExtScsiPassThruMode;\r
852\r
853 return Private;\r
854}\r
855\r
856\r
857/**\r
858 Clean the iSCSI driver data.\r
859\r
e590d29f
ZL
860 @param[in] Private The iSCSI driver data.\r
861\r
6d0bab0e 862 @retval EFI_SUCCESS The clean operation is successful.\r
e590d29f 863 @retval Others Other errors as indicated.\r
4c5a5e0c 864\r
865**/\r
e590d29f 866EFI_STATUS\r
4c5a5e0c 867IScsiCleanDriverData (\r
868 IN ISCSI_DRIVER_DATA *Private\r
869 )\r
870{\r
871 EFI_STATUS Status;\r
6d0bab0e
ZL
872\r
873 Status = EFI_SUCCESS;\r
4c5a5e0c 874\r
875 if (Private->DevicePath != NULL) {\r
e590d29f
ZL
876 Status = gBS->UninstallProtocolInterface (\r
877 Private->ExtScsiPassThruHandle,\r
878 &gEfiDevicePathProtocolGuid,\r
879 Private->DevicePath\r
880 );\r
881 if (EFI_ERROR (Status)) {\r
882 goto EXIT;\r
883 }\r
4c5a5e0c 884\r
885 FreePool (Private->DevicePath);\r
886 }\r
887\r
888 if (Private->ExtScsiPassThruHandle != NULL) {\r
889 Status = gBS->UninstallProtocolInterface (\r
890 Private->ExtScsiPassThruHandle,\r
891 &gEfiExtScsiPassThruProtocolGuid,\r
892 &Private->IScsiExtScsiPassThru\r
893 );\r
894 if (!EFI_ERROR (Status)) {\r
895 mPrivate->OneSessionEstablished = FALSE;\r
896 }\r
897 }\r
898\r
e590d29f
ZL
899EXIT:\r
900\r
4c5a5e0c 901 gBS->CloseEvent (Private->ExitBootServiceEvent);\r
902\r
3cb5b997
ZL
903 mCallbackInfo->Current = NULL;\r
904\r
4c5a5e0c 905 FreePool (Private);\r
e590d29f 906 return Status;\r
4c5a5e0c 907}\r
908\r
b7cc5bf1
WJ
909/**\r
910 Check wheather the Controller handle is configured to use DHCP protocol.\r
911\r
912 @param[in] Controller The handle of the controller.\r
913 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.\r
914 \r
915 @retval TRUE The handle of the controller need the Dhcp protocol.\r
916 @retval FALSE The handle of the controller does not need the Dhcp protocol.\r
917 \r
918**/\r
919BOOLEAN\r
920IScsiDhcpIsConfigured (\r
921 IN EFI_HANDLE Controller,\r
922 IN UINT8 IpVersion\r
923 )\r
924{\r
925 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptTmp;\r
926 UINT8 *AttemptConfigOrder;\r
927 UINTN AttemptConfigOrderSize;\r
928 UINTN Index;\r
929 EFI_STATUS Status;\r
930 EFI_MAC_ADDRESS MacAddr;\r
931 UINTN HwAddressSize;\r
932 UINT16 VlanId;\r
933 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];\r
934 CHAR16 AttemptName[ISCSI_NAME_IFR_MAX_SIZE];\r
935 \r
936 AttemptConfigOrder = IScsiGetVariableAndSize (\r
937 L"AttemptOrder",\r
938 &gIScsiConfigGuid,\r
939 &AttemptConfigOrderSize\r
940 );\r
941 if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {\r
942 return FALSE;\r
943 }\r
944 \r
945 //\r
946 // Get MAC address of this network device.\r
947 //\r
948 Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);\r
949 if(EFI_ERROR (Status)) {\r
950 return FALSE;\r
951 }\r
952 //\r
953 // Get VLAN ID of this network device.\r
954 //\r
955 VlanId = NetLibGetVlanId (Controller);\r
956 IScsiMacAddrToStr (&MacAddr, (UINT32) HwAddressSize, VlanId, MacString);\r
957 \r
958 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {\r
959 UnicodeSPrint (\r
960 AttemptName,\r
961 (UINTN) 128,\r
962 L"%s%d",\r
963 MacString,\r
964 (UINTN) AttemptConfigOrder[Index]\r
965 );\r
966 Status = GetVariable2 (\r
967 AttemptName,\r
968 &gEfiIScsiInitiatorNameProtocolGuid,\r
969 (VOID**)&AttemptTmp,\r
970 NULL\r
971 );\r
107e3d7a 972 if(AttemptTmp == NULL || EFI_ERROR (Status)) {\r
b7cc5bf1
WJ
973 continue;\r
974 }\r
107e3d7a 975 \r
b7cc5bf1
WJ
976 ASSERT (AttemptConfigOrder[Index] == AttemptTmp->AttemptConfigIndex);\r
977\r
978 if (AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED) {\r
979 FreePool (AttemptTmp);\r
980 continue;\r
981 }\r
982\r
983 if (AttemptTmp->SessionConfigData.IpMode != IP_MODE_AUTOCONFIG && \r
984 AttemptTmp->SessionConfigData.IpMode != ((IpVersion == IP_VERSION_4) ? IP_MODE_IP4 : IP_MODE_IP6)) {\r
985 FreePool (AttemptTmp);\r
986 continue;\r
987 }\r
988 \r
989 if(AttemptTmp->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG ||\r
990 AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp == TRUE ||\r
991 AttemptTmp->SessionConfigData.TargetInfoFromDhcp == TRUE) { \r
992 FreePool (AttemptTmp);\r
993 FreePool (AttemptConfigOrder);\r
994 return TRUE;\r
995 }\r
996\r
997 FreePool (AttemptTmp);\r
998 }\r
999 \r
1000 FreePool (AttemptConfigOrder);\r
1001 return FALSE;\r
1002}\r
4c5a5e0c 1003\r
eabc6e59
ZL
1004/**\r
1005 Check wheather the Controller handle is configured to use DNS protocol.\r
1006\r
1007 @param[in] Controller The handle of the controller.\r
1008 \r
1009 @retval TRUE The handle of the controller need the Dns protocol.\r
1010 @retval FALSE The handle of the controller does not need the Dns protocol.\r
1011 \r
1012**/\r
1013BOOLEAN\r
1014IScsiDnsIsConfigured (\r
1015 IN EFI_HANDLE Controller\r
1016 )\r
1017{\r
1018 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptTmp;\r
1019 UINT8 *AttemptConfigOrder;\r
1020 UINTN AttemptConfigOrderSize;\r
1021 UINTN Index;\r
1022 EFI_STATUS Status;\r
1023 EFI_MAC_ADDRESS MacAddr;\r
1024 UINTN HwAddressSize;\r
1025 UINT16 VlanId;\r
1026 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];\r
1027 CHAR16 AttemptName[ISCSI_NAME_IFR_MAX_SIZE];\r
1028 \r
1029 AttemptConfigOrder = IScsiGetVariableAndSize (\r
1030 L"AttemptOrder",\r
1031 &gIScsiConfigGuid,\r
1032 &AttemptConfigOrderSize\r
1033 );\r
1034 if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {\r
1035 return FALSE;\r
1036 }\r
1037 \r
1038 //\r
1039 // Get MAC address of this network device.\r
1040 //\r
1041 Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);\r
1042 if(EFI_ERROR (Status)) {\r
1043 return FALSE;\r
1044 }\r
1045 //\r
1046 // Get VLAN ID of this network device.\r
1047 //\r
1048 VlanId = NetLibGetVlanId (Controller);\r
1049 IScsiMacAddrToStr (&MacAddr, (UINT32) HwAddressSize, VlanId, MacString);\r
1050 \r
1051 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {\r
1052 UnicodeSPrint (\r
1053 AttemptName,\r
1054 (UINTN) 128,\r
1055 L"%s%d",\r
1056 MacString,\r
1057 (UINTN) AttemptConfigOrder[Index]\r
1058 );\r
1059 Status = GetVariable2 (\r
1060 AttemptName,\r
1061 &gEfiIScsiInitiatorNameProtocolGuid,\r
1062 (VOID**)&AttemptTmp,\r
1063 NULL\r
1064 );\r
1065 if(AttemptTmp == NULL || EFI_ERROR (Status)) {\r
1066 continue;\r
1067 }\r
1068 \r
1069 ASSERT (AttemptConfigOrder[Index] == AttemptTmp->AttemptConfigIndex);\r
1070\r
1071 if (AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED) {\r
1072 FreePool (AttemptTmp);\r
1073 continue;\r
1074 }\r
1075 \r
1076 if (AttemptTmp->SessionConfigData.DnsMode) {\r
1077 FreePool (AttemptTmp);\r
1078 FreePool (AttemptConfigOrder);\r
1079 return TRUE;\r
1080 } else {\r
1081 FreePool (AttemptTmp);\r
1082 continue;\r
1083 }\r
1084\r
1085 }\r
1086\r
1087 FreePool (AttemptConfigOrder);\r
1088 return FALSE;\r
1089\r
1090}\r
1091\r
4c5a5e0c 1092/**\r
1093 Get the various configuration data.\r
1094\r
1095 @param[in] Private The iSCSI driver data.\r
1096\r
1097 @retval EFI_SUCCESS The configuration data is retrieved.\r
1098 @retval EFI_NOT_FOUND This iSCSI driver is not configured yet.\r
7c275b3c 1099 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
4c5a5e0c 1100\r
1101**/\r
1102EFI_STATUS\r
1103IScsiGetConfigData (\r
1104 IN ISCSI_DRIVER_DATA *Private\r
1105 )\r
1106{\r
1107 EFI_STATUS Status;\r
1108 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];\r
1109 UINTN Index;\r
1110 ISCSI_NIC_INFO *NicInfo;\r
1111 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
1112 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptTmp;\r
1113 UINT8 *AttemptConfigOrder;\r
1114 UINTN AttemptConfigOrderSize;\r
1115 CHAR16 IScsiMode[64];\r
1116 CHAR16 IpMode[64];\r
1117\r
1118 //\r
1119 // There should be at least one attempt configured.\r
1120 //\r
1121 AttemptConfigOrder = IScsiGetVariableAndSize (\r
1122 L"AttemptOrder",\r
9bdc6592 1123 &gIScsiConfigGuid,\r
4c5a5e0c 1124 &AttemptConfigOrderSize\r
1125 );\r
1126 if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {\r
1127 return EFI_NOT_FOUND;\r
1128 }\r
1129\r
1130 //\r
1131 // Get the iSCSI Initiator Name.\r
1132 //\r
1133 mPrivate->InitiatorNameLength = ISCSI_NAME_MAX_SIZE;\r
1134 Status = gIScsiInitiatorName.Get (\r
1135 &gIScsiInitiatorName,\r
1136 &mPrivate->InitiatorNameLength,\r
1137 mPrivate->InitiatorName\r
1138 );\r
1139 if (EFI_ERROR (Status)) {\r
1140 return Status;\r
1141 }\r
1142\r
1143 //\r
1144 // Get the normal configuration.\r
1145 //\r
1146 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {\r
1147\r
1148 //\r
1149 // Check whether the attempt exists in AttemptConfig.\r
1150 //\r
1151 AttemptTmp = IScsiConfigGetAttemptByConfigIndex (AttemptConfigOrder[Index]); \r
1152 if (AttemptTmp != NULL && AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED) {\r
1153 continue;\r
1154 } else if (AttemptTmp != NULL && AttemptTmp->SessionConfigData.Enabled != ISCSI_DISABLED) {\r
1155 //\r
1156 // Check the autoconfig path to see whether it should be retried.\r
1157 //\r
1158 if (AttemptTmp->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG &&\r
87ce4210 1159 !AttemptTmp->AutoConfigureSuccess) {\r
4c5a5e0c 1160 if (mPrivate->Ipv6Flag &&\r
1161 AttemptTmp->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6) {\r
1162 //\r
1163 // Autoconfigure for IP6 already attempted but failed. Do not try again.\r
1164 //\r
1165 continue;\r
1166 } else if (!mPrivate->Ipv6Flag &&\r
1167 AttemptTmp->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP4) {\r
1168 //\r
1169 // Autoconfigure for IP4 already attempted but failed. Do not try again.\r
1170 //\r
1171 continue;\r
1172 } else {\r
1173 //\r
1174 // Try another approach for this autoconfigure path.\r
1175 //\r
1176 AttemptTmp->AutoConfigureMode =\r
1177 (UINT8) (mPrivate->Ipv6Flag ? IP_MODE_AUTOCONFIG_IP6 : IP_MODE_AUTOCONFIG_IP4);\r
1178 AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp = TRUE;\r
1179 AttemptTmp->SessionConfigData.TargetInfoFromDhcp = TRUE;\r
1180 AttemptTmp->DhcpSuccess = FALSE;\r
1181\r
1182 //\r
1183 // Get some information from the dhcp server.\r
1184 //\r
1185 if (!mPrivate->Ipv6Flag) {\r
1186 Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptTmp);\r
1187 if (!EFI_ERROR (Status)) {\r
1188 AttemptTmp->DhcpSuccess = TRUE;\r
1189 }\r
1190 } else {\r
1191 Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptTmp);\r
1192 if (!EFI_ERROR (Status)) {\r
1193 AttemptTmp->DhcpSuccess = TRUE;\r
1194 }\r
1195 }\r
1196\r
1197 //\r
1198 // Refresh the state of this attempt to NVR.\r
1199 //\r
f256ab43 1200 AsciiStrToUnicodeStrS (AttemptTmp->MacString, MacString, ARRAY_SIZE (MacString));\r
4c5a5e0c 1201 UnicodeSPrint (\r
1202 mPrivate->PortString,\r
1203 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
1204 L"%s%d",\r
1205 MacString,\r
1206 (UINTN) AttemptTmp->AttemptConfigIndex\r
1207 );\r
1208\r
1209 gRT->SetVariable (\r
1210 mPrivate->PortString,\r
1211 &gEfiIScsiInitiatorNameProtocolGuid,\r
1212 ISCSI_CONFIG_VAR_ATTR,\r
1213 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),\r
1214 AttemptTmp\r
1215 );\r
1216\r
1217 continue;\r
1218 }\r
1219 } else if (AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp && !AttemptTmp->ValidPath) {\r
1220 //\r
1221 // Get DHCP information for already added, but failed, attempt.\r
1222 //\r
1223 AttemptTmp->DhcpSuccess = FALSE;\r
1224 if (!mPrivate->Ipv6Flag && (AttemptTmp->SessionConfigData.IpMode == IP_MODE_IP4)) {\r
1225 Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptTmp);\r
1226 if (!EFI_ERROR (Status)) {\r
1227 AttemptTmp->DhcpSuccess = TRUE;\r
1228 }\r
1229 } else if (mPrivate->Ipv6Flag && (AttemptTmp->SessionConfigData.IpMode == IP_MODE_IP6)) {\r
1230 Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptTmp);\r
1231 if (!EFI_ERROR (Status)) {\r
1232 AttemptTmp->DhcpSuccess = TRUE;\r
1233 }\r
1234 }\r
1235\r
1236 //\r
1237 // Refresh the state of this attempt to NVR.\r
1238 //\r
f256ab43 1239 AsciiStrToUnicodeStrS (AttemptTmp->MacString, MacString, ARRAY_SIZE (MacString));\r
4c5a5e0c 1240 UnicodeSPrint (\r
1241 mPrivate->PortString,\r
1242 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
1243 L"%s%d",\r
1244 MacString,\r
1245 (UINTN) AttemptTmp->AttemptConfigIndex\r
1246 );\r
1247\r
1248 gRT->SetVariable (\r
1249 mPrivate->PortString,\r
1250 &gEfiIScsiInitiatorNameProtocolGuid,\r
1251 ISCSI_CONFIG_VAR_ATTR,\r
1252 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),\r
1253 AttemptTmp\r
1254 );\r
1255\r
1256 continue;\r
1257\r
1258 } else {\r
1259 continue;\r
1260 }\r
1261 }\r
1262\r
1263 //\r
1264 // This attempt does not exist in AttemptConfig. Try to add a new one.\r
1265 //\r
1266\r
1267 NicInfo = IScsiGetNicInfoByIndex (mPrivate->CurrentNic);\r
1268 ASSERT (NicInfo != NULL);\r
1269 IScsiMacAddrToStr (&NicInfo->PermanentAddress, NicInfo->HwAddressSize, NicInfo->VlanId, MacString);\r
1270 UnicodeSPrint (\r
1271 mPrivate->PortString,\r
1272 (UINTN) 128,\r
1273 L"%s%d",\r
1274 MacString,\r
1275 (UINTN) AttemptConfigOrder[Index]\r
1276 );\r
1277\r
bf4a3dbd 1278 GetVariable2 (\r
a2d59ef2
YT
1279 mPrivate->PortString,\r
1280 &gEfiIScsiInitiatorNameProtocolGuid,\r
1281 (VOID**)&AttemptConfigData,\r
1282 NULL\r
1283 );\r
4c5a5e0c 1284\r
1285 if (AttemptConfigData == NULL) {\r
1286 continue;\r
1287 }\r
1288\r
1289 ASSERT (AttemptConfigOrder[Index] == AttemptConfigData->AttemptConfigIndex);\r
1290\r
1291 AttemptConfigData->NicIndex = NicInfo->NicIndex;\r
1292 AttemptConfigData->DhcpSuccess = FALSE;\r
1293 AttemptConfigData->ValidiBFTPath = (BOOLEAN) (mPrivate->EnableMpio ? TRUE : FALSE);\r
1294 AttemptConfigData->ValidPath = FALSE;\r
1295\r
1296 if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) {\r
1297 AttemptConfigData->SessionConfigData.InitiatorInfoFromDhcp = TRUE;\r
1298 AttemptConfigData->SessionConfigData.TargetInfoFromDhcp = TRUE;\r
1299\r
1300 AttemptConfigData->AutoConfigureMode =\r
1301 (UINT8) (mPrivate->Ipv6Flag ? IP_MODE_AUTOCONFIG_IP6 : IP_MODE_AUTOCONFIG_IP4);\r
87ce4210 1302 AttemptConfigData->AutoConfigureSuccess = FALSE;\r
4c5a5e0c 1303 }\r
1304 \r
1305 //\r
1306 // Get some information from dhcp server.\r
1307 //\r
1308 if (AttemptConfigData->SessionConfigData.Enabled != ISCSI_DISABLED &&\r
1309 AttemptConfigData->SessionConfigData.InitiatorInfoFromDhcp) {\r
1310\r
1311 if (!mPrivate->Ipv6Flag &&\r
1312 (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP4 ||\r
1313 AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP4)) {\r
1314 Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptConfigData);\r
1315 if (!EFI_ERROR (Status)) {\r
1316 AttemptConfigData->DhcpSuccess = TRUE;\r
1317 }\r
1318 } else if (mPrivate->Ipv6Flag &&\r
1319 (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP6 ||\r
1320 AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6)) {\r
1321 Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptConfigData);\r
1322 if (!EFI_ERROR (Status)) {\r
1323 AttemptConfigData->DhcpSuccess = TRUE;\r
1324 }\r
1325 }\r
1326\r
1327 //\r
1328 // Refresh the state of this attempt to NVR.\r
1329 //\r
f256ab43 1330 AsciiStrToUnicodeStrS (AttemptConfigData->MacString, MacString, ARRAY_SIZE (MacString));\r
4c5a5e0c 1331 UnicodeSPrint (\r
1332 mPrivate->PortString,\r
1333 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
1334 L"%s%d",\r
1335 MacString,\r
1336 (UINTN) AttemptConfigData->AttemptConfigIndex\r
1337 );\r
1338\r
1339 gRT->SetVariable (\r
1340 mPrivate->PortString,\r
1341 &gEfiIScsiInitiatorNameProtocolGuid,\r
1342 ISCSI_CONFIG_VAR_ATTR,\r
1343 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),\r
1344 AttemptConfigData\r
1345 );\r
1346 }\r
1347\r
1348 //\r
1349 // Update Attempt Help Info.\r
1350 //\r
1351\r
1352 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_DISABLED) {\r
1353 UnicodeSPrint (IScsiMode, 64, L"Disabled");\r
1354 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED) {\r
1355 UnicodeSPrint (IScsiMode, 64, L"Enabled");\r
1356 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {\r
1357 UnicodeSPrint (IScsiMode, 64, L"Enabled for MPIO");\r
1358 }\r
1359\r
1360 if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP4) {\r
1361 UnicodeSPrint (IpMode, 64, L"IP4");\r
1362 } else if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP6) {\r
1363 UnicodeSPrint (IpMode, 64, L"IP6");\r
1364 } else if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) {\r
1365 UnicodeSPrint (IpMode, 64, L"Autoconfigure");\r
1366 }\r
1367\r
1368 UnicodeSPrint (\r
1369 mPrivate->PortString,\r
1370 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
1371 L"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",\r
1372 MacString,\r
1373 NicInfo->BusNumber,\r
1374 NicInfo->DeviceNumber,\r
1375 NicInfo->FunctionNumber,\r
1376 IScsiMode,\r
1377 IpMode\r
1378 );\r
1379\r
1380 AttemptConfigData->AttemptTitleHelpToken = HiiSetString (\r
1381 mCallbackInfo->RegisteredHandle,\r
1382 0,\r
1383 mPrivate->PortString,\r
1384 NULL\r
1385 );\r
7c275b3c
ZL
1386 if (AttemptConfigData->AttemptTitleHelpToken == 0) {\r
1387 return EFI_OUT_OF_RESOURCES;\r
1388 }\r
4c5a5e0c 1389\r
1390 //\r
1391 // Record the attempt in global link list.\r
1392 //\r
1393 InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link);\r
1394 mPrivate->AttemptCount++;\r
1395\r
1396 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {\r
1397 mPrivate->MpioCount++;\r
1398 mPrivate->EnableMpio = TRUE;\r
1399\r
1400 if (AttemptConfigData->AuthenticationType == ISCSI_AUTH_TYPE_KRB) {\r
1401 mPrivate->Krb5MpioCount++;\r
1402 }\r
1403 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED) {\r
1404 mPrivate->SinglePathCount++;\r
1405 }\r
1406 }\r
1407\r
1408 //\r
1409 // Reorder the AttemptConfig by the configured order.\r
1410 //\r
1411 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {\r
1412 AttemptConfigData = IScsiConfigGetAttemptByConfigIndex (AttemptConfigOrder[Index]);\r
1413 if (AttemptConfigData == NULL) {\r
1414 continue;\r
1415 }\r
1416\r
1417 RemoveEntryList (&AttemptConfigData->Link);\r
1418 InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link);\r
1419 }\r
1420\r
1421 //\r
1422 // Update the Main Form.\r
1423 //\r
1424 IScsiConfigUpdateAttempt ();\r
1425\r
1426 FreePool (AttemptConfigOrder);\r
1427\r
1428 //\r
1429 // There should be at least one attempt configuration.\r
1430 //\r
1431 if (!mPrivate->EnableMpio) {\r
1432 if (mPrivate->SinglePathCount == 0) {\r
1433 return EFI_NOT_FOUND;\r
1434 }\r
1435 mPrivate->ValidSinglePathCount = mPrivate->SinglePathCount;\r
1436 }\r
1437\r
1438 return EFI_SUCCESS;\r
1439}\r
1440\r
1441\r
1442/**\r
1443 Get the device path of the iSCSI tcp connection and update it.\r
1444\r
1445 @param Session The iSCSI session.\r
1446\r
1447 @return The updated device path.\r
1448 @retval NULL Other errors as indicated.\r
1449\r
1450**/\r
1451EFI_DEVICE_PATH_PROTOCOL *\r
1452IScsiGetTcpConnDevicePath (\r
1453 IN ISCSI_SESSION *Session\r
1454 )\r
1455{\r
1456 ISCSI_CONNECTION *Conn;\r
1457 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
1458 EFI_STATUS Status;\r
1459 EFI_DEV_PATH *DPathNode;\r
42f0586d 1460 UINTN PathLen;\r
4c5a5e0c 1461\r
1462 if (Session->State != SESSION_STATE_LOGGED_IN) {\r
1463 return NULL;\r
1464 }\r
1465\r
1466 Conn = NET_LIST_USER_STRUCT_S (\r
1467 Session->Conns.ForwardLink,\r
1468 ISCSI_CONNECTION,\r
1469 Link,\r
1470 ISCSI_CONNECTION_SIGNATURE\r
1471 );\r
1472\r
1473 Status = gBS->HandleProtocol (\r
1474 Conn->TcpIo.Handle,\r
1475 &gEfiDevicePathProtocolGuid,\r
1476 (VOID **) &DevicePath\r
1477 ); \r
1478 if (EFI_ERROR (Status)) {\r
1479 return NULL;\r
1480 }\r
1481 //\r
1482 // Duplicate it.\r
1483 //\r
1484 DevicePath = DuplicateDevicePath (DevicePath);\r
1485 if (DevicePath == NULL) {\r
1486 return NULL;\r
1487 }\r
1488\r
1489 DPathNode = (EFI_DEV_PATH *) DevicePath;\r
1490\r
1491 while (!IsDevicePathEnd (&DPathNode->DevPath)) {\r
1492 if (DevicePathType (&DPathNode->DevPath) == MESSAGING_DEVICE_PATH) {\r
1493 if (!Conn->Ipv6Flag && DevicePathSubType (&DPathNode->DevPath) == MSG_IPv4_DP) {\r
1494 DPathNode->Ipv4.LocalPort = 0;\r
501793fa
RN
1495\r
1496 DPathNode->Ipv4.StaticIpAddress = \r
1497 (BOOLEAN) (!Session->ConfigData->SessionConfigData.InitiatorInfoFromDhcp);\r
1498\r
42f0586d 1499 //\r
1500 // Add a judgement here to support previous versions of IPv4_DEVICE_PATH.\r
1501 // In previous versions of IPv4_DEVICE_PATH, GatewayIpAddress and SubnetMask\r
1502 // do not exist.\r
1503 // In new version of IPv4_DEVICE_PATH, structcure length is 27.\r
1504 //\r
501793fa 1505\r
42f0586d 1506 PathLen = DevicePathNodeLength (&DPathNode->Ipv4);\r
1507 \r
5ae7578a 1508 if (PathLen == IP4_NODE_LEN_NEW_VERSIONS) { \r
42f0586d 1509 \r
1510 IP4_COPY_ADDRESS (\r
1511 &DPathNode->Ipv4.GatewayIpAddress,\r
1512 &Session->ConfigData->SessionConfigData.Gateway\r
1513 );\r
1514\r
1515 IP4_COPY_ADDRESS (\r
1516 &DPathNode->Ipv4.SubnetMask,\r
1517 &Session->ConfigData->SessionConfigData.SubnetMask\r
1518 );\r
1519 }\r
1520 \r
4c5a5e0c 1521 break;\r
1522 } else if (Conn->Ipv6Flag && DevicePathSubType (&DPathNode->DevPath) == MSG_IPv6_DP) {\r
1523 DPathNode->Ipv6.LocalPort = 0;\r
42f0586d 1524\r
1525 //\r
1526 // Add a judgement here to support previous versions of IPv6_DEVICE_PATH.\r
1527 // In previous versions of IPv6_DEVICE_PATH, IpAddressOrigin, PrefixLength\r
1528 // and GatewayIpAddress do not exist.\r
1529 // In new version of IPv6_DEVICE_PATH, structure length is 60, while in \r
1530 // old versions, the length is 43.\r
1531 //\r
1532\r
1533 PathLen = DevicePathNodeLength (&DPathNode->Ipv6);\r
1534 \r
5ae7578a 1535 if (PathLen == IP6_NODE_LEN_NEW_VERSIONS ) { \r
42f0586d 1536\r
1537 DPathNode->Ipv6.IpAddressOrigin = 0;\r
1538 DPathNode->Ipv6.PrefixLength = IP6_PREFIX_LENGTH;\r
1539 ZeroMem (&DPathNode->Ipv6.GatewayIpAddress, sizeof (EFI_IPv6_ADDRESS));\r
1540 }\r
5ae7578a 1541 else if (PathLen == IP6_NODE_LEN_OLD_VERSIONS) { \r
42f0586d 1542\r
1543 //\r
1544 // StaticIPAddress is a field in old versions of IPv6_DEVICE_PATH, while ignored in new \r
1545 // version. Set StaticIPAddress through its' offset in old IPv6_DEVICE_PATH.\r
1546 //\r
5ae7578a 1547 *((UINT8 *)(&DPathNode->Ipv6) + IP6_OLD_IPADDRESS_OFFSET) = \r
42f0586d 1548 (BOOLEAN) (!Session->ConfigData->SessionConfigData.InitiatorInfoFromDhcp);\r
1549 }\r
1550 \r
4c5a5e0c 1551 break;\r
1552 }\r
1553 }\r
1554\r
1555 DPathNode = (EFI_DEV_PATH *) NextDevicePathNode (&DPathNode->DevPath);\r
1556 }\r
1557\r
1558 return DevicePath;\r
1559}\r
1560\r
1561\r
1562/**\r
1563 Abort the session when the transition from BS to RT is initiated.\r
1564\r
1565 @param[in] Event The event signaled.\r
1566 @param[in] Context The iSCSI driver data.\r
1567\r
1568**/\r
1569VOID\r
1570EFIAPI\r
1571IScsiOnExitBootService (\r
1572 IN EFI_EVENT Event,\r
1573 IN VOID *Context\r
1574 )\r
1575{\r
1576 ISCSI_DRIVER_DATA *Private;\r
1577\r
1578 Private = (ISCSI_DRIVER_DATA *) Context;\r
1579 gBS->CloseEvent (Private->ExitBootServiceEvent);\r
1580\r
1581 if (Private->Session != NULL) {\r
1582 IScsiSessionAbort (Private->Session);\r
1583 }\r
1584}\r
18b24f92
FS
1585\r
1586/**\r
1587 Tests whether a controller handle is being managed by IScsi driver.\r
1588\r
1589 This function tests whether the driver specified by DriverBindingHandle is\r
1590 currently managing the controller specified by ControllerHandle. This test\r
1591 is performed by evaluating if the the protocol specified by ProtocolGuid is\r
1592 present on ControllerHandle and is was opened by DriverBindingHandle and Nic\r
1593 Device handle with an attribute of EFI_OPEN_PROTOCOL_BY_DRIVER. \r
1594 If ProtocolGuid is NULL, then ASSERT().\r
1595\r
1596 @param ControllerHandle A handle for a controller to test.\r
1597 @param DriverBindingHandle Specifies the driver binding handle for the\r
1598 driver.\r
1599 @param ProtocolGuid Specifies the protocol that the driver specified\r
1600 by DriverBindingHandle opens in its Start()\r
1601 function.\r
1602\r
1603 @retval EFI_SUCCESS ControllerHandle is managed by the driver\r
1604 specified by DriverBindingHandle.\r
1605 @retval EFI_UNSUPPORTED ControllerHandle is not managed by the driver\r
1606 specified by DriverBindingHandle.\r
1607\r
1608**/\r
1609EFI_STATUS\r
1610EFIAPI\r
1611IScsiTestManagedDevice (\r
1612 IN EFI_HANDLE ControllerHandle,\r
1613 IN EFI_HANDLE DriverBindingHandle,\r
1614 IN EFI_GUID *ProtocolGuid\r
1615 )\r
1616{\r
1617 EFI_STATUS Status;\r
1618 VOID *ManagedInterface;\r
1619 EFI_HANDLE NicControllerHandle;\r
1620\r
1621 ASSERT (ProtocolGuid != NULL);\r
1622\r
1623 NicControllerHandle = NetLibGetNicHandle (ControllerHandle, ProtocolGuid);\r
1624 if (NicControllerHandle == NULL) {\r
1625 return EFI_UNSUPPORTED;\r
1626 }\r
1627\r
1628 Status = gBS->OpenProtocol (\r
1629 ControllerHandle,\r
1630 (EFI_GUID *) ProtocolGuid,\r
1631 &ManagedInterface,\r
1632 DriverBindingHandle,\r
1633 NicControllerHandle,\r
1634 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1635 );\r
1636 if (!EFI_ERROR (Status)) {\r
1637 gBS->CloseProtocol (\r
1638 ControllerHandle,\r
1639 (EFI_GUID *) ProtocolGuid,\r
1640 DriverBindingHandle,\r
1641 NicControllerHandle\r
1642 );\r
1643 return EFI_UNSUPPORTED;\r
1644 }\r
1645\r
1646 if (Status != EFI_ALREADY_STARTED) {\r
1647 return EFI_UNSUPPORTED;\r
1648 }\r
1649\r
1650 return EFI_SUCCESS;\r
1651}\r