]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/IScsiDxe/IScsiMisc.c
Fix a K9 error.Result of GetVariable2() function that may return NULL will be derefer...
[mirror_edk2.git] / MdeModulePkg / Universal / Network / IScsiDxe / IScsiMisc.c
1 /** @file
2 Miscellaneous routines for iSCSI driver.
3
4 Copyright (c) 2004 - 2013, 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
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
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
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
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 Str[StrLen (Str) - 1] = 0;
223
224 for (Index = StrLen (Str) - 1; Index > 1; Index = Index - 2) {
225 if ((Str[Index] == L'0') && (Str[Index - 1] == L'-')) {
226 Str[Index - 1] = 0;
227 } else {
228 break;
229 }
230 }
231 }
232
233 /**
234 Convert the ASCII string into a UNICODE string.
235
236 @param[in] Source The ASCII string.
237 @param[out] Destination The storage to return the UNICODE string.
238
239 @return CHAR16 * Pointer to the UNICODE string.
240 **/
241 CHAR16 *
242 IScsiAsciiStrToUnicodeStr (
243 IN CHAR8 *Source,
244 OUT CHAR16 *Destination
245 )
246 {
247 ASSERT (Destination != NULL);
248 ASSERT (Source != NULL);
249
250 while (*Source != '\0') {
251 *(Destination++) = (CHAR16) *(Source++);
252 }
253
254 *Destination = '\0';
255
256 return Destination;
257 }
258
259 /**
260 Convert the UNICODE string into an ASCII string.
261
262 @param[in] Source The UNICODE string.
263 @param[out] Destination The storage to return the ASCII string.
264
265 @return CHAR8 * Pointer to the ASCII string.
266 **/
267 CHAR8 *
268 IScsiUnicodeStrToAsciiStr (
269 IN CHAR16 *Source,
270 OUT CHAR8 *Destination
271 )
272 {
273 ASSERT (Destination != NULL);
274 ASSERT (Source != NULL);
275
276 while (*Source != '\0') {
277 //
278 // If any Unicode characters in Source contain
279 // non-zero value in the upper 8 bits, then ASSERT().
280 //
281 ASSERT (*Source < 0x100);
282 *(Destination++) = (CHAR8) *(Source++);
283 }
284
285 *Destination = '\0';
286
287 return Destination;
288 }
289
290 /**
291 Convert the decimal dotted IPv4 address into the binary IPv4 address.
292
293 @param[in] Str The UNICODE string.
294 @param[out] Ip The storage to return the ASCII string.
295
296 @retval EFI_SUCCESS The binary IP address is returned in Ip.
297 @retval EFI_INVALID_PARAMETER The IP string is malformatted.
298 **/
299 EFI_STATUS
300 IScsiAsciiStrToIp (
301 IN CHAR8 *Str,
302 OUT EFI_IPv4_ADDRESS *Ip
303 )
304 {
305 UINTN Index;
306 UINTN Number;
307
308 Index = 0;
309
310 while (*Str != 0) {
311
312 if (Index > 3) {
313 return EFI_INVALID_PARAMETER;
314 }
315
316 Number = 0;
317 while (NET_IS_DIGIT (*Str)) {
318 Number = Number * 10 + (*Str - '0');
319 Str++;
320 }
321
322 if (Number > 0xFF) {
323 return EFI_INVALID_PARAMETER;
324 }
325
326 Ip->Addr[Index] = (UINT8) Number;
327
328 if ((*Str != '\0') && (*Str != '.')) {
329 //
330 // The current character should be either the NULL terminator or
331 // the dot delimiter.
332 //
333 return EFI_INVALID_PARAMETER;
334 }
335
336 if (*Str == '.') {
337 //
338 // Skip the delimiter.
339 //
340 Str++;
341 }
342
343 Index++;
344 }
345
346 if (Index != 4) {
347 return EFI_INVALID_PARAMETER;
348 }
349
350 return EFI_SUCCESS;
351 }
352
353 /**
354 Convert the mac address into a hexadecimal encoded "-" seperated string.
355
356 @param[in] Mac The mac address.
357 @param[in] Len Length in bytes of the mac address.
358 @param[in] VlanId VLAN ID of the network device.
359 @param[out] Str The storage to return the mac string.
360 **/
361 VOID
362 IScsiMacAddrToStr (
363 IN EFI_MAC_ADDRESS *Mac,
364 IN UINT32 Len,
365 IN UINT16 VlanId,
366 OUT CHAR16 *Str
367 )
368 {
369 UINT32 Index;
370 CHAR16 *String;
371
372 for (Index = 0; Index < Len; Index++) {
373 Str[3 * Index] = (CHAR16) IScsiHexString[(Mac->Addr[Index] >> 4) & 0x0F];
374 Str[3 * Index + 1] = (CHAR16) IScsiHexString[Mac->Addr[Index] & 0x0F];
375 Str[3 * Index + 2] = L'-';
376 }
377
378 String = &Str[3 * Index - 1] ;
379 if (VlanId != 0) {
380 String += UnicodeSPrint (String, 6 * sizeof (CHAR16), L"\\%04x", (UINTN) VlanId);
381 }
382
383 *String = L'\0';
384 }
385
386 /**
387 Convert the binary encoded buffer into a hexadecimal encoded string.
388
389 @param[in] BinBuffer The buffer containing the binary data.
390 @param[in] BinLength Length of the binary buffer.
391 @param[in, out] HexStr Pointer to the string.
392 @param[in, out] HexLength The length of the string.
393
394 @retval EFI_SUCCESS The binary data is converted to the hexadecimal string
395 and the length of the string is updated.
396 @retval EFI_BUFFER_TOO_SMALL The string is too small.
397 @retval EFI_INVALID_PARAMETER The IP string is malformatted.
398 **/
399 EFI_STATUS
400 IScsiBinToHex (
401 IN UINT8 *BinBuffer,
402 IN UINT32 BinLength,
403 IN OUT CHAR8 *HexStr,
404 IN OUT UINT32 *HexLength
405 )
406 {
407 UINTN Index;
408
409 if ((HexStr == NULL) || (BinBuffer == NULL) || (BinLength == 0)) {
410 return EFI_INVALID_PARAMETER;
411 }
412
413 if (((*HexLength) - 3) < BinLength * 2) {
414 *HexLength = BinLength * 2 + 3;
415 return EFI_BUFFER_TOO_SMALL;
416 }
417
418 *HexLength = BinLength * 2 + 3;
419 //
420 // Prefix for Hex String
421 //
422 HexStr[0] = '0';
423 HexStr[1] = 'x';
424
425 for (Index = 0; Index < BinLength; Index++) {
426 HexStr[Index * 2 + 2] = IScsiHexString[BinBuffer[Index] >> 4];
427 HexStr[Index * 2 + 3] = IScsiHexString[BinBuffer[Index] & 0x0F];
428 }
429
430 HexStr[Index * 2 + 2] = '\0';
431
432 return EFI_SUCCESS;
433 }
434
435 /**
436 Convert the hexadecimal string into a binary encoded buffer.
437
438 @param[in, out] BinBuffer The binary buffer.
439 @param[in, out] BinLength Length of the binary buffer.
440 @param[in] HexStr The hexadecimal string.
441
442 @retval EFI_SUCCESS The hexadecimal string is converted into a binary
443 encoded buffer.
444 @retval EFI_BUFFER_TOO_SMALL The binary buffer is too small to hold the converted data.
445 **/
446 EFI_STATUS
447 IScsiHexToBin (
448 IN OUT UINT8 *BinBuffer,
449 IN OUT UINT32 *BinLength,
450 IN CHAR8 *HexStr
451 )
452 {
453 UINTN Index;
454 UINTN Length;
455 UINT8 Digit;
456 CHAR8 TemStr[2];
457
458 ZeroMem (TemStr, sizeof (TemStr));
459
460 //
461 // Find out how many hex characters the string has.
462 //
463 if ((HexStr[0] == '0') && ((HexStr[1] == 'x') || (HexStr[1] == 'X'))) {
464 HexStr += 2;
465 }
466
467 Length = AsciiStrLen (HexStr);
468
469 for (Index = 0; Index < Length; Index ++) {
470 TemStr[0] = HexStr[Index];
471 Digit = (UINT8) AsciiStrHexToUint64 (TemStr);
472 if (Digit == 0 && TemStr[0] != '0') {
473 //
474 // Invalid Lun Char
475 //
476 break;
477 }
478 if ((Index & 1) == 0) {
479 BinBuffer [Index/2] = Digit;
480 } else {
481 BinBuffer [Index/2] = (UINT8) ((BinBuffer [Index/2] << 4) + Digit);
482 }
483 }
484
485 *BinLength = (UINT32) ((Index + 1)/2);
486
487 return EFI_SUCCESS;
488 }
489
490 /**
491 Generate random numbers.
492
493 @param[in, out] Rand The buffer to contain random numbers.
494 @param[in] RandLength The length of the Rand buffer.
495 **/
496 VOID
497 IScsiGenRandom (
498 IN OUT UINT8 *Rand,
499 IN UINTN RandLength
500 )
501 {
502 UINT32 Random;
503
504 while (RandLength > 0) {
505 Random = NET_RANDOM (NetRandomInitSeed ());
506 *Rand++ = (UINT8) (Random);
507 RandLength--;
508 }
509 }
510
511 /**
512 Create the iSCSI driver data..
513
514 @param[in] Image The handle of the driver image.
515 @param[in] Controller The handle of the controller.
516
517 @return The iSCSI driver data created.
518 @retval NULL Other errors as indicated.
519 **/
520 ISCSI_DRIVER_DATA *
521 IScsiCreateDriverData (
522 IN EFI_HANDLE Image,
523 IN EFI_HANDLE Controller
524 )
525 {
526 ISCSI_DRIVER_DATA *Private;
527 EFI_STATUS Status;
528
529 Private = AllocateZeroPool (sizeof (ISCSI_DRIVER_DATA));
530 if (Private == NULL) {
531 return NULL;
532 }
533
534 Private->Signature = ISCSI_DRIVER_DATA_SIGNATURE;
535 Private->Image = Image;
536 Private->Controller = Controller;
537
538 //
539 // Create an event to be signal when the BS to RT transition is triggerd so
540 // as to abort the iSCSI session.
541 //
542 Status = gBS->CreateEventEx (
543 EVT_NOTIFY_SIGNAL,
544 TPL_CALLBACK,
545 IScsiOnExitBootService,
546 Private,
547 &gEfiEventExitBootServicesGuid,
548 &Private->ExitBootServiceEvent
549 );
550 if (EFI_ERROR (Status)) {
551 FreePool (Private);
552 return NULL;
553 }
554
555 CopyMem(&Private->IScsiExtScsiPassThru, &gIScsiExtScsiPassThruProtocolTemplate, sizeof(EFI_EXT_SCSI_PASS_THRU_PROTOCOL));
556
557 //
558 // 0 is designated to the TargetId, so use another value for the AdapterId.
559 //
560 Private->ExtScsiPassThruMode.AdapterId = 2;
561 Private->ExtScsiPassThruMode.Attributes = EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;
562 Private->ExtScsiPassThruMode.IoAlign = 4;
563 Private->IScsiExtScsiPassThru.Mode = &Private->ExtScsiPassThruMode;
564
565 //
566 // Install the Ext SCSI PASS THRU protocol.
567 //
568 Status = gBS->InstallProtocolInterface (
569 &Private->ExtScsiPassThruHandle,
570 &gEfiExtScsiPassThruProtocolGuid,
571 EFI_NATIVE_INTERFACE,
572 &Private->IScsiExtScsiPassThru
573 );
574 if (EFI_ERROR (Status)) {
575 gBS->CloseEvent (Private->ExitBootServiceEvent);
576 FreePool (Private);
577
578 return NULL;
579 }
580
581 IScsiSessionInit (&Private->Session, FALSE);
582
583 return Private;
584 }
585
586 /**
587 Clean the iSCSI driver data.
588
589 @param[in] Private The iSCSI driver data.
590 **/
591 VOID
592 IScsiCleanDriverData (
593 IN ISCSI_DRIVER_DATA *Private
594 )
595 {
596 if (Private->DevicePath != NULL) {
597 gBS->UninstallProtocolInterface (
598 Private->ExtScsiPassThruHandle,
599 &gEfiDevicePathProtocolGuid,
600 Private->DevicePath
601 );
602
603 FreePool (Private->DevicePath);
604 }
605
606 if (Private->ExtScsiPassThruHandle != NULL) {
607 gBS->UninstallProtocolInterface (
608 Private->ExtScsiPassThruHandle,
609 &gEfiExtScsiPassThruProtocolGuid,
610 &Private->IScsiExtScsiPassThru
611 );
612 }
613
614 gBS->CloseEvent (Private->ExitBootServiceEvent);
615
616 FreePool (Private);
617 }
618
619 /**
620 Check wheather the Controller is configured to use DHCP protocol.
621
622 @param[in] Controller The handle of the controller.
623
624 @retval TRUE The handle of the controller need the Dhcp protocol.
625 @retval FALSE The handle of the controller does not need the Dhcp protocol.
626
627 **/
628 BOOLEAN
629 IScsiDhcpIsConfigured (
630 IN EFI_HANDLE Controller
631 )
632 {
633 EFI_STATUS Status;
634 EFI_MAC_ADDRESS MacAddress;
635 UINTN HwAddressSize;
636 UINT16 VlanId;
637 CHAR16 MacString[70];
638 ISCSI_SESSION_CONFIG_NVDATA *ConfigDataTmp;
639
640 //
641 // Get the mac string, it's the name of various variable
642 //
643 Status = NetLibGetMacAddress (Controller, &MacAddress, &HwAddressSize);
644 if (EFI_ERROR (Status)) {
645 return FALSE;
646 }
647 VlanId = NetLibGetVlanId (Controller);
648 IScsiMacAddrToStr (&MacAddress, (UINT32) HwAddressSize, VlanId, MacString);
649
650 //
651 // Get the normal configuration.
652 //
653 Status = GetVariable2 (
654 MacString,
655 &gEfiIScsiInitiatorNameProtocolGuid,
656 (VOID**)&ConfigDataTmp,
657 NULL
658 );
659 if (ConfigDataTmp == NULL || EFI_ERROR (Status)) {
660 return FALSE;
661 }
662
663 if (ConfigDataTmp->Enabled && ConfigDataTmp->InitiatorInfoFromDhcp) {
664 FreePool (ConfigDataTmp);
665 return TRUE;
666 }
667
668 FreePool (ConfigDataTmp);
669 return FALSE;
670 }
671
672 /**
673 Get the various configuration data of this iSCSI instance.
674
675 @param[in] Private The iSCSI driver data.
676
677 @retval EFI_SUCCESS The configuration of this instance is got.
678 @retval EFI_ABORTED The operation was aborted.
679 @retval Others Other errors as indicated.
680 **/
681 EFI_STATUS
682 IScsiGetConfigData (
683 IN ISCSI_DRIVER_DATA *Private
684 )
685 {
686 EFI_STATUS Status;
687 ISCSI_SESSION *Session;
688 UINTN BufferSize;
689 EFI_MAC_ADDRESS MacAddress;
690 UINTN HwAddressSize;
691 UINT16 VlanId;
692 CHAR16 MacString[70];
693
694 //
695 // get the iSCSI Initiator Name
696 //
697 Session = &Private->Session;
698 Session->InitiatorNameLength = ISCSI_NAME_MAX_SIZE;
699 Status = gIScsiInitiatorName.Get (
700 &gIScsiInitiatorName,
701 &Session->InitiatorNameLength,
702 Session->InitiatorName
703 );
704 if (EFI_ERROR (Status)) {
705 return Status;
706 }
707
708 //
709 // Get the mac string, it's the name of various variable
710 //
711 Status = NetLibGetMacAddress (Private->Controller, &MacAddress, &HwAddressSize);
712 ASSERT (Status == EFI_SUCCESS);
713 VlanId = NetLibGetVlanId (Private->Controller);
714 IScsiMacAddrToStr (&MacAddress, (UINT32) HwAddressSize, VlanId, MacString);
715
716 //
717 // Get the normal configuration.
718 //
719 BufferSize = sizeof (Session->ConfigData.NvData);
720 Status = gRT->GetVariable (
721 MacString,
722 &gEfiIScsiInitiatorNameProtocolGuid,
723 NULL,
724 &BufferSize,
725 &Session->ConfigData.NvData
726 );
727 if (EFI_ERROR (Status)) {
728 return Status;
729 }
730
731 if (!Session->ConfigData.NvData.Enabled) {
732 return EFI_ABORTED;
733 }
734 //
735 // Get the CHAP Auth information.
736 //
737 BufferSize = sizeof (Session->AuthData.AuthConfig);
738 Status = gRT->GetVariable (
739 MacString,
740 &gIScsiCHAPAuthInfoGuid,
741 NULL,
742 &BufferSize,
743 &Session->AuthData.AuthConfig
744 );
745
746 if (!EFI_ERROR (Status) && Session->ConfigData.NvData.InitiatorInfoFromDhcp) {
747 //
748 // Start dhcp.
749 //
750 Status = IScsiDoDhcp (Private->Image, Private->Controller, &Session->ConfigData);
751 }
752
753 return Status;
754 }
755
756 /**
757 Get the device path of the iSCSI tcp connection and update it.
758
759 @param[in] Private The iSCSI driver data.
760
761 @return The updated device path.
762 @retval NULL Other errors as indicated.
763 **/
764 EFI_DEVICE_PATH_PROTOCOL *
765 IScsiGetTcpConnDevicePath (
766 IN ISCSI_DRIVER_DATA *Private
767 )
768 {
769 ISCSI_SESSION *Session;
770 ISCSI_CONNECTION *Conn;
771 TCP4_IO *Tcp4Io;
772 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
773 EFI_STATUS Status;
774 EFI_DEV_PATH *DPathNode;
775
776 Session = &Private->Session;
777 if (Session->State != SESSION_STATE_LOGGED_IN) {
778 return NULL;
779 }
780
781 Conn = NET_LIST_USER_STRUCT_S (
782 Session->Conns.ForwardLink,
783 ISCSI_CONNECTION,
784 Link,
785 ISCSI_CONNECTION_SIGNATURE
786 );
787 Tcp4Io = &Conn->Tcp4Io;
788
789 Status = gBS->HandleProtocol (
790 Tcp4Io->Handle,
791 &gEfiDevicePathProtocolGuid,
792 (VOID **)&DevicePath
793 );
794 if (EFI_ERROR (Status)) {
795 return NULL;
796 }
797 //
798 // Duplicate it.
799 //
800 DevicePath = DuplicateDevicePath (DevicePath);
801 if (DevicePath == NULL) {
802 return NULL;
803 }
804
805 DPathNode = (EFI_DEV_PATH *) DevicePath;
806
807 while (!IsDevicePathEnd (&DPathNode->DevPath)) {
808 if ((DevicePathType (&DPathNode->DevPath) == MESSAGING_DEVICE_PATH) &&
809 (DevicePathSubType (&DPathNode->DevPath) == MSG_IPv4_DP)
810 ) {
811
812 DPathNode->Ipv4.LocalPort = 0;
813 DPathNode->Ipv4.StaticIpAddress =
814 (BOOLEAN) (!Session->ConfigData.NvData.InitiatorInfoFromDhcp);
815
816 IP4_COPY_ADDRESS (
817 &DPathNode->Ipv4.GatewayIpAddress,
818 &Session->ConfigData.NvData.Gateway
819 );
820
821 IP4_COPY_ADDRESS (
822 &DPathNode->Ipv4.SubnetMask,
823 &Session->ConfigData.NvData.SubnetMask
824 );
825
826 break;
827 }
828
829 DPathNode = (EFI_DEV_PATH *) NextDevicePathNode (&DPathNode->DevPath);
830 }
831
832 return DevicePath;
833 }
834
835 /**
836 Abort the session when the transition from BS to RT is initiated.
837
838 @param[in] Event The event signaled.
839 @param[in] Context The iSCSI driver data.
840 **/
841 VOID
842 EFIAPI
843 IScsiOnExitBootService (
844 IN EFI_EVENT Event,
845 IN VOID *Context
846 )
847 {
848 ISCSI_DRIVER_DATA *Private;
849
850 Private = (ISCSI_DRIVER_DATA *) Context;
851 gBS->CloseEvent (Private->ExitBootServiceEvent);
852
853 IScsiSessionAbort (&Private->Session);
854 }