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