]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/IScsiDxe/IScsiMisc.c
8dee904babc48f20542da405096c5b6212c4e1f6
[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 NetZeroMem (Lun, 8);
202 NetZeroMem (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 //
572 // Find out how many hex characters the string has.
573 //
574 HexBuf = HexStr;
575 if ((HexBuf[0] == '0') && ((HexBuf[1] == 'x') || (HexBuf[1] == 'X'))) {
576 HexBuf += 2;
577 }
578
579 for (Index = 0, HexCount = 0; IsHexDigit (&Digit, HexBuf[Index]); Index++, HexCount++)
580 ;
581
582 if (HexCount == 0) {
583 *BinLength = 0;
584 return EFI_SUCCESS;
585 }
586 //
587 // Test if buffer is passed enough.
588 //
589 if (((HexCount + 1) / 2) > *BinLength) {
590 *BinLength = (HexCount + 1) / 2;
591 return EFI_BUFFER_TOO_SMALL;
592 }
593
594 *BinLength = (HexCount + 1) / 2;
595
596 for (Index = 0; Index < HexCount; Index++) {
597
598 IsHexDigit (&Digit, HexBuf[HexCount - 1 - Index]);
599
600 if ((Index & 1) == 0) {
601 Byte = Digit;
602 } else {
603 Byte = BinBuffer[*BinLength - 1 - Index / 2];
604 Byte &= 0x0F;
605 Byte = (UINT8) (Byte | (Digit << 4));
606 }
607
608 BinBuffer[*BinLength - 1 - Index / 2] = Byte;
609 }
610
611 return EFI_SUCCESS;
612 }
613
614 VOID
615 IScsiGenRandom (
616 IN OUT UINT8 *Rand,
617 IN UINTN RandLength
618 )
619 /*++
620
621 Routine Description:
622
623 Generate random numbers.
624
625 Arguments:
626
627 Rand - The buffer to contain random numbers.
628 RandLength - The length of the Rand buffer.
629
630 Returns:
631
632 None.
633
634 --*/
635 {
636 UINT32 Random;
637
638 while (RandLength > 0) {
639 Random = NET_RANDOM (NetRandomInitSeed ());
640 *Rand++ = (UINT8) (Random);
641 RandLength--;
642 }
643 }
644
645 ISCSI_DRIVER_DATA *
646 IScsiCreateDriverData (
647 IN EFI_HANDLE Image,
648 IN EFI_HANDLE Controller
649 )
650 /*++
651
652 Routine Description:
653
654 Create the iSCSI driver data..
655
656 Arguments:
657
658 Image - The handle of the driver image.
659 Controller - The handle of the controller.
660
661 Returns:
662
663 The iSCSI driver data created.
664
665 --*/
666 {
667 ISCSI_DRIVER_DATA *Private;
668 EFI_STATUS Status;
669
670 Private = NetAllocateZeroPool (sizeof (ISCSI_DRIVER_DATA));
671 if (Private == NULL) {
672 return NULL;
673 }
674
675 Private->Signature = ISCSI_DRIVER_DATA_SIGNATURE;
676 Private->Image = Image;
677 Private->Controller = Controller;
678
679 //
680 // Create an event to be signal when the BS to RT transition is triggerd so
681 // as to abort the iSCSI session.
682 //
683 Status = gBS->CreateEvent (
684 EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES,
685 TPL_CALLBACK,
686 IScsiOnExitBootService,
687 Private,
688 &Private->ExitBootServiceEvent
689 );
690 if (EFI_ERROR (Status)) {
691 NetFreePool (Private);
692 return NULL;
693 }
694
695 NetCopyMem(&Private->IScsiExtScsiPassThru, &gIScsiExtScsiPassThruProtocolTemplate, sizeof(EFI_EXT_SCSI_PASS_THRU_PROTOCOL));
696
697 //
698 // 0 is designated to the TargetId, so use another value for the AdapterId.
699 //
700 Private->ExtScsiPassThruMode.AdapterId = 2;
701 Private->ExtScsiPassThruMode.Attributes = EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;
702 Private->ExtScsiPassThruMode.IoAlign = 4;
703 Private->IScsiExtScsiPassThru.Mode = &Private->ExtScsiPassThruMode;
704
705 //
706 // Install the Ext SCSI PASS THRU protocol.
707 //
708 Status = gBS->InstallProtocolInterface (
709 &Private->ExtScsiPassThruHandle,
710 &gEfiExtScsiPassThruProtocolGuid,
711 EFI_NATIVE_INTERFACE,
712 &Private->IScsiExtScsiPassThru
713 );
714 if (EFI_ERROR (Status)) {
715 gBS->CloseEvent (Private->ExitBootServiceEvent);
716 NetFreePool (Private);
717
718 return NULL;
719 }
720
721 IScsiSessionInit (&Private->Session, FALSE);
722
723 return Private;
724 }
725
726 VOID
727 IScsiCleanDriverData (
728 IN ISCSI_DRIVER_DATA *Private
729 )
730 /*++
731
732 Routine Description:
733
734 Clean the iSCSI driver data.
735
736 Arguments:
737
738 Private - The iSCSI driver data.
739
740 Returns:
741
742 None.
743
744 --*/
745 {
746 if (Private->DevicePath != NULL) {
747 gBS->UninstallProtocolInterface (
748 Private->ExtScsiPassThruHandle,
749 &gEfiDevicePathProtocolGuid,
750 Private->DevicePath
751 );
752
753 NetFreePool (Private->DevicePath);
754 }
755
756 if (Private->ExtScsiPassThruHandle != NULL) {
757 gBS->UninstallProtocolInterface (
758 Private->ExtScsiPassThruHandle,
759 &gEfiExtScsiPassThruProtocolGuid,
760 &Private->IScsiExtScsiPassThru
761 );
762 }
763
764 gBS->CloseEvent (Private->ExitBootServiceEvent);
765
766 NetFreePool (Private);
767 }
768
769 EFI_STATUS
770 IScsiGetConfigData (
771 IN ISCSI_DRIVER_DATA *Private
772 )
773 /*++
774
775 Routine Description:
776
777 Get the various configuration data of this iSCSI instance.
778
779 Arguments:
780
781 Private - The iSCSI driver data.
782
783 Returns:
784
785 EFI_SUCCESS - The configuration of this instance is got.
786 EFI_NOT_FOUND - This iSCSI instance is not configured yet.
787
788 --*/
789 {
790 EFI_STATUS Status;
791 ISCSI_SESSION *Session;
792 UINTN BufferSize;
793 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
794 EFI_SIMPLE_NETWORK_MODE *Mode;
795 CHAR16 MacString[65];
796
797 //
798 // get the iSCSI Initiator Name
799 //
800 Session = &Private->Session;
801 Session->InitiatorNameLength = ISCSI_NAME_MAX_SIZE;
802 Status = gIScsiInitiatorName.Get (
803 &gIScsiInitiatorName,
804 &Session->InitiatorNameLength,
805 Session->InitiatorName
806 );
807 if (EFI_ERROR (Status)) {
808 return Status;
809 }
810
811 Status = gBS->HandleProtocol (
812 Private->Controller,
813 &gEfiSimpleNetworkProtocolGuid,
814 (VOID **)&Snp
815 );
816 if (EFI_ERROR (Status)) {
817 return Status;
818 }
819
820 Mode = Snp->Mode;
821
822 //
823 // Get the mac string, it's the name of various variable
824 //
825 IScsiMacAddrToStr (&Mode->PermanentAddress, Mode->HwAddressSize, MacString);
826
827 //
828 // Get the normal configuration.
829 //
830 BufferSize = sizeof (Session->ConfigData.NvData);
831 Status = gRT->GetVariable (
832 MacString,
833 &gEfiIScsiInitiatorNameProtocolGuid,
834 NULL,
835 &BufferSize,
836 &Session->ConfigData.NvData
837 );
838 if (EFI_ERROR (Status)) {
839 return Status;
840 }
841
842 if (!Session->ConfigData.NvData.Enabled) {
843 return EFI_ABORTED;
844 }
845 //
846 // Get the CHAP Auth information.
847 //
848 BufferSize = sizeof (Session->AuthData.AuthConfig);
849 Status = gRT->GetVariable (
850 MacString,
851 &mIScsiCHAPAuthInfoGuid,
852 NULL,
853 &BufferSize,
854 &Session->AuthData.AuthConfig
855 );
856
857 if (!EFI_ERROR (Status) && Session->ConfigData.NvData.InitiatorInfoFromDhcp) {
858 //
859 // Start dhcp.
860 //
861 Status = IScsiDoDhcp (Private->Image, Private->Controller, &Session->ConfigData);
862 }
863
864 return Status;
865 }
866
867 EFI_DEVICE_PATH_PROTOCOL *
868 IScsiGetTcpConnDevicePath (
869 IN ISCSI_DRIVER_DATA *Private
870 )
871 /*++
872
873 Routine Description:
874
875 Get the device path of the iSCSI tcp connection and update it.
876
877 Arguments:
878
879 Private - The iSCSI driver data.
880
881 Returns:
882
883 The updated device path.
884
885 --*/
886 {
887 ISCSI_SESSION *Session;
888 ISCSI_CONNECTION *Conn;
889 TCP4_IO *Tcp4Io;
890 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
891 EFI_STATUS Status;
892 EFI_DEV_PATH *DPathNode;
893
894 Session = &Private->Session;
895 if (Session->State != SESSION_STATE_LOGGED_IN) {
896 return NULL;
897 }
898
899 Conn = NET_LIST_USER_STRUCT_S (
900 Session->Conns.ForwardLink,
901 ISCSI_CONNECTION,
902 Link,
903 ISCSI_CONNECTION_SIGNATURE
904 );
905 Tcp4Io = &Conn->Tcp4Io;
906
907 Status = gBS->HandleProtocol (
908 Tcp4Io->Handle,
909 &gEfiDevicePathProtocolGuid,
910 (VOID **)&DevicePath
911 );
912 if (EFI_ERROR (Status)) {
913 return NULL;
914 }
915 //
916 // Duplicate it.
917 //
918 DevicePath = DuplicateDevicePath (DevicePath);
919
920 DPathNode = (EFI_DEV_PATH *) DevicePath;
921
922 while (!IsDevicePathEnd (&DPathNode->DevPath)) {
923 if ((DevicePathType (&DPathNode->DevPath) == MESSAGING_DEVICE_PATH) &&
924 (DevicePathSubType (&DPathNode->DevPath) == MSG_IPv4_DP)
925 ) {
926
927 DPathNode->Ipv4.LocalPort = 0;
928 DPathNode->Ipv4.StaticIpAddress = (BOOLEAN) (!Session->ConfigData.NvData.InitiatorInfoFromDhcp);
929 break;
930 }
931
932 DPathNode = (EFI_DEV_PATH *) NextDevicePathNode (&DPathNode->DevPath);
933 }
934
935 return DevicePath;
936 }
937
938 VOID
939 EFIAPI
940 IScsiOnExitBootService (
941 IN EFI_EVENT Event,
942 IN VOID *Context
943 )
944 /*++
945
946 Routine Description:
947
948 Abort the session when the transition from BS to RT is initiated.
949
950 Arguments:
951
952 Event - The event signaled.
953 Context - The iSCSI driver data.
954
955 Returns:
956
957 None.
958
959 --*/
960 {
961 ISCSI_DRIVER_DATA *Private;
962
963 Private = (ISCSI_DRIVER_DATA *) Context;
964 gBS->CloseEvent (Private->ExitBootServiceEvent);
965
966 IScsiSessionAbort (&Private->Session);
967 }