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