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