]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/iScsi/IScsiMisc.c
UEFI HII: Merge UEFI HII support changes from branch.
[mirror_edk2.git] / MdeModulePkg / Universal / iScsi / IScsiMisc.c
1 /*++
2
3 Copyright (c) 2007 Intel Corporation. All rights reserved
4 This software and associated documentation (if any) is furnished
5 under a license and may only be used or copied in accordance
6 with the terms of the license. Except as permitted by such
7 license, no part of this software or documentation may be
8 reproduced, stored in a retrieval system, or transmitted in any
9 form or by any means without the express written consent of
10 Intel Corporation.
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 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
200 NetZeroMem (Lun, 8);
201 NetZeroMem (LunUnitStr, sizeof (LunUnitStr));
202
203 Index = 0;
204 LunUnitStr[0] = Str;
205
206 if (!IsHexDigit (&Digit, *Str)) {
207 return EFI_INVALID_PARAMETER;
208 }
209
210 while (*Str != '\0') {
211 //
212 // Legal representations of LUN:
213 // 4752-3A4F-6b7e-2F99,
214 // 6734-9-156f-127,
215 // 4186-9
216 //
217 if (*Str == '-') {
218 *Str = '\0';
219 Index++;
220
221 if (*(Str + 1) != '\0') {
222 if (!IsHexDigit (&Digit, *(Str + 1))) {
223 return EFI_INVALID_PARAMETER;
224 }
225
226 LunUnitStr[Index] = Str + 1;
227 }
228 } else if (!IsHexDigit (&Digit, *Str)) {
229 return EFI_INVALID_PARAMETER;
230 }
231
232 Str++;
233 }
234
235 for (Index = 0; (Index < 4) && (LunUnitStr[Index] != NULL); Index++) {
236 if (AsciiStrLen (LunUnitStr[Index]) > 4) {
237 return EFI_INVALID_PARAMETER;
238 }
239
240 *((UINT16 *) &Lun[Index * 2]) = HTONS (AsciiStrHexToUintn (LunUnitStr[Index]));
241 }
242
243 return EFI_SUCCESS;
244 }
245
246 VOID
247 IScsiLunToUnicodeStr (
248 IN UINT8 *Lun,
249 OUT CHAR16 *Str
250 )
251 /*++
252
253 Routine Description:
254
255 Convert the 64-bit LUN into the hexadecimal encoded LUN string.
256
257 Arguments:
258
259 Lun - The 64-bit LUN.
260 Str - The storage to return the hexadecimal encoded LUN string.
261
262 Returns:
263
264 None.
265
266 --*/
267 {
268 UINTN Index;
269 CHAR16 *TempStr;
270
271 TempStr = Str;
272
273 for (Index = 0; Index < 4; Index++) {
274
275 if ((Lun[2 * Index] | Lun[2 * Index + 1]) == 0) {
276 StrCpy (TempStr, L"0-");
277 } else {
278 TempStr[0] = (CHAR16) IScsiHexString[Lun[2 * Index] >> 4];
279 TempStr[1] = (CHAR16) IScsiHexString[Lun[2 * Index] & 0xf];
280 TempStr[2] = (CHAR16) IScsiHexString[Lun[2 * Index + 1] >> 4];
281 TempStr[3] = (CHAR16) IScsiHexString[Lun[2 * Index + 1] & 0xf];
282 TempStr[4] = L'-';
283 TempStr[5] = 0;
284
285 StrTrim (TempStr, L'0');
286 }
287
288 TempStr += StrLen (TempStr);
289 }
290
291 Str[StrLen (Str) - 1] = 0;
292
293 for (Index = StrLen (Str) - 1; Index > 1; Index = Index - 2) {
294 if ((Str[Index] == L'0') && (Str[Index - 1] == L'-')) {
295 Str[Index - 1] = 0;
296 } else {
297 break;
298 }
299 }
300 }
301
302 CHAR16 *
303 IScsiAsciiStrToUnicodeStr (
304 IN CHAR8 *Source,
305 OUT CHAR16 *Destination
306 )
307 /*++
308
309 Routine Description:
310
311 Convert the ASCII string into a UNICODE string.
312
313 Arguments:
314
315 Source - The ASCII string.
316 Destination - The storage to return the UNICODE string.
317
318 Returns:
319
320 Pointer to the UNICODE string.
321
322 --*/
323 {
324 ASSERT (Destination != NULL);
325 ASSERT (Source != NULL);
326
327 while (*Source != '\0') {
328 *(Destination++) = (CHAR16) *(Source++);
329 }
330
331 *Destination = '\0';
332
333 return Destination;
334 }
335
336 CHAR8 *
337 IScsiUnicodeStrToAsciiStr (
338 IN CHAR16 *Source,
339 OUT CHAR8 *Destination
340 )
341 /*++
342
343 Routine Description:
344
345 Convert the UNICODE string into an ASCII string.
346
347 Arguments:
348
349 Source - The UNICODE string.
350 Destination - The storage to return the ASCII string.
351
352 Returns:
353
354 Pointer to the ASCII string.
355
356 --*/
357 {
358 ASSERT (Destination != NULL);
359 ASSERT (Source != NULL);
360
361 while (*Source != '\0') {
362 //
363 // If any Unicode characters in Source contain
364 // non-zero value in the upper 8 bits, then ASSERT().
365 //
366 ASSERT (*Source < 0x100);
367 *(Destination++) = (CHAR8) *(Source++);
368 }
369
370 *Destination = '\0';
371
372 return Destination;
373 }
374
375 EFI_STATUS
376 IScsiAsciiStrToIp (
377 IN CHAR8 *Str,
378 OUT EFI_IPv4_ADDRESS *Ip
379 )
380 /*++
381
382 Routine Description:
383
384 Convert the decimal dotted IPv4 address into the binary IPv4 address.
385
386 Arguments:
387
388 Str - The UNICODE string.
389 Ip - The storage to return the ASCII string.
390
391 Returns:
392
393 EFI_SUCCESS - The binary IP address is returned in Ip.
394 EFI_INVALID_PARAMETER - The IP string is malformatted.
395
396 --*/
397 {
398 UINTN Index;
399 UINTN Number;
400
401 Index = 0;
402
403 while (*Str) {
404
405 if (Index > 3) {
406 return EFI_INVALID_PARAMETER;
407 }
408
409 Number = 0;
410 while (NET_IS_DIGIT (*Str)) {
411 Number = Number * 10 + (*Str - '0');
412 Str++;
413 }
414
415 if (Number > 0xFF) {
416 return EFI_INVALID_PARAMETER;
417 }
418
419 Ip->Addr[Index] = (UINT8) Number;
420
421 if ((*Str != '\0') && (*Str != '.')) {
422 //
423 // The current character should be either the NULL terminator or
424 // the dot delimiter.
425 //
426 return EFI_INVALID_PARAMETER;
427 }
428
429 if (*Str == '.') {
430 //
431 // Skip the delimiter.
432 //
433 Str++;
434 }
435
436 Index++;
437 }
438
439 if (Index != 4) {
440 return EFI_INVALID_PARAMETER;
441 }
442
443 return EFI_SUCCESS;
444 }
445
446 VOID
447 IScsiMacAddrToStr (
448 IN EFI_MAC_ADDRESS *Mac,
449 IN UINT32 Len,
450 OUT CHAR16 *Str
451 )
452 /*++
453
454 Routine Description:
455
456 Convert the mac address into a hexadecimal encoded "-" seperated string.
457
458 Arguments:
459
460 Mac - The mac address.
461 Len - Length in bytes of the mac address.
462 Str - The storage to return the mac string.
463
464 Returns:
465
466 None.
467
468 --*/
469 {
470 UINT32 Index;
471
472 for (Index = 0; Index < Len; Index++) {
473 Str[3 * Index] = NibbleToHexChar (Mac->Addr[Index] >> 4);
474 Str[3 * Index + 1] = NibbleToHexChar (Mac->Addr[Index]);
475 Str[3 * Index + 2] = L'-';
476 }
477
478 Str[3 * Index - 1] = L'\0';
479 }
480
481 EFI_STATUS
482 IScsiBinToHex (
483 IN UINT8 *BinBuffer,
484 IN UINT32 BinLength,
485 IN OUT CHAR8 *HexStr,
486 IN OUT UINT32 *HexLength
487 )
488 /*++
489
490 Routine Description:
491
492 Convert the binary encoded buffer into a hexadecimal encoded string.
493
494 Arguments:
495
496 BinBuffer - The buffer containing the binary data.
497 BinLength - Length of the binary buffer.
498 HexStr - Pointer to the string.
499 HexLength - The length of the string.
500
501 Returns:
502
503 EFI_SUCCESS - The binary data is converted to the hexadecimal string
504 and the length of the string is updated.
505 EFI_BUFFER_TOO_SMALL - The string is too small.
506
507 --*/
508 {
509 UINTN Index;
510
511 if ((HexStr == NULL) || (BinBuffer == NULL) || (BinLength == 0)) {
512 return EFI_INVALID_PARAMETER;
513 }
514
515 if (((*HexLength) - 3) < BinLength * 2) {
516 *HexLength = BinLength * 2 + 3;
517 return EFI_BUFFER_TOO_SMALL;
518 }
519
520 *HexLength = BinLength * 2 + 3;
521 //
522 // Prefix for Hex String
523 //
524 HexStr[0] = '0';
525 HexStr[1] = 'x';
526
527 for (Index = 0; Index < BinLength; Index++) {
528 HexStr[Index * 2 + 2] = IScsiHexString[BinBuffer[Index] >> 4];
529 HexStr[Index * 2 + 3] = IScsiHexString[BinBuffer[Index] & 0xf];
530 }
531
532 HexStr[Index * 2 + 2] = '\0';
533
534 return EFI_SUCCESS;
535 }
536
537 EFI_STATUS
538 IScsiHexToBin (
539 IN OUT UINT8 *BinBuffer,
540 IN OUT UINT32 *BinLength,
541 IN CHAR8 *HexStr
542 )
543 /*++
544
545 Routine Description:
546
547 Convert the hexadecimal string into a binary encoded buffer.
548
549 Arguments:
550
551 BinBuffer - The binary buffer.
552 BinLength - Length of the binary buffer.
553 HexStr - The hexadecimal string.
554
555 Returns:
556
557 EFI_SUCCESS - The hexadecimal string is converted into a binary
558 encoded buffer.
559 EFI_BUFFER_TOO_SMALL - The binary buffer is too small to hold the converted data.s
560
561 --*/
562 {
563 UINTN Index;
564 UINT32 HexCount;
565 CHAR8 *HexBuf;
566 UINT8 Digit;
567 UINT8 Byte;
568
569 //
570 // Find out how many hex characters the string has.
571 //
572 HexBuf = HexStr;
573 if ((HexBuf[0] == '0') && ((HexBuf[1] == 'x') || (HexBuf[1] == 'X'))) {
574 HexBuf += 2;
575 }
576
577 for (Index = 0, HexCount = 0; IsHexDigit (&Digit, HexBuf[Index]); Index++, HexCount++)
578 ;
579
580 if (HexCount == 0) {
581 *BinLength = 0;
582 return EFI_SUCCESS;
583 }
584 //
585 // Test if buffer is passed enough.
586 //
587 if (((HexCount + 1) / 2) > *BinLength) {
588 *BinLength = (HexCount + 1) / 2;
589 return EFI_BUFFER_TOO_SMALL;
590 }
591
592 *BinLength = (HexCount + 1) / 2;
593
594 for (Index = 0; Index < HexCount; Index++) {
595
596 IsHexDigit (&Digit, HexBuf[HexCount - 1 - Index]);
597
598 if ((Index & 1) == 0) {
599 Byte = Digit;
600 } else {
601 Byte = BinBuffer[*BinLength - 1 - Index / 2];
602 Byte &= 0x0F;
603 Byte |= Digit << 4;
604 }
605
606 BinBuffer[*BinLength - 1 - Index / 2] = Byte;
607 }
608
609 return EFI_SUCCESS;
610 }
611
612 VOID
613 IScsiGenRandom (
614 IN OUT UINT8 *Rand,
615 IN UINTN RandLength
616 )
617 /*++
618
619 Routine Description:
620
621 Generate random numbers.
622
623 Arguments:
624
625 Rand - The buffer to contain random numbers.
626 RandLength - The length of the Rand buffer.
627
628 Returns:
629
630 None.
631
632 --*/
633 {
634 UINT32 Random;
635
636 while (RandLength > 0) {
637 Random = NET_RANDOM (NetRandomInitSeed ());
638 *Rand++ = (UINT8) (Random);
639 RandLength--;
640 }
641 }
642
643 ISCSI_DRIVER_DATA *
644 IScsiCreateDriverData (
645 IN EFI_HANDLE Image,
646 IN EFI_HANDLE Controller
647 )
648 /*++
649
650 Routine Description:
651
652 Create the iSCSI driver data..
653
654 Arguments:
655
656 Image - The handle of the driver image.
657 Controller - The handle of the controller.
658
659 Returns:
660
661 The iSCSI driver data created.
662
663 --*/
664 {
665 ISCSI_DRIVER_DATA *Private;
666 EFI_STATUS Status;
667
668 Private = NetAllocateZeroPool (sizeof (ISCSI_DRIVER_DATA));
669 if (Private == NULL) {
670 return NULL;
671 }
672
673 Private->Signature = ISCSI_DRIVER_DATA_SIGNATURE;
674 Private->Image = Image;
675 Private->Controller = Controller;
676
677 //
678 // Create an event to be signal when the BS to RT transition is triggerd so
679 // as to abort the iSCSI session.
680 //
681 Status = gBS->CreateEvent (
682 EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES,
683 TPL_CALLBACK,
684 IScsiOnExitBootService,
685 Private,
686 &Private->ExitBootServiceEvent
687 );
688 if (EFI_ERROR (Status)) {
689 NetFreePool (Private);
690 return NULL;
691 }
692
693 NetCopyMem(&Private->IScsiExtScsiPassThru, &gIScsiExtScsiPassThruProtocolTemplate, sizeof(EFI_EXT_SCSI_PASS_THRU_PROTOCOL));
694
695 //
696 // 0 is designated to the TargetId, so use another value for the AdapterId.
697 //
698 Private->ExtScsiPassThruMode.AdapterId = 2;
699 Private->ExtScsiPassThruMode.Attributes = EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;
700 Private->ExtScsiPassThruMode.IoAlign = 4;
701 Private->IScsiExtScsiPassThru.Mode = &Private->ExtScsiPassThruMode;
702
703 //
704 // Install the Ext SCSI PASS THRU protocol.
705 //
706 Status = gBS->InstallProtocolInterface (
707 &Private->ExtScsiPassThruHandle,
708 &gEfiExtScsiPassThruProtocolGuid,
709 EFI_NATIVE_INTERFACE,
710 &Private->IScsiExtScsiPassThru
711 );
712 if (EFI_ERROR (Status)) {
713 gBS->CloseEvent (Private->ExitBootServiceEvent);
714 NetFreePool (Private);
715
716 return NULL;
717 }
718
719 IScsiSessionInit (&Private->Session, FALSE);
720
721 return Private;
722 }
723
724 VOID
725 IScsiCleanDriverData (
726 IN ISCSI_DRIVER_DATA *Private
727 )
728 /*++
729
730 Routine Description:
731
732 Clean the iSCSI driver data.
733
734 Arguments:
735
736 Private - The iSCSI driver data.
737
738 Returns:
739
740 None.
741
742 --*/
743 {
744 if (Private->DevicePath != NULL) {
745 gBS->UninstallProtocolInterface (
746 Private->ExtScsiPassThruHandle,
747 &gEfiDevicePathProtocolGuid,
748 Private->DevicePath
749 );
750
751 NetFreePool (Private->DevicePath);
752 }
753
754 if (Private->ExtScsiPassThruHandle != NULL) {
755 gBS->UninstallProtocolInterface (
756 Private->ExtScsiPassThruHandle,
757 &gEfiExtScsiPassThruProtocolGuid,
758 &Private->IScsiExtScsiPassThru
759 );
760 }
761
762 gBS->CloseEvent (Private->ExitBootServiceEvent);
763
764 NetFreePool (Private);
765 }
766
767 EFI_STATUS
768 IScsiGetConfigData (
769 IN ISCSI_DRIVER_DATA *Private
770 )
771 /*++
772
773 Routine Description:
774
775 Get the various configuration data of this iSCSI instance.
776
777 Arguments:
778
779 Private - The iSCSI driver data.
780
781 Returns:
782
783 EFI_SUCCESS - The configuration of this instance is got.
784 EFI_NOT_FOUND - This iSCSI instance is not configured yet.
785
786 --*/
787 {
788 EFI_STATUS Status;
789 ISCSI_SESSION *Session;
790 UINTN BufferSize;
791 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
792 EFI_SIMPLE_NETWORK_MODE *Mode;
793 CHAR16 MacString[65];
794
795 //
796 // get the iSCSI Initiator Name
797 //
798 Session = &Private->Session;
799 Session->InitiatorNameLength = ISCSI_NAME_MAX_SIZE;
800 Status = gIScsiInitiatorName.Get (
801 &gIScsiInitiatorName,
802 &Session->InitiatorNameLength,
803 Session->InitiatorName
804 );
805 if (EFI_ERROR (Status)) {
806 return Status;
807 }
808
809 Status = gBS->HandleProtocol (
810 Private->Controller,
811 &gEfiSimpleNetworkProtocolGuid,
812 &Snp
813 );
814 if (EFI_ERROR (Status)) {
815 return Status;
816 }
817
818 Mode = Snp->Mode;
819
820 //
821 // Get the mac string, it's the name of various variable
822 //
823 IScsiMacAddrToStr (&Mode->PermanentAddress, Mode->HwAddressSize, MacString);
824
825 //
826 // Get the normal configuration.
827 //
828 BufferSize = sizeof (Session->ConfigData.NvData);
829 Status = gRT->GetVariable (
830 MacString,
831 &gEfiIScsiInitiatorNameProtocolGuid,
832 NULL,
833 &BufferSize,
834 &Session->ConfigData.NvData
835 );
836 if (EFI_ERROR (Status)) {
837 return Status;
838 }
839
840 if (!Session->ConfigData.NvData.Enabled) {
841 return EFI_ABORTED;
842 }
843 //
844 // Get the CHAP Auth information.
845 //
846 BufferSize = sizeof (Session->AuthData.AuthConfig);
847 Status = gRT->GetVariable (
848 MacString,
849 &mIScsiCHAPAuthInfoGuid,
850 NULL,
851 &BufferSize,
852 &Session->AuthData.AuthConfig
853 );
854
855 if (!EFI_ERROR (Status) && Session->ConfigData.NvData.InitiatorInfoFromDhcp) {
856 //
857 // Start dhcp.
858 //
859 Status = IScsiDoDhcp (Private->Image, Private->Controller, &Session->ConfigData);
860 }
861
862 return Status;
863 }
864
865 EFI_DEVICE_PATH_PROTOCOL *
866 IScsiGetTcpConnDevicePath (
867 IN ISCSI_DRIVER_DATA *Private
868 )
869 /*++
870
871 Routine Description:
872
873 Get the device path of the iSCSI tcp connection and update it.
874
875 Arguments:
876
877 Private - The iSCSI driver data.
878
879 Returns:
880
881 The updated device path.
882
883 --*/
884 {
885 ISCSI_SESSION *Session;
886 ISCSI_CONNECTION *Conn;
887 TCP4_IO *Tcp4Io;
888 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
889 EFI_STATUS Status;
890 EFI_DEV_PATH *DPathNode;
891
892 Session = &Private->Session;
893 if (Session->State != SESSION_STATE_LOGGED_IN) {
894 return NULL;
895 }
896
897 Conn = NET_LIST_USER_STRUCT_S (
898 Session->Conns.ForwardLink,
899 ISCSI_CONNECTION,
900 Link,
901 ISCSI_CONNECTION_SIGNATURE
902 );
903 Tcp4Io = &Conn->Tcp4Io;
904
905 Status = gBS->HandleProtocol (
906 Tcp4Io->Handle,
907 &gEfiDevicePathProtocolGuid,
908 &DevicePath
909 );
910 if (EFI_ERROR (Status)) {
911 return NULL;
912 }
913 //
914 // Duplicate it.
915 //
916 DevicePath = DuplicateDevicePath (DevicePath);
917
918 DPathNode = (EFI_DEV_PATH *) DevicePath;
919
920 while (!IsDevicePathEnd (&DPathNode->DevPath)) {
921 if ((DevicePathType (&DPathNode->DevPath) == MESSAGING_DEVICE_PATH) &&
922 (DevicePathSubType (&DPathNode->DevPath) == MSG_IPv4_DP)
923 ) {
924
925 DPathNode->Ipv4.LocalPort = 0;
926 DPathNode->Ipv4.StaticIpAddress = !Session->ConfigData.NvData.InitiatorInfoFromDhcp;
927 break;
928 }
929
930 DPathNode = (EFI_DEV_PATH *) NextDevicePathNode (&DPathNode->DevPath);
931 }
932
933 return DevicePath;
934 }
935
936 VOID
937 EFIAPI
938 IScsiOnExitBootService (
939 IN EFI_EVENT Event,
940 IN VOID *Context
941 )
942 /*++
943
944 Routine Description:
945
946 Abort the session when the transition from BS to RT is initiated.
947
948 Arguments:
949
950 Event - The event signaled.
951 Context - The iSCSI driver data.
952
953 Returns:
954
955 None.
956
957 --*/
958 {
959 ISCSI_DRIVER_DATA *Private;
960
961 Private = (ISCSI_DRIVER_DATA *) Context;
962 gBS->CloseEvent (Private->ExitBootServiceEvent);
963
964 IScsiSessionAbort (&Private->Session);
965 }