• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Miscellaneous routines for iSCSI driver.
3 
4 Copyright (c) 2004 - 2016, 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       CopyMem(TempStr, L"0-", sizeof (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   @retval EFI_SUCCESS     The clean operation is successful.
593   @retval Others          Other errors as indicated.
594 
595 **/
596 EFI_STATUS
IScsiCleanDriverData(IN ISCSI_DRIVER_DATA * Private)597 IScsiCleanDriverData (
598   IN ISCSI_DRIVER_DATA  *Private
599   )
600 {
601   EFI_STATUS             Status;
602 
603   Status = EFI_SUCCESS;
604 
605   if (Private->DevicePath != NULL) {
606     Status = gBS->UninstallProtocolInterface (
607                     Private->ExtScsiPassThruHandle,
608                     &gEfiDevicePathProtocolGuid,
609                     Private->DevicePath
610                     );
611     if (EFI_ERROR (Status)) {
612       goto EXIT;
613     }
614 
615     FreePool (Private->DevicePath);
616   }
617 
618   if (Private->ExtScsiPassThruHandle != NULL) {
619     Status = gBS->UninstallProtocolInterface (
620                     Private->ExtScsiPassThruHandle,
621                     &gEfiExtScsiPassThruProtocolGuid,
622                     &Private->IScsiExtScsiPassThru
623                     );
624   }
625 
626 EXIT:
627 
628   gBS->CloseEvent (Private->ExitBootServiceEvent);
629 
630   FreePool (Private);
631   return Status;
632 }
633 
634 /**
635   Check wheather the Controller is configured to use DHCP protocol.
636 
637   @param[in]  Controller           The handle of the controller.
638 
639   @retval TRUE                     The handle of the controller need the Dhcp protocol.
640   @retval FALSE                    The handle of the controller does not need the Dhcp protocol.
641 
642 **/
643 BOOLEAN
IScsiDhcpIsConfigured(IN EFI_HANDLE Controller)644 IScsiDhcpIsConfigured (
645   IN EFI_HANDLE  Controller
646   )
647 {
648   EFI_STATUS                  Status;
649   EFI_MAC_ADDRESS             MacAddress;
650   UINTN                       HwAddressSize;
651   UINT16                      VlanId;
652   CHAR16                      MacString[70];
653   ISCSI_SESSION_CONFIG_NVDATA *ConfigDataTmp;
654 
655   //
656   // Get the mac string, it's the name of various variable
657   //
658   Status = NetLibGetMacAddress (Controller, &MacAddress, &HwAddressSize);
659   if (EFI_ERROR (Status)) {
660     return FALSE;
661   }
662   VlanId = NetLibGetVlanId (Controller);
663   IScsiMacAddrToStr (&MacAddress, (UINT32) HwAddressSize, VlanId, MacString);
664 
665   //
666   // Get the normal configuration.
667   //
668   Status = GetVariable2 (
669              MacString,
670              &gEfiIScsiInitiatorNameProtocolGuid,
671              (VOID**)&ConfigDataTmp,
672              NULL
673              );
674   if (ConfigDataTmp == NULL || EFI_ERROR (Status)) {
675     return FALSE;
676   }
677 
678   if (ConfigDataTmp->Enabled && ConfigDataTmp->InitiatorInfoFromDhcp) {
679     FreePool (ConfigDataTmp);
680     return TRUE;
681   }
682 
683   FreePool (ConfigDataTmp);
684   return FALSE;
685 }
686 
687 /**
688   Get the various configuration data of this iSCSI instance.
689 
690   @param[in]  Private   The iSCSI driver data.
691 
692   @retval EFI_SUCCESS   The configuration of this instance is got.
693   @retval EFI_ABORTED   The operation was aborted.
694   @retval Others        Other errors as indicated.
695 **/
696 EFI_STATUS
IScsiGetConfigData(IN ISCSI_DRIVER_DATA * Private)697 IScsiGetConfigData (
698   IN ISCSI_DRIVER_DATA  *Private
699   )
700 {
701   EFI_STATUS                  Status;
702   ISCSI_SESSION               *Session;
703   UINTN                       BufferSize;
704   EFI_MAC_ADDRESS             MacAddress;
705   UINTN                       HwAddressSize;
706   UINT16                      VlanId;
707   CHAR16                      MacString[70];
708 
709   //
710   // get the iSCSI Initiator Name
711   //
712   Session                       = &Private->Session;
713   Session->InitiatorNameLength  = ISCSI_NAME_MAX_SIZE;
714   Status = gIScsiInitiatorName.Get (
715                                 &gIScsiInitiatorName,
716                                 &Session->InitiatorNameLength,
717                                 Session->InitiatorName
718                                 );
719   if (EFI_ERROR (Status)) {
720     return Status;
721   }
722 
723   //
724   // Get the mac string, it's the name of various variable
725   //
726   Status = NetLibGetMacAddress (Private->Controller, &MacAddress, &HwAddressSize);
727   ASSERT (Status == EFI_SUCCESS);
728   VlanId = NetLibGetVlanId (Private->Controller);
729   IScsiMacAddrToStr (&MacAddress, (UINT32) HwAddressSize, VlanId, MacString);
730 
731   //
732   // Get the normal configuration.
733   //
734   BufferSize = sizeof (Session->ConfigData.NvData);
735   Status = gRT->GetVariable (
736                   MacString,
737                   &gEfiIScsiInitiatorNameProtocolGuid,
738                   NULL,
739                   &BufferSize,
740                   &Session->ConfigData.NvData
741                   );
742   if (EFI_ERROR (Status)) {
743     return Status;
744   }
745 
746   if (!Session->ConfigData.NvData.Enabled) {
747     return EFI_ABORTED;
748   }
749   //
750   // Get the CHAP Auth information.
751   //
752   BufferSize = sizeof (Session->AuthData.AuthConfig);
753   Status = gRT->GetVariable (
754                   MacString,
755                   &gIScsiCHAPAuthInfoGuid,
756                   NULL,
757                   &BufferSize,
758                   &Session->AuthData.AuthConfig
759                   );
760 
761   if (!EFI_ERROR (Status) && Session->ConfigData.NvData.InitiatorInfoFromDhcp) {
762     //
763     // Start dhcp.
764     //
765     Status = IScsiDoDhcp (Private->Image, Private->Controller, &Session->ConfigData);
766   }
767 
768   return Status;
769 }
770 
771 /**
772   Get the device path of the iSCSI tcp connection and update it.
773 
774   @param[in]  Private The iSCSI driver data.
775 
776   @return The updated device path.
777   @retval NULL Other errors as indicated.
778 **/
779 EFI_DEVICE_PATH_PROTOCOL *
IScsiGetTcpConnDevicePath(IN ISCSI_DRIVER_DATA * Private)780 IScsiGetTcpConnDevicePath (
781   IN ISCSI_DRIVER_DATA  *Private
782   )
783 {
784   ISCSI_SESSION             *Session;
785   ISCSI_CONNECTION          *Conn;
786   TCP4_IO                   *Tcp4Io;
787   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
788   EFI_STATUS                Status;
789   EFI_DEV_PATH              *DPathNode;
790 
791   Session = &Private->Session;
792   if (Session->State != SESSION_STATE_LOGGED_IN) {
793     return NULL;
794   }
795 
796   Conn = NET_LIST_USER_STRUCT_S (
797           Session->Conns.ForwardLink,
798           ISCSI_CONNECTION,
799           Link,
800           ISCSI_CONNECTION_SIGNATURE
801           );
802   Tcp4Io = &Conn->Tcp4Io;
803 
804   Status = gBS->HandleProtocol (
805                   Tcp4Io->Handle,
806                   &gEfiDevicePathProtocolGuid,
807                   (VOID **)&DevicePath
808                   );
809   if (EFI_ERROR (Status)) {
810     return NULL;
811   }
812   //
813   // Duplicate it.
814   //
815   DevicePath  = DuplicateDevicePath (DevicePath);
816   if (DevicePath == NULL) {
817     return NULL;
818   }
819 
820   DPathNode   = (EFI_DEV_PATH *) DevicePath;
821 
822   while (!IsDevicePathEnd (&DPathNode->DevPath)) {
823     if ((DevicePathType (&DPathNode->DevPath) == MESSAGING_DEVICE_PATH) &&
824         (DevicePathSubType (&DPathNode->DevPath) == MSG_IPv4_DP)
825         ) {
826 
827       DPathNode->Ipv4.LocalPort       = 0;
828       DPathNode->Ipv4.StaticIpAddress =
829         (BOOLEAN) (!Session->ConfigData.NvData.InitiatorInfoFromDhcp);
830 
831       //
832       //  Add a judgement here to support previous versions of IPv4_DEVICE_PATH.
833       //  In previous versions of IPv4_DEVICE_PATH, GatewayIpAddress and SubnetMask
834       //  do not exist.
835       //  In new version of IPv4_DEVICE_PATH, structcure length is 27.
836       //
837       if (DevicePathNodeLength (&DPathNode->Ipv4) == IP4_NODE_LEN_NEW_VERSIONS) {
838 
839         IP4_COPY_ADDRESS (
840           &DPathNode->Ipv4.GatewayIpAddress,
841           &Session->ConfigData.NvData.Gateway
842           );
843 
844         IP4_COPY_ADDRESS (
845           &DPathNode->Ipv4.SubnetMask,
846           &Session->ConfigData.NvData.SubnetMask
847           );
848       }
849 
850       break;
851     }
852 
853     DPathNode = (EFI_DEV_PATH *) NextDevicePathNode (&DPathNode->DevPath);
854   }
855 
856   return DevicePath;
857 }
858 
859 /**
860   Abort the session when the transition from BS to RT is initiated.
861 
862   @param[in]   Event  The event signaled.
863   @param[in]  Context The iSCSI driver data.
864 **/
865 VOID
866 EFIAPI
IScsiOnExitBootService(IN EFI_EVENT Event,IN VOID * Context)867 IScsiOnExitBootService (
868   IN EFI_EVENT  Event,
869   IN VOID       *Context
870   )
871 {
872   ISCSI_DRIVER_DATA *Private;
873 
874   Private = (ISCSI_DRIVER_DATA *) Context;
875   gBS->CloseEvent (Private->ExitBootServiceEvent);
876 
877   IScsiSessionAbort (&Private->Session);
878 }
879 
880 /**
881   Tests whether a controller handle is being managed by IScsi driver.
882 
883   This function tests whether the driver specified by DriverBindingHandle is
884   currently managing the controller specified by ControllerHandle.  This test
885   is performed by evaluating if the the protocol specified by ProtocolGuid is
886   present on ControllerHandle and is was opened by DriverBindingHandle and Nic
887   Device handle with an attribute of EFI_OPEN_PROTOCOL_BY_DRIVER.
888   If ProtocolGuid is NULL, then ASSERT().
889 
890   @param  ControllerHandle     A handle for a controller to test.
891   @param  DriverBindingHandle  Specifies the driver binding handle for the
892                                driver.
893   @param  ProtocolGuid         Specifies the protocol that the driver specified
894                                by DriverBindingHandle opens in its Start()
895                                function.
896 
897   @retval EFI_SUCCESS          ControllerHandle is managed by the driver
898                                specified by DriverBindingHandle.
899   @retval EFI_UNSUPPORTED      ControllerHandle is not managed by the driver
900                                specified by DriverBindingHandle.
901 
902 **/
903 EFI_STATUS
904 EFIAPI
IScsiTestManagedDevice(IN EFI_HANDLE ControllerHandle,IN EFI_HANDLE DriverBindingHandle,IN EFI_GUID * ProtocolGuid)905 IScsiTestManagedDevice (
906   IN  EFI_HANDLE       ControllerHandle,
907   IN  EFI_HANDLE       DriverBindingHandle,
908   IN  EFI_GUID         *ProtocolGuid
909   )
910 {
911   EFI_STATUS     Status;
912   VOID           *ManagedInterface;
913   EFI_HANDLE     NicControllerHandle;
914 
915   ASSERT (ProtocolGuid != NULL);
916 
917   NicControllerHandle = NetLibGetNicHandle (ControllerHandle, ProtocolGuid);
918   if (NicControllerHandle == NULL) {
919     return EFI_UNSUPPORTED;
920   }
921 
922   Status = gBS->OpenProtocol (
923                   ControllerHandle,
924                   (EFI_GUID *) ProtocolGuid,
925                   &ManagedInterface,
926                   DriverBindingHandle,
927                   NicControllerHandle,
928                   EFI_OPEN_PROTOCOL_BY_DRIVER
929                   );
930   if (!EFI_ERROR (Status)) {
931     gBS->CloseProtocol (
932            ControllerHandle,
933            (EFI_GUID *) ProtocolGuid,
934            DriverBindingHandle,
935            NicControllerHandle
936            );
937     return EFI_UNSUPPORTED;
938   }
939 
940   if (Status != EFI_ALREADY_STARTED) {
941     return EFI_UNSUPPORTED;
942   }
943 
944   return EFI_SUCCESS;
945 }
946