Fix a bug about the iSCSI DHCP dependency issue.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / IScsiDxe / IScsiMisc.c
1 /** @file\r
2   Miscellaneous routines for iSCSI driver.\r
3 \r
4 Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>\r
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution.  The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9 \r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12 \r
13 **/\r
14 \r
15 #include "IScsiImpl.h"\r
16 \r
17 GLOBAL_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. On return, \r
23                         Str will hold the trimmed string. \r
24 \r
25   @param[in]      CharC Character will be trimmed from str.\r
26 **/\r
27 VOID\r
28 StrTrim (\r
29   IN OUT CHAR16   *Str,\r
30   IN     CHAR16   CharC\r
31   )\r
32 {\r
33   CHAR16  *Pointer1;\r
34   CHAR16  *Pointer2;\r
35   \r
36   if (*Str == 0) {\r
37     return;\r
38   }\r
39   \r
40   //\r
41   // Trim off the leading and trailing characters c\r
42   //\r
43   for (Pointer1 = Str; (*Pointer1 != 0) && (*Pointer1 == CharC); Pointer1++) {\r
44     ;\r
45   }\r
46   \r
47   Pointer2 = Str;\r
48   if (Pointer2 == Pointer1) {\r
49     while (*Pointer1 != 0) {\r
50       Pointer2++;\r
51       Pointer1++;\r
52     }\r
53   } else {\r
54     while (*Pointer1 != 0) {    \r
55     *Pointer2 = *Pointer1;    \r
56     Pointer1++;\r
57     Pointer2++;\r
58     }\r
59     *Pointer2 = 0;\r
60   }\r
61   \r
62   \r
63   for (Pointer1 = Str + StrLen(Str) - 1; Pointer1 >= Str && *Pointer1 == CharC; Pointer1--) {\r
64     ;\r
65   }\r
66   if  (Pointer1 !=  Str + StrLen(Str) - 1) { \r
67     *(Pointer1 + 1) = 0;\r
68   }\r
69 }\r
70 \r
71 /**\r
72   Calculate the prefix length of the IPv4 subnet mask.\r
73 \r
74   @param[in]  SubnetMask The IPv4 subnet mask.\r
75 \r
76   @return The prefix length of the subnet mask.\r
77   @retval 0 Other errors as indicated.\r
78 **/\r
79 UINT8\r
80 IScsiGetSubnetMaskPrefixLength (\r
81   IN EFI_IPv4_ADDRESS  *SubnetMask\r
82   )\r
83 {\r
84   UINT8   Len;\r
85   UINT32  ReverseMask;\r
86 \r
87   //\r
88   // The SubnetMask is in network byte order.\r
89   //\r
90   ReverseMask = (SubnetMask->Addr[0] << 24) | (SubnetMask->Addr[1] << 16) | (SubnetMask->Addr[2] << 8) | (SubnetMask->Addr[3]);\r
91 \r
92   //\r
93   // Reverse it.\r
94   //\r
95   ReverseMask = ~ReverseMask;\r
96 \r
97   if ((ReverseMask & (ReverseMask + 1)) != 0) {\r
98     return 0;\r
99   }\r
100 \r
101   Len = 0;\r
102 \r
103   while (ReverseMask != 0) {\r
104     ReverseMask = ReverseMask >> 1;\r
105     Len++;\r
106   }\r
107 \r
108   return (UINT8) (32 - Len);\r
109 }\r
110 \r
111 /**\r
112   Convert the hexadecimal encoded LUN string into the 64-bit LUN. \r
113 \r
114   @param[in]   Str             The hexadecimal encoded LUN string.\r
115   @param[out]  Lun             Storage to return the 64-bit LUN.\r
116 \r
117   @retval EFI_SUCCESS           The 64-bit LUN is stored in Lun.\r
118   @retval EFI_INVALID_PARAMETER The string is malformatted.\r
119 **/\r
120 EFI_STATUS\r
121 IScsiAsciiStrToLun (\r
122   IN  CHAR8  *Str,\r
123   OUT UINT8  *Lun\r
124   )\r
125 {\r
126   UINTN   Index, IndexValue, IndexNum, SizeStr;\r
127   CHAR8   TemStr[2];\r
128   UINT8   TemValue;\r
129   UINT16  Value[4];\r
130   \r
131   ZeroMem (Lun, 8);\r
132   ZeroMem (TemStr, 2);\r
133   ZeroMem ((UINT8 *) Value, sizeof (Value));\r
134   SizeStr    = AsciiStrLen (Str);  \r
135   IndexValue = 0;\r
136   IndexNum   = 0;\r
137 \r
138   for (Index = 0; Index < SizeStr; Index ++) {\r
139     TemStr[0] = Str[Index];\r
140     TemValue = (UINT8) AsciiStrHexToUint64 (TemStr);\r
141     if (TemValue == 0 && TemStr[0] != '0') {\r
142       if ((TemStr[0] != '-') || (IndexNum == 0)) {\r
143         //\r
144         // Invalid Lun Char\r
145         //\r
146         return EFI_INVALID_PARAMETER;\r
147       }\r
148     }\r
149     \r
150     if ((TemValue == 0) && (TemStr[0] == '-')) {\r
151       //\r
152       // Next Lun value\r
153       //\r
154       if (++IndexValue >= 4) {\r
155         //\r
156         // Max 4 Lun value\r
157         //\r
158         return EFI_INVALID_PARAMETER;\r
159       }\r
160       //\r
161       // Restart str index for the next lun value\r
162       //\r
163       IndexNum = 0;\r
164       continue;\r
165     }\r
166     \r
167     if (++IndexNum > 4) {\r
168       //     \r
169       // Each Lun Str can't exceed size 4, because it will be as UINT16 value\r
170       //\r
171       return EFI_INVALID_PARAMETER;\r
172     }\r
173     \r
174     //\r
175     // Combine UINT16 value\r
176     //\r
177     Value[IndexValue] = (UINT16) ((Value[IndexValue] << 4) + TemValue);\r
178   }\r
179  \r
180   for (Index = 0; Index <= IndexValue; Index ++) {\r
181     *((UINT16 *) &Lun[Index * 2]) =  HTONS (Value[Index]);\r
182   }\r
183   \r
184   return EFI_SUCCESS;\r
185 }\r
186 \r
187 /**\r
188   Convert the 64-bit LUN into the hexadecimal encoded LUN string.\r
189 \r
190   @param[in]   Lun The 64-bit LUN.\r
191   @param[out]  Str The storage to return the hexadecimal encoded LUN string.\r
192 **/\r
193 VOID\r
194 IScsiLunToUnicodeStr (\r
195   IN UINT8    *Lun,\r
196   OUT CHAR16  *Str\r
197   )\r
198 {\r
199   UINTN   Index;\r
200   CHAR16  *TempStr;\r
201 \r
202   TempStr = Str;\r
203 \r
204   for (Index = 0; Index < 4; Index++) {\r
205 \r
206     if ((Lun[2 * Index] | Lun[2 * Index + 1]) == 0) {\r
207       StrCpy (TempStr, L"0-");\r
208     } else {\r
209       TempStr[0]  = (CHAR16) IScsiHexString[Lun[2 * Index] >> 4];\r
210       TempStr[1]  = (CHAR16) IScsiHexString[Lun[2 * Index] & 0x0F];\r
211       TempStr[2]  = (CHAR16) IScsiHexString[Lun[2 * Index + 1] >> 4];\r
212       TempStr[3]  = (CHAR16) IScsiHexString[Lun[2 * Index + 1] & 0x0F];\r
213       TempStr[4]  = L'-';\r
214       TempStr[5]  = 0;\r
215 \r
216       StrTrim (TempStr, L'0');\r
217     }\r
218 \r
219     TempStr += StrLen (TempStr);\r
220   }\r
221 \r
222   Str[StrLen (Str) - 1] = 0;\r
223 \r
224   for (Index = StrLen (Str) - 1; Index > 1; Index = Index - 2) {\r
225     if ((Str[Index] == L'0') && (Str[Index - 1] == L'-')) {\r
226       Str[Index - 1] = 0;\r
227     } else {\r
228       break;\r
229     }\r
230   }\r
231 }\r
232 \r
233 /**\r
234   Convert the ASCII string into a UNICODE string.\r
235 \r
236   @param[in]   Source      The ASCII string.\r
237   @param[out]  Destination The storage to return the UNICODE string.\r
238 \r
239   @return CHAR16 *         Pointer to the UNICODE string.\r
240 **/\r
241 CHAR16 *\r
242 IScsiAsciiStrToUnicodeStr (\r
243   IN  CHAR8   *Source,\r
244   OUT CHAR16  *Destination\r
245   )\r
246 {\r
247   ASSERT (Destination != NULL);\r
248   ASSERT (Source != NULL);\r
249 \r
250   while (*Source != '\0') {\r
251     *(Destination++) = (CHAR16) *(Source++);\r
252   }\r
253 \r
254   *Destination = '\0';\r
255 \r
256   return Destination;\r
257 }\r
258 \r
259 /**\r
260   Convert the UNICODE string into an ASCII string.\r
261 \r
262   @param[in]  Source       The UNICODE string.\r
263   @param[out] Destination  The storage to return the ASCII string.\r
264 \r
265   @return CHAR8 *          Pointer to the ASCII string.\r
266 **/\r
267 CHAR8 *\r
268 IScsiUnicodeStrToAsciiStr (\r
269   IN  CHAR16  *Source,\r
270   OUT CHAR8   *Destination\r
271   )\r
272 {\r
273   ASSERT (Destination != NULL);\r
274   ASSERT (Source != NULL);\r
275 \r
276   while (*Source != '\0') {\r
277     //\r
278     // If any Unicode characters in Source contain\r
279     // non-zero value in the upper 8 bits, then ASSERT().\r
280     //\r
281     ASSERT (*Source < 0x100);\r
282     *(Destination++) = (CHAR8) *(Source++);\r
283   }\r
284 \r
285   *Destination = '\0';\r
286 \r
287   return Destination;\r
288 }\r
289 \r
290 /**\r
291   Convert the decimal dotted IPv4 address into the binary IPv4 address.\r
292 \r
293   @param[in]   Str             The UNICODE string.\r
294   @param[out]  Ip              The storage to return the ASCII string.\r
295 \r
296   @retval EFI_SUCCESS           The binary IP address is returned in Ip.\r
297   @retval EFI_INVALID_PARAMETER The IP string is malformatted.\r
298 **/\r
299 EFI_STATUS\r
300 IScsiAsciiStrToIp (\r
301   IN  CHAR8             *Str,\r
302   OUT EFI_IPv4_ADDRESS  *Ip\r
303   )\r
304 {\r
305   UINTN Index;\r
306   UINTN Number;\r
307 \r
308   Index = 0;\r
309 \r
310   while (*Str != 0) {\r
311 \r
312     if (Index > 3) {\r
313       return EFI_INVALID_PARAMETER;\r
314     }\r
315 \r
316     Number = 0;\r
317     while (NET_IS_DIGIT (*Str)) {\r
318       Number = Number * 10 + (*Str - '0');\r
319       Str++;\r
320     }\r
321 \r
322     if (Number > 0xFF) {\r
323       return EFI_INVALID_PARAMETER;\r
324     }\r
325 \r
326     Ip->Addr[Index] = (UINT8) Number;\r
327 \r
328     if ((*Str != '\0') && (*Str != '.')) {\r
329       //\r
330       // The current character should be either the NULL terminator or\r
331       // the dot delimiter.\r
332       //\r
333       return EFI_INVALID_PARAMETER;\r
334     }\r
335 \r
336     if (*Str == '.') {\r
337       //\r
338       // Skip the delimiter.\r
339       //\r
340       Str++;\r
341     }\r
342 \r
343     Index++;\r
344   }\r
345 \r
346   if (Index != 4) {\r
347     return EFI_INVALID_PARAMETER;\r
348   }\r
349 \r
350   return EFI_SUCCESS;\r
351 }\r
352 \r
353 /**\r
354   Convert the mac address into a hexadecimal encoded "-" seperated string.\r
355 \r
356   @param[in]  Mac     The mac address.\r
357   @param[in]  Len     Length in bytes of the mac address.\r
358   @param[in]  VlanId  VLAN ID of the network device.\r
359   @param[out] Str     The storage to return the mac string.\r
360 **/\r
361 VOID\r
362 IScsiMacAddrToStr (\r
363   IN  EFI_MAC_ADDRESS  *Mac,\r
364   IN  UINT32           Len,\r
365   IN  UINT16           VlanId,\r
366   OUT CHAR16           *Str\r
367   )\r
368 {\r
369   UINT32  Index;\r
370   CHAR16  *String;\r
371 \r
372   for (Index = 0; Index < Len; Index++) {\r
373     Str[3 * Index]      = (CHAR16) IScsiHexString[(Mac->Addr[Index] >> 4) & 0x0F];\r
374     Str[3 * Index + 1]  = (CHAR16) IScsiHexString[Mac->Addr[Index] & 0x0F];\r
375     Str[3 * Index + 2]  = L'-';\r
376   }\r
377 \r
378   String = &Str[3 * Index - 1] ;\r
379   if (VlanId != 0) {\r
380     String += UnicodeSPrint (String, 6 * sizeof (CHAR16), L"\\%04x", (UINTN) VlanId);\r
381   }\r
382 \r
383   *String = L'\0';\r
384 }\r
385 \r
386 /**\r
387   Convert the binary encoded buffer into a hexadecimal encoded string.\r
388 \r
389   @param[in]       BinBuffer   The buffer containing the binary data.\r
390   @param[in]       BinLength   Length of the binary buffer.\r
391   @param[in, out]  HexStr      Pointer to the string.\r
392   @param[in, out]  HexLength   The length of the string.\r
393 \r
394   @retval EFI_SUCCESS          The binary data is converted to the hexadecimal string \r
395                                and the length of the string is updated.\r
396   @retval EFI_BUFFER_TOO_SMALL The string is too small.\r
397   @retval EFI_INVALID_PARAMETER The IP string is malformatted.\r
398 **/\r
399 EFI_STATUS\r
400 IScsiBinToHex (\r
401   IN     UINT8  *BinBuffer,\r
402   IN     UINT32 BinLength,\r
403   IN OUT CHAR8  *HexStr,\r
404   IN OUT UINT32 *HexLength\r
405   )\r
406 {\r
407   UINTN Index;\r
408 \r
409   if ((HexStr == NULL) || (BinBuffer == NULL) || (BinLength == 0)) {\r
410     return EFI_INVALID_PARAMETER;\r
411   }\r
412 \r
413   if (((*HexLength) - 3) < BinLength * 2) {\r
414     *HexLength = BinLength * 2 + 3;\r
415     return EFI_BUFFER_TOO_SMALL;\r
416   }\r
417 \r
418   *HexLength = BinLength * 2 + 3;\r
419   //\r
420   // Prefix for Hex String\r
421   //\r
422   HexStr[0] = '0';\r
423   HexStr[1] = 'x';\r
424 \r
425   for (Index = 0; Index < BinLength; Index++) {\r
426     HexStr[Index * 2 + 2] = IScsiHexString[BinBuffer[Index] >> 4];\r
427     HexStr[Index * 2 + 3] = IScsiHexString[BinBuffer[Index] & 0x0F];\r
428   }\r
429 \r
430   HexStr[Index * 2 + 2] = '\0';\r
431 \r
432   return EFI_SUCCESS;\r
433 }\r
434 \r
435 /**\r
436   Convert the hexadecimal string into a binary encoded buffer.\r
437 \r
438   @param[in, out]  BinBuffer   The binary buffer.\r
439   @param[in, out]  BinLength   Length of the binary buffer.\r
440   @param[in]       HexStr      The hexadecimal string.\r
441 \r
442   @retval EFI_SUCCESS          The hexadecimal string is converted into a binary\r
443                                encoded buffer.\r
444   @retval EFI_BUFFER_TOO_SMALL The binary buffer is too small to hold the converted data.\r
445 **/\r
446 EFI_STATUS\r
447 IScsiHexToBin (\r
448   IN OUT UINT8  *BinBuffer,\r
449   IN OUT UINT32 *BinLength,\r
450   IN     CHAR8  *HexStr\r
451   )\r
452 {\r
453   UINTN   Index;\r
454   UINTN   Length;\r
455   UINT8   Digit;\r
456   CHAR8   TemStr[2];\r
457   \r
458   ZeroMem (TemStr, sizeof (TemStr));\r
459 \r
460   //\r
461   // Find out how many hex characters the string has.\r
462   //\r
463   if ((HexStr[0] == '0') && ((HexStr[1] == 'x') || (HexStr[1] == 'X'))) {\r
464     HexStr += 2;\r
465   }\r
466   \r
467   Length = AsciiStrLen (HexStr);\r
468 \r
469   for (Index = 0; Index < Length; Index ++) {\r
470     TemStr[0] = HexStr[Index];\r
471     Digit = (UINT8) AsciiStrHexToUint64 (TemStr);\r
472     if (Digit == 0 && TemStr[0] != '0') {\r
473       //\r
474       // Invalid Lun Char\r
475       //\r
476       break;\r
477     }\r
478     if ((Index & 1) == 0) {\r
479       BinBuffer [Index/2] = Digit;\r
480     } else {\r
481       BinBuffer [Index/2] = (UINT8) ((BinBuffer [Index/2] << 4) + Digit);\r
482     }\r
483   }\r
484   \r
485   *BinLength = (UINT32) ((Index + 1)/2);\r
486 \r
487   return EFI_SUCCESS;\r
488 }\r
489 \r
490 /**\r
491   Generate random numbers.\r
492 \r
493   @param[in, out]  Rand       The buffer to contain random numbers.\r
494   @param[in]       RandLength The length of the Rand buffer.\r
495 **/\r
496 VOID\r
497 IScsiGenRandom (\r
498   IN OUT UINT8  *Rand,\r
499   IN     UINTN  RandLength\r
500   )\r
501 {\r
502   UINT32  Random;\r
503 \r
504   while (RandLength > 0) {\r
505     Random  = NET_RANDOM (NetRandomInitSeed ());\r
506     *Rand++ = (UINT8) (Random);\r
507     RandLength--;\r
508   }\r
509 }\r
510 \r
511 /**\r
512   Create the iSCSI driver data..\r
513 \r
514   @param[in] Image      The handle of the driver image.\r
515   @param[in] Controller The handle of the controller.\r
516 \r
517   @return The iSCSI driver data created.\r
518   @retval NULL Other errors as indicated.\r
519 **/\r
520 ISCSI_DRIVER_DATA *\r
521 IScsiCreateDriverData (\r
522   IN EFI_HANDLE  Image,\r
523   IN EFI_HANDLE  Controller\r
524   )\r
525 {\r
526   ISCSI_DRIVER_DATA *Private;\r
527   EFI_STATUS        Status;\r
528 \r
529   Private = AllocateZeroPool (sizeof (ISCSI_DRIVER_DATA));\r
530   if (Private == NULL) {\r
531     return NULL;\r
532   }\r
533 \r
534   Private->Signature  = ISCSI_DRIVER_DATA_SIGNATURE;\r
535   Private->Image      = Image;\r
536   Private->Controller = Controller;\r
537 \r
538   //\r
539   // Create an event to be signal when the BS to RT transition is triggerd so\r
540   // as to abort the iSCSI session.\r
541   //\r
542   Status = gBS->CreateEventEx (\r
543                   EVT_NOTIFY_SIGNAL,\r
544                   TPL_CALLBACK,\r
545                   IScsiOnExitBootService,\r
546                   Private,\r
547                   &gEfiEventExitBootServicesGuid,\r
548                   &Private->ExitBootServiceEvent\r
549                   );\r
550   if (EFI_ERROR (Status)) {\r
551     FreePool (Private);\r
552     return NULL;\r
553   }\r
554 \r
555   CopyMem(&Private->IScsiExtScsiPassThru, &gIScsiExtScsiPassThruProtocolTemplate, sizeof(EFI_EXT_SCSI_PASS_THRU_PROTOCOL));\r
556 \r
557   //\r
558   // 0 is designated to the TargetId, so use another value for the AdapterId.\r
559   //\r
560   Private->ExtScsiPassThruMode.AdapterId = 2;\r
561   Private->ExtScsiPassThruMode.Attributes = EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;\r
562   Private->ExtScsiPassThruMode.IoAlign  = 4;\r
563   Private->IScsiExtScsiPassThru.Mode    = &Private->ExtScsiPassThruMode;\r
564 \r
565   //\r
566   // Install the Ext SCSI PASS THRU protocol.\r
567   //\r
568   Status = gBS->InstallProtocolInterface (\r
569                   &Private->ExtScsiPassThruHandle,\r
570                   &gEfiExtScsiPassThruProtocolGuid,\r
571                   EFI_NATIVE_INTERFACE,\r
572                   &Private->IScsiExtScsiPassThru\r
573                   );\r
574   if (EFI_ERROR (Status)) {\r
575     gBS->CloseEvent (Private->ExitBootServiceEvent);\r
576     FreePool (Private);\r
577 \r
578     return NULL;\r
579   }\r
580 \r
581   IScsiSessionInit (&Private->Session, FALSE);\r
582 \r
583   return Private;\r
584 }\r
585 \r
586 /**\r
587   Clean the iSCSI driver data.\r
588 \r
589   @param[in]  Private The iSCSI driver data.\r
590 **/\r
591 VOID\r
592 IScsiCleanDriverData (\r
593   IN ISCSI_DRIVER_DATA  *Private\r
594   )\r
595 {\r
596   if (Private->DevicePath != NULL) {\r
597     gBS->UninstallProtocolInterface (\r
598           Private->ExtScsiPassThruHandle,\r
599           &gEfiDevicePathProtocolGuid,\r
600           Private->DevicePath\r
601           );\r
602 \r
603     FreePool (Private->DevicePath);\r
604   }\r
605 \r
606   if (Private->ExtScsiPassThruHandle != NULL) {\r
607     gBS->UninstallProtocolInterface (\r
608           Private->ExtScsiPassThruHandle,\r
609           &gEfiExtScsiPassThruProtocolGuid,\r
610           &Private->IScsiExtScsiPassThru\r
611           );\r
612   }\r
613 \r
614   gBS->CloseEvent (Private->ExitBootServiceEvent);\r
615 \r
616   FreePool (Private);\r
617 }\r
618 \r
619 /**\r
620   Check wheather the Controller is configured to use DHCP protocol.\r
621 \r
622   @param[in]  Controller           The handle of the controller.\r
623   \r
624   @retval TRUE                     The handle of the controller need the Dhcp protocol.\r
625   @retval FALSE                    The handle of the controller does not need the Dhcp protocol.\r
626   \r
627 **/\r
628 BOOLEAN\r
629 IScsiDhcpIsConfigured (\r
630   IN EFI_HANDLE  Controller\r
631   )\r
632 {\r
633   EFI_STATUS                  Status;\r
634   EFI_MAC_ADDRESS             MacAddress;\r
635   UINTN                       HwAddressSize;\r
636   UINT16                      VlanId;\r
637   CHAR16                      MacString[70];\r
638   ISCSI_SESSION_CONFIG_NVDATA *ConfigDataTmp;\r
639 \r
640   //\r
641   // Get the mac string, it's the name of various variable\r
642   //\r
643   Status = NetLibGetMacAddress (Controller, &MacAddress, &HwAddressSize);\r
644   if (EFI_ERROR (Status)) {\r
645     return FALSE;\r
646   }\r
647   VlanId = NetLibGetVlanId (Controller);\r
648   IScsiMacAddrToStr (&MacAddress, (UINT32) HwAddressSize, VlanId, MacString);\r
649 \r
650   //\r
651   // Get the normal configuration.\r
652   //\r
653   Status = GetVariable2 (\r
654              MacString,\r
655              &gEfiIScsiInitiatorNameProtocolGuid,\r
656              (VOID**)&ConfigDataTmp,\r
657              NULL\r
658              );\r
659   if (EFI_ERROR (Status)) {\r
660     return FALSE;\r
661   }\r
662   \r
663 \r
664   if (ConfigDataTmp->Enabled && ConfigDataTmp->InitiatorInfoFromDhcp) {\r
665     FreePool (ConfigDataTmp);\r
666     return TRUE;\r
667   }\r
668 \r
669   FreePool (ConfigDataTmp);\r
670   return FALSE;\r
671 }\r
672 \r
673 /**\r
674   Get the various configuration data of this iSCSI instance.\r
675 \r
676   @param[in]  Private   The iSCSI driver data.\r
677 \r
678   @retval EFI_SUCCESS   The configuration of this instance is got.\r
679   @retval EFI_ABORTED   The operation was aborted.\r
680   @retval Others        Other errors as indicated.\r
681 **/\r
682 EFI_STATUS\r
683 IScsiGetConfigData (\r
684   IN ISCSI_DRIVER_DATA  *Private\r
685   )\r
686 {\r
687   EFI_STATUS                  Status;\r
688   ISCSI_SESSION               *Session;\r
689   UINTN                       BufferSize;\r
690   EFI_MAC_ADDRESS             MacAddress;\r
691   UINTN                       HwAddressSize;\r
692   UINT16                      VlanId;\r
693   CHAR16                      MacString[70];\r
694 \r
695   //\r
696   // get the iSCSI Initiator Name\r
697   //\r
698   Session                       = &Private->Session;\r
699   Session->InitiatorNameLength  = ISCSI_NAME_MAX_SIZE;\r
700   Status = gIScsiInitiatorName.Get (\r
701                                 &gIScsiInitiatorName,\r
702                                 &Session->InitiatorNameLength,\r
703                                 Session->InitiatorName\r
704                                 );\r
705   if (EFI_ERROR (Status)) {\r
706     return Status;\r
707   }\r
708 \r
709   //\r
710   // Get the mac string, it's the name of various variable\r
711   //\r
712   Status = NetLibGetMacAddress (Private->Controller, &MacAddress, &HwAddressSize);\r
713   ASSERT (Status == EFI_SUCCESS);\r
714   VlanId = NetLibGetVlanId (Private->Controller);\r
715   IScsiMacAddrToStr (&MacAddress, (UINT32) HwAddressSize, VlanId, MacString);\r
716 \r
717   //\r
718   // Get the normal configuration.\r
719   //\r
720   BufferSize = sizeof (Session->ConfigData.NvData);\r
721   Status = gRT->GetVariable (\r
722                   MacString,\r
723                   &gEfiIScsiInitiatorNameProtocolGuid,\r
724                   NULL,\r
725                   &BufferSize,\r
726                   &Session->ConfigData.NvData\r
727                   );\r
728   if (EFI_ERROR (Status)) {\r
729     return Status;\r
730   }\r
731 \r
732   if (!Session->ConfigData.NvData.Enabled) {\r
733     return EFI_ABORTED;\r
734   }\r
735   //\r
736   // Get the CHAP Auth information.\r
737   //\r
738   BufferSize = sizeof (Session->AuthData.AuthConfig);\r
739   Status = gRT->GetVariable (\r
740                   MacString,\r
741                   &gIScsiCHAPAuthInfoGuid,\r
742                   NULL,\r
743                   &BufferSize,\r
744                   &Session->AuthData.AuthConfig\r
745                   );\r
746 \r
747   if (!EFI_ERROR (Status) && Session->ConfigData.NvData.InitiatorInfoFromDhcp) {\r
748     //\r
749     // Start dhcp.\r
750     //\r
751     Status = IScsiDoDhcp (Private->Image, Private->Controller, &Session->ConfigData);\r
752   }\r
753 \r
754   return Status;\r
755 }\r
756 \r
757 /**\r
758   Get the device path of the iSCSI tcp connection and update it.\r
759 \r
760   @param[in]  Private The iSCSI driver data.\r
761 \r
762   @return The updated device path.\r
763   @retval NULL Other errors as indicated.\r
764 **/\r
765 EFI_DEVICE_PATH_PROTOCOL *\r
766 IScsiGetTcpConnDevicePath (\r
767   IN ISCSI_DRIVER_DATA  *Private\r
768   )\r
769 {\r
770   ISCSI_SESSION             *Session;\r
771   ISCSI_CONNECTION          *Conn;\r
772   TCP4_IO                   *Tcp4Io;\r
773   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
774   EFI_STATUS                Status;\r
775   EFI_DEV_PATH              *DPathNode;\r
776 \r
777   Session = &Private->Session;\r
778   if (Session->State != SESSION_STATE_LOGGED_IN) {\r
779     return NULL;\r
780   }\r
781 \r
782   Conn = NET_LIST_USER_STRUCT_S (\r
783           Session->Conns.ForwardLink,\r
784           ISCSI_CONNECTION,\r
785           Link,\r
786           ISCSI_CONNECTION_SIGNATURE\r
787           );\r
788   Tcp4Io = &Conn->Tcp4Io;\r
789 \r
790   Status = gBS->HandleProtocol (\r
791                   Tcp4Io->Handle,\r
792                   &gEfiDevicePathProtocolGuid,\r
793                   (VOID **)&DevicePath\r
794                   );\r
795   if (EFI_ERROR (Status)) {\r
796     return NULL;\r
797   }\r
798   //\r
799   // Duplicate it.\r
800   //\r
801   DevicePath  = DuplicateDevicePath (DevicePath);\r
802   if (DevicePath == NULL) {\r
803     return NULL;\r
804   }\r
805 \r
806   DPathNode   = (EFI_DEV_PATH *) DevicePath;\r
807 \r
808   while (!IsDevicePathEnd (&DPathNode->DevPath)) {\r
809     if ((DevicePathType (&DPathNode->DevPath) == MESSAGING_DEVICE_PATH) &&\r
810         (DevicePathSubType (&DPathNode->DevPath) == MSG_IPv4_DP)\r
811         ) {\r
812 \r
813       DPathNode->Ipv4.LocalPort       = 0;\r
814       DPathNode->Ipv4.StaticIpAddress = \r
815         (BOOLEAN) (!Session->ConfigData.NvData.InitiatorInfoFromDhcp);\r
816 \r
817       IP4_COPY_ADDRESS (\r
818         &DPathNode->Ipv4.GatewayIpAddress,\r
819         &Session->ConfigData.NvData.Gateway\r
820         );\r
821 \r
822       IP4_COPY_ADDRESS (\r
823         &DPathNode->Ipv4.SubnetMask,\r
824         &Session->ConfigData.NvData.SubnetMask\r
825         );\r
826 \r
827       break;\r
828     }\r
829 \r
830     DPathNode = (EFI_DEV_PATH *) NextDevicePathNode (&DPathNode->DevPath);\r
831   }\r
832 \r
833   return DevicePath;\r
834 }\r
835 \r
836 /**\r
837   Abort the session when the transition from BS to RT is initiated.\r
838 \r
839   @param[in]   Event  The event signaled.\r
840   @param[in]  Context The iSCSI driver data.\r
841 **/\r
842 VOID\r
843 EFIAPI\r
844 IScsiOnExitBootService (\r
845   IN EFI_EVENT  Event,\r
846   IN VOID       *Context\r
847   )\r
848 {\r
849   ISCSI_DRIVER_DATA *Private;\r
850 \r
851   Private = (ISCSI_DRIVER_DATA *) Context;\r
852   gBS->CloseEvent (Private->ExitBootServiceEvent);\r
853 \r
854   IScsiSessionAbort (&Private->Session);\r
855 }\r