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