3 Copyright (c) 2007 Intel Corporation. All rights reserved
4 This software and associated documentation (if any) is furnished
5 under a license and may only be used or copied in accordance
6 with the terms of the license. Except as permitted by such
7 license, no part of this software or documentation may be
8 reproduced, stored in a retrieval system, or transmitted in any
9 form or by any means without the express written consent of
18 Miscellaneous routines for iSCSI driver.
22 #include "IScsiImpl.h"
24 STATIC CONST CHAR8 IScsiHexString
[] = "0123456789ABCDEFabcdef";
35 Determines if a Unicode character is a hexadecimal digit.
36 The test is case insensitive.
39 Digit - Pointer to byte that receives the value of the hex character.
40 Char - Unicode character to test.
43 TRUE - If the character is a hexadecimal digit.
48 if ((Char
>= L
'0') && (Char
<= L
'9')) {
49 *Digit
= (UINT8
) (Char
- L
'0');
53 if ((Char
>= L
'A') && (Char
<= L
'F')) {
54 *Digit
= (UINT8
) (Char
- L
'A' + 0x0A);
58 if ((Char
>= L
'a') && (Char
<= L
'f')) {
59 *Digit
= (UINT8
) (Char
- L
'a' + 0x0A);
76 Removes (trims) specified leading and trailing characters from a string.
80 str - Pointer to the null-terminated string to be trimmed. On return,
81 str will hold the trimmed string.
82 CharC - Character will be trimmed from str.
96 // Trim off the leading and trailing characters c
98 for (p1
= str
; *p1
&& *p1
== CharC
; p1
++) {
118 for (p1
= str
+ StrLen(str
) - 1; p1
>= str
&& *p1
== CharC
; p1
--) {
121 if (p1
!= str
+ StrLen(str
) - 1) {
127 IScsiGetSubnetMaskPrefixLength (
128 IN EFI_IPv4_ADDRESS
*SubnetMask
134 Calculate the prefix length of the IPv4 subnet mask.
138 SubnetMask - The IPv4 subnet mask.
142 The prefix length of the subnet mask.
150 // The SubnetMask is in network byte order.
152 ReverseMask
= (SubnetMask
->Addr
[0] << 24) | (SubnetMask
->Addr
[1] << 16) | (SubnetMask
->Addr
[2] << 8) | (SubnetMask
->Addr
[3]);
157 ReverseMask
= ~ReverseMask
;
159 if (ReverseMask
& (ReverseMask
+ 1)) {
165 while (ReverseMask
!= 0) {
166 ReverseMask
= ReverseMask
>> 1;
170 return (UINT8
)(32 - Len
);
182 Convert the hexadecimal encoded LUN string into the 64-bit LUN.
186 Str - The hexadecimal encoded LUN string.
187 Lun - Storage to return the 64-bit LUN.
191 EFI_SUCCESS - The 64-bit LUN is stored in Lun.
192 EFI_INVALID_PARAMETER - The string is malformatted.
197 CHAR8
*LunUnitStr
[4];
202 NetZeroMem (LunUnitStr
, sizeof (LunUnitStr
));
207 if (!IsHexDigit ((UINT8
*)&Digit
, *Str
)) {
208 return EFI_INVALID_PARAMETER
;
211 while (*Str
!= '\0') {
213 // Legal representations of LUN:
214 // 4752-3A4F-6b7e-2F99,
222 if (*(Str
+ 1) != '\0') {
223 if (!IsHexDigit ((UINT8
*)&Digit
, *(Str
+ 1))) {
224 return EFI_INVALID_PARAMETER
;
227 LunUnitStr
[Index
] = Str
+ 1;
229 } else if (!IsHexDigit ((UINT8
*)&Digit
, *Str
)) {
230 return EFI_INVALID_PARAMETER
;
236 for (Index
= 0; (Index
< 4) && (LunUnitStr
[Index
] != NULL
); Index
++) {
237 if (AsciiStrLen (LunUnitStr
[Index
]) > 4) {
238 return EFI_INVALID_PARAMETER
;
241 Temp
= AsciiStrHexToUintn (LunUnitStr
[Index
]);
242 *((UINT16
*) &Lun
[Index
* 2]) = HTONS (Temp
);
249 IScsiLunToUnicodeStr (
257 Convert the 64-bit LUN into the hexadecimal encoded LUN string.
261 Lun - The 64-bit LUN.
262 Str - The storage to return the hexadecimal encoded LUN string.
275 for (Index
= 0; Index
< 4; Index
++) {
277 if ((Lun
[2 * Index
] | Lun
[2 * Index
+ 1]) == 0) {
278 StrCpy (TempStr
, L
"0-");
280 TempStr
[0] = (CHAR16
) IScsiHexString
[Lun
[2 * Index
] >> 4];
281 TempStr
[1] = (CHAR16
) IScsiHexString
[Lun
[2 * Index
] & 0xf];
282 TempStr
[2] = (CHAR16
) IScsiHexString
[Lun
[2 * Index
+ 1] >> 4];
283 TempStr
[3] = (CHAR16
) IScsiHexString
[Lun
[2 * Index
+ 1] & 0xf];
287 StrTrim (TempStr
, L
'0');
290 TempStr
+= StrLen (TempStr
);
293 Str
[StrLen (Str
) - 1] = 0;
295 for (Index
= StrLen (Str
) - 1; Index
> 1; Index
= Index
- 2) {
296 if ((Str
[Index
] == L
'0') && (Str
[Index
- 1] == L
'-')) {
305 IScsiAsciiStrToUnicodeStr (
307 OUT CHAR16
*Destination
313 Convert the ASCII string into a UNICODE string.
317 Source - The ASCII string.
318 Destination - The storage to return the UNICODE string.
322 Pointer to the UNICODE string.
326 ASSERT (Destination
!= NULL
);
327 ASSERT (Source
!= NULL
);
329 while (*Source
!= '\0') {
330 *(Destination
++) = (CHAR16
) *(Source
++);
339 IScsiUnicodeStrToAsciiStr (
341 OUT CHAR8
*Destination
347 Convert the UNICODE string into an ASCII string.
351 Source - The UNICODE string.
352 Destination - The storage to return the ASCII string.
356 Pointer to the ASCII string.
360 ASSERT (Destination
!= NULL
);
361 ASSERT (Source
!= NULL
);
363 while (*Source
!= '\0') {
365 // If any Unicode characters in Source contain
366 // non-zero value in the upper 8 bits, then ASSERT().
368 ASSERT (*Source
< 0x100);
369 *(Destination
++) = (CHAR8
) *(Source
++);
380 OUT EFI_IPv4_ADDRESS
*Ip
386 Convert the decimal dotted IPv4 address into the binary IPv4 address.
390 Str - The UNICODE string.
391 Ip - The storage to return the ASCII string.
395 EFI_SUCCESS - The binary IP address is returned in Ip.
396 EFI_INVALID_PARAMETER - The IP string is malformatted.
408 return EFI_INVALID_PARAMETER
;
412 while (NET_IS_DIGIT (*Str
)) {
413 Number
= Number
* 10 + (*Str
- '0');
418 return EFI_INVALID_PARAMETER
;
421 Ip
->Addr
[Index
] = (UINT8
) Number
;
423 if ((*Str
!= '\0') && (*Str
!= '.')) {
425 // The current character should be either the NULL terminator or
426 // the dot delimiter.
428 return EFI_INVALID_PARAMETER
;
433 // Skip the delimiter.
442 return EFI_INVALID_PARAMETER
;
450 IN EFI_MAC_ADDRESS
*Mac
,
458 Convert the mac address into a hexadecimal encoded "-" seperated string.
462 Mac - The mac address.
463 Len - Length in bytes of the mac address.
464 Str - The storage to return the mac string.
474 for (Index
= 0; Index
< Len
; Index
++) {
475 Str
[3 * Index
] = NibbleToHexChar ((UINT8
)(Mac
->Addr
[Index
] >> 4));
476 Str
[3 * Index
+ 1] = NibbleToHexChar (Mac
->Addr
[Index
]);
477 Str
[3 * Index
+ 2] = L
'-';
480 Str
[3 * Index
- 1] = L
'\0';
487 IN OUT CHAR8
*HexStr
,
488 IN OUT UINT32
*HexLength
494 Convert the binary encoded buffer into a hexadecimal encoded string.
498 BinBuffer - The buffer containing the binary data.
499 BinLength - Length of the binary buffer.
500 HexStr - Pointer to the string.
501 HexLength - The length of the string.
505 EFI_SUCCESS - The binary data is converted to the hexadecimal string
506 and the length of the string is updated.
507 EFI_BUFFER_TOO_SMALL - The string is too small.
513 if ((HexStr
== NULL
) || (BinBuffer
== NULL
) || (BinLength
== 0)) {
514 return EFI_INVALID_PARAMETER
;
517 if (((*HexLength
) - 3) < BinLength
* 2) {
518 *HexLength
= BinLength
* 2 + 3;
519 return EFI_BUFFER_TOO_SMALL
;
522 *HexLength
= BinLength
* 2 + 3;
524 // Prefix for Hex String
529 for (Index
= 0; Index
< BinLength
; Index
++) {
530 HexStr
[Index
* 2 + 2] = IScsiHexString
[BinBuffer
[Index
] >> 4];
531 HexStr
[Index
* 2 + 3] = IScsiHexString
[BinBuffer
[Index
] & 0xf];
534 HexStr
[Index
* 2 + 2] = '\0';
541 IN OUT UINT8
*BinBuffer
,
542 IN OUT UINT32
*BinLength
,
549 Convert the hexadecimal string into a binary encoded buffer.
553 BinBuffer - The binary buffer.
554 BinLength - Length of the binary buffer.
555 HexStr - The hexadecimal string.
559 EFI_SUCCESS - The hexadecimal string is converted into a binary
561 EFI_BUFFER_TOO_SMALL - The binary buffer is too small to hold the converted data.s
572 // Find out how many hex characters the string has.
575 if ((HexBuf
[0] == '0') && ((HexBuf
[1] == 'x') || (HexBuf
[1] == 'X'))) {
579 for (Index
= 0, HexCount
= 0; IsHexDigit (&Digit
, HexBuf
[Index
]); Index
++, HexCount
++)
587 // Test if buffer is passed enough.
589 if (((HexCount
+ 1) / 2) > *BinLength
) {
590 *BinLength
= (HexCount
+ 1) / 2;
591 return EFI_BUFFER_TOO_SMALL
;
594 *BinLength
= (HexCount
+ 1) / 2;
596 for (Index
= 0; Index
< HexCount
; Index
++) {
598 IsHexDigit (&Digit
, HexBuf
[HexCount
- 1 - Index
]);
600 if ((Index
& 1) == 0) {
603 Byte
= BinBuffer
[*BinLength
- 1 - Index
/ 2];
605 Byte
= (UINT8
)(Byte
| (Digit
<< 4));
608 BinBuffer
[*BinLength
- 1 - Index
/ 2] = Byte
;
623 Generate random numbers.
627 Rand - The buffer to contain random numbers.
628 RandLength - The length of the Rand buffer.
638 while (RandLength
> 0) {
639 Random
= NET_RANDOM (NetRandomInitSeed ());
640 *Rand
++ = (UINT8
) (Random
);
646 IScsiCreateDriverData (
648 IN EFI_HANDLE Controller
654 Create the iSCSI driver data..
658 Image - The handle of the driver image.
659 Controller - The handle of the controller.
663 The iSCSI driver data created.
667 ISCSI_DRIVER_DATA
*Private
;
670 Private
= NetAllocateZeroPool (sizeof (ISCSI_DRIVER_DATA
));
671 if (Private
== NULL
) {
675 Private
->Signature
= ISCSI_DRIVER_DATA_SIGNATURE
;
676 Private
->Image
= Image
;
677 Private
->Controller
= Controller
;
680 // Create an event to be signal when the BS to RT transition is triggerd so
681 // as to abort the iSCSI session.
683 Status
= gBS
->CreateEvent (
684 EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES
,
686 IScsiOnExitBootService
,
688 &Private
->ExitBootServiceEvent
690 if (EFI_ERROR (Status
)) {
691 NetFreePool (Private
);
695 NetCopyMem(&Private
->IScsiExtScsiPassThru
, &gIScsiExtScsiPassThruProtocolTemplate
, sizeof(EFI_EXT_SCSI_PASS_THRU_PROTOCOL
));
698 // 0 is designated to the TargetId, so use another value for the AdapterId.
700 Private
->ExtScsiPassThruMode
.AdapterId
= 2;
701 Private
->ExtScsiPassThruMode
.Attributes
= EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL
| EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL
;
702 Private
->ExtScsiPassThruMode
.IoAlign
= 4;
703 Private
->IScsiExtScsiPassThru
.Mode
= &Private
->ExtScsiPassThruMode
;
706 // Install the Ext SCSI PASS THRU protocol.
708 Status
= gBS
->InstallProtocolInterface (
709 &Private
->ExtScsiPassThruHandle
,
710 &gEfiExtScsiPassThruProtocolGuid
,
711 EFI_NATIVE_INTERFACE
,
712 &Private
->IScsiExtScsiPassThru
714 if (EFI_ERROR (Status
)) {
715 gBS
->CloseEvent (Private
->ExitBootServiceEvent
);
716 NetFreePool (Private
);
721 IScsiSessionInit (&Private
->Session
, FALSE
);
727 IScsiCleanDriverData (
728 IN ISCSI_DRIVER_DATA
*Private
734 Clean the iSCSI driver data.
738 Private - The iSCSI driver data.
746 if (Private
->DevicePath
!= NULL
) {
747 gBS
->UninstallProtocolInterface (
748 Private
->ExtScsiPassThruHandle
,
749 &gEfiDevicePathProtocolGuid
,
753 NetFreePool (Private
->DevicePath
);
756 if (Private
->ExtScsiPassThruHandle
!= NULL
) {
757 gBS
->UninstallProtocolInterface (
758 Private
->ExtScsiPassThruHandle
,
759 &gEfiExtScsiPassThruProtocolGuid
,
760 &Private
->IScsiExtScsiPassThru
764 gBS
->CloseEvent (Private
->ExitBootServiceEvent
);
766 NetFreePool (Private
);
771 IN ISCSI_DRIVER_DATA
*Private
777 Get the various configuration data of this iSCSI instance.
781 Private - The iSCSI driver data.
785 EFI_SUCCESS - The configuration of this instance is got.
786 EFI_NOT_FOUND - This iSCSI instance is not configured yet.
791 ISCSI_SESSION
*Session
;
793 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
794 EFI_SIMPLE_NETWORK_MODE
*Mode
;
795 CHAR16 MacString
[65];
798 // get the iSCSI Initiator Name
800 Session
= &Private
->Session
;
801 Session
->InitiatorNameLength
= ISCSI_NAME_MAX_SIZE
;
802 Status
= gIScsiInitiatorName
.Get (
803 &gIScsiInitiatorName
,
804 &Session
->InitiatorNameLength
,
805 Session
->InitiatorName
807 if (EFI_ERROR (Status
)) {
811 Status
= gBS
->HandleProtocol (
813 &gEfiSimpleNetworkProtocolGuid
,
816 if (EFI_ERROR (Status
)) {
823 // Get the mac string, it's the name of various variable
825 IScsiMacAddrToStr (&Mode
->PermanentAddress
, Mode
->HwAddressSize
, MacString
);
828 // Get the normal configuration.
830 BufferSize
= sizeof (Session
->ConfigData
.NvData
);
831 Status
= gRT
->GetVariable (
833 &gEfiIScsiInitiatorNameProtocolGuid
,
836 &Session
->ConfigData
.NvData
838 if (EFI_ERROR (Status
)) {
842 if (!Session
->ConfigData
.NvData
.Enabled
) {
846 // Get the CHAP Auth information.
848 BufferSize
= sizeof (Session
->AuthData
.AuthConfig
);
849 Status
= gRT
->GetVariable (
851 &mIScsiCHAPAuthInfoGuid
,
854 &Session
->AuthData
.AuthConfig
857 if (!EFI_ERROR (Status
) && Session
->ConfigData
.NvData
.InitiatorInfoFromDhcp
) {
861 Status
= IScsiDoDhcp (Private
->Image
, Private
->Controller
, &Session
->ConfigData
);
867 EFI_DEVICE_PATH_PROTOCOL
*
868 IScsiGetTcpConnDevicePath (
869 IN ISCSI_DRIVER_DATA
*Private
875 Get the device path of the iSCSI tcp connection and update it.
879 Private - The iSCSI driver data.
883 The updated device path.
887 ISCSI_SESSION
*Session
;
888 ISCSI_CONNECTION
*Conn
;
890 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
892 EFI_DEV_PATH
*DPathNode
;
894 Session
= &Private
->Session
;
895 if (Session
->State
!= SESSION_STATE_LOGGED_IN
) {
899 Conn
= NET_LIST_USER_STRUCT_S (
900 Session
->Conns
.ForwardLink
,
903 ISCSI_CONNECTION_SIGNATURE
905 Tcp4Io
= &Conn
->Tcp4Io
;
907 Status
= gBS
->HandleProtocol (
909 &gEfiDevicePathProtocolGuid
,
912 if (EFI_ERROR (Status
)) {
918 DevicePath
= DuplicateDevicePath (DevicePath
);
920 DPathNode
= (EFI_DEV_PATH
*) DevicePath
;
922 while (!IsDevicePathEnd (&DPathNode
->DevPath
)) {
923 if ((DevicePathType (&DPathNode
->DevPath
) == MESSAGING_DEVICE_PATH
) &&
924 (DevicePathSubType (&DPathNode
->DevPath
) == MSG_IPv4_DP
)
927 DPathNode
->Ipv4
.LocalPort
= 0;
928 DPathNode
->Ipv4
.StaticIpAddress
= (BOOLEAN
)(!Session
->ConfigData
.NvData
.InitiatorInfoFromDhcp
);
932 DPathNode
= (EFI_DEV_PATH
*) NextDevicePathNode (&DPathNode
->DevPath
);
940 IScsiOnExitBootService (
948 Abort the session when the transition from BS to RT is initiated.
952 Event - The event signaled.
953 Context - The iSCSI driver data.
961 ISCSI_DRIVER_DATA
*Private
;
963 Private
= (ISCSI_DRIVER_DATA
*) Context
;
964 gBS
->CloseEvent (Private
->ExitBootServiceEvent
);
966 IScsiSessionAbort (&Private
->Session
);