Fix a K9 error.Result of GetVariable2() function that may return NULL will be derefer...
[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 (ConfigDataTmp == NULL || EFI_ERROR (Status)) {\r
660     return FALSE;\r
661   }\r
662 \r
663   if (ConfigDataTmp->Enabled && ConfigDataTmp->InitiatorInfoFromDhcp) {\r
664     FreePool (ConfigDataTmp);\r
665     return TRUE;\r
666   }\r
667 \r
668   FreePool (ConfigDataTmp);\r
669   return FALSE;\r
670 }\r
671 \r
672 /**\r
673   Get the various configuration data of this iSCSI instance.\r
674 \r
675   @param[in]  Private   The iSCSI driver data.\r
676 \r
677   @retval EFI_SUCCESS   The configuration of this instance is got.\r
678   @retval EFI_ABORTED   The operation was aborted.\r
679   @retval Others        Other errors as indicated.\r
680 **/\r
681 EFI_STATUS\r
682 IScsiGetConfigData (\r
683   IN ISCSI_DRIVER_DATA  *Private\r
684   )\r
685 {\r
686   EFI_STATUS                  Status;\r
687   ISCSI_SESSION               *Session;\r
688   UINTN                       BufferSize;\r
689   EFI_MAC_ADDRESS             MacAddress;\r
690   UINTN                       HwAddressSize;\r
691   UINT16                      VlanId;\r
692   CHAR16                      MacString[70];\r
693 \r
694   //\r
695   // get the iSCSI Initiator Name\r
696   //\r
697   Session                       = &Private->Session;\r
698   Session->InitiatorNameLength  = ISCSI_NAME_MAX_SIZE;\r
699   Status = gIScsiInitiatorName.Get (\r
700                                 &gIScsiInitiatorName,\r
701                                 &Session->InitiatorNameLength,\r
702                                 Session->InitiatorName\r
703                                 );\r
704   if (EFI_ERROR (Status)) {\r
705     return Status;\r
706   }\r
707 \r
708   //\r
709   // Get the mac string, it's the name of various variable\r
710   //\r
711   Status = NetLibGetMacAddress (Private->Controller, &MacAddress, &HwAddressSize);\r
712   ASSERT (Status == EFI_SUCCESS);\r
713   VlanId = NetLibGetVlanId (Private->Controller);\r
714   IScsiMacAddrToStr (&MacAddress, (UINT32) HwAddressSize, VlanId, MacString);\r
715 \r
716   //\r
717   // Get the normal configuration.\r
718   //\r
719   BufferSize = sizeof (Session->ConfigData.NvData);\r
720   Status = gRT->GetVariable (\r
721                   MacString,\r
722                   &gEfiIScsiInitiatorNameProtocolGuid,\r
723                   NULL,\r
724                   &BufferSize,\r
725                   &Session->ConfigData.NvData\r
726                   );\r
727   if (EFI_ERROR (Status)) {\r
728     return Status;\r
729   }\r
730 \r
731   if (!Session->ConfigData.NvData.Enabled) {\r
732     return EFI_ABORTED;\r
733   }\r
734   //\r
735   // Get the CHAP Auth information.\r
736   //\r
737   BufferSize = sizeof (Session->AuthData.AuthConfig);\r
738   Status = gRT->GetVariable (\r
739                   MacString,\r
740                   &gIScsiCHAPAuthInfoGuid,\r
741                   NULL,\r
742                   &BufferSize,\r
743                   &Session->AuthData.AuthConfig\r
744                   );\r
745 \r
746   if (!EFI_ERROR (Status) && Session->ConfigData.NvData.InitiatorInfoFromDhcp) {\r
747     //\r
748     // Start dhcp.\r
749     //\r
750     Status = IScsiDoDhcp (Private->Image, Private->Controller, &Session->ConfigData);\r
751   }\r
752 \r
753   return Status;\r
754 }\r
755 \r
756 /**\r
757   Get the device path of the iSCSI tcp connection and update it.\r
758 \r
759   @param[in]  Private The iSCSI driver data.\r
760 \r
761   @return The updated device path.\r
762   @retval NULL Other errors as indicated.\r
763 **/\r
764 EFI_DEVICE_PATH_PROTOCOL *\r
765 IScsiGetTcpConnDevicePath (\r
766   IN ISCSI_DRIVER_DATA  *Private\r
767   )\r
768 {\r
769   ISCSI_SESSION             *Session;\r
770   ISCSI_CONNECTION          *Conn;\r
771   TCP4_IO                   *Tcp4Io;\r
772   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
773   EFI_STATUS                Status;\r
774   EFI_DEV_PATH              *DPathNode;\r
775 \r
776   Session = &Private->Session;\r
777   if (Session->State != SESSION_STATE_LOGGED_IN) {\r
778     return NULL;\r
779   }\r
780 \r
781   Conn = NET_LIST_USER_STRUCT_S (\r
782           Session->Conns.ForwardLink,\r
783           ISCSI_CONNECTION,\r
784           Link,\r
785           ISCSI_CONNECTION_SIGNATURE\r
786           );\r
787   Tcp4Io = &Conn->Tcp4Io;\r
788 \r
789   Status = gBS->HandleProtocol (\r
790                   Tcp4Io->Handle,\r
791                   &gEfiDevicePathProtocolGuid,\r
792                   (VOID **)&DevicePath\r
793                   );\r
794   if (EFI_ERROR (Status)) {\r
795     return NULL;\r
796   }\r
797   //\r
798   // Duplicate it.\r
799   //\r
800   DevicePath  = DuplicateDevicePath (DevicePath);\r
801   if (DevicePath == NULL) {\r
802     return NULL;\r
803   }\r
804 \r
805   DPathNode   = (EFI_DEV_PATH *) DevicePath;\r
806 \r
807   while (!IsDevicePathEnd (&DPathNode->DevPath)) {\r
808     if ((DevicePathType (&DPathNode->DevPath) == MESSAGING_DEVICE_PATH) &&\r
809         (DevicePathSubType (&DPathNode->DevPath) == MSG_IPv4_DP)\r
810         ) {\r
811 \r
812       DPathNode->Ipv4.LocalPort       = 0;\r
813       DPathNode->Ipv4.StaticIpAddress = \r
814         (BOOLEAN) (!Session->ConfigData.NvData.InitiatorInfoFromDhcp);\r
815 \r
816       IP4_COPY_ADDRESS (\r
817         &DPathNode->Ipv4.GatewayIpAddress,\r
818         &Session->ConfigData.NvData.Gateway\r
819         );\r
820 \r
821       IP4_COPY_ADDRESS (\r
822         &DPathNode->Ipv4.SubnetMask,\r
823         &Session->ConfigData.NvData.SubnetMask\r
824         );\r
825 \r
826       break;\r
827     }\r
828 \r
829     DPathNode = (EFI_DEV_PATH *) NextDevicePathNode (&DPathNode->DevPath);\r
830   }\r
831 \r
832   return DevicePath;\r
833 }\r
834 \r
835 /**\r
836   Abort the session when the transition from BS to RT is initiated.\r
837 \r
838   @param[in]   Event  The event signaled.\r
839   @param[in]  Context The iSCSI driver data.\r
840 **/\r
841 VOID\r
842 EFIAPI\r
843 IScsiOnExitBootService (\r
844   IN EFI_EVENT  Event,\r
845   IN VOID       *Context\r
846   )\r
847 {\r
848   ISCSI_DRIVER_DATA *Private;\r
849 \r
850   Private = (ISCSI_DRIVER_DATA *) Context;\r
851   gBS->CloseEvent (Private->ExitBootServiceEvent);\r
852 \r
853   IScsiSessionAbort (&Private->Session);\r
854 }\r