]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/IScsiDxe/IScsiMisc.c
Fix bug in unload function: Check if component name protocol exist, only uninstall...
[mirror_edk2.git] / MdeModulePkg / Universal / Network / IScsiDxe / IScsiMisc.c
1 /** @file
2 Miscellaneous routines for iSCSI driver.
3
4 Copyright (c) 2004 - 2014, 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 }
855
856 /**
857 Tests whether a controller handle is being managed by IScsi driver.
858
859 This function tests whether the driver specified by DriverBindingHandle is
860 currently managing the controller specified by ControllerHandle. This test
861 is performed by evaluating if the the protocol specified by ProtocolGuid is
862 present on ControllerHandle and is was opened by DriverBindingHandle and Nic
863 Device handle with an attribute of EFI_OPEN_PROTOCOL_BY_DRIVER.
864 If ProtocolGuid is NULL, then ASSERT().
865
866 @param ControllerHandle A handle for a controller to test.
867 @param DriverBindingHandle Specifies the driver binding handle for the
868 driver.
869 @param ProtocolGuid Specifies the protocol that the driver specified
870 by DriverBindingHandle opens in its Start()
871 function.
872
873 @retval EFI_SUCCESS ControllerHandle is managed by the driver
874 specified by DriverBindingHandle.
875 @retval EFI_UNSUPPORTED ControllerHandle is not managed by the driver
876 specified by DriverBindingHandle.
877
878 **/
879 EFI_STATUS
880 EFIAPI
881 IScsiTestManagedDevice (
882 IN EFI_HANDLE ControllerHandle,
883 IN EFI_HANDLE DriverBindingHandle,
884 IN EFI_GUID *ProtocolGuid
885 )
886 {
887 EFI_STATUS Status;
888 VOID *ManagedInterface;
889 EFI_HANDLE NicControllerHandle;
890
891 ASSERT (ProtocolGuid != NULL);
892
893 NicControllerHandle = NetLibGetNicHandle (ControllerHandle, ProtocolGuid);
894 if (NicControllerHandle == NULL) {
895 return EFI_UNSUPPORTED;
896 }
897
898 Status = gBS->OpenProtocol (
899 ControllerHandle,
900 (EFI_GUID *) ProtocolGuid,
901 &ManagedInterface,
902 DriverBindingHandle,
903 NicControllerHandle,
904 EFI_OPEN_PROTOCOL_BY_DRIVER
905 );
906 if (!EFI_ERROR (Status)) {
907 gBS->CloseProtocol (
908 ControllerHandle,
909 (EFI_GUID *) ProtocolGuid,
910 DriverBindingHandle,
911 NicControllerHandle
912 );
913 return EFI_UNSUPPORTED;
914 }
915
916 if (Status != EFI_ALREADY_STARTED) {
917 return EFI_UNSUPPORTED;
918 }
919
920 return EFI_SUCCESS;
921 }