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